mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-10 08:35:29 +08:00
feat: 监控前端界面显示
This commit is contained in:
parent
e57fd7050e
commit
cb741cc41d
13 changed files with 760 additions and 10378 deletions
|
@ -1,6 +1,6 @@
|
||||||
system:
|
system:
|
||||||
port: 9999
|
port: 9999
|
||||||
db_type: mysql
|
db_type: sqlite
|
||||||
level: debug
|
level: debug
|
||||||
|
|
||||||
jwt:
|
jwt:
|
||||||
|
|
10492
frontend/package-lock.json
generated
10492
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
13
frontend/src/api/interface/monitor.ts
Normal file
13
frontend/src/api/interface/monitor.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
export namespace Monitor {
|
||||||
|
export interface MonitorData {
|
||||||
|
param: string;
|
||||||
|
date: Array<Date>;
|
||||||
|
value: Array<any>;
|
||||||
|
}
|
||||||
|
export interface MonitorSearch {
|
||||||
|
param: string;
|
||||||
|
info: string;
|
||||||
|
startTime: Date;
|
||||||
|
endTime: Date;
|
||||||
|
}
|
||||||
|
}
|
10
frontend/src/api/modules/monitor.ts
Normal file
10
frontend/src/api/modules/monitor.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import http from '@/api';
|
||||||
|
import { Monitor } from '../interface/monitor';
|
||||||
|
|
||||||
|
export const loadMonitor = (param: Monitor.MonitorSearch) => {
|
||||||
|
return http.post<Array<Monitor.MonitorData>>(`/monitors/search`, param);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNetworkOptions = () => {
|
||||||
|
return http.get<Array<string>>(`/monitors/netoptions`);
|
||||||
|
};
|
|
@ -11,6 +11,13 @@ export default {
|
||||||
login: 'Login',
|
login: 'Login',
|
||||||
conn: 'Connect',
|
conn: 'Connect',
|
||||||
},
|
},
|
||||||
|
search: {
|
||||||
|
timeStart: 'Time start',
|
||||||
|
timeEnd: 'Time end',
|
||||||
|
timeRange: 'To',
|
||||||
|
dateStart: 'Date start',
|
||||||
|
dateEnd: 'Date end',
|
||||||
|
},
|
||||||
table: {
|
table: {
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
group: 'Group',
|
group: 'Group',
|
||||||
|
@ -77,6 +84,7 @@ export default {
|
||||||
menu: {
|
menu: {
|
||||||
home: 'Dashboard',
|
home: 'Dashboard',
|
||||||
demo: 'Demo',
|
demo: 'Demo',
|
||||||
|
monitor: 'Monitor',
|
||||||
terminal: 'Terminal',
|
terminal: 'Terminal',
|
||||||
operations: 'Operation logs',
|
operations: 'Operation logs',
|
||||||
files: 'File Management',
|
files: 'File Management',
|
||||||
|
@ -105,6 +113,25 @@ export default {
|
||||||
changePassword: 'Change Password',
|
changePassword: 'Change Password',
|
||||||
logout: 'Logout',
|
logout: 'Logout',
|
||||||
},
|
},
|
||||||
|
monitor: {
|
||||||
|
avgLoad: 'Average load',
|
||||||
|
loadDetail: 'Load detail',
|
||||||
|
resourceUsage: 'Resource utilization rate',
|
||||||
|
min: 'Minutes',
|
||||||
|
read: 'Read',
|
||||||
|
write: 'Write',
|
||||||
|
count: 'Times',
|
||||||
|
readWriteCount: 'Read or write Times',
|
||||||
|
readWriteTime: 'Read or write delay',
|
||||||
|
today: 'Today',
|
||||||
|
yestoday: 'Yestoday',
|
||||||
|
lastNDay: 'Last {0} day',
|
||||||
|
memory: 'Memory',
|
||||||
|
disk: 'Disk',
|
||||||
|
network: 'Network',
|
||||||
|
up: 'Up',
|
||||||
|
down: 'Down',
|
||||||
|
},
|
||||||
terminal: {
|
terminal: {
|
||||||
conn: 'connection',
|
conn: 'connection',
|
||||||
testConn: 'Test connection',
|
testConn: 'Test connection',
|
||||||
|
@ -200,5 +227,8 @@ export default {
|
||||||
downloadSuccess: 'Download successful',
|
downloadSuccess: 'Download successful',
|
||||||
downloadUrl: 'download URL',
|
downloadUrl: 'download URL',
|
||||||
downloadStart: 'Download started!',
|
downloadStart: 'Download started!',
|
||||||
|
moveStart: 'Move start',
|
||||||
|
move: 'Move',
|
||||||
|
copy: 'Cpoy',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,13 @@ export default {
|
||||||
conn: '连接',
|
conn: '连接',
|
||||||
login: '登录',
|
login: '登录',
|
||||||
},
|
},
|
||||||
|
search: {
|
||||||
|
timeStart: '开始时间',
|
||||||
|
timeEnd: '结束时间',
|
||||||
|
timeRange: '至',
|
||||||
|
dateStart: '开始日期',
|
||||||
|
dateEnd: '结束日期',
|
||||||
|
},
|
||||||
table: {
|
table: {
|
||||||
name: '名称',
|
name: '名称',
|
||||||
group: '组',
|
group: '组',
|
||||||
|
@ -78,6 +85,7 @@ export default {
|
||||||
home: '概览',
|
home: '概览',
|
||||||
demo: '样例',
|
demo: '样例',
|
||||||
terminal: '终端管理',
|
terminal: '终端管理',
|
||||||
|
monitor: '监控',
|
||||||
operations: '操作记录',
|
operations: '操作记录',
|
||||||
files: '文件管理',
|
files: '文件管理',
|
||||||
},
|
},
|
||||||
|
@ -105,6 +113,25 @@ export default {
|
||||||
changePassword: '修改密码',
|
changePassword: '修改密码',
|
||||||
logout: '退出登录',
|
logout: '退出登录',
|
||||||
},
|
},
|
||||||
|
monitor: {
|
||||||
|
avgLoad: '平均负载',
|
||||||
|
loadDetail: '负载详情',
|
||||||
|
resourceUsage: '资源使用率',
|
||||||
|
min: '分钟',
|
||||||
|
read: '读取',
|
||||||
|
write: '写入',
|
||||||
|
count: '次',
|
||||||
|
readWriteCount: '读写次数',
|
||||||
|
readWriteTime: '读写延迟',
|
||||||
|
today: '今天',
|
||||||
|
yestoday: '昨天',
|
||||||
|
lastNDay: '近 {0} 天',
|
||||||
|
memory: '内存',
|
||||||
|
disk: '磁盘',
|
||||||
|
network: '网络',
|
||||||
|
up: '上行',
|
||||||
|
down: '下行',
|
||||||
|
},
|
||||||
terminal: {
|
terminal: {
|
||||||
conn: '连接',
|
conn: '连接',
|
||||||
testConn: '连接测试',
|
testConn: '连接测试',
|
||||||
|
|
28
frontend/src/routers/modules/monitor.ts
Normal file
28
frontend/src/routers/modules/monitor.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { Layout } from '@/routers/constant';
|
||||||
|
|
||||||
|
const monitorRouter = {
|
||||||
|
sort: 2,
|
||||||
|
path: '/monitors',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/monitor',
|
||||||
|
meta: {
|
||||||
|
title: 'menu.monitor',
|
||||||
|
icon: 'monitor',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/monitors/monitor',
|
||||||
|
name: 'Monitor',
|
||||||
|
component: () => import('@/views/monitor/index.vue'),
|
||||||
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
key: 'Monitor',
|
||||||
|
title: 'menu.monitor',
|
||||||
|
icon: 'Connection',
|
||||||
|
activeMenu: '/monitors',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default monitorRouter;
|
|
@ -49,6 +49,19 @@ export function dateFromat(row: number, col: number, dataStr: any) {
|
||||||
return `${String(y)}-${String(m)}-${String(d)} ${String(h)}:${String(minute)}:${String(second)}`;
|
return `${String(y)}-${String(m)}-${String(d)} ${String(h)}:${String(minute)}:${String(second)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function dateFromatWithoutYear(dataStr: any) {
|
||||||
|
const date = new Date(dataStr);
|
||||||
|
let m: string | number = date.getMonth() + 1;
|
||||||
|
m = m < 10 ? `0${String(m)}` : m;
|
||||||
|
let d: string | number = date.getDate();
|
||||||
|
d = d < 10 ? `0${String(d)}` : d;
|
||||||
|
let h: string | number = date.getHours();
|
||||||
|
h = h < 10 ? `0${String(h)}` : h;
|
||||||
|
let minute: string | number = date.getMinutes();
|
||||||
|
minute = minute < 10 ? `0${String(minute)}` : minute;
|
||||||
|
return `${String(m)}-${String(d)}\n${String(h)}:${String(minute)}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function getRandomStr(e: number): string {
|
export function getRandomStr(e: number): string {
|
||||||
const t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
const t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
||||||
const a = t.length;
|
const a = t.length;
|
||||||
|
|
|
@ -72,7 +72,7 @@ const batchDelete = async (row: User.User | null) => {
|
||||||
} else {
|
} else {
|
||||||
ids.push(row.id);
|
ids.push(row.id);
|
||||||
}
|
}
|
||||||
await useDeleteData(deleteUser, { ids: ids }, 'commons.msg.delete');
|
await useDeleteData(deleteUser, { ids: ids }, 'commons.msg.delete', true);
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
|
502
frontend/src/views/monitor/index.vue
Normal file
502
frontend/src/views/monitor/index.vue
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-card style="overflow: inherit">
|
||||||
|
<template #header>
|
||||||
|
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.avgLoad') }}</span>
|
||||||
|
<el-date-picker
|
||||||
|
@change="search('load')"
|
||||||
|
v-model="timeRangeLoad"
|
||||||
|
type="datetimerange"
|
||||||
|
size="small"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
style="float: right; right: 20px"
|
||||||
|
>
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
<div id="loadLoadChart" style="width: 100%; height: 400px"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card style="overflow: inherit">
|
||||||
|
<template #header>
|
||||||
|
<span style="font-size: 16px; font-weight: 500">CPU</span>
|
||||||
|
<el-date-picker
|
||||||
|
@change="search('cpu')"
|
||||||
|
v-model="timeRangeCpu"
|
||||||
|
type="datetimerange"
|
||||||
|
size="small"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
style="float: right; right: 20px"
|
||||||
|
>
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
<div id="loadCPUChart" style="width: 100%; height: 400px"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card style="overflow: inherit">
|
||||||
|
<template #header>
|
||||||
|
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.memory') }}</span>
|
||||||
|
<el-date-picker
|
||||||
|
@change="search('memory')"
|
||||||
|
v-model="timeRangeMemory"
|
||||||
|
type="datetimerange"
|
||||||
|
size="small"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
style="float: right; right: 20px"
|
||||||
|
>
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
<div id="loadMemoryChart" style="width: 100%; height: 400px"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card style="overflow: inherit">
|
||||||
|
<template #header>
|
||||||
|
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.disk') }} IO</span>
|
||||||
|
<el-date-picker
|
||||||
|
@change="search('io')"
|
||||||
|
v-model="timeRangeIO"
|
||||||
|
type="datetimerange"
|
||||||
|
size="small"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
style="float: right; right: 20px"
|
||||||
|
>
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
<div id="loadIOChart" style="width: 100%; height: 400px"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card style="overflow: inherit">
|
||||||
|
<template #header>
|
||||||
|
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.network') }} IO</span>
|
||||||
|
<el-select
|
||||||
|
v-model="networkChoose"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
@change="search('network')"
|
||||||
|
style="margin-left: 20px"
|
||||||
|
placeholder="Select"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-option v-for="item in netOptions" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
<el-date-picker
|
||||||
|
@change="search('network')"
|
||||||
|
v-model="timeRangeNetwork"
|
||||||
|
type="datetimerange"
|
||||||
|
size="small"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
style="float: right; right: 20px"
|
||||||
|
>
|
||||||
|
</el-date-picker>
|
||||||
|
</template>
|
||||||
|
<div id="loadNetworkChart" style="width: 100%; height: 400px"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import { loadMonitor, getNetworkOptions } from '@/api/modules/monitor';
|
||||||
|
import { Monitor } from '@/api/interface/monitor';
|
||||||
|
import { dateFromatWithoutYear } from '@/utils/util';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
|
||||||
|
const zoomStart = ref();
|
||||||
|
const monitorBase = ref();
|
||||||
|
const timeRangeLoad = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
|
const timeRangeCpu = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
|
const timeRangeMemory = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
|
const timeRangeIO = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
|
const timeRangeNetwork = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
|
const networkChoose = ref();
|
||||||
|
const netOptions = ref();
|
||||||
|
const shortcuts = [
|
||||||
|
{
|
||||||
|
text: i18n.global.t('monitor.today'),
|
||||||
|
value: () => {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date(new Date().setHours(0, 0, 0, 0));
|
||||||
|
return [start, end];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: i18n.global.t('monitor.yestoday'),
|
||||||
|
value: () => {
|
||||||
|
const yestoday = new Date(new Date().getTime() - 3600 * 1000 * 24 * 1);
|
||||||
|
const end = new Date(yestoday.setHours(23, 59, 59, 999));
|
||||||
|
const start = new Date(yestoday.setHours(0, 0, 0, 0));
|
||||||
|
return [start, end];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: i18n.global.t('monitor.lastNDay', [3]),
|
||||||
|
value: () => {
|
||||||
|
const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 3);
|
||||||
|
const end = new Date();
|
||||||
|
return [start, end];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: i18n.global.t('monitor.lastNDay', [7]),
|
||||||
|
value: () => {
|
||||||
|
const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 7);
|
||||||
|
const end = new Date();
|
||||||
|
return [start, end];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: i18n.global.t('monitor.lastNDay', [30]),
|
||||||
|
value: () => {
|
||||||
|
const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 30);
|
||||||
|
const end = new Date();
|
||||||
|
return [start, end];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const searchTime = ref();
|
||||||
|
const searchInfo = reactive<Monitor.MonitorSearch>({
|
||||||
|
param: '',
|
||||||
|
info: '',
|
||||||
|
startTime: new Date(new Date().setHours(0, 0, 0, 0)),
|
||||||
|
endTime: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const search = async (param: string) => {
|
||||||
|
searchInfo.param = param;
|
||||||
|
switch (param) {
|
||||||
|
case 'load':
|
||||||
|
searchTime.value = timeRangeLoad.value;
|
||||||
|
break;
|
||||||
|
case 'cpu':
|
||||||
|
searchTime.value = timeRangeCpu.value;
|
||||||
|
break;
|
||||||
|
case 'memory':
|
||||||
|
searchTime.value = timeRangeMemory.value;
|
||||||
|
break;
|
||||||
|
case 'io':
|
||||||
|
searchTime.value = timeRangeIO.value;
|
||||||
|
break;
|
||||||
|
case 'network':
|
||||||
|
searchTime.value = timeRangeNetwork.value;
|
||||||
|
searchInfo.info = networkChoose.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (searchTime.value && searchTime.value.length === 2) {
|
||||||
|
searchInfo.startTime = searchTime.value[0];
|
||||||
|
searchInfo.endTime = searchTime.value[1];
|
||||||
|
}
|
||||||
|
const res = await loadMonitor(searchInfo);
|
||||||
|
if (res.data[0].value === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
monitorBase.value = res.data;
|
||||||
|
for (const item of monitorBase.value) {
|
||||||
|
switch (item.param) {
|
||||||
|
case 'base':
|
||||||
|
let baseDate = item.date.map(function (item: any) {
|
||||||
|
return dateFromatWithoutYear(item);
|
||||||
|
});
|
||||||
|
if (param === 'cpu' || param === 'all') {
|
||||||
|
let cpuData = item.value.map(function (item: any) {
|
||||||
|
return item.cpu.toFixed(2);
|
||||||
|
});
|
||||||
|
let yDatasOfCpu = { name: 'CPU', type: 'line', data: cpuData, showSymbol: false };
|
||||||
|
initCharts('loadCPUChart', baseDate, yDatasOfCpu, 'CPU', '%');
|
||||||
|
}
|
||||||
|
if (param === 'memory' || param === 'all') {
|
||||||
|
let memoryData = item.value.map(function (item: any) {
|
||||||
|
return item.memory.toFixed(2);
|
||||||
|
});
|
||||||
|
let yDatasOfMem = {
|
||||||
|
name: i18n.global.t('monitor.memory'),
|
||||||
|
type: 'line',
|
||||||
|
data: memoryData,
|
||||||
|
showSymbol: false,
|
||||||
|
};
|
||||||
|
initCharts('loadMemoryChart', baseDate, yDatasOfMem, i18n.global.t('monitor.memory'), '%');
|
||||||
|
}
|
||||||
|
if (param === 'load' || param === 'all') {
|
||||||
|
initLoadCharts(item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'io':
|
||||||
|
initIOCharts(item);
|
||||||
|
break;
|
||||||
|
case 'network':
|
||||||
|
let networkDate = item.date.map(function (item: any) {
|
||||||
|
return dateFromatWithoutYear(item);
|
||||||
|
});
|
||||||
|
let networkUp = item.value.map(function (item: any) {
|
||||||
|
return item.up.toFixed(2);
|
||||||
|
});
|
||||||
|
let yDatasOfUp = {
|
||||||
|
name: i18n.global.t('monitor.up'),
|
||||||
|
type: 'line',
|
||||||
|
data: networkUp,
|
||||||
|
showSymbol: false,
|
||||||
|
};
|
||||||
|
let networkOut = item.value.map(function (item: any) {
|
||||||
|
return item.down.toFixed(2);
|
||||||
|
});
|
||||||
|
let yDatasOfDown = {
|
||||||
|
name: i18n.global.t('monitor.down'),
|
||||||
|
type: 'line',
|
||||||
|
data: networkOut,
|
||||||
|
showSymbol: false,
|
||||||
|
};
|
||||||
|
initCharts('loadNetworkChart', networkDate, [yDatasOfUp, yDatasOfDown], 'KB/s', 'KB/s');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadNetworkOptions = async () => {
|
||||||
|
const res = await getNetworkOptions();
|
||||||
|
netOptions.value = res.data;
|
||||||
|
searchInfo.info = netOptions.value && netOptions.value[0];
|
||||||
|
networkChoose.value = searchInfo.info;
|
||||||
|
search('all');
|
||||||
|
};
|
||||||
|
|
||||||
|
function initCharts(chartName: string, xDatas: any, yDatas: any, yTitle: string, formatStr: string) {
|
||||||
|
const lineChart = echarts.init(document.getElementById(chartName) as HTMLElement);
|
||||||
|
const option = {
|
||||||
|
zlevel: 1,
|
||||||
|
z: 1,
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function (datas: any) {
|
||||||
|
let res = datas[0].name + '<br/>';
|
||||||
|
for (const item of datas) {
|
||||||
|
res += item.marker + ' ' + item.seriesName + ':' + item.data + formatStr + '<br/>';
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: chartName === 'loadNetworkChart' && [i18n.global.t('monitor.up'), i18n.global.t('monitor.down')],
|
||||||
|
},
|
||||||
|
grid: { left: '7%', right: '7%', bottom: '20%' },
|
||||||
|
xAxis: { data: xDatas },
|
||||||
|
yAxis: { name: '( ' + formatStr + ' )' },
|
||||||
|
dataZoom: [{ startValue: zoomStart.value }],
|
||||||
|
series: yDatas,
|
||||||
|
};
|
||||||
|
lineChart.setOption(option, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initLoadCharts(item: Monitor.MonitorData) {
|
||||||
|
const lineChart = echarts.init(document.getElementById('loadLoadChart') as HTMLElement);
|
||||||
|
const option = {
|
||||||
|
zlevel: 1,
|
||||||
|
z: 1,
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function (datas: any) {
|
||||||
|
let res = datas[0].name + '<br/>';
|
||||||
|
for (const item of datas) {
|
||||||
|
res += item.marker + ' ' + item.seriesName + ':' + item.data + '%' + '<br/>';
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: [
|
||||||
|
'1 ' + i18n.global.t('monitor.min'),
|
||||||
|
'5 ' + i18n.global.t('monitor.min'),
|
||||||
|
'15 ' + i18n.global.t('monitor.min'),
|
||||||
|
i18n.global.t('monitor.resourceUsage'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
grid: { left: '7%', right: '7%', bottom: '20%' },
|
||||||
|
xAxis: {
|
||||||
|
data: item.date.map(function (item: any) {
|
||||||
|
return dateFromatWithoutYear(item);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{ type: 'value', name: i18n.global.t('monitor.loadDetail') + ' ( % )' },
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: i18n.global.t('monitor.resourceUsage') + ' ( % )',
|
||||||
|
position: 'right',
|
||||||
|
alignTicks: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dataZoom: [{ startValue: zoomStart.value }],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '1 ' + i18n.global.t('monitor.min'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.cpuLoad1.toFixed(2);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '5 ' + i18n.global.t('monitor.min'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.cpuLoad5.toFixed(2);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '15 ' + i18n.global.t('monitor.min'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.cpuLoad15.toFixed(2);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n.global.t('monitor.resourceUsage'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.loadUsage.toFixed(2);
|
||||||
|
}),
|
||||||
|
yAxisIndex: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
lineChart.setOption(option, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initIOCharts(item: Monitor.MonitorData) {
|
||||||
|
const lineChart = echarts.init(document.getElementById('loadIOChart') as HTMLElement);
|
||||||
|
const option = {
|
||||||
|
zlevel: 1,
|
||||||
|
z: 1,
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function (datas: any) {
|
||||||
|
let res = datas[0].name + '<br/>';
|
||||||
|
for (const item of datas) {
|
||||||
|
if (
|
||||||
|
item.seriesName === i18n.global.t('monitor.read') ||
|
||||||
|
item.seriesName === i18n.global.t('monitor.write')
|
||||||
|
) {
|
||||||
|
res += item.marker + ' ' + item.seriesName + ':' + item.data + ' KB/s' + '<br/>';
|
||||||
|
}
|
||||||
|
if (item.seriesName === i18n.global.t('monitor.readWriteCount')) {
|
||||||
|
res +=
|
||||||
|
item.marker +
|
||||||
|
' ' +
|
||||||
|
item.seriesName +
|
||||||
|
':' +
|
||||||
|
item.data +
|
||||||
|
' ' +
|
||||||
|
i18n.global.t('monitor.count') +
|
||||||
|
'/s' +
|
||||||
|
'<br/>';
|
||||||
|
}
|
||||||
|
if (item.seriesName === i18n.global.t('monitor.readWriteTime')) {
|
||||||
|
res += item.marker + ' ' + item.seriesName + ':' + item.data + ' ms' + '<br/>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: [
|
||||||
|
i18n.global.t('monitor.read'),
|
||||||
|
i18n.global.t('monitor.write'),
|
||||||
|
i18n.global.t('monitor.readWriteCount'),
|
||||||
|
i18n.global.t('monitor.readWriteTime'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
grid: { left: '7%', right: '7%', bottom: '20%' },
|
||||||
|
xAxis: {
|
||||||
|
data: item.date.map(function (item: any) {
|
||||||
|
return dateFromatWithoutYear(item);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{ type: 'value', name: '( KB/s )' },
|
||||||
|
{ type: 'value', position: 'right', alignTicks: true },
|
||||||
|
],
|
||||||
|
dataZoom: [{ startValue: zoomStart.value }],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: i18n.global.t('monitor.read'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return (item.read / 1024).toFixed(2);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n.global.t('monitor.write'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return (item.write / 1024).toFixed(2);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n.global.t('monitor.readWriteCount'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.count;
|
||||||
|
}),
|
||||||
|
yAxisIndex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n.global.t('monitor.readWriteTime'),
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: item.value.map(function (item: any) {
|
||||||
|
return item.time;
|
||||||
|
}),
|
||||||
|
yAxisIndex: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
lineChart.setOption(option, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeChartSize() {
|
||||||
|
echarts.getInstanceByDom(document.getElementById('loadLoadChart') as HTMLElement)?.resize();
|
||||||
|
echarts.getInstanceByDom(document.getElementById('loadCPUChart') as HTMLElement)?.resize();
|
||||||
|
echarts.getInstanceByDom(document.getElementById('loadMemoryChart') as HTMLElement)?.resize();
|
||||||
|
echarts.getInstanceByDom(document.getElementById('loadIOChart') as HTMLElement)?.resize();
|
||||||
|
echarts.getInstanceByDom(document.getElementById('loadNetworkChart') as HTMLElement)?.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
zoomStart.value = dateFromatWithoutYear(new Date(new Date().setHours(0, 0, 0, 0)));
|
||||||
|
loadNetworkOptions();
|
||||||
|
window.addEventListener('resize', changeChartSize);
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', changeChartSize);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -113,7 +113,7 @@ const batchDelete = async (row: Command.CommandInfo | null) => {
|
||||||
} else {
|
} else {
|
||||||
ids.push(row.id);
|
ids.push(row.id);
|
||||||
}
|
}
|
||||||
await useDeleteData(deleteCommand, { ids: ids }, 'commons.msg.delete');
|
await useDeleteData(deleteCommand, { ids: ids }, 'commons.msg.delete', true);
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -265,10 +265,10 @@ const onDelete = async (node: Node, data: Tree) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node.level === 1) {
|
if (node.level === 1) {
|
||||||
await useDeleteData(deleteGroup, data.id - 10000, i18n.global.t('terminal.groupDeleteHelper'));
|
await useDeleteData(deleteGroup, data.id - 10000, i18n.global.t('terminal.groupDeleteHelper'), true);
|
||||||
loadGroups();
|
loadGroups();
|
||||||
} else {
|
} else {
|
||||||
await useDeleteData(deleteHost, data.id, 'commons.msg.delete');
|
await useDeleteData(deleteHost, data.id, 'commons.msg.delete', true);
|
||||||
}
|
}
|
||||||
loadHostTree();
|
loadHostTree();
|
||||||
loadGroups();
|
loadGroups();
|
||||||
|
|
|
@ -174,7 +174,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onBeforeMount, ref, watch, nextTick, reactive, getCurrentInstance } from 'vue';
|
import { onMounted, onBeforeMount, ref, watch, reactive, getCurrentInstance } from 'vue';
|
||||||
import { Rules } from '@/global/form-rues';
|
import { Rules } from '@/global/form-rues';
|
||||||
import { testConn, getHostTree, addHost } from '@/api/modules/host';
|
import { testConn, getHostTree, addHost } from '@/api/modules/host';
|
||||||
import { getCommandList } from '@/api/modules/command';
|
import { getCommandList } from '@/api/modules/command';
|
||||||
|
@ -396,13 +396,6 @@ const onConnLocal = () => {
|
||||||
terminalValue.value = `127.0.0.1-${tabIndex}`;
|
terminalValue.value = `127.0.0.1-${tabIndex}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
function changeFrameHeight() {
|
|
||||||
let ifm = document.getElementById('iframeTerminal') as HTMLInputElement | null;
|
|
||||||
if (ifm) {
|
|
||||||
ifm.style.height = document.documentElement.clientHeight - 300 + 'px';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncTerminal() {
|
function syncTerminal() {
|
||||||
for (const terminal of terminalTabs.value) {
|
for (const terminal of terminalTabs.value) {
|
||||||
if (ctx && ctx.refs[`Ref${terminal.key}`][0]) {
|
if (ctx && ctx.refs[`Ref${terminal.key}`][0]) {
|
||||||
|
@ -413,10 +406,6 @@ function syncTerminal() {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
onConnLocal();
|
onConnLocal();
|
||||||
nextTick(() => {
|
|
||||||
changeFrameHeight();
|
|
||||||
window.addEventListener('resize', changeFrameHeight);
|
|
||||||
});
|
|
||||||
loadHost();
|
loadHost();
|
||||||
loadCommand();
|
loadCommand();
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue