版本更新
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
94ef1448d9
commit
8b00dd8622
@ -5,6 +5,10 @@ export interface AppData {
|
||||
AppId : number;
|
||||
AppName : string;
|
||||
WsHost? : string;
|
||||
NodeName?: string;
|
||||
MysqlName?: string;
|
||||
Topic?: string;
|
||||
tz?: string;
|
||||
Status?: string;
|
||||
Update?:number;
|
||||
Loading?:boolean;
|
||||
|
||||
@ -9,7 +9,10 @@
|
||||
"dashboard": {
|
||||
"title": "服务器管理",
|
||||
"analytics": "分析台",
|
||||
"server-list": "服务器列表"
|
||||
"server-list": "区服列表",
|
||||
"node-list": "节点列表",
|
||||
"mysql-list": "MySQL列表",
|
||||
"app-list": "应用列表"
|
||||
},
|
||||
"userlog":{
|
||||
"title": "玩家管理",
|
||||
|
||||
12
apps/web-antd/src/model/app.ts
Normal file
12
apps/web-antd/src/model/app.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export interface AppInfo {
|
||||
id:number;
|
||||
AppName: string;
|
||||
WsHost : string;
|
||||
WsPort : number;
|
||||
NodeId : number;
|
||||
MysqlId : number;
|
||||
Database : string;
|
||||
Topic : string;
|
||||
Path:string;
|
||||
tz : string;
|
||||
}
|
||||
12
apps/web-antd/src/model/node.ts
Normal file
12
apps/web-antd/src/model/node.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export interface NodeInfo {
|
||||
id:number;
|
||||
AppName: string;
|
||||
WsHost : string;
|
||||
WsPort : number;
|
||||
NodeId : number;
|
||||
MysqlId : number;
|
||||
Database : string;
|
||||
Topic : string;
|
||||
Path:string;
|
||||
tz : string;
|
||||
}
|
||||
@ -30,10 +30,40 @@ const routes: RouteRecordRaw[] = [
|
||||
component: () => import('#/views/dashboard/serverList/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
icon: 'lucide:gamepad',
|
||||
title: $t('page.dashboard.server-list'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'AppList',
|
||||
path: '/app-list',
|
||||
component: () => import('#/views/dashboard/appList/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
icon: 'lucide:app-window',
|
||||
title: $t('page.dashboard.app-list'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'NodeList',
|
||||
path: '/node-list',
|
||||
component: () => import('#/views/dashboard/nodeList/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
icon: 'lucide:server',
|
||||
title: $t('page.dashboard.node-list'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MysqlList',
|
||||
path: '/mysql-list',
|
||||
component: () => import('#/views/dashboard/mysqlList/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
icon: 'lucide:database',
|
||||
title: $t('page.dashboard.mysql-list'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
169
apps/web-antd/src/views/dashboard/appList/addServer.vue
Normal file
169
apps/web-antd/src/views/dashboard/appList/addServer.vue
Normal file
@ -0,0 +1,169 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { addServer } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
|
||||
const date = dayjs();
|
||||
const [Form, FormApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
|
||||
// 使用 tailwindcss grid布局
|
||||
// 提交函数
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
layout: 'horizontal',
|
||||
// 水平布局,label和input在同一行
|
||||
schema: [
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '1',
|
||||
},
|
||||
formItemClass:'col-span-2',
|
||||
fieldName: 'AppId',
|
||||
rules: "required|integer",
|
||||
label: 'AppId',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'AppName',
|
||||
label: 'App名称',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'WsHost',
|
||||
label: '域名',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'WsPort',
|
||||
label: 'ws端口',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'NodeName',
|
||||
label: '节点名称',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'MysqlName',
|
||||
label: 'Mysql名称',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'Topic',
|
||||
label: 'kafka主题',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'Database',
|
||||
label: '数据库',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
placeholder: '/usr/local/app',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'Path',
|
||||
label: '根目录路径',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'Tz',
|
||||
label: '时区',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
|
||||
],
|
||||
showDefaultActions: false,
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
confirmText: '提交',
|
||||
onOpenChange:() => {
|
||||
|
||||
},
|
||||
onConfirm: async () => {
|
||||
// 提交表单
|
||||
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 ServerId = parseInt(values.ServerId, 10);
|
||||
await addServer(modalData.AppId, ServerId, values.ServerName, values.Status, dateTime);
|
||||
modalApi.close();
|
||||
},
|
||||
});
|
||||
defineOptions({
|
||||
name: 'AddServerModal',
|
||||
})
|
||||
defineExpose({
|
||||
FormApi
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal title="添加服务器" :width="800">
|
||||
<Form />
|
||||
|
||||
</Modal>
|
||||
</template>
|
||||
58
apps/web-antd/src/views/dashboard/appList/appList.vue
Normal file
58
apps/web-antd/src/views/dashboard/appList/appList.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AppData } from '#/api/core/server';
|
||||
import AddServerModal from './addServer.vue'
|
||||
defineOptions({
|
||||
name: 'AppList',
|
||||
})
|
||||
interface Props {
|
||||
items: AppData[];
|
||||
title: string;
|
||||
}
|
||||
withDefaults(defineProps<Props>(),{
|
||||
items: () => [],
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<!-- <------------------- Add your code here ------------------->
|
||||
<template>
|
||||
<AddServerModal></AddServerModal>
|
||||
<div v-for="item in items" :key="item.AppId">
|
||||
<div class="card-box p-4 py-6 md:mt-4">
|
||||
<div class="flex justify-between h-2 border-foreground/10">
|
||||
|
||||
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>{{ item.AppId }}</span>
|
||||
</h2>
|
||||
</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>{{ item.AppName }}</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>{{ item.NodeName }}</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>{{ item.MysqlName }}</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>{{ item.Topic }}</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>{{ item.tz }}</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
85
apps/web-antd/src/views/dashboard/appList/index.vue
Normal file
85
apps/web-antd/src/views/dashboard/appList/index.vue
Normal file
@ -0,0 +1,85 @@
|
||||
<script lang="ts" setup>
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { Button, Card, Space, notification } from 'ant-design-vue';
|
||||
import AppList from './appList.vue';
|
||||
import { getAppListApi, updateAppApi } from '#/api/core/server';
|
||||
import type { AppData } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui'
|
||||
import { ref,onMounted } from 'vue';
|
||||
import addServerModal from './addServer.vue';
|
||||
|
||||
|
||||
const [addServerM, addServerApi] = useVbenModal({
|
||||
connectedComponent: addServerModal,
|
||||
onClosed: async () => {
|
||||
addServerApi.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const appList = ref<AppData[]>([]);
|
||||
onMounted(async() => {
|
||||
try{
|
||||
const response = await getAppListApi();
|
||||
appList.value = Array.isArray(response) ? response : [];
|
||||
const app = appList.value[0];
|
||||
if (!app) return;
|
||||
}catch(e){
|
||||
appList.value = [];
|
||||
//console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
async function addApp() {
|
||||
addServerApi.open()
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<Page>
|
||||
<addServerM class="w-[50%]"/>
|
||||
<Card class="mb-5" title="节点操作">
|
||||
<Space>
|
||||
<Button @click="addApp">新增</Button>
|
||||
<Button> 删除 </Button>
|
||||
</Space>
|
||||
</Card>
|
||||
<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">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>AppId</span>
|
||||
</h2>
|
||||
</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>AppName</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>NodeName</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>MysqlName</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>Topic</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>tz</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<AppList :items="appList" title="服务器列表"/>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
154
apps/web-antd/src/views/dashboard/mysqlList/addServer.vue
Normal file
154
apps/web-antd/src/views/dashboard/mysqlList/addServer.vue
Normal file
@ -0,0 +1,154 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { addServer } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
|
||||
const date = dayjs();
|
||||
const [Form, FormApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
|
||||
// 使用 tailwindcss grid布局
|
||||
// 提交函数
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
layout: 'horizontal',
|
||||
// 水平布局,label和input在同一行
|
||||
schema: [
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: false,
|
||||
defaultValue: 0,
|
||||
componentProps: {
|
||||
placeholder: '1',
|
||||
},
|
||||
formItemClass:'col-span-2',
|
||||
fieldName: 'AppId',
|
||||
label: 'AppId:',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: false,
|
||||
componentProps: {
|
||||
placeholder: '2',
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'ServerId',
|
||||
label: 'ServerId:',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
placeholder: 'node1',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'ServerName',
|
||||
label: 'ServerName:',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'DatePicker',
|
||||
fieldName: 'datePicker',
|
||||
defaultValue: date,
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
wrapperClass: 'grid-span-1',
|
||||
label: '开服日期',
|
||||
},
|
||||
{
|
||||
component: 'TimePicker',
|
||||
fieldName: 'timePicker',
|
||||
defaultValue: date,
|
||||
componentProps: {
|
||||
format: 'HH:mm:ss',
|
||||
},
|
||||
wrapperClass: 'grid-span-2 grid-start-2',
|
||||
label: '开服时间',
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
filterOption: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Start',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: 'Stop',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: 'Maintain',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
placeholder: '请选择',
|
||||
showSearch: true,
|
||||
},
|
||||
fieldName: 'Status',
|
||||
label: 'Status',
|
||||
},
|
||||
|
||||
],
|
||||
showDefaultActions: false,
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
confirmText: '提交',
|
||||
onOpenChange:() => {
|
||||
const modalData = modalApi.getData();
|
||||
FormApi.updateSchema([
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: true,
|
||||
defaultValue: modalData.AppId,
|
||||
componentProps: {
|
||||
placeholder: modalData.AppId,
|
||||
},
|
||||
formItemClass:'col-span-2',
|
||||
fieldName: 'AppId',
|
||||
label: 'AppId:',
|
||||
},
|
||||
])
|
||||
},
|
||||
onConfirm: async () => {
|
||||
// 提交表单
|
||||
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 ServerId = parseInt(values.ServerId, 10);
|
||||
await addServer(modalData.AppId, ServerId, values.ServerName, values.Status, dateTime);
|
||||
modalApi.close();
|
||||
},
|
||||
});
|
||||
defineOptions({
|
||||
name: 'AddServerModal',
|
||||
})
|
||||
defineExpose({
|
||||
FormApi
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal title="添加服务器" :width="800">
|
||||
<Form />
|
||||
|
||||
</Modal>
|
||||
</template>
|
||||
149
apps/web-antd/src/views/dashboard/mysqlList/appList.vue
Normal file
149
apps/web-antd/src/views/dashboard/mysqlList/appList.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<script lang="ts" setup>
|
||||
import { Button, Tag, notification, Modal } from 'ant-design-vue';
|
||||
import type { ServerData } from '#/api/core/server';
|
||||
import {restartServer, getServerListApi, reloadServer} from '#/api/core/server';
|
||||
import AddServerModal from './addServer.vue'
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
defineOptions({
|
||||
name: 'AppList',
|
||||
})
|
||||
interface Props {
|
||||
items: ServerData[];
|
||||
title: string;
|
||||
}
|
||||
withDefaults(defineProps<Props>(),{
|
||||
items: () => [],
|
||||
})
|
||||
|
||||
|
||||
function getColor(status: number) {
|
||||
switch (status){
|
||||
case 0:
|
||||
return 'red';
|
||||
case 1:
|
||||
return 'green';
|
||||
default:
|
||||
return 'blue';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function restart(Server: ServerData) {
|
||||
try{
|
||||
Server.Loading = true;
|
||||
const AppId = Server.AppId;
|
||||
await restartServer(AppId, Server.ServerId, Server.ServerName);
|
||||
notification.success({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '重启成功',
|
||||
type: 'success',
|
||||
});
|
||||
Server.Loading = false;
|
||||
const serverResponse = await getServerListApi({AppId:Server.AppId});
|
||||
const foundServer = serverResponse.find((item) => item.ServerId == Server.ServerId);
|
||||
Server.StartTime = foundServer ? foundServer.StartTime : undefined;
|
||||
//console.log('更新成功');
|
||||
}catch(e){
|
||||
notification.error({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '更新失败',
|
||||
type: 'error',
|
||||
});
|
||||
Server.Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function reload(Server: ServerData) {
|
||||
try{
|
||||
Server.Reload = true;
|
||||
const AppId = Server.AppId;
|
||||
await reloadServer(AppId, Server.ServerId, Server.ServerName);
|
||||
notification.success({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '重载成功',
|
||||
type: 'success',
|
||||
});
|
||||
Server.Reload = false;
|
||||
const serverResponse = await getServerListApi({AppId:Server.AppId});
|
||||
const foundServer = serverResponse.find((item) => item.ServerId == Server.ServerId);
|
||||
Server.StartTime = foundServer ? foundServer.StartTime : undefined;
|
||||
//console.log('更新成功');
|
||||
}catch(e){
|
||||
notification.error({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '更新失败',
|
||||
type: 'error',
|
||||
});
|
||||
Server.Loading = false;
|
||||
}
|
||||
}
|
||||
function confirmUpdate(Server: ServerData) {
|
||||
Modal.confirm({
|
||||
title: '确认更新',
|
||||
content: `你确定要更新 ${Server.ServerName} 吗?`,
|
||||
onOk() {
|
||||
restart(Server);
|
||||
},
|
||||
onCancel() {
|
||||
//console.log('取消更新');
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<!-- <------------------- Add your code here ------------------->
|
||||
<template>
|
||||
<AddServerModal></AddServerModal>
|
||||
<div v-for="item in items" :key="item.ServerId">
|
||||
<div class="card-box p-4 py-6 md:mt-4">
|
||||
<div class="flex justify-between h-2 border-foreground/10">
|
||||
|
||||
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>{{ item.ServerId }}</span>
|
||||
</h2>
|
||||
</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>{{ item.ServerName }}</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 :color="getColor(item.Status || 0)">
|
||||
{{ item.Status == 0 ? 'Inactive' : item.Status == 1 ? 'Active' : 'Unknown' }}
|
||||
</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>{{ dayjs((item.StartTime ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss') }}</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>{{ item.PlayerNum }}</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>{{ dayjs((item.OpenServerTime ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss') }}</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 @click=confirmUpdate(item) type="primary" :loading="item.Loading">Restart</Button>
|
||||
</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 @click=reload(item) type="primary" :loading="item.Reload">Reload</Button>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
226
apps/web-antd/src/views/dashboard/mysqlList/index.vue
Normal file
226
apps/web-antd/src/views/dashboard/mysqlList/index.vue
Normal file
@ -0,0 +1,226 @@
|
||||
<script lang="ts" setup>
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { Button, Card, Space, notification } from 'ant-design-vue';
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import AppList from './appList.vue';
|
||||
import { getServerListApi, getAppListApi, updateAppApi } from '#/api/core/server';
|
||||
import type { AppData, ServerData } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui'
|
||||
import { ref,onMounted } from 'vue';
|
||||
import addServerModal from './addServer.vue';
|
||||
import dayjs from 'dayjs';
|
||||
const [BaseForm, BaseFormApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
|
||||
// 使用 tailwindcss grid布局
|
||||
// 提交函数
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
layout: 'horizontal',
|
||||
// 水平布局,label和input在同一行
|
||||
schema: [
|
||||
{
|
||||
component: 'Select',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
onChange: async (value: number) => {
|
||||
const serverResponse = await getServerListApi({AppId:value});
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
const app = appList.value.find((item) => item.AppId === value);
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
},
|
||||
filterOption: true,
|
||||
options: [
|
||||
|
||||
],
|
||||
placeholder: '请选择',
|
||||
showSearch: true,
|
||||
},
|
||||
fieldName: 'fieldOptions',
|
||||
label: 'APP:',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: true,
|
||||
defaultValue: "",
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
},
|
||||
fieldName: 'update',
|
||||
label: '更新时间:',
|
||||
}
|
||||
],
|
||||
// handleSubmit: async (values: Record<string, any>) => {
|
||||
// console.log(values);
|
||||
// },
|
||||
showDefaultActions: false,
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-2 ',
|
||||
});
|
||||
const [addServerM, addServerApi] = useVbenModal({
|
||||
connectedComponent: addServerModal,
|
||||
onClosed: async () => {
|
||||
const Value = await BaseFormApi.getValues();
|
||||
const serverResponse = await getServerListApi(Value.fieldOptions);
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
addServerApi.close();
|
||||
},
|
||||
});
|
||||
|
||||
const serverList = [
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
];
|
||||
const appList = ref<AppData[]>([]);
|
||||
const ServerList = ref<ServerData[]>([]);
|
||||
const reload = ref(false);
|
||||
onMounted(async() => {
|
||||
try{
|
||||
const response = await getAppListApi();
|
||||
appList.value = Array.isArray(response) ? response : [];
|
||||
const app = appList.value[0];
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
BaseFormApi.updateSchema([
|
||||
{
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: appList.value.map((item) => ({
|
||||
label: item.AppName,
|
||||
value: item.AppId,
|
||||
})),
|
||||
},
|
||||
fieldName: 'fieldOptions',
|
||||
},
|
||||
]);
|
||||
const serverResponse = await getServerListApi({AppId:app.AppId});
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
}catch(e){
|
||||
appList.value = serverList;
|
||||
//console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
async function addServer() {
|
||||
const Value = await BaseFormApi.getValues();
|
||||
addServerApi.setData({AppId: Value.fieldOptions});
|
||||
addServerApi.open();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async function update() {
|
||||
reload.value = true;
|
||||
const Value = await BaseFormApi.getValues();
|
||||
try{
|
||||
await updateAppApi(Value.fieldOptions);
|
||||
reload.value = false;
|
||||
notification.info({
|
||||
duration:10,
|
||||
message:"服务器更新成功"
|
||||
})
|
||||
const response = await getAppListApi();
|
||||
appList.value = Array.isArray(response) ? response : [];
|
||||
const app = appList.value.find((item) => item.AppId === Value.fieldOptions);
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
}catch(e){
|
||||
reload.value = false;
|
||||
notification.error({
|
||||
duration:10,
|
||||
message:"服务器更新失败"
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Page>
|
||||
<addServerM class="w-[50%]" @hidden="update"/>
|
||||
<Card class="mb-5" title="服务器操作">
|
||||
<BaseForm />
|
||||
<Space>
|
||||
<Button @click="addServer">新增</Button>
|
||||
<Button type="primary" @click="update" :loading="reload"> 更新 </Button>
|
||||
<Button> 删除 </Button>
|
||||
<Button danger> 更新配置 </Button>
|
||||
</Space>
|
||||
</Card>
|
||||
<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">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>ServerId</span>
|
||||
</h2>
|
||||
</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>ServerName</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>Status</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>StartTime</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>PlayerNum</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>OpenServerTime</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>Handle</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>Config</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <template>
|
||||
<AppList :items="ServerList" title="服务器列表"/>
|
||||
</template> -->
|
||||
<AppList :items="ServerList" title="服务器列表"/>
|
||||
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
154
apps/web-antd/src/views/dashboard/nodeList/addServer.vue
Normal file
154
apps/web-antd/src/views/dashboard/nodeList/addServer.vue
Normal file
@ -0,0 +1,154 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { addServer } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
|
||||
const date = dayjs();
|
||||
const [Form, FormApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
|
||||
// 使用 tailwindcss grid布局
|
||||
// 提交函数
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
layout: 'horizontal',
|
||||
// 水平布局,label和input在同一行
|
||||
schema: [
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: false,
|
||||
defaultValue: 0,
|
||||
componentProps: {
|
||||
placeholder: '1',
|
||||
},
|
||||
formItemClass:'col-span-2',
|
||||
fieldName: 'AppId',
|
||||
label: 'AppId:',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: false,
|
||||
componentProps: {
|
||||
placeholder: '2',
|
||||
typeof: 'number',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'ServerId',
|
||||
label: 'ServerId:',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
defaultValue: '',
|
||||
componentProps: {
|
||||
placeholder: 'node1',
|
||||
},
|
||||
rules: "required",
|
||||
fieldName: 'ServerName',
|
||||
label: 'ServerName:',
|
||||
formItemClass:'col-span-2',
|
||||
},
|
||||
{
|
||||
component: 'DatePicker',
|
||||
fieldName: 'datePicker',
|
||||
defaultValue: date,
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
wrapperClass: 'grid-span-1',
|
||||
label: '开服日期',
|
||||
},
|
||||
{
|
||||
component: 'TimePicker',
|
||||
fieldName: 'timePicker',
|
||||
defaultValue: date,
|
||||
componentProps: {
|
||||
format: 'HH:mm:ss',
|
||||
},
|
||||
wrapperClass: 'grid-span-2 grid-start-2',
|
||||
label: '开服时间',
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
filterOption: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Start',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: 'Stop',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: 'Maintain',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
placeholder: '请选择',
|
||||
showSearch: true,
|
||||
},
|
||||
fieldName: 'Status',
|
||||
label: 'Status',
|
||||
},
|
||||
|
||||
],
|
||||
showDefaultActions: false,
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
confirmText: '提交',
|
||||
onOpenChange:() => {
|
||||
const modalData = modalApi.getData();
|
||||
FormApi.updateSchema([
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: true,
|
||||
defaultValue: modalData.AppId,
|
||||
componentProps: {
|
||||
placeholder: modalData.AppId,
|
||||
},
|
||||
formItemClass:'col-span-2',
|
||||
fieldName: 'AppId',
|
||||
label: 'AppId:',
|
||||
},
|
||||
])
|
||||
},
|
||||
onConfirm: async () => {
|
||||
// 提交表单
|
||||
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 ServerId = parseInt(values.ServerId, 10);
|
||||
await addServer(modalData.AppId, ServerId, values.ServerName, values.Status, dateTime);
|
||||
modalApi.close();
|
||||
},
|
||||
});
|
||||
defineOptions({
|
||||
name: 'AddServerModal',
|
||||
})
|
||||
defineExpose({
|
||||
FormApi
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal title="添加服务器" :width="800">
|
||||
<Form />
|
||||
|
||||
</Modal>
|
||||
</template>
|
||||
149
apps/web-antd/src/views/dashboard/nodeList/appList.vue
Normal file
149
apps/web-antd/src/views/dashboard/nodeList/appList.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<script lang="ts" setup>
|
||||
import { Button, Tag, notification, Modal } from 'ant-design-vue';
|
||||
import type { ServerData } from '#/api/core/server';
|
||||
import {restartServer, getServerListApi, reloadServer} from '#/api/core/server';
|
||||
import AddServerModal from './addServer.vue'
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
defineOptions({
|
||||
name: 'AppList',
|
||||
})
|
||||
interface Props {
|
||||
items: ServerData[];
|
||||
title: string;
|
||||
}
|
||||
withDefaults(defineProps<Props>(),{
|
||||
items: () => [],
|
||||
})
|
||||
|
||||
|
||||
function getColor(status: number) {
|
||||
switch (status){
|
||||
case 0:
|
||||
return 'red';
|
||||
case 1:
|
||||
return 'green';
|
||||
default:
|
||||
return 'blue';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function restart(Server: ServerData) {
|
||||
try{
|
||||
Server.Loading = true;
|
||||
const AppId = Server.AppId;
|
||||
await restartServer(AppId, Server.ServerId, Server.ServerName);
|
||||
notification.success({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '重启成功',
|
||||
type: 'success',
|
||||
});
|
||||
Server.Loading = false;
|
||||
const serverResponse = await getServerListApi({AppId:Server.AppId});
|
||||
const foundServer = serverResponse.find((item) => item.ServerId == Server.ServerId);
|
||||
Server.StartTime = foundServer ? foundServer.StartTime : undefined;
|
||||
//console.log('更新成功');
|
||||
}catch(e){
|
||||
notification.error({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '更新失败',
|
||||
type: 'error',
|
||||
});
|
||||
Server.Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function reload(Server: ServerData) {
|
||||
try{
|
||||
Server.Reload = true;
|
||||
const AppId = Server.AppId;
|
||||
await reloadServer(AppId, Server.ServerId, Server.ServerName);
|
||||
notification.success({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '重载成功',
|
||||
type: 'success',
|
||||
});
|
||||
Server.Reload = false;
|
||||
const serverResponse = await getServerListApi({AppId:Server.AppId});
|
||||
const foundServer = serverResponse.find((item) => item.ServerId == Server.ServerId);
|
||||
Server.StartTime = foundServer ? foundServer.StartTime : undefined;
|
||||
//console.log('更新成功');
|
||||
}catch(e){
|
||||
notification.error({
|
||||
duration: 10,
|
||||
message: Server.ServerName + '更新失败',
|
||||
type: 'error',
|
||||
});
|
||||
Server.Loading = false;
|
||||
}
|
||||
}
|
||||
function confirmUpdate(Server: ServerData) {
|
||||
Modal.confirm({
|
||||
title: '确认更新',
|
||||
content: `你确定要更新 ${Server.ServerName} 吗?`,
|
||||
onOk() {
|
||||
restart(Server);
|
||||
},
|
||||
onCancel() {
|
||||
//console.log('取消更新');
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<!-- <------------------- Add your code here ------------------->
|
||||
<template>
|
||||
<AddServerModal></AddServerModal>
|
||||
<div v-for="item in items" :key="item.ServerId">
|
||||
<div class="card-box p-4 py-6 md:mt-4">
|
||||
<div class="flex justify-between h-2 border-foreground/10">
|
||||
|
||||
<div class="flex flex-col justify-center md:mt-0 lg:w-1/12">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>{{ item.ServerId }}</span>
|
||||
</h2>
|
||||
</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>{{ item.ServerName }}</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 :color="getColor(item.Status || 0)">
|
||||
{{ item.Status == 0 ? 'Inactive' : item.Status == 1 ? 'Active' : 'Unknown' }}
|
||||
</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>{{ dayjs((item.StartTime ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss') }}</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>{{ item.PlayerNum }}</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>{{ dayjs((item.OpenServerTime ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss') }}</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 @click=confirmUpdate(item) type="primary" :loading="item.Loading">Restart</Button>
|
||||
</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 @click=reload(item) type="primary" :loading="item.Reload">Reload</Button>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
226
apps/web-antd/src/views/dashboard/nodeList/index.vue
Normal file
226
apps/web-antd/src/views/dashboard/nodeList/index.vue
Normal file
@ -0,0 +1,226 @@
|
||||
<script lang="ts" setup>
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { Button, Card, Space, notification } from 'ant-design-vue';
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import AppList from './appList.vue';
|
||||
import { getServerListApi, getAppListApi, updateAppApi } from '#/api/core/server';
|
||||
import type { AppData, ServerData } from '#/api/core/server';
|
||||
import { useVbenModal } from '@vben/common-ui'
|
||||
import { ref,onMounted } from 'vue';
|
||||
import addServerModal from './addServer.vue';
|
||||
import dayjs from 'dayjs';
|
||||
const [BaseForm, BaseFormApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
|
||||
// 使用 tailwindcss grid布局
|
||||
// 提交函数
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
layout: 'horizontal',
|
||||
// 水平布局,label和input在同一行
|
||||
schema: [
|
||||
{
|
||||
component: 'Select',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
onChange: async (value: number) => {
|
||||
const serverResponse = await getServerListApi({AppId:value});
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
const app = appList.value.find((item) => item.AppId === value);
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
},
|
||||
filterOption: true,
|
||||
options: [
|
||||
|
||||
],
|
||||
placeholder: '请选择',
|
||||
showSearch: true,
|
||||
},
|
||||
fieldName: 'fieldOptions',
|
||||
label: 'APP:',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
disabled: true,
|
||||
defaultValue: "",
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
},
|
||||
fieldName: 'update',
|
||||
label: '更新时间:',
|
||||
}
|
||||
],
|
||||
// handleSubmit: async (values: Record<string, any>) => {
|
||||
// console.log(values);
|
||||
// },
|
||||
showDefaultActions: false,
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-2 ',
|
||||
});
|
||||
const [addServerM, addServerApi] = useVbenModal({
|
||||
connectedComponent: addServerModal,
|
||||
onClosed: async () => {
|
||||
const Value = await BaseFormApi.getValues();
|
||||
const serverResponse = await getServerListApi(Value.fieldOptions);
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
addServerApi.close();
|
||||
},
|
||||
});
|
||||
|
||||
const serverList = [
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
{
|
||||
AppId: 1,
|
||||
AppName: '测试版本',
|
||||
WsHost: '1.226.16.67',
|
||||
Status: 'Online',
|
||||
},
|
||||
];
|
||||
const appList = ref<AppData[]>([]);
|
||||
const ServerList = ref<ServerData[]>([]);
|
||||
const reload = ref(false);
|
||||
onMounted(async() => {
|
||||
try{
|
||||
const response = await getAppListApi();
|
||||
appList.value = Array.isArray(response) ? response : [];
|
||||
const app = appList.value[0];
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
BaseFormApi.updateSchema([
|
||||
{
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: appList.value.map((item) => ({
|
||||
label: item.AppName,
|
||||
value: item.AppId,
|
||||
})),
|
||||
},
|
||||
fieldName: 'fieldOptions',
|
||||
},
|
||||
]);
|
||||
const serverResponse = await getServerListApi({AppId:app.AppId});
|
||||
ServerList.value = Array.isArray(serverResponse) ? serverResponse : [];
|
||||
}catch(e){
|
||||
appList.value = serverList;
|
||||
//console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
async function addServer() {
|
||||
const Value = await BaseFormApi.getValues();
|
||||
addServerApi.setData({AppId: Value.fieldOptions});
|
||||
addServerApi.open();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async function update() {
|
||||
reload.value = true;
|
||||
const Value = await BaseFormApi.getValues();
|
||||
try{
|
||||
await updateAppApi(Value.fieldOptions);
|
||||
reload.value = false;
|
||||
notification.info({
|
||||
duration:10,
|
||||
message:"服务器更新成功"
|
||||
})
|
||||
const response = await getAppListApi();
|
||||
appList.value = Array.isArray(response) ? response : [];
|
||||
const app = appList.value.find((item) => item.AppId === Value.fieldOptions);
|
||||
if (!app) return;
|
||||
const updateTime = dayjs((app.Update ?? 0) * 1000).format('YYYY-MM-DD HH:mm:ss')
|
||||
BaseFormApi.setFieldValue("update", updateTime)
|
||||
}catch(e){
|
||||
reload.value = false;
|
||||
notification.error({
|
||||
duration:10,
|
||||
message:"服务器更新失败"
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Page>
|
||||
<addServerM class="w-[50%]" @hidden="update"/>
|
||||
<Card class="mb-5" title="服务器操作">
|
||||
<BaseForm />
|
||||
<Space>
|
||||
<Button @click="addServer">新增</Button>
|
||||
<Button type="primary" @click="update" :loading="reload"> 更新 </Button>
|
||||
<Button> 删除 </Button>
|
||||
<Button danger> 更新配置 </Button>
|
||||
</Space>
|
||||
</Card>
|
||||
<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">
|
||||
<h2 class="text-md font-semibold md:text-ml text-center">
|
||||
<span>ServerId</span>
|
||||
</h2>
|
||||
</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>ServerName</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>Status</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>StartTime</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>PlayerNum</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>OpenServerTime</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>Handle</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>Config</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <template>
|
||||
<AppList :items="ServerList" title="服务器列表"/>
|
||||
</template> -->
|
||||
<AppList :items="ServerList" title="服务器列表"/>
|
||||
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
@ -41,13 +41,13 @@ const formatItemName = (cellValue: number) => {
|
||||
return cellValue;
|
||||
}
|
||||
}
|
||||
const date = dayjs();
|
||||
const d = ref({
|
||||
sum : 0,
|
||||
psum : 0,
|
||||
nsum : 0,
|
||||
});
|
||||
const startDate = dayjs().startOf('day');
|
||||
const endDate = dayjs().endOf('day');
|
||||
const formOptions: VbenFormProps = {
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
@ -101,7 +101,7 @@ const formOptions: VbenFormProps = {
|
||||
},
|
||||
{
|
||||
component: 'DatePicker',
|
||||
defaultValue: date,
|
||||
defaultValue: endDate,
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
|
||||
@ -12,8 +12,8 @@ import { Page } from '@vben/common-ui';
|
||||
import dayjs from 'dayjs';
|
||||
const state = inject('globalState', globalState);
|
||||
|
||||
const date = dayjs();
|
||||
const startDate = dayjs().startOf('day');
|
||||
const endDate = dayjs().endOf('day');
|
||||
interface RowType {
|
||||
Uid: string;
|
||||
Event: string;
|
||||
@ -63,7 +63,7 @@ const formOptions: VbenFormProps = {
|
||||
},
|
||||
{
|
||||
component: 'DatePicker',
|
||||
defaultValue: date,
|
||||
defaultValue: endDate,
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
|
||||
@ -40,10 +40,10 @@ withDefaults(defineProps<Props>(), {
|
||||
<h1 v-if="$slots.nick_name" class="text-md font-semibold md:text-xl">
|
||||
<slot name="nick_name"></slot>
|
||||
</h1>
|
||||
<span v-if="$slots.user_name" class="text-foreground/80 mt-1" @click='copyUserName' id="user_name">
|
||||
<span v-if="$slots.user_name" class="text-foreground/80 mt-1 ant-btn" @click='copyUserName' id="user_name">
|
||||
<slot name="user_name"></slot>
|
||||
</span>
|
||||
<span v-if="$slots.uid" class="text-foreground/80 mt-1" @click='copyUid' id="uid">
|
||||
<span v-if="$slots.uid" class="text-foreground/80 mt-1 ant-btn" @click='copyUid' id="uid">
|
||||
<slot name="uid"></slot>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -70,7 +70,6 @@
|
||||
|
||||
/* Default border color */
|
||||
--border: 240 5.9% 90%;
|
||||
|
||||
/* Border color for inputs such as <Input />, <Select />, <Textarea /> */
|
||||
--input: 240deg 5.88% 90%;
|
||||
--input-placeholder: 217 10.6% 65%;
|
||||
|
||||
@ -100,7 +100,7 @@ defineEmits(['click']);
|
||||
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 p-1 leading-2">
|
||||
<span>Bonus:</span>
|
||||
</div>
|
||||
<div class="text-foreground/80 mt-3 flex h-4 md:w-1/2 justify-start p-1 leading-2">
|
||||
<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>
|
||||
|
||||
@ -50,3 +50,24 @@
|
||||
.ant-app .form-valid-error .ant-picker-focused {
|
||||
box-shadow: 0 0 0 2px rgb(255 38 5 / 6%);
|
||||
}
|
||||
|
||||
|
||||
.text-outline {
|
||||
text-shadow:
|
||||
-1px -1px 0 hsl(var(--foreground)),
|
||||
1px -1px 0 hsl(var(--foreground)),
|
||||
-1px 1px 0 hsl(var(--foreground)),
|
||||
1px 1px 0 hsl(var(--foreground));
|
||||
}
|
||||
/* 按钮点击动画 */
|
||||
.ant-btn:active {
|
||||
transform: scale(0.96);
|
||||
transition: transform 0.1s;
|
||||
}
|
||||
/* 按钮悬停动画 */
|
||||
.ant-btn:hover {
|
||||
transform: scale(1.02);
|
||||
transition: transform 0.1s;
|
||||
cursor: pointer;
|
||||
color: hsl(var(--ring));
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user