版本更新
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
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:
parent
487753fdc5
commit
e0d7b5c509
3
apps/web-antd/.vscode/settings.json
vendored
3
apps/web-antd/.vscode/settings.json
vendored
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"workbench.colorTheme":"One Dark Pro",
|
"workbench.colorTheme":"One Dark Pro",
|
||||||
"editor.fontSize": 14
|
"editor.fontSize": 14,
|
||||||
|
"typescript.experimental.useTsgo": false
|
||||||
}
|
}
|
||||||
18
apps/web-antd/.vscode/tasks.json
vendored
Normal file
18
apps/web-antd/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "pnpm build:antd",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "pnpm",
|
||||||
|
"args": [
|
||||||
|
"build:antd"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "D:\\Github\\admin_web"
|
||||||
|
},
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
apps/web-antd/public/item/shop_diamond_LV1.png
Normal file
BIN
apps/web-antd/public/item/shop_diamond_LV1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
apps/web-antd/public/item/shop_energy_LV1.png
Normal file
BIN
apps/web-antd/public/item/shop_energy_LV1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
apps/web-antd/public/merge_pic_expplate2.png
Normal file
BIN
apps/web-antd/public/merge_pic_expplate2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
@ -1,4 +1,5 @@
|
|||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
import type { friendRecord } from '#/model/type';
|
||||||
|
|
||||||
export interface UserData {
|
export interface UserData {
|
||||||
data: object[];
|
data: object[];
|
||||||
@ -55,6 +56,8 @@ export interface UserLogInfo {
|
|||||||
ChessMap?:string;
|
ChessMap?:string;
|
||||||
Heatmap?: heatType[];
|
Heatmap?: heatType[];
|
||||||
ActLog?:actlog[];
|
ActLog?:actlog[];
|
||||||
|
MaxCharge?: number;
|
||||||
|
FriendList?: friendRecord[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface actlog {
|
export interface actlog {
|
||||||
|
|||||||
@ -23,6 +23,9 @@ export interface MailData {
|
|||||||
send_type: number;
|
send_type: number;
|
||||||
to_uids :string;
|
to_uids :string;
|
||||||
create_time?: number;
|
create_time?: number;
|
||||||
|
title_es_latam?: string;
|
||||||
|
subTitle_es_latam?: string;
|
||||||
|
content_es_latam?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MailListParam {
|
export interface MailListParam {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export interface ServerData {
|
|||||||
MemUsage?: number;
|
MemUsage?: number;
|
||||||
ClientVersion?: string;
|
ClientVersion?: string;
|
||||||
Tags?: string[];
|
Tags?: string[];
|
||||||
|
Latency?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface editServerParam {
|
export interface editServerParam {
|
||||||
|
|||||||
@ -5,5 +5,6 @@ import assetModal from "./modal/asset.vue";
|
|||||||
import orderComponent from "./modal/orderComponent.vue";
|
import orderComponent from "./modal/orderComponent.vue";
|
||||||
import chessComponent from "./modal/chessComponent.vue";
|
import chessComponent from "./modal/chessComponent.vue";
|
||||||
import type {dataType} from "./calendar/index.vue";
|
import type {dataType} from "./calendar/index.vue";
|
||||||
export { eventTable, calendar, eventModal, assetModal, orderComponent, chessComponent };
|
import friendComponent from "./user/friend/index.vue";
|
||||||
|
export { eventTable, calendar, eventModal, assetModal, orderComponent, chessComponent, friendComponent };
|
||||||
export type { dataType };
|
export type { dataType };
|
||||||
|
|||||||
@ -25,13 +25,14 @@ defineEmits(['click']);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Card>
|
<Card class="hover:shadow-lg">
|
||||||
<CardHeader class="py-4 border-border border-b">
|
<CardHeader class="py-4 border-b">
|
||||||
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="flex flex-wrap p-0">
|
<CardContent class="flex flex-wrap p-0" style="background-color: rgb(132, 86, 68);">
|
||||||
|
<div class="flex flex-wrap items-center justify-center w-full h-full mt-1 mb-1">
|
||||||
<template v-for="(item, index) in [...items].sort((a, b) => a.Pos - b.Pos)" :key="index">
|
<template v-for="(item, index) in [...items].sort((a, b) => a.Pos - b.Pos)" :key="index">
|
||||||
<div class="border-border group cursor-pointer border-b border-r border-t p-0 transition-all hover:shadow-xl flex-none"
|
<div class=" group cursor-pointer border-b border-r border-t p-0 transition-all hover:shadow-xl flex-none"
|
||||||
:style="{ width: '35px', height: '35px', backgroundColor: index % 2 === 1 ? '#ced1ca' : '#dde0d7' }"
|
:style="{ width: '35px', height: '35px', backgroundColor: index % 2 === 1 ? '#ced1ca' : '#dde0d7' }"
|
||||||
style="position: relative;" :id="index.toString()">
|
style="position: relative;" :id="index.toString()">
|
||||||
<img v-if="item.Icon" :src="`../../../merge/${item.Icon}.png`"
|
<img v-if="item.Icon" :src="`../../../merge/${item.Icon}.png`"
|
||||||
@ -41,6 +42,7 @@ defineEmits(['click']);
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="(index + 1) % 7 === 0" class="w-full h-0" :id="(index + 1).toString()"></div>
|
<div v-if="(index + 1) % 7 === 0" class="w-full h-0" :id="(index + 1).toString()"></div>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
30
apps/web-antd/src/component/user/friend/friend_item.vue
Normal file
30
apps/web-antd/src/component/user/friend/friend_item.vue
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {Tag} from "ant-design-vue";
|
||||||
|
import { VbenAvatar } from '../../../../../../packages/@core/ui-kit/shadcn-ui/src/components';
|
||||||
|
import type {friendRecord} from "#/model/type";
|
||||||
|
defineProps({
|
||||||
|
// 定义一个名为 "friend" 的 prop,类型为对象,包含好友的相关信息
|
||||||
|
friend: {
|
||||||
|
type: Object as () => friendRecord,
|
||||||
|
required: true, // 这个 prop 是必需的
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center p-4 border-b border-black pl-12 ml-4 mr-4 mt-2 w-[60%]" style="background: rgb(255, 254, 231);border-radius: 1cm; padding: 1px 10px 1px 10px;justify-content: space-between;">
|
||||||
|
<VbenAvatar :src="'./' + friend.avatarUrl" class="w-12 h-12 rounded-full " />
|
||||||
|
<div class="ml-5 w-full">
|
||||||
|
<div class="flex flex-row items-center w-full">
|
||||||
|
<h2 class="text-sm font-semibold text-black">{{ friend.NickName }}</h2>
|
||||||
|
<Tag class="text-xs ml-2" color="green" v-if="friend.onlineStatus">在线</Tag>
|
||||||
|
<Tag class="text-xs ml-2" color="red" v-else>离线</Tag>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-gray-500">uid:{{ friend.Uid }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="ml-40 flex items-center relative">
|
||||||
|
<img src="../../../../public/merge_pic_expplate2.png" />
|
||||||
|
<span class="absolute inset-0 flex items-center justify-center text-white font-bold">Lv.{{ friend.Level }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
56
apps/web-antd/src/component/user/friend/index.vue
Normal file
56
apps/web-antd/src/component/user/friend/index.vue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import firendItem from "./friend_item.vue";
|
||||||
|
import { Pagination } from "ant-design-vue";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from '../../../../../../packages/@core/ui-kit/shadcn-ui';
|
||||||
|
import type { friendRecord } from "../../../model/type";
|
||||||
|
import CardFooter from "../../../../../../packages/@core/ui-kit/shadcn-ui/src/ui/card/CardFooter.vue";
|
||||||
|
defineProps({
|
||||||
|
Items: {
|
||||||
|
type: Array as () => friendRecord[],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const currentPage = ref(1);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Card style="background-color: rgb(236, 214, 179);" class="hover:shadow-lg">
|
||||||
|
<CardHeader class="py-4 border-b border-gray-200">
|
||||||
|
<CardTitle class="text-lg">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="text-center text-black">{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent class="flex flex-wrap p-0 items-center justify-center ">
|
||||||
|
<template v-if="Items.length === 0">
|
||||||
|
<div class="flex flex-col items-center justify-center w-full h-full py-10">
|
||||||
|
<p class="text-gray-500">暂无好友数据</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-for="(item, index) in Items.slice((currentPage - 1) * 10, currentPage * 10)" :key="index">
|
||||||
|
<firendItem :friend="item"></firendItem>
|
||||||
|
</template>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter class="py-4 flex flex-col items-center border-t border-gray-200 mt-2">
|
||||||
|
<Pagination
|
||||||
|
v-model:current="currentPage"
|
||||||
|
:total="Items.length"
|
||||||
|
:pageSize="10"
|
||||||
|
:showSizeChanger="false"
|
||||||
|
>
|
||||||
|
|
||||||
|
</Pagination>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
</template>
|
||||||
@ -84,3 +84,13 @@ export interface scriptsRecord{
|
|||||||
code: number;
|
code: number;
|
||||||
color?: string;
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface friendRecord{
|
||||||
|
Uid: number;
|
||||||
|
NickName: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
Level: number;
|
||||||
|
LogoutTime?: string;
|
||||||
|
LoginTime: string;
|
||||||
|
onlineStatus?: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export const overridesPreferences = defineOverridesPreferences({
|
|||||||
companySiteLink: 'https://bywaystudios.com',
|
companySiteLink: 'https://bywaystudios.com',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
enable: true,
|
enable: false,
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
source: import.meta.env.VITE_APP_LOGO || 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
|
source: import.meta.env.VITE_APP_LOGO || 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,13 @@
|
|||||||
import MergeData from "./MergeData.json";
|
import MergeData from './MergeData.json';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
export function getImageUrl(key: string): string {
|
export function getImageUrl(key: string): string {
|
||||||
if (!key) return "";
|
if (!key) return '';
|
||||||
|
|
||||||
// 1. 判断 key 是否为 UI_MergeData_<number> 格式,取出数字;同时支持直接传入数字字符串或数字
|
// 1. 判断 key 是否为 UI_MergeData_<number> 格式,取出数字;同时支持直接传入数字字符串或数字
|
||||||
let id: string | null = null;
|
let id: string | null = null;
|
||||||
const m = /^UI_MergeData_(\d+)$/.exec(key);
|
const m = /^UI_MergeData_(\d+)$/.exec(key);
|
||||||
if (m) id = m[1] ?? "";
|
if (m) id = m[1] ?? '';
|
||||||
else if (/^\d+$/.test(key)) id = key;
|
else if (/^\d+$/.test(key)) id = key;
|
||||||
else id = String(key);
|
else id = String(key);
|
||||||
|
|
||||||
@ -22,15 +23,24 @@ export function getImageUrl(key: string): string {
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const SEARCH_DIR = 'D:\\Github\\AplusB_Pet_nation\\Assets\\GameMain\\UI\\UISprites\\MergeObj';
|
const SEARCH_DIR =
|
||||||
|
'D:\\Github\\AplusB_Pet_nation\\Assets\\GameMain\\UI\\UISprites\\MergeObj';
|
||||||
|
|
||||||
function findFile(dir: string): string | null {
|
function findFile(dir: string): string | null {
|
||||||
let entries: string[] = [];
|
let entries: string[] = [];
|
||||||
try { entries = fs.readdirSync(dir); } catch (e) { return null; }
|
try {
|
||||||
|
entries = fs.readdirSync(dir);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
for (const name of entries) {
|
for (const name of entries) {
|
||||||
const full = path.join(dir, name);
|
const full = path.join(dir, name);
|
||||||
let stat;
|
let stat;
|
||||||
try { stat = fs.statSync(full); } catch (e) { continue; }
|
try {
|
||||||
|
stat = fs.statSync(full);
|
||||||
|
} catch (e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
const res = findFile(full);
|
const res = findFile(full);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
@ -50,3 +60,29 @@ export function getImageUrl(key: string): string {
|
|||||||
// 回退:返回 icon 名称(供前端拼接资源路径使用)
|
// 回退:返回 icon 名称(供前端拼接资源路径使用)
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getUnixTime = (date: any): number => {
|
||||||
|
if (date) {
|
||||||
|
if (typeof date === 'string') {
|
||||||
|
return dayjs(date).unix();
|
||||||
|
} else if (dayjs.isDayjs(date)) {
|
||||||
|
return date.unix();
|
||||||
|
} else if (typeof (date as any).unix === 'function') {
|
||||||
|
return (date as any).unix();
|
||||||
|
} else {
|
||||||
|
return dayjs(date).unix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getItemUrl = (itemId: number): string => {
|
||||||
|
switch (itemId) {
|
||||||
|
case 100001:
|
||||||
|
return './Assets/Art_SubModule/Art_Resource/Art_UISprites/Shop/Big/shop_energy_LV1.png';
|
||||||
|
case 100003:
|
||||||
|
return './Assets/Art_SubModule/Art_Resource/Art_UISprites/Shop/Big/shop_diamond_LV2.png';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -49,6 +49,16 @@ function getCpuColor(usage: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLatencyColor(latency: number) {
|
||||||
|
if (latency < 100) {
|
||||||
|
return 'green';
|
||||||
|
} else if (latency < 200) {
|
||||||
|
return 'orange';
|
||||||
|
} else {
|
||||||
|
return 'red';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function formatMemUsage(usage: number) {
|
function formatMemUsage(usage: number) {
|
||||||
if (usage < 1024) {
|
if (usage < 1024) {
|
||||||
return usage + ' MB';
|
return usage + ' MB';
|
||||||
@ -179,6 +189,11 @@ function getStatusName(status: number) {
|
|||||||
<span>{{ item.ClientVersion }}</span>
|
<span>{{ item.ClientVersion }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||||
|
<h1 class="text-md font-semibold md:text-ml text-center">
|
||||||
|
<span :style="{ color: getLatencyColor(item.Latency || 0) }">{{ item.Latency }}ms</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||||
<h1 class="text-md font-semibold md:text-ml text-center">
|
<h1 class="text-md font-semibold md:text-ml text-center">
|
||||||
<Button @click=confirmUpdate(item) type="primary" :loading="item.Loading">Restart</Button>
|
<Button @click=confirmUpdate(item) type="primary" :loading="item.Loading">Restart</Button>
|
||||||
|
|||||||
@ -270,6 +270,11 @@ async function updateReview() {
|
|||||||
<span>CLIENT VERSION</span>
|
<span>CLIENT VERSION</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||||
|
<h1 class="text-md font-semibold md:text-ml text-center">
|
||||||
|
<span>LATENCY</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||||
<h1 class="text-md font-semibold md:text-ml text-center">
|
<h1 class="text-md font-semibold md:text-ml text-center">
|
||||||
<span>RESTART</span>
|
<span>RESTART</span>
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { $t } from '#/locales'
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { AccessControl } from '@vben/access';
|
import { AccessControl } from '@vben/access';
|
||||||
import { useAccess } from '@vben/access';
|
import { useAccess } from '@vben/access';
|
||||||
|
import GlossaryData from '#/store/glossary.json';
|
||||||
const { hasAccessByRoles } = useAccess();
|
const { hasAccessByRoles } = useAccess();
|
||||||
const [AddLanguageModal, AddLanguageModalApi] = useVbenModal({
|
const [AddLanguageModal, AddLanguageModalApi] = useVbenModal({
|
||||||
connectedComponent: addLanguage,
|
connectedComponent: addLanguage,
|
||||||
@ -108,7 +109,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
border: true,
|
border: true,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: 'Id', field: 'Id', width: 100 },
|
{ title: 'Id', field: 'Id', width: 100 },
|
||||||
{ editRender: { name: 'input' }, field: 'key', title: 'key', filters: [{ data: "" }], filterRender: { name: "input" }, visible: keyVisible },
|
{ editRender: { name: 'input' }, field: 'key', title: 'key', filters: [{ data: "" }], filterRender: { name: "input" }, visible: keyVisible, sortBy: 'key' },
|
||||||
{
|
{
|
||||||
field: 'imageUrl',
|
field: 'imageUrl',
|
||||||
slots: { default: 'image-url' },
|
slots: { default: 'image-url' },
|
||||||
@ -122,7 +123,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
title: 'zh_CN', filters: [{ data: "" }], filterRender: { name: "input" }, visible: chineseVisible
|
title: 'zh_CN', filters: [{ data: "" }], filterRender: { name: "input" }, visible: chineseVisible
|
||||||
},
|
},
|
||||||
{ editRender: { name: 'input' }, field: 'pt_BR', title: 'pt_BR', filters: [{ data: "" }], filterRender: { name: "input" }, visible: pt_BRVisible },
|
{ editRender: { name: 'input' }, field: 'pt_BR', title: 'pt_BR', filters: [{ data: "" }], filterRender: { name: "input" }, visible: pt_BRVisible },
|
||||||
{ editRender: { name: 'input' }, field: 'es_LATAM', title: 'es_LATAM', filters: [{ data: "" }], filterRender: { name: "input" }, visible: es_LATAMVisible, slots: { default: 'es_LATAM' } },
|
{ editRender: { name: 'input' }, field: 'es_LATAM', title: 'es_LATAM', filters: [{ data: "" }], filterRender: { name: "input" }, visible: es_LATAMVisible },
|
||||||
|
|
||||||
{ slots: { default: 'action' }, title: $t('page.common.action'), width: 150 },
|
{ slots: { default: 'action' }, title: $t('page.common.action'), width: 150 },
|
||||||
],
|
],
|
||||||
@ -257,7 +258,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
let length = response.data ? response.data.length : 0;
|
let length = response.data ? response.data.length : 0;
|
||||||
GridApi.setGridOptions({
|
GridApi.setGridOptions({
|
||||||
columns: [
|
columns: [
|
||||||
{ editRender: { name: 'input' }, field: 'key', title: 'key', filters: [{ data: "" }], filterRender: { name: "input" }, visible: keyVisible },
|
{ editRender: { name: 'input' }, field: 'key', title: 'key', filters: [{ data: "" }], filterRender: { name: "input" }, visible: keyVisible, sortBy: 'key', sortable: true, },
|
||||||
{
|
{
|
||||||
field: 'imageUrl',
|
field: 'imageUrl',
|
||||||
slots: { default: 'image-url' },
|
slots: { default: 'image-url' },
|
||||||
@ -272,7 +273,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
},
|
},
|
||||||
{ editRender: { name: 'input' }, field: 'pt_BR', title: 'pt_BR', filters: [{ data: "" }], filterRender: { name: "input" }, visible: pt_BRVisible },
|
{ editRender: { name: 'input' }, field: 'pt_BR', title: 'pt_BR', filters: [{ data: "" }], filterRender: { name: "input" }, visible: pt_BRVisible },
|
||||||
{ editRender: { name: 'input' }, field: 'es_LATAM', title: 'es_LATAM', filters: [{ data: "" }], filterRender: { name: "input" }, visible: es_LATAMVisible },
|
{ editRender: { name: 'input' }, field: 'es_LATAM', title: 'es_LATAM', filters: [{ data: "" }], filterRender: { name: "input" }, visible: es_LATAMVisible },
|
||||||
|
{ slots: { default: 'glossary' }, title: 'Glossary', width: 150 },
|
||||||
{ slots: { default: 'action' }, title: $t('page.common.action'), width: 150, visible: actionVisible },
|
{ slots: { default: 'action' }, title: $t('page.common.action'), width: 150, visible: actionVisible },
|
||||||
],
|
],
|
||||||
pagerConfig: {
|
pagerConfig: {
|
||||||
@ -406,6 +407,45 @@ function deleteRow(row: languageType) {
|
|||||||
GridApi.reload();
|
GridApi.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getGlossary(row: languageType) {
|
||||||
|
const glossaryItems: string[] = [];
|
||||||
|
let head = 'en';
|
||||||
|
if (chineseVisible) {
|
||||||
|
head += ' | zh';
|
||||||
|
}
|
||||||
|
if (pt_BRVisible) {
|
||||||
|
head += ' | pt';
|
||||||
|
}
|
||||||
|
if (es_LATAMVisible) {
|
||||||
|
head += ' | es';
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(GlossaryData).forEach(([key, value]: [string, any]) => {
|
||||||
|
const inGameGlossary = value.term || '';
|
||||||
|
if (row.en_US && new RegExp(`\\b${inGameGlossary.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i').test(row.en_US)) {
|
||||||
|
let content = `${inGameGlossary}`;
|
||||||
|
if (chineseVisible) {
|
||||||
|
const zhCN = value.zh_CN || '';
|
||||||
|
content += ` | ${zhCN}`;
|
||||||
|
}
|
||||||
|
if (pt_BRVisible) {
|
||||||
|
const ptBR = value.pt_BR || '';
|
||||||
|
content += ` | ${ptBR}`;
|
||||||
|
}
|
||||||
|
if (es_LATAMVisible) {
|
||||||
|
const esLATAM = value.es_LATAM || '';
|
||||||
|
content += ` | ${esLATAM}`;
|
||||||
|
}
|
||||||
|
glossaryItems.push(content);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (glossaryItems.length > 0) {
|
||||||
|
glossaryItems.unshift(head);
|
||||||
|
return glossaryItems.join('\n');
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="css">
|
||||||
@ -434,6 +474,9 @@ function deleteRow(row: languageType) {
|
|||||||
<!-- <Image src="./public/merge/Launcher_A_LV1.png" height="50" width="50" /> -->
|
<!-- <Image src="./public/merge/Launcher_A_LV1.png" height="50" width="50" /> -->
|
||||||
<Image v-if="row.url" :src="row.url" height="40" width="40" />
|
<Image v-if="row.url" :src="row.url" height="40" width="40" />
|
||||||
</template>
|
</template>
|
||||||
|
<template #glossary="{ row }">
|
||||||
|
<span style="font-size: 11px;">{{ getGlossary(row) }} </span>
|
||||||
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<AccessControl :codes="['super', 'admin']" type="role">
|
<AccessControl :codes="['super', 'admin']" type="role">
|
||||||
<Button type="primary" @click="deleteRow(row)">删除</Button>
|
<Button type="primary" @click="deleteRow(row)">删除</Button>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { copyUser } from '#/api/core/operation';
|
import { copyUser } from '#/api/core/operation';
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
import { VbenPopover, VbenIcon } from '../../../../../../packages/@core/ui-kit/shadcn-ui';
|
import { VbenPopover, VbenIcon } from '../../../../../../packages/@core/ui-kit/shadcn-ui';
|
||||||
import type { copyUserParam } from '#/model/type';
|
import type { copyUserParam } from '#/model/type';
|
||||||
const [Form] = useVbenForm({
|
const [Form] = useVbenForm({
|
||||||
@ -9,7 +10,7 @@ const [Form] = useVbenForm({
|
|||||||
commonConfig: {
|
commonConfig: {
|
||||||
// 所有表单项
|
// 所有表单项
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-full h-full',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 使用 tailwindcss grid布局
|
// 使用 tailwindcss grid布局
|
||||||
@ -23,7 +24,7 @@ const [Form] = useVbenForm({
|
|||||||
fieldName: 'src_app',
|
fieldName: 'src_app',
|
||||||
label: '源应用ID',
|
label: '源应用ID',
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
defaultValue: 1,
|
defaultValue: 0,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
@ -93,6 +94,7 @@ async function onSubmit(values: Record<string, any>) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<Page auto-content-height class="h-[1200px]">
|
||||||
<VbenPopover class="ml-5" :content-props="{ side: 'top' }">
|
<VbenPopover class="ml-5" :content-props="{ side: 'top' }">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<VbenIcon icon="solar:question-circle-bold" class="ml-5" />
|
<VbenIcon icon="solar:question-circle-bold" class="ml-5" />
|
||||||
@ -107,8 +109,7 @@ async function onSubmit(values: Record<string, any>) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</VbenPopover>
|
</VbenPopover>
|
||||||
<Form class="mt-20" >
|
<Form />
|
||||||
|
|
||||||
</Form>
|
|
||||||
|
|
||||||
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useVbenForm, useVbenModal } from '@vben/common-ui';
|
import { useVbenForm, useVbenModal } from '@vben/common-ui';
|
||||||
|
import {Image} from "ant-design-vue";
|
||||||
|
import Icon from '../../../../../../packages/@core/ui-kit/shadcn-ui/src/components/icon/icon.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'DetailMailModal',
|
name: 'DetailMailModal',
|
||||||
@ -64,7 +66,7 @@ const [Form, FormApi] = useVbenForm({
|
|||||||
{
|
{
|
||||||
component: 'Textarea',
|
component: 'Textarea',
|
||||||
fieldName: 'items',
|
fieldName: 'items',
|
||||||
label: '邮件道具',
|
label: '邮件道具11',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '{}',
|
placeholder: '{}',
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
@ -230,6 +232,13 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Modal :width="800" title="邮件详情">
|
<Modal :width="800" title="邮件详情">
|
||||||
<Form />
|
<Form>
|
||||||
|
<template #items>
|
||||||
|
<div class="border-2 border-solid border-x-sky-50 rounded-xl p-1">
|
||||||
|
<Image src="../../../../public/item/mini-gamesWK_icon_yanzhao.png" width="30px" />x20
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -82,12 +82,33 @@ const [Form, FormApi] = useVbenForm({
|
|||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'TitleESLatam',
|
||||||
|
label: '西班牙(拉美)邮件标题',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'SubtitleESLatam',
|
||||||
|
label: '西班牙(拉美)邮件副标题',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
fieldName: 'ContentESLatam',
|
||||||
|
label: '西班牙(拉美)邮件内容',
|
||||||
|
componentProps: {
|
||||||
|
type: 'textarea',
|
||||||
|
rows: 8,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: 'Textarea',
|
component: 'Textarea',
|
||||||
fieldName: 'Items',
|
fieldName: 'Items',
|
||||||
label: '邮件道具',
|
label: '邮件道具',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '[{Id:1,Num:1},{Id:2,Num:2}]',
|
placeholder: '[{"Id":1,"Num":1},{"Id":2,"Num":2}]',
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
rows: 3,
|
rows: 3,
|
||||||
},
|
},
|
||||||
@ -206,6 +227,9 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
title_ptbr: values.TitlePTBR,
|
title_ptbr: values.TitlePTBR,
|
||||||
subTitle_ptbr: values.SubtitlePTBR,
|
subTitle_ptbr: values.SubtitlePTBR,
|
||||||
content_ptbr: values.ContentPTBR,
|
content_ptbr: values.ContentPTBR,
|
||||||
|
title_es_latam: values.TitleESLatam,
|
||||||
|
subTitle_es_latam: values.SubtitleESLatam,
|
||||||
|
content_es_latam: values.ContentESLatam,
|
||||||
items: Items,
|
items: Items,
|
||||||
to_uids: ToUids,
|
to_uids: ToUids,
|
||||||
start_time: start_time,
|
start_time: start_time,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { Button, Card, Space } from 'ant-design-vue';
|
import { Button, Card, Space, Image, Tag } from 'ant-design-vue';
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
import type { VbenFormProps } from '#/adapter/form';
|
||||||
@ -12,6 +12,7 @@ import { useVbenModal } from '@vben/common-ui';
|
|||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import AddMailModal from './mail-info.vue';
|
import AddMailModal from './mail-info.vue';
|
||||||
import DetailMailModal from './mail-detail.vue';
|
import DetailMailModal from './mail-detail.vue';
|
||||||
|
import { getItemUrl } from '#/store/util';
|
||||||
const appList = ref<AppData[]>([]);
|
const appList = ref<AppData[]>([]);
|
||||||
const ServerList = ref<ServerData[]>([]);
|
const ServerList = ref<ServerData[]>([]);
|
||||||
|
|
||||||
@ -81,7 +82,13 @@ const gridOptions: VxeGridProps<MailData> = {
|
|||||||
// { field: 'subtitleEN', title: '英文邮件副标题' },
|
// { field: 'subtitleEN', title: '英文邮件副标题' },
|
||||||
{ field: 'content', title: '邮件内容' },
|
{ field: 'content', title: '邮件内容' },
|
||||||
// { field: 'content_en', title: '英文邮件内容' },
|
// { field: 'content_en', title: '英文邮件内容' },
|
||||||
{ field: 'items', title: '道具' },
|
{ field: 'items', title: '道具', slots: { default: 'items' } },
|
||||||
|
{
|
||||||
|
field: 'start_time',
|
||||||
|
title: '开始时间',
|
||||||
|
formatter: ({ cellValue }) =>
|
||||||
|
cellValue ? new Date(cellValue * 1000).toLocaleString() : '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'mail_type',
|
field: 'mail_type',
|
||||||
title: '邮件类型',
|
title: '邮件类型',
|
||||||
@ -203,6 +210,20 @@ async function deleteRow(row: MailData) {
|
|||||||
GridApi.setLoading(false);
|
GridApi.setLoading(false);
|
||||||
GridApi.query();
|
GridApi.query();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromatItems(items: string) {
|
||||||
|
try {
|
||||||
|
const itemList = JSON.parse(items);
|
||||||
|
const r = itemList.map((item: { Id: number; Num: number }) => ({
|
||||||
|
...item,
|
||||||
|
url: getItemUrl(item.Id),
|
||||||
|
}));
|
||||||
|
return r;
|
||||||
|
} catch (e) {
|
||||||
|
//console.error('Failed to parse items:', e);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -215,6 +236,21 @@ async function deleteRow(row: MailData) {
|
|||||||
</Space>
|
</Space>
|
||||||
</Card>
|
</Card>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
<template #items="{ row }">
|
||||||
|
<div class="flex flex-wrap items-center justify-center">
|
||||||
|
<div v-for="item in fromatItems(row.items)" :key="item.Id" class="flex items-center gap-1">
|
||||||
|
<template v-if="item.url">
|
||||||
|
<Image :src="item.url" width="30px" />
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<Tag class="w-[45px] h-[30px] flex items-center justify-center text-xs">
|
||||||
|
{{item.Id}}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
|
<span>x{{ item.Num }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<Button type="link" @click="deleteRow(row)" style="color: #cc0000">删除</Button>
|
<Button type="link" @click="deleteRow(row)" style="color: #cc0000">删除</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -156,7 +156,7 @@ const gridOptions: VxeGridProps<RowType> = {
|
|||||||
],
|
],
|
||||||
stripe: true,
|
stripe: true,
|
||||||
round: true,
|
round: true,
|
||||||
height: 'auto',
|
height: '800px',
|
||||||
exportConfig: {
|
exportConfig: {
|
||||||
filename: '用户资产日志',
|
filename: '用户资产日志',
|
||||||
type: 'csv',
|
type: 'csv',
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import type { dataType } from '#/component/index';
|
|||||||
// 引入 cal-heatmap 样式
|
// 引入 cal-heatmap 样式
|
||||||
import 'cal-heatmap/cal-heatmap.css';
|
import 'cal-heatmap/cal-heatmap.css';
|
||||||
import type { WorkbenchProjectItem, WorkbenchTrendItem } from '@vben/common-ui';
|
import type { WorkbenchProjectItem, WorkbenchTrendItem } from '@vben/common-ui';
|
||||||
import { orderComponent, chessComponent } from '#/component/index';
|
import { orderComponent, chessComponent, friendComponent } from '#/component/index';
|
||||||
import type { Order, Merge, Chess } from '#/model/type';
|
import type { Order, Merge, Chess, friendRecord } from '#/model/type';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { WorkbenchDetail } from '@vben/common-ui';
|
import { WorkbenchDetail } from '@vben/common-ui';
|
||||||
import UserHeader from './user-header.vue';
|
import UserHeader from './user-header.vue';
|
||||||
@ -231,6 +231,8 @@ const info = ref<{
|
|||||||
Order: Order[];
|
Order: Order[];
|
||||||
Heatmap: dataType[];
|
Heatmap: dataType[];
|
||||||
Chess: Chess[];
|
Chess: Chess[];
|
||||||
|
Friend: friendRecord[];
|
||||||
|
MaxCharge?: number;
|
||||||
}>({
|
}>({
|
||||||
Level: 0,
|
Level: 0,
|
||||||
Star: 0,
|
Star: 0,
|
||||||
@ -248,6 +250,8 @@ const info = ref<{
|
|||||||
Order: [],
|
Order: [],
|
||||||
Heatmap: [],
|
Heatmap: [],
|
||||||
Chess: [],
|
Chess: [],
|
||||||
|
Friend: [],
|
||||||
|
MaxCharge: 0,
|
||||||
});
|
});
|
||||||
let trendItems: WorkbenchTrendItem[] = [
|
let trendItems: WorkbenchTrendItem[] = [
|
||||||
|
|
||||||
@ -290,6 +294,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
info.value.Name = r.Name;
|
info.value.Name = r.Name;
|
||||||
info.value.Charge = r.Charge;
|
info.value.Charge = r.Charge;
|
||||||
info.value.AreaId = r.AreaId;
|
info.value.AreaId = r.AreaId;
|
||||||
|
info.value.MaxCharge = r.MaxCharge;
|
||||||
|
info.value.Friend = r.FriendList || [];
|
||||||
// 计算封号剩余天数(如果Ban为时间戳且大于当前时间,则计算剩余天数,否则为0或-1)
|
// 计算封号剩余天数(如果Ban为时间戳且大于当前时间,则计算剩余天数,否则为0或-1)
|
||||||
if (r.Ban && r.Ban > 0) {
|
if (r.Ban && r.Ban > 0) {
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
@ -499,6 +505,7 @@ watch(
|
|||||||
<WorkbenchDetail :items="projectItems" class="mt-5 lg:mt-0" title="玩家详情">
|
<WorkbenchDetail :items="projectItems" class="mt-5 lg:mt-0" title="玩家详情">
|
||||||
<template #areaid> {{ info.AreaId }}</template>
|
<template #areaid> {{ info.AreaId }}</template>
|
||||||
<template #charge> <b>$</b>{{ chargeDisplay }}</template>
|
<template #charge> <b>$</b>{{ chargeDisplay }}</template>
|
||||||
|
<template #maxCharge> <b>$</b>{{ info.MaxCharge }}</template>
|
||||||
<template #RegisterTime> {{ info.RegisterTime }}</template>
|
<template #RegisterTime> {{ info.RegisterTime }}</template>
|
||||||
<template #logintime> {{ info.LoginTime }}</template>
|
<template #logintime> {{ info.LoginTime }}</template>
|
||||||
<template #Cumulative>{{ info.Cumulative }}</template>
|
<template #Cumulative>{{ info.Cumulative }}</template>
|
||||||
@ -507,6 +514,7 @@ watch(
|
|||||||
<template #TodayCumulative>{{ info.TodayCumulative }}</template>
|
<template #TodayCumulative>{{ info.TodayCumulative }}</template>
|
||||||
</WorkbenchDetail>
|
</WorkbenchDetail>
|
||||||
<chessComponent :items="info.Chess" title="棋盘" class="mt-6" />
|
<chessComponent :items="info.Chess" title="棋盘" class="mt-6" />
|
||||||
|
<friendComponent :Items="info.Friend" title="好友" class="mt-6" />
|
||||||
<!-- <WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" /> -->
|
<!-- <WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" /> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -146,13 +146,13 @@ const gridOptions: VxeGridProps<RowType> = {
|
|||||||
columns: [
|
columns: [
|
||||||
{ field: 'Uid', title: 'id' , sortable: true, sortBy: 'Uid'},
|
{ field: 'Uid', title: 'id' , sortable: true, sortBy: 'Uid'},
|
||||||
{ field: 'UserName', title: '登录名' },
|
{ field: 'UserName', title: '登录名' },
|
||||||
{ field: 'Level', title: '等级', formatter: ({ cellValue }) => `${cellValue} 级`, sortable: true, sortBy: 'Level' },
|
{ field: 'Level', title: '等级', formatter: ({ cellValue }: { cellValue: string | number }) => `${cellValue} 级`, sortable: true, sortBy: 'Level' },
|
||||||
{ field: 'Node', title: '节点', },
|
{ field: 'Node', title: '节点', },
|
||||||
{ field: 'Nickname', title: '昵称', },
|
{ field: 'Nickname', title: '昵称', },
|
||||||
{ field: 'Diamond', title: '钻石', formatter: ({ cellValue }) => `${cellValue} 💎`, sortable: true, sortBy: 'Diamond' },
|
{ field: 'Diamond', title: '钻石', formatter: ({ cellValue }: { cellValue: string | number }) => `${cellValue} 💎`, sortable: true, sortBy: 'Diamond' },
|
||||||
{ field: 'Star', title: '星星', formatter: ({ cellValue }) => `${cellValue} ⭐`, sortable: true, sortBy: 'Star' },
|
{ field: 'Star', title: '星星', formatter: ({ cellValue }: { cellValue: string | number }) => `${cellValue} ⭐`, sortable: true, sortBy: 'Star' },
|
||||||
{ field: 'Energy', title: '能量', formatter: ({ cellValue }) => `${cellValue} ⚡`, sortable: true, sortBy: 'Energy' },
|
{ field: 'Energy', title: '能量', formatter: ({ cellValue }: { cellValue: string | number }) => `${cellValue} ⚡`, sortable: true, sortBy: 'Energy' },
|
||||||
{ field: 'LoginTime', sortable: true, title: '登录时间', formatter: ({ cellValue }) => dayjs(cellValue * 1000).format('YYYY-MM-DD HH:mm:ss'),sortBy: 'LoginTime' },
|
{ field: 'LoginTime', sortable: true, title: '登录时间', formatter: ({ cellValue }: { cellValue: number }) => dayjs(cellValue * 1000).format('YYYY-MM-DD HH:mm:ss'),sortBy: 'LoginTime' },
|
||||||
{ field: 'Online', title: '在线状态', slots: { default: 'online' } , sortable: true, sortBy: 'Online' },
|
{ field: 'Online', title: '在线状态', slots: { default: 'online' } , sortable: true, sortBy: 'Online' },
|
||||||
],
|
],
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
@ -172,7 +172,10 @@ const gridOptions: VxeGridProps<RowType> = {
|
|||||||
result: "data"
|
result: "data"
|
||||||
},
|
},
|
||||||
ajax: {
|
ajax: {
|
||||||
query: async ({ page }, formValues) => {
|
query: async (
|
||||||
|
{ page }: { page: { pageSize: number; currentPage: number } },
|
||||||
|
formValues: Record<string, any>,
|
||||||
|
) => {
|
||||||
let Id = parseInt(formValues.AppId, 10);
|
let Id = parseInt(formValues.AppId, 10);
|
||||||
let ServerId = 1;
|
let ServerId = 1;
|
||||||
let Uid = parseInt(formValues.Uid, 10);
|
let Uid = parseInt(formValues.Uid, 10);
|
||||||
|
|||||||
11
config
Normal file
11
config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Energy": {
|
||||||
|
"Value": 100
|
||||||
|
},
|
||||||
|
"Star": {
|
||||||
|
"Value": 0
|
||||||
|
},
|
||||||
|
"Diamond": {
|
||||||
|
"Value": 50
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,16 +24,12 @@ defineEmits(['click']);
|
|||||||
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="flex flex-wrap p-0">
|
<CardContent class="flex flex-wrap p-0">
|
||||||
<div
|
<div class="border-border w-full border-b border-r border-t p-5 transition-all hover:shadow-xl">
|
||||||
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="flex w-full">
|
||||||
<div class="text-foreground/80 leading-2 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">总充值金额:</span>
|
<span class="font-bold">总充值金额:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.charge">
|
<span v-if="$slots.charge">
|
||||||
<slot name="charge"></slot>
|
<slot name="charge"></slot>
|
||||||
@ -41,14 +37,24 @@ defineEmits(['click']);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
|
<div class="Value">
|
||||||
|
<span v-if="$slots.maxCharge">
|
||||||
|
<slot name="maxCharge"></slot>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">场景:</span>
|
<span class="font-bold">场景:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.AreaId">
|
<span v-if="$slots.AreaId">
|
||||||
<slot name="AreaId"></slot>
|
<slot name="AreaId"></slot>
|
||||||
@ -61,9 +67,7 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">注册时间:</span>
|
<span class="font-bold">注册时间:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.RegisterTime">
|
<span v-if="$slots.RegisterTime">
|
||||||
<slot name="RegisterTime"></slot>
|
<slot name="RegisterTime"></slot>
|
||||||
@ -76,9 +80,7 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">最后登录:</span>
|
<span class="font-bold">最后登录:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.logintime">
|
<span v-if="$slots.logintime">
|
||||||
<slot name="logintime"></slot>
|
<slot name="logintime"></slot>
|
||||||
@ -91,9 +93,7 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">累计在线:</span>
|
<span class="font-bold">累计在线:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.Cumulative">
|
<span v-if="$slots.Cumulative">
|
||||||
<slot name="Cumulative"></slot>
|
<slot name="Cumulative"></slot>
|
||||||
@ -106,9 +106,7 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">今日累计在线:</span>
|
<span class="font-bold">今日累计在线:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.TodayCumulative">
|
<span v-if="$slots.TodayCumulative">
|
||||||
<slot name="TodayCumulative"></slot>
|
<slot name="TodayCumulative"></slot>
|
||||||
@ -121,9 +119,7 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
<div class="text-foreground/80 leading-2 mt-3 flex h-4 p-1 md:w-1/2">
|
||||||
<span class="font-bold">邀请码:</span>
|
<span class="font-bold">邀请码:</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="text-foreground/80 leading-2 text-shadow mt-3 flex h-4 justify-start p-1 md:w-1/2">
|
||||||
class="text-foreground/80 leading-2 text-shadow mt-3 flex h-4 justify-start p-1 md:w-1/2"
|
|
||||||
>
|
|
||||||
<div class="Value">
|
<div class="Value">
|
||||||
<span v-if="$slots.Code">
|
<span v-if="$slots.Code">
|
||||||
<slot name="Code"></slot>
|
<slot name="Code"></slot>
|
||||||
|
|||||||
@ -31,7 +31,7 @@ withDefaults(defineProps<Props>(), {
|
|||||||
<CardContent class="flex flex-wrap p-5 pt-0">
|
<CardContent class="flex flex-wrap p-5 pt-0">
|
||||||
<ul class="divide-border w-full divide-y" role="list">
|
<ul class="divide-border w-full divide-y" role="list">
|
||||||
<li
|
<li
|
||||||
v-for="item in items"
|
v-for="item in items.slice(0, 10)"
|
||||||
:key="item.title"
|
:key="item.title"
|
||||||
class="flex justify-between gap-x-6 py-5"
|
class="flex justify-between gap-x-6 py-5"
|
||||||
>
|
>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user