ssvfdn 3 mēneši atpakaļ
vecāks
revīzija
49336e2ab8

+ 4 - 0
apps/web-antd/src/api/game_control/game_config.ts

@@ -13,6 +13,10 @@ interface ApiResultInfoData {
     message: string;
 }
 
+export async function getGameMinList() {
+    return requestClient.get<ApiResultListData>('/game/get_games');
+}
+
 /**
  * 获取游戏列表
  */

+ 0 - 0
apps/web-antd/src/api/player/game_records.ts


+ 4 - 0
apps/web-antd/src/locales/langs/zh-CN/player_data.json

@@ -1,6 +1,7 @@
 {
     "title": "玩家数据",
     "player_list": "玩家列表",
+    "game_records": "游戏记录",
     "placeholder": "请输入",
     "search": {
         "uname": "平台ID",
@@ -25,5 +26,8 @@
         "history_login_count": "历史登录次数",
         "login_ip": "登录IP",
         "reg_ip": "注册IP"
+    },
+    "gamerecords": {
+
     }
 }

+ 9 - 0
apps/web-antd/src/router/routes/modules/player_data.ts

@@ -22,6 +22,15 @@ const routes: RouteRecordRaw[] = [
                 path: '/player-data/player-list',
                 component: () => import('#/views/player_data/player_list/index.vue'),
             },
+            {
+                meta: {
+                    title: $t('player_data.game_records'),
+                    icon:'solar:gamepad-minimalistic-outline',
+                },
+                name: 'GameRecordList',
+                path: '/player-data/game-records',
+                component: () => import('#/views/player_data/game_records/index.vue'),
+            },
         ],
     },
 ];

+ 2 - 2
apps/web-antd/src/views/game_control/game_config/game_info.vue

