From 96c1f54b71096978d5657635053f59ab2ef4a223 Mon Sep 17 00:00:00 2001 From: zhongzm Date: Fri, 18 Jul 2025 17:27:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E7=BB=BC=E5=90=88=E4=BB=AA=E8=A1=A8?= =?UTF-8?q?=E7=9B=98=E4=BF=AE=E6=94=B9=E8=BF=81=E7=A7=BB=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=85=BC=E5=AE=B9=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/api/neUser/base5G.ts | 34 ++ src/api/neUser/ims.ts | 66 ++++ src/api/neUser/smf.ts | 113 +++++++ src/i18n/locales/en-US.ts | 6 +- src/i18n/locales/zh-CN.ts | 6 +- src/store/modules/neinfo.ts | 93 ++++++ .../components/AlarnTypeBar/index.vue | 197 ++++++----- .../components/NeResources/index.vue | 2 +- .../overview2/components/Topology/index.vue | 28 +- src/views/dashboard/overview2/index.vue | 314 ++++++++---------- 11 files changed, 584 insertions(+), 276 deletions(-) create mode 100644 src/api/neUser/base5G.ts create mode 100644 src/api/neUser/ims.ts create mode 100644 src/api/neUser/smf.ts create mode 100644 src/store/modules/neinfo.ts diff --git a/package.json b/package.json index 3c04f55a..07a2b8ac 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "crypto-js": "4.2.0", "dayjs": "1.11.13", "echarts": "5.6.0", + "echarts-liquidfill": "^3.1.0", "file-saver": "2.0.5", "grid-layout-plus": "1.0.6", "intl-tel-input": "25.2.0", diff --git a/src/api/neUser/base5G.ts b/src/api/neUser/base5G.ts new file mode 100644 index 00000000..662ba2d7 --- /dev/null +++ b/src/api/neUser/base5G.ts @@ -0,0 +1,34 @@ +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { request } from '@/plugins/http-fetch'; +import { parseObjLineToHump } from '@/utils/parse-utils'; + +/** + * 查询列表 + * @param query 查询参数 + * @returns object + */ +export async function listBase5G(query: Record) { + const result = await request({ + url: `/api/rest/ueManagement/v1/elementType/${query.neType.toLowerCase()}/objectType/nbInfo`, + method: 'GET', + params: query, + }); + let data: DataList = { + total: 0, + rows: [], + code: result.code, + msg: result.msg, + }; + // 解析数据 + if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { + const rows = parseObjLineToHump(result.data.data); + data.total = rows.length; + data.rows = rows; + } + + // 模拟数据 + // data.rows = [{"address":"192.168.1.137:38412","id":"217","name":"attach-enb-100000-20","ueNum":0}] + // data.rows = [{address: "192.168.8.223", id: 257, name: "SmallCell", ueNum: 0}] + + return data; +} diff --git a/src/api/neUser/ims.ts b/src/api/neUser/ims.ts new file mode 100644 index 00000000..a29e7cea --- /dev/null +++ b/src/api/neUser/ims.ts @@ -0,0 +1,66 @@ +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { request } from '@/plugins/http-fetch'; +import { parseObjLineToHump } from '@/utils/parse-utils'; + +/** + * 查询列表 + * @param query 查询参数 + * @returns object + */ +export async function listUEInfoByIMS(query: Record) { + query.nbId = query.id; + const result = await request({ + url: '/api/rest/ueManagement/v1/elementType/ims/objectType/ueInfo', + method: 'GET', + params: query, + }); + let data: DataList = { + total: 0, + rows: [], + code: result.code, + msg: result.msg, + }; + // 解析数据 + if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) { + const rows = parseObjLineToHump(result.data.data); + data.total = rows.length; + data.rows = rows; + } + + // 测试数据 + // data.rows = [ + // { + // activeTime: '2023-11-29 17:04:54', + // barring: 0, + // impu: 'sip:12307551232@ims.mnc000.mcc460.3gppnetwork.org', + // imsi: '460001230000002', + // msisdn: '12307551232', + // regState: 1, + // }, + // ]; + return data; +} + +/** + * 首页查询IMS在线用户数 + * @param query 查询参数 + * @returns neId + */ +export async function listUENumByIMS(neId: String) { + const result = await request({ + url: `/api/rest/ueManagement/v1/elementType/ims/objectType/ueNum?neId=${neId}`, + method: 'GET', + }); + if (result.code === RESULT_CODE_SUCCESS) { + let num = result.data['ueNum'] || 0; + if (num === 0) { + num = result.data.data['ueNum'] || 0; + } + return Object.assign(result, { data: num }); + } + + // 模拟数据 + // { "ueNum": 0 } + // result.data = 0 + return result; +} diff --git a/src/api/neUser/smf.ts b/src/api/neUser/smf.ts new file mode 100644 index 00000000..dc436756 --- /dev/null +++ b/src/api/neUser/smf.ts @@ -0,0 +1,113 @@ +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { request } from '@/plugins/http-fetch'; + +/** + * 查询列表 + * @param query 查询参数 + * @returns object + */ +export async function listUEInfoBySMF(query: Record) { + query.nbId = query.id; + const result = await request({ + url: '/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo', + method: 'GET', + params: query, + }); + let data: DataList = { + total: 0, + rows: [], + code: result.code, + msg: result.msg, + }; + // 解析数据 + if (result.code === RESULT_CODE_SUCCESS && result.data) { + if (result.data.total && result.data.data) { + data.total = result.data.total; + data.rows = result.data.data; + } else { + Object.assign(data, { + total: result.data.length, + rows: result.data, + }); + } + } + + // 模拟数据 + // data.code = RESULT_CODE_SUCCESS; + // data.total = 2; + // data.rows = [ + // { + // imsi: 'imsi-460000100000090', + // msisdn: 'msisdn-12307550090', + // pduSessionInfo: [ + // { + // activeTime: '2024-06-19 14:35:26', + // dnn: 'ims', + // ipv4: '10.10.48.8', + // ipv6: '', + // pduSessionID: 6, + // ranN3IP: '192.168.1.137', + // sstSD: '1-000001', + // tai: '46000-001124', + // upState: 'Active', + // upfN3IP: '192.168.1.161', + // }, + // { + // activeTime: '2024-06-19 14:35:26', + // dnn: 'cmnet', + // ipv4: '10.10.48.9', + // ipv6: '2001:4860:4860::/64', + // pduSessionID: 7, + // ranN3IP: '192.168.1.137', + // sstSD: '1-000001', + // tai: '46000-001124', + // upState: 'Active', + // upfN3IP: '192.168.1.161', + // }, + // ], + // ratType: 'NR', + // }, + // { + // imsi: 'imsi-460602072701180', + // msisdn: 'msisdn-123460600080', + // pduSessionInfo: [ + // { + // activeTime: '2024-06-19 14:31:09', + // dnn: 'cmnet', + // ipv4: '10.10.48.4', + // ipv6: '', + // pduSessionID: 5, + // ranN3IP: '192.168.8.223', + // sstSD: '1-000001', + // tai: '46060-0001', + // upState: 'Active', + // upfN3IP: '192.168.1.161', + // }, + // ], + // ratType: 'EUTRAN', + // }, + // ]; + return data; +} + +/** + * 首页查询SMF在线用户数 + * @param query 查询参数 + * @returns neId + */ +export async function listUENumBySMF(neId: String) { + const result = await request({ + url: `/api/rest/ueManagement/v1/elementType/smf/objectType/ueNum?neId=${neId}`, + method: 'GET', + }); + if (result.code === RESULT_CODE_SUCCESS) { + return Object.assign(result, { + data: result.data.data['ueNum'], + }); + } + + // 模拟数据 + // { "data": { "ueNum": 0 } } + // result.data = 0 + return result; +} diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 485d9614..9a238246 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -368,10 +368,13 @@ export default { imsUeNum: "VoNR/VoLTE", smfUeNum: "Data Sessions", gnbBase: "Online gNodeB", + gnbSumBase: "Total gNodeB", enbBase: "Online eNodeB", + enbSumBase: "Total eNodeB", gnbUeNum:'5G Active Users', enbUeNum:'4G Active Users', baseTitle:'Online Information', + nodeBInfo: 'NodeB Information', }, upfFlow:{ title: "UPF Throughput", @@ -401,6 +404,7 @@ export default { }, userActivity: { title: "User Activity", + imsTitle: "IMS Activity", type: "Type", duration: "Duration", caller: "Caller", @@ -675,7 +679,7 @@ export default { toIpPleace: "Please input the remote backup server IP address", toPort: "Service Port", username: "UserName", - usernamePleace: 'Please enter the service login username', + usernamePleace: 'Please enter the service login username', password: "Password", dir: "Save Dir", dirPleace: 'Please enter the service address target file directory', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 6afa5faa..1cd2327a 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -368,10 +368,13 @@ export default { imsUeNum: "IMS 会话数", smfUeNum: "Data 会话数", gnbBase: "5G 基站数", + gnbSumBase: "5G 基站总数", gnbUeNum:'5G 用户数', enbBase: "4G 基站数", + enbSumBase: "4G 基站总数", enbUeNum:'4G 用户数', baseTitle:'在线信息', + nodeBInfo: '基站信息', }, upfFlow:{ title: "用户面吞吐量", @@ -401,6 +404,7 @@ export default { }, userActivity: { title: "用户活动", + imsTitle: "IMS 活动", type: "类型", duration: "时长", caller: "主叫", @@ -675,7 +679,7 @@ export default { toIpPleace: "请输入远程备份服务器 IP 地址", toPort: "服务端口", username: "登录用户名", - usernamePleace: '请输入服务登录用户名', + usernamePleace: '请输入服务登录用户名', password: "登录密码", dir: "保存目录", dirPleace: '请输入服务地址目标文件目录', diff --git a/src/store/modules/neinfo.ts b/src/store/modules/neinfo.ts new file mode 100644 index 00000000..13bab5ee --- /dev/null +++ b/src/store/modules/neinfo.ts @@ -0,0 +1,93 @@ +import { defineStore } from 'pinia'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; +import { listAllNeInfo } from '@/api/ne/neInfo'; +import { parseDataToOptions } from '@/utils/parse-tree-utils'; +import { getNePerformanceList } from '@/api/perfManage/taskManage'; + +/**网元信息类型 */ +type NeInfo = { + /**网元列表 */ + neList: Record[]; + /**级联options树结构 */ + neCascaderOptions: Record[]; + /**选择器单级父类型 */ + neSelectOtions: Record[]; + /**性能测量数据集 */ + perMeasurementList: Record[]; +}; + +const useNeInfoStore = defineStore('neinfo', { + state: (): NeInfo => ({ + neList: [], + neCascaderOptions: [], + neSelectOtions: [], + perMeasurementList: [], + }), + getters: { + /** + * 获取级联options树结构 + * @param state 内部属性不用传入 + * @returns 级联options + */ + getNeCascaderOptions(state) { + return state.neCascaderOptions; + }, + /** + * 选择器单级父类型 + * @param state 内部属性不用传入 + * @returns 级联options + */ + getNeSelectOtions(state) { + return state.neSelectOtions; + }, + }, + actions: { + // 刷新网元列表 + async fnRefreshNelist() { + this.neList = []; + const res = await this.fnNelist(); + return res; + }, + // 获取网元列表 + async fnNelist() { + // 有数据不请求 + if (this.neList.length > 0) { + return { code: 1, data: this.neList, msg: 'success' }; + } + const res = await listAllNeInfo({ + bandStatus: false, + }); + if (res.code === RESULT_CODE_SUCCESS) { + // 原始列表 + this.neList = JSON.parse(JSON.stringify(res.data)); + + // 转级联数据 + const options = parseDataToOptions( + res.data, + 'neType', + 'neName', + 'neId' + ); + this.neCascaderOptions = options; + + // 转选择器单级父类型 + this.neSelectOtions = options.map(item => item); + } + return res; + }, + // 获取性能测量数据集列表 + async fnNeTaskPerformance() { + // 有数据不请求 + if (this.perMeasurementList.length > 0) { + return { code: 1, data: this.perMeasurementList, msg: 'success' }; + } + const res = await getNePerformanceList(); + if (res.code === RESULT_CODE_SUCCESS) { + this.perMeasurementList = res.data; + } + return res; + }, + }, +}); + +export default useNeInfoStore; diff --git a/src/views/dashboard/overview2/components/AlarnTypeBar/index.vue b/src/views/dashboard/overview2/components/AlarnTypeBar/index.vue index a1d63140..3469a235 100644 --- a/src/views/dashboard/overview2/components/AlarnTypeBar/index.vue +++ b/src/views/dashboard/overview2/components/AlarnTypeBar/index.vue @@ -78,9 +78,9 @@ const alarmTypeType = ref([ /**告警类型Top数据 */ const alarmTypeTypeTop = ref([ - { neType: 'AMF', total: 0 }, - { neType: 'UDM', total: 0 }, - { neType: 'SMF', total: 0 }, + { name: 'AMF', value: 0 }, + { name: 'UDM', value: 0 }, + { name: 'SMF', value: 0 }, ]); // @@ -92,7 +92,7 @@ function initPicture() { if (res0.code === RESULT_CODE_SUCCESS && Array.isArray(res0.data)) { for (const item of res0.data) { let index = 0; - switch (item.severity) { + switch (item.name) { case 'Critical': index = 0; break; @@ -109,7 +109,7 @@ function initPicture() { // index = 4; // break; } - alarmTypeType.value[index].value = Number(item.total); + alarmTypeType.value[index].value = Number(item.value); } } } @@ -119,7 +119,7 @@ function initPicture() { alarmTypeTypeTop.value = alarmTypeTypeTop.value .concat(res1.data) .sort((a: any, b: any) => { - return b.total - a.total; + return b.value - a.value; }) .slice(0, 3); } @@ -129,79 +129,123 @@ function initPicture() { const optionData: EChartsOption = { title: [ { - show: false, - }, - { - text: t('views.dashboard.overview.alarmTypeBar.topTitle'), + text: 'Top3', + left: 'center', + top: '36%', textStyle: { color: '#fff', - fontSize: '14', - fontWeight: 400, + fontSize: 16, + fontWeight: 'bold', }, - top: '50%', - left: '0%', }, ], + grid: [ + { // 主图 + top: '5%', + left: '20%', + right: '10%', + height: '35%' + }, + { // Top3 + top: '50%', + left: '20%', + right: '10%', + height: '30%' + } + ], tooltip: { - trigger: 'item', + + axisPointer: { type: 'shadow' }, formatter: '{b} : {c}', }, legend: { - orient: 'vertical', - right: '2%', - top: '12%', - data: alarmTypeType.value.map((item: any) => item.name), //label数组 - textStyle: { - color: '#A7D6F4', // 设置图例文字颜色 - }, + show: false }, - grid: [ + xAxis: [ { - top: '60%', - left: '15%', - right: '25%', - bottom: '10%', + type: 'value', + gridIndex: 0, + show: false, }, + { + type: 'value', + gridIndex: 1, + show: false, + } + ], + yAxis: [ + { + type: 'category', + gridIndex: 0, + data: alarmTypeType.value.map((item: any) => item.name), + axisLabel: { color: '#fff', fontSize: 14,fontWeight: 'bold' }, + axisLine: { show: false }, + axisTick: { show: false }, + inverse: true + }, + { + type: 'category', + gridIndex: 1, + data: alarmTypeTypeTop.value.map((item: any) => item.name), + axisLabel: { color: '#fff', fontSize: 14,fontWeight: 'bold' }, + axisLine: { show: false }, + axisTick: { show: false }, + inverse: true + } ], series: [ - //饼图: + // 四类型告警横向柱状图 { - type: 'pie', - radius: '35%', - color: ['#f5222d', '#fa8c16', '#fadb14', '#1677ff', '#13c2c2'], + type: 'bar', + xAxisIndex: 0, + yAxisIndex: 0, + barWidth: 18, + itemStyle: { + borderRadius: [0, 8, 8, 0], + color: function (params: any) { + // 渐变色 + const colorArr = [ + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#f5222d' }, + { offset: 1, color: '#fa8c16' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#fa8c16' }, + { offset: 1, color: '#fadb14' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#fadb14' }, + { offset: 1, color: '#1677ff' } + ]), + new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#1677ff' }, + { offset: 1, color: '#00fcff' } + ]) + ]; + return colorArr[params.dataIndex] || colorArr[3]; + } + }, label: { show: true, - position: 'inner', + position: 'right', + color: '#fff', //淡蓝色 + fontWeight: 'bold', + fontSize: 16, formatter: (params: any) => { if (!params.value) return ''; return `${params.value}`; }, }, - labelLine: { - show: false, - }, - center: ['35%', '25%'], - data: alarmTypeType.value, - zlevel: 2, // 设置zlevel为1,使得柱状图在下层显示 - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)', - }, + data: alarmTypeType.value.map((item: any) => item.value), + zlevel: 2 }, - //柱状 + // Top3横向柱状图 { + name: 'Top3', type: 'bar', - barWidth: 12, // 柱子宽度 - barCategoryGap: '30%', // 控制同一系列的柱间距离 - label: { - show: true, - position: 'right', // 位置 - color: '#A7D6F4', //淡蓝色 - fontSize: 14, - distance: 14, // label与柱子距离 - formatter: '{c}', - }, + xAxisIndex: 1, + yAxisIndex: 1, + barWidth: 18, itemStyle: { borderRadius: [0, 20, 20, 0], // 圆角(左上、右上、右下、左下) color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ @@ -210,42 +254,19 @@ function initPicture() { { offset: 1, color: '#2f54eb' }, ]), // 渐变 }, - data: alarmTypeTypeTop.value.map((item: any) => item.total), - }, - ], - // 柱状图设置 - xAxis: [ - { - splitLine: { - show: false, + label: { + show: true, + position: 'right', + color: '#fff', //淡蓝色 + fontWeight: 'bold', + fontSize: 16, + formatter: '{c}' }, - type: 'value', - show: false, - }, - ], - yAxis: [ - { - splitLine: { - show: false, - }, - axisLine: { - //y轴 - show: false, - }, - type: 'category', - axisTick: { - show: false, - }, - inverse: true, - data: alarmTypeTypeTop.value.map((item: any) => item.neType), - axisLabel: { - color: '#A7D6F4', - fontSize: 14, - }, - }, - ], + data: alarmTypeTypeTop.value.map((item: any) => item.value), + zlevel: 1 + } + ] }; - fnDesign(alarmTypeBar.value, optionData); }); } diff --git a/src/views/dashboard/overview2/components/NeResources/index.vue b/src/views/dashboard/overview2/components/NeResources/index.vue index bb4326bd..669214c8 100644 --- a/src/views/dashboard/overview2/components/NeResources/index.vue +++ b/src/views/dashboard/overview2/components/NeResources/index.vue @@ -7,7 +7,7 @@ import { graphNodeClickID, graphNodeState } from '../../hooks/useTopology'; import useI18n from '@/hooks/useI18n'; import { markRaw } from 'vue'; // 引入液体填充图表 -// import 'echarts-liquidfill'; +import 'echarts-liquidfill'; const { t } = useI18n(); diff --git a/src/views/dashboard/overview2/components/Topology/index.vue b/src/views/dashboard/overview2/components/Topology/index.vue index 1b9e04c8..6c4c36fd 100644 --- a/src/views/dashboard/overview2/components/Topology/index.vue +++ b/src/views/dashboard/overview2/components/Topology/index.vue @@ -50,10 +50,10 @@ const graphNodeTooltip = new Tooltip({ >
${t('views.monitor.topology.state')}: ${ - neState.online - ? t('views.monitor.topology.normalcy') - : t('views.monitor.topology.exceptions') - } + neState.online + ? t('views.monitor.topology.normalcy') + : t('views.monitor.topology.exceptions') + }
${t('views.monitor.topology.refreshTime')}: ${neState.refreshTime ?? '--'} @@ -88,10 +88,10 @@ const graphNodeTooltip = new Tooltip({ >
${t('views.monitor.topology.state')}: ${ - neState.online - ? t('views.monitor.topology.normalcy') - : t('views.monitor.topology.exceptions') - } + neState.online + ? t('views.monitor.topology.normalcy') + : t('views.monitor.topology.exceptions') + }
${t('views.monitor.topology.refreshTime')}: ${neState.refreshTime ?? '--'} @@ -102,7 +102,7 @@ const graphNodeTooltip = new Tooltip({ sameTypeNes.forEach((ne: any, index: number) => { // 获取该网元的状态信息 const neStateInfo = neStateMap?.[ne.neId] || - (ne.neId === neState.neId ? neState : {}); + (ne.neId === neState.neId ? neState : {}); content += `
${t('views.monitor.topology.name')}:${ne.neName || id + '_' + ne.neId}
@@ -121,8 +121,8 @@ const graphNodeTooltip = new Tooltip({ ${ neStateInfo.online !== undefined ? (neStateInfo.online - ? t('views.monitor.topology.normalcy') - : t('views.monitor.topology.exceptions')) + ? t('views.monitor.topology.normalcy') + : t('views.monitor.topology.exceptions')) : 'undefined' }
@@ -203,14 +203,14 @@ function handleRanderGraph( * 获取图组数据渲染到画布 * @param reload 是否重载数据 */ - function fnGraphDataLoad(reload: boolean = false) { +function fnGraphDataLoad(reload: boolean = false) { Promise.all([ getGraphData(graphState.group), listAllNeInfo({ bandStatus: false, }), ]) - .then(resArr => { + .then(resArr => { const graphRes = resArr[0]; const neRes = resArr[1]; if ( @@ -265,7 +265,7 @@ function handleRanderGraph( if (notNeNodes.includes(nodeID)) { return true; } - //(neTypeMap.get(nodeID),nodeID,node.neState) + //(neTypeMap.get(nodeID),nodeID,node.neState) // 处理网元节点 if (neTypeMap.has(nodeID)) { // all NeInfo diff --git a/src/views/dashboard/overview2/index.vue b/src/views/dashboard/overview2/index.vue index f8ef58bf..e18d64d8 100644 --- a/src/views/dashboard/overview2/index.vue +++ b/src/views/dashboard/overview2/index.vue @@ -10,25 +10,33 @@ import UserActivity from './components/UserActivity/index.vue'; import IMSActivity from './components/IMSActivity/index.vue'; import AlarnTypeBar from './components/AlarnTypeBar/index.vue'; import UPFFlow from './components/UPFFlow/index.vue'; -import { listIMSSessionNum } from '@/api/neData/ims'; import { listUDMSub } from '@/api/neData/udm_sub'; -import { listAMFNblist } from '@/api/neData/amf'; -import { listMMENblist } from '@/api/neData/mme'; -import { listSMFSubNum } from '@/api/neData/smf'; -import { graphNodeClickID, graphState, notNeNodes } from './hooks/useTopology'; +import { listUENumBySMF } from '@/api/neUser/smf'; +import { listUENumByIMS } from '@/api/neUser/ims'; +import { listBase5G } from '@/api/neUser/base5G'; +import { + graphNodeClickID, + graphState, + notNeNodes, + graphNodeStateNum, + neStateRequestMap, +} from './hooks/useTopology'; import { upfTotalFlow, upfTFActive } from './hooks/useUPFTotalFlow'; import { useFullscreen } from '@vueuse/core'; import useWS from './hooks/useWS'; import useAppStore from '@/store/modules/app'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { useRouter } from 'vue-router'; -import useNeListStore from '@/store/modules/ne_list'; +import useNeInfoStore from '@/store/modules/neinfo'; import { message } from 'ant-design-vue'; import { upfWhoId } from './hooks/useWS'; -import { listAMFNbStatelist } from '@/api/neData/amf'; +import { + listAMFNbStatelist, +} from '@/api/neData/amf'; import { listMMENbStatelist } from '@/api/neData/mme'; -const neInfoStore = useNeListStore(); + +const neInfoStore = useNeInfoStore(); const router = useRouter(); const appStore = useAppStore(); const { t } = useI18n(); @@ -66,6 +74,7 @@ let skimState: SkimStateType = reactive({ enbUeNum: 0, gNbSumNum: 0, eNbSumNum: 0, + }); /**网元参数 */ @@ -88,10 +97,13 @@ function fnGetNeState() { for (const node of graphState.data.nodes) { if (notNeNodes.includes(node.id)) continue; + const neInfoList = node.neInfoList || []; if (neInfoList.length === 0) continue; + for (const neInfo of neInfoList) { + if (!neInfo.neType || !neInfo.neId) continue; wsSend({ @@ -108,6 +120,7 @@ function fnGetNeState() { /**获取概览信息 */ async function fnGetSkim() { + let tempGnbSumNum = 0; let tempEnbSumNum = 0; @@ -122,10 +135,18 @@ async function fnGetSkim() { // (skimState.udmSubNum += res.total), // }, // ], + [ + 'UDM', + { + request: (neId: string) => listUDMSub({ neId: neId, pageNum: 1, pageSize: 1 }), + process: (res: any) => + res.code === RESULT_CODE_SUCCESS && (skimState.udmSubNum = res.total), + }, + ], [ 'SMF', { - request: (neId: string) => listSMFSubNum(neId), + request: (neId: string) => listUENumBySMF(neId), process: (res: any) => res.code === RESULT_CODE_SUCCESS && (skimState.smfUeNum += res.data), }, @@ -133,7 +154,7 @@ async function fnGetSkim() { [ 'IMS', { - request: (neId: string) => listIMSSessionNum(neId), + request: (neId: string) => listUENumByIMS(neId), process: (res: any) => res.code === RESULT_CODE_SUCCESS && (skimState.imsUeNum += res.data), }, @@ -141,7 +162,7 @@ async function fnGetSkim() { [ 'AMF', { - request: (neId: string) => listAMFNblist({ neId }), + request: (neId: string) => listBase5G({ neType: 'AMF', neId }), process: async (res: any, neId: any) => { if (res.code === RESULT_CODE_SUCCESS) { skimState.gnbNum += res.total; @@ -150,12 +171,10 @@ async function fnGetSkim() { 0 ); const amfNbRes = await listAMFNbStatelist({ neId }); - if ( - amfNbRes.code === RESULT_CODE_SUCCESS && - Array.isArray(amfNbRes.data) - ) { + if (amfNbRes.code === RESULT_CODE_SUCCESS && Array.isArray(amfNbRes.data)) { // skimState.gNbSumNum += amfNbRes.data.length; tempGnbSumNum += amfNbRes.data.length; + } } }, @@ -164,7 +183,7 @@ async function fnGetSkim() { [ 'MME', { - request: (neId: string) => listMMENblist({ neId }), + request: (neId: string) => listBase5G({ neType: 'MME', neId }), process: async (res: any, neId: any) => { if (res.code === RESULT_CODE_SUCCESS) { skimState.enbNum += res.total; @@ -174,13 +193,11 @@ async function fnGetSkim() { ); const mmeNbRes = await listMMENbStatelist({ neId }); - if ( - mmeNbRes.code === RESULT_CODE_SUCCESS && - Array.isArray(mmeNbRes.data) - ) { + if (mmeNbRes.code === RESULT_CODE_SUCCESS && Array.isArray(mmeNbRes.data)) { // skimState.eNbSumNum += mmeNbRes.data.length; tempEnbSumNum += mmeNbRes.data.length; } + } }, }, @@ -194,10 +211,10 @@ async function fnGetSkim() { const handler = neHandlers.get(child.neType); return handler ? { - promise: handler.request(child.neId), - process: handler.process, - neId: child.neId, // 这里加上neId - } + promise: handler.request(child.neId), + process: handler.process, + neId: child.neId, // 这里加上neId + } : null; }) .filter(Boolean) || [] @@ -207,7 +224,7 @@ async function fnGetSkim() { // 重置 Object.assign(skimState, { - // udmSubNum: 0, + udmSubNum: 0, smfUeNum: 0, imsUeNum: 0, gnbNum: 0, @@ -231,13 +248,31 @@ async function fnGetSkim() { skimState.eNbSumNum = tempEnbSumNum; // UDM - listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => { - if (res.code === RESULT_CODE_SUCCESS) { - skimState.udmSubNum = res.total; - } - }); + // UDM - 使用await确保同步处理 + // try { + // const udmRes = await listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }); + // if (udmRes.code === RESULT_CODE_SUCCESS) { + // skimState.udmSubNum = udmRes.total; + // } else { + // skimState.udmSubNum = 0; + // } + // } catch (error) { + // skimState.udmSubNum = 0; + // } + // UDM + // listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => { + // if (res.code === RESULT_CODE_SUCCESS) { + // skimState.udmSubNum = res.total; + // } else { + // skimState.udmSubNum = 0; + // } + // }).catch(() => { + // skimState.udmSubNum = 0; + // }); } + + /**初始数据函数 */ function loadData() { fnGetNeState(); // 获取网元状态 @@ -306,13 +341,22 @@ let udmOtions = ref[]>([]); let onlineOtions = ref[]>([]); /**用户数量-选择UDM */ -function fnSelectUDM(e: any) { +async function fnSelectUDM(e: any) { udmNeId.value = e.key; - listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => { + try { + const res = await listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }); + // listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => { if (res.code === RESULT_CODE_SUCCESS) { skimState.udmSubNum = res.total; + }else{ + skimState.udmSubNum = 0; } - }); + // }).catch(() => { + // skimState.udmSubNum = 0; + // }); + } catch (error) { + skimState.udmSubNum = 0; + } } /**资源控制-选择NE */ function fnSelectNeRe(e: any) { @@ -351,26 +395,8 @@ onMounted(() => { // UDM let arr1: Record[] = []; res.data.forEach((v: any) => { - if ( - v.status && - [ - 'UDM', - 'UPF', - 'AUSF', - 'PCF', - 'SMF', - 'AMF', - 'OMC', - 'SMSC', - 'IMS', - 'MME', - ].includes(v.neType) - ) { - onlineArr.push({ - value: v.neType + '_' + v.neId, - label: v.neName, - rmUid: v.rmUid, - }); + if (v.status && ['UDM', 'UPF', 'AUSF', 'PCF', 'SMF', 'AMF', 'OMC', 'SMSC', 'IMS', 'MME'].includes(v.neType)) { + onlineArr.push({ value: v.neType + '_' + v.neId, label: v.neName, rmUid: v.rmUid }); } if (v.neType === 'UDM') { arr1.push({ value: v.neId, label: v.neName, rmUid: v.rmUid }); @@ -378,9 +404,17 @@ onMounted(() => { }); udmOtions.value = arr1; onlineOtions.value = onlineArr; + // if (arr1.length > 0) { + // fnSelectUDM({ key: arr1[0].value }); + // } + // 确保设置正确的udmNeId if (arr1.length > 0) { - fnSelectUDM({ key: arr1[0].value }); + udmNeId.value = arr1[0].value; } + // 移除单独的fnSelectUDM调用,让fnGetSkim统一处理 + // if (arr1.length > 0) { + // fnSelectUDM({ key: arr1[0].value }); + // } if (onlineArr.length > 0) { fnSelectNeRe({ key: onlineArr[0].value }); @@ -427,11 +461,7 @@ onBeforeUnmount(() => {