版本更新
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled

This commit is contained in:
hahwu 2025-07-17 15:07:34 +08:00
parent eaa008b67f
commit e52eb2ca64
11 changed files with 499 additions and 267 deletions

View File

@ -1,11 +1,10 @@
import { requestClient } from '#/api/request';
export interface UserData {
data: object[];
total: number;
sum : number;
psum : number;
nsum : number;
sum: number;
psum: number;
nsum: number;
}
export interface UserLogAssetParam {
Id: number;
@ -17,61 +16,60 @@ export interface UserLogAssetParam {
CurrentPage: number;
AppId?: number;
}
export interface UserLogOrder{
Id: number,
Time: number,
Type: number,
Diff: number,
ChessId: string,
export interface UserLogOrder {
Id: number;
Time: number;
Type: number;
Diff: number;
ChessId: string;
}
export interface heatType {
date :string;
value : number;
date: string;
value: number;
}
export interface UserLogInfo{
AreaId : number,
Charge:number,
Level: number,
Name: string,
Star: number,
Login: number,
Energy: number,
Diamond: number,
Mac : string,
Cumulative: number,
TodayCumulative: number,
Bonus?: number,
Order:UserLogOrder[],
Heatmap?: heatType[],
export interface UserLogInfo {
AreaId: number;
Charge: number;
Level: number;
Name: string;
Star: number;
Login: number;
Energy: number;
Diamond: number;
Mac: string;
Cumulative: number;
TodayCumulative: number;
Bonus?: number;
Code?: string;
RegisterTime: number;
Order: UserLogOrder[];
Heatmap?: heatType[];
}
export interface UserOrder{
Id: number,
OrderId: number,
Price: number,
PayChannelOrderId: number,
ProductId: number,
CreateTime: number,
PayTime: number,
PayType: number,
Param:string
export interface UserOrder {
Id: number;
OrderId: number;
Price: number;
PayChannelOrderId: number;
ProductId: number;
CreateTime: number;
PayTime: number;
PayType: number;
Param: string;
}
export async function getUserLogAssetApi(data : UserLogAssetParam) {
export async function getUserLogAssetApi(data: UserLogAssetParam) {
return requestClient.post<UserData>('/log/asset', data);
}
export async function getUserlogEventApi(data : UserLogAssetParam) {
export async function getUserlogEventApi(data: UserLogAssetParam) {
return requestClient.post<UserData>('/log/event', data);
}
export async function getUserlogInfoApi(data : UserLogAssetParam) {
export async function getUserlogInfoApi(data: UserLogAssetParam) {
return requestClient.post<UserLogInfo>('/log/user', data);
}
export async function getUserlogOrderApi(data : UserLogAssetParam) {
export async function getUserlogOrderApi(data: UserLogAssetParam) {
return requestClient.post<UserOrder>('/log/order', data);
}

View File

@ -29,7 +29,6 @@ export interface dataType{
onMounted(() => {
cal = new CalHeatMap();
console.log(new Date(new Date().getFullYear(), 1, 1), new Date(new Date().getFullYear()+1, 0, 0));
cal.paint({
itemSelector: '#cal-heatmap',
data: {

View File

@ -1,5 +1,7 @@
import eventTable from "./calendar/event-table.vue";
import calendar from "./calendar/index.vue";
import eventModal from "./modal/event.vue";
import assetModal from "./modal/asset.vue";
import type {dataType} from "./calendar/index.vue";
export { eventTable, calendar };
export { eventTable, calendar, eventModal, assetModal };
export type { dataType };

View File

@ -0,0 +1,100 @@
<script setup lang="ts">
import { useVbenModal } from '@vben/common-ui';
import { getUserLogAssetApi } from '#/api/core/log';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { inject, ref } from 'vue';
import { globalState } from '#/store/globalState';
import type { VxeGridProps } from '#/adapter/vxe-table';
const state = inject('globalState', globalState);
const [Modal, modalApi] = useVbenModal({
});
interface RowType {
Uid: number;
change_type: string;
change_num: string;
change_after: string;
item_id: string;
timestamp: string;
}
const formatType = (cellValue: string) => {
switch (cellValue) {
case "gain":
return '增加';
case "consume":
return '减少';
default:
return cellValue;
}
}
const formatItemName = (cellValue: number) => {
// console.log(cellValue);
switch (cellValue) {
case 100001:
return '能量';
case 100002:
return '宠物币';
case 100003:
return '钻石';
default:
return cellValue;
}
}
const d = ref({
sum : 0,
psum : 0,
nsum : 0,
});
const gridOptions: VxeGridProps<RowType> = {
columns: [
{ field: 'Uid', title: 'Uid' },
{ field: 'change_type', title: '变化类型', formatter:({cellValue}) => formatType(cellValue)},
{ field: 'change_num', title: '变化数值' },
{ field: 'change_after', title: '变化后数值' },
{ field: 'item_id', title: '道具id', formatter: ({ cellValue }) => formatItemName(cellValue) },
{ field: 'timestamp', title: '时间', formatter: ({ cellValue }) => new Date(cellValue*1000).toLocaleString()},
],
height: '500px',
keepSource: true,
pagerConfig: {},
proxyConfig: {
response: {
total: "total",
result: "data"
},
ajax: {
query: async () => {
const r = await getUserLogAssetApi({
Id: state.uid,
Event :'',
StartTime: modalApi.getData()?.StartTime || 0,
EndTime: modalApi.getData()?.EndTime || 0,
ItemId: 0,
CurrentPage: 1,
PageSize: 100,
});
d.value.sum = r.sum;
d.value.psum = r.psum;
d.value.nsum = r.nsum;
return r
},
},
},
rowConfig: {
isHover: true,
},
};
const [Grid] = useVbenVxeGrid({ gridOptions});
</script>
<template>
<Modal>
<Grid />
</Modal>
</template>

View File

@ -0,0 +1,66 @@
<script setup lang="ts">
import { getUserlogEventApi } from '#/api/core/log';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { inject } from 'vue';
import { globalState } from '#/store/globalState';
import { $t } from '#/locales';
import type { VxeGridProps } from '#/adapter/vxe-table';
import {useVbenModal } from '@vben/common-ui';
const state = inject('globalState', globalState);
interface RowType {
Uid: string;
Event: string;
Param: string;
Timestamp: string;
}
const [Modal, modalApi] = useVbenModal({});
const gridOptions: VxeGridProps<RowType> = {
columns: [
{ field: 'Uid', title: 'Uid' },
{ field: 'Event', title: '事件类型', formatter: ({ cellValue }) => $t('page.log.event.' + `${cellValue}`) || cellValue },
{ field: 'Label', title: 'Label'},
{ field: 'Param', title: '参数' },
{ field: 'Timestamp', title: '时间', formatter: ({ cellValue }) => new Date(cellValue*1000).toLocaleString()},
],
stripe: true,
height: 'auto',
pagerConfig: {
enabled:true
},
proxyConfig: {
response: {
total: "total",
result: "data"
},
ajax: {
query: async () => {
return await getUserlogEventApi({
Id: state.uid,
Event: '',
StartTime: modalApi.getData()?.StartTime || "2025-03-17T16:00:00.000Z",
EndTime: modalApi.getData()?.EndTime || "2025-03-17T16:00:00.000Z",
CurrentPage: 1,
PageSize: 100,
});
},
},
},
rowConfig: {
isHover: true,
},
};
const [Grid] = useVbenVxeGrid({gridOptions });
</script>
<template>
<Modal>
<Grid style="height: 500px;" />
</Modal>
</template>

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,21 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import { Page, useVbenModal } from '@vben/common-ui';
import type { VxeGridListeners } from 'vxe-table';
import { getUserLogAssetApi } from '#/api/core/log';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { inject, ref } from 'vue';
import { globalState } from '#/store/globalState';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { VbenFormProps } from '#/adapter/form';
import { ItemData } from '#/store/item';
import { eventModal } from '#/component';
import dayjs from 'dayjs';
const state = inject('globalState', globalState);
const [Modal, modalApi] = useVbenModal({
connectedComponent:eventModal,
class:'width:1800px;',
});
interface RowType {
Uid: number;
change_type: string;
@ -30,16 +36,7 @@ const formatType = (cellValue: string) => {
}
const formatItemName = (cellValue: number) => {
// console.log(cellValue);
switch (cellValue) {
case 100001:
return '能量';
case 100002:
return '宠物币';
case 100003:
return '钻石';
default:
return cellValue;
}
return ItemData.find((item) => item.Id === cellValue)?.Name || cellValue;
}
const d = ref({
sum : 0,
@ -141,21 +138,31 @@ const formOptions: VbenFormProps = {
//
submitOnEnter: false,
}
const gridEvents: VxeGridListeners<RowType> = {
cellClick: async ({ row }) => {
console.log(row);
modalApi.setData({
StartTime: row.timestamp,
EndTime: row.timestamp,
});
modalApi.open();
},
};
const gridOptions: VxeGridProps<RowType> = {
columns: [
{ field: 'Uid', title: 'Uid' },
{ field: 'change_type', title: '变化类型', formatter:({cellValue}) => formatType(cellValue)},
{ field: 'change_num', title: '变化数值' },
{ field: 'change_after', title: '变化后数值' },
{ field: 'item_id', title: '道具id', formatter: ({ cellValue }) => formatItemName(cellValue) },
{ field: 'timestamp', title: '时间', formatter: ({ cellValue }) => new Date(cellValue*1000).toLocaleString()},
{ field: 'Uid', title: 'Uid' },
{ field: 'change_type', title: '变化类型', formatter:({cellValue}) => formatType(cellValue)},
{ field: 'change_num', title: '变化数值' },
{ field: 'change_after', title: '变化后数值' },
{ field: 'item_id', title: '道具名称', formatter: ({ cellValue }) => formatItemName(cellValue) },
{ field: 'item_id', title: '道具id'},
{ field: 'timestamp', title: '时间', formatter: ({ cellValue }) => new Date(cellValue*1000).toLocaleString()},
],
height: 'auto',
keepSource: true,
toolbarConfig: {
custom: true,
export: true,
// import: true,
refresh: true,
zoom: true,
},
@ -174,11 +181,13 @@ const gridOptions: VxeGridProps<RowType> = {
state.uid = uid;
const ItemId = parseInt(formValues.ItemId, 10);
console.log(formValues.StartTime.unix());
const r = await getUserLogAssetApi({
Id: uid,
Event :formValues.Event,
StartTime: formValues.StartTime,
EndTime: formValues.EndTime,
StartTime: formValues.StartTime.unix(),
EndTime: formValues.EndTime.unix(),
ItemId: ItemId,
CurrentPage: page.currentPage,
PageSize: page.pageSize,
@ -196,18 +205,21 @@ const gridOptions: VxeGridProps<RowType> = {
},
};
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions, gridEvents });
</script>
<template>
<Page auto-content-height>
<Grid>
<template #toolbar-tools>
总数:<span style="margin-right: 10px;margin-left: 5px;"> {{ d.sum }} </span>
正数和: <span style="margin-right: 10px;margin-left: 5px;color:green">{{ d.psum }} </span>
负数和: <span style="color: red;margin-left: 5px;">{{ d.nsum }} </span>
</template>
<div>
<Page auto-content-height>
<Grid>
<template #toolbar-tools>
总数:<span style="margin-right: 10px;margin-left: 5px;"> {{ d.sum }} </span>
正数和: <span style="margin-right: 10px;margin-left: 5px;color:green">{{ d.psum }} </span>
负数和: <span style="color: red;margin-left: 5px;">{{ d.nsum }} </span>
</template>
</Grid>
</Page>
</Page>
<Modal class="w-[1200px]" "> </Modal>
</div>
</template>

View File

@ -2,16 +2,21 @@
import { getUserlogEventApi } from '#/api/core/log';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { inject, ref } from 'vue';
import { inject } from 'vue';
import type { VxeGridListeners } from 'vxe-table';
import { globalState } from '#/store/globalState';
import { $t } from '#/locales';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { VbenFormProps } from '#/adapter/form';
import { Page } from '@vben/common-ui';
import { Page, useVbenModal } from '@vben/common-ui';
import { assetModal } from '#/component';
import dayjs from 'dayjs';
const state = inject('globalState', globalState);
const [Modal, modalApi] = useVbenModal({
connectedComponent:assetModal,
class:'width:1800px;',
});
const startDate = dayjs().startOf('day');
const endDate = dayjs().endOf('day');
interface RowType {
@ -92,9 +97,19 @@ const formOptions: VbenFormProps = {
submitOnEnter: false,
wrapperClass: 'grid-cols-1 md:grid-cols-5',
}
const gridEvents: VxeGridListeners<RowType> = {
cellClick: async ({ row }) => {
console.log(row);
modalApi.setData({
StartTime: row.Timestamp,
EndTime: row.Timestamp,
});
modalApi.open();
},
};
const gridOptions: VxeGridProps<RowType> = {
columns: [
{ field: 'Uid', title: 'id' },
{ field: 'Uid', title: 'Uid' },
{ field: 'Event', title: '事件类型', formatter: ({ cellValue }) => $t('page.log.event.' + `${cellValue}`) || cellValue },
{ field: 'Label', title: 'Label'},
{ field: 'Param', title: '参数' },
@ -119,8 +134,8 @@ const gridOptions: VxeGridProps<RowType> = {
return await getUserlogEventApi({
Id: Uid,
Event: formValues.Event,
StartTime: formValues.StartTime,
EndTime: formValues.EndTime,
StartTime: formValues.StartTime.unix(),
EndTime: formValues.EndTime.unix(),
CurrentPage: page.currentPage,
PageSize: page.pageSize,
});
@ -133,12 +148,16 @@ const gridOptions: VxeGridProps<RowType> = {
},
};
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions, gridEvents });
</script>
<template>
<Page auto-content-height>
<Grid />
</Page>
<div>
<Page auto-content-height>
<Grid />
</Page>
<Modal class="w-[1200px]"> </Modal>
</div>
</template>

View File

@ -4,25 +4,15 @@ import { useVbenModal, useVbenForm } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { getUserlogInfoApi } from '#/api/core/log';
import { userGmApi } from '#/api/core/user';
import {calendar} from '#/component/index'
import type {dataType} from '#/component/index';
import { calendar } from '#/component/index';
import type { dataType } from '#/component/index';
// cal-heatmap
import 'cal-heatmap/cal-heatmap.css';
import type {
WorkbenchProjectItem,
} from '@vben/common-ui';
import type { WorkbenchProjectItem } from '@vben/common-ui';
import dayjs from 'dayjs';
import {
WorkbenchProject,
WorkbenchDetail,
} from '@vben/common-ui';
import UserHeader from './user-header.vue';
import { WorkbenchProject, WorkbenchDetail } from '@vben/common-ui';
import UserHeader from './user-header.vue';
import { preferences } from '@vben/preferences';
import { useUserStore } from '@vben/stores';
@ -50,21 +40,21 @@ const [BaseForm] = useVbenForm({
schema: [
{
component: 'Input',
defaultValue: "",
defaultValue: '',
componentProps: {
placeholder: '请输入gm命令',
placeholder: '请输入gm命令',
},
label: 'Gm:',
fieldName: 'gm',
}
},
],
handleSubmit: async (values) => {
const cv = modalApi.getData<Record<string, any>>();
const cv = modalApi.getData<Record<string, any>>();
const r = await userGmApi({
Uid: cv.uid,
AppId: cv.AppId,
ServerId: cv.ServerId,
Command: values.gm,
Uid: cv.uid,
AppId: cv.AppId,
ServerId: cv.ServerId,
Command: values.gm,
});
message.success(r.Msg);
},
@ -75,85 +65,97 @@ const [BaseForm] = useVbenForm({
const data = ref();
const info = ref<{
Level: number;
Star: number;
Name: string;
Charge: number;
AreaId: number;
LoginTime: string;
Diamond: number;
Energy: number;
Mac: string;
Uid: number;
Cumulative:string;
TodayCumulative:string;
Bonus?: number;
Order: WorkbenchProjectItem[];
Heatmap: dataType[];
Level: number;
Star: number;
Name: string;
Charge: number;
AreaId: number;
LoginTime: string;
Diamond: number;
Energy: number;
Mac: string;
Uid: number;
Cumulative: string;
TodayCumulative: string;
Bonus?: number;
Code?: string;
RegisterTime?: string;
Order: WorkbenchProjectItem[];
Heatmap: dataType[];
}>({
Level: 0,
Star: 0,
Name: '',
Charge: 0,
Uid: 0,
AreaId: 0,
LoginTime: '',
Diamond: 0,
Energy: 0,
Mac: '',
Cumulative:'0h',
TodayCumulative:'0h',
Order: [],
Heatmap: [],
})
Level: 0,
Star: 0,
Name: '',
Charge: 0,
Uid: 0,
AreaId: 0,
LoginTime: '',
Diamond: 0,
Energy: 0,
Mac: '',
Cumulative: '0h',
TodayCumulative: '0h',
Order: [],
Heatmap: [],
});
const [Modal, modalApi] = useVbenModal({
onCancel() {
modalApi.close();
},
onConfirm() {
message.info('onConfirm');
// modalApi.close();
},
async onOpenChange(isOpen: boolean) {
if (isOpen) {
data.value = modalApi.getData<Record<string, any>>();
try {
const r = await getUserlogInfoApi({
Id: data.value.uid,
Event: 'someEvent', // replace 'someEvent' with the actual event
PageSize: 10, // replace 10 with the actual page size
CurrentPage: 1, // replace 1 with the actual current page
});
info.value.Uid = data.value.uid;
info.value.Level = r.Level
info.value.Star = r.Star
info.value.Name = r.Name
info.value.Charge = r.Charge
info.value.AreaId = r.AreaId
info.value.LoginTime = dayjs(r.Login * 1000).format('YYYY-MM-DD HH:mm:ss'); //
info.value.Diamond = r.Diamond
info.value.Energy = r.Energy
info.value.Mac = r.Mac
info.value.Cumulative = (r.Cumulative / 3600).toFixed(2) + 'h'
info.value.TodayCumulative = (r.TodayCumulative / 3600).toFixed(2) + 'h'
info.value.Order = []
info.value.Heatmap = r.Heatmap || [];
for (const i in r.Order) {
info.value.Order.push({
color: '#3fb27f',
content: r.Order[i]?.ChessId || '',
date: dayjs((r.Order[i]?.Time ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss') || '',
group: String(r.Order[i]?.Type) || '',
icon: 'lets-icons:order',
title: String(r.Order[i]?.Id) || '',
url: '',
});
}
} catch (error) {
//console.error('Error fetching user info:', error);
}
onCancel() {
modalApi.close();
},
onConfirm() {
message.info('onConfirm');
// modalApi.close();
},
async onOpenChange(isOpen: boolean) {
if (isOpen) {
data.value = modalApi.getData<Record<string, any>>();
try {
const r = await getUserlogInfoApi({
Id: data.value.uid,
Event: 'someEvent', // replace 'someEvent' with the actual event
PageSize: 10, // replace 10 with the actual page size
CurrentPage: 1, // replace 1 with the actual current page
});
info.value.Uid = data.value.uid;
info.value.Level = r.Level;
info.value.Star = r.Star;
info.value.Name = r.Name;
info.value.Charge = r.Charge;
info.value.AreaId = r.AreaId;
info.value.LoginTime = dayjs(r.Login * 1000).format(
'YYYY-MM-DD HH:mm:ss',
); //
info.value.Diamond = r.Diamond;
info.value.Energy = r.Energy;
info.value.Mac = r.Mac;
info.value.Cumulative = (r.Cumulative / 3600).toFixed(2) + 'h';
info.value.TodayCumulative =
(r.TodayCumulative / 3600).toFixed(2) + 'h';
info.value.Order = [];
info.value.Code = r.Code || '';
info.value.RegisterTime = dayjs(r.RegisterTime * 1000).format(
'YYYY-MM-DD HH:mm:ss',
); //
info.value.Heatmap = r.Heatmap || [];
for (const i in r.Order) {
info.value.Order.push({
color: '#3fb27f',
content: r.Order[i]?.ChessId || '',
date:
dayjs((r.Order[i]?.Time ?? 0) * 1000).format(
'YYYY-MM-DD HH:mm:ss',
) || '',
group: String(r.Order[i]?.Type) || '',
icon: 'lets-icons:order',
title: String(r.Order[i]?.Id) || '',
url: '',
});
}
},
} catch (error) {
//console.error('Error fetching user info:', error);
}
}
},
});
//
@ -161,59 +163,70 @@ watch(
() => info.value.Heatmap,
(newHeatmap) => {
if (newHeatmap && newHeatmap.length > 0) {
console.log('Heatmap data loaded:', newHeatmap);
//
}
},
{ deep: true }
{ deep: true },
);
</script>
<template>
<Modal title="玩家详情">
<div class="p-5">
<UserHeader :avatar="userStore.userInfo?.avatar || preferences.app.defaultAvatar">
<template #nick_name>
nick_name: {{ info.Name || 'N/A' }}
</template>
<template #user_name> user_name: {{ info.Mac }} </template>
<template #uid> uid: {{ info.Uid }} </template>
<template #level>{{ info.Level }}</template>
<template #star>{{ info.Star }}</template>
<template #energy>{{ info.Energy }} </template>
<template #diamond>{{ info.Diamond }}</template>
</UserHeader>
<div class="mt-5">
<BaseForm />
</div>
<div class="mt-5 flex flex-col lg:flex-row">
<div class="mr-4 w-full lg:w-3/5">
<WorkbenchProject :items="info.Order" title="订单" />
<!-- <WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" /> -->
</div>
<div class="w-full lg:w-2/5">
<WorkbenchDetail :items="projectItems" class="mt-5 lg:mt-0" title="玩家详情">
<template #areaid> {{ info.AreaId }}</template>
<template #charge> <b>$</b>{{ info.Charge.toFixed(2) }}</template>
<template #logintime> {{ info.LoginTime }}</template>
<template #Cumulative>{{ info.Cumulative }}</template>
<template #AreaId>{{ info.AreaId }}</template>
<template #Bonus>{{ info.Bonus || 0 }}</template>
<template #TodayCumulative>{{ info.TodayCumulative }}</template>
</WorkbenchDetail>
<calendar
v-if="info.Heatmap.length > 0"
style="margin-top:15px"
:dataList="info.Heatmap"
title="热力图"
:key="`heatmap-${info.Uid}`"
/>
<div v-else style="margin-top:15px; padding: 20px; text-align: center; color: #999;">
暂无热力图数据
</div>
<!-- <WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" /> -->
</div>
</div>
<Modal title="玩家详情">
<div class="p-5">
<UserHeader
:avatar="userStore.userInfo?.avatar || preferences.app.defaultAvatar"
>
<template #nick_name> nick_name: {{ info.Name || 'N/A' }} </template>
<template #user_name> user_name: {{ info.Mac }} </template>
<template #uid> uid: {{ info.Uid }} </template>
<template #level>{{ info.Level }}</template>
<template #star>{{ info.Star }}</template>
<template #energy>{{ info.Energy }} </template>
<template #diamond>{{ info.Diamond }}</template>
</UserHeader>
<div class="mt-5">
<BaseForm />
</div>
<div class="mt-5 flex flex-col lg:flex-row">
<div class="mr-4 w-full lg:w-3/5">
<WorkbenchProject :items="info.Order" title="订单" />
<!-- <WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" /> -->
</div>
</Modal>
<div class="w-full lg:w-2/5">
<WorkbenchDetail
:items="projectItems"
class="mt-5 lg:mt-0"
title="玩家详情"
>
<template #areaid> {{ info.AreaId }}</template>
<template #charge> <b>$</b>{{ info.Charge.toFixed(2) }}</template>
<template #RegisterTime> {{ info.RegisterTime }}</template>
<template #logintime> {{ info.LoginTime }}</template>
<template #Cumulative>{{ info.Cumulative }}</template>
<template #AreaId>{{ info.AreaId }}</template>
<template #Code>{{ info.Code || 0 }}</template>
<template #TodayCumulative>{{ info.TodayCumulative }}</template>
</WorkbenchDetail>
<calendar
v-if="info.Heatmap.length > 0"
style="margin-top: 15px"
:dataList="info.Heatmap"
title="热力图"
:key="`heatmap-${info.Uid}`"
/>
<div
v-else
style="
margin-top: 15px;
padding: 20px;
text-align: center;
color: #999;
"
>
暂无热力图数据
</div>
<!-- <WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" /> -->
</div>
</div>
</div>
</Modal>
</template>

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import { getUserListApi } from '#/api';
// import { getPlayerInfoApi } from '#/api/core/player';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import dayjs from 'dayjs'; // 使 dayjs
import { Tag } from 'ant-design-vue';
@ -9,10 +8,11 @@ import type { VbenFormProps } from '#/adapter/form';
import { Page } from '@vben/common-ui';
import type { VxeGridListeners } from 'vxe-table';
import { useVbenModal } from '@vben/common-ui'
import { onMounted, ref } from 'vue';
import { onMounted, ref, inject } from 'vue';
import { globalState } from '#/store/globalState';
import { getServerListApi, getAppListApi } from '#/api/core/server';
import type { AppData, ServerData } from '#/api/core/server';
const state = inject('globalState', globalState);
const appList = ref<AppData[]>([]);
const ServerList = ref<ServerData[]>([]);
import userModalDemo from './user.vue';
@ -111,7 +111,7 @@ const gridEvents: VxeGridListeners<RowType> = {
const value = await GridApi.formApi.getValues();
userModalApi.setData({ uid: row.Uid, AppId: value.AppId, ServerId: value.ServerId });
userModalApi.open();
await navigator.clipboard.writeText(row.Uid.toString());
state.uid = row.Uid;
},
};

View File

@ -1,11 +1,6 @@
<script setup lang="ts">
import type { WorkbenchProjectItem } from '../typing';
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from '@vben-core/shadcn-ui';
import { Card, CardContent, CardHeader, CardTitle } from '@vben-core/shadcn-ui';
interface Props {
items: WorkbenchProjectItem[];
@ -29,14 +24,17 @@ defineEmits(['click']);
<CardTitle class="text-lg">{{ title }}</CardTitle>
</CardHeader>
<CardContent class="flex flex-wrap p-0">
<div class="border-border w-full border-b border-r border-t p-5 transition-all hover:shadow-xl">
<div
class="border-border w-full border-b border-r border-t p-5 transition-all hover:shadow-xl"
>
<div class="flex w-full">
<div class="text-foreground/80 flex h-4 md:w-1/2 p-1 leading-2">
<div class="text-foreground/80 leading-2 flex h-4 p-1 md:w-1/2">
<span class="font-bold">总充值金额:</span>
</div>
<div class="text-foreground/80 flex h-4 md:w-1/2 justify-start p-1 leading-2">
<div class="Value ">
<div
class="text-foreground/80 leading-2 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.charge">
<slot name="charge"></slot>
</span>
@ -45,11 +43,13 @@ defineEmits(['click']);
</div>
<div class="flex w-full">
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2 ">
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">场景:</span>
</div>
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2">
<div class="Value ">
<div
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.AreaId">
<slot name="AreaId"></slot>
</span>
@ -58,11 +58,28 @@ defineEmits(['click']);
</div>
<div class="flex w-full">
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2 ">
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">注册时间:</span>
</div>
<div
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.RegisterTime">
<slot name="RegisterTime"></slot>
</span>
</div>
</div>
</div>
<div class="flex w-full">
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">最后登录:</span>
</div>
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2">
<div class="Value ">
<div
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.logintime">
<slot name="logintime"></slot>
</span>
@ -71,11 +88,13 @@ defineEmits(['click']);
</div>
<div class="flex w-full">
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2">
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">累计在线:</span>
</div>
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2">
<div class="Value ">
<div
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.Cumulative">
<slot name="Cumulative"></slot>
</span>
@ -84,11 +103,13 @@ defineEmits(['click']);
</div>
<div class="flex w-full">
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2">
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">今日累计在线:</span>
</div>
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2">
<div class="Value ">
<div
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.TodayCumulative">
<slot name="TodayCumulative"></slot>
</span>
@ -97,13 +118,15 @@ defineEmits(['click']);
</div>
<div class="flex w-full">
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2">
<span class="font-bold">Bonus:</span>
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
<span class="font-bold">邀请码:</span>
</div>
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2 text-shadow">
<div class="Value ">
<span v-if="$slots.Bonus">
<slot name="Bonus"></slot>
<div
class="text-foreground/80 leading-2 text-shadow mt-3 flex h-4 justify-start p-1 md:w-1/2"
>
<div class="Value">
<span v-if="$slots.Code">
<slot name="Code"></slot>
</span>
</div>
</div>
@ -117,5 +140,4 @@ defineEmits(['click']);
.Value {
text-align: center;
}
</style>