Merge branch 'main-v2' into lite-ba

This commit is contained in:
TsMask
2025-08-29 19:53:10 +08:00
18 changed files with 114 additions and 77 deletions

View File

@@ -1,5 +1,17 @@
# 版本发布日志 # 版本发布日志
## 2.2508.4-20250829
- 新增 网元授权显示用户数/基站数
- 优化 网元当前版本显示是否有包存在
- 优化 cdr/ue导出操作后锁定按钮事件防重发
- 优化 网元可选静态可选项添加PGWC
- 优化 参数配置添加校验过滤长度~和-定义范围
- 修复 UPF流量统计数据同时获取刷新
- 修复 UPF流量统计字节数据格式化显示不一致问题
- 新增 指标Title管理页面功能
- 新增 增加多个导出操作的超时时间至180秒
## 2.2508.2-20250815 ## 2.2508.2-20250815
- 优化 给config.js加随机数避免缓存 - 优化 给config.js加随机数避免缓存

View File

@@ -22,6 +22,12 @@ export const NE_TYPE_LIST = [
'CHF', 'CHF',
'HLR', 'HLR',
'SGWC', 'SGWC',
'PGWC',
'IP-SM-GW',
'MMTel-AS',
'I-CSCF',
'P-CSCF',
'S-CSCF',
]; ];
/** /**

View File

@@ -539,6 +539,8 @@ export default {
port: 'Port', port: 'Port',
portTip: "Network element port default:33030", portTip: "Network element port default:33030",
capability: 'Capability', capability: 'Capability',
ueNumber: 'UE Number',
nbNumber: 'Radio Number',
serialNum: 'Serial Number', serialNum: 'Serial Number',
expiryDate: 'Expiry Date', expiryDate: 'Expiry Date',
normalcy: 'Normal', normalcy: 'Normal',

View File

@@ -539,6 +539,8 @@ export default {
port: '服务端口', port: '服务端口',
portTip: "网元服务端口,默认:33030", portTip: "网元服务端口,默认:33030",
capability: '容量', capability: '容量',
ueNumber: '用户数',
nbNumber: '基站数',
serialNum: '序列号', serialNum: '序列号',
expiryDate: '许可证到期日期', expiryDate: '许可证到期日期',
normalcy: '正常', normalcy: '正常',

View File

@@ -177,25 +177,6 @@ export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
return [(realBit / 1000 / 1000).toFixed(2), ' Mbits/sec']; 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 * @param byte 字节Byte大小 64009540 = 512.08 MB

View File

@@ -339,6 +339,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.ue.exportTip'), content: t('views.dashboard.ue.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -408,6 +408,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.cdr.exportTip'), content: t('views.dashboard.cdr.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -341,6 +341,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.ue.exportTip'), content: t('views.dashboard.ue.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -1,5 +1,5 @@
import { parseDateToStr } from '@/utils/date-utils'; import { parseDateToStr } from '@/utils/date-utils';
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils'; import { parseSizeFromByte, parseSizeFromKbs } from '@/utils/parse-utils';
import { ref } from 'vue'; import { ref } from 'vue';
type FDType = { type FDType = {
@@ -81,9 +81,9 @@ export function upfTFParse(day: string, data: Record<string, number>) {
let { up, down } = data; let { up, down } = data;
upfTotalFlow.value[day] = { upfTotalFlow.value[day] = {
up: up, up: up,
upFrom: parseSizeFromBits(up), upFrom: parseSizeFromByte(up),
down: down, down: down,
downFrom: parseSizeFromBits(down), downFrom: parseSizeFromByte(down),
requestFlag: false, requestFlag: false,
}; };
} }

View File

@@ -229,15 +229,15 @@ function loadData() {
interval10s.value = setInterval(() => { interval10s.value = setInterval(() => {
if (!interval10s.value || !initFlag) return; if (!interval10s.value || !initFlag) return;
if (upfTFActive.value === '0') { if (upfTFActive.value === '0') {
upfTFSend('7');
upfTFActive.value = '7'; upfTFActive.value = '7';
} else if (upfTFActive.value === '7') { } else if (upfTFActive.value === '7') {
upfTFSend('30');
upfTFActive.value = '30'; upfTFActive.value = '30';
} else if (upfTFActive.value === '30') { } else if (upfTFActive.value === '30') {
upfTFSend('0');
upfTFActive.value = '0'; upfTFActive.value = '0';
} }
upfTFSend('0');
upfTFSend('7');
upfTFSend('30');
}, 10_000); }, 10_000);
clearInterval(interval5s.value); clearInterval(interval5s.value);

View File

@@ -1,5 +1,5 @@
import { parseDateToStr } from '@/utils/date-utils'; import { parseDateToStr } from '@/utils/date-utils';
import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils'; import { parseSizeFromByte, parseSizeFromKbs } from '@/utils/parse-utils';
import { ref } from 'vue'; import { ref } from 'vue';
type FDType = { type FDType = {
@@ -79,9 +79,9 @@ export function upfTFParse(day: string, data: Record<string, number>) {
let { up, down } = data; let { up, down } = data;
upfTotalFlow.value[day] = { upfTotalFlow.value[day] = {
up: up, up: up,
upFrom: parseSizeFromBits(up), upFrom: parseSizeFromByte(up),
down: down, down: down,
downFrom: parseSizeFromBits(down), downFrom: parseSizeFromByte(down),
requestFlag: false, requestFlag: false,
}; };
} }

View File

@@ -176,15 +176,15 @@ async function fnGetSkim() {
{ {
request: (neId: string) => listAMFNblist({ neId }), request: (neId: string) => listAMFNblist({ neId }),
process: async (res: any, neId: any) => { process: async (res: any, neId: any) => {
console.log(neId) console.log(neId);
if (res.code === RESULT_CODE_SUCCESS&& Array.isArray(res.data)) { if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
skimState.gnbNum += res.data.length; skimState.gnbNum += res.data.length;
skimState.gnbUeNum += res.data.reduce( skimState.gnbUeNum += res.data.reduce(
(sum: number, item: any) => sum + item.ueNum, (sum: number, item: any) => sum + item.ueNum,
0 0
); );
const amfNbRes = await listAMFNbStatelist({ neId }); const amfNbRes = await listAMFNbStatelist({ neId });
console.log(amfNbRes) console.log(amfNbRes);
if ( if (
amfNbRes.code === RESULT_CODE_SUCCESS && amfNbRes.code === RESULT_CODE_SUCCESS &&
Array.isArray(amfNbRes.data) Array.isArray(amfNbRes.data)
@@ -224,13 +224,13 @@ async function fnGetSkim() {
); );
const mmeNbRes = await listMMENbStatelist({ neId }); const mmeNbRes = await listMMENbStatelist({ neId });
console.log(mmeNbRes) console.log(mmeNbRes);
if ( if (
mmeNbRes.code === RESULT_CODE_SUCCESS && mmeNbRes.code === RESULT_CODE_SUCCESS &&
Array.isArray(mmeNbRes.data) Array.isArray(mmeNbRes.data)
) { ) {
// skimState.eNbSumNum += mmeNbRes.data.length; // skimState.eNbSumNum += mmeNbRes.data.length;
console.log(mmeNbRes) console.log(mmeNbRes);
tempEnbSumNum += mmeNbRes.data.length; tempEnbSumNum += mmeNbRes.data.length;
} }
} }
@@ -238,21 +238,20 @@ async function fnGetSkim() {
}, },
], ],
]); ]);
console.log(neCascaderOptions) console.log(neCascaderOptions);
const requests = neCascaderOptions.value.flatMap( const requests = neCascaderOptions.value.flatMap(
(ne: any) => (ne: any) =>
ne.children ne.children
?.map((child: any) => { ?.map((child: any) => {
console.log(child.neId) console.log(child.neId);
const handler = neHandlers.get(child.neType); const handler = neHandlers.get(child.neType);
return handler return handler
? { ? {
promise: handler.request(child.neId), promise: handler.request(child.neId),
process: handler.process, process: handler.process,
neId: child.neId, // 这里加上neId neId: child.neId, // 这里加上neId
}
}
: null; : null;
}) })
.filter(Boolean) || [] .filter(Boolean) || []
@@ -311,15 +310,15 @@ function loadData() {
interval10s.value = setInterval(() => { interval10s.value = setInterval(() => {
if (!interval10s.value || !initFlag) return; if (!interval10s.value || !initFlag) return;
if (upfTFActive.value === '0') { if (upfTFActive.value === '0') {
upfTFSend('7');
upfTFActive.value = '7'; upfTFActive.value = '7';
} else if (upfTFActive.value === '7') { } else if (upfTFActive.value === '7') {
upfTFSend('30');
upfTFActive.value = '30'; upfTFActive.value = '30';
} else if (upfTFActive.value === '30') { } else if (upfTFActive.value === '30') {
upfTFSend('0');
upfTFActive.value = '0'; upfTFActive.value = '0';
} }
upfTFSend('0');
upfTFSend('7');
upfTFSend('30');
}, 10_000); }, 10_000);
clearInterval(interval5s.value); clearInterval(interval5s.value);
@@ -375,12 +374,14 @@ async function fnSelectUDM(e: any) {
pageNum: 1, pageNum: 1,
pageSize: 1, pageSize: 1,
}); });
console.log(res) console.log(res);
// listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(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; skimState.udmSubNum = res.data.total;
console.log(res) console.log(res);
} else { } else {
skimState.udmSubNum = 0; skimState.udmSubNum = 0;
} }
@@ -393,7 +394,7 @@ async function fnSelectUDM(e: any) {
} }
/**资源控制-选择NE */ /**资源控制-选择NE */
function fnSelectNeRe(e: any) { function fnSelectNeRe(e: any) {
console.log(e) console.log(e);
graphNodeClickID.value = e.key; graphNodeClickID.value = e.key;
} }
// //
@@ -408,7 +409,7 @@ const getPopupContainer = () => {
onMounted(() => { onMounted(() => {
// 获取网元网元列表 // 获取网元网元列表
neListStore.neCascaderOptions.forEach(item => { neListStore.neCascaderOptions.forEach(item => {
console.log(item) console.log(item);
if (item.value === 'UPF') { if (item.value === 'UPF') {
neOtions.value = JSON.parse(JSON.stringify(item.children)); neOtions.value = JSON.parse(JSON.stringify(item.children));
} }

View File

@@ -378,6 +378,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.cdr.exportTip'), content: t('views.dashboard.cdr.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -405,6 +405,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.cdr.exportTip'), content: t('views.dashboard.cdr.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -372,6 +372,7 @@ function fnExportList() {
title: t('common.tipTitle'), title: t('common.tipTitle'),
content: t('views.dashboard.cdr.exportTip'), content: t('views.dashboard.cdr.exportTip'),
onOk() { onOk() {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0); const hide = message.loading(t('common.loading'), 0);
const querys = toRaw(queryParams); const querys = toRaw(queryParams);
querys.pageSize = 10000; querys.pageSize = 10000;

View File

@@ -29,8 +29,13 @@ export default function useOptions({ t }: any) {
case 'int': case 'int':
// filter: "0~128" // filter: "0~128"
if (filter && filter.indexOf('~') !== -1) { if (filter) {
const filterArr = filter.split('~'); 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 minInt = parseInt(filterArr[0]);
const maxInt = parseInt(filterArr[1]); const maxInt = parseInt(filterArr[1]);
const valueInt = parseInt(value); const valueInt = parseInt(value);
@@ -47,18 +52,12 @@ export default function useOptions({ t }: any) {
break; break;
case 'ipv4': case 'ipv4':
if (!regExpIPv4.test(value)) { if (!regExpIPv4.test(value)) {
return [ return [false, t('views.ne.neConfig.requireIpv4', { display })];
false,
t('views.ne.neConfig.requireIpv4', { display }),
];
} }
break; break;
case 'ipv6': case 'ipv6':
if (!regExpIPv6.test(value)) { if (!regExpIPv6.test(value)) {
return [ return [false, t('views.ne.neConfig.requireIpv6', { display })];
false,
t('views.ne.neConfig.requireIpv6', { display }),
];
} }
break; break;
case 'enum': case 'enum':
@@ -71,10 +70,7 @@ export default function useOptions({ t }: any) {
} }
if (!Object.keys(filterJson).includes(`${value}`)) { if (!Object.keys(filterJson).includes(`${value}`)) {
return [ return [false, t('views.ne.neConfig.requireEnum', { display })];
false,
t('views.ne.neConfig.requireEnum', { display }),
];
} }
} }
break; break;
@@ -90,10 +86,7 @@ export default function useOptions({ t }: any) {
} }
if (!Object.values(filterJson).includes(`${value}`)) { if (!Object.values(filterJson).includes(`${value}`)) {
return [ return [false, t('views.ne.neConfig.requireBool', { display })];
false,
t('views.ne.neConfig.requireBool', { display }),
];
} }
} }
break; break;
@@ -101,12 +94,20 @@ export default function useOptions({ t }: any) {
// filter: "0~128" // filter: "0~128"
// 字符串长度判断 // 字符串长度判断
if (filter && filter.indexOf('~') !== -1) { if (filter) {
try { try {
const filterArr = filter.split('~'); let rule: RegExp = new RegExp('^.*$');
let rule = new RegExp( if (filter.indexOf('-') !== -1) {
'^\\S{' + filterArr[0] + ',' + filterArr[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)) { if (!rule.test(value)) {
return [ return [
false, false,
@@ -157,10 +158,7 @@ export default function useOptions({ t }: any) {
break; break;
default: default:
return [ return [false, t('views.ne.neConfig.requireUn', { display })];
false,
t('views.ne.neConfig.requireUn', { display }),
];
} }
return result; return result;
} }

View File

@@ -105,8 +105,8 @@ let tableColumns = ref<TableColumnsType>([
width: 120, width: 120,
}, },
{ {
title: t('views.ne.common.capability'), title: t('views.ne.common.ueNumber'),
dataIndex: 'capability', dataIndex: 'ueNumber',
align: 'left', align: 'left',
customRender(opt) { customRender(opt) {
if (['UDM', 'AMF', 'MME'].includes(opt.record.neType)) { if (['UDM', 'AMF', 'MME'].includes(opt.record.neType)) {
@@ -116,6 +116,18 @@ let tableColumns = ref<TableColumnsType>([
}, },
width: 100, 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'), title: t('common.remark'),
dataIndex: 'remark', dataIndex: 'remark',
@@ -276,7 +288,8 @@ function fnRecordState(row: Record<string, any>) {
row.status = '1'; row.status = '1';
row.serialNum = res.data.sn; row.serialNum = res.data.sn;
row.expiryDate = res.data.expire; 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(); row.updateTime = new Date().getTime();
message.success( message.success(
`${row.neType} ${row.neId} ${dictStatus.value[1].label}`, `${row.neType} ${row.neId} ${dictStatus.value[1].label}`,

View File

@@ -108,6 +108,7 @@ let tableColumns = ref<TableColumnsType>([
{ {
title: t('views.ne.neVersion.version'), title: t('views.ne.neVersion.version'),
dataIndex: 'version', dataIndex: 'version',
key: 'version',
align: 'left', align: 'left',
width: 150, width: 150,
resizable: true, resizable: true,
@@ -605,6 +606,21 @@ onMounted(() => {
<template v-if="column.key === 'status'"> <template v-if="column.key === 'status'">
<DictTag :options="dictStatus" :value="record.status" /> <DictTag :options="dictStatus" :value="record.status" />
</template> </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'"> <template v-if="column.key === 'preVersion'">
{{ record.preVersion }} {{ record.preVersion }}
<a-tooltip <a-tooltip