@@ -115,7 +115,7 @@ const updateDefaultDeposit = () => {
 				(slot的AUTO附加功能,开启后,玩家在游戏内自动旋转时,可以设定条件,达到输赢条件停止自动旋转)
 			</FormItem>
 			<FormItem label="最低押注限制">
-				<Input v-model:value="form.min_deposit" style="width:30%;" />
+				<InputNumber v-model:value="form.min_deposit" step="0.01" style="width:30%;" :precision="2" />
 			</FormItem>
 			<FormItem label="返奖倍数限制">
 				<Select style="width:30%;" v-model:value="form.max_multiple_count">
@@ -135,7 +135,7 @@ const updateDefaultDeposit = () => {
 				<div class="slots-wrap">
 					<div class="wrap-item" v-for="(value, idx) in form.deposit_list">
 						<div>
-							<InputNumber v-model:value="form.deposit_list[idx]" :step="0.01">
+							<InputNumber v-model:value="form.deposit_list[idx]" :step="0.01" :precision="2">
 								<template #addonBefore>
 									<Button :disabled="form.deposit_list.length <= 1 || formDisabled" @click="deleteDepositList(idx)"><DeleteIcon :style="'color:' + (form.deposit_list.length <= 1 || formDisabled ? 'gray' : 'red')  +';font-size:18px;'" /></Button>
 								</template>

+ 31 - 17
apps/web-antd/src/views/game_control/game_config/index.vue

@@ -4,8 +4,21 @@ import {Button, Card, Tag, Avatar, Switch} from "ant-design-vue";
 import { useVbenForm } from '#/adapter/form';
 import {$t} from "@vben/locales";
 import { useVbenVxeGrid } from '#/adapter/vxe-table';
-import {getGameList} from "#/api/game_control/game_config.js";
-const [QueryForm] = useVbenForm({
+import {getGameList, getGameMinList} from "#/api/game_control/game_config.js";
+
+
+const filterGameList = ref([]);
+getGameMinList().then((data) => {
+	data.forEach((game) => {
+		filterGameList.value.push({
+			'label': `【${game.game_id}】${game.title}`,
+			'value': game.game_id,
+		})
+	})
+})
+
+
+const [QueryForm, formApi] = useVbenForm({
 	// 默认展开
 	collapsed: false,
 	// 所有表单项共用,可单独在表单内覆盖
@@ -17,6 +30,7 @@ const [QueryForm] = useVbenForm({
 	},
 	// 提交函数
 	handleSubmit: onSubmit,
+	handleReset: onReset,
 	// 垂直布局,label和input在不同行,值为vertical
 	// 水平布局,label和input在同一行
 	layout: 'horizontal',
@@ -26,34 +40,28 @@ const [QueryForm] = useVbenForm({
 			componentProps: {
 				allowClear: true,
 				filterOption: true,
-				options: [
-					{
-						label: '选项1',
-						value: '1',
-					},
-					{
-						label: '选项2',
-						value: '2',
-					},
-				],
+				name:'game_id',
+				options: filterGameList,
 				placeholder: $t('common.placeholder_select'),
 				showSearch: true,
 			},
-			fieldName: 'options',
+			fieldName: 'game_id',
 			label: $t('game_control.game'),
 		},
 	],
 	// 是否可展开
-	showCollapseButton: true,
+	// showCollapseButton: true,
 	submitButtonOptions: {
 		content: '查询',
 	},
 	wrapperClass: 'grid-cols-1 md:grid-cols-2',
 });
 function onSubmit(values) {
-	// message.success({
-	// 	content: `form values: ${JSON.stringify(values)}`,
-	// });
+	gridApi.reload();
+}
+function onReset() {
+	formApi.resetForm();
+	gridApi.reload();
 }
 
 const gridOptions = {
@@ -87,6 +95,10 @@ const gridOptions = {
 					page: page.currentPage,
 					limit: page.pageSize,
 				};
+				const filterData = await formApi.getValues();
+				if(filterData.game_id) {
+					form.game_id = filterData.game_id;
+				}
 				const list = await getGameList(form);
 				return {
 					total: list.total,
@@ -112,6 +124,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
 });
 
 import ExtraModal from './game_info.vue';
+import {ref} from "vue";
+import {reset} from "ant-design-vue/es/_util/cssinjs/hooks/useStyleRegister/cacheMapUtil.js";
 const [Modal, modalApi] = useVbenModal({
 	// 连接抽离的组件
 	connectedComponent: ExtraModal,

+ 117 - 0
apps/web-antd/src/views/player_data/game_records/index.vue

@@ -0,0 +1,117 @@
+<script setup>
+import {Input, InputGroup, message, Select, SelectOption} from 'ant-design-vue';
+import { useVbenForm } from '#/adapter/form';
+import { Page, useVbenModal } from '@vben/common-ui';
+import {Button, Card, Tag, Avatar, Switch} from "ant-design-vue";
+import {$t} from "@vben/locales";
+
+const [QueryForm] = useVbenForm({
+	// 默认展开
+	collapsed: false,
+	// 所有表单项共用,可单独在表单内覆盖
+	commonConfig: {
+		// 所有表单项
+		componentProps: {
+			class: 'w-full',
+		},
+	},
+	// 提交函数
+	handleSubmit: onSubmit,
+	// 垂直布局,label和input在不同行,值为vertical
+	// 水平布局,label和input在同一行
+	layout: 'horizontal',
+	schema: [
+		{
+			// 组件需要在 #/adapter.ts内注册,并加上类型
+			component: 'Input',
+			// 对应组件的参数
+			componentProps: {
+				placeholder: '请输入用户名',
+			},
+			// 字段名
+			fieldName: 'username',
+			// 界面显示的label
+			label: '字符串',
+		},
+		{
+			component: 'InputPassword',
+			componentProps: {
+				placeholder: '请输入密码',
+			},
+			fieldName: 'password',
+			label: '密码',
+		},
+		{
+			component: 'InputNumber',
+			componentProps: {
+				placeholder: '请输入',
+			},
+			fieldName: 'number',
+			label: '数字(带后缀)',
+			suffix: () => '¥',
+		},
+		{
+			component: 'Select',
+			componentProps: {
+				allowClear: true,
+				filterOption: true,
+				options: [
+					{
+						label: '选项1',
+						value: '1',
+					},
+					{
+						label: '选项2',
+						value: '2',
+					},
+				],
+				placeholder: '请选择',
+				showSearch: true,
+			},
+			fieldName: 'options',
+			label: '下拉选',
+		},
+		{
+			component: 'DatePicker',
+			fieldName: 'datePicker',
+			label: '日期选择框',
+		},
+	],
+	// 是否可展开
+	showCollapseButton: true,
+	submitButtonOptions: {
+		content: '查询',
+	},
+	wrapperClass: 'grid-cols-1 md:grid-cols-2',
+});
+function onSubmit(values) {
+	message.success({
+		content: `form values: ${JSON.stringify(values)}`,
+	});
+}
+</script>
+
+<template>
+	<Page>
+		<Card>
+			<QueryForm>
+				<template #username="slotProps">
+					<Input-Group compact>
+						<Select name="search_type" style="width: 20%">
+							<Select-Option value="uname">{{$t('player_data.search.uname')}}</Select-Option>
+							<Select-Option value="nickname">{{$t('player_data.search.nickname')}}</Select-Option>
+							<Select-Option value="user_id">{{$t('player_data.search.user_id')}}</Select-Option>
+						</Select>
+						<Input name="search_text" allowClear  v-bind="slotProps" style="width:80%"></Input>
+					</Input-Group>
+				</template>
+			</QueryForm>
+		</Card>
+	</Page>
+</template>
+
+<style scoped>
+.ant-input-group.ant-input-group-compact>*:not(:last-child) {
+	border-inline-end-width: 0;
+}
+</style>

+ 107 - 112
apps/web-antd/src/views/player_data/player_list/index.vue

@@ -1,5 +1,14 @@
 <script setup>
-import {Card,Button,Form,FormItem,Input,Space,Select,SelectOption,InputGroup, RangePicker, Row, Col, Tag} from 'ant-design-vue';
+import {
+	Card,
+	Button,
+	Input,
+	Select,
+	SelectOption,
+	InputGroup,
+	RangePicker,
+	Tag,
+} from 'ant-design-vue';
 import { Page, useVbenModal } from '@vben/common-ui';
 import { $t } from '@vben/locales';
 import { reactive, toRaw, ref } from 'vue';
@@ -8,25 +17,76 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
 import {getPlayerList} from "#/api/player/player_list";
 
 
+
 // 列表筛选
-let filterData = {
-	page: 1,
-	limit: 10,
-	// login_time_start: "",//dayjs().format('YYYY-MM-DD'),
-	// login_time_end: "",//dayjs().format('YYYY-MM-DD')
-}
+const filterData = reactive({
+	'search_type':"uname",
+	'ip_type':'login_ip'
+});
 const disabledDate = (current) => {
 	// Can not select days before today and today
 	return current && current > dayjs().endOf('day');
 };
+const [QueryForm, formApi] = useVbenForm({
+	// 默认展开
+	collapsed: false,
+	// 所有表单项共用,可单独在表单内覆盖
+	commonConfig: {
+		// 所有表单项
+		componentProps: {
+			class: 'w-full',
+		},
+	},
+	// 提交函数
+	handleSubmit: onSubmit,
+	handleReset: onReset,
+	// 垂直布局,label和input在不同行,值为vertical
+	// 水平布局,label和input在同一行
+	layout: 'horizontal',
+	schema: [
+		{
+			// 组件需要在 #/adapter.ts内注册,并加上类型
+			component: 'Input',
+			// 对应组件的参数
+			// 字段名
+			fieldName: 'search_text',
+			// 界面显示的label
+		},
+		{
+			component: 'Input',
+			fieldName: 'ip_text',
+		},
+		{
+			component: 'RangePicker',
+			defaultValue: [dayjs(), dayjs()],
+			fieldName: 'range_time',
+			componentProps: {
+				disabledDate: disabledDate,
+			}
+		},
+	],
+	// 是否可展开
+	submitButtonOptions: {
+		content: '查询',
+	},
+	wrapperClass: 'grid-cols-1 md:grid-cols-3',
+});
+function onSubmit(values) {
+	gridApi.reload();
+}
+function onReset() {
+	formApi.resetForm();
+	filterData.search_type = 'uname';
+	filterData.ip_type = 'login_ip';
+	gridApi.reload();
+}
 
-
+// 列表
 const gridOptions = {
 	border: true,
 	stripe: true,
 	checkboxConfig: {
 		highlight: true,
-		// labelField: 'name',
 	},
 	columns: [
 		{ fixed: 'left',  title: '序号', type: 'seq', width: 50 },
@@ -51,12 +111,21 @@ const gridOptions = {
 	proxyConfig: {
 		ajax: {
 			query: async ({ page }) => {
-
-				let form = toRaw({
-					...filterData,
+				const search = await formApi.getValues();
+				let form = {
 					page: page.currentPage,
 					limit: page.pageSize,
-				});
+				};
+				if(search.ip_text) {
+					form[filterData['ip_type']] = search.ip_text;
+				}
+				if(search.search_text) {
+					form[filterData['search_type']] = search.search_text;
+				}
+				if(search.range_time) {
+					form['login_time_start'] = search.range_time[0].format('YYYY-MM-DD');
+					form['login_time_end'] = search.range_time[1].format('YYYY-MM-DD');
+				}
 				const list = await getPlayerList(form);
 				return {
 					total: list.total,
@@ -76,56 +145,13 @@ const gridOptions = {
 		zoom: true,
 	},
 };
-
 const [Grid, gridApi] = useVbenVxeGrid({
 	gridOptions,
 });
 
-
-const useForm = Form.useForm;
-
-const formData = reactive({
-	search_type: 'uname',
-	search_text: '',
-	ip_type: 'login_ip',
-	ip_text: '',
-	range_time: [ filterData.login_time_start, filterData.login_time_end ],
-});
-const { resetFields } = useForm(formData, []);
-
-const onSearchFinish = () => {
-	if(!formData['range_time']) {
-		formData['range_time'] = [];
-	}
-	const tempForm = toRaw(formData);
-	filterData = {
-		page: 1,
-		limit: 20,
-	}
-	if(tempForm['ip_type'] == 'login_ip' || tempForm['ip_type'] == 'reg_ip'){
-		filterData[tempForm['ip_type']] = tempForm['ip_text'];
-	}
-
-	if(tempForm['search_type'] == 'uname' || tempForm['search_type'] == 'nickname'){
-		filterData[tempForm['search_type']] = tempForm['search_text'];
-	}else {
-		filterData['player_id'] = tempForm['search_text'];
-	}
-	filterData['login_time_start'] = tempForm.range_time[0] || "";
-	filterData['login_time_end'] = tempForm.range_time[1] || "";
-	gridApi.reload();
-};
-
-const onResetSearch = () => {
-	filterData = {
-		page: 1,
-		limit: 20,
-	}
-	resetFields();
-	gridApi.reload();
-}
-
+// 查看玩家详情
 import ExtraModal from './player_info.vue';
+import {useVbenForm} from "#/adapter/form.js";
 const [Modal, modalApi] = useVbenModal({
 	// 连接抽离的组件
 	connectedComponent: ExtraModal,
@@ -138,65 +164,34 @@ const playerInfo = (row) => {
 	}).open();
 }
 
+
+
 </script>
 
 <template>
 	<Page>
 		<Card class="mb-5">
-			<Form
-				:model="formData"
-				name="formRef"
-				ref="formRef"
-				@finish="onSearchFinish"
-			>
-				<Row>
-					<Col :span="8">
-						<Space>
-							<Form-Item
-							>
-								<Input-Group compact>
-									<Select name="search_type" v-model:value="formData.search_type"  style="width: 40%">
-										<Select-Option value="uname">{{$t('player_data.search.uname')}}</Select-Option>
-										<Select-Option value="nickname">{{$t('player_data.search.nickname')}}</Select-Option>
-										<Select-Option value="user_id">{{$t('player_data.search.user_id')}}</Select-Option>
-									</Select>
-									<Input name="search_text" allowClear :placeholder="$t('player_data.placeholder') + '' + $t('player_data.search[\''+formData.search_type+'\']')" v-model:value="formData.search_text" style="width:60%"></Input>
-								</Input-Group>
-							</Form-Item>
-						</Space>
-					</Col>
-					<Col :span="8">
-
-					<Space>
-						<Form-Item
-						>
-							<Input-Group compact>
-								<Select name="ip_type" v-model:value="formData.ip_type"  style="width: 40%">
-									<Select-Option value="login_ip">{{$t('player_data.search.login_ip')}}</Select-Option>
-									<Select-Option value="reg_ip">{{$t('player_data.search.reg_ip')}}</Select-Option>
-								</Select>
-								<Input name="ip_text" allowClear :placeholder="$t('player_data.placeholder') + '' + $t('player_data.search[\''+formData.ip_type+'\']')" v-model:value="formData.ip_text" style="width:60%"></Input>
-							</Input-Group>
-						</Form-Item>
-					</Space>
-					</Col>
-					<Col :span="8">
-					<Space>
-						<FormItem>
-							<Input-Group compact>
-								<RangePicker v-model:value="formData.range_time" :disabled-date="disabledDate" value-format="YYYY-MM-DD"></RangePicker>
-							</Input-Group>
-						</FormItem>
-					</Space>
-					</Col>
-				</Row>
-				<Row>
-					<Col :span="24" style="text-align: right">
-						<Button style="margin: 0 8px" @click="onResetSearch">{{$t('player_data.search.restart')}}</Button>
-						<Button type="primary" html-type="submit">{{$t('player_data.search.subimt')}}</Button>
-					</Col>
-				</Row>
-			</Form>
+			<QueryForm>
+				<template #search_text="slotProps">
+					<Input-Group compact>
+						<Select name="search_type" style="width: 30%" v-model:value="filterData.search_type">
+							<Select-Option value="uname">{{$t('player_data.search.uname')}}</Select-Option>
+							<Select-Option value="nickname">{{$t('player_data.search.nickname')}}</Select-Option>
+							<Select-Option value="user_id">{{$t('player_data.search.user_id')}}</Select-Option>
+						</Select>
+						<Input name="search_text" allowClear :placeholder="$t('player_data.placeholder') + '' + $t('player_data.search[\''+filterData.search_type+'\']')" v-bind="slotProps" style="width:70%"></Input>
+					</Input-Group>
+				</template>
+				<template #ip_text="slotProps">
+					<Input-Group compact>
+						<Select name="search_type" style="width: 30%" v-model:value="filterData.ip_type">
+							<Select-Option value="login_ip">{{$t('player_data.search.login_ip')}}</Select-Option>
+							<Select-Option value="reg_ip">{{$t('player_data.search.reg_ip')}}</Select-Option>
+						</Select>
+						<Input name="ip_text" allowClear :placeholder="$t('player_data.placeholder') + '' + $t('player_data.search[\''+filterData.ip_type+'\']')"  v-bind="slotProps" style="width:70%"></Input>
+					</Input-Group>
+				</template>
+			</QueryForm>
 		</Card>
 		<Card>
 			<div class="vp-raw w-full">