Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90395e7464 | ||
|
|
0b15ff1476 | ||
|
|
8ced920aec | ||
|
|
4ae74103f1 | ||
|
|
1c4c1a796d | ||
|
|
a658852772 | ||
|
|
0d13400229 | ||
|
|
7491ccc00b | ||
|
|
fc64460870 | ||
|
|
323da55c9d | ||
|
|
26cf7fa560 | ||
|
|
5ea56e779a | ||
|
|
174a7afc47 | ||
|
|
f4e61a0ebc | ||
|
|
97e5533d6e | ||
|
|
e1c4229e58 | ||
|
|
c6e21c6c38 | ||
|
|
b1d0771d56 | ||
|
|
22b0b7e204 | ||
|
|
93f31eded4 | ||
|
|
1eec47f410 | ||
|
|
d9bc5b9f02 | ||
|
|
3116e51338 | ||
|
|
3026ac1dd8 | ||
|
|
c01380da6b | ||
|
|
98e4d39cdf | ||
|
|
1c025c2cc1 | ||
|
|
20a12eba56 | ||
|
|
904488f59a | ||
|
|
a2f93f7862 | ||
|
|
d249d14c49 | ||
|
|
58d0e6e884 | ||
|
|
510e3e1006 | ||
|
|
02b12d76a7 | ||
|
|
5839aa3cb1 | ||
|
|
83a289492d | ||
|
|
05d59ec526 | ||
|
|
c22d7604cf | ||
|
|
6f9639d3d4 | ||
|
|
5932662e7c | ||
|
|
cdbe9a1e42 | ||
|
|
a032236d7d | ||
|
|
1dcd8a6e25 | ||
|
|
e075779b91 | ||
|
|
e5ce2ebb02 | ||
|
|
3da786f6b9 | ||
|
|
d4e603be63 | ||
|
|
a7024df325 | ||
|
|
b525b92163 |
No files matched your search
@@ -1,5 +1,52 @@
|
||||
# 版本发布日志
|
||||
|
||||
## 2.2510.4-20251024
|
||||
|
||||
- 新增 同步语音仪表盘:修改useNeInfoStore导入地址、补充接口导入、修改ims请求参数、修改响应码
|
||||
- 新增 基站状态补充randId列
|
||||
|
||||
## 2.2510.3-20251018
|
||||
|
||||
- 新增 备份网元日志文件数据查看
|
||||
- 修复 更新根网管节点处理逻辑,支持无OMC情况
|
||||
- 新增 网元配置选择传入neId查询相应版本配置数据
|
||||
- 修复 网元配置备份修改表单校验规则,添加备注字段必填项
|
||||
|
||||
## 2.2510.2-20251011
|
||||
|
||||
- 新增 UDM-auth数据导出按钮权限定义
|
||||
- 新增 SMSC-CDR添加结果原因说明
|
||||
- 优化 移除CDR/UE/网元版本/授权列表显示ID列
|
||||
- 修复 MML回车undefined问题,关闭搜索匹配
|
||||
|
||||
## 2.2509.4-20250926
|
||||
|
||||
- 优化 UDM数据显示创建时间列
|
||||
- 优化 中英文补充
|
||||
- 新增 添加系统备份功能,包括导入导出OMC的API和界面支持
|
||||
- 新增 日志备份文件查看kpi文件记录
|
||||
- 优化 根据搜索条件导出,去除最大记录限制
|
||||
- 新增 添加活动告警自动刷新功能并优化代码结构
|
||||
- 修复 奇安信浏览器时区格式错误
|
||||
- 新增 添加网元配置快速PLMN修改框
|
||||
- 新增 ue和ne模块权限按钮
|
||||
- 新增 监控模块按钮权限
|
||||
- 修复 UDM数据导出提示信息,导出总数
|
||||
- 新增 网元许可快速上传功能
|
||||
- 新增 网元信息快速OAM功能
|
||||
|
||||
## 2.2508.4-20250829
|
||||
|
||||
- 新增 网元授权显示用户数/基站数
|
||||
- 优化 网元当前版本显示是否有包存在
|
||||
- 优化 cdr/ue导出操作后锁定按钮事件防重发
|
||||
- 优化 网元可选静态可选项添加PGWC
|
||||
- 优化 参数配置添加校验过滤长度~和-定义范围
|
||||
- 修复 UPF流量统计数据同时获取刷新
|
||||
- 修复 UPF流量统计字节数据格式化显示不一致问题
|
||||
- 新增 指标Title管理页面功能
|
||||
- 新增 增加多个导出操作的超时时间至180秒
|
||||
|
||||
## 2.2508.2-20250815
|
||||
|
||||
- 优化 给config.js加随机数避免缓存
|
||||
|
||||
@@ -6,10 +6,11 @@ import { request } from '@/plugins/http-fetch';
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function getAllNeConfig(neType: string) {
|
||||
export function getAllNeConfig(neType: string, neId: string) {
|
||||
return request({
|
||||
url: `/ne/config/list/${neType}`,
|
||||
method: 'GET',
|
||||
params: { neId },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,3 +36,33 @@ export function updateBackupFTP(data: Record<string, any>) {
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-导出OMC
|
||||
* @returns object
|
||||
*/
|
||||
export function exportBackupOMC() {
|
||||
return request({
|
||||
url: '/neData/backup/export-omc',
|
||||
method: 'POST',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-导入OMC
|
||||
* @param filePath 备份文件上传返回的/upload 路径
|
||||
* @returns object
|
||||
*/
|
||||
export function importBackupOMC(filePath: string) {
|
||||
return request({
|
||||
url: '/neData/backup/import-omc',
|
||||
method: 'POST',
|
||||
data: {
|
||||
neType: 'OMC',
|
||||
path: filePath,
|
||||
},
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -140,3 +140,17 @@ export function exportUDMAuth(data: Record<string, any>) {
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出DecAuth
|
||||
* @param neId 网元ID
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMDecAuth(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/export-dec?neId=${neId}`,
|
||||
method: 'GET',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -33,3 +33,28 @@ export async function getKPITitle(neType: string) {
|
||||
// 解析数据//
|
||||
return result;
|
||||
}
|
||||
//忙时呼叫
|
||||
export async function getbusyhour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/kpi/busy-hour',
|
||||
method: 'GET',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
//MOS指标
|
||||
export async function getMosHour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/mos-hour',
|
||||
method: 'GET',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
//CCT指标
|
||||
export async function getCctHour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/cct-hour',
|
||||
method: 'GET',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
@@ -22,6 +22,12 @@ export const NE_TYPE_LIST = [
|
||||
'CHF',
|
||||
'HLR',
|
||||
'SGWC',
|
||||
'PGWC',
|
||||
'IP-SM-GW',
|
||||
'MMTel-AS',
|
||||
'I-CSCF',
|
||||
'P-CSCF',
|
||||
'S-CSCF',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
+46
-10
@@ -485,7 +485,7 @@ export default {
|
||||
resultOk: "Success",
|
||||
resultFail: "Fail",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data?",
|
||||
chargingID: 'Charging ID',
|
||||
smfSubscriptionIDData: 'Subscription ID Data',
|
||||
smfSubscriptionIDType: 'Subscription ID Type',
|
||||
@@ -517,7 +517,7 @@ export default {
|
||||
result: "Result",
|
||||
resultOk: "Successes",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition? (Maximum 10,000 items can be exported.)",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition?",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -539,6 +539,8 @@ export default {
|
||||
port: 'Port',
|
||||
portTip: "Network element port default:33030",
|
||||
capability: 'Capability',
|
||||
ueNumber: 'UE Number',
|
||||
nbNumber: 'Radio Number',
|
||||
serialNum: 'Serial Number',
|
||||
expiryDate: 'Expiry Date',
|
||||
normalcy: 'Normal',
|
||||
@@ -588,6 +590,22 @@ export default {
|
||||
kpiTimerPlease: 'Please enter the reporting period (in seconds)',
|
||||
omcIP: 'OMC IP',
|
||||
},
|
||||
quickOam: {
|
||||
title: 'Quick OAM Configuration',
|
||||
selectNe: 'Select NE',
|
||||
omcIP: 'OMC IP',
|
||||
oamPort: 'OAM Port',
|
||||
progress:'Progress',
|
||||
processing:'Progressing',
|
||||
result:'Result',
|
||||
success:'Success',
|
||||
default:'Default',
|
||||
allsuccess:'All NE have been configured successfully!',
|
||||
},
|
||||
quickUpload: {
|
||||
title: 'Quick License Upload',
|
||||
selectNe: 'Select NE',
|
||||
},
|
||||
backConf: {
|
||||
export: 'Config Export',
|
||||
import: 'Config Import',
|
||||
@@ -699,6 +717,10 @@ export default {
|
||||
uploadFile: "Upload License",
|
||||
uploadChangeOk: 'Network Element renewed license successfully and is being calibrated in the background!',
|
||||
uploadChangeFail: "Some network elements failed to update the license, please check whether the service terminal environment is available!",
|
||||
quickUpload: {
|
||||
title: 'Quick License Upload',
|
||||
selectNe: 'Select NE',
|
||||
},
|
||||
},
|
||||
neConfig: {
|
||||
treeTitle: "Navigation Configuration",
|
||||
@@ -824,7 +846,7 @@ export default {
|
||||
passwordPlease: "Please enter your password correctly",
|
||||
addTitle: 'Add VOIP subscriber',
|
||||
delTip: 'Confirm that you want to delete the information of VOIP user as [{num}]?',
|
||||
exportTip: "Confirm exporting xlsx table files based on search criteria?",
|
||||
exportTip: "Confirm exporting all VOIP user data based on the current search criteria?",
|
||||
},
|
||||
udmVolteIMS: {
|
||||
startMSISDN: 'Starting MSISDN',
|
||||
@@ -833,7 +855,7 @@ export default {
|
||||
vniTip: 'Example: ims.mnc000.mcc000.3gppnetwork.org',
|
||||
vniPlease: 'Please enter VNI correctly',
|
||||
delTip: 'Are you sure you want to delete the information of IMS signing as [{num}]?',
|
||||
exportTip: "Confirm exporting xlsx table files based on search criteria?",
|
||||
exportTip: "Confirm exporting all VoLTE user data based on the current search criteria?",
|
||||
},
|
||||
pcfSub: {
|
||||
exportTip: 'Confirm exporting all user policy control information data?',
|
||||
@@ -853,6 +875,7 @@ export default {
|
||||
list: "List",
|
||||
topology: "Topology",
|
||||
nbName: "RAN Node Name",
|
||||
nbId: "RAN Node ID",
|
||||
ueNum: "UE Number",
|
||||
topologyTitle: "Radio State Graph",
|
||||
name: "Name",
|
||||
@@ -884,7 +907,7 @@ export default {
|
||||
neTypePlease: 'Query network element Object',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all authentication user data?',
|
||||
exportConfirm: 'Confirm exporting all Authentication user data based on the current search criteria?',
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
||||
import: 'Import',
|
||||
@@ -913,7 +936,7 @@ export default {
|
||||
subInfo:' Subscription Info',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all signed user data?',
|
||||
exportConfirm: 'Confirm exporting all Subscribers user data based on the current search criteria?',
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
||||
import: 'Import',
|
||||
@@ -1339,10 +1362,19 @@ export default {
|
||||
deleteTipErr: "Failed to delete file",
|
||||
sysloginLog:'System Login Log',
|
||||
sysOperateLog:'System Operation Log',
|
||||
cdrIMS:'CDR Voice',
|
||||
cdrSMF:'CDR Data',
|
||||
cdrSMSC:'CDR SMS',
|
||||
cdrSGWC:'CDR Roaming Data',
|
||||
neLog:'NE Log',
|
||||
cdrIMS:'CDR IMS Voice',
|
||||
cdrSMF:'CDR SMF Data',
|
||||
cdrSMSC:'CDR SMSC SMS',
|
||||
cdrSGWC:'CDR SGWC Roaming Data',
|
||||
kpiIMS:'KPI IMS',
|
||||
kpiAMF:'KPI AMF',
|
||||
kpiUDM:'KPI UDM',
|
||||
kpiSMF:'KPI SMF',
|
||||
kpiPCF:'KPI PCF',
|
||||
kpiUPF:'KPI UPF',
|
||||
kpiMME:'KPI MME',
|
||||
kpiSMSC:'KPI SMSC',
|
||||
}
|
||||
},
|
||||
monitor: {
|
||||
@@ -1887,6 +1919,10 @@ export default {
|
||||
home: 'Home Page',
|
||||
homeTip:'Do you want to submit the current interface as the system interface?',
|
||||
homeSet:'Home Page Settings',
|
||||
backup: 'System Backup',
|
||||
backupInstruction: 'System backup will back up the net element information records and configuration files running on the current system, and can restore the system to the previous state!',
|
||||
backupExportTip: 'Confirm to export system backup?',
|
||||
backupImportTip: 'Confirm to import system backup?',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'All data permissions',
|
||||
|
||||
+46
-10
@@ -485,7 +485,7 @@ export default {
|
||||
resultOk: "成功",
|
||||
resultFail: "失败",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||
exportTip: "确认导出当前查询条件的话单数据吗?",
|
||||
chargingID: '计费ID',
|
||||
smfSubscriptionIDData: '订阅 ID 数据',
|
||||
smfSubscriptionIDType: '订阅 ID 类型',
|
||||
@@ -517,7 +517,7 @@ export default {
|
||||
result: "结果",
|
||||
resultOk: "成功",
|
||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||
exportTip: "确认导出当前查询条件的事件数据吗?(导出最大支持一万条)",
|
||||
exportTip: "确认导出当前查询条件的事件数据吗?",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -539,6 +539,8 @@ export default {
|
||||
port: '服务端口',
|
||||
portTip: "网元服务端口,默认:33030",
|
||||
capability: '容量',
|
||||
ueNumber: '用户数',
|
||||
nbNumber: '基站数',
|
||||
serialNum: '序列号',
|
||||
expiryDate: '许可证到期日期',
|
||||
normalcy: '正常',
|
||||
@@ -588,6 +590,22 @@ export default {
|
||||
kpiTimerPlease: '请输入上报周期(单位秒)',
|
||||
omcIP: 'OMC IP',
|
||||
},
|
||||
quickOam: {
|
||||
title: '快速OAM配置',
|
||||
selectNe: '选择网元',
|
||||
omcIP: 'OMC IP地址',
|
||||
oamPort: 'OAM端口',
|
||||
progress:'配置进度',
|
||||
processing:'正在处理',
|
||||
result:'操作结果',
|
||||
success:'成功',
|
||||
default:'失败',
|
||||
allsuccess:'所有网元配置成功!',
|
||||
},
|
||||
quickUpload: {
|
||||
title: '快速许可证上传',
|
||||
selectNe: '选择网元',
|
||||
},
|
||||
backConf: {
|
||||
export: '配置导出',
|
||||
import: '配置导入',
|
||||
@@ -699,6 +717,10 @@ export default {
|
||||
uploadFile: "上传许可证",
|
||||
uploadChangeOk: '网元更新许可证成功,正在后台校验!',
|
||||
uploadChangeFail: "部分网元更新许可证失败,请检查服务终端环境是否可用!",
|
||||
quickUpload: {
|
||||
title: '快速许可证上传',
|
||||
selectNe: '选择网元',
|
||||
},
|
||||
},
|
||||
neConfig: {
|
||||
treeTitle: "配置导航",
|
||||
@@ -824,7 +846,7 @@ export default {
|
||||
passwordPlease: "请正确输入密码",
|
||||
addTitle: '新增VOIP用户',
|
||||
delTip: '确认要删除VOIP用户为【{num}】的信息吗?',
|
||||
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
|
||||
exportTip: "确认根据当前搜索条件导出全部VoIP用户数据吗?",
|
||||
},
|
||||
udmVolteIMS: {
|
||||
startMSISDN: '起始MSISDN',
|
||||
@@ -833,7 +855,7 @@ export default {
|
||||
vniTip: '示例:ims.mnc000.mcc000.3gppnetwork.org',
|
||||
vniPlease: '请正确输入VNI',
|
||||
delTip: '确认要删除IMS签约为【{num}】的信息吗?',
|
||||
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
|
||||
exportTip: "确认根据当前搜索条件导出全部VoLTE用户数据吗?",
|
||||
},
|
||||
pcfSub: {
|
||||
exportTip: '确认导出全部用户策略控制信息数据吗?',
|
||||
@@ -853,6 +875,7 @@ export default {
|
||||
list: "列表",
|
||||
topology: "拓扑图",
|
||||
nbName: "设备名称",
|
||||
nbId: "设备ID",
|
||||
ueNum: "在线用户数",
|
||||
topologyTitle: "基站状态关系图",
|
||||
name: "基站名称",
|
||||
@@ -884,7 +907,7 @@ export default {
|
||||
neTypePlease: '查询网元类型',
|
||||
neType: 'UDM网元对象',
|
||||
export: '导出',
|
||||
exportConfirm: '确认导出全部鉴权用户数据吗?',
|
||||
exportConfirm: '确认根据当前搜索条件导出全部鉴权用户数据吗?',
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的鉴权用户数据吗?',
|
||||
import: '导入',
|
||||
@@ -915,7 +938,7 @@ export default {
|
||||
export: '导出',
|
||||
exportConfirm: '确认导出全部签约用户数据吗?',
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的签约用户数据吗?',
|
||||
checkExportConfirm: '确认根据当前搜索条件导出全部签约用户数据吗?',
|
||||
import: '导入',
|
||||
importFail: '失败记录',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
@@ -1339,10 +1362,19 @@ export default {
|
||||
deleteTipErr: "文件删除失败",
|
||||
sysloginLog:'系统登录日志',
|
||||
sysOperateLog:'系统操作日志',
|
||||
cdrIMS:'语音话单',
|
||||
cdrSMF:'数据话单',
|
||||
cdrSMSC:'短信话单',
|
||||
cdrSGWC:'漫游数据话单',
|
||||
neLog:'网元日志',
|
||||
cdrIMS:'话单 IMS 语音',
|
||||
cdrSMF:'话单 SMF 数据',
|
||||
cdrSMSC:'话单 SMSC 短信',
|
||||
cdrSGWC:'话单 SGWC 漫游数据',
|
||||
kpiIMS:'KPI IMS',
|
||||
kpiAMF:'KPI AMF',
|
||||
kpiUDM:'KPI UDM',
|
||||
kpiSMF:'KPI SMF',
|
||||
kpiPCF:'KPI PCF',
|
||||
kpiUPF:'KPI UPF',
|
||||
kpiMME:'KPI MME',
|
||||
kpiSMSC:'KPI SMSC',
|
||||
}
|
||||
},
|
||||
monitor: {
|
||||
@@ -1887,6 +1919,10 @@ export default {
|
||||
home: '系统首页',
|
||||
homeTip:'确认要提交当前界面为系统界面吗?',
|
||||
homeSet:'系统首页设置',
|
||||
backup: '系统备份',
|
||||
backupInstruction: '系统备份将会对当前系统上运行的网元信息记录及配置文件进行备份,可进行系统的恢复操作!',
|
||||
backupExportTip: '确认要导出系统备份吗?',
|
||||
backupImportTip: '确认要导入系统备份吗?',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'全部数据权限',
|
||||
|
||||
@@ -217,6 +217,7 @@ onMounted(() => {
|
||||
let serverTimeInterval: any = null;
|
||||
let serverTime = 0;
|
||||
let serverTimeZone = getTimezoneOffset();
|
||||
let activeAlarmRefresh = 0;
|
||||
|
||||
// 获取服务器时间
|
||||
function fnGetServerTime() {
|
||||
@@ -230,6 +231,7 @@ function fnGetServerTime() {
|
||||
const serverTimeDom = document.getElementById('serverTimeDom');
|
||||
serverTimeInterval = setInterval(() => {
|
||||
serverTime += 1000;
|
||||
activeAlarmRefresh += 1;
|
||||
if (serverTimeDom) {
|
||||
serverTimeDom.innerText = parseDateUTCToStr(
|
||||
serverTime,
|
||||
@@ -239,6 +241,10 @@ function fnGetServerTime() {
|
||||
clearInterval(serverTimeInterval);
|
||||
serverTimeInterval = null;
|
||||
}
|
||||
if (activeAlarmRefresh === 5) {
|
||||
useAlarmStore().fnGetActiveAlarmInfo();
|
||||
activeAlarmRefresh = 0;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
+31
-1
@@ -17,6 +17,35 @@ export const RFC3339 = 'YYYY-MM-DDTHH:mm:ssZ';
|
||||
/**国际时间 列如:Thu, Nov 14 2024 10:19 GMT+08:00 */
|
||||
export const RFC822Z = 'ddd, MMM DD YYYY HH:mm [GMT]Z';
|
||||
|
||||
// 映射时区偏移量与IANA时区名称关联
|
||||
export const offsetToIanaMap: Record<string, string> = {
|
||||
'+0000': 'UTC',
|
||||
'+0100': 'Europe/London',
|
||||
'+0200': 'Europe/Paris',
|
||||
'+0300': 'Europe/Moscow',
|
||||
'+0400': 'Asia/Dubai',
|
||||
'+0500': 'Asia/Karachi',
|
||||
'+0600': 'Asia/Almaty',
|
||||
'+0700': 'Asia/Bangkok',
|
||||
'+0800': 'Asia/Shanghai',
|
||||
'+0900': 'Asia/Tokyo',
|
||||
'+1000': 'Australia/Sydney',
|
||||
'+1100': 'Pacific/Noumea',
|
||||
'+1200': 'Pacific/Fiji',
|
||||
'-0100': 'America/Noronha',
|
||||
'-0200': 'Atlantic/Azores',
|
||||
'-0300': 'America/Argentina/Buenos_Aires',
|
||||
'-0400': 'America/New_York',
|
||||
'-0500': 'America/New_York',
|
||||
'-0600': 'America/Chicago',
|
||||
'-0700': 'America/Denver',
|
||||
'-0800': 'America/Los_Angeles',
|
||||
'-0900': 'Pacific/Honolulu',
|
||||
'-1000': 'Pacific/Honolulu',
|
||||
'-1100': 'Pacific/Pago_Pago',
|
||||
'-1200': 'Pacific/Kwajalein',
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式时间字符串
|
||||
* @param dateStr 时间字符串
|
||||
@@ -53,9 +82,10 @@ export function parseDateUTCToStr(
|
||||
date: string | number | Date,
|
||||
offset: string = '+0000'
|
||||
): string {
|
||||
const ianaTimezone = offsetToIanaMap[offset] || 'UTC';
|
||||
return dayjs
|
||||
.utc(date) // 将时间戳按 UTC 时间
|
||||
.tz(offset) // 使用时区偏移
|
||||
.tz(ianaTimezone) // 使用时区偏移
|
||||
.format(`YYYY-MM-DD HH:mm:ss [UTC${offset}]`); // 格式化时间
|
||||
}
|
||||
|
||||
|
||||
@@ -177,25 +177,6 @@ export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
|
||||
return [(realBit / 1000 / 1000).toFixed(2), ' Mbits/sec'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 位数据转换单位
|
||||
* @param bits 位Bit大小 64009540 = 512.08 MB
|
||||
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
||||
*/
|
||||
export function parseSizeFromBits(bits: number | string): string {
|
||||
bits = Number(bits) || 0;
|
||||
if (bits <= 0) return '0 B';
|
||||
bits = bits * 8;
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
const unitIndex = Math.floor(Math.log2(bits) / 10);
|
||||
const value = bits / Math.pow(1000, unitIndex);
|
||||
const unti = units[unitIndex];
|
||||
if (unitIndex > 0) {
|
||||
return `${value.toFixed(2)} ${unti}`;
|
||||
}
|
||||
return `${value} ${unti}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数转换单位
|
||||
* @param byte 字节Byte大小 64009540 = 512.08 MB
|
||||
|
||||
@@ -88,12 +88,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.cbc.cbe.eventName'),
|
||||
dataIndex: 'messageJson',
|
||||
|
||||
@@ -63,7 +63,7 @@ let tableColumns: ColumnsType = [
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
if (opt.value?.refreshTime) {
|
||||
return parseDateToStr(opt.value?.refreshTime, 'HH:mm:ss');
|
||||
return parseDateToStr(opt.value?.refreshTime);
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
@@ -94,11 +94,8 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.index.ipAddress'),
|
||||
dataIndex: 'serverState',
|
||||
dataIndex: 'ip',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
return opt.value?.neIP || '-';
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -250,8 +247,9 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
|
||||
serverState.value = Object.assign(
|
||||
{
|
||||
// cpuUse: `NE:${nfCpuP}%; SYS:${sysCpuP}%`,
|
||||
// memoryUse: `Total: ${totalMemInMB}MB; NE: ${nfUsedMemInMB}MB; SYS: ${sysMemUsageInMB}MB`,
|
||||
// cpuUse: `NE:${nfCpuP}%; SYS:${sysCpuP}%`,
|
||||
// memoryUse: `Total: ${totalMemInMB}MB; NE: ${nfUsedMemInMB}MB; SYS: ${sysMemUsageInMB}MB`,
|
||||
neIP: row.ip,
|
||||
},
|
||||
neState
|
||||
);
|
||||
@@ -315,22 +313,13 @@ onBeforeUnmount(() => {
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="14" :md="16" :xs="24">
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
size="small"
|
||||
:columns="tableColumns"
|
||||
:data-source="tableState.data"
|
||||
:loading="tableState.loading"
|
||||
:pagination="false"
|
||||
:scroll="{ x: true }"
|
||||
:row-selection="{
|
||||
<a-table class="table" row-key="id" size="small" :columns="tableColumns" :data-source="tableState.data"
|
||||
:loading="tableState.loading" :pagination="false" :scroll="{ x: true }" :row-selection="{
|
||||
type: 'radio',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
}">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'status'">
|
||||
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
||||
@@ -339,24 +328,12 @@ onBeforeUnmount(() => {
|
||||
</a-table>
|
||||
</a-col>
|
||||
<a-col :lg="10" :md="8" :xs="24">
|
||||
<a-card
|
||||
:title="t('views.index.runStatus')"
|
||||
style="margin-bottom: 16px"
|
||||
size="small"
|
||||
>
|
||||
<a-card :title="t('views.index.runStatus')" style="margin-bottom: 16px" size="small">
|
||||
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
||||
</a-card>
|
||||
<a-card
|
||||
:loading="tableState.loading"
|
||||
:title="`${t('views.index.mark')} - ${serverState.neName || 'OMC'}`"
|
||||
style="margin-top: 16px"
|
||||
size="small"
|
||||
>
|
||||
<a-descriptions
|
||||
bordered
|
||||
:column="1"
|
||||
:label-style="{ width: '160px' }"
|
||||
>
|
||||
<a-card :loading="tableState.loading" :title="`${t('views.index.mark')} - ${serverState.neName || 'OMC'}`"
|
||||
style="margin-top: 16px" size="small">
|
||||
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
||||
<a-descriptions-item :label="t('views.index.hostName')">
|
||||
{{ serverState.hostname }}
|
||||
</a-descriptions-item>
|
||||
|
||||
@@ -134,12 +134,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
@@ -339,9 +339,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportAMFDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
|
||||
@@ -141,12 +141,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.dashboard.cdr.recordType'),
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -408,9 +408,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportIMSDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
|
||||
@@ -135,12 +135,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: 'IMSI',
|
||||
dataIndex: 'eventJSON',
|
||||
@@ -341,9 +341,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.ue.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportMMEDataUE(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
|
||||
@@ -247,42 +247,7 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
// console.log(info.neState.cpu.sysCpuUsage);
|
||||
// console.log(info.neState.mem);
|
||||
// console.log(info.neState.disk);
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (info.neState.cpu) {
|
||||
nfCpuUsage = info.neState.cpu.nfCpuUsage;
|
||||
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
if (nfCpuUsage > 100) {
|
||||
nfCpuUsage = 100;
|
||||
}
|
||||
|
||||
sysCpuUsage = info.neState.cpu.sysCpuUsage;
|
||||
let sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
if (sysCpuUsage > 100) {
|
||||
sysCpuUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (info.neState.mem) {
|
||||
const men = info.neState.mem.sysMemUsage;
|
||||
sysMemUsage = +(men / 100).toFixed(2);
|
||||
if (sysMemUsage > 100) {
|
||||
sysMemUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (info.neState.disk && Array.isArray(info.neState.disk.partitionInfo)) {
|
||||
let disks: any[] = info.neState.disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
const { nfCpuUsage, sysCpuUsage, sysMemUsage, sysDiskUsage } = info.neState
|
||||
|
||||
category.value[0].value = sysDiskUsage;
|
||||
category.value[1].value = sysMemUsage;
|
||||
|
||||
@@ -74,8 +74,7 @@ export function neStateParse(neType: string, data: Record<string, any>) {
|
||||
|
||||
// 更新网元状态
|
||||
const newNeState = Object.assign(node.neState, data, {
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'),
|
||||
online: !!data.cpu,
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'MM-DD HH:mm:ss'),
|
||||
});
|
||||
|
||||
// 通过 ID 查询节点实例
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { parseSizeFromByte, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { ref } from 'vue';
|
||||
|
||||
type FDType = {
|
||||
@@ -81,9 +81,9 @@ export function upfTFParse(day: string, data: Record<string, number>) {
|
||||
let { up, down } = data;
|
||||
upfTotalFlow.value[day] = {
|
||||
up: up,
|
||||
upFrom: parseSizeFromBits(up),
|
||||
upFrom: parseSizeFromByte(up),
|
||||
down: down,
|
||||
downFrom: parseSizeFromBits(down),
|
||||
downFrom: parseSizeFromByte(down),
|
||||
requestFlag: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -229,15 +229,15 @@ function loadData() {
|
||||
interval10s.value = setInterval(() => {
|
||||
if (!interval10s.value || !initFlag) return;
|
||||
if (upfTFActive.value === '0') {
|
||||
upfTFSend('7');
|
||||
upfTFActive.value = '7';
|
||||
} else if (upfTFActive.value === '7') {
|
||||
upfTFSend('30');
|
||||
upfTFActive.value = '30';
|
||||
} else if (upfTFActive.value === '30') {
|
||||
upfTFSend('0');
|
||||
upfTFActive.value = '0';
|
||||
}
|
||||
upfTFSend('0');
|
||||
upfTFSend('7');
|
||||
upfTFSend('30');
|
||||
}, 10_000);
|
||||
|
||||
clearInterval(interval5s.value);
|
||||
|
||||
@@ -71,9 +71,8 @@ const optionData: any = {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.neCpu')}\n${
|
||||
resourceData.value.neCpu
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.neCpu')}\n${resourceData.value.neCpu
|
||||
}%`;
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
@@ -103,9 +102,8 @@ const optionData: any = {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysCpu')}\n${
|
||||
resourceData.value.sysCpu
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysCpu')}\n${resourceData.value.sysCpu
|
||||
}%`;
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
@@ -135,9 +133,8 @@ const optionData: any = {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysMem')}\n${
|
||||
resourceData.value.sysMem
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysMem')}\n${resourceData.value.sysMem
|
||||
}%`;
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
@@ -167,9 +164,8 @@ const optionData: any = {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysDisk')}\n${
|
||||
resourceData.value.sysDisk
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysDisk')}\n${resourceData.value.sysDisk
|
||||
}%`;
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
@@ -213,45 +209,7 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
let info = data.find((item: any) => item.id === neType);
|
||||
if (!info || !info.neStateMap[neID]?.online) return;
|
||||
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (info.neStateMap[neID].cpu) {
|
||||
nfCpuUsage = info.neStateMap[neID].cpu.nfCpuUsage;
|
||||
const nfCpu = +(info.neStateMap[neID].cpu.nfCpuUsage / 100);
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
if (nfCpuUsage > 100) {
|
||||
nfCpuUsage = 100;
|
||||
}
|
||||
|
||||
sysCpuUsage = info.neStateMap[neID].cpu.sysCpuUsage;
|
||||
let sysCpu = +(info.neStateMap[neID].cpu.sysCpuUsage / 100);
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
if (sysCpuUsage > 100) {
|
||||
sysCpuUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (info.neStateMap[neID].mem) {
|
||||
const men = info.neStateMap[neID].mem.sysMemUsage;
|
||||
sysMemUsage = +(men / 100).toFixed(2);
|
||||
if (sysMemUsage > 100) {
|
||||
sysMemUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (
|
||||
info.neStateMap[neID].disk &&
|
||||
Array.isArray(info.neStateMap[neID].disk.partitionInfo)
|
||||
) {
|
||||
let disks: any[] = info.neStateMap[neID].disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
const { nfCpuUsage, sysCpuUsage, sysMemUsage, sysDiskUsage } = info.neStateMap[neID]
|
||||
|
||||
resourceData.value = {
|
||||
neCpu: nfCpuUsage,
|
||||
@@ -269,9 +227,8 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.neCpu')}\n${
|
||||
resourceData.value.neCpu
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.neCpu')}\n${resourceData.value.neCpu
|
||||
}%`;
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -282,9 +239,8 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysCpu')}\n${
|
||||
resourceData.value.sysCpu
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysCpu')}\n${resourceData.value.sysCpu
|
||||
}%`;
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -295,9 +251,8 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysMem')}\n${
|
||||
resourceData.value.sysMem
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysMem')}\n${resourceData.value.sysMem
|
||||
}%`;
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -308,9 +263,8 @@ function fnChangeData(data: any[], itemID: string) {
|
||||
label: {
|
||||
normal: {
|
||||
formatter: () => {
|
||||
return `${t('views.dashboard.overview.resources.sysDisk')}\n${
|
||||
resourceData.value.sysDisk
|
||||
}%`;
|
||||
return `${t('views.dashboard.overview.resources.sysDisk')}\n${resourceData.value.sysDisk
|
||||
}%`;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -38,18 +38,16 @@ export const graphG6 = ref<any>(null);
|
||||
export const graphNodeClickID = ref<string>('UPF_001');
|
||||
|
||||
/**图节点网元信息状态 */
|
||||
export const graphNodeState = computed(() =>{
|
||||
return graphState.data.nodes.map((item: any) => ({
|
||||
export const graphNodeState = computed(() => {
|
||||
return graphState.data.nodes.map((item: any) => ({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
neInfo: item.neInfo,
|
||||
neState: item.neState,
|
||||
neInfoList:item.neInfoList,
|
||||
neInfoList: item.neInfoList,
|
||||
neStateMap: item.neStateMap,
|
||||
}))
|
||||
}
|
||||
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
/**图节点网元状态数量 */
|
||||
export const graphNodeStateNum = computed(() => {
|
||||
@@ -72,8 +70,12 @@ export const graphNodeStateNum = computed(() => {
|
||||
export const neStateRequestMap = ref<Map<string, boolean>>(new Map());
|
||||
|
||||
/**neStateParse 网元状态 数据解析 */
|
||||
export function neStateParse(neType: string, data: Record<string, any>,neId: string) {
|
||||
// console.log('neStateParse',neType, data, neId);
|
||||
export function neStateParse(
|
||||
neType: string,
|
||||
data: Record<string, any>,
|
||||
neId: string
|
||||
) {
|
||||
// console.log('neStateParse',neType, data, neId);
|
||||
|
||||
const { combos, edges, nodes } = graphState.data;
|
||||
|
||||
@@ -82,25 +84,24 @@ export function neStateParse(neType: string, data: Record<string, any>,neId: str
|
||||
|
||||
if (!node) return;
|
||||
|
||||
// 初始化状态映射
|
||||
if (!node.neStateMap) node.neStateMap = {};
|
||||
// 初始化状态映射
|
||||
if (!node.neStateMap) node.neStateMap = {};
|
||||
|
||||
// 更新网元状态
|
||||
const newNeState :any = {
|
||||
...data, // 先展开data对象
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'),
|
||||
online: !!data.cpu,
|
||||
neId: neId
|
||||
const newNeState: any = {
|
||||
...data, // 先展开data对象
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'MM-DD HH:mm:ss'),
|
||||
neId: neId,
|
||||
};
|
||||
// 如果是001,更新节点状态。neInfo为主要的网元信息
|
||||
if (node.neInfo && node.neInfo.neId === neId) {
|
||||
Object.assign(node.neState, newNeState);
|
||||
}
|
||||
// 如果是001,更新节点状态。neInfo为主要的网元信息
|
||||
if (node.neInfo && node.neInfo.neId === neId) {
|
||||
Object.assign(node.neState, newNeState);
|
||||
}
|
||||
|
||||
//console.log(node.neState)
|
||||
// 无论是否为主要网元,都更新状态映射
|
||||
node.neStateMap[neId] = {...newNeState};
|
||||
// 通过 ID 查询节点实例
|
||||
//console.log(node.neState)
|
||||
// 无论是否为主要网元,都更新状态映射
|
||||
node.neStateMap[neId] = { ...newNeState };
|
||||
// 通过 ID 查询节点实例
|
||||
const item = graphG6.value.findById(node.id);
|
||||
if (item) {
|
||||
// 检查当前节点下所有网元的状态
|
||||
@@ -109,32 +110,33 @@ export function neStateParse(neType: string, data: Record<string, any>,neId: str
|
||||
let stateColor = '#52c41a'; // 默认绿色(所有网元都正常)
|
||||
if (allStates.some((state: any) => !state.online)) {
|
||||
// 如果有任何一个网元不正常
|
||||
stateColor = allStates.every((state: any) => !state.online) ? '#f5222d' : '#faad14'; // 红色(全部不正常)或黄色(部分不正常)
|
||||
stateColor = allStates.every((state: any) => !state.online)
|
||||
? '#f5222d'
|
||||
: '#faad14'; // 红色(全部不正常)或黄色(部分不正常)
|
||||
}
|
||||
|
||||
// 图片类型不能填充
|
||||
if (node.type && node.type.startsWith('image')) {
|
||||
// 更新节点
|
||||
if (node.label !== newNeState.neType) {
|
||||
graphG6.value.updateItem(item, {
|
||||
label: newNeState.neType,
|
||||
});
|
||||
}
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'top-right-dot', stateColor);
|
||||
} else {
|
||||
// 更新节点
|
||||
// 图片类型不能填充
|
||||
if (node.type && node.type.startsWith('image')) {
|
||||
// 更新节点
|
||||
if (node.label !== newNeState.neType) {
|
||||
graphG6.value.updateItem(item, {
|
||||
label: newNeState.neType,
|
||||
style: {
|
||||
fill: stateColor, // 填充色
|
||||
stroke: stateColor, // 填充色
|
||||
},
|
||||
});
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'stroke', newNeState.online);
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'top-right-dot', stateColor);
|
||||
} else {
|
||||
// 更新节点
|
||||
graphG6.value.updateItem(item, {
|
||||
label: newNeState.neType,
|
||||
style: {
|
||||
fill: stateColor, // 填充色
|
||||
stroke: stateColor, // 填充色
|
||||
},
|
||||
});
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'stroke', newNeState.online);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置边状态
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { parseSizeFromByte, parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { ref } from 'vue';
|
||||
|
||||
type FDType = {
|
||||
@@ -79,9 +79,9 @@ export function upfTFParse(day: string, data: Record<string, number>) {
|
||||
let { up, down } = data;
|
||||
upfTotalFlow.value[day] = {
|
||||
up: up,
|
||||
upFrom: parseSizeFromBits(up),
|
||||
upFrom: parseSizeFromByte(up),
|
||||
down: down,
|
||||
downFrom: parseSizeFromBits(down),
|
||||
downFrom: parseSizeFromByte(down),
|
||||
requestFlag: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -176,15 +176,15 @@ async function fnGetSkim() {
|
||||
{
|
||||
request: (neId: string) => listAMFNblist({ neId }),
|
||||
process: async (res: any, neId: any) => {
|
||||
console.log(neId)
|
||||
if (res.code === RESULT_CODE_SUCCESS&& Array.isArray(res.data)) {
|
||||
console.log(neId);
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
skimState.gnbNum += res.data.length;
|
||||
skimState.gnbUeNum += res.data.reduce(
|
||||
(sum: number, item: any) => sum + item.ueNum,
|
||||
0
|
||||
);
|
||||
const amfNbRes = await listAMFNbStatelist({ neId });
|
||||
console.log(amfNbRes)
|
||||
console.log(amfNbRes);
|
||||
if (
|
||||
amfNbRes.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(amfNbRes.data)
|
||||
@@ -224,13 +224,13 @@ async function fnGetSkim() {
|
||||
);
|
||||
|
||||
const mmeNbRes = await listMMENbStatelist({ neId });
|
||||
console.log(mmeNbRes)
|
||||
console.log(mmeNbRes);
|
||||
if (
|
||||
mmeNbRes.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(mmeNbRes.data)
|
||||
) {
|
||||
// skimState.eNbSumNum += mmeNbRes.data.length;
|
||||
console.log(mmeNbRes)
|
||||
console.log(mmeNbRes);
|
||||
tempEnbSumNum += mmeNbRes.data.length;
|
||||
}
|
||||
}
|
||||
@@ -238,21 +238,20 @@ async function fnGetSkim() {
|
||||
},
|
||||
],
|
||||
]);
|
||||
console.log(neCascaderOptions)
|
||||
console.log(neCascaderOptions);
|
||||
|
||||
const requests = neCascaderOptions.value.flatMap(
|
||||
(ne: any) =>
|
||||
ne.children
|
||||
?.map((child: any) => {
|
||||
console.log(child.neId)
|
||||
console.log(child.neId);
|
||||
const handler = neHandlers.get(child.neType);
|
||||
return handler
|
||||
? {
|
||||
promise: handler.request(child.neId),
|
||||
process: handler.process,
|
||||
neId: child.neId, // 这里加上neId
|
||||
|
||||
}
|
||||
neId: child.neId, // 这里加上neId
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter(Boolean) || []
|
||||
@@ -311,15 +310,15 @@ function loadData() {
|
||||
interval10s.value = setInterval(() => {
|
||||
if (!interval10s.value || !initFlag) return;
|
||||
if (upfTFActive.value === '0') {
|
||||
upfTFSend('7');
|
||||
upfTFActive.value = '7';
|
||||
} else if (upfTFActive.value === '7') {
|
||||
upfTFSend('30');
|
||||
upfTFActive.value = '30';
|
||||
} else if (upfTFActive.value === '30') {
|
||||
upfTFSend('0');
|
||||
upfTFActive.value = '0';
|
||||
}
|
||||
upfTFSend('0');
|
||||
upfTFSend('7');
|
||||
upfTFSend('30');
|
||||
}, 10_000);
|
||||
|
||||
clearInterval(interval5s.value);
|
||||
@@ -375,12 +374,14 @@ async function fnSelectUDM(e: any) {
|
||||
pageNum: 1,
|
||||
pageSize: 1,
|
||||
});
|
||||
console.log(res)
|
||||
console.log(res);
|
||||
// listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && typeof res.data.total === 'number') {
|
||||
if (
|
||||
res.code === RESULT_CODE_SUCCESS &&
|
||||
typeof res.data.total === 'number'
|
||||
) {
|
||||
skimState.udmSubNum = res.data.total;
|
||||
console.log(res)
|
||||
|
||||
console.log(res);
|
||||
} else {
|
||||
skimState.udmSubNum = 0;
|
||||
}
|
||||
@@ -393,7 +394,7 @@ async function fnSelectUDM(e: any) {
|
||||
}
|
||||
/**资源控制-选择NE */
|
||||
function fnSelectNeRe(e: any) {
|
||||
console.log(e)
|
||||
console.log(e);
|
||||
graphNodeClickID.value = e.key;
|
||||
}
|
||||
//
|
||||
@@ -408,7 +409,7 @@ const getPopupContainer = () => {
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
neListStore.neCascaderOptions.forEach(item => {
|
||||
console.log(item)
|
||||
console.log(item);
|
||||
if (item.value === 'UPF') {
|
||||
neOtions.value = JSON.parse(JSON.stringify(item.children));
|
||||
}
|
||||
|
||||
@@ -111,12 +111,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.dashboard.cdr.chargingID'), // 计费ID
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -378,9 +378,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportSGWCDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import PQueue from 'p-queue';
|
||||
import saveAs from 'file-saver';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { parseSizeFromByte } from '@/utils/parse-utils';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
const { copy } = useClipboard({ legacy: true });
|
||||
const { t } = useI18n();
|
||||
@@ -107,12 +108,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'center',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.dashboard.cdr.chargingID'), // 计费ID
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -165,7 +166,7 @@ let tableColumns = ref<ColumnsType>([
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataVolumeUplink;
|
||||
return parseSizeFromByte(dataVolumeUplink);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -190,7 +191,7 @@ let tableColumns = ref<ColumnsType>([
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataVolumeDownlink;
|
||||
return parseSizeFromByte(dataVolumeDownlink);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -215,7 +216,7 @@ let tableColumns = ref<ColumnsType>([
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataTotalVolume;
|
||||
return parseSizeFromByte(dataTotalVolume);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -405,9 +406,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportSMFDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -810,15 +813,21 @@ onBeforeUnmount(() => {
|
||||
<div>
|
||||
<div>
|
||||
<span>Data Total Volume: </span>
|
||||
<span>{{ udata.dataTotalVolume }}</span>
|
||||
<span>
|
||||
{{ parseSizeFromByte(udata.dataTotalVolume || 0) }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Downlink: </span>
|
||||
<span>{{ udata.dataVolumeDownlink }}</span>
|
||||
<span>
|
||||
{{ parseSizeFromByte(udata.dataVolumeDownlink || 0) }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Data Volume Uplink: </span>
|
||||
<span>{{ udata.dataVolumeUplink }}</span>
|
||||
<span>
|
||||
{{ parseSizeFromByte(udata.dataVolumeUplink || 0) }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- <div>
|
||||
<span>Time: </span>
|
||||
|
||||
@@ -33,10 +33,10 @@ const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**CDR 响应原因代码类别类型 */
|
||||
cdrCauseCode: DictType[];
|
||||
/**CDR SMSC 响应原因代码类别类型 */
|
||||
cdrSMSCCauseCode: DictType[];
|
||||
} = reactive({
|
||||
cdrCauseCode: [],
|
||||
cdrSMSCCauseCode: [],
|
||||
});
|
||||
|
||||
/**网元可选 */
|
||||
@@ -136,12 +136,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.dashboard.cdr.recordType'),
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -186,12 +186,19 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
|
||||
{
|
||||
title: t('views.dashboard.cdr.result'),
|
||||
title: t('views.dashboard.cdr.resultCode'),
|
||||
dataIndex: 'cdrJSON',
|
||||
key: 'cause',
|
||||
align: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.resultCause'),
|
||||
dataIndex: 'cdrJSON',
|
||||
key: 'result',
|
||||
align: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.dashboard.cdr.time'),
|
||||
dataIndex: 'cdrJSON',
|
||||
@@ -372,9 +379,11 @@ function fnExportList() {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.dashboard.cdr.exportTip'),
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageSize = 10000;
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportSMSCDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -470,9 +479,9 @@ function wsMessage(res: Record<string, any>) {
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([getDict('cdr_cause_code')]).then(resArr => {
|
||||
Promise.allSettled([getDict('cdr_cause_smsc')]).then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.cdrCauseCode = resArr[0].value;
|
||||
dict.cdrSMSCCauseCode = resArr[0].value;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -710,17 +719,15 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'cause'">
|
||||
<span v-if="record.cdrJSON.result === 0">
|
||||
{{ t('views.dashboard.cdr.resultFail') }},
|
||||
<DictTag
|
||||
:options="dict.cdrCauseCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.cdr.resultOk') }}
|
||||
</span>
|
||||
<span v-if="record.cdrJSON.result === 0"> FAILED </span>
|
||||
<span v-else> SUCCESS </span>
|
||||
</template>
|
||||
<template v-if="column.key === 'result'">
|
||||
<DictTag
|
||||
:options="dict.cdrSMSCCauseCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-default="0"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
@@ -792,18 +799,19 @@ onBeforeUnmount(() => {
|
||||
<span>{{ record.cdrJSON.calledParty }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.result') }}: </span>
|
||||
<span v-if="record.cdrJSON.result === 0">
|
||||
{{ t('views.dashboard.cdr.resultFail') }},
|
||||
<span>{{ t('views.dashboard.cdr.resultCode') }}: </span>
|
||||
<span v-if="record.cdrJSON.result === 0"> FAILED </span>
|
||||
<span v-else> SUCCESS </span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.dashboard.cdr.resultCause') }}: </span>
|
||||
<span>
|
||||
<DictTag
|
||||
:options="dict.cdrCauseCode"
|
||||
:options="dict.cdrSMSCCauseCode"
|
||||
:value="record.cdrJSON.cause"
|
||||
value-default="0"
|
||||
/>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('views.dashboard.cdr.resultOk') }}
|
||||
</span>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { reactive, ref, onMounted, toRaw, onBeforeUnmount } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Modal } from 'ant-design-vue/es';
|
||||
@@ -560,22 +560,24 @@ function fnCancelConfirm() {
|
||||
*/
|
||||
function fnSync() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
listSync().then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.faultManage.activeAlarm.sysncSuss'),
|
||||
duration: 2,
|
||||
});
|
||||
fnGetList();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
}).finally(()=>{
|
||||
hide();
|
||||
});
|
||||
listSync()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.faultManage.activeAlarm.sysncSuss'),
|
||||
duration: 2,
|
||||
});
|
||||
fnGetList();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -821,6 +823,24 @@ function fnGetList(pageNum?: number) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
let interval: any = null;
|
||||
/**自动刷新 */
|
||||
function AutoRefresh() {
|
||||
interval = setInterval(() => {
|
||||
listAct(toRaw(queryParams)).then((res: any) => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
const { total, rows } = res.data;
|
||||
tablePagination.total = total;
|
||||
tableState.data = rows;
|
||||
} else {
|
||||
tablePagination.total = 0;
|
||||
tableState.data = [];
|
||||
}
|
||||
});
|
||||
}, 5_000);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([
|
||||
@@ -844,7 +864,12 @@ onMounted(() => {
|
||||
});
|
||||
// 获取列表
|
||||
fnGetList();
|
||||
// 自动刷新
|
||||
AutoRefresh();
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval);
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -957,7 +982,11 @@ onMounted(() => {
|
||||
{{ t('views.faultManage.activeAlarm.updateConfirm') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" @click.prevent="fnSync()">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnSync()"
|
||||
v-perms:has="['faultManage:active-alarm:async']"
|
||||
>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
@@ -974,6 +1003,7 @@ onMounted(() => {
|
||||
danger
|
||||
@click.prevent="fnClear()"
|
||||
:disabled="state.selectedRowKeys.length <= 0"
|
||||
v-perms:has="['faultManage:active-alarm:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
@@ -981,7 +1011,11 @@ onMounted(() => {
|
||||
{{ t('views.faultManage.activeAlarm.clear') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click.prevent="fnExportList()"
|
||||
v-perms:has="['faultManage:active-alarm:export']"
|
||||
>
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
|
||||
@@ -744,7 +744,7 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<a-button type="dashed" @click.prevent="fnExportList()" v-perms:has="['faultManage:history-alarm:export']">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
|
||||
@@ -104,12 +104,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
|
||||
@@ -30,29 +30,78 @@ let sourceState = reactive({
|
||||
label: t('views.logManage.exportFile.sysOperateLog'),
|
||||
path: '/usr/local/omc/backup',
|
||||
},
|
||||
|
||||
{
|
||||
value: '/cdr/ims_cdr_event',
|
||||
value: '/log/ne_log',
|
||||
label: t('views.logManage.exportFile.neLog'),
|
||||
path: '/usr/local/omc/backup',
|
||||
},
|
||||
|
||||
{
|
||||
value: '/cdr/ims',
|
||||
label: t('views.logManage.exportFile.cdrIMS'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'IMS',
|
||||
},
|
||||
{
|
||||
value: '/cdr/smf_cdr_event',
|
||||
value: '/cdr/smf',
|
||||
label: t('views.logManage.exportFile.cdrSMF'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'SMF',
|
||||
},
|
||||
{
|
||||
value: '/cdr/smsc_cdr_event',
|
||||
value: '/cdr/smsc',
|
||||
label: t('views.logManage.exportFile.cdrSMSC'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'SMSC',
|
||||
},
|
||||
{
|
||||
value: '/cdr/sgwc_cdr_event',
|
||||
label: t('views.logManage.exportFile.cdrSGWC'),
|
||||
value: '/kpi/ims',
|
||||
label: t('views.logManage.exportFile.kpiIMS'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'SGWC',
|
||||
neType: 'IMS',
|
||||
},
|
||||
{
|
||||
value: '/kpi/amf',
|
||||
label: t('views.logManage.exportFile.kpiAMF'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'AMF',
|
||||
},
|
||||
{
|
||||
value: '/kpi/udm',
|
||||
label: t('views.logManage.exportFile.kpiUDM'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UDM',
|
||||
},
|
||||
{
|
||||
value: '/kpi/smf',
|
||||
label: t('views.logManage.exportFile.kpiSMF'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'SMF',
|
||||
},
|
||||
{
|
||||
value: '/kpi/pcf',
|
||||
label: t('views.logManage.exportFile.kpiPCF'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'PCF',
|
||||
},
|
||||
{
|
||||
value: '/kpi/upf',
|
||||
label: t('views.logManage.exportFile.kpiUPF'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UPF',
|
||||
},
|
||||
{
|
||||
value: '/kpi/mme',
|
||||
label: t('views.logManage.exportFile.kpiMME'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'MME',
|
||||
},
|
||||
{
|
||||
value: '/kpi/smsc',
|
||||
label: t('views.logManage.exportFile.kpiSMSC'),
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'SMSC',
|
||||
},
|
||||
],
|
||||
/**选择value */
|
||||
@@ -242,9 +291,31 @@ function fnRecordDelete(row: Record<string, any>) {
|
||||
});
|
||||
}
|
||||
|
||||
/**访问路径 */
|
||||
let nePathArr = ref<string[]>([]);
|
||||
/**进入目录 */
|
||||
function fnDirCD(dir: string, index?: number) {
|
||||
if (index === undefined) {
|
||||
nePathArr.value.push(dir);
|
||||
queryParams.path = nePathArr.value.join('/');
|
||||
fnGetList(1);
|
||||
return;
|
||||
}
|
||||
if (index === 0) {
|
||||
nePathArr.value = [nePathArr.value[0]];
|
||||
queryParams.path = nePathArr.value.join('/');
|
||||
fnGetList(1);
|
||||
} else {
|
||||
nePathArr.value = nePathArr.value.slice(0, index + 1);
|
||||
queryParams.path = nePathArr.value.join('/');
|
||||
fnGetList(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**网元类型选择对应修改 */
|
||||
function fnNeChange(_: any, opt: any) {
|
||||
queryParams.path = `${opt.path}${opt.value}`;
|
||||
nePathArr.value = [`${opt.path}${opt.value}`];
|
||||
queryParams.path = nePathArr.value.join('/');
|
||||
ftpInfo.path = queryParams.path;
|
||||
ftpInfo.tag = opt.value;
|
||||
fnGetList(1);
|
||||
@@ -346,8 +417,12 @@ onMounted(() => {
|
||||
<span>{{ t('views.logManage.neFile.nePath') }}:</span>
|
||||
<a-col>
|
||||
<a-breadcrumb>
|
||||
<a-breadcrumb-item>
|
||||
{{ queryParams.path }}
|
||||
<a-breadcrumb-item
|
||||
v-for="(path, index) in nePathArr"
|
||||
:key="path"
|
||||
@click="fnDirCD(path, index)"
|
||||
>
|
||||
{{ path }}
|
||||
</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</a-col>
|
||||
@@ -421,6 +496,15 @@ onMounted(() => {
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-button
|
||||
type="link"
|
||||
:loading="downLoading"
|
||||
@click.prevent="fnDirCD(record.fileName)"
|
||||
v-if="record.fileType === 'dir'"
|
||||
>
|
||||
<template #icon><FolderOutlined /></template>
|
||||
{{ t('views.logManage.neFile.dirCd') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -99,12 +99,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = reactive([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.logManage.forwarding.alarmInter'),
|
||||
dataIndex: 'type',
|
||||
|
||||
@@ -63,12 +63,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = reactive([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 80,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 80,
|
||||
// },
|
||||
{
|
||||
title: t('views.logManage.mml.account'),
|
||||
dataIndex: 'user',
|
||||
|
||||
@@ -442,6 +442,7 @@ function fnGetList() {
|
||||
/**自动完成搜索匹配前缀 */
|
||||
function fnAutoCompleteSearch(value: string) {
|
||||
state.autoCompleteSearch = [];
|
||||
return; // 回车undefined问题,关闭搜索匹配
|
||||
for (const item of state.autoCompleteData) {
|
||||
const filterOptions = item.options.filter((s: any) => {
|
||||
return `${s.operation} ${s.object}`.indexOf(value.toLowerCase()) >= 0;
|
||||
|
||||
@@ -408,6 +408,7 @@ function fnGetList() {
|
||||
/**自动完成搜索匹配前缀 */
|
||||
function fnAutoCompleteSearch(value: string) {
|
||||
state.autoCompleteSearch = [];
|
||||
return; // 回车undefined问题,关闭搜索匹配
|
||||
for (const item of state.autoCompleteData) {
|
||||
const filterOptions = item.options.filter((s: any) => {
|
||||
return `${s.operation} ${s.object}`.indexOf(value.toLowerCase()) >= 0;
|
||||
|
||||
Vendored
+18
-18
@@ -49,15 +49,15 @@ function fnCacheKeyInfo(cacheKey: string) {
|
||||
|
||||
/**键名列表表格字段列 */
|
||||
let cacheKeyTableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'num',
|
||||
width: '50px',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
return opt.index + 1;
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'num',
|
||||
// width: '50px',
|
||||
// align: 'center',
|
||||
// customRender(opt) {
|
||||
// return opt.index + 1;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: t('views.monitor.cache.cacheKey'),
|
||||
dataIndex: 'cacheKey',
|
||||
@@ -152,15 +152,15 @@ let cacheNameTable = reactive({
|
||||
|
||||
/**缓存列表表格字段列 */
|
||||
let cacheNameTableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'num',
|
||||
width: '50px',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
return opt.index + 1;
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'num',
|
||||
// width: '50px',
|
||||
// align: 'center',
|
||||
// customRender(opt) {
|
||||
// return opt.index + 1;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: t('views.monitor.cache.cacheName'),
|
||||
dataIndex: 'cacheName',
|
||||
|
||||
@@ -98,11 +98,11 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'jobId',
|
||||
align: 'center',
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'jobId',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: t('views.monitor.job.jobName'),
|
||||
dataIndex: 'jobName',
|
||||
@@ -680,14 +680,14 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
<!-- <a-button
|
||||
type="default"
|
||||
@click.prevent="fnJobLogView()"
|
||||
v-perms:has="['monitor:job:query']"
|
||||
>
|
||||
<template #icon><ContainerOutlined /></template>
|
||||
{{ t('views.monitor.job.jobLog') }}
|
||||
</a-button>
|
||||
</a-button> -->
|
||||
<a-button
|
||||
type="dashed"
|
||||
danger
|
||||
@@ -755,11 +755,13 @@ onMounted(() => {
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120 }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
:row-selection="hasPermissions(['monitor:job:remove'])
|
||||
? {
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}
|
||||
: undefined"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'jobGroup'">
|
||||
|
||||
@@ -117,12 +117,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'logId',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'logId',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.monitor.jobLog.jobName'),
|
||||
dataIndex: 'jobName',
|
||||
@@ -247,6 +247,13 @@ let modalState: ModalStateType = reactive({
|
||||
*/
|
||||
function fnModalVisibleByVive(row: Record<string, string>) {
|
||||
modalState.from = Object.assign(modalState.from, row);
|
||||
try {
|
||||
modalState.from.jobMsg = JSON.stringify(
|
||||
JSON.parse(modalState.from.jobMsg),
|
||||
null,
|
||||
4
|
||||
);
|
||||
} catch (_) {}
|
||||
modalState.title = t('views.monitor.jobLog.viewLog');
|
||||
modalState.open = true;
|
||||
}
|
||||
|
||||
@@ -41,16 +41,16 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'num',
|
||||
width: '50px',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
const idxNum = (tablePagination.current - 1) * tablePagination.pageSize;
|
||||
return idxNum + opt.index + 1;
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'num',
|
||||
// width: '50px',
|
||||
// align: 'left',
|
||||
// customRender(opt) {
|
||||
// const idxNum = (tablePagination.current - 1) * tablePagination.pageSize;
|
||||
// return idxNum + opt.index + 1;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: t('views.monitor.online.mettingId'),
|
||||
dataIndex: 'tokenId',
|
||||
|
||||
@@ -64,10 +64,50 @@ function fnGetList(refresh: boolean = false) {
|
||||
Array.isArray(res.data) &&
|
||||
res.data.length > 0
|
||||
) {
|
||||
// 根网管
|
||||
let rootNodeInfo = { neName: 'OMC_001' };
|
||||
const nodes = [];
|
||||
const edges = [];
|
||||
|
||||
// 根网管
|
||||
let rootNodeInfo = {
|
||||
neName: 'ROOT',
|
||||
serverState: {
|
||||
online: true,
|
||||
},
|
||||
};
|
||||
// 处理没有OMC的情况
|
||||
const omcFilter = res.data.filter(v => v.neType === 'OMC');
|
||||
if (omcFilter.length === 1) {
|
||||
rootNodeInfo.neName = omcFilter[0].neName;
|
||||
} else {
|
||||
nodes.unshift({
|
||||
id: rootNodeInfo.neName,
|
||||
label: rootNodeInfo.neName,
|
||||
info: rootNodeInfo,
|
||||
labelCfg: {
|
||||
position: 'bottom',
|
||||
offset: 8,
|
||||
style: {
|
||||
fill: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
size: 60,
|
||||
icon: {
|
||||
x: -30,
|
||||
y: -30,
|
||||
// 可更换为其他图片地址
|
||||
img: parseBasePath('/svg/service_db.svg'),
|
||||
width: 60,
|
||||
height: 60,
|
||||
},
|
||||
});
|
||||
edges.push({
|
||||
source: rootNodeInfo.neName,
|
||||
target: rootNodeInfo.neName,
|
||||
label: `${rootNodeInfo.neName}-${rootNodeInfo.neName}`,
|
||||
});
|
||||
}
|
||||
|
||||
for (const item of res.data) {
|
||||
item.serverState = {};
|
||||
// 节点
|
||||
@@ -96,7 +136,6 @@ function fnGetList(refresh: boolean = false) {
|
||||
height: 60,
|
||||
},
|
||||
});
|
||||
!rootNodeInfo.neName && (rootNodeInfo = item);
|
||||
} else {
|
||||
nodes.push({
|
||||
id: item.neName,
|
||||
|
||||
@@ -143,11 +143,10 @@ const graphNodeTooltip = new Tooltip({
|
||||
"
|
||||
>
|
||||
<div><strong>${t('views.monitor.topology.state')}:</strong><span>
|
||||
${
|
||||
neState.online
|
||||
? t('views.monitor.topology.normalcy')
|
||||
: t('views.monitor.topology.exceptions')
|
||||
}
|
||||
${neState.online
|
||||
? t('views.monitor.topology.normalcy')
|
||||
: t('views.monitor.topology.exceptions')
|
||||
}
|
||||
</span></div>
|
||||
<div><strong>${t('views.monitor.topology.refreshTime')}:</strong><span>
|
||||
${neState.refreshTime ?? '--'}
|
||||
@@ -399,11 +398,10 @@ function wsMessage(res: Record<string, any>) {
|
||||
const [neType, neId] = requestId.split('_');
|
||||
const { combos, edges, nodes } = graphState.data;
|
||||
const node = nodes.find((item: Record<string, any>) => item.id === neType);
|
||||
|
||||
console.log(data)
|
||||
// 更新网元状态
|
||||
const newNeState = Object.assign(node.neState, data, {
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'),
|
||||
online: !!data.cpu,
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'MM-DD HH:mm:ss'),
|
||||
});
|
||||
|
||||
// 通过 ID 查询节点实例
|
||||
@@ -505,11 +503,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px' }"
|
||||
size="small"
|
||||
>
|
||||
<a-card :bordered="false" :body-style="{ marginBottom: '24px' }" size="small">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
@@ -521,12 +515,10 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click.prevent="fnGraphDataLoad(true)"
|
||||
>
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<a-button type="default" size="small" @click.prevent="fnGraphDataLoad(true)">
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
{{ t('common.reloadText') }}
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,592 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch, ref } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { Form, message } from 'ant-design-vue/es';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useNeListStore from '@/store/modules/ne_list';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import {
|
||||
getNeConfigData,
|
||||
addNeConfigData,
|
||||
editNeConfigData,
|
||||
} from '@/api/ne/neConfig';
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
/**网元类型_多neId */
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**网元类型 */
|
||||
neType: string[];
|
||||
/**需要配置的网元列表 */
|
||||
toNe: {
|
||||
neType: string;
|
||||
neId: string;
|
||||
}[];
|
||||
/**提示信息 */
|
||||
msg: string;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: 'PLMN Info',
|
||||
from: {
|
||||
plmnId: {
|
||||
mcc: '001',
|
||||
mnc: '01',
|
||||
},
|
||||
tac: '4388',
|
||||
snssai: {
|
||||
sst: '1',
|
||||
sd: '000001',
|
||||
},
|
||||
dnn_data: 'internet',
|
||||
dnn_ims: 'ims',
|
||||
},
|
||||
neType: [],
|
||||
toNe: [],
|
||||
msg: '',
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from.plmnId,
|
||||
reactive({
|
||||
mcc: [
|
||||
{
|
||||
required: true,
|
||||
message: t('common.inputPlease'),
|
||||
},
|
||||
],
|
||||
mnc: [
|
||||
{
|
||||
required: true,
|
||||
message: t('common.inputPlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**网元类型选择对应修改 */
|
||||
function fnNeChange(p: any, c: any) {
|
||||
let neList: { neType: string; neId: string }[] = [];
|
||||
for (let i = 0; i < p.length; i++) {
|
||||
const v = p[i];
|
||||
if (v.length === 1) {
|
||||
c[i][0].children.forEach((item: any) => {
|
||||
neList.push({
|
||||
neType: item.neType,
|
||||
neId: item.neId,
|
||||
});
|
||||
});
|
||||
} else if (v.length === 2) {
|
||||
neList.push({
|
||||
neType: v[0],
|
||||
neId: v[1],
|
||||
});
|
||||
}
|
||||
}
|
||||
if (neList.length > 0) {
|
||||
modalState.toNe = neList;
|
||||
} else {
|
||||
modalState.toNe = [];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalOk() {
|
||||
if (modalState.confirmLoading) return;
|
||||
if (modalState.toNe.length === 0) {
|
||||
message.warning({
|
||||
content: 'Please select NE',
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const form = toRaw(modalState.from);
|
||||
// console.log(form);
|
||||
|
||||
modalStateFrom
|
||||
.validate()
|
||||
.then(async () => {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
let errArr = [];
|
||||
for (const item of modalState.toNe) {
|
||||
const err = await toConfig(item.neType, item.neId, form);
|
||||
if (err.length > 0) {
|
||||
errArr.push(...err);
|
||||
}
|
||||
}
|
||||
modalState.msg = errArr.join('\n');
|
||||
modalState.confirmLoading = false;
|
||||
emit('ok', JSON.parse(JSON.stringify(form)));
|
||||
hide();
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalStateFrom.resetFields();
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
// 还原默认值
|
||||
modalState.from = {
|
||||
plmnId: {
|
||||
mcc: '001',
|
||||
mnc: '01',
|
||||
},
|
||||
tac: '4388',
|
||||
snssai: {
|
||||
sst: '1',
|
||||
sd: '000001',
|
||||
},
|
||||
dnn_data: 'internet',
|
||||
dnn_ims: 'ims',
|
||||
};
|
||||
modalState.neType = [];
|
||||
modalState.toNe = [];
|
||||
modalState.msg = '';
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
// 获取网元网元列表
|
||||
neCascaderOptions.value = neListStore.getNeCascaderOptions.filter(
|
||||
(item: any) => {
|
||||
return ['MME', 'AMF', 'UDM', 'IMS'].includes(item.value); // 过滤不可用的网元
|
||||
}
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
modalState.openByEdit = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// =============== 处理函数
|
||||
|
||||
const supportMapper: Record<string, any> = {
|
||||
AMF: [
|
||||
{
|
||||
type: 'array',
|
||||
name: 'guami',
|
||||
display: 'GUAMI List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
pointer: lastItem.pointer,
|
||||
regionId: lastItem.regionId,
|
||||
setId: lastItem.setId,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
name: 'tai',
|
||||
display: 'TAI List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
tac: param.tac,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
name: 'slice',
|
||||
display: 'Slice List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
const sdStr = param.snssai.sd.padStart(6, '0');
|
||||
return {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
sst: parseInt(param.snssai.sst),
|
||||
sd: sdStr,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
IMS: [
|
||||
{
|
||||
type: 'array',
|
||||
name: 'plmn',
|
||||
display: 'PLMN List',
|
||||
key: ['mcc', 'mnc'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
const mccDomain = param.plmnId.mcc.padStart(3, '0');
|
||||
const domain = `ims.mnc${param.plmnId.mnc}.mcc${mccDomain}.3gppnetwork.org`;
|
||||
return {
|
||||
index: index,
|
||||
domain: domain,
|
||||
mcc: param.plmnId.mcc,
|
||||
mnc: param.plmnId.mnc,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
UDM: [
|
||||
{
|
||||
type: 'list',
|
||||
name: 'system',
|
||||
display: 'System',
|
||||
key: [
|
||||
'supportedPlmn1',
|
||||
'supportedPlmn2',
|
||||
'supportedPlmn3',
|
||||
'supportedPlmn4',
|
||||
],
|
||||
},
|
||||
],
|
||||
MME: [
|
||||
{
|
||||
type: 'array',
|
||||
name: 'gummei',
|
||||
display: 'Gummei List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return Object.assign(lastItem, {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
name: 'tai',
|
||||
display: 'TAI List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
tac: parseInt(param.tac),
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
name: 'hss',
|
||||
display: 'HSS List',
|
||||
key: ['imsiPre'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return Object.assign(lastItem, {
|
||||
index: index,
|
||||
imsiPre: plmn,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
name: 'sgw',
|
||||
display: 'SGW List',
|
||||
key: ['plmnId'],
|
||||
item: (index: any, param: any, lastItem: any) => {
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
return Object.assign(lastItem, {
|
||||
index: index,
|
||||
plmnId: plmn,
|
||||
tac: parseInt(param.tac),
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async function toConfig(
|
||||
ntType: string,
|
||||
neId: string,
|
||||
param: Record<string, any>
|
||||
) {
|
||||
let errMsgArr = [];
|
||||
const plmn = `${param.plmnId.mcc}${param.plmnId.mnc}`;
|
||||
for (const rule of supportMapper[ntType]) {
|
||||
const res = await getNeConfigData({
|
||||
neType: ntType,
|
||||
neId: neId,
|
||||
paramName: rule.name,
|
||||
});
|
||||
if (res.code != RESULT_CODE_SUCCESS) {
|
||||
// console.log('获取数据失败', rule);
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} get data failed`);
|
||||
continue;
|
||||
}
|
||||
if (res.data.length === 0) {
|
||||
// console.log('数据为空', rule);
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} data empty`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rule.type === 'list') {
|
||||
// key
|
||||
const data = res.data[0];
|
||||
let vArr = [];
|
||||
for (const k of rule.key) {
|
||||
vArr.push(data[k]);
|
||||
}
|
||||
if (vArr.includes(plmn)) {
|
||||
// console.log('存在跳过', rule.name, vArr, plmn);
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} already exists`);
|
||||
continue;
|
||||
}
|
||||
if (vArr.includes('')) {
|
||||
const index = vArr.findIndex(s => s == '');
|
||||
// console.log('空白新增', rule.name, rule.key[index], plmn);
|
||||
const resList = await editNeConfigData({
|
||||
neType: ntType,
|
||||
neId: neId,
|
||||
paramName: rule.name,
|
||||
paramData: {
|
||||
[rule.key[index]]: plmn,
|
||||
},
|
||||
});
|
||||
const state =
|
||||
resList.code != RESULT_CODE_SUCCESS ? 'failed' : 'success';
|
||||
errMsgArr.push(
|
||||
`${ntType}_${neId} ${rule.display} blank items added ${state}`
|
||||
);
|
||||
} else {
|
||||
// console.log(
|
||||
// '不存在替换最后的',
|
||||
// rule.name,
|
||||
// rule.key[rule.key.length - 1],
|
||||
// plmn
|
||||
// );
|
||||
const resList = await editNeConfigData({
|
||||
neType: ntType,
|
||||
neId: neId,
|
||||
paramName: rule.name,
|
||||
paramData: {
|
||||
[rule.key[rule.key.length - 1]]: plmn,
|
||||
},
|
||||
});
|
||||
const state =
|
||||
resList.code != RESULT_CODE_SUCCESS ? 'failed' : 'success';
|
||||
errMsgArr.push(
|
||||
`${ntType}_${neId} ${rule.display} replace the final ${state}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (rule.type === 'array') {
|
||||
// item
|
||||
let vArr = [];
|
||||
for (const item of res.data) {
|
||||
vArr.push(item[rule.key]);
|
||||
}
|
||||
if (vArr.includes(plmn)) {
|
||||
const item = res.data.find((s: any) => s[rule.key] == plmn);
|
||||
if (!item) {
|
||||
// console.log('没有找到', rule.name, index);
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} not found`);
|
||||
continue;
|
||||
}
|
||||
const index = item.index;
|
||||
const updateItem = rule.item(index, param, item);
|
||||
// console.log('存在修改', rule.name, index, updateItem);
|
||||
const resList = await editNeConfigData({
|
||||
neType: ntType,
|
||||
neId: neId,
|
||||
paramName: rule.name,
|
||||
paramData: updateItem,
|
||||
loc: `${index}`,
|
||||
});
|
||||
const state =
|
||||
resList.code != RESULT_CODE_SUCCESS ? 'failed' : 'success';
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} modify ${state}`);
|
||||
} else {
|
||||
let lastIndex = 0;
|
||||
const arr = res.data.sort((a: any, b: any) => b.index - a.index);
|
||||
if (arr.length != 0) {
|
||||
lastIndex = arr[0].index + 1;
|
||||
}
|
||||
const addItem = rule.item(lastIndex, param, arr[0]);
|
||||
// console.log('不存在新增', rule.name, lastIndex, addItem);
|
||||
const resList = await addNeConfigData({
|
||||
neType: ntType,
|
||||
neId: neId,
|
||||
paramName: rule.name,
|
||||
paramData: addItem,
|
||||
loc: `${lastIndex}`,
|
||||
});
|
||||
const state =
|
||||
resList.code != RESULT_CODE_SUCCESS ? 'failed' : 'success';
|
||||
errMsgArr.push(`${ntType}_${neId} ${rule.display} added ${state}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return errMsgArr;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFromByEdit"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="DNN_DATA" name="basic.dnn_data" v-if="false">
|
||||
<a-input
|
||||
v-model:value="modalState.from.dnn_data"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> DNN </template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="MCC"
|
||||
name="basic.plmnId.mcc"
|
||||
v-bind="modalStateFrom.validateInfos.mcc"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.plmnId.mcc"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="SST" name="basic.snssai.sst">
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.snssai.sst"
|
||||
:min="1"
|
||||
:max="3"
|
||||
placeholder="1-3"
|
||||
style="width: 100%"
|
||||
>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label="TAC" name="basic.tac">
|
||||
<a-input
|
||||
v-model:value="modalState.from.tac"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="DNN_IMS" name="basic.dnn_ims" v-if="false">
|
||||
<a-input
|
||||
v-model:value="modalState.from.dnn_ims"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="50"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="MNC"
|
||||
name="basic.plmnId.mnc"
|
||||
v-bind="modalStateFrom.validateInfos.mnc"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.plmnId.mnc"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="SD" name="basic.snssai.sd">
|
||||
<a-input
|
||||
v-model:value="modalState.from.snssai.sd"
|
||||
placeholder="1-65535"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="left">To NE</a-divider>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neType')"
|
||||
name="neType"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="modalState.neType"
|
||||
:options="neCascaderOptions"
|
||||
@change="fnNeChange"
|
||||
multiple
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.ne.common.neTypePlease')"
|
||||
/>
|
||||
<a-textarea
|
||||
:disabled="true"
|
||||
:hidden="!modalState.msg"
|
||||
:value="modalState.msg"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="margin-top: 8px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -24,7 +24,7 @@ export default function useArrayImport({
|
||||
fileetx: '.xlsx',
|
||||
itemKey: 'index',
|
||||
item: (row: Record<string, any>) => {
|
||||
const index = row['Index'] || 0;
|
||||
const index = row['Index'] ?? -1;
|
||||
return {
|
||||
imeiPrefixValue: `${row['IMEI Prefix']}`,
|
||||
index: parseInt(index),
|
||||
@@ -36,7 +36,7 @@ export default function useArrayImport({
|
||||
fileetx: '.xlsx',
|
||||
itemKey: 'index',
|
||||
item: (row: Record<string, any>) => {
|
||||
const index = row['Index'] || 0;
|
||||
const index = row['Index'] ?? -1;
|
||||
return {
|
||||
imsiValue: `${row['IMSI Value']}`,
|
||||
imeiValue: `${row['IMEI Value/Prefix']}`,
|
||||
@@ -51,7 +51,7 @@ export default function useArrayImport({
|
||||
fileetx: '.xlsx',
|
||||
itemKey: 'index',
|
||||
item: (row: Record<string, any>) => {
|
||||
const index = row['Index'] || 0;
|
||||
const index = row['Index'] ?? -1;
|
||||
return {
|
||||
imei: `${row['IMEI']}`,
|
||||
index: parseInt(index),
|
||||
@@ -128,7 +128,7 @@ export default function useArrayImport({
|
||||
importState.loading = true;
|
||||
for (const row of rows) {
|
||||
const rowItem = importState.item(row);
|
||||
const rowKey = rowItem[importState.itemKey] || -1;
|
||||
const rowKey = rowItem[importState.itemKey];
|
||||
let result: any = null;
|
||||
// 检查index是否定义
|
||||
const has = arrayState.columnsData.find(
|
||||
|
||||
@@ -29,8 +29,13 @@ export default function useOptions({ t }: any) {
|
||||
case 'int':
|
||||
// filter: "0~128"
|
||||
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
const filterArr = filter.split('~');
|
||||
if (filter) {
|
||||
let filterArr = ['0', '1'];
|
||||
if (filter.indexOf('-') !== -1) {
|
||||
filterArr = filter.split('-');
|
||||
} else if (filter.indexOf('~') !== -1) {
|
||||
filterArr = filter.split('~');
|
||||
}
|
||||
const minInt = parseInt(filterArr[0]);
|
||||
const maxInt = parseInt(filterArr[1]);
|
||||
const valueInt = parseInt(value);
|
||||
@@ -47,18 +52,12 @@ export default function useOptions({ t }: any) {
|
||||
break;
|
||||
case 'ipv4':
|
||||
if (!regExpIPv4.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireIpv4', { display }),
|
||||
];
|
||||
return [false, t('views.ne.neConfig.requireIpv4', { display })];
|
||||
}
|
||||
break;
|
||||
case 'ipv6':
|
||||
if (!regExpIPv6.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireIpv6', { display }),
|
||||
];
|
||||
return [false, t('views.ne.neConfig.requireIpv6', { display })];
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
@@ -71,10 +70,7 @@ export default function useOptions({ t }: any) {
|
||||
}
|
||||
|
||||
if (!Object.keys(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireEnum', { display }),
|
||||
];
|
||||
return [false, t('views.ne.neConfig.requireEnum', { display })];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -90,10 +86,7 @@ export default function useOptions({ t }: any) {
|
||||
}
|
||||
|
||||
if (!Object.values(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireBool', { display }),
|
||||
];
|
||||
return [false, t('views.ne.neConfig.requireBool', { display })];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -101,12 +94,20 @@ export default function useOptions({ t }: any) {
|
||||
// filter: "0~128"
|
||||
|
||||
// 字符串长度判断
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
if (filter) {
|
||||
try {
|
||||
const filterArr = filter.split('~');
|
||||
let rule = new RegExp(
|
||||
'^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$'
|
||||
);
|
||||
let rule: RegExp = new RegExp('^.*$');
|
||||
if (filter.indexOf('-') !== -1) {
|
||||
const filterArr = filter.split('-');
|
||||
rule = new RegExp(
|
||||
'^.{' + filterArr[0] + ',' + filterArr[1] + '}$'
|
||||
);
|
||||
} else if (filter.indexOf('~') !== -1) {
|
||||
const filterArr = filter.split('~');
|
||||
rule = new RegExp(
|
||||
'^\\S{' + filterArr[0] + ',' + filterArr[1] + '}$'
|
||||
);
|
||||
}
|
||||
if (!rule.test(value)) {
|
||||
return [
|
||||
false,
|
||||
@@ -157,10 +158,7 @@ export default function useOptions({ t }: any) {
|
||||
break;
|
||||
|
||||
default:
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireUn', { display }),
|
||||
];
|
||||
return [false, t('views.ne.neConfig.requireUn', { display })];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { message } from 'ant-design-vue/es';
|
||||
import { DataNode } from 'ant-design-vue/es/tree';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import QuickSetup from './components/QuickSetup.vue';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeListStore from '@/store/modules/ne_list';
|
||||
import useOptions from './hooks/useOptions';
|
||||
@@ -208,7 +209,7 @@ function fnActiveConfigNode(key: string | number) {
|
||||
|
||||
/**查询配置可选属性值列表 */
|
||||
function fnGetNeConfig() {
|
||||
const neType = neTypeSelect.value[0];
|
||||
const [neType, neId] = neTypeSelect.value ;
|
||||
if (!neType) {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.neTypePleace'),
|
||||
@@ -219,7 +220,7 @@ function fnGetNeConfig() {
|
||||
|
||||
treeState.loading = true;
|
||||
// 获取数据
|
||||
getAllNeConfig(neType).then(res => {
|
||||
getAllNeConfig(neType, neId).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
const arr = [];
|
||||
for (const item of res.data) {
|
||||
@@ -391,6 +392,12 @@ const { batchState, modalBatchOpen, modalBatchClose, modalBatchOk } =
|
||||
fnActiveConfigNode,
|
||||
});
|
||||
|
||||
/**快速修改编辑框 */
|
||||
const quickOpen = ref(false);
|
||||
function fnQuickOpen() {
|
||||
quickOpen.value = !quickOpen.value;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
neCascaderOptions.value = neListStore.getNeCascaderOptions.filter(
|
||||
@@ -430,6 +437,13 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<template #content> </template>
|
||||
<template #contentExtra>
|
||||
<a-button type="primary" @click="fnQuickOpen">
|
||||
Quickly Modify PLMN
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col
|
||||
:lg="6"
|
||||
@@ -1053,6 +1067,9 @@ onMounted(() => {
|
||||
</a-row>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
|
||||
<!-- 快速修改 -->
|
||||
<QuickSetup v-model:open="quickOpen"></QuickSetup>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -73,12 +73,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
@@ -303,12 +303,8 @@ function fnModalVisibleByEdit(row: Record<string, any>) {
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称',
|
||||
},
|
||||
],
|
||||
name: [{ required: true, message: t('common.inputPlease') }],
|
||||
remark: [{ required: true, message: t('common.inputPlease') }],
|
||||
})
|
||||
);
|
||||
|
||||
@@ -462,7 +458,11 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
||||
<template #title>
|
||||
{{ t('views.ne.neConfigBackup.backupModal.title') }}
|
||||
</template>
|
||||
<a-button type="text" @click.prevent="fnFTPModalOpen()">
|
||||
<a-button
|
||||
type="text"
|
||||
@click.prevent="fnFTPModalOpen()"
|
||||
v-perms:has="['ne:neConfigBackup:ftp']"
|
||||
>
|
||||
<template #icon><DeliveredProcedureOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
@@ -524,13 +524,21 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
||||
<template #title>
|
||||
{{ t('views.ne.neConfigBackup.backupModal.pushFileOper') }}
|
||||
</template>
|
||||
<a-button type="link" @click.prevent="fnSyncFileToFTP(record)">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnSyncFileToFTP(record)"
|
||||
v-perms:has="['ne:neConfigBackup:ftpSync']"
|
||||
>
|
||||
<template #icon><CloudServerOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.downloadText') }}</template>
|
||||
<a-button type="link" @click.prevent="fnDownloadFile(record)">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnDownloadFile(record)"
|
||||
v-perms:has="['ne:neConfigBackup:download']"
|
||||
>
|
||||
<template #icon><DownloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
@@ -226,7 +226,8 @@ async function fnGetNeConfig(neType: string) {
|
||||
|
||||
treeState.loading = true;
|
||||
// 获取数据
|
||||
const res = await getAllNeConfig(neType);
|
||||
let neId = neTypeSelect.value[1];
|
||||
const res = await getAllNeConfig(neType, neId);
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
const arr = [];
|
||||
for (const v of res.data) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeListStore from '@/store/modules/ne_list';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import ViewDrawer from './components/ViewDrawer.vue';
|
||||
import BackupModal from '@/views/ne/neConfigBackup/components/BackupModal.vue';
|
||||
import saveAs from 'file-saver';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { parseSizeFromFile } from '@/utils/parse-utils';
|
||||
@@ -282,6 +283,12 @@ function fnDrawerOpen(row: Record<string, any>) {
|
||||
viewDrawerState.open = !viewDrawerState.open;
|
||||
}
|
||||
|
||||
/**打开FTP配置窗口 */
|
||||
const openFTPModal = ref<boolean>(false);
|
||||
function fnFTPModalOpen() {
|
||||
openFTPModal.value = !openFTPModal.value;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (routeParams.neType) {
|
||||
neTypeSelect.value = [routeParams.neType, routeParams.neId];
|
||||
@@ -327,6 +334,18 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip placement="topRight">
|
||||
<template #title>
|
||||
{{ t('views.ne.neConfigBackup.backupModal.title') }}
|
||||
</template>
|
||||
<a-button
|
||||
type="text"
|
||||
@click.prevent="fnFTPModalOpen()"
|
||||
v-perms:has="['ne-data:backup-data:ftp']"
|
||||
>
|
||||
<template #icon><DeliveredProcedureOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
@@ -387,6 +406,9 @@ onMounted(() => {
|
||||
:ne-type="viewDrawerState.neType"
|
||||
:ne-id="viewDrawerState.neId"
|
||||
></ViewDrawer>
|
||||
|
||||
<!-- FTP配置窗口 -->
|
||||
<BackupModal v-model:open="openFTPModal"></BackupModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -80,12 +80,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
width: 50,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'center',
|
||||
// width: 50,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.neHost.hostType'),
|
||||
dataIndex: 'hostType',
|
||||
|
||||
@@ -78,12 +78,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'cmdId',
|
||||
align: 'center',
|
||||
width: 50,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'cmdId',
|
||||
// align: 'center',
|
||||
// width: 50,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.neHostCmd.cmdType'),
|
||||
dataIndex: 'cmdType',
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch, ref } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Form, Progress } from 'ant-design-vue/es';
|
||||
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { getOAMFile, saveOAMFile, serviceNeAction } from '@/api/ne/neInfo';
|
||||
import useNeListStore from '@/store/modules/ne_list';
|
||||
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: {
|
||||
selectedNeList: string[];
|
||||
omcIP: string;
|
||||
oamPort: number;
|
||||
restart: boolean;
|
||||
};
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**进度显示 */
|
||||
progress: {
|
||||
visible: boolean;
|
||||
current: number;
|
||||
total: number;
|
||||
currentNe: string;
|
||||
};
|
||||
/**操作结果 */
|
||||
results: Array<{
|
||||
neType: string;
|
||||
neId: string;
|
||||
neName: string;
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: '快速OAM配置',
|
||||
from: {
|
||||
selectedNeList: [],
|
||||
omcIP: '127.0.0.1',
|
||||
oamPort: 33030,
|
||||
restart: false,
|
||||
},
|
||||
confirmLoading: false,
|
||||
progress: {
|
||||
visible: false,
|
||||
current: 0,
|
||||
total: 0,
|
||||
currentNe: '',
|
||||
},
|
||||
results: [],
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
selectedNeList: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.neInfo.quickOam.selectNe'),
|
||||
},
|
||||
],
|
||||
omcIP: [
|
||||
{
|
||||
required: true,
|
||||
|
||||
},
|
||||
{
|
||||
pattern: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
|
||||
|
||||
},
|
||||
],
|
||||
oamPort: [
|
||||
{
|
||||
required: true,
|
||||
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**获取网元列表选项 */
|
||||
const neOptions = ref<Array<{ label: string; value: string; neType: string; neId: string; neName: string }>>([]);
|
||||
|
||||
/**
|
||||
* 初始化网元选项
|
||||
*/
|
||||
async function initNeOptions() {
|
||||
// 确保网元列表已加载
|
||||
await neListStore.fnNelistRefresh();
|
||||
// 从store获取网元列表,过滤掉OMC类型
|
||||
const neList = neListStore.getNeList.filter((ne: any) => ne.neType !== 'OMC');
|
||||
neOptions.value = neList.map((ne: any) => ({
|
||||
label: `${ne.neType}-${ne.neId} (${ne.neName})`,
|
||||
value: `${ne.neType}@${ne.neId}`,
|
||||
neType: ne.neType,
|
||||
neId: ne.neId,
|
||||
neName: ne.neName,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个网元OAM配置(复用OAMModal的逻辑)
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @param omcIP OMC IP地址
|
||||
* @param oamPort OAM端口
|
||||
* @param restart 是否重启网元
|
||||
* @returns Promise<{success: boolean, message: string}>
|
||||
*/
|
||||
async function configureSingleNeOAM(neType: string, neId: string, omcIP: string, oamPort: number, restart: boolean = false) {
|
||||
try {
|
||||
// 1. 获取当前OAM配置(复用OAMModal的获取逻辑)
|
||||
const getRes = await getOAMFile(neType, neId);
|
||||
|
||||
if (getRes.code !== RESULT_CODE_SUCCESS) {
|
||||
return {
|
||||
success: false,
|
||||
message: `${getRes.msg}`,
|
||||
};
|
||||
}
|
||||
|
||||
// 2. 构建保存数据(复用OAMModal的数据结构转换逻辑)
|
||||
const data = getRes.data;
|
||||
const ipType = data?.oamConfig?.ipType || 'ipv4';
|
||||
|
||||
const saveContent = {
|
||||
omcIP: omcIP,
|
||||
oamEnable: data?.oamConfig?.enable || false,
|
||||
oamPort: oamPort,
|
||||
snmpEnable: data?.snmpConfig?.enable || false,
|
||||
snmpPort: data?.snmpConfig?.port || 4957,
|
||||
kpiEnable: data?.kpiConfig?.enable || false,
|
||||
kpiTimer: data?.kpiConfig?.timer || 60,
|
||||
};
|
||||
|
||||
// 3. 保存配置(复用OAMModal的保存逻辑)
|
||||
const saveRes = await saveOAMFile({
|
||||
neType,
|
||||
neId,
|
||||
content: saveContent,
|
||||
sync: true,
|
||||
});
|
||||
|
||||
if (saveRes.code === RESULT_CODE_SUCCESS) {
|
||||
// 如果需要重启网元,调用重启服务(复用OAMModal的重启逻辑)
|
||||
if (restart) {
|
||||
try {
|
||||
await serviceNeAction({
|
||||
neType,
|
||||
neId,
|
||||
action: 'restart',
|
||||
});
|
||||
} catch (restartError: any) {
|
||||
return {
|
||||
success: true,
|
||||
message: `${restartError.message || restartError}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: restart ? `${t('views.ne.neInfo.quickOam.success')}` : `${t('views.ne.neInfo.quickOam.success')}`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: `${saveRes.msg}`,
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
message: `${error.message || error}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
async function fnModalOk() {
|
||||
try {
|
||||
await modalStateFrom.validate();
|
||||
|
||||
modalState.confirmLoading = true;
|
||||
modalState.progress.visible = true;
|
||||
modalState.progress.current = 0;
|
||||
modalState.progress.total = modalState.from.selectedNeList.length;
|
||||
modalState.results = [];
|
||||
|
||||
const { omcIP, oamPort, restart } = modalState.from;
|
||||
|
||||
// 循环处理每个选中的网元
|
||||
for (let i = 0; i < modalState.from.selectedNeList.length; i++) {
|
||||
const neInfo = modalState.from.selectedNeList[i];
|
||||
const [neType, neId] = neInfo.split('@');
|
||||
const neName = neOptions.value.find(opt => opt.value === neInfo)?.neName || neId;
|
||||
|
||||
modalState.progress.current = i + 1;
|
||||
modalState.progress.currentNe = `${neType}-${neId}`;
|
||||
|
||||
// 调用单个网元配置函数
|
||||
const result = await configureSingleNeOAM(neType, neId, omcIP, oamPort, restart);
|
||||
|
||||
modalState.results.push({
|
||||
neType,
|
||||
neId,
|
||||
neName,
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
});
|
||||
}
|
||||
|
||||
// 显示操作结果
|
||||
const successCount = modalState.results.filter(r => r.success).length;
|
||||
const failCount = modalState.results.length - successCount;
|
||||
|
||||
if (failCount === 0) {
|
||||
message.success(`${t('views.ne.neInfo.quickOam.success')} ${successCount} `, 5);
|
||||
} else {
|
||||
message.warning(`${t('views.ne.neInfo.quickOam.success')} ${successCount} ,${t('views.ne.neInfo.quickOam.default')} ${failCount} `, 5);
|
||||
}
|
||||
|
||||
// 不自动关闭弹窗,让用户查看结果
|
||||
// emit('ok');
|
||||
// fnModalCancel();
|
||||
} catch (error: any) {
|
||||
message.error(t('common.errorFields', { num: error.errorFields?.length || 0 }), 3);
|
||||
} finally {
|
||||
modalState.confirmLoading = false;
|
||||
modalState.progress.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalState.progress.visible = false;
|
||||
modalState.progress.current = 0;
|
||||
modalState.progress.total = 0;
|
||||
modalState.progress.currentNe = '';
|
||||
modalState.results = [];
|
||||
modalStateFrom.resetFields();
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动关闭弹窗(用于操作完成后)
|
||||
*/
|
||||
function fnModalClose() {
|
||||
fnModalCancel();
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
initNeOptions();
|
||||
modalState.title = t('views.ne.neInfo.quickOam.title');
|
||||
modalState.openByEdit = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
:width='500'
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 8 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.restart')"
|
||||
name="restart"
|
||||
>
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="modalState.from.restart"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.quickOam.omcIP')"
|
||||
name="omcIP"
|
||||
v-bind="modalStateFrom.validateInfos.omcIP"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.omcIP"
|
||||
:maxlength="128"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.quickOam.oamPort')"
|
||||
name="oamPort"
|
||||
v-bind="modalStateFrom.validateInfos.oamPort"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.oamPort"
|
||||
:min="3000"
|
||||
:max="65535"
|
||||
:step="1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.quickOam.selectNe')"
|
||||
name="selectedNeList"
|
||||
v-bind="modalStateFrom.validateInfos.selectedNeList"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.selectedNeList"
|
||||
mode="multiple"
|
||||
:options="neOptions"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:max-tag-count="3"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- 进度显示 -->
|
||||
<div v-if="modalState.progress.visible || modalState.results.length > 0" style="margin-top: 20px;">
|
||||
<a-divider>{{ t('views.ne.neInfo.quickOam.progress') }}</a-divider>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span>{{ t('views.ne.neInfo.quickOam.processing') }}: {{ modalState.progress.currentNe }}</span>
|
||||
<span style="float: right;">
|
||||
{{ modalState.progress.current }} / {{ modalState.progress.total }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- <Progress-->
|
||||
<!-- :percent="Math.round((modalState.progress.current / modalState.progress.total) * 100)"-->
|
||||
<!-- :status="modalState.progress.current === modalState.progress.total ? 'success' : 'active'"-->
|
||||
<!-- :show-info="false"-->
|
||||
<!-- style="overflow: hidden;"-->
|
||||
<!-- />-->
|
||||
<div style="width: 100%; overflow: hidden;">
|
||||
<Progress
|
||||
:percent="Math.round((modalState.progress.current / modalState.progress.total) * 100)"
|
||||
:status="modalState.progress.current === modalState.progress.total ? 'success' : 'active'"
|
||||
:show-info="false"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作结果 -->
|
||||
<div v-if="modalState.results.length > 0" style="margin-top: 20px;">
|
||||
<a-divider>{{ t('views.ne.neInfo.quickOam.result') }}</a-divider>
|
||||
<div style="max-height: 200px; overflow-y: auto;">
|
||||
<!-- 只显示失败的网元 -->
|
||||
<div
|
||||
v-for="(result, index) in modalState.results.filter(r => !r.success)"
|
||||
:key="index"
|
||||
style="margin-bottom: 8px; padding: 8px; border-radius: 4px;"
|
||||
:style="{
|
||||
backgroundColor: '#fff2f0',
|
||||
border: '1px solid #ffccc7',
|
||||
}"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>
|
||||
<CloseCircleOutlined
|
||||
:style="{ color: '#ff4d4f', marginRight: '8px' }"
|
||||
/>
|
||||
{{ result.neType }}-{{ result.neId }} ({{ result.neName }})
|
||||
</span>
|
||||
<span :style="{ color: '#ff4d4f', fontSize: '12px' }">
|
||||
{{ result.message }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 如果没有失败的网元,显示提示信息 -->
|
||||
<div
|
||||
v-if="modalState.results.filter(r => !r.success).length === 0"
|
||||
style="text-align: center; padding: 20px; color: #52c41a;"
|
||||
>
|
||||
<CheckCircleOutlined :style="{ marginRight: '8px' }" />
|
||||
{{ t('views.ne.neInfo.quickOam.allsuccess') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-progress-text {
|
||||
color: #1890ff;
|
||||
}
|
||||
</style>
|
||||
+114
-151
@@ -1,5 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, defineAsyncComponent, ref } from 'vue';
|
||||
import {
|
||||
reactive,
|
||||
onMounted,
|
||||
toRaw,
|
||||
defineAsyncComponent,
|
||||
ref,
|
||||
} from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
@@ -11,6 +17,7 @@ import useNeListStore from '@/store/modules/ne_list';
|
||||
import { listNeInfo, delNeInfo, stateNeInfo } from '@/api/ne/neInfo';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeOptions from './hooks/useNeOptions';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
const { getDict } = useDictStore();
|
||||
const neListStore = useNeListStore();
|
||||
const { t } = useI18n();
|
||||
@@ -33,6 +40,10 @@ const OAMModal = defineAsyncComponent(
|
||||
const BackConfModal = defineAsyncComponent(
|
||||
() => import('./components/BackConfModal.vue')
|
||||
);
|
||||
// 快速OAM配置
|
||||
const QuickOAMModal = defineAsyncComponent(
|
||||
() => import('./components/QuickOAMModal.vue')
|
||||
);
|
||||
const backConf = ref(); // 引用句柄,取导出函数
|
||||
|
||||
/**字典数据 */
|
||||
@@ -186,6 +197,8 @@ type ModalStateType = {
|
||||
openByBackConf: boolean;
|
||||
/**OAM文件配置框是否显示 */
|
||||
openByOAM: boolean;
|
||||
/**快速OAM配置框是否显示 */
|
||||
openByQuickOAM: boolean;
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**新增框或修改框ID */
|
||||
@@ -201,6 +214,7 @@ type ModalStateType = {
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByBackConf: false,
|
||||
openByOAM: false,
|
||||
openByQuickOAM: false,
|
||||
openByEdit: false,
|
||||
editId: 0,
|
||||
neId: '',
|
||||
@@ -257,8 +271,6 @@ function reloadRowInfo(row: Record<string, any>) {
|
||||
item.status = '0';
|
||||
}
|
||||
Object.assign(item.serverState, res.data);
|
||||
const resouresUsage = parseResouresUsage(item.serverState);
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -275,6 +287,7 @@ function fnModalEditCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.openByOAM = false;
|
||||
modalState.openByBackConf = false;
|
||||
modalState.openByQuickOAM = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -360,6 +373,9 @@ function fnRecordMore(type: string | number, row: Record<string, any>) {
|
||||
modalState.neType = row.neType;
|
||||
modalState.openByBackConf = !modalState.openByBackConf;
|
||||
break;
|
||||
case 'quickOAM':
|
||||
modalState.openByQuickOAM = !modalState.openByQuickOAM;
|
||||
break;
|
||||
default:
|
||||
console.warn(type);
|
||||
break;
|
||||
@@ -382,23 +398,7 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
const { total, rows } = res.data;
|
||||
tablePagination.total = total;
|
||||
// 遍历处理资源情况数值
|
||||
tableState.data = rows.map((item: any) => {
|
||||
let resouresUsage = {
|
||||
sysDiskUsage: 0,
|
||||
sysMemUsage: 0,
|
||||
sysCpuUsage: 0,
|
||||
nfCpuUsage: 0,
|
||||
};
|
||||
const neState = item.serverState;
|
||||
if (neState) {
|
||||
resouresUsage = parseResouresUsage(neState);
|
||||
} else {
|
||||
item.serverState = { online: false };
|
||||
}
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
return item;
|
||||
});
|
||||
tableState.data = rows
|
||||
}
|
||||
tableState.loading = false;
|
||||
})
|
||||
@@ -423,33 +423,29 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<a-card v-show="tableState.seached" :bordered="false" :body-style="{ marginBottom: '24px', paddingBottom: 0 }">
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType ">
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="neListStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
<a-auto-complete v-model:value="queryParams.neType" :options="neListStore.getNeSelectOtions" allow-clear
|
||||
:placeholder="t('common.inputPlease')" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
<template #icon>
|
||||
<ClearOutlined />
|
||||
</template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -463,18 +459,25 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()" v-perms:has="['ne:neInfo:add']">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
<a-button type="default" :loading="modalState.confirmLoading" @click.prevent="fnRecordMore('quickOAM', {})"
|
||||
v-perms:has="['ne:neInfo:oam']">
|
||||
<template #icon>
|
||||
<SettingOutlined />
|
||||
</template>
|
||||
{{ t('views.ne.neInfo.quickOam.title') }}
|
||||
</a-button>
|
||||
<a-button type="default" danger :disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading" @click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['ne:neInfo:delete']">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -485,30 +488,27 @@ onMounted(() => {
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
<a-switch v-model:checked="tableState.seached" :checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')" size="small" />
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
<template #icon>
|
||||
<ColumnHeightOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu :selected-keys="[tableState.size as string]" @click="fnTableSize">
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
@@ -526,22 +526,14 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120 }"
|
||||
:row-selection="{
|
||||
<a-table class="table" row-key="id" :columns="tableColumns" :loading="tableState.loading"
|
||||
:data-source="tableState.data" :size="tableState.size" :pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120 }" :row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
}">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'status'">
|
||||
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
||||
@@ -550,41 +542,42 @@ onMounted(() => {
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record)"
|
||||
>
|
||||
<template #icon><FormOutlined /></template>
|
||||
<a-button type="link" @click.prevent="fnModalVisibleByEdit(record)" v-perms:has="['ne:neInfo:edit']">
|
||||
<template #icon>
|
||||
<FormOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{ t('views.ne.common.restart') }}
|
||||
</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordMore('restart', record)"
|
||||
>
|
||||
<template #icon><UndoOutlined /></template>
|
||||
<a-button type="link" @click.prevent="fnRecordMore('restart', record)"
|
||||
v-perms:has="['ne:neInfo:restart']">
|
||||
<template #icon>
|
||||
<UndoOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-button type="link">
|
||||
<template #icon><EllipsisOutlined /> </template>
|
||||
<template #icon>
|
||||
<EllipsisOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }:any) => fnRecordMore(key, record)">
|
||||
<a-menu @click="({ key }: any) => fnRecordMore(key, record)">
|
||||
<a-menu-item key="log">
|
||||
<FileTextOutlined />
|
||||
{{ t('views.ne.common.log') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="start">
|
||||
<a-menu-item key="start" v-if="hasPermissions(['ne:neInfo:start'])">
|
||||
<ThunderboltOutlined />
|
||||
{{ t('views.ne.common.start') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="stop">
|
||||
<a-menu-item key="stop" v-if="hasPermissions(['ne:neInfo:stop'])">
|
||||
<CloseSquareOutlined />
|
||||
{{ t('views.ne.common.stop') }}
|
||||
</a-menu-item>
|
||||
@@ -592,23 +585,23 @@ onMounted(() => {
|
||||
<SyncOutlined />
|
||||
{{ t('views.ne.common.reload') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="delete">
|
||||
<a-menu-item key="delete" v-if="hasPermissions(['ne:neInfo:delete'])">
|
||||
<DeleteOutlined />
|
||||
{{ t('common.deleteText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="oam"
|
||||
v-if="!['OMC'].includes(record.neType)"
|
||||
>
|
||||
<a-menu-item key="oam" v-if="
|
||||
!['OMC'].includes(record.neType) ||
|
||||
hasPermissions(['ne:neInfo:oam'])
|
||||
">
|
||||
<FileTextOutlined />
|
||||
{{ t('views.ne.common.oam') }}
|
||||
</a-menu-item>
|
||||
<!-- 配置备份 -->
|
||||
<a-menu-item key="backConfExport">
|
||||
<a-menu-item key="backConfExport" v-if="hasPermissions(['ne:neInfo:export'])">
|
||||
<ExportOutlined />
|
||||
{{ t('views.ne.neInfo.backConf.export') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="backConfImport">
|
||||
<a-menu-item key="backConfImport" v-if="hasPermissions(['ne:neInfo:import'])">
|
||||
<ImportOutlined />
|
||||
{{ t('views.ne.neInfo.backConf.import') }}
|
||||
</a-menu-item>
|
||||
@@ -648,59 +641,39 @@ onMounted(() => {
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.neCpu') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.nfCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.nfCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.nfCpuUsage"
|
||||
/>
|
||||
<a-progress status="normal" :stroke-color="record.serverState.nfCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.serverState.nfCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
" :percent="record.serverState.nfCpuUsage" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysCpu') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysCpuUsage"
|
||||
/>
|
||||
<a-progress status="normal" :stroke-color="record.serverState.sysCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.serverState.sysCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
" :percent="record.serverState.sysCpuUsage" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysMem') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysMemUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysMemUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysMemUsage"
|
||||
/>
|
||||
<a-progress status="normal" :stroke-color="record.serverState.sysMemUsage < 30
|
||||
? '#52c41a'
|
||||
: record.serverState.sysMemUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
" :percent="record.serverState.sysMemUsage" />
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysDisk') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysDiskUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysDiskUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysDiskUsage"
|
||||
/>
|
||||
<a-progress status="normal" :stroke-color="record.serverState.sysDiskUsage < 30
|
||||
? '#52c41a'
|
||||
: record.serverState.sysDiskUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
" :percent="record.serverState.sysDiskUsage" />
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -709,29 +682,19 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<EditModal
|
||||
v-model:open="modalState.openByEdit"
|
||||
:edit-id="modalState.editId"
|
||||
@ok="fnModalEditOk"
|
||||
@cancel="fnModalEditCancel"
|
||||
></EditModal>
|
||||
<EditModal v-model:open="modalState.openByEdit" :edit-id="modalState.editId" @ok="fnModalEditOk"
|
||||
@cancel="fnModalEditCancel"></EditModal>
|
||||
|
||||
<!-- OAM编辑框 -->
|
||||
<OAMModal
|
||||
v-model:open="modalState.openByOAM"
|
||||
:ne-id="modalState.neId"
|
||||
:ne-type="modalState.neType"
|
||||
@cancel="fnModalEditCancel"
|
||||
></OAMModal>
|
||||
<OAMModal v-model:open="modalState.openByOAM" :ne-id="modalState.neId" :ne-type="modalState.neType"
|
||||
@cancel="fnModalEditCancel"></OAMModal>
|
||||
|
||||
<!-- 配置文件备份框 -->
|
||||
<BackConfModal
|
||||
ref="backConf"
|
||||
v-model:open="modalState.openByBackConf"
|
||||
:ne-id="modalState.neId"
|
||||
:ne-type="modalState.neType"
|
||||
@cancel="fnModalEditCancel"
|
||||
></BackConfModal>
|
||||
<BackConfModal ref="backConf" v-model:open="modalState.openByBackConf" :ne-id="modalState.neId"
|
||||
:ne-type="modalState.neType" @cancel="fnModalEditCancel"></BackConfModal>
|
||||
|
||||
<!-- 快速OAM配置框 -->
|
||||
<QuickOAMModal v-model:open="modalState.openByQuickOAM" @cancel="fnModalEditCancel"></QuickOAMModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch, ref } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Form, Progress, Upload } from 'ant-design-vue/es';
|
||||
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
|
||||
import { FileType } from 'ant-design-vue/es/upload/interface';
|
||||
import { UploadOutlined, CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { changeNeLicense, getNeLicenseByTypeAndID } from '@/api/ne/neLicense';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import useNeListStore from '@/store/modules/ne_list';
|
||||
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: {
|
||||
selectedNeList: string[];
|
||||
licensePath: string;
|
||||
remark: string;
|
||||
};
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**上传文件 */
|
||||
uploadFiles: any[];
|
||||
/**进度显示 */
|
||||
progress: {
|
||||
visible: boolean;
|
||||
current: number;
|
||||
total: number;
|
||||
currentNe: string;
|
||||
};
|
||||
/**操作结果 */
|
||||
results: Array<{
|
||||
neType: string;
|
||||
neId: string;
|
||||
neName: string;
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: t('views.ne.neLicense.quickUpload.title'),
|
||||
from: {
|
||||
selectedNeList: [],
|
||||
licensePath: '',
|
||||
remark: '',
|
||||
},
|
||||
confirmLoading: false,
|
||||
uploadFiles: [],
|
||||
progress: {
|
||||
visible: false,
|
||||
current: 0,
|
||||
total: 0,
|
||||
currentNe: '',
|
||||
},
|
||||
results: [],
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
selectedNeList: [
|
||||
{
|
||||
required: true,
|
||||
|
||||
},
|
||||
],
|
||||
licensePath: [
|
||||
{
|
||||
required: true,
|
||||
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**获取网元列表选项 */
|
||||
const neOptions = ref<Array<{ label: string; value: string; neType: string; neId: string; neName: string }>>([]);
|
||||
|
||||
/**
|
||||
* 初始化网元选项
|
||||
*/
|
||||
async function initNeOptions() {
|
||||
// 确保网元列表已加载
|
||||
await neListStore.fnNelistRefresh();
|
||||
// 从store获取网元列表,过滤掉OMC类型
|
||||
const neList = neListStore.getNeList.filter((ne: any) => ne.neType !== 'OMC');
|
||||
neOptions.value = neList.map((ne: any) => ({
|
||||
label: `${ne.neType}-${ne.neId} (${ne.neName})`,
|
||||
value: `${ne.neType}@${ne.neId}`,
|
||||
neType: ne.neType,
|
||||
neId: ne.neId,
|
||||
neName: ne.neName,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个网元许可证上传(复用EditModal的逻辑)
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @param licensePath 许可证文件路径
|
||||
* @param remark 备注
|
||||
* @returns Promise<{success: boolean, message: string}>
|
||||
*/
|
||||
async function uploadSingleNeLicense(neType: string, neId: string, licensePath: string, remark: string = '') {
|
||||
try {
|
||||
// 1. 获取网元许可证信息(复用EditModal的获取逻辑)
|
||||
const getRes = await getNeLicenseByTypeAndID(neType, neId);
|
||||
|
||||
if (getRes.code !== RESULT_CODE_SUCCESS) {
|
||||
return {
|
||||
success: false,
|
||||
message: ` ${getRes.msg}`,
|
||||
};
|
||||
}
|
||||
|
||||
// 2. 构建上传数据(复用EditModal的数据结构)
|
||||
const uploadData = {
|
||||
id: getRes.data.id,
|
||||
neType: neType,
|
||||
neId: neId,
|
||||
licensePath: licensePath,
|
||||
remark: remark,
|
||||
reload: false, // 网元授权不允许操作重启
|
||||
};
|
||||
|
||||
// 3. 上传许可证(复用EditModal的上传逻辑)
|
||||
const uploadRes = await changeNeLicense(uploadData);
|
||||
|
||||
if (uploadRes.code === RESULT_CODE_SUCCESS) {
|
||||
return {
|
||||
success: true,
|
||||
message: t('views.ne.neInfo.quickOam.success'),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: ` ${uploadRes.msg}`,
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
message: ` ${error.message || error}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
async function fnModalOk() {
|
||||
try {
|
||||
await modalStateFrom.validate();
|
||||
|
||||
modalState.confirmLoading = true;
|
||||
modalState.progress.visible = true;
|
||||
modalState.progress.current = 0;
|
||||
modalState.progress.total = modalState.from.selectedNeList.length;
|
||||
modalState.results = [];
|
||||
|
||||
const { licensePath, remark } = modalState.from;
|
||||
|
||||
// 循环处理每个选中的网元
|
||||
for (let i = 0; i < modalState.from.selectedNeList.length; i++) {
|
||||
const neInfo = modalState.from.selectedNeList[i];
|
||||
const [neType, neId] = neInfo.split('@');
|
||||
const neName = neOptions.value.find(opt => opt.value === neInfo)?.neName || neId;
|
||||
|
||||
modalState.progress.current = i + 1;
|
||||
modalState.progress.currentNe = `${neType}-${neId}`;
|
||||
|
||||
// 调用单个网元许可证上传函数
|
||||
const result = await uploadSingleNeLicense(neType, neId, licensePath, remark);
|
||||
|
||||
modalState.results.push({
|
||||
neType,
|
||||
neId,
|
||||
neName,
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
});
|
||||
}
|
||||
|
||||
// 显示操作结果
|
||||
const successCount = modalState.results.filter(r => r.success).length;
|
||||
const failCount = modalState.results.length - successCount;
|
||||
|
||||
if (failCount === 0) {
|
||||
message.success(`${t('views.ne.neInfo.quickOam.success')} ${successCount} `, 5);
|
||||
} else {
|
||||
message.warning(`${t('views.ne.neInfo.quickOam.success')} ${successCount} ,${t('views.ne.neInfo.quickOam.default')} ${failCount} `, 5);
|
||||
}
|
||||
|
||||
const firstSuccessNe = modalState.results.find(r => r.success);
|
||||
const paramForMain = firstSuccessNe ? {
|
||||
neType: firstSuccessNe.neType,
|
||||
neId: firstSuccessNe.neId
|
||||
} : {
|
||||
neType: 'BATCH', // 批量操作
|
||||
neId: 'OPERATION'
|
||||
};
|
||||
|
||||
emit('ok', paramForMain);
|
||||
fnModalCancel();
|
||||
} catch (error: any) {
|
||||
message.error(t('common.errorFields', { num: error.errorFields?.length || 0 }), 3);
|
||||
} finally {
|
||||
modalState.confirmLoading = false;
|
||||
modalState.progress.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalState.progress.visible = false;
|
||||
modalState.progress.current = 0;
|
||||
modalState.progress.total = 0;
|
||||
modalState.progress.currentNe = '';
|
||||
modalState.results = [];
|
||||
modalStateFrom.resetFields();
|
||||
modalState.uploadFiles = [];
|
||||
modalState.from.licensePath = '';
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
/**表单上传前删除 */
|
||||
function fnBeforeRemoveFile(file: any) {
|
||||
modalState.from.licensePath = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
/**表单上传前检查或转换压缩 */
|
||||
function fnBeforeUploadFile(file: FileType) {
|
||||
if (modalState.confirmLoading) return false;
|
||||
if (!file.name.endsWith('.ini')) {
|
||||
const msg = `${t('components.UploadModal.onlyAllow')} .ini`;
|
||||
message.error(msg, 3);
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
const isLt3M = file.size / 1024 / 1024 < 3;
|
||||
if (!isLt3M) {
|
||||
const msg = `${t('components.UploadModal.allowFilter')} 3MB`;
|
||||
message.error(msg, 3);
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**表单上传文件 */
|
||||
function fnUploadFile(up: UploadRequestOption) {
|
||||
// 发送请求
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
modalState.confirmLoading = true;
|
||||
let formData = new FormData();
|
||||
formData.append('file', up.file);
|
||||
formData.append('subPath', 'license');
|
||||
uploadFile(formData)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 改为完成状态
|
||||
const file = modalState.uploadFiles[0];
|
||||
file.percent = 100;
|
||||
file.status = 'done';
|
||||
// 预置到表单
|
||||
modalState.from.licensePath = res.data.filePath;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
initNeOptions();
|
||||
modalState.title = t('views.ne.neLicense.quickUpload.title');
|
||||
modalState.openByEdit = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
:width="500"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 8 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neLicense.licensePath')"
|
||||
name="file"
|
||||
v-bind="modalStateFrom.validateInfos.licensePath"
|
||||
>
|
||||
<a-upload
|
||||
name="file"
|
||||
v-model:file-list="modalState.uploadFiles"
|
||||
accept=".ini"
|
||||
list-type="text"
|
||||
:max-count="1"
|
||||
:show-upload-list="{
|
||||
showPreviewIcon: false,
|
||||
showRemoveIcon: true,
|
||||
showDownloadIcon: false,
|
||||
}"
|
||||
@remove="fnBeforeRemoveFile"
|
||||
:before-upload="fnBeforeUploadFile"
|
||||
:custom-request="fnUploadFile"
|
||||
:disabled="modalState.confirmLoading"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
{{ t('views.ne.neLicense.upload') }}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="t('common.remark')" name="remark">
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.remark"
|
||||
:maxlength="200"
|
||||
:show-count="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neLicense.quickUpload.selectNe')"
|
||||
name="selectedNeList"
|
||||
v-bind="modalStateFrom.validateInfos.selectedNeList"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.selectedNeList"
|
||||
mode="multiple"
|
||||
:options="neOptions"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:max-tag-count="3"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- 进度显示 -->
|
||||
<div v-if="modalState.progress.visible || modalState.results.length > 0" style="margin-top: 20px; overflow: hidden;">
|
||||
<a-divider>{{ t('views.ne.neInfo.quickOam.progress') }}</a-divider>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span>{{ t('views.ne.neInfo.quickOam.processing') }}: {{ modalState.progress.currentNe }}</span>
|
||||
<span style="float: right;">
|
||||
{{ modalState.progress.current }} / {{ modalState.progress.total }}
|
||||
</span>
|
||||
</div>
|
||||
<div style="width: 100%; overflow: hidden;">
|
||||
<Progress
|
||||
:percent="Math.round((modalState.progress.current / modalState.progress.total) * 100)"
|
||||
:status="modalState.progress.current === modalState.progress.total ? 'success' : 'active'"
|
||||
:show-info="false"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作结果 -->
|
||||
<div v-if="modalState.results.length > 0" style="margin-top: 20px;">
|
||||
<a-divider>{{ t('views.ne.neInfo.quickOam.result') }}</a-divider>
|
||||
<div style="max-height: 200px; overflow-y: auto;">
|
||||
<div
|
||||
v-for="(result, index) in modalState.results"
|
||||
:key="index"
|
||||
style="margin-bottom: 8px; padding: 8px; border-radius: 4px;"
|
||||
:style="{
|
||||
backgroundColor: result.success ? '#f6ffed' : '#fff2f0',
|
||||
border: `1px solid ${result.success ? '#b7eb8f' : '#ffccc7'}`,
|
||||
}"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>
|
||||
<CheckCircleOutlined
|
||||
v-if="result.success"
|
||||
:style="{ color: '#52c41a', marginRight: '8px' }"
|
||||
/>
|
||||
<CloseCircleOutlined
|
||||
v-else
|
||||
:style="{ color: '#ff4d4f', marginRight: '8px' }"
|
||||
/>
|
||||
{{ result.neType }}-{{ result.neId }} ({{ result.neName }})
|
||||
</span>
|
||||
<span :style="{ color: result.success ? '#52c41a' : '#ff4d4f', fontSize: '12px' }">
|
||||
{{ result.message }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-progress-text {
|
||||
color: #1890ff;
|
||||
}
|
||||
</style>
|
||||
@@ -16,6 +16,10 @@ const neListStore = useNeListStore();
|
||||
const EditModal = defineAsyncComponent(
|
||||
() => import('./components/EditModal.vue')
|
||||
);
|
||||
// 快速许可证上传
|
||||
const QuickLicenseModal = defineAsyncComponent(
|
||||
() => import('./components/QuickLicenseModal.vue')
|
||||
);
|
||||
|
||||
/**字典数据-状态 */
|
||||
let dictStatus = ref<DictType[]>([]);
|
||||
@@ -67,12 +71,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
@@ -105,8 +109,8 @@ let tableColumns = ref<TableColumnsType>([
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.capability'),
|
||||
dataIndex: 'capability',
|
||||
title: t('views.ne.common.ueNumber'),
|
||||
dataIndex: 'ueNumber',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
if (['UDM', 'AMF', 'MME'].includes(opt.record.neType)) {
|
||||
@@ -116,6 +120,18 @@ let tableColumns = ref<TableColumnsType>([
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.nbNumber'),
|
||||
dataIndex: 'nbNumber',
|
||||
align: 'left',
|
||||
customRender(opt) {
|
||||
if (['AMF', 'MME'].includes(opt.record.neType)) {
|
||||
return opt.value;
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('common.remark'),
|
||||
dataIndex: 'remark',
|
||||
@@ -198,7 +214,7 @@ function fnGetList(pageNum?: number) {
|
||||
tablePagination.total = totalV;
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
@@ -216,6 +232,8 @@ function fnGetList(pageNum?: number) {
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**快速许可证上传框是否显示 */
|
||||
openByQuickUpload: boolean;
|
||||
/**授权记录ID */
|
||||
licenseId: number;
|
||||
/**确定按钮 loading */
|
||||
@@ -225,6 +243,7 @@ type ModalStateType = {
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
openByQuickUpload: false,
|
||||
licenseId: 0,
|
||||
confirmLoading: false,
|
||||
});
|
||||
@@ -258,6 +277,7 @@ function fnModalOk(e: any) {
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.openByQuickUpload = false;
|
||||
modalState.licenseId = 0;
|
||||
}
|
||||
|
||||
@@ -276,7 +296,8 @@ function fnRecordState(row: Record<string, any>) {
|
||||
row.status = '1';
|
||||
row.serialNum = res.data.sn;
|
||||
row.expiryDate = res.data.expire;
|
||||
row.capability = res.data.capability;
|
||||
row.ueNumber = res.data.ueNumber;
|
||||
row.nbNumber = res.data.nbNumber;
|
||||
row.updateTime = new Date().getTime();
|
||||
message.success(
|
||||
`${row.neType} ${row.neId} ${dictStatus.value[1].label}`,
|
||||
@@ -397,10 +418,20 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="primary"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="modalState.openByQuickUpload = true"
|
||||
v-perms:has="['ne:neLicense:upload']"
|
||||
>
|
||||
<template #icon><UploadOutlined /></template>
|
||||
{{ t('views.ne.neLicense.quickUpload.title') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="default"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordStateReload()"
|
||||
v-perms:has="['ne:neLicense:reload']"
|
||||
>
|
||||
<template #icon><SyncOutlined /></template>
|
||||
{{ t('views.ne.neLicense.reloadBatch') }}
|
||||
@@ -475,7 +506,7 @@ onMounted(() => {
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip placement="topRight">
|
||||
<template #title>{{ t('views.ne.neLicense.reload') }}</template>
|
||||
<a-button type="link" @click.prevent="fnRecordState(record)">
|
||||
<a-button type="link" @click.prevent="fnRecordState(record)" v-perms:has="['ne:neLicense:sync']">
|
||||
<template #icon><SyncOutlined /> </template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
@@ -484,6 +515,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record.id)"
|
||||
v-perms:has="['ne:neLicense:edit']"
|
||||
>
|
||||
<template #icon><UploadOutlined /> </template>
|
||||
</a-button>
|
||||
@@ -501,6 +533,13 @@ onMounted(() => {
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
></EditModal>
|
||||
|
||||
<!-- 快速许可证上传框 -->
|
||||
<QuickLicenseModal
|
||||
v-model:open="modalState.openByQuickUpload"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
></QuickLicenseModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@ const EditModal = defineAsyncComponent(
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 50,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 50,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw, defineAsyncComponent } from 'vue';
|
||||
import { reactive, ref, onMounted, toRaw, defineAsyncComponent,computed } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Modal, TableColumnsType, message } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
@@ -11,6 +11,7 @@ import { listNeSoftware, delNeSoftware } from '@/api/ne/neSoftware';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { downloadFile } from '@/api/tool/file';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
const neListStore = useNeListStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -21,7 +22,10 @@ const EditModal = defineAsyncComponent(
|
||||
const UploadMoreFile = defineAsyncComponent(
|
||||
() => import('./components/UploadMoreFile.vue')
|
||||
);
|
||||
|
||||
const hasAnyBatchPermission = computed(() => {
|
||||
return hasPermissions(['ne:neSoftware:download']) ||
|
||||
hasPermissions(['ne:neSoftware:delete']) ;
|
||||
});
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
@@ -79,12 +83,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
@@ -400,7 +404,7 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit(0)">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit(0)" v-perms:has="['ne:neSoftware:upload']">
|
||||
<template #icon><UploadOutlined /></template>
|
||||
{{ t('views.ne.neSoftware.upload') }}
|
||||
</a-button>
|
||||
@@ -410,6 +414,7 @@ onMounted(() => {
|
||||
@click.prevent="
|
||||
() => (modalState.openByMoreFile = !modalState.openByMoreFile)
|
||||
"
|
||||
v-perms:has="['ne:neSoftware:upload']"
|
||||
>
|
||||
<template #icon><UploadOutlined /></template>
|
||||
<template v-if="tableState.selectedRowOne.neType">
|
||||
@@ -426,6 +431,7 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['ne:neSoftware:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
@@ -521,6 +527,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record.id)"
|
||||
v-perms:has="['ne:neSoftware:edit']"
|
||||
>
|
||||
<template #icon> <ProfileOutlined /></template>
|
||||
</a-button>
|
||||
@@ -528,17 +535,17 @@ onMounted(() => {
|
||||
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-dropdown placement="bottomRight" trigger="click" v-if="hasAnyBatchPermission">
|
||||
<a-button type="link">
|
||||
<template #icon><EllipsisOutlined /> </template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }:any) => fnRecordMore(key, record)">
|
||||
<a-menu-item key="download">
|
||||
<a-menu-item key="download" v-if="hasPermissions(['ne:neSoftware:download'])">
|
||||
<DownloadOutlined />
|
||||
{{ t('common.downloadText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="delete">
|
||||
<a-menu-item key="delete" v-if="hasPermissions(['ne:neSoftware:delete'])">
|
||||
<DeleteOutlined />
|
||||
{{ t('common.deleteText') }}
|
||||
</a-menu-item>
|
||||
|
||||
@@ -87,12 +87,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
@@ -108,6 +108,7 @@ let tableColumns = ref<TableColumnsType>([
|
||||
{
|
||||
title: t('views.ne.neVersion.version'),
|
||||
dataIndex: 'version',
|
||||
key: 'version',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
resizable: true,
|
||||
@@ -505,6 +506,7 @@ onMounted(() => {
|
||||
@click.prevent="
|
||||
() => (modalState.openByEdit = !modalState.openByEdit)
|
||||
"
|
||||
v-perms:has="['ne:neVersion:upload']"
|
||||
>
|
||||
<template #icon><UploadOutlined /></template>
|
||||
{{ t('views.ne.neSoftware.upload') }}
|
||||
@@ -515,6 +517,7 @@ onMounted(() => {
|
||||
@click.prevent="
|
||||
() => (modalState.openByMoreFile = !modalState.openByMoreFile)
|
||||
"
|
||||
v-perms:has="['ne:neVersion:upload']"
|
||||
>
|
||||
<template #icon><UploadOutlined /></template>
|
||||
<template v-if="tableState.selectedRowOne.neType">
|
||||
@@ -531,6 +534,7 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordUpgradeConfirm()"
|
||||
v-perms:has="['ne:neVersion:upgrade']"
|
||||
>
|
||||
<template #icon><ThunderboltOutlined /></template>
|
||||
{{ t('views.ne.neVersion.upgradeBatch') }}
|
||||
@@ -605,6 +609,21 @@ onMounted(() => {
|
||||
<template v-if="column.key === 'status'">
|
||||
<DictTag :options="dictStatus" :value="record.status" />
|
||||
</template>
|
||||
<template v-if="column.key === 'version'">
|
||||
{{ record.version }}
|
||||
<a-tooltip
|
||||
placement="topRight"
|
||||
v-if="
|
||||
record.version &&
|
||||
(record.path === '' || record.path === '-')
|
||||
"
|
||||
>
|
||||
<template #title>
|
||||
{{ t('views.ne.neVersion.noPath') }}
|
||||
</template>
|
||||
<InfoCircleOutlined />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'preVersion'">
|
||||
{{ record.preVersion }}
|
||||
<a-tooltip
|
||||
@@ -629,6 +648,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordVersion('upgrade', record)"
|
||||
v-perms:has="['ne:neVersion:upgrade']"
|
||||
>
|
||||
<template #icon><ThunderboltOutlined /></template>
|
||||
</a-button>
|
||||
@@ -640,6 +660,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordVersion('rollback', record)"
|
||||
v-perms:has="['ne:neVersion:rollback']"
|
||||
>
|
||||
<template #icon><RollbackOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
@@ -21,27 +21,27 @@ let sourceState = reactive({
|
||||
/**文件列表 */
|
||||
list: [
|
||||
{
|
||||
value: '/auth',
|
||||
value: '/udm/auth',
|
||||
label: t('views.neData.backupData.auth'),
|
||||
path: '/usr/local/omc/backup/udm_data',
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UDM',
|
||||
},
|
||||
{
|
||||
value: '/sub',
|
||||
value: '/udm/sub',
|
||||
label: t('views.neData.backupData.sub'),
|
||||
path: '/usr/local/omc/backup/udm_data',
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UDM',
|
||||
},
|
||||
{
|
||||
value: '/voip',
|
||||
value: '/udm/voip',
|
||||
label: t('views.neData.backupData.voip'),
|
||||
path: '/usr/local/omc/backup/udm_data',
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UDM',
|
||||
},
|
||||
{
|
||||
value: '/volte',
|
||||
value: '/udm/volte',
|
||||
label: t('views.neData.backupData.volte'),
|
||||
path: '/usr/local/omc/backup/udm_data',
|
||||
path: '/usr/local/omc/backup',
|
||||
neType: 'UDM+IMS',
|
||||
},
|
||||
],
|
||||
@@ -353,7 +353,11 @@ onMounted(() => {
|
||||
<template #title>
|
||||
{{ t('views.ne.neConfigBackup.backupModal.title') }}
|
||||
</template>
|
||||
<a-button type="text" @click.prevent="fnFTPModalOpen()">
|
||||
<a-button
|
||||
type="text"
|
||||
@click.prevent="fnFTPModalOpen()"
|
||||
v-perms:has="['ne-data:backup-data:ftp']"
|
||||
>
|
||||
<template #icon><DeliveredProcedureOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
@@ -387,6 +391,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnSyncFileToFTP(record.fileName)"
|
||||
v-perms:has="['ne-data:backup-data:ftpSync']"
|
||||
>
|
||||
<template #icon><CloudServerOutlined /></template>
|
||||
</a-button>
|
||||
@@ -397,6 +402,7 @@ onMounted(() => {
|
||||
type="link"
|
||||
:loading="downLoading"
|
||||
@click.prevent="fnDownloadFile(record)"
|
||||
v-perms:has="['ne-data:backup-data:download']"
|
||||
>
|
||||
<template #icon><DownloadOutlined /></template>
|
||||
</a-button>
|
||||
@@ -407,6 +413,7 @@ onMounted(() => {
|
||||
type="link"
|
||||
:loading="delLoading"
|
||||
@click.prevent="fnRecordDelete(record)"
|
||||
v-perms:has="['ne-data:backup-data:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
@@ -109,12 +109,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 80,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 80,
|
||||
// },
|
||||
{
|
||||
title: t('views.neData.baseStation.name'),
|
||||
dataIndex: 'name',
|
||||
@@ -150,6 +150,15 @@ let tableColumns = ref<ColumnsType>([
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.nbId'),
|
||||
dataIndex: 'nbId',
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
width: 100,
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.state'),
|
||||
dataIndex: 'state',
|
||||
@@ -202,6 +211,8 @@ function fnExportList() {
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
exportNBState(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -245,7 +256,7 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
|
||||
listNBState(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 取消勾选
|
||||
if (tableState.selectedRowKeys.length > 0) {
|
||||
tableState.selectedRowKeys = [];
|
||||
@@ -256,7 +267,7 @@ function fnGetList(pageNum?: number) {
|
||||
tableState.data = rows;
|
||||
if (
|
||||
tablePagination.total <=
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
||||
queryParams.pageNum !== 1
|
||||
) {
|
||||
tableState.loading = false;
|
||||
@@ -288,62 +299,43 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:width="1200"
|
||||
:title="props.title"
|
||||
:open="props.open"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@cancel="fnModalCancel"
|
||||
:footer="null"
|
||||
>
|
||||
<ProModal :drag="true" :destroyOnClose="true" :width="1200" :title="props.title" :open="props.open" :keyboard="false"
|
||||
:mask-closable="false" @cancel="fnModalCancel" :footer="null">
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16" style="margin-left: 0; margin-right: 0">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.state')"
|
||||
name="status"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="queryParams.status"
|
||||
allow-clear
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:options="nbStateOptions"
|
||||
>
|
||||
<a-form-item :label="t('views.neData.baseStation.state')" name="status">
|
||||
<a-select v-model:value="queryParams.status" allow-clear :placeholder="t('common.selectPlease')"
|
||||
:options="nbStateOptions">
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="16" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.time')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
:bordered="true"
|
||||
:allow-clear="true"
|
||||
style="width: 100%"
|
||||
:show-time="{ format: 'HH:mm:ss' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
></a-range-picker>
|
||||
<a-form-item :label="t('views.neData.baseStation.time')" name="queryRangePicker">
|
||||
<a-range-picker v-model:value="queryRangePicker" :bordered="true" :allow-clear="true" style="width: 100%"
|
||||
:show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="24" :md="24" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
<template #icon>
|
||||
<ClearOutlined />
|
||||
</template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -353,24 +345,13 @@ watch(
|
||||
</a-form>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
<a-table class="table" row-key="id" :columns="tableColumns" :loading="tableState.loading"
|
||||
:data-source="tableState.data" :size="tableState.size" :pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
>
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'state'">
|
||||
<DictTag
|
||||
:options="nbStateOptions"
|
||||
:value="record.state"
|
||||
value-default="OFF"
|
||||
/>
|
||||
<DictTag :options="nbStateOptions" :value="record.state" value-default="OFF" />
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
@@ -140,6 +140,12 @@ let tableColumns = ref<ColumnsType>([
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.nbId'),
|
||||
dataIndex: 'ranId',
|
||||
align: 'left',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('views.neData.baseStation.ueNum'),
|
||||
dataIndex: 'ueNum',
|
||||
@@ -641,13 +647,12 @@ function fnModalImportUpload(file: File) {
|
||||
/**对话框表格信息导入模板 */
|
||||
async function fnModalImportTemplate() {
|
||||
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
|
||||
const xlsxUrl = `${
|
||||
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
|
||||
const xlsxUrl = `${baseUrl.length === 1 && baseUrl.indexOf('/') === 0
|
||||
? ''
|
||||
: baseUrl.indexOf('/') === -1
|
||||
? '/' + baseUrl
|
||||
: baseUrl
|
||||
}/nbStateImput`;
|
||||
? '/' + baseUrl
|
||||
: baseUrl
|
||||
}/nbStateImput`;
|
||||
const lang = currentLocale.value.split('_')[0];
|
||||
saveAs(
|
||||
`${xlsxUrl}/${lang}.xlsx`,
|
||||
@@ -688,46 +693,35 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<a-card :bordered="false" :body-style="{ marginBottom: '24px', paddingBottom: 0 }">
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType ">
|
||||
<a-cascader
|
||||
v-model:value="neTypeAndId"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnGetList"
|
||||
/>
|
||||
<a-cascader v-model:value="neTypeAndId" :options="neCascaderOptions" :allow-clear="false"
|
||||
:placeholder="t('common.selectPlease')" @change="fnGetList" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="4" :md="6" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.state')"
|
||||
name="state"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="queryParams.state"
|
||||
:options="nbState"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
@change="fnGetList"
|
||||
/>
|
||||
<a-form-item :label="t('views.neData.baseStation.state')" name="state">
|
||||
<a-select v-model:value="queryParams.state" :options="nbState" :placeholder="t('common.selectPlease')"
|
||||
@change="fnGetList" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList()">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
<template #icon>
|
||||
<ClearOutlined />
|
||||
</template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -747,35 +741,36 @@ onMounted(() => {
|
||||
</template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length != 1"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnModalVisibleByEdit('0')"
|
||||
>
|
||||
<template #icon><FormOutlined /></template>
|
||||
<a-button type="default" :disabled="tableState.selectedRowKeys.length != 1"
|
||||
:loading="modalState.confirmLoading" @click.prevent="fnModalVisibleByEdit('0')">
|
||||
<template #icon>
|
||||
<FormOutlined />
|
||||
</template>
|
||||
{{ t('common.editText') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
<a-button type="default" danger :disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading" @click.prevent="fnRecordDelete('0')">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnModalImportOpen()">
|
||||
<template #icon><ImportOutlined /></template>
|
||||
<template #icon>
|
||||
<ImportOutlined />
|
||||
</template>
|
||||
{{ t('common.import') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnHistoryView()">
|
||||
<template #icon><ContainerOutlined /></template>
|
||||
<template #icon>
|
||||
<ContainerOutlined />
|
||||
</template>
|
||||
{{ t('views.neData.baseStation.history') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -785,19 +780,15 @@ onMounted(() => {
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div>
|
||||
<template
|
||||
v-if="
|
||||
queryParams.state === undefined || queryParams.state === 'ON'
|
||||
"
|
||||
>
|
||||
<template v-if="
|
||||
queryParams.state === undefined || queryParams.state === 'ON'
|
||||
">
|
||||
{{ t('views.neData.baseStation.online') }}:
|
||||
<strong style="color: green">{{ stateNum[0] }} </strong>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
queryParams.state === undefined || queryParams.state === 'OFF'
|
||||
"
|
||||
>
|
||||
<template v-if="
|
||||
queryParams.state === undefined || queryParams.state === 'OFF'
|
||||
">
|
||||
|
||||
{{ t('views.neData.baseStation.offline') }}:
|
||||
<strong style="color: red">
|
||||
@@ -808,139 +799,72 @@ onMounted(() => {
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="index"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:row-selection="{
|
||||
<a-table class="table" row-key="index" :columns="tableColumns" :loading="tableState.loading"
|
||||
:data-source="tableState.data" :size="tableState.size" :pagination="tablePagination" :row-selection="{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
>
|
||||
}" :scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
||||
@resizeColumn="(w: number, col: any) => (col.width = w)">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'state'">
|
||||
<DictTag
|
||||
:options="nbState"
|
||||
:value="record.state"
|
||||
value-default="OFF"
|
||||
/>
|
||||
<DictTag :options="nbState" :value="record.state" value-default="OFF" />
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="500"
|
||||
:destroyOnClose="true"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.name')"
|
||||
name="name"
|
||||
v-bind="modalStateFrom.validateInfos.name"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.name"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
<ProModal :drag="true" :width="500" :destroyOnClose="true" :keyboard="false" :mask-closable="false"
|
||||
:open="modalState.openByEdit" :title="modalState.title" :confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk" @cancel="fnModalCancel">
|
||||
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }" :labelWrap="true">
|
||||
<a-form-item :label="t('views.neData.baseStation.name')" name="name" v-bind="modalStateFrom.validateInfos.name">
|
||||
<a-input v-model:value="modalState.from.name" allow-clear :maxlength="64">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.neData.baseStation.position')"
|
||||
name="position"
|
||||
v-bind="modalStateFrom.validateInfos.position"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.position"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
<a-form-item :label="t('views.neData.baseStation.position')" name="position"
|
||||
v-bind="modalStateFrom.validateInfos.position">
|
||||
<a-input v-model:value="modalState.from.position" allow-clear :maxlength="64">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="!modalState.from.state"
|
||||
:label="t('views.neData.baseStation.address')"
|
||||
name="address"
|
||||
v-bind="modalStateFrom.validateInfos.address"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.address"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
<a-form-item v-if="!modalState.from.state" :label="t('views.neData.baseStation.address')" name="address"
|
||||
v-bind="modalStateFrom.validateInfos.address">
|
||||
<a-input v-model:value="modalState.from.address" allow-clear :maxlength="64">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
|
||||
<!-- 状态历史框 -->
|
||||
<HistoryModal
|
||||
v-if="neTypeAndId.length > 1"
|
||||
v-model:open="modalState.openByHistory"
|
||||
:title="t('views.neData.baseStation.history')"
|
||||
:ne-type="neTypeAndId[0]"
|
||||
:ne-id="neTypeAndId[1]"
|
||||
@cancel="fnModalCancel"
|
||||
></HistoryModal>
|
||||
<HistoryModal v-if="neTypeAndId.length > 1" v-model:open="modalState.openByHistory"
|
||||
:title="t('views.neData.baseStation.history')" :ne-type="neTypeAndId[0]" :ne-id="neTypeAndId[1]"
|
||||
@cancel="fnModalCancel"></HistoryModal>
|
||||
|
||||
<!-- 上传导入表格数据文件框 -->
|
||||
<UploadModal
|
||||
:title="t('common.import')"
|
||||
@upload="fnModalImportUpload"
|
||||
@close="fnModalImportClose"
|
||||
v-model:open="modalState.openByImport"
|
||||
:ext="['.xls', '.xlsx']"
|
||||
:size="10"
|
||||
>
|
||||
<UploadModal :title="t('common.import')" @upload="fnModalImportUpload" @close="fnModalImportClose"
|
||||
v-model:open="modalState.openByImport" :ext="['.xls', '.xlsx']" :size="10">
|
||||
<template #default>
|
||||
<a-row justify="space-between" align="middle">
|
||||
<a-col :span="12"> </a-col>
|
||||
<a-col :span="6">
|
||||
<a-button
|
||||
type="link"
|
||||
:title="t('views.system.user.downloadObj')"
|
||||
@click.prevent="fnModalImportTemplate"
|
||||
>
|
||||
<a-button type="link" :title="t('views.system.user.downloadObj')" @click.prevent="fnModalImportTemplate">
|
||||
{{ t('views.system.user.downloadObj') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-textarea
|
||||
:disabled="true"
|
||||
:hidden="modalState.importMsgArr.length <= 0"
|
||||
:value="modalState.importMsgArr.join('\r\n')"
|
||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||
/>
|
||||
<a-textarea :disabled="true" :hidden="modalState.importMsgArr.length <= 0"
|
||||
:value="modalState.importMsgArr.join('\r\n')" :auto-size="{ minRows: 2, maxRows: 8 }"
|
||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)" />
|
||||
</template>
|
||||
</UploadModal>
|
||||
</div>
|
||||
|
||||
@@ -132,10 +132,9 @@ const graphNodeTooltip = new Tooltip({
|
||||
"
|
||||
>
|
||||
<div><strong>${t('views.neData.baseStation.state')}:</strong><span>
|
||||
${
|
||||
nInfo.state === 'ON'
|
||||
? t('views.neData.baseStation.online')
|
||||
: t('views.neData.baseStation.offline')
|
||||
${nInfo.state === 'ON'
|
||||
? t('views.neData.baseStation.online')
|
||||
: t('views.neData.baseStation.offline')
|
||||
}
|
||||
</span></div>
|
||||
<div><strong>${t('views.neData.baseStation.time')}:</strong><span>
|
||||
@@ -147,6 +146,8 @@ const graphNodeTooltip = new Tooltip({
|
||||
${nInfo.address ?? '--'}</span></div>
|
||||
<div><strong>${t('views.neData.baseStation.nbName')}:</strong><span>
|
||||
${nInfo.nbName ?? '--'}</span></div>
|
||||
<div><strong>${t('views.neData.baseStation.nbId')}:</strong><span>
|
||||
${nInfo.ranId ?? '--'}</span></div>
|
||||
<div><strong>${t('views.neData.baseStation.ueNum')}:</strong><span>
|
||||
${nInfo.ueNum ?? '--'}</span></div>
|
||||
<div><strong>${t('views.neData.baseStation.name')}:</strong><span>
|
||||
@@ -169,11 +170,10 @@ const graphNodeTooltip = new Tooltip({
|
||||
"
|
||||
>
|
||||
<div><strong>${t('views.monitor.topology.state')}:</strong><span>
|
||||
${
|
||||
nInfo.online
|
||||
? t('views.monitor.topology.normalcy')
|
||||
: t('views.monitor.topology.exceptions')
|
||||
}
|
||||
${nInfo.online
|
||||
? t('views.monitor.topology.normalcy')
|
||||
: t('views.monitor.topology.exceptions')
|
||||
}
|
||||
</span></div>
|
||||
<div><strong>${t('views.monitor.topology.refreshTime')}:</strong><span>
|
||||
${nInfo.refreshTime ?? '--'}
|
||||
@@ -417,7 +417,7 @@ async function fnGraphDataBase() {
|
||||
target: id,
|
||||
});
|
||||
}
|
||||
item.children.forEach((v: any) => {});
|
||||
item.children.forEach((v: any) => { });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ import {
|
||||
importUDMAuth,
|
||||
resetUDMAuth,
|
||||
listUDMAuth,
|
||||
exportUDMDecAuth,
|
||||
} from '@/api/neData/udm_auth';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { getNeViewFile } from '@/api/tool/neFile';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
/**网元参数 */
|
||||
@@ -117,6 +119,16 @@ let tableColumns = ref<ColumnsType>([
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'Create Time',
|
||||
dataIndex: 'createTime',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(+opt.value);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'imsi',
|
||||
@@ -505,6 +517,8 @@ function fnExportList(type: string) {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
queryParams.pageNum = 1;
|
||||
queryParams.pageSize = tablePagination.total;
|
||||
exportUDMAuth(Object.assign({ type: type }, queryParams))
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -519,6 +533,25 @@ function fnExportList(type: string) {
|
||||
});
|
||||
}
|
||||
|
||||
/** UDM鉴权用户导出DecAuth */
|
||||
function fnExportDec() {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
exportUDMDecAuth(neId)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.msgSuccess', { msg: t('common.export') }), 3);
|
||||
saveAs(res.data, `UDMAuth_dec_${Date.now()}.txt`);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**重新加载数据 */
|
||||
function fnLoadData() {
|
||||
const neId = queryParams.neId;
|
||||
@@ -817,7 +850,11 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-flex wrap="wrap" gap="small">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
v-perms:has="['neData:udm-auth:add']"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
@@ -829,6 +866,7 @@ onMounted(() => {
|
||||
danger
|
||||
ghost
|
||||
@click.prevent="fnModalVisibleByBatch()"
|
||||
v-perms:has="['neData:udm-auth:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
@@ -848,13 +886,18 @@ onMounted(() => {
|
||||
danger
|
||||
:disabled="modalState.loadDataLoading"
|
||||
:loading="modalState.loadDataLoading"
|
||||
v-perms:has="['neData:udm-auth:reload']"
|
||||
>
|
||||
<template #icon><SyncOutlined /></template>
|
||||
{{ t('views.neUser.auth.loadData') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnModalUploadImportOpen">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click.prevent="fnModalUploadImportOpen"
|
||||
v-perms:has="['neData:udm-auth:import']"
|
||||
>
|
||||
<template #icon><ImportOutlined /></template>
|
||||
{{ t('views.neUser.auth.import') }}
|
||||
</a-button>
|
||||
@@ -865,13 +908,20 @@ onMounted(() => {
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
v-if="false"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<a-button type="dashed" v-perms:has="['neData:udm-auth:export']">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('views.neUser.auth.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click="fnExportDec()"
|
||||
v-perms:has="['neData:udm-auth:export-dec']"
|
||||
>
|
||||
<template #icon><ExportOutlined /></template>
|
||||
Export Dec
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
@@ -879,6 +929,7 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['neData:udm-auth:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('views.neUser.auth.checkDel') }}
|
||||
@@ -891,11 +942,11 @@ onMounted(() => {
|
||||
ok-type="default"
|
||||
@confirm="fnRecordExport('txt')"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
v-if="false"
|
||||
>
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
v-perms:has="['neData:udm-auth:export']"
|
||||
>
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('views.neUser.auth.checkExport') }}
|
||||
@@ -980,6 +1031,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record)"
|
||||
v-perms:has="['neData:udm-auth:edit']"
|
||||
>
|
||||
<template #icon>
|
||||
<FormOutlined />
|
||||
@@ -991,6 +1043,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.imsi)"
|
||||
v-perms:has="['neData:udm-auth:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
} from '@/api/neData/udm_sub';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { getNeViewFile } from '@/api/tool/neFile';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
/**网元参数 */
|
||||
@@ -155,6 +156,16 @@ let tableColumns = ref<ColumnsType>([
|
||||
minWidth: 150,
|
||||
maxWidth: 500,
|
||||
},
|
||||
{
|
||||
title: 'Create Time',
|
||||
dataIndex: 'createTime',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(+opt.value);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'imsi',
|
||||
@@ -875,6 +886,8 @@ function fnExportList(type: string) {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
queryParams.pageNum = 1;
|
||||
queryParams.pageSize = tablePagination.total;
|
||||
exportUDMSub(Object.assign({ type: type }, queryParams))
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -1218,7 +1231,11 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-flex wrap="wrap" gap="small">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
v-perms:has="['neData:udm-sub:add']"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
@@ -1230,6 +1247,7 @@ onMounted(() => {
|
||||
danger
|
||||
ghost
|
||||
@click.prevent="fnModalVisibleByBatch()"
|
||||
v-perms:has="['neData:udm-sub:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
@@ -1249,6 +1267,7 @@ onMounted(() => {
|
||||
danger
|
||||
:disabled="modalState.loadDataLoading"
|
||||
:loading="modalState.loadDataLoading"
|
||||
v-perms:has="['neData:udm-sub:reload']"
|
||||
>
|
||||
<template #icon>
|
||||
<SyncOutlined />
|
||||
@@ -1257,7 +1276,11 @@ onMounted(() => {
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnModalUploadImportOpen">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click.prevent="fnModalUploadImportOpen"
|
||||
v-perms:has="['neData:udm-sub:import']"
|
||||
>
|
||||
<template #icon>
|
||||
<ImportOutlined />
|
||||
</template>
|
||||
@@ -1271,7 +1294,7 @@ onMounted(() => {
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<a-button type="dashed" v-perms:has="['neData:udm-sub:export']">
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
@@ -1285,6 +1308,7 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['neData:udm-sub:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
@@ -1303,6 +1327,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
v-perms:has="['neData:udm-sub:export']"
|
||||
>
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
@@ -1408,6 +1433,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record.imsi)"
|
||||
v-perms:has="['neData:udm-sub:edit']"
|
||||
>
|
||||
<template #icon>
|
||||
<FormOutlined />
|
||||
@@ -1419,6 +1445,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.imsi)"
|
||||
v-perms:has="['neData:udm-sub:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { reactive, ref, onMounted, toRaw, computed } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import {
|
||||
@@ -28,6 +28,8 @@ import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { getNeViewFile } from '@/api/tool/neFile';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
/**网元参数 */
|
||||
@@ -49,6 +51,13 @@ let queryParams = reactive({
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
const hasAnyBatchPermission = computed(() => {
|
||||
return (
|
||||
hasPermissions(['neData:udm-voip:add']) ||
|
||||
hasPermissions(['neData:udm-voip:delete'])
|
||||
);
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
@@ -94,6 +103,16 @@ let tableColumns = ref<TableColumnsType>([
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
},
|
||||
{
|
||||
title: 'Create Time',
|
||||
dataIndex: 'createTime',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(+opt.value);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
@@ -363,6 +382,8 @@ function fnExportList(type: string) {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
queryParams.pageNum = 1;
|
||||
queryParams.pageSize = tablePagination.total;
|
||||
exportUDMVOIP(Object.assign({ type: type }, queryParams))
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -659,7 +680,11 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
v-perms:has="['neData:udm-voip:add']"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
@@ -672,23 +697,30 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['neData:udm-voip:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('views.neData.common.checkDel') }}
|
||||
</a-button>
|
||||
|
||||
<a-dropdown trigger="click">
|
||||
<a-dropdown trigger="click" v-if="hasAnyBatchPermission">
|
||||
<a-button>
|
||||
{{ t('views.neData.common.batchOper') }}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }:any) => fnModalVisibleByBatch(key)">
|
||||
<a-menu-item key="add">
|
||||
<a-menu-item
|
||||
key="add"
|
||||
v-if="hasPermissions(['neData:udm-voip:add'])"
|
||||
>
|
||||
<PlusOutlined />
|
||||
{{ t('views.neData.common.batchAddText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="delete">
|
||||
<a-menu-item
|
||||
key="delete"
|
||||
v-if="hasPermissions(['neData:udm-voip:delete'])"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
{{ t('views.neData.common.batchDelText') }}
|
||||
</a-menu-item>
|
||||
@@ -709,13 +741,18 @@ onMounted(() => {
|
||||
danger
|
||||
:disabled="modalState.loadDataLoading"
|
||||
:loading="modalState.loadDataLoading"
|
||||
v-perms:has="['neData:udm-voip:reload']"
|
||||
>
|
||||
<template #icon><SyncOutlined /></template>
|
||||
{{ t('views.neData.common.loadData') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnModalUploadImportOpen">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click.prevent="fnModalUploadImportOpen"
|
||||
v-perms:has="['neData:udm-voip:import']"
|
||||
>
|
||||
<template #icon><ImportOutlined /></template>
|
||||
{{ t('common.import') }}
|
||||
</a-button>
|
||||
@@ -726,7 +763,7 @@ onMounted(() => {
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<a-button type="dashed" v-perms:has="['neData:udm-voip:export']">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
@@ -816,6 +853,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.username)"
|
||||
v-perms:has="['neData:udm-voip:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { reactive, ref, onMounted, toRaw, computed } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import {
|
||||
@@ -28,8 +28,16 @@ import {
|
||||
listUDMVolteIMS,
|
||||
resetUDMVolteIMS,
|
||||
} from '@/api/neData/udm_volte_ims';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
const { t } = useI18n();
|
||||
const neListStore = useNeListStore();
|
||||
const hasAnyBatchPermission = computed(() => {
|
||||
return (
|
||||
hasPermissions(['neData:udm-volte:add']) ||
|
||||
hasPermissions(['neData:udm-volte:delete'])
|
||||
);
|
||||
});
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**Tag标签类型 0=VoIP, 1=VoLTE */
|
||||
@@ -145,6 +153,16 @@ let tableColumns = ref<TableColumnsType>([
|
||||
minWidth: 250,
|
||||
maxWidth: 400,
|
||||
},
|
||||
{
|
||||
title: 'Create Time',
|
||||
dataIndex: 'createTime',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(+opt.value);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('common.operate'),
|
||||
key: 'id',
|
||||
@@ -442,6 +460,8 @@ function fnExportList(type: string) {
|
||||
const neId = queryParams.neId;
|
||||
if (!neId) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
queryParams.pageNum = 1;
|
||||
queryParams.pageSize = tablePagination.total;
|
||||
exportUDMVolteIMS(Object.assign({ type: type }, queryParams))
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -449,7 +469,7 @@ function fnExportList(type: string) {
|
||||
content: t('common.operateOk'),
|
||||
duration: 2,
|
||||
});
|
||||
saveAs(res.data, `UDM_VOLTE_${neId}_${Date.now()}.${type}`);
|
||||
saveAs(res.data, `UDM_VoLTE_${neId}_${Date.now()}.${type}`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
@@ -755,7 +775,11 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
v-perms:has="['neData:udm-volte:add']"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
@@ -768,23 +792,30 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['neData:udm-volte:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('views.neData.common.checkDel') }}
|
||||
</a-button>
|
||||
|
||||
<a-dropdown trigger="click">
|
||||
<a-dropdown trigger="click" v-if="hasAnyBatchPermission">
|
||||
<a-button>
|
||||
{{ t('views.neData.common.batchOper') }}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }:any) => fnModalVisibleByBatch(key)">
|
||||
<a-menu-item key="add">
|
||||
<a-menu-item
|
||||
key="add"
|
||||
v-if="hasPermissions(['neData:udm-volte:add'])"
|
||||
>
|
||||
<PlusOutlined />
|
||||
{{ t('views.neData.common.batchAddText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="delete">
|
||||
<a-menu-item
|
||||
key="delete"
|
||||
v-if="hasPermissions(['neData:udm-volte:delete'])"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
{{ t('views.neData.common.batchDelText') }}
|
||||
</a-menu-item>
|
||||
@@ -805,13 +836,18 @@ onMounted(() => {
|
||||
danger
|
||||
:disabled="modalState.loadDataLoading"
|
||||
:loading="modalState.loadDataLoading"
|
||||
v-perms:has="['neData:udm-volte:reload']"
|
||||
>
|
||||
<template #icon><SyncOutlined /></template>
|
||||
{{ t('views.neData.common.loadData') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnModalUploadImportOpen">
|
||||
<a-button
|
||||
type="dashed"
|
||||
@click.prevent="fnModalUploadImportOpen"
|
||||
v-perms:has="['neData:udm-volte:import']"
|
||||
>
|
||||
<template #icon><ImportOutlined /></template>
|
||||
{{ t('common.import') }}
|
||||
</a-button>
|
||||
@@ -822,7 +858,7 @@ onMounted(() => {
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<a-button type="dashed" v-perms:has="['neData:udm-volte:export']">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
@@ -915,6 +951,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
v-perms:has="['neData:udm-volte:delete']"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
|
||||
@@ -80,12 +80,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: 'NE Type',
|
||||
dataIndex: 'neType',
|
||||
|
||||
+1357
-851
File diff suppressed because it is too large.
Load diff
@@ -77,11 +77,11 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: t('views.perfManage.taskManage.neType'),
|
||||
dataIndex: 'neType',
|
||||
|
||||
@@ -21,6 +21,7 @@ import useDictStore from '@/store/modules/dict';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import { hasPermissions } from '@/plugins/auth-user';
|
||||
const { t } = useI18n();
|
||||
const { getDict } = useDictStore();
|
||||
|
||||
@@ -95,12 +96,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'configId',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'configId',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.system.config.configName'),
|
||||
dataIndex: 'configName',
|
||||
@@ -665,11 +666,11 @@ onMounted(() => {
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: tableColumns.length * 120 }"
|
||||
:row-selection="{
|
||||
:row-selection="hasPermissions(['system:config:remove']) ? {
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
}: undefined"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'configType'">
|
||||
|
||||
@@ -83,12 +83,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns = ref<ColumnsType>([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.system.loginSource.uid'),
|
||||
dataIndex: 'uid',
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
<script lang="ts" setup>
|
||||
import { message, Modal } from 'ant-design-vue/es';
|
||||
import { reactive } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { FileType } from 'ant-design-vue/es/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
|
||||
import { uploadFileChunk } from '@/api/tool/file';
|
||||
import { exportBackupOMC, importBackupOMC } from '@/api/neData/backup';
|
||||
import saveAs from 'file-saver';
|
||||
const { t } = useI18n();
|
||||
|
||||
type StateType = {
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
let state: StateType = reactive({
|
||||
loading: false,
|
||||
});
|
||||
|
||||
/**导出 */
|
||||
function fnExport() {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.system.setting.backupExportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
exportBackupOMC()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
saveAs(res.data, `BackupOMC-${Date.now()}.zip`);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**上传前检查或转换压缩 */
|
||||
function fnBeforeUpload(file: FileType) {
|
||||
if (state.loading) return false;
|
||||
console.log(file);
|
||||
if (file.type !== 'application/x-zip-compressed') {
|
||||
message.error(
|
||||
t('views.system.setting.uploadFormat', { format: 'zip' }),
|
||||
3
|
||||
);
|
||||
}
|
||||
// const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
// if (!isLt10M) {
|
||||
// message.error(t('views.system.setting.uploadSize', { size: 10 }), 3);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**上传变更 */
|
||||
function fnUpload(up: UploadRequestOption) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.system.setting.backupImportTip'),
|
||||
onOk() {
|
||||
// 发送请求
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
state.loading = true;
|
||||
uploadFileChunk(up.file as File, 5, 'import')
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
return importBackupOMC(res.data.filePath);
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.then(res => {
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false;
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-button type="default" @click="fnExport()">
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
<a-upload
|
||||
name="file"
|
||||
list-type="picture"
|
||||
accept=".zip"
|
||||
:max-count="1"
|
||||
:show-upload-list="false"
|
||||
:before-upload="fnBeforeUpload"
|
||||
:custom-request="fnUpload"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<a-button type="link" :disabled="state.loading">
|
||||
{{ t('common.import') }}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-typography>
|
||||
<a-typography-paragraph>
|
||||
{{ t('views.system.setting.backupInstruction') }}
|
||||
</a-typography-paragraph>
|
||||
</a-typography>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -8,6 +8,7 @@ import ChangeHelpDoc from './components/change-help-doc.vue';
|
||||
import ChangeOfficialUrl from './components/change-official-url.vue';
|
||||
import ChangeI18n from './components/change-i18n.vue';
|
||||
import SystemReset from './components/system-reset.vue';
|
||||
import SystemBackup from './components/system-backup.vue';
|
||||
import ChangeHome from './components/change-home-index.vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t } = useI18n();
|
||||
@@ -50,14 +51,24 @@ const { t } = useI18n();
|
||||
</a-divider>
|
||||
<ChangeI18n></ChangeI18n>
|
||||
</div>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.homeSet') }}
|
||||
</a-divider>
|
||||
<ChangeHome></ChangeHome>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.reset') }}
|
||||
</a-divider>
|
||||
<SystemReset></SystemReset>
|
||||
<div v-perms:has="['system:setting:homeSet']">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.homeSet') }}
|
||||
</a-divider>
|
||||
<ChangeHome></ChangeHome>
|
||||
</div>
|
||||
<div v-perms:has="['system:setting:backup']">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.backup') }}
|
||||
</a-divider>
|
||||
<SystemBackup></SystemBackup>
|
||||
</div>
|
||||
<div v-perms:has="['system:setting:reset']">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.reset') }}
|
||||
</a-divider>
|
||||
<SystemReset></SystemReset>
|
||||
</div>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
@@ -65,12 +65,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
width: 50,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'center',
|
||||
// width: 50,
|
||||
// },
|
||||
{
|
||||
title: t('views.ne.neHost.hostType'),
|
||||
dataIndex: 'hostType',
|
||||
|
||||
@@ -593,13 +593,13 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button @click="fnFileView()">
|
||||
<a-button @click="fnFileView()" v-perms:has="['traceManage:pcap:fileview']">
|
||||
<FileSearchOutlined />
|
||||
{{ t('views.traceManage.pcap.fileView') }}
|
||||
</a-button>
|
||||
|
||||
<a-dropdown trigger="click">
|
||||
<a-button :disabled="tableState.selectedRowKeys.length <= 0">
|
||||
<a-button :disabled="tableState.selectedRowKeys.length <= 0" >
|
||||
{{ t('views.traceManage.pcap.batchOper') }}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
@@ -678,6 +678,7 @@ onMounted(() => {
|
||||
size="small"
|
||||
:disabled="modalState.from[record.id].loading"
|
||||
@click.prevent="fnRecordStart(record)"
|
||||
v-perms:has="['traceManage:pcap:start']"
|
||||
>
|
||||
<template #icon><PlayCircleOutlined /> </template>
|
||||
</a-button>
|
||||
@@ -697,6 +698,7 @@ onMounted(() => {
|
||||
danger
|
||||
size="small"
|
||||
@click.prevent="fnRecordStop(record)"
|
||||
v-perms:has="['traceManage:pcap:stop']"
|
||||
>
|
||||
<template #icon><StopOutlined /> </template>
|
||||
</a-button>
|
||||
@@ -736,6 +738,7 @@ onMounted(() => {
|
||||
ghost
|
||||
size="small"
|
||||
@click.prevent="fnDownPCAP(record)"
|
||||
v-perms:has="['traceManage:pcap:download']"
|
||||
>
|
||||
<template #icon><DownloadOutlined /> </template>
|
||||
</a-button>
|
||||
|
||||
@@ -83,12 +83,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = reactive([
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'right',
|
||||
width: 50,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'right',
|
||||
// width: 50,
|
||||
// },
|
||||
{
|
||||
title: t('views.traceManage.task.imsi'),
|
||||
dataIndex: 'imsi',
|
||||
|
||||
@@ -95,12 +95,12 @@ let tableState: TabeStateType = reactive({
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('common.rowId'),
|
||||
dataIndex: 'id',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: t('common.rowId'),
|
||||
// dataIndex: 'id',
|
||||
// align: 'left',
|
||||
// width: 100,
|
||||
// },
|
||||
{
|
||||
title: t('views.traceManage.task.msgNe'),
|
||||
dataIndex: 'msgNe',
|
||||
|
||||
@@ -701,7 +701,7 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="primary" @click.prevent="fnModalOpenByEdit()">
|
||||
<a-button type="primary" @click.prevent="fnModalOpenByEdit()" v-perms:has="['traceManage:task:add']">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
@@ -712,6 +712,7 @@ onMounted(() => {
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.confirmLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
v-perms:has="['traceManage:task:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('common.deleteText') }}
|
||||
@@ -796,6 +797,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordView(record, 'data')"
|
||||
v-perms:has="['traceManage:task:dataview']"
|
||||
>
|
||||
<template #icon><ContainerOutlined /></template>
|
||||
</a-button>
|
||||
@@ -809,6 +811,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordView(record, 'analyze')"
|
||||
v-perms:has="['traceManage:task:pcapview']"
|
||||
>
|
||||
<template #icon><BarsOutlined /></template>
|
||||
</a-button>
|
||||
@@ -820,6 +823,7 @@ onMounted(() => {
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalOpenByEdit(record.id)"
|
||||
v-perms:has="['traceManage:task:edit']"
|
||||
>
|
||||
<template #icon><ProfileOutlined /></template>
|
||||
</a-button>
|
||||
@@ -830,6 +834,7 @@ onMounted(() => {
|
||||
type="link"
|
||||
danger
|
||||
@click.prevent="fnRecordDelete(record.id)"
|
||||
v-perms:has="['traceManage:task:delete']"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
@@ -582,6 +582,7 @@ onBeforeUnmount(() => {
|
||||
type="primary"
|
||||
@click="fnStart"
|
||||
:disabled="!taskState.stop && taskState.task.taskNo !== ''"
|
||||
v-perms:has="['traceManage:wireshark:start']"
|
||||
>
|
||||
<PlayCircleOutlined />
|
||||
Start Trace
|
||||
@@ -610,6 +611,7 @@ onBeforeUnmount(() => {
|
||||
danger
|
||||
@click.prevent="fnStop()"
|
||||
:disabled="taskState.stop || taskState.task.taskNo === ''"
|
||||
v-perms:has="['traceManage:wireshark:stop']"
|
||||
>
|
||||
<template #icon><CloseCircleOutlined /></template>
|
||||
Stop Trace
|
||||
|
||||
Reference in new issue
Block a user