|
|
@@ -0,0 +1,257 @@
|
|
|
+<script setup>
|
|
|
+import {$t} from "@vben/locales";
|
|
|
+import {Avatar, Button, Card, Input, InputGroup, Select, SelectOption, Tag} from "ant-design-vue";
|
|
|
+import {Page, useVbenModal} from "@vben/common-ui";
|
|
|
+import {reactive, ref} from "vue";
|
|
|
+import {getGameMinList} from "#/api/game_control/game_config.js";
|
|
|
+import dayjs from "dayjs";
|
|
|
+import {useVbenVxeGrid} from "#/adapter/vxe-table.js";
|
|
|
+import {getPlayerControlList} from "#/api/game_control/player_control.js";
|
|
|
+
|
|
|
+
|
|
|
+// 列表筛选
|
|
|
+const filterData = reactive({
|
|
|
+ 'search_type':"uname",
|
|
|
+});
|
|
|
+const filterGameList = ref([]);
|
|
|
+getGameMinList().then((data) => {
|
|
|
+ data.forEach((game) => {
|
|
|
+ filterGameList.value.push({
|
|
|
+ 'label': `【${game.game_id}】${game.title}`,
|
|
|
+ 'value': game.game_id,
|
|
|
+ })
|
|
|
+ })
|
|
|
+})
|
|
|
+const disabledDate = (current) => {
|
|
|
+ // Can not select days before today and today
|
|
|
+ return current && current > dayjs().endOf('day');
|
|
|
+};
|
|
|
+const formOptions = {
|
|
|
+ // 默认展开
|
|
|
+ collapsed: false,
|
|
|
+ // 所有表单项共用,可单独在表单内覆盖
|
|
|
+ commonConfig: {
|
|
|
+ // 所有表单项
|
|
|
+ componentProps: {
|
|
|
+ class: 'w-full',
|
|
|
+ },
|
|
|
+ labelWidth: 80
|
|
|
+ },
|
|
|
+ // 提交函数
|
|
|
+ // handleSubmit: onSubmit,
|
|
|
+ handleReset: onReset,
|
|
|
+ // 垂直布局,label和input在不同行,值为vertical
|
|
|
+ // 水平布局,label和input在同一行
|
|
|
+ layout: 'horizontal',
|
|
|
+ schema: [
|
|
|
+ {
|
|
|
+ // 组件需要在 #/adapter.ts内注册,并加上类型
|
|
|
+ component: 'Input',
|
|
|
+ // 对应组件的参数
|
|
|
+ // 字段名
|
|
|
+ fieldName: 'search_text',
|
|
|
+ // 界面显示的label
|
|
|
+ },
|
|
|
+ {
|
|
|
+ component: 'Select',
|
|
|
+ componentProps: {
|
|
|
+ allowClear: true,
|
|
|
+ filterOption: true,
|
|
|
+ name:'game_id',
|
|
|
+ options: filterGameList,
|
|
|
+ placeholder: $t('common.placeholder_select'),
|
|
|
+ showSearch: true,
|
|
|
+ mode:"tags",
|
|
|
+ maxTagCount: 3
|
|
|
+ },
|
|
|
+ fieldName: 'game_id',
|
|
|
+ label: $t('game_control.game'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label:$t("common.range_time"),
|
|
|
+ component: 'RangePicker',
|
|
|
+ defaultValue: [dayjs(), dayjs()],
|
|
|
+ fieldName: 'range_time',
|
|
|
+ componentProps: {
|
|
|
+ disabledDate: disabledDate,
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ ],
|
|
|
+ showCollapseButton: false,
|
|
|
+ // 是否可展开
|
|
|
+ submitButtonOptions: {
|
|
|
+ content: $t('common.search_submit_button'),
|
|
|
+ },
|
|
|
+ wrapperClass: 'grid-cols-1 md:grid-cols-3',
|
|
|
+};
|
|
|
+function onReset() {
|
|
|
+ gridApi.formApi.resetForm();
|
|
|
+ filterData.search_type = 'uname';
|
|
|
+ gridApi.reload();
|
|
|
+}
|
|
|
+// 列表
|
|
|
+const gridOptions = {
|
|
|
+ border: true,
|
|
|
+ stripe: true,
|
|
|
+ scrollbarConfig: {
|
|
|
+ x: {
|
|
|
+ visible: 'visible'
|
|
|
+ },
|
|
|
+ y: {
|
|
|
+ visible: 'auto'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // checkboxConfig: {
|
|
|
+ // highlight: true,
|
|
|
+ // },
|
|
|
+ columns: [
|
|
|
+ { fixed: 'left', title: $t('common.serial'), type: 'seq', width: 50},
|
|
|
+ { fixed: 'left', field: 'third_gid', title: $t('player_data.search.third_gid'), width: 230, titlePrefix: {'content':$t('player_data.gameRecords.tips.third_gid')}, treeNode: true },
|
|
|
+ { field: 'third_order_id', title: $t('player_data.fundsChange.uuid'), width: 230},
|
|
|
+ { field: 'third_round_id', title: $t('player_data.gameRecords.third_round_id'), width: 230, titlePrefix: {'content':$t('player_data.gameRecords.tips.third_round_id')} },
|
|
|
+ { field: 'nickname', title: $t('player_data.gameRecords.nickname'), width: 150, titlePrefix: {'content':$t('player_data.gameRecords.tips.nickname')}},
|
|
|
+ { field: 'user_id', title: $t('player_data.gameRecords.user_id'), width: 120, titlePrefix: {'content':$t('player_data.gameRecords.tips.user_id')}},
|
|
|
+ { field: 'uname', title: $t('player_data.gameRecords.uname'), width: 150, titlePrefix: {'content':$t('player_data.gameRecords.tips.uname')}},
|
|
|
+ { align: 'left', field: 'game_title', title: $t('player_data.gameRecords.game_title'), width: 200, slots: {"default":"game_title"}},
|
|
|
+ { field: 'amount', title: $t('player_data.fundsChange.change_amount'), width: 140, slots: {'default':'amount'}},
|
|
|
+ { field: 'prev_amount', title: $t('player_data.gameRecords.prev_amount'), width: 140, titlePrefix: {'content':$t('player_data.gameRecords.tips.prev_amount')}},
|
|
|
+ { field: 'next_amount', title: $t('player_data.gameRecords.next_amount'), width: 140, titlePrefix: {'content':$t('player_data.gameRecords.tips.next_amount')}},
|
|
|
+ { field: 'bet', title: $t('player_data.fundsChange.bet_amount'), width: 140, titlePrefix: {'content':$t('player_data.gameRecords.tips.bet_amount')}, slots: {'default':'bet_amount'}},
|
|
|
+ { field: 'total_win_amount', title: $t('player_data.fundsChange.change_total_amount'), width: 140, slots: {'default':'total_win_amount'}},
|
|
|
+ { field: 'total_amount', title: $t('player_data.fundsChange.total_amount'), width: 140,},
|
|
|
+ { field: 'action_type', title: $t('player_data.fundsChange.order_type'), width: 140, slots: {'default':'action_type'}},
|
|
|
+ { field: 'status', title: $t('player_data.fundsChange.order_status'), width: 140, slots: {'default':'status'}},
|
|
|
+ { field: 'reason', title: $t('player_data.fundsChange.reason'), width: 200},
|
|
|
+ { field: 'create_time', title: $t('player_data.gameRecords.create_time'), width: 200, titlePrefix: {'content':$t('player_data.gameRecords.tips.create_time')} },
|
|
|
+ // { align:"left", title: $t('game_control.game_list.action'), width: 220, slots: {default:'action'}},
|
|
|
+ ],
|
|
|
+ exportConfig: {},
|
|
|
+ // height: 'auto', // 如果设置为 auto,则必须确保存在父节点且不允许存在相邻元素,否则会出现高度闪动问题
|
|
|
+ keepSource: true,
|
|
|
+ treeConfig: {
|
|
|
+ transform: true, // 指定表格为树形表格
|
|
|
+ parentField: 'parent_id', // 父节点字段名
|
|
|
+ rowField: 'id', // 行数据字段名
|
|
|
+ },
|
|
|
+ proxyConfig: {
|
|
|
+ ajax: {
|
|
|
+ query: async ({ page }) => {
|
|
|
+ let form = {
|
|
|
+ page: page.currentPage,
|
|
|
+ limit: page.pageSize,
|
|
|
+ compress: 0
|
|
|
+ };
|
|
|
+ const search = await gridApi.formApi.getValues();
|
|
|
+ if(search.game_id) {
|
|
|
+ form.game_id = search.game_id;
|
|
|
+ }
|
|
|
+ if(search.range_time) {
|
|
|
+ form['start_time'] = search.range_time[0].format('YYYY-MM-DD');
|
|
|
+ form['end_time'] = search.range_time[1].format('YYYY-MM-DD');
|
|
|
+ }
|
|
|
+ if(search.search_text) {
|
|
|
+ form[filterData['search_type']] = search.search_text;
|
|
|
+ }
|
|
|
+ const list = await getPlayerControlList(form);
|
|
|
+ return {
|
|
|
+ total: list.total,
|
|
|
+ items: list.list
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ rowConfig: {
|
|
|
+ isHover: true,
|
|
|
+ },
|
|
|
+ toolbarConfig: {
|
|
|
+ custom: true,
|
|
|
+ export: true,
|
|
|
+ // import: true,
|
|
|
+ refresh: true,
|
|
|
+ zoom: true,
|
|
|
+ },
|
|
|
+};
|
|
|
+const [Grid, gridApi] = useVbenVxeGrid({
|
|
|
+ formOptions,
|
|
|
+ gridOptions,
|
|
|
+});
|
|
|
+
|
|
|
+// 查看玩家详情
|
|
|
+import ExtraModal from './create_player.vue';
|
|
|
+const [Modal, modalApi] = useVbenModal({
|
|
|
+ // 连接抽离的组件
|
|
|
+ connectedComponent: ExtraModal,
|
|
|
+ class:'w-[50%]',
|
|
|
+ onClosed: function () {
|
|
|
+ const _data = modalApi.getData();
|
|
|
+ if(_data.is_reload){
|
|
|
+ gridApi.reload();
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+const createControl = (row) => {
|
|
|
+ // modalApi.setData({
|
|
|
+ // user_id: row.user_id
|
|
|
+ // }).open();
|
|
|
+ modalApi.open();
|
|
|
+}
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <Page>
|
|
|
+ <Grid>
|
|
|
+ <template #bet_amount="{ row }">
|
|
|
+ <span style="color:red">{{row.bet}}</span>
|
|
|
+ </template>
|
|
|
+ <template #amount="{ row }">
|
|
|
+ <span style="color: green" v-if="row.amount >= 0">{{row.amount}}</span>
|
|
|
+ <span style="color: red" v-else>{{row.amount}}</span>
|
|
|
+ </template>
|
|
|
+ <template #total_win_amount="{ row }">
|
|
|
+ <span style="color: green" v-if="row.total_win_amount >= 0">{{row.total_win_amount}}</span>
|
|
|
+ <span style="color: red" v-else>{{row.total_win_amount}}</span>
|
|
|
+ </template>
|
|
|
+ <template #action_type="{ row }">
|
|
|
+ <Tag v-if="row.action_type == 1" color="blue">{{ $t('player_data.fundsChange.bet') }}</Tag>
|
|
|
+ <Tag v-if="row.action_type == 3" color="green">{{ $t('player_data.fundsChange.result_amount') }}</Tag>
|
|
|
+ <Tag v-if="row.action_type == 4" color="red">{{ $t('player_data.fundsChange.check') }}</Tag>
|
|
|
+ </template>
|
|
|
+ <template #game_title="{ row }">
|
|
|
+ <div>
|
|
|
+ <Tag color="blue" size="large">{{row.game_type_text}}</Tag>
|
|
|
+ <Avatar shape="square" :src="row.game_image_url"></Avatar>
|
|
|
+ <span style="margin-left: .5rem;display: inline-block;">{{row.game_title}}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #status="{ row }">
|
|
|
+ <Tag v-if="row.status == 2" color="green">{{$t('common.success')}}</Tag>
|
|
|
+ <Tag v-if="row.status == 0" color="red">{{$t('common.abnormal')}}</Tag>
|
|
|
+ <Tag v-if="row.status == 1" color="blue">{{$t('common.warn')}}</Tag>
|
|
|
+ </template>
|
|
|
+ <template #form-search_text="slotProps">
|
|
|
+ <Input-Group compact>
|
|
|
+ <Select name="search_type" style="width: 110px;" 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:calc(100% - 110px)"></Input>
|
|
|
+ </Input-Group>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #toolbar-actions>
|
|
|
+ <Button type="primary" @click="createControl">{{$t('game_control.button.create_control')}}</Button>
|
|
|
+ <Button type="primary" danger style="margin-left:10px;">{{$t('game_control.button.all_cancel_control')}}</Button>
|
|
|
+ </template>
|
|
|
+ </Grid>
|
|
|
+ <Modal />
|
|
|
+ </Page>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.ant-input-group.ant-input-group-compact>*:not(:last-child) {
|
|
|
+ border-inline-end-width: 0;
|
|
|
+}
|
|
|
+</style>
|