增加自动化脚本
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
1dc256452e
commit
abab4f3637
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ vite.config.ts.*
|
|||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
.history
|
.history
|
||||||
|
node-compile-cache/*
|
||||||
|
|||||||
@ -23,7 +23,12 @@ export interface UserLogOrder {
|
|||||||
Time: number;
|
Time: number;
|
||||||
Type: number;
|
Type: number;
|
||||||
Diff: number;
|
Diff: number;
|
||||||
ChessId: string;
|
ChessId: ChessType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChessType {
|
||||||
|
Id: string;
|
||||||
|
Icon: string;
|
||||||
}
|
}
|
||||||
export interface heatType {
|
export interface heatType {
|
||||||
date: string;
|
date: string;
|
||||||
|
|||||||
8
apps/web-antd/src/api/core/scripts.ts
Normal file
8
apps/web-antd/src/api/core/scripts.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export interface scripts_params{
|
||||||
|
step :number;
|
||||||
|
}
|
||||||
|
export async function copywritingscript(params :scripts_params) {
|
||||||
|
return requestClient.post('/scripts/copywriting', params, {timeout: 180000});
|
||||||
|
}
|
||||||
@ -18,8 +18,8 @@ export interface ServerData {
|
|||||||
AppId : number;
|
AppId : number;
|
||||||
ServerId: number;
|
ServerId: number;
|
||||||
ServerName: string;
|
ServerName: string;
|
||||||
Status: number;
|
Status?: number;
|
||||||
OpenServerTime: number;
|
OpenServerTime?: number;
|
||||||
StartTime?: number;
|
StartTime?: number;
|
||||||
PlayerNum?: number;
|
PlayerNum?: number;
|
||||||
Loading?:boolean;
|
Loading?:boolean;
|
||||||
@ -30,6 +30,14 @@ export interface ServerData {
|
|||||||
Tags?: string[];
|
Tags?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface editServerParam {
|
||||||
|
AppId : number;
|
||||||
|
ServerId: number;
|
||||||
|
ServerName: string;
|
||||||
|
Tags?: string;
|
||||||
|
ClientVersion?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NodeData{
|
export interface NodeData{
|
||||||
NodeId?: number;
|
NodeId?: number;
|
||||||
NodeName: string;
|
NodeName: string;
|
||||||
@ -85,3 +93,7 @@ export async function addServer(AppId:number, ServerId:number, ServerName: strin
|
|||||||
return requestClient.post(`/server/addServer`, {AppId:AppId, ServerId: ServerId, ServerName: ServerName, Status: Status, OpenServerTime: OpenServerTime});
|
return requestClient.post(`/server/addServer`, {AppId:AppId, ServerId: ServerId, ServerName: ServerName, Status: Status, OpenServerTime: OpenServerTime});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function editServer(editParam: editServerParam){
|
||||||
|
return requestClient.post(`/server/editServer`, editParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -118,8 +118,8 @@ defineEmits(['click']);
|
|||||||
<div class="text-foreground/80 mt-4 h-12 ">
|
<div class="text-foreground/80 mt-4 h-12 ">
|
||||||
<div v-if="item.merge && item.merge.length > 0" class="flex flex-wrap gap-1">
|
<div v-if="item.merge && item.merge.length > 0" class="flex flex-wrap gap-1">
|
||||||
<img v-for="mergeItem in item.merge" :key="mergeItem.Icon"
|
<img v-for="mergeItem in item.merge" :key="mergeItem.Icon"
|
||||||
:src="`../../../merge/${mergeItem.Icon}.png`" class="inline-block h-6 w-6 rounded"
|
:src="`${mergeItem.Icon}`" class="inline-block h-6 w-6 rounded"
|
||||||
:alt="mergeItem.Title" :title="mergeItem.Title" />
|
:alt="mergeItem.Icon" :title="mergeItem.Id" />
|
||||||
</div>
|
</div>
|
||||||
<span v-else>{{ item.content }}</span>
|
<span v-else>{{ item.content }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
"log": "操作日志"
|
"log": "操作日志"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "服务器管理",
|
"title": "运维管理",
|
||||||
"analytics": "分析台",
|
"analytics": "分析台",
|
||||||
"server-list": "区服列表",
|
"server-list": "区服列表",
|
||||||
"node-list": "节点列表",
|
"node-list": "节点列表",
|
||||||
@ -52,12 +52,18 @@
|
|||||||
},
|
},
|
||||||
"operation": {
|
"operation": {
|
||||||
"title": "运营管理",
|
"title": "运营管理",
|
||||||
"level": "等级分布",
|
"scripts": "自动化脚本",
|
||||||
"mail": "邮件管理",
|
"mail": "邮件管理",
|
||||||
"order": "订单管理",
|
"order": "订单管理",
|
||||||
"language": "翻译管理",
|
"language": "翻译管理",
|
||||||
"copyUser": "用户数据复制"
|
"copyUser": "用户数据复制"
|
||||||
},
|
},
|
||||||
|
"server":{
|
||||||
|
"merge_pet_test":"测试服",
|
||||||
|
"merge_pet_sdk":"QA服",
|
||||||
|
"merge_pet_online":"正式服",
|
||||||
|
"merge_pet_audit":"审核服"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"event": {
|
"event": {
|
||||||
"order_finish": "完成订单",
|
"order_finish": "完成订单",
|
||||||
|
|||||||
@ -21,12 +21,15 @@ export interface Merge {
|
|||||||
export interface MergeRecord{
|
export interface MergeRecord{
|
||||||
[key: string]: Merge;
|
[key: string]: Merge;
|
||||||
}
|
}
|
||||||
|
export interface ChessType {
|
||||||
|
Id: string;
|
||||||
|
Icon: string;
|
||||||
|
}
|
||||||
export interface Order {
|
export interface Order {
|
||||||
id: number;
|
id: number;
|
||||||
color?: string;
|
color?: string;
|
||||||
icon?:string;
|
icon?:string;
|
||||||
merge?: Merge[];
|
merge?: ChessType[];
|
||||||
type?: number;
|
type?: number;
|
||||||
typeName?: string;
|
typeName?: string;
|
||||||
diff: number;
|
diff: number;
|
||||||
@ -72,3 +75,11 @@ export interface copyUserParam{
|
|||||||
dst_app: number;
|
dst_app: number;
|
||||||
dst_uid: number;
|
dst_uid: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface scriptsRecord{
|
||||||
|
step: number;
|
||||||
|
label: string;
|
||||||
|
tips :string[];
|
||||||
|
code: number;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
name: 'Language',
|
name: 'Language',
|
||||||
path: '/language',
|
path: '/language',
|
||||||
component: () => import('#/views/language/language/index.vue'),
|
component: () => import('#/views/language/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
affixTab: true,
|
affixTab: true,
|
||||||
icon: 'lets-icons:order',
|
icon: 'lets-icons:order',
|
||||||
|
|||||||
@ -16,13 +16,13 @@ const routes: RouteRecordRaw[] = [
|
|||||||
path: '/operation',
|
path: '/operation',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Level',
|
name: 'Scripts',
|
||||||
path: '/level',
|
path: '/scripts',
|
||||||
component: () => import('#/views/operation/level/index.vue'),
|
component: () => import('#/views/operation/scripts/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
affixTab: true,
|
affixTab: true,
|
||||||
icon: 'lucide:chart-no-axes-column-increasing',
|
icon: 'lucide:chart-no-axes-column-increasing',
|
||||||
title: $t('page.operation.level'),
|
title: $t('page.operation.scripts'),
|
||||||
authority: ['super', 'admin'],
|
authority: ['super', 'admin'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -157,12 +157,7 @@ function confirmUpdate(Server: ServerData) {
|
|||||||
</div>
|
</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>32ms</span>
|
<span>{{ item.ClientVersion }}</span>
|
||||||
</h1>
|
|
||||||
</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>1.0.0</span>
|
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</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">
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
import { addServer } from '#/api/core/server';
|
import { editServer } from '#/api/core/server';
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
@ -79,18 +79,6 @@ const [Form, FormApi] = useVbenForm({
|
|||||||
label: 'version',
|
label: 'version',
|
||||||
formItemClass: 'col-span-2',
|
formItemClass: 'col-span-2',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
component: 'NumberPicker',
|
|
||||||
defaultValue: '',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: 'node1',
|
|
||||||
},
|
|
||||||
rules: "required",
|
|
||||||
fieldName: 'max_online',
|
|
||||||
label: 'max_online',
|
|
||||||
formItemClass: 'col-span-2',
|
|
||||||
},
|
|
||||||
|
|
||||||
],
|
],
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||||
@ -163,12 +151,16 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const values = await FormApi.getValues();
|
const values = await FormApi.getValues();
|
||||||
const date = dayjs(values.datePicker).format('YYYY-MM-DD');
|
|
||||||
const time = dayjs(values.timePicker).format('HH:mm:ss');
|
|
||||||
const dateTime = dayjs(`${date} ${time}`).valueOf() / 1000;
|
|
||||||
const modalData = modalApi.getData();
|
const modalData = modalApi.getData();
|
||||||
const ServerId = parseInt(values.ServerId, 10);
|
const ServerId = parseInt(values.ServerId, 10);
|
||||||
await addServer(modalData.AppId, ServerId, values.ServerName, values.Status, dateTime);
|
const editParam = {
|
||||||
|
AppId: modalData.AppId,
|
||||||
|
ServerId: ServerId,
|
||||||
|
ServerName: values.ServerName,
|
||||||
|
Tags: values.Tags,
|
||||||
|
ClientVersion: values.version,
|
||||||
|
}
|
||||||
|
await editServer(editParam);
|
||||||
modalApi.close();
|
modalApi.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { useVbenModal } from '@vben/common-ui'
|
|||||||
import { ref,onMounted } from 'vue';
|
import { ref,onMounted } from 'vue';
|
||||||
import addServerModal from './addServer.vue';
|
import addServerModal from './addServer.vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { $t } from '#/locales'
|
||||||
const [BaseForm, BaseFormApi] = useVbenForm({
|
const [BaseForm, BaseFormApi] = useVbenForm({
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
// 所有表单项共用,可单独在表单内覆盖
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
@ -111,7 +112,7 @@ onMounted(async() => {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: appList.value.map((item) => ({
|
options: appList.value.map((item) => ({
|
||||||
label: item.AppName,
|
label: $t('page.server.' + item.AppName),
|
||||||
value: item.AppId,
|
value: item.AppId,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
@ -207,11 +208,6 @@ async function update() {
|
|||||||
<span>MEMORY</span>
|
<span>MEMORY</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>CLIENT VERSION</span>
|
<span>CLIENT VERSION</span>
|
||||||
|
|||||||
@ -100,7 +100,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Modal width="100%">
|
<Modal width="80%">
|
||||||
<Form />
|
<Form />
|
||||||
<Grid />
|
<Grid />
|
||||||
</Modal>
|
</Modal>
|
||||||
@ -103,6 +103,9 @@ const formOptions: VbenFormProps = {
|
|||||||
}
|
}
|
||||||
const gridOptions: VxeGridProps<languageType> = {
|
const gridOptions: VxeGridProps<languageType> = {
|
||||||
border: true,
|
border: true,
|
||||||
|
cellConfig:{
|
||||||
|
height:60,
|
||||||
|
},
|
||||||
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 },
|
||||||
@ -110,7 +113,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
field: 'imageUrl',
|
field: 'imageUrl',
|
||||||
slots: { default: 'image-url' },
|
slots: { default: 'image-url' },
|
||||||
title: 'Image',
|
title: 'Image',
|
||||||
width: 100,
|
width: 60,
|
||||||
},
|
},
|
||||||
{ editRender: { name: 'input' }, field: 'en_US', title: 'en_US', filters: [{ data: "" }], filterRender: { name: "input" }, visible: en_USVisible },
|
{ editRender: { name: 'input' }, field: 'en_US', title: 'en_US', filters: [{ data: "" }], filterRender: { name: "input" }, visible: en_USVisible },
|
||||||
{
|
{
|
||||||
@ -253,7 +256,7 @@ const gridOptions: VxeGridProps<languageType> = {
|
|||||||
field: 'imageUrl',
|
field: 'imageUrl',
|
||||||
slots: { default: 'image-url' },
|
slots: { default: 'image-url' },
|
||||||
title: 'Image',
|
title: 'Image',
|
||||||
width: 50,
|
width: 60,
|
||||||
},
|
},
|
||||||
{ editRender: { name: 'input' }, field: 'en_US', title: 'en_US', filters: [{ data: "" }], filterRender: { name: "input" }, visible: en_USVisible },
|
{ editRender: { name: 'input' }, field: 'en_US', title: 'en_US', filters: [{ data: "" }], filterRender: { name: "input" }, visible: en_USVisible },
|
||||||
{
|
{
|
||||||
@ -420,7 +423,7 @@ function deleteRow(row: languageType) {
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col">
|
<div class="min-h-screen flex flex-col">
|
||||||
<Page auto-content-height>
|
<Page auto-content-height>
|
||||||
<AddLanguageModal width="1200px" height="1200px"></AddLanguageModal />
|
<AddLanguageModal width="800px" height="800px"></AddLanguageModal />
|
||||||
<Grid>
|
<Grid>
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<span class="mr-4 font-bold">{{ $t('page.language.lastUpdate') }}:{{ lastUpdate }}</span>
|
<span class="mr-4 font-bold">{{ $t('page.language.lastUpdate') }}:{{ lastUpdate }}</span>
|
||||||
@ -428,11 +431,11 @@ function deleteRow(row: languageType) {
|
|||||||
{{ $t('page.common.addLine') }}
|
{{ $t('page.common.addLine') }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" @click="saveAll" class="mr-2"> {{ $t('page.common.save') }} </Button>
|
<Button type="primary" @click="saveAll" class="mr-2"> {{ $t('page.common.save') }} </Button>
|
||||||
<Button type="primary" @click="exportLang"> {{ $t('page.common.gitCommit') }} </Button>
|
<!-- <Button type="primary" @click="exportLang"> {{ $t('page.common.gitCommit') }} </Button> -->
|
||||||
</template>
|
</template>
|
||||||
<template #image-url="{ row }">
|
<template #image-url="{ row }">
|
||||||
<!-- <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="50" width="50" />
|
<Image v-if="row.url" :src="row.url" height="40" width="40" />
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<AccessControl :codes="['super', 'admin']" type="role">
|
<AccessControl :codes="['super', 'admin']" type="role">
|
||||||
@ -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 { 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({
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
// 所有表单项共用,可单独在表单内覆盖
|
||||||
@ -69,16 +70,6 @@ const [Form] = useVbenForm({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'dst_uid',
|
|
||||||
label: '目标用户ID',
|
|
||||||
defaultValue: 100100042,
|
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入目标用户ID',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
handleSubmit: onSubmit,
|
handleSubmit: onSubmit,
|
||||||
|
|
||||||
@ -102,7 +93,22 @@ async function onSubmit(values: Record<string, any>) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<VbenPopover class="ml-5" :content-props="{ side: 'top' }">
|
||||||
|
<template #trigger>
|
||||||
|
<VbenIcon icon="solar:question-circle-bold" class="ml-5" />
|
||||||
|
</template>
|
||||||
|
<div class="max-w-xs text-sm">
|
||||||
|
<h3 class="font-semibold mt-4 mb-2">账号复制说明</h3>
|
||||||
|
<ul>
|
||||||
|
<li><b>源应用ID:</b>需要复制的账号所在的APP</li>
|
||||||
|
<li><b>源用户ID:</b>需要复制的账号所生成的后端唯一ID</li>
|
||||||
|
<li><b>目标应用ID:</b>需要复制到的APP</li>
|
||||||
|
<li><b>目标应用账号:</b>源用户ID</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</VbenPopover>
|
||||||
|
<Form class="mt-20" >
|
||||||
|
|
||||||
<Form class="mt-20" />
|
</Form>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@ -1,152 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { Page } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { getStatisticsLevel } from '#/api/core/statistics';
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
|
||||||
import { getServerListApi, getAppListApi } from '#/api/core/server';
|
|
||||||
import type { AppData, ServerData } from '#/api/core/server';
|
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
const appList = ref<AppData[]>([]);
|
|
||||||
const ServerList = ref<ServerData[]>([]);
|
|
||||||
interface RowType {
|
|
||||||
Uid: number;
|
|
||||||
change_type: string;
|
|
||||||
change_num: string;
|
|
||||||
change_after: string;
|
|
||||||
item_id: string;
|
|
||||||
timestamp: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formOptions: VbenFormProps = {
|
|
||||||
// 默认展开
|
|
||||||
collapsed: false,
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
defaultValue: 1,
|
|
||||||
componentProps: {
|
|
||||||
onChange: async (value: number) => {
|
|
||||||
const serverResponse = await getServerListApi({ AppId: value, Type: 1 });
|
|
||||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
|
||||||
GridApi.formApi.updateSchema([
|
|
||||||
{
|
|
||||||
component: 'CheckboxGroup',
|
|
||||||
componentProps: {
|
|
||||||
options: ServerList.value.map((item) => ({
|
|
||||||
label: item.ServerName,
|
|
||||||
value: item.ServerId,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
fieldName: 'ServerList',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
filterOption: true,
|
|
||||||
options: [
|
|
||||||
|
|
||||||
],
|
|
||||||
placeholder: '请选择',
|
|
||||||
showSearch: true,
|
|
||||||
},
|
|
||||||
fieldName: 'AppId',
|
|
||||||
label: 'APP:',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'CheckboxGroup',
|
|
||||||
componentProps: {
|
|
||||||
name: 'cname',
|
|
||||||
options: [],
|
|
||||||
},
|
|
||||||
fieldName: 'ServerList',
|
|
||||||
label: '区服',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// 控制表单是否显示折叠按钮
|
|
||||||
showCollapseButton: true,
|
|
||||||
submitButtonOptions: {
|
|
||||||
content: '查询',
|
|
||||||
},
|
|
||||||
// 是否在字段值改变时提交表单
|
|
||||||
submitOnChange: false,
|
|
||||||
// 按下回车时是否提交表单
|
|
||||||
submitOnEnter: false,
|
|
||||||
}
|
|
||||||
const gridOptions: VxeGridProps<RowType> = {
|
|
||||||
columns: [
|
|
||||||
{ field: 'Level', title: '等级' },
|
|
||||||
{ field: 'Sum', title: '人数' },
|
|
||||||
],
|
|
||||||
height: 'auto',
|
|
||||||
pagerConfig: {},
|
|
||||||
proxyConfig: {
|
|
||||||
response: {
|
|
||||||
total: "total",
|
|
||||||
result: "data"
|
|
||||||
},
|
|
||||||
ajax: {
|
|
||||||
query: async ({ }, formValues) => {
|
|
||||||
if (formValues.ServerList.length == 0) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
let AppId = parseInt(formValues.AppId, 10);
|
|
||||||
return await getStatisticsLevel({
|
|
||||||
AppId: AppId,
|
|
||||||
ServerList: formValues.ServerList
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
rowConfig: {
|
|
||||||
isHover: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [Grid, GridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
|
||||||
onMounted(async () => {
|
|
||||||
try {
|
|
||||||
const response = await getAppListApi();
|
|
||||||
appList.value = Array.isArray(response) ? response : [];
|
|
||||||
const app = appList.value[0];
|
|
||||||
if (!app) return;
|
|
||||||
GridApi.formApi.updateSchema([
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
options: appList.value.map((item) => ({
|
|
||||||
label: item.AppName,
|
|
||||||
value: item.AppId,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
fieldName: 'AppId',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const serverResponse = await getServerListApi({ AppId: app.AppId, Type: 1 });
|
|
||||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
|
||||||
GridApi.formApi.updateSchema([
|
|
||||||
{
|
|
||||||
component: 'CheckboxGroup',
|
|
||||||
componentProps: {
|
|
||||||
options: ServerList.value.map((item) => ({
|
|
||||||
label: item.ServerName,
|
|
||||||
value: item.ServerId,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
fieldName: 'ServerList',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
} catch (e) {
|
|
||||||
appList.value = [];
|
|
||||||
//console.log(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Page auto-content-height class="h-[800px]">
|
|
||||||
<Grid />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
112
apps/web-antd/src/views/operation/scripts/drawer.vue
Normal file
112
apps/web-antd/src/views/operation/scripts/drawer.vue
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useVbenDrawer } from '@vben/common-ui';
|
||||||
|
import { VbenIcon } from '../../../../../../packages/@core/ui-kit/shadcn-ui';
|
||||||
|
import { Timeline } from 'ant-design-vue';
|
||||||
|
import { copywritingscript } from '#/api/core/scripts';
|
||||||
|
import type { scriptsRecord } from '#/model/type';
|
||||||
|
const data = ref();
|
||||||
|
const end = ref(false);
|
||||||
|
const pendinglabel = ref('脚本运行中...');
|
||||||
|
const stepList = ref<scriptsRecord[]>([]);
|
||||||
|
const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
|
onCancel() {
|
||||||
|
drawerApi.close();
|
||||||
|
},
|
||||||
|
onConfirm() {
|
||||||
|
console.log('onConfirm');
|
||||||
|
},
|
||||||
|
onOpenChange(open: boolean) {
|
||||||
|
if (open) {
|
||||||
|
data.value = drawerApi.getData<Record<string, any>>();
|
||||||
|
stepList.value = [];
|
||||||
|
end.value = false;
|
||||||
|
pendinglabel.value = '脚本运行中...';
|
||||||
|
// 使用 nextTick 确保状态重置后再执行脚本
|
||||||
|
setTimeout(() => {
|
||||||
|
switch (data.value.scriptInstanceId) {
|
||||||
|
case 1:
|
||||||
|
console.log('running script copywriting');
|
||||||
|
runningStep(copywritingscript, stepList.value.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
// switch (data.value.scriptInstanceId) {
|
||||||
|
// case 1:
|
||||||
|
// // load data or do something
|
||||||
|
// console.log('running script copywriting');
|
||||||
|
// runningStep(copywritingscript, stepList.value.length);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function runningStep(func: Function, step: number) {
|
||||||
|
func({ step: step }).then((res: scriptsRecord) => {
|
||||||
|
if (res.step != 1) {
|
||||||
|
stepList.value?.push({
|
||||||
|
step: res.step - 1,
|
||||||
|
label: pendinglabel.value,
|
||||||
|
tips: res.tips || [],
|
||||||
|
code: res.code,
|
||||||
|
});
|
||||||
|
if (res.code !== 0) {
|
||||||
|
// 出错,结束
|
||||||
|
end.value = true;
|
||||||
|
pendinglabel.value = '';
|
||||||
|
stepList.value = stepList.value.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
color: index === stepList.value.length - 1 ? 'red' : 'blue'
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.step !== -1) {
|
||||||
|
// 合并当前步骤的tips到上一个record
|
||||||
|
stepList.value = stepList.value.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
color: index === stepList.value.length ? 'gray' : 'blue'
|
||||||
|
}));
|
||||||
|
pendinglabel.value = res.label;
|
||||||
|
runningStep(func, res.step);
|
||||||
|
} else {
|
||||||
|
stepList.value = stepList.value.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
color: 'blue'
|
||||||
|
}));
|
||||||
|
end.value = true;
|
||||||
|
pendinglabel.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Drawer>
|
||||||
|
<Timeline :pending="pendinglabel">
|
||||||
|
<Timeline.Item v-for="item in stepList" :key="item.step" :pending="false" :color="item.color || 'blue'">
|
||||||
|
<template #dot>
|
||||||
|
<VbenIcon :icon="item.code == 0?'system-uicons:check-circle':'system-uicons:cross-circle'" />
|
||||||
|
</template>
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
<div>
|
||||||
|
<ul class="list-disc ml-5">
|
||||||
|
<li v-for="tip in item.tips">{{ tip }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</Timeline.Item>
|
||||||
|
<Timeline.Item v-if="end" color="blue">
|
||||||
|
<template #dot>
|
||||||
|
<VbenIcon icon="system-uicons:check-circle" />
|
||||||
|
</template>
|
||||||
|
completed
|
||||||
|
</Timeline.Item>
|
||||||
|
<template #pendingDot>
|
||||||
|
<VbenIcon icon="svg-spinners:12-dots-scale-rotate" />
|
||||||
|
</template>
|
||||||
|
</Timeline>
|
||||||
|
</Drawer>
|
||||||
|
</template>
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
|
||||||
import AnalyticsVisitsTable from './level-table.vue';
|
import AnalyticsVisitsTable from './scripts.vue';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
83
apps/web-antd/src/views/operation/scripts/scripts.vue
Normal file
83
apps/web-antd/src/views/operation/scripts/scripts.vue
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
|
import { Button, Card, Space, notification, Tag } from 'ant-design-vue';
|
||||||
|
import { useVbenDrawer, VbenButton } from '@vben/common-ui';
|
||||||
|
import ExtraDrawer from './drawer.vue';
|
||||||
|
const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
|
connectedComponent: ExtraDrawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function startScript(id:number) {
|
||||||
|
notification.success({
|
||||||
|
message: '脚本已启动',
|
||||||
|
description: '文案自动化脚本已成功启动,正在运行中。',
|
||||||
|
});
|
||||||
|
drawerApi.setState({
|
||||||
|
title: '文案自动化脚本',
|
||||||
|
});
|
||||||
|
drawerApi.setData({
|
||||||
|
scriptLaber: '文案自动化脚本',
|
||||||
|
scriptInstanceId: id,
|
||||||
|
});
|
||||||
|
drawerApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Page>
|
||||||
|
<Drawer />
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="card-box p-4 py-6 flex justify-between h-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">
|
||||||
|
<span>Script Name</span>
|
||||||
|
</h1>
|
||||||
|
</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>TAGS</span>
|
||||||
|
</h1>
|
||||||
|
</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>Last Running</span>
|
||||||
|
</h1>
|
||||||
|
</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>Start</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="card-box p-4 py-6 flex justify-between h-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">
|
||||||
|
<span>文案自动化脚本</span>
|
||||||
|
</h1>
|
||||||
|
</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">
|
||||||
|
<Tag>xlsx</Tag>
|
||||||
|
</h1>
|
||||||
|
</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>2026-01-01 12:00:00</span>
|
||||||
|
</h1>
|
||||||
|
</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">
|
||||||
|
<Button type="primary" @click="startScript(1)">Start</Button>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
@ -331,16 +331,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
}
|
}
|
||||||
for (const i in r.Order) {
|
for (const i in r.Order) {
|
||||||
var chessArr = r.Order[i]?.ChessId
|
var chessArr = r.Order[i]?.ChessId
|
||||||
? r.Order[i]?.ChessId.split(' ')
|
|
||||||
: [];
|
|
||||||
var ChessData: Merge[] = [];
|
|
||||||
for (const chessId of chessArr) {
|
|
||||||
const key = String(parseInt(chessId));
|
|
||||||
const chessInfo = (MergeData as Record<string, Merge>)[key];
|
|
||||||
if (chessInfo) {
|
|
||||||
ChessData.push(chessInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var orderTypeName = Object.entries(orderTypeData).find(
|
var orderTypeName = Object.entries(orderTypeData).find(
|
||||||
([key]) => Number(key) === r.Order[i]?.Type
|
([key]) => Number(key) === r.Order[i]?.Type
|
||||||
)?.[1];
|
)?.[1];
|
||||||
@ -349,9 +339,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
)?.[1];
|
)?.[1];
|
||||||
info.value.Order.push({
|
info.value.Order.push({
|
||||||
id: r.Order[i]?.Id || 0,
|
id: r.Order[i]?.Id || 0,
|
||||||
merge: ChessData,
|
merge: chessArr,
|
||||||
color: '#3fb27f',
|
color: '#3fb27f',
|
||||||
content: r.Order[i]?.ChessId || '',
|
|
||||||
typeName: orderTypeName || '未知类型',
|
typeName: orderTypeName || '未知类型',
|
||||||
diff: r.Order[i]?.Diff || 0,
|
diff: r.Order[i]?.Diff || 0,
|
||||||
diffName: diffName || '未知',
|
diffName: diffName || '未知',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user