feat: 添加导出所有学生配置功能,优化提示信息
This commit is contained in:
@@ -44,7 +44,7 @@ export function ptContrastAsDefault(params: Record<string, any>) {
|
|||||||
* @param student 仅教师 student
|
* @param student 仅教师 student
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export function ptExport(student: string|undefined) {
|
export function ptExport(student: string | undefined) {
|
||||||
return request({
|
return request({
|
||||||
url: `/pt/neConfigData/export`,
|
url: `/pt/neConfigData/export`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@@ -54,6 +54,19 @@ export function ptExport(student: string|undefined) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置数据导出Excel (仅教师全量)
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function ptExportAll() {
|
||||||
|
return request({
|
||||||
|
url: `/pt/neConfigData/export-all`,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 180_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网元参数配置信息
|
* 网元参数配置信息
|
||||||
* @param params 数据 {neType,paramName}
|
* @param params 数据 {neType,paramName}
|
||||||
|
|||||||
@@ -514,13 +514,17 @@ export default {
|
|||||||
ptDiffRest: 'Restore this version',
|
ptDiffRest: 'Restore this version',
|
||||||
ptHistory: 'History',
|
ptHistory: 'History',
|
||||||
ptReset: 'Reset To Example',
|
ptReset: 'Reset To Example',
|
||||||
|
ptResetTip: 'Confirmed to reset to the sample configuration?',
|
||||||
ptLoad: 'Load Current Configuration',
|
ptLoad: 'Load Current Configuration',
|
||||||
|
ptLoadTip: 'Confirm that you want to load the current network element configuration?',
|
||||||
ptExport: "Export Excel",
|
ptExport: "Export Excel",
|
||||||
ptExportTip: "Exporting NE Configuration Data to an Excel file",
|
ptExportTip: "Confirm that you want to export the network element configuration data to an Excel file?",
|
||||||
|
ptExportAll: "导出所有学生配置",
|
||||||
ptApplyShow: 'View Student',
|
ptApplyShow: 'View Student',
|
||||||
ptApply: 'request',
|
ptApply: 'request',
|
||||||
ptApplyNE: 'Application To NE',
|
ptApplyNE: 'Application To NE',
|
||||||
ptApplyStu: 'Application To {ne}',
|
ptApplyStu: 'Application To {ne}',
|
||||||
|
ptApplyStuTip: 'Confirm that you want to initiate a Configure Application to {ne} request to the teacher?',
|
||||||
ptApplyStuRack: 'Return Request',
|
ptApplyStuRack: 'Return Request',
|
||||||
ptApplyStuNE: 'Application Request',
|
ptApplyStuNE: 'Application Request',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -514,13 +514,17 @@ export default {
|
|||||||
ptDiffRest: '还原此版本',
|
ptDiffRest: '还原此版本',
|
||||||
ptHistory: '历史记录',
|
ptHistory: '历史记录',
|
||||||
ptReset: '重置为示例',
|
ptReset: '重置为示例',
|
||||||
|
ptResetTip: '确认要重置为示例配置吗?',
|
||||||
ptLoad: '载入当前网元配置',
|
ptLoad: '载入当前网元配置',
|
||||||
|
ptLoadTip: '确认要载入当前网元配置吗?',
|
||||||
ptExport: "导出Excel",
|
ptExport: "导出Excel",
|
||||||
ptExportTip: "导出网元配置数据到Excel文件中",
|
ptExportTip: "确认要导出网元配置数据到Excel文件中吗?",
|
||||||
|
ptExportAll: "导出所有学生配置",
|
||||||
ptApplyShow: '查看学生',
|
ptApplyShow: '查看学生',
|
||||||
ptApply: '申请',
|
ptApply: '申请',
|
||||||
ptApplyNE: '应用配置到网元',
|
ptApplyNE: '应用配置到网元',
|
||||||
ptApplyStu: '申请配置应用到 {ne}',
|
ptApplyStu: '申请配置应用到 {ne}',
|
||||||
|
ptApplyStuTip: '确认要向教师发起配置应用到 {ne} 的申请吗?',
|
||||||
ptApplyStuRack: '退回该学生配置',
|
ptApplyStuRack: '退回该学生配置',
|
||||||
ptApplyStuNE: '应用该学生配置',
|
ptApplyStuNE: '应用该学生配置',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
updatePtNeConfigApply,
|
updatePtNeConfigApply,
|
||||||
} from '@/api/pt/neConfigApply';
|
} from '@/api/pt/neConfigApply';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { hasRoles } from '@/plugins/auth-user';
|
import { Modal } from 'ant-design-vue/es';
|
||||||
import { message } from 'ant-design-vue/lib';
|
import { message } from 'ant-design-vue/lib';
|
||||||
import { computed, onMounted, reactive } from 'vue';
|
import { computed, reactive } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实训教学函数
|
* 实训教学函数
|
||||||
@@ -22,48 +22,60 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
});
|
});
|
||||||
/**(管理员)保存网元下所有配置为示例配置 */
|
/**(管理员)保存网元下所有配置为示例配置 */
|
||||||
function ptConfigSave(neType: string) {
|
function ptConfigSave(neType: string) {
|
||||||
ptConfigState.saveLoading = true;
|
Modal.confirm({
|
||||||
ptSaveAsDefault(neType, '001')
|
title: t('common.tipTitle'),
|
||||||
.then(res => {
|
content: t('views.configManage.configParamForm.ptLoadTip'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
onOk() {
|
||||||
message.success({
|
ptConfigState.saveLoading = true;
|
||||||
content: t('common.operateOk'),
|
ptSaveAsDefault(neType, '001')
|
||||||
duration: 3,
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
ptConfigState.saveLoading = false;
|
||||||
|
fnActiveConfigNode('#');
|
||||||
});
|
});
|
||||||
} else {
|
},
|
||||||
message.error({
|
});
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.saveLoading = false;
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**重置网元下所有配置 */
|
/**重置网元下所有配置 */
|
||||||
function ptConfigReset(neType: string) {
|
function ptConfigReset(neType: string) {
|
||||||
ptConfigState.restLoading = true;
|
Modal.confirm({
|
||||||
ptResetAsDefault(neType)
|
title: t('common.tipTitle'),
|
||||||
.then(res => {
|
content: t('views.configManage.configParamForm.ptResetTip'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
onOk() {
|
||||||
message.success({
|
ptConfigState.restLoading = true;
|
||||||
content: t('common.operateOk'),
|
ptResetAsDefault(neType)
|
||||||
duration: 3,
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
ptConfigState.restLoading = false;
|
||||||
|
fnActiveConfigNode('#');
|
||||||
});
|
});
|
||||||
} else {
|
},
|
||||||
message.error({
|
});
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.restLoading = false;
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**配置下方应用(学生)申请撤回和(管理/教师)应用退回 */
|
/**配置下方应用(学生)申请撤回和(管理/教师)应用退回 */
|
||||||
@@ -97,33 +109,42 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
result = stuPtNeConfigApply({ neType, status });
|
result = stuPtNeConfigApply({ neType, status });
|
||||||
}
|
}
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
ptConfigState.applyLoading = true;
|
|
||||||
result
|
Modal.confirm({
|
||||||
.then((res: any) => {
|
title: t('common.tipTitle'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
content: t('views.configManage.configParamForm.ptApplyStuTip', {
|
||||||
message.success({
|
ne: neType,
|
||||||
content: t('common.operateOk'),
|
}),
|
||||||
duration: 3,
|
onOk() {
|
||||||
});
|
ptConfigState.applyLoading = true;
|
||||||
// 教师修改学生时改变状态
|
result
|
||||||
if (student) {
|
.then((res: any) => {
|
||||||
const item = classState.studentOptionsDef.find(
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
s => s.value === classState.student
|
message.success({
|
||||||
);
|
content: t('common.operateOk'),
|
||||||
if (item) {
|
duration: 3,
|
||||||
item.applyStatus = status;
|
});
|
||||||
|
// 教师修改学生时改变状态
|
||||||
|
if (student) {
|
||||||
|
const item = classState.studentOptionsDef.find(
|
||||||
|
s => s.value === classState.student
|
||||||
|
);
|
||||||
|
if (item) {
|
||||||
|
item.applyStatus = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} else {
|
.finally(() => {
|
||||||
message.error({
|
ptConfigState.applyLoading = false;
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.applyLoading = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const classState = reactive<{
|
const classState = reactive<{
|
||||||
@@ -148,13 +169,6 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
studentOptionsDef: [],
|
studentOptionsDef: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 仅教师加载
|
|
||||||
if (hasRoles(['teacher'])) {
|
|
||||||
onMounted(() => {
|
|
||||||
classStudents(); // 初始学生列表
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**学生选择搜索 */
|
/**学生选择搜索 */
|
||||||
function studentChange(v: any) {
|
function studentChange(v: any) {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
@@ -166,7 +180,7 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
let timeout: any;
|
let timeout: any;
|
||||||
|
|
||||||
/**学生选择搜索 */
|
/**学生选择搜索 */
|
||||||
function studentSearch(val: string) {
|
function studentSearch(neType: string, val: string) {
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
timeout = null;
|
timeout = null;
|
||||||
@@ -175,12 +189,12 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timeout = setTimeout(() => classStudents(val), 500);
|
timeout = setTimeout(() => classStudents(neType, val), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**班级学生列表 */
|
/**班级学生列表 */
|
||||||
function classStudents(val?: string) {
|
function classStudents(neType: string, val?: string) {
|
||||||
getPtClassStudents({ userName: val }).then(res => {
|
getPtClassStudents({ neType, userName: val }).then(res => {
|
||||||
classState.studentOptions = [];
|
classState.studentOptions = [];
|
||||||
if (!Array.isArray(res.data) || res.data.length <= 0) {
|
if (!Array.isArray(res.data) || res.data.length <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -221,6 +235,7 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
ptConfigReset,
|
ptConfigReset,
|
||||||
ptConfigApply,
|
ptConfigApply,
|
||||||
classState,
|
classState,
|
||||||
|
classStudents,
|
||||||
studentStatus,
|
studentStatus,
|
||||||
studentSearch,
|
studentSearch,
|
||||||
studentChange,
|
studentChange,
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, toRaw, watch, defineAsyncComponent } from 'vue';
|
import {
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
toRaw,
|
||||||
|
watch,
|
||||||
|
defineAsyncComponent,
|
||||||
|
} from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
import { ProModal } from 'antdv-pro-modal';
|
||||||
import { message, Modal } from 'ant-design-vue/es';
|
import { message, Modal } from 'ant-design-vue/es';
|
||||||
@@ -18,8 +25,10 @@ import {
|
|||||||
getPtNeConfigData,
|
getPtNeConfigData,
|
||||||
ptContrastAsDefault,
|
ptContrastAsDefault,
|
||||||
ptExport,
|
ptExport,
|
||||||
|
ptExportAll,
|
||||||
} from '@/api/pt/neConfig';
|
} from '@/api/pt/neConfig';
|
||||||
import { isSystemAdmin, hasRoles } from '@/plugins/auth-user';const neInfoStore = useNeInfoStore();
|
import { isSystemAdmin, hasRoles } from '@/plugins/auth-user';
|
||||||
|
const neInfoStore = useNeInfoStore();
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { ruleVerification, smfByUPFIdLoadData, smfByUPFIdOptions } = useOptions({
|
const { ruleVerification, smfByUPFIdLoadData, smfByUPFIdOptions } = useOptions({
|
||||||
@@ -232,35 +241,42 @@ function fnGetNeConfig() {
|
|||||||
|
|
||||||
treeState.loading = true;
|
treeState.loading = true;
|
||||||
// 获取数据
|
// 获取数据
|
||||||
getAllNeConfig(neType).then(res => {
|
getAllNeConfig(neType)
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
.then(res => {
|
||||||
const arr = [];
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
for (const item of res.data) {
|
const arr = [];
|
||||||
let paramPerms: string[] = [];
|
for (const item of res.data) {
|
||||||
if (item.paramPerms) {
|
let paramPerms: string[] = [];
|
||||||
paramPerms = item.paramPerms.split(',');
|
if (item.paramPerms) {
|
||||||
} else {
|
paramPerms = item.paramPerms.split(',');
|
||||||
paramPerms = ['post', 'put', 'delete'];
|
} else {
|
||||||
|
paramPerms = ['post', 'put', 'delete'];
|
||||||
|
}
|
||||||
|
arr.push({
|
||||||
|
...item,
|
||||||
|
children: undefined,
|
||||||
|
title: item.paramDisplay,
|
||||||
|
key: item.paramName,
|
||||||
|
paramPerms,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
treeState.data = arr;
|
||||||
|
treeState.loading = false;
|
||||||
|
// 取首个tag
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
const item = JSON.parse(JSON.stringify(treeState.data[0]));
|
||||||
|
treeState.selectNode = item;
|
||||||
|
treeState.selectLoading = false;
|
||||||
|
fnActiveConfigNode(item.key);
|
||||||
}
|
}
|
||||||
arr.push({
|
|
||||||
...item,
|
|
||||||
children: undefined,
|
|
||||||
title: item.paramDisplay,
|
|
||||||
key: item.paramName,
|
|
||||||
paramPerms,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
treeState.data = arr;
|
})
|
||||||
treeState.loading = false;
|
.finally(() => {
|
||||||
// 取首个tag
|
// 仅教师加载
|
||||||
if (res.data.length > 0) {
|
if (hasRoles(['teacher'])) {
|
||||||
const item = JSON.parse(JSON.stringify(treeState.data[0]));
|
classStudents(neType);
|
||||||
treeState.selectNode = item;
|
|
||||||
treeState.selectLoading = false;
|
|
||||||
fnActiveConfigNode(item.key);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**对话框对象信息状态类型 */
|
/**对话框对象信息状态类型 */
|
||||||
@@ -344,6 +360,7 @@ const {
|
|||||||
studentStatus,
|
studentStatus,
|
||||||
studentSearch,
|
studentSearch,
|
||||||
studentChange,
|
studentChange,
|
||||||
|
classStudents,
|
||||||
} = usePtOptions({ t, fnActiveConfigNode });
|
} = usePtOptions({ t, fnActiveConfigNode });
|
||||||
|
|
||||||
const { tablePagination, listState, listEdit, listEditClose, listEditOk } =
|
const { tablePagination, listState, listEdit, listEditClose, listEditOk } =
|
||||||
@@ -450,6 +467,35 @@ function fnDataExport() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 数据导出Excel
|
||||||
|
function fnDataExportAll() {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.configManage.configParamForm.ptExportTip'),
|
||||||
|
onOk() {
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
ptExportAll()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
saveAs(res.data, `students_config_data_${Date.now()}.zip`);
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
@@ -500,7 +546,7 @@ onMounted(() => {
|
|||||||
<a-col :lg="8" :md="12" :xs="24" v-roles:has="['teacher']">
|
<a-col :lg="8" :md="12" :xs="24" v-roles:has="['teacher']">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.configManage.configParamForm.ptApplyShow')"
|
:label="t('views.configManage.configParamForm.ptApplyShow')"
|
||||||
name="neType "
|
name="student "
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="classState.student"
|
v-model:value="classState.student"
|
||||||
@@ -512,7 +558,7 @@ onMounted(() => {
|
|||||||
:filter-option="false"
|
:filter-option="false"
|
||||||
:not-found-content="null"
|
:not-found-content="null"
|
||||||
:options="classState.studentOptions"
|
:options="classState.studentOptions"
|
||||||
@search="studentSearch"
|
@search="(v:any)=> studentSearch(treeState.neType, v)"
|
||||||
@change="studentChange"
|
@change="studentChange"
|
||||||
>
|
>
|
||||||
<template #option="{ value, label, applyStatus }">
|
<template #option="{ value, label, applyStatus }">
|
||||||
@@ -586,6 +632,9 @@ onMounted(() => {
|
|||||||
<a-button @click="fnDataExport()" v-roles:has="['teacher']">
|
<a-button @click="fnDataExport()" v-roles:has="['teacher']">
|
||||||
{{ t('views.configManage.configParamForm.ptExport') }}
|
{{ t('views.configManage.configParamForm.ptExport') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button @click="fnDataExportAll()" v-roles:has="['teacher']">
|
||||||
|
{{ t('views.configManage.configParamForm.ptExportAll') }}
|
||||||
|
</a-button>
|
||||||
|
|
||||||
<!-- 学生 -->
|
<!-- 学生 -->
|
||||||
<a-button
|
<a-button
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@ export function ptContrastAsDefault(params: Record<string, any>) {
|
|||||||
* @param student 仅教师 student
|
* @param student 仅教师 student
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export function ptExport(student: string|undefined) {
|
export function ptExport(student: string | undefined) {
|
||||||
return request({
|
return request({
|
||||||
url: `/pt/neConfigData/export`,
|
url: `/pt/neConfigData/export`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@@ -54,6 +54,19 @@ export function ptExport(student: string|undefined) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置数据导出Excel (仅教师全量)
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
export function ptExportAll() {
|
||||||
|
return request({
|
||||||
|
url: `/pt/neConfigData/export-all`,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 180_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网元参数配置信息
|
* 网元参数配置信息
|
||||||
* @param params 数据 {neType,paramName}
|
* @param params 数据 {neType,paramName}
|
||||||
|
|||||||
@@ -514,13 +514,17 @@ export default {
|
|||||||
ptDiffRest: 'Restore this version',
|
ptDiffRest: 'Restore this version',
|
||||||
ptHistory: 'History',
|
ptHistory: 'History',
|
||||||
ptReset: 'Reset To Example',
|
ptReset: 'Reset To Example',
|
||||||
|
ptResetTip: 'Confirmed to reset to the sample configuration?',
|
||||||
ptLoad: 'Load Current Configuration',
|
ptLoad: 'Load Current Configuration',
|
||||||
|
ptLoadTip: 'Confirm that you want to load the current network element configuration?',
|
||||||
ptExport: "Export Excel",
|
ptExport: "Export Excel",
|
||||||
ptExportTip: "Exporting NE Configuration Data to an Excel file",
|
ptExportTip: "Confirm that you want to export the network element configuration data to an Excel file?",
|
||||||
|
ptExportAll: "导出所有学生配置",
|
||||||
ptApplyShow: 'View Student',
|
ptApplyShow: 'View Student',
|
||||||
ptApply: 'request',
|
ptApply: 'request',
|
||||||
ptApplyNE: 'Application To NE',
|
ptApplyNE: 'Application To NE',
|
||||||
ptApplyStu: 'Application To {ne}',
|
ptApplyStu: 'Application To {ne}',
|
||||||
|
ptApplyStuTip: 'Confirm that you want to initiate a Configure Application to {ne} request to the teacher?',
|
||||||
ptApplyStuRack: 'Return Request',
|
ptApplyStuRack: 'Return Request',
|
||||||
ptApplyStuNE: 'Application Request',
|
ptApplyStuNE: 'Application Request',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -514,13 +514,17 @@ export default {
|
|||||||
ptDiffRest: '还原此版本',
|
ptDiffRest: '还原此版本',
|
||||||
ptHistory: '历史记录',
|
ptHistory: '历史记录',
|
||||||
ptReset: '重置为示例',
|
ptReset: '重置为示例',
|
||||||
|
ptResetTip: '确认要重置为示例配置吗?',
|
||||||
ptLoad: '载入当前网元配置',
|
ptLoad: '载入当前网元配置',
|
||||||
|
ptLoadTip: '确认要载入当前网元配置吗?',
|
||||||
ptExport: "导出Excel",
|
ptExport: "导出Excel",
|
||||||
ptExportTip: "导出网元配置数据到Excel文件中",
|
ptExportTip: "确认要导出网元配置数据到Excel文件中吗?",
|
||||||
|
ptExportAll: "导出所有学生配置",
|
||||||
ptApplyShow: '查看学生',
|
ptApplyShow: '查看学生',
|
||||||
ptApply: '申请',
|
ptApply: '申请',
|
||||||
ptApplyNE: '应用配置到网元',
|
ptApplyNE: '应用配置到网元',
|
||||||
ptApplyStu: '申请配置应用到 {ne}',
|
ptApplyStu: '申请配置应用到 {ne}',
|
||||||
|
ptApplyStuTip: '确认要向教师发起配置应用到 {ne} 的申请吗?',
|
||||||
ptApplyStuRack: '退回该学生配置',
|
ptApplyStuRack: '退回该学生配置',
|
||||||
ptApplyStuNE: '应用该学生配置',
|
ptApplyStuNE: '应用该学生配置',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
updatePtNeConfigApply,
|
updatePtNeConfigApply,
|
||||||
} from '@/api/pt/neConfigApply';
|
} from '@/api/pt/neConfigApply';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { hasRoles } from '@/plugins/auth-user';
|
import { Modal } from 'ant-design-vue/es';
|
||||||
import { message } from 'ant-design-vue/lib';
|
import { message } from 'ant-design-vue/lib';
|
||||||
import { computed, onMounted, reactive } from 'vue';
|
import { computed, reactive } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实训教学函数
|
* 实训教学函数
|
||||||
@@ -22,48 +22,60 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
});
|
});
|
||||||
/**(管理员)保存网元下所有配置为示例配置 */
|
/**(管理员)保存网元下所有配置为示例配置 */
|
||||||
function ptConfigSave(neType: string) {
|
function ptConfigSave(neType: string) {
|
||||||
ptConfigState.saveLoading = true;
|
Modal.confirm({
|
||||||
ptSaveAsDefault(neType, '001')
|
title: t('common.tipTitle'),
|
||||||
.then(res => {
|
content: t('views.configManage.configParamForm.ptLoadTip'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
onOk() {
|
||||||
message.success({
|
ptConfigState.saveLoading = true;
|
||||||
content: t('common.operateOk'),
|
ptSaveAsDefault(neType, '001')
|
||||||
duration: 3,
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
ptConfigState.saveLoading = false;
|
||||||
|
fnActiveConfigNode('#');
|
||||||
});
|
});
|
||||||
} else {
|
},
|
||||||
message.error({
|
});
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.saveLoading = false;
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**重置网元下所有配置 */
|
/**重置网元下所有配置 */
|
||||||
function ptConfigReset(neType: string) {
|
function ptConfigReset(neType: string) {
|
||||||
ptConfigState.restLoading = true;
|
Modal.confirm({
|
||||||
ptResetAsDefault(neType)
|
title: t('common.tipTitle'),
|
||||||
.then(res => {
|
content: t('views.configManage.configParamForm.ptResetTip'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
onOk() {
|
||||||
message.success({
|
ptConfigState.restLoading = true;
|
||||||
content: t('common.operateOk'),
|
ptResetAsDefault(neType)
|
||||||
duration: 3,
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
ptConfigState.restLoading = false;
|
||||||
|
fnActiveConfigNode('#');
|
||||||
});
|
});
|
||||||
} else {
|
},
|
||||||
message.error({
|
});
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.restLoading = false;
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**配置下方应用(学生)申请撤回和(管理/教师)应用退回 */
|
/**配置下方应用(学生)申请撤回和(管理/教师)应用退回 */
|
||||||
@@ -97,33 +109,42 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
result = stuPtNeConfigApply({ neType, status });
|
result = stuPtNeConfigApply({ neType, status });
|
||||||
}
|
}
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
ptConfigState.applyLoading = true;
|
|
||||||
result
|
Modal.confirm({
|
||||||
.then((res: any) => {
|
title: t('common.tipTitle'),
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
content: t('views.configManage.configParamForm.ptApplyStuTip', {
|
||||||
message.success({
|
ne: neType,
|
||||||
content: t('common.operateOk'),
|
}),
|
||||||
duration: 3,
|
onOk() {
|
||||||
});
|
ptConfigState.applyLoading = true;
|
||||||
// 教师修改学生时改变状态
|
result
|
||||||
if (student) {
|
.then((res: any) => {
|
||||||
const item = classState.studentOptionsDef.find(
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
s => s.value === classState.student
|
message.success({
|
||||||
);
|
content: t('common.operateOk'),
|
||||||
if (item) {
|
duration: 3,
|
||||||
item.applyStatus = status;
|
});
|
||||||
|
// 教师修改学生时改变状态
|
||||||
|
if (student) {
|
||||||
|
const item = classState.studentOptionsDef.find(
|
||||||
|
s => s.value === classState.student
|
||||||
|
);
|
||||||
|
if (item) {
|
||||||
|
item.applyStatus = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} else {
|
.finally(() => {
|
||||||
message.error({
|
ptConfigState.applyLoading = false;
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
.finally(() => {
|
|
||||||
ptConfigState.applyLoading = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const classState = reactive<{
|
const classState = reactive<{
|
||||||
@@ -148,13 +169,6 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
studentOptionsDef: [],
|
studentOptionsDef: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 仅教师加载
|
|
||||||
if (hasRoles(['teacher'])) {
|
|
||||||
onMounted(() => {
|
|
||||||
classStudents(); // 初始学生列表
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**学生选择搜索 */
|
/**学生选择搜索 */
|
||||||
function studentChange(v: any) {
|
function studentChange(v: any) {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
@@ -166,7 +180,7 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
let timeout: any;
|
let timeout: any;
|
||||||
|
|
||||||
/**学生选择搜索 */
|
/**学生选择搜索 */
|
||||||
function studentSearch(val: string) {
|
function studentSearch(neType: string, val: string) {
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
timeout = null;
|
timeout = null;
|
||||||
@@ -175,12 +189,12 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timeout = setTimeout(() => classStudents(val), 500);
|
timeout = setTimeout(() => classStudents(neType, val), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**班级学生列表 */
|
/**班级学生列表 */
|
||||||
function classStudents(val?: string) {
|
function classStudents(neType: string, val?: string) {
|
||||||
getPtClassStudents({ userName: val }).then(res => {
|
getPtClassStudents({ neType, userName: val }).then(res => {
|
||||||
classState.studentOptions = [];
|
classState.studentOptions = [];
|
||||||
if (!Array.isArray(res.data) || res.data.length <= 0) {
|
if (!Array.isArray(res.data) || res.data.length <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -221,6 +235,7 @@ export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
|||||||
ptConfigReset,
|
ptConfigReset,
|
||||||
ptConfigApply,
|
ptConfigApply,
|
||||||
classState,
|
classState,
|
||||||
|
classStudents,
|
||||||
studentStatus,
|
studentStatus,
|
||||||
studentSearch,
|
studentSearch,
|
||||||
studentChange,
|
studentChange,
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, toRaw, watch, defineAsyncComponent } from 'vue';
|
import {
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
toRaw,
|
||||||
|
watch,
|
||||||
|
defineAsyncComponent,
|
||||||
|
} from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
import { ProModal } from 'antdv-pro-modal';
|
||||||
import { message, Modal } from 'ant-design-vue/es';
|
import { message, Modal } from 'ant-design-vue/es';
|
||||||
@@ -18,8 +25,10 @@ import {
|
|||||||
getPtNeConfigData,
|
getPtNeConfigData,
|
||||||
ptContrastAsDefault,
|
ptContrastAsDefault,
|
||||||
ptExport,
|
ptExport,
|
||||||
|
ptExportAll,
|
||||||
} from '@/api/pt/neConfig';
|
} from '@/api/pt/neConfig';
|
||||||
import { isSystemAdmin, hasRoles } from '@/plugins/auth-user';const neInfoStore = useNeInfoStore();
|
import { isSystemAdmin, hasRoles } from '@/plugins/auth-user';
|
||||||
|
const neInfoStore = useNeInfoStore();
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { ruleVerification, smfByUPFIdLoadData, smfByUPFIdOptions } = useOptions({
|
const { ruleVerification, smfByUPFIdLoadData, smfByUPFIdOptions } = useOptions({
|
||||||
@@ -232,35 +241,42 @@ function fnGetNeConfig() {
|
|||||||
|
|
||||||
treeState.loading = true;
|
treeState.loading = true;
|
||||||
// 获取数据
|
// 获取数据
|
||||||
getAllNeConfig(neType).then(res => {
|
getAllNeConfig(neType)
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
.then(res => {
|
||||||
const arr = [];
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
for (const item of res.data) {
|
const arr = [];
|
||||||
let paramPerms: string[] = [];
|
for (const item of res.data) {
|
||||||
if (item.paramPerms) {
|
let paramPerms: string[] = [];
|
||||||
paramPerms = item.paramPerms.split(',');
|
if (item.paramPerms) {
|
||||||
} else {
|
paramPerms = item.paramPerms.split(',');
|
||||||
paramPerms = ['post', 'put', 'delete'];
|
} else {
|
||||||
|
paramPerms = ['post', 'put', 'delete'];
|
||||||
|
}
|
||||||
|
arr.push({
|
||||||
|
...item,
|
||||||
|
children: undefined,
|
||||||
|
title: item.paramDisplay,
|
||||||
|
key: item.paramName,
|
||||||
|
paramPerms,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
treeState.data = arr;
|
||||||
|
treeState.loading = false;
|
||||||
|
// 取首个tag
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
const item = JSON.parse(JSON.stringify(treeState.data[0]));
|
||||||
|
treeState.selectNode = item;
|
||||||
|
treeState.selectLoading = false;
|
||||||
|
fnActiveConfigNode(item.key);
|
||||||
}
|
}
|
||||||
arr.push({
|
|
||||||
...item,
|
|
||||||
children: undefined,
|
|
||||||
title: item.paramDisplay,
|
|
||||||
key: item.paramName,
|
|
||||||
paramPerms,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
treeState.data = arr;
|
})
|
||||||
treeState.loading = false;
|
.finally(() => {
|
||||||
// 取首个tag
|
// 仅教师加载
|
||||||
if (res.data.length > 0) {
|
if (hasRoles(['teacher'])) {
|
||||||
const item = JSON.parse(JSON.stringify(treeState.data[0]));
|
classStudents(neType);
|
||||||
treeState.selectNode = item;
|
|
||||||
treeState.selectLoading = false;
|
|
||||||
fnActiveConfigNode(item.key);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**对话框对象信息状态类型 */
|
/**对话框对象信息状态类型 */
|
||||||
@@ -344,6 +360,7 @@ const {
|
|||||||
studentStatus,
|
studentStatus,
|
||||||
studentSearch,
|
studentSearch,
|
||||||
studentChange,
|
studentChange,
|
||||||
|
classStudents,
|
||||||
} = usePtOptions({ t, fnActiveConfigNode });
|
} = usePtOptions({ t, fnActiveConfigNode });
|
||||||
|
|
||||||
const { tablePagination, listState, listEdit, listEditClose, listEditOk } =
|
const { tablePagination, listState, listEdit, listEditClose, listEditOk } =
|
||||||
@@ -450,6 +467,35 @@ function fnDataExport() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 数据导出Excel
|
||||||
|
function fnDataExportAll() {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('common.tipTitle'),
|
||||||
|
content: t('views.configManage.configParamForm.ptExportTip'),
|
||||||
|
onOk() {
|
||||||
|
const hide = message.loading(t('common.loading'), 0);
|
||||||
|
ptExportAll()
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
|
message.success({
|
||||||
|
content: t('common.operateOk'),
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
saveAs(res.data, `students_config_data_${Date.now()}.zip`);
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `${res.msg}`,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hide();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
@@ -500,7 +546,7 @@ onMounted(() => {
|
|||||||
<a-col :lg="8" :md="12" :xs="24" v-roles:has="['teacher']">
|
<a-col :lg="8" :md="12" :xs="24" v-roles:has="['teacher']">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.configManage.configParamForm.ptApplyShow')"
|
:label="t('views.configManage.configParamForm.ptApplyShow')"
|
||||||
name="neType "
|
name="student "
|
||||||
>
|
>
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="classState.student"
|
v-model:value="classState.student"
|
||||||
@@ -512,7 +558,7 @@ onMounted(() => {
|
|||||||
:filter-option="false"
|
:filter-option="false"
|
||||||
:not-found-content="null"
|
:not-found-content="null"
|
||||||
:options="classState.studentOptions"
|
:options="classState.studentOptions"
|
||||||
@search="studentSearch"
|
@search="(v:any)=> studentSearch(treeState.neType, v)"
|
||||||
@change="studentChange"
|
@change="studentChange"
|
||||||
>
|
>
|
||||||
<template #option="{ value, label, applyStatus }">
|
<template #option="{ value, label, applyStatus }">
|
||||||
@@ -586,6 +632,9 @@ onMounted(() => {
|
|||||||
<a-button @click="fnDataExport()" v-roles:has="['teacher']">
|
<a-button @click="fnDataExport()" v-roles:has="['teacher']">
|
||||||
{{ t('views.configManage.configParamForm.ptExport') }}
|
{{ t('views.configManage.configParamForm.ptExport') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button @click="fnDataExportAll()" v-roles:has="['teacher']">
|
||||||
|
{{ t('views.configManage.configParamForm.ptExportAll') }}
|
||||||
|
</a-button>
|
||||||
|
|
||||||
<!-- 学生 -->
|
<!-- 学生 -->
|
||||||
<a-button
|
<a-button
|
||||||
|
|||||||
@@ -2,7 +2,14 @@
|
|||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||||
import { message } from 'ant-design-vue/es';
|
import { message } from 'ant-design-vue/es';
|
||||||
import { reactive, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
|
import {
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
markRaw,
|
||||||
|
useTemplateRef,
|
||||||
|
} from 'vue';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { TooltipComponent } from 'echarts/components';
|
import { TooltipComponent } from 'echarts/components';
|
||||||
import { GaugeChart } from 'echarts/charts';
|
import { GaugeChart } from 'echarts/charts';
|
||||||
@@ -32,24 +39,12 @@ echarts.use([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
/**图DOM节点实例对象 */
|
||||||
const statusBar = ref<HTMLElement | undefined>(undefined);
|
const statusBar = useTemplateRef<HTMLDivElement>('statusBar');
|
||||||
|
|
||||||
/**图实例对象 */
|
/**图实例对象 */
|
||||||
const statusBarChart = ref<any>(null);
|
const statusBarChart = ref<any>(null);
|
||||||
|
|
||||||
/**网元状态字典数据 */
|
|
||||||
let indexColor = ref<DictType[]>([
|
|
||||||
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
|
|
||||||
{
|
|
||||||
label: 'Abnormal',
|
|
||||||
value: 'abnormal',
|
|
||||||
tagType: '',
|
|
||||||
tagClass: '#ee6666',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
//customRender(){} ----单元格处理
|
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
{
|
{
|
||||||
title: t('views.index.object'),
|
title: t('views.index.object'),
|
||||||
@@ -67,7 +62,9 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'serverState',
|
dataIndex: 'serverState',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
if (opt.value?.refreshTime) return parseDateToStr(opt.value?.refreshTime);
|
if (opt.value?.refreshTime) {
|
||||||
|
return parseDateToStr(opt.value?.refreshTime, 'HH:mm:ss');
|
||||||
|
}
|
||||||
return '-';
|
return '-';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -104,12 +101,13 @@ let tableColumns: ColumnsType = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**表格状态类型 */
|
/**表格状态类型 */
|
||||||
type TabeStateType = {
|
type TabeStateType = {
|
||||||
/**加载等待 */
|
/**加载等待 */
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
/**记录数据 */
|
/**记录数据 */
|
||||||
data: object[];
|
data: Record<string, any>[];
|
||||||
/**勾选记录 */
|
/**勾选记录 */
|
||||||
selectedRowKeys: (string | number)[];
|
selectedRowKeys: (string | number)[];
|
||||||
};
|
};
|
||||||
@@ -121,114 +119,92 @@ let tableState: TabeStateType = reactive({
|
|||||||
selectedRowKeys: [],
|
selectedRowKeys: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**表格状态 */
|
/**状态 */
|
||||||
let nfInfo: any = reactive({
|
let serverState: any = ref({});
|
||||||
obj: 'OMC',
|
|
||||||
version: appStore.version,
|
|
||||||
status: t('views.index.normal'),
|
|
||||||
outTimeDate: '',
|
|
||||||
serialNum: appStore.serialNum,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type nfStateType = {
|
|
||||||
/**主机名 */
|
|
||||||
hostName: string;
|
|
||||||
/**操作系统信息 */
|
|
||||||
osInfo: string;
|
|
||||||
/**IP地址 */
|
|
||||||
ipAddress: string;
|
|
||||||
/**版本 */
|
|
||||||
version: string;
|
|
||||||
/**CPU利用率 */
|
|
||||||
cpuUse: string;
|
|
||||||
/**内存使用 */
|
|
||||||
memoryUse: string;
|
|
||||||
/**用户容量 */
|
|
||||||
capability: number;
|
|
||||||
/**序列号 */
|
|
||||||
serialNum: string;
|
|
||||||
/**许可证到期日期 */
|
|
||||||
/* selectedRowKeys: (string | number)[];*/
|
|
||||||
expiryDate: string;
|
|
||||||
};
|
|
||||||
/**网元详细信息 */
|
|
||||||
let pronInfo: nfStateType = reactive({
|
|
||||||
hostName: '5gc',
|
|
||||||
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
|
|
||||||
ipAddress: '-',
|
|
||||||
version: '-',
|
|
||||||
cpuUse: '-',
|
|
||||||
memoryUse: '-',
|
|
||||||
capability: 0,
|
|
||||||
serialNum: '-',
|
|
||||||
expiryDate: '-',
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询网元状态列表 */
|
/**查询网元状态列表 */
|
||||||
function fnGetList(one: boolean) {
|
async function fnGetList(reload: boolean = false) {
|
||||||
if (tableState.loading) return;
|
tableState.loading = !reload;
|
||||||
one && (tableState.loading = true);
|
try {
|
||||||
listAllNeInfo({ bandStatus: true }).then(res => {
|
const res = await listAllNeInfo({ bandStatus: true });
|
||||||
tableState.data = res.data;
|
tableState.data = res.data;
|
||||||
tableState.loading = false;
|
} catch (error) {
|
||||||
var rightNum = 0;
|
console.error(error);
|
||||||
var errorNum = 0;
|
tableState.data = [];
|
||||||
res.data.forEach((item: any) => {
|
}
|
||||||
if (item.serverState.online) {
|
tableState.loading = false;
|
||||||
rightNum++;
|
if (tableState.data.length == 0) {
|
||||||
} else {
|
return;
|
||||||
errorNum++;
|
}
|
||||||
}
|
|
||||||
});
|
var rightNum = 0;
|
||||||
const optionData: any = {
|
var errorNum = 0;
|
||||||
title: {
|
for (const v of tableState.data) {
|
||||||
text: '',
|
if (v?.serverState?.online) {
|
||||||
subtext: '',
|
rightNum++;
|
||||||
left: 'center',
|
} else {
|
||||||
},
|
errorNum++;
|
||||||
tooltip: {
|
}
|
||||||
trigger: 'item',
|
}
|
||||||
},
|
|
||||||
legend: {
|
// 初始
|
||||||
orient: 'vertical',
|
if (!reload) {
|
||||||
left: 'left',
|
// 选择第一个
|
||||||
},
|
if (tableState.data.length > 0) {
|
||||||
color: indexColor.value.map(item => item.tagClass),
|
const id = tableState.data[0].id;
|
||||||
|
fnTableSelectedRowKeys([id]);
|
||||||
|
} else {
|
||||||
|
fnTableSelectedRowKeys(tableState.selectedRowKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusBar.value) {
|
||||||
|
fnDesign(statusBar.value, rightNum, errorNum);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statusBarChart.value.setOption({
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: t('views.index.realNeStatus'),
|
|
||||||
type: 'pie',
|
|
||||||
radius: '70%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
data: [
|
data: [
|
||||||
{ value: rightNum, name: t('views.index.normal') },
|
{ value: rightNum, name: t('views.index.normal') },
|
||||||
{ value: errorNum, name: t('views.index.abnormal') },
|
{ value: errorNum, name: t('views.index.abnormal') },
|
||||||
],
|
],
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
label: {},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
});
|
||||||
|
}
|
||||||
fnDesign(statusBar.value, optionData);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fnDesign(container: HTMLElement | undefined, option: any) {
|
function fnDesign(container: HTMLElement, rightNum: number, errorNum: number) {
|
||||||
if (!container) return;
|
/// 图表数据
|
||||||
|
const optionData: any = {
|
||||||
if (!statusBarChart.value) {
|
title: {
|
||||||
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
text: '',
|
||||||
}
|
subtext: '',
|
||||||
option && statusBarChart.value.setOption(option);
|
left: 'center',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
},
|
||||||
|
color: dict.indexStatus.map(item => item.tagClass),
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: t('views.index.runStatus'),
|
||||||
|
type: 'pie',
|
||||||
|
radius: '70%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
data: [
|
||||||
|
{ value: rightNum, name: t('views.index.normal') },
|
||||||
|
{ value: errorNum, name: t('views.index.abnormal') },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
|
statusBarChart.value.setOption(optionData);
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
// 创建 ResizeObserver 实例
|
||||||
var observer = new ResizeObserver(entries => {
|
var observer = new ResizeObserver(entries => {
|
||||||
@@ -240,66 +216,43 @@ function fnDesign(container: HTMLElement | undefined, option: any) {
|
|||||||
observer.observe(container);
|
observer.observe(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**抽屉 网元详细信息 */
|
/**表格多选 */
|
||||||
const open = ref(false);
|
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||||
const closeDrawer = () => {
|
if (keys.length <= 0) return;
|
||||||
open.value = false;
|
const id = keys[0];
|
||||||
};
|
const row: any = tableState.data.find((item: any) => item.id === id);
|
||||||
/**抽屉 网元详细信息 */
|
if (!row) {
|
||||||
|
message.error(t('views.index.neStatus'), 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const neState = row.serverState;
|
||||||
|
if (!neState?.online) {
|
||||||
|
message.error(t('views.index.neStatus'), 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableState.selectedRowKeys = keys;
|
||||||
|
// Mem 将KB转换为MB
|
||||||
|
// const totalMemInKB = neState.mem?.totalMem;
|
||||||
|
// const nfUsedMemInKB = neState.mem?.nfUsedMem;
|
||||||
|
// const sysMemUsageInKB = neState.mem?.sysMemUsage;
|
||||||
|
// const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
||||||
|
// const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
||||||
|
// const sysMemUsageInMB = Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
||||||
|
|
||||||
/**监听表格行事件*/
|
// CPU
|
||||||
function rowClick(record: any, index: any) {
|
// const nfCpu = neState.cpu?.nfCpuUsage;
|
||||||
return {
|
// const sysCpu = neState.cpu?.sysCpuUsage;
|
||||||
onClick: (event: any) => {
|
// const nfCpuP = Math.round(nfCpu) / 100;
|
||||||
let pronData = JSON.parse(JSON.stringify(record.serverState));
|
// const sysCpuP = Math.round(sysCpu) / 100;
|
||||||
if (!pronData.online) {
|
|
||||||
message.error(t('views.index.neStatus'), 2);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
const totalMemInKB = pronData.mem?.totalMem;
|
|
||||||
const nfUsedMemInKB = pronData.mem?.nfUsedMem;
|
|
||||||
const sysMemUsageInKB = pronData.mem?.sysMemUsage;
|
|
||||||
|
|
||||||
// 将KB转换为MB
|
serverState.value = Object.assign(
|
||||||
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
{
|
||||||
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
// cpuUse: `NE:${nfCpuP}%; SYS:${sysCpuP}%`,
|
||||||
const sysMemUsageInMB =
|
// memoryUse: `Total: ${totalMemInMB}MB; NE: ${nfUsedMemInMB}MB; SYS: ${sysMemUsageInMB}MB`,
|
||||||
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
|
||||||
|
|
||||||
//渲染详细信息
|
|
||||||
pronInfo = {
|
|
||||||
hostName: pronData.hostname,
|
|
||||||
osInfo: pronData.os,
|
|
||||||
ipAddress: pronData.neIP,
|
|
||||||
version: pronData.version,
|
|
||||||
cpuUse:
|
|
||||||
pronData.neName +
|
|
||||||
':' +
|
|
||||||
pronData.cpu?.nfCpuUsage / 100 +
|
|
||||||
'%; ' +
|
|
||||||
'SYS:' +
|
|
||||||
pronData.cpu?.sysCpuUsage / 100 +
|
|
||||||
'%',
|
|
||||||
memoryUse:
|
|
||||||
'Total:' +
|
|
||||||
totalMemInMB +
|
|
||||||
'MB; ' +
|
|
||||||
pronData.name +
|
|
||||||
':' +
|
|
||||||
nfUsedMemInMB +
|
|
||||||
'MB; SYS:' +
|
|
||||||
sysMemUsageInMB +
|
|
||||||
'MB',
|
|
||||||
capability: pronData.capability,
|
|
||||||
serialNum: pronData.sn,
|
|
||||||
expiryDate: pronData.expire,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
open.value = true;
|
|
||||||
},
|
},
|
||||||
};
|
neState
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let timer: any;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 国际化翻译转换
|
* 国际化翻译转换
|
||||||
@@ -312,63 +265,50 @@ function fnLocale() {
|
|||||||
appStore.setTitle(title);
|
appStore.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**字典数据 */
|
||||||
|
let dict: {
|
||||||
|
/**网元信息状态 */
|
||||||
|
neInfoStatus: DictType[];
|
||||||
|
/**主页状态 */
|
||||||
|
indexStatus: DictType[];
|
||||||
|
} = reactive({
|
||||||
|
neInfoStatus: [],
|
||||||
|
indexStatus: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
let timer: any;
|
||||||
|
let timerFlag: boolean = false;
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDict('index_status')
|
// 初始字典数据
|
||||||
.then(res => {
|
Promise.allSettled([getDict('ne_info_status'), getDict('index_status')])
|
||||||
if (res.length > 0) {
|
.then(resArr => {
|
||||||
indexColor.value = res;
|
if (resArr[0].status === 'fulfilled') {
|
||||||
|
dict.neInfoStatus = resArr[0].value;
|
||||||
|
}
|
||||||
|
if (resArr[1].status === 'fulfilled') {
|
||||||
|
dict.indexStatus = resArr[1].value;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(async () => {
|
||||||
fnLocale();
|
fnLocale();
|
||||||
fnGetList(true);
|
await fnGetList(false);
|
||||||
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
|
timer = setInterval(() => {
|
||||||
|
if (timerFlag) return;
|
||||||
|
fnGetList(true);
|
||||||
|
}, 10_000); // 每隔10秒执行一次
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 在组件卸载之前清除定时器
|
// 在组件卸载之前清除定时器
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
|
timer = null;
|
||||||
|
timerFlag = true;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageContainer :breadcrumb="{}">
|
<PageContainer :breadcrumb="{}">
|
||||||
<div>
|
|
||||||
<a-drawer :open="open" @close="closeDrawer" :width="700">
|
|
||||||
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
|
||||||
<a-descriptions-item :label="t('views.index.hostName')">{{
|
|
||||||
pronInfo.hostName
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.osInfo')">{{
|
|
||||||
pronInfo.osInfo
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.ipAddress')">{{
|
|
||||||
pronInfo.ipAddress
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.version')">{{
|
|
||||||
pronInfo.version
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.capability')">{{
|
|
||||||
pronInfo.capability
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.cpuUse')">{{
|
|
||||||
pronInfo.cpuUse
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.memoryUse')">{{
|
|
||||||
pronInfo.memoryUse
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
|
||||||
pronInfo.serialNum
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
|
||||||
pronInfo.expiryDate
|
|
||||||
}}</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
</a-drawer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="14" :md="16" :xs="24">
|
<a-col :lg="14" :md="16" :xs="24">
|
||||||
<!-- 表格列表 -->
|
<!-- 表格列表 -->
|
||||||
@@ -377,20 +317,20 @@ onBeforeUnmount(() => {
|
|||||||
row-key="id"
|
row-key="id"
|
||||||
size="small"
|
size="small"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
|
:loading="tableState.loading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:scroll="{ x: true }"
|
:scroll="{ x: true }"
|
||||||
:customRow="rowClick"
|
:row-selection="{
|
||||||
|
type: 'radio',
|
||||||
|
columnWidth: '48px',
|
||||||
|
selectedRowKeys: tableState.selectedRowKeys,
|
||||||
|
onChange: fnTableSelectedRowKeys,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<div v-if="record.serverState.online">
|
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
||||||
<a-tag color="blue">{{ t('views.index.normal') }}</a-tag>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<a-tag color="pink">{{ t('views.index.abnormal') }}</a-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
@@ -404,7 +344,8 @@ onBeforeUnmount(() => {
|
|||||||
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
||||||
</a-card>
|
</a-card>
|
||||||
<a-card
|
<a-card
|
||||||
:title="t('views.index.mark')"
|
:loading="tableState.loading"
|
||||||
|
:title="`${t('views.index.mark')} - ${serverState.neName || 'OMC'}`"
|
||||||
style="margin-top: 16px"
|
style="margin-top: 16px"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
@@ -413,25 +354,33 @@ onBeforeUnmount(() => {
|
|||||||
:column="1"
|
:column="1"
|
||||||
:label-style="{ width: '160px' }"
|
:label-style="{ width: '160px' }"
|
||||||
>
|
>
|
||||||
<a-descriptions-item :label="t('views.index.object')">{{
|
<a-descriptions-item :label="t('views.index.hostName')">
|
||||||
nfInfo.obj
|
{{ serverState.hostname }}
|
||||||
}}</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<template v-if="nfInfo.obj === 'OMC'">
|
<a-descriptions-item :label="t('views.index.osInfo')">
|
||||||
<a-descriptions-item :label="t('views.index.versionNum')">{{
|
{{ serverState.os }}
|
||||||
nfInfo.version
|
</a-descriptions-item>
|
||||||
}}</a-descriptions-item>
|
<a-descriptions-item :label="t('views.index.ipAddress')">
|
||||||
<a-descriptions-item :label="t('views.index.systemStatus')">{{
|
{{ serverState.neIP }}
|
||||||
nfInfo.status
|
</a-descriptions-item>
|
||||||
}}</a-descriptions-item>
|
<a-descriptions-item :label="t('views.index.version')">
|
||||||
</template>
|
{{ serverState.version }}
|
||||||
<template v-else>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
<a-descriptions-item :label="t('views.index.capability')">
|
||||||
nfInfo.serialNum
|
{{ serverState.capability }}
|
||||||
}}</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
<!-- <a-descriptions-item :label="t('views.index.cpuUse')">
|
||||||
nfInfo.outTimeDate
|
{{ serverState.cpuUse }}
|
||||||
}}</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
</template>
|
<a-descriptions-item :label="t('views.index.memoryUse')">
|
||||||
|
{{ serverState.memoryUse }}
|
||||||
|
</a-descriptions-item> -->
|
||||||
|
<a-descriptions-item :label="t('views.index.serialNum')">
|
||||||
|
{{ serverState.sn }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.expiryDate')">
|
||||||
|
{{ serverState.expire }}
|
||||||
|
</a-descriptions-item>
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ async function fnGetState() {
|
|||||||
graphG6.value.setItemState(neShape, 'neState', ne.serverState.online);
|
graphG6.value.setItemState(neShape, 'neState', ne.serverState.online);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 15_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**查询全部网元数据列表 */
|
/**查询全部网元数据列表 */
|
||||||
|
|||||||
@@ -96,13 +96,13 @@ const graphNodeMenu = new Menu({
|
|||||||
${neState.neName ?? '--'}
|
${neState.neName ?? '--'}
|
||||||
</h3>
|
</h3>
|
||||||
<div id="restart" style="cursor: pointer; margin-bottom: 4px">
|
<div id="restart" style="cursor: pointer; margin-bottom: 4px">
|
||||||
> ${t('views.configManage.neManage.restart')}
|
> ${t('views.ne.common.restart')}
|
||||||
</div>
|
</div>
|
||||||
<div id="stop" style="cursor: pointer; margin-bottom: 4px;">
|
<div id="stop" style="cursor: pointer; margin-bottom: 4px;">
|
||||||
> ${t('views.configManage.neManage.stop')}
|
> ${t('views.ne.common.stop')}
|
||||||
</div>
|
</div>
|
||||||
<div id="log" style="cursor: pointer; margin-bottom: 4px;">
|
<div id="log" style="cursor: pointer; margin-bottom: 4px;">
|
||||||
> ${t('views.configManage.neManage.log')}
|
> ${t('views.ne.common.log')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user