From 729d5518e83d953c1ba743fe43073227379a9945 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Sat, 23 Nov 2024 15:51:31 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E4=BF=AE=E5=A4=8D=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/dashboard/imsCDR/index.vue | 40 +- .../views/dashboard/mmeUE/index.vue | 67 +-- .../components/AlarnTypeBar/index.vue | 284 ++++++++++ .../overview/components/NeResources/index.vue | 368 +++++++++++++ .../overview/components/Topology/index.vue | 267 ++++++++++ .../overview/components/UPFFlow/index.vue | 290 +++++++++++ .../components/UserActivity/index.vue | 370 +++++++++++++ .../views/dashboard/overview/css/index.css | 277 ++++++++++ .../dashboard/overview/hooks/useTopology.ts | 172 ++++++ .../overview/hooks/useUPFTotalFlow.ts | 115 ++++ .../overview/hooks/useUserActivity.ts | 148 ++++++ .../views/dashboard/overview/hooks/useWS.ts | 204 ++++++++ .../dashboard/overview/images/border.png | Bin 0 -> 2418 bytes .../views/dashboard/overview/images/brand.png | Bin 0 -> 14403 bytes .../views/dashboard/overview/images/line.png | Bin 0 -> 237 bytes .../views/dashboard/overview/images/rect.png | Bin 0 -> 1089 bytes .../views/dashboard/overview/index.vue | 493 ++++++++++++++++++ .../views/dashboard/smfCDR/index.vue | 43 +- .../views/dashboard/smscCDR/index.vue | 45 +- src/views/dashboard/imsCDR/index.vue | 40 +- src/views/dashboard/mmeUE/index.vue | 67 +-- src/views/dashboard/overview/index.vue | 6 +- src/views/dashboard/smfCDR/index.vue | 43 +- src/views/dashboard/smscCDR/index.vue | 45 +- 24 files changed, 3038 insertions(+), 346 deletions(-) create mode 100644 practical_training/views/dashboard/overview/components/AlarnTypeBar/index.vue create mode 100644 practical_training/views/dashboard/overview/components/NeResources/index.vue create mode 100644 practical_training/views/dashboard/overview/components/Topology/index.vue create mode 100644 practical_training/views/dashboard/overview/components/UPFFlow/index.vue create mode 100644 practical_training/views/dashboard/overview/components/UserActivity/index.vue create mode 100644 practical_training/views/dashboard/overview/css/index.css create mode 100644 practical_training/views/dashboard/overview/hooks/useTopology.ts create mode 100644 practical_training/views/dashboard/overview/hooks/useUPFTotalFlow.ts create mode 100644 practical_training/views/dashboard/overview/hooks/useUserActivity.ts create mode 100644 practical_training/views/dashboard/overview/hooks/useWS.ts create mode 100644 practical_training/views/dashboard/overview/images/border.png create mode 100644 practical_training/views/dashboard/overview/images/brand.png create mode 100644 practical_training/views/dashboard/overview/images/line.png create mode 100644 practical_training/views/dashboard/overview/images/rect.png create mode 100644 practical_training/views/dashboard/overview/index.vue diff --git a/practical_training/views/dashboard/imsCDR/index.vue b/practical_training/views/dashboard/imsCDR/index.vue index 3405700a..be212ab3 100644 --- a/practical_training/views/dashboard/imsCDR/index.vue +++ b/practical_training/views/dashboard/imsCDR/index.vue @@ -11,7 +11,6 @@ import { RESULT_CODE_SUCCESS, } from '@/constants/result-constants'; import useDictStore from '@/store/modules/dict'; -import useNeInfoStore from '@/store/modules/neinfo'; import { delIMSDataCDR, exportIMSDataCDR, @@ -38,9 +37,6 @@ let dict: { cdrCallType: [], }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -468,31 +464,6 @@ onMounted(() => { if (resArr[1].status === 'fulfilled') { dict.cdrCallType = resArr[1].value; } - } - ); - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'IMS') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); - } }) .finally(() => { // 获取列表数据 @@ -517,15 +488,6 @@ onBeforeUnmount(() => { - - - - - { > - + diff --git a/practical_training/views/dashboard/mmeUE/index.vue b/practical_training/views/dashboard/mmeUE/index.vue index b6f4f842..b95d71ab 100644 --- a/practical_training/views/dashboard/mmeUE/index.vue +++ b/practical_training/views/dashboard/mmeUE/index.vue @@ -11,7 +11,6 @@ import { RESULT_CODE_SUCCESS, } from '@/constants/result-constants'; import useDictStore from '@/store/modules/dict'; -import useNeInfoStore from '@/store/modules/neinfo'; import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme'; import { parseDateToStr } from '@/utils/date-utils'; import { OptionsType, WS } from '@/plugins/ws-websocket'; @@ -23,9 +22,6 @@ const { getDict } = useDictStore(); const ws = new WS(); const queue = new PQueue({ concurrency: 1, autoStart: true }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**字典数据 */ let dict: { /**UE 事件认证代码类型 */ @@ -411,47 +407,23 @@ onMounted(() => { getDict('ue_auth_code'), getDict('ue_event_type'), getDict('ue_event_cm_state'), - ]).then(resArr => { - if (resArr[0].status === 'fulfilled') { - dict.ueAauthCode = resArr[0].value; - } - if (resArr[1].status === 'fulfilled') { - const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1])); - dict.ueEventType = ueEventType.map(item => { - if (item.value === 'cm-state') { - item.label = item.label.replace('CM', 'ECM'); - } - return item; - }); - } - if (resArr[2].status === 'fulfilled') { - dict.ueEventCmState = resArr[2].value; - } - }); - - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'MME') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; + ]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.ueAauthCode = resArr[0].value; + } + if (resArr[1].status === 'fulfilled') { + const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1])); + dict.ueEventType = ueEventType.map(item => { + if (item.value === 'cm-state') { + item.label = item.label.replace('CM', 'ECM'); } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, + return item; }); } + if (resArr[2].status === 'fulfilled') { + dict.ueEventCmState = resArr[2].value; + } }) .finally(() => { // 获取列表数据 @@ -476,15 +448,6 @@ onBeforeUnmount(() => { - - - - - { > - + +import * as echarts from 'echarts/core'; +import { + TitleComponent, + TitleComponentOption, + TooltipComponent, + TooltipComponentOption, + GridComponent, + GridComponentOption, + LegendComponent, + LegendComponentOption, +} from 'echarts/components'; +import { + PieChart, + PieSeriesOption, + BarChart, + BarSeriesOption, +} from 'echarts/charts'; +import { LabelLayout } from 'echarts/features'; +import { CanvasRenderer } from 'echarts/renderers'; + +import { markRaw, onMounted, ref } from 'vue'; +import { origGet, top3Sel } from '@/api/faultManage/actAlarm'; +import useI18n from '@/hooks/useI18n'; +import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; + +const { t } = useI18n(); + +echarts.use([ + TitleComponent, + TooltipComponent, + GridComponent, + LegendComponent, + PieChart, + BarChart, + CanvasRenderer, + LabelLayout, +]); + +type EChartsOption = echarts.ComposeOption< + | TitleComponentOption + | TooltipComponentOption + | GridComponentOption + | LegendComponentOption + | PieSeriesOption + | BarSeriesOption +>; + +/**图DOM节点实例对象 */ +const alarmTypeBar = ref(undefined); + +/**图实例对象 */ +const alarmTypeBarChart = ref(null); + +/**告警类型数据 */ +const alarmTypeType = ref([ + { + value: 0, + name: t('views.index.Critical'), + }, + { + value: 0, + name: t('views.index.Major'), + }, + { + value: 0, + name: t('views.index.Minor'), + }, + { + value: 0, + name: t('views.index.Warning'), + }, + // { + // value: 0, + // name: t('views.index.Event'), + // }, +]); + +/**告警类型Top数据 */ +const alarmTypeTypeTop = ref([ + { name: 'AMF', value: 0 }, + { name: 'UDM', value: 0 }, + { name: 'SMF', value: 0 }, +]); + +// +function initPicture() { + Promise.allSettled([origGet(), top3Sel()]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + const res0 = resArr[0].value; + if (res0.code === RESULT_CODE_SUCCESS && Array.isArray(res0.data)) { + for (const item of res0.data) { + let index = 0; + switch (item.name) { + case 'Critical': + index = 0; + break; + case 'Major': + index = 1; + break; + case 'Minor': + index = 2; + break; + case 'Warning': + index = 3; + break; + // case 'Event': + // index = 4; + // break; + } + alarmTypeType.value[index].value = Number(item.value); + } + } + } + if (resArr[1].status === 'fulfilled') { + const res1 = resArr[1].value; + if (res1.code === RESULT_CODE_SUCCESS && Array.isArray(res1.data)) { + alarmTypeTypeTop.value = alarmTypeTypeTop.value + .concat(res1.data) + .sort((a: any, b: any) => { + return b.value - a.value; + }) + .slice(0, 3); + } + } + }) + .then(() => { + const optionData: EChartsOption = { + title: [ + { + show: false, + }, + { + text: t('views.dashboard.overview.alarmTypeBar.topTitle'), + textStyle: { + color: '#fff', + fontSize: '14', + fontWeight: 400, + }, + top: '50%', + left: '0%', + }, + ], + tooltip: { + trigger: 'item', + formatter: '{b} : {c}', + }, + legend: { + orient: 'vertical', + right: '2%', + top: '12%', + data: alarmTypeType.value.map((item: any) => item.name), //label数组 + textStyle: { + color: '#A7D6F4', // 设置图例文字颜色 + }, + }, + grid: [ + { + top: '60%', + left: '15%', + right: '25%', + bottom: '10%', + }, + ], + series: [ + //饼图: + { + type: 'pie', + radius: '35%', + color: ['#f5222d', '#fa8c16', '#fadb14', '#1677ff', '#13c2c2'], + label: { + show: true, + position: 'inner', + 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)', + }, + }, + //柱状 + { + type: 'bar', + barWidth: 12, // 柱子宽度 + barCategoryGap: '30%', // 控制同一系列的柱间距离 + label: { + show: true, + position: 'right', // 位置 + color: '#A7D6F4', //淡蓝色 + fontSize: 14, + distance: 14, // label与柱子距离 + formatter: '{c}', + }, + itemStyle: { + borderRadius: [0, 20, 20, 0], // 圆角(左上、右上、右下、左下) + color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ + { offset: 0, color: '#f0f5ff' }, + { offset: 0.5, color: '#adc6ff' }, + { offset: 1, color: '#2f54eb' }, + ]), // 渐变 + }, + data: alarmTypeTypeTop.value, + }, + ], + // 柱状图设置 + xAxis: [ + { + splitLine: { + show: false, + }, + 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.name), + axisLabel: { + color: '#A7D6F4', + fontSize: 14, + }, + }, + ], + }; + + fnDesign(alarmTypeBar.value, optionData); + }); +} + +function fnDesign(container: HTMLElement | undefined, option: any) { + if (!container) return; + + alarmTypeBarChart.value = markRaw(echarts.init(container, 'light')); + option && alarmTypeBarChart.value.setOption(option); + + // 创建 ResizeObserver 实例 + var observer = new ResizeObserver(entries => { + if (alarmTypeBarChart.value) { + alarmTypeBarChart.value.resize(); + } + }); + // 监听元素大小变化 + observer.observe(container); +} + +onMounted(() => { + initPicture(); +}); + + + + + diff --git a/practical_training/views/dashboard/overview/components/NeResources/index.vue b/practical_training/views/dashboard/overview/components/NeResources/index.vue new file mode 100644 index 00000000..a50a6a20 --- /dev/null +++ b/practical_training/views/dashboard/overview/components/NeResources/index.vue @@ -0,0 +1,368 @@ + + + + + diff --git a/practical_training/views/dashboard/overview/components/Topology/index.vue b/practical_training/views/dashboard/overview/components/Topology/index.vue new file mode 100644 index 00000000..29fcde82 --- /dev/null +++ b/practical_training/views/dashboard/overview/components/Topology/index.vue @@ -0,0 +1,267 @@ + + + + + diff --git a/practical_training/views/dashboard/overview/components/UPFFlow/index.vue b/practical_training/views/dashboard/overview/components/UPFFlow/index.vue new file mode 100644 index 00000000..12694af7 --- /dev/null +++ b/practical_training/views/dashboard/overview/components/UPFFlow/index.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/practical_training/views/dashboard/overview/components/UserActivity/index.vue b/practical_training/views/dashboard/overview/components/UserActivity/index.vue new file mode 100644 index 00000000..ae3e07a5 --- /dev/null +++ b/practical_training/views/dashboard/overview/components/UserActivity/index.vue @@ -0,0 +1,370 @@ + + + + + diff --git a/practical_training/views/dashboard/overview/css/index.css b/practical_training/views/dashboard/overview/css/index.css new file mode 100644 index 00000000..9b053c7c --- /dev/null +++ b/practical_training/views/dashboard/overview/css/index.css @@ -0,0 +1,277 @@ +.viewport { + /* 限定大小 */ + min-width: 1024px; + max-width: 1920px; + min-height: 780px; + margin: 0 auto; + position: relative; + display: flex; + padding: 5rem 0.833rem 0; + line-height: 1.15; + background-color: #101129; + height: 100vh; + margin-bottom: -20px; +} + +.column { + flex: 3; + position: relative; +} + +/* 边框 */ +.panel { + box-sizing: border-box; + border: 2px solid red; + border-image: url(../images/border.png) 51 38 21 132; + border-width: 2.125rem 1.583rem 0.875rem 5.5rem; + position: relative; + margin-bottom: 0.833rem; +} +.panel .inner { + /* 装内容 */ + /* height: 60px; */ + position: absolute; + top: -2.125rem; + right: -1.583rem; + bottom: -0.875rem; + left: -5.5rem; + padding: 1rem 1.5rem; +} +.panel h3 { + font-size: 0.833rem; + color: #fff; +} + +/* 总览标题 */ +.brand { + background-image: url(../images/brand.png); + background-repeat: no-repeat; + background-size: cover; + background-position: center center; + position: absolute; + top: 0.833rem; + left: 0; + right: 0; + width: 100%; + height: 5rem; + display: flex; + flex-direction: column; + align-items: center; + cursor: pointer; +} +.brand .brand-title { + color: #ffffff; + font-size: 1.4rem; + font-weight: 600; + padding-top: 1rem; + padding-bottom: 0.5rem; +} +.brand .brand-desc { + color: #d9d9d9; + font-size: 0.9rem; +} + +/* 实时流量 */ +.upfFlow { + /* min-height: 16rem; */ + height: 40%; +} +.upfFlow .inner .chart { + width: 100%; + height: 100%; + margin-top: 1rem; +} + +/* 网络拓扑 */ +.topology { + /* min-height: 27.8rem; */ + height: 56.4%; +} +.topology .inner h3 { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: baseline; +} +.topology .inner h3 .normal { + color: #52c41a; + font-size: 1.1rem; + margin-right: 8px; +} +.topology .inner h3 .abnormal { + color: #f5222d; + font-size: 1.1rem; +} +.topology .inner .chart { + width: 100%; + height: 100%; + margin-top: 1rem; +} + +/* 概览区域 */ +.skim { + /* min-height: 7.78rem; */ + height: 14.4%; +} +.skim .inner .data { + display: flex; + flex-direction: row; + align-items: center; + height: 90%; +} +.skim .inner .data .item { + display: flex; + flex-direction: column; + align-items: baseline; + width: 33%; +} +.skim .inner .data .item div { + font-size: 1.467rem; + color: #fff; + margin-bottom: 0; + display: flex; + align-items: baseline; + line-height: 2rem; +} +.skim .inner .data .item span { + color: #4c9bfd; + font-size: 0.833rem; + width: 100%; + position: relative; + line-height: 2rem; + white-space: nowrap; + text-align: start; + text-overflow: ellipsis; + overflow: hidden; +} +.skim .inner .data .item span::before { + content: ' '; + position: absolute; + top: 2px; + left: 0; + right: 0; + bottom: 0; + z-index: 0; + background-image: linear-gradient(to right, #fff, #fff0); + height: 1px; + border-radius: 4px; +} + +/* 概览区域 衍生基站信息 */ +.skim.base { + height: 12%; +} + +.skim.base .inner .data { + display: flex; + flex-direction: row; + align-items: center; + height: 75%; +} +.skim.base .inner .data .item { + display: flex; + flex-direction: column; + align-items: baseline; + width: 50%; +} + +/* 用户行为 */ +.userActivity { + /* min-height: 35.8rem; */ + height: 54.6%; +} +.userActivity .inner .chart { + width: 100%; + height: 100%; + margin-top: 1rem; +} + +/* 流量统计 */ +.upfFlowTotal { + /* min-height: 7.5rem; */ + height: 14.4%; +} +.upfFlowTotal .inner h3 { + display: flex; + justify-content: space-between; +} +.upfFlowTotal .inner h3 .filter { + display: flex; +} +.upfFlowTotal .inner h3 .filter span { + display: block; + height: 0.75rem; + line-height: 1; + padding: 0 0.75rem; + color: #1950c4; + font-size: 0.75rem; + border-right: 0.083rem solid #00f2f1; + cursor: pointer; +} +.upfFlowTotal .inner h3 .filter span:first-child { + padding-left: 0; +} +.upfFlowTotal .inner h3 .filter span:last-child { + border-right: none; +} +.upfFlowTotal .inner h3 .filter span.active { + color: #fff; + font-size: 0.833rem; +} +.upfFlowTotal .inner .chart { + width: 100%; + height: 100%; + margin-top: 0.1rem; +} +.upfFlowTotal .inner .chart .data { + display: flex; + flex-direction: column; + justify-content: space-around; + height: 60%; +} +.upfFlowTotal .inner .chart .data .item { + display: flex; + justify-content: space-between; + align-items: baseline; +} +.upfFlowTotal .inner .chart .data .item h4 { + font-size: 1.467rem; + color: #fff; + margin-bottom: 0; +} +.upfFlowTotal .inner .chart .data .item span { + color: #4c9bfd; + font-size: 0.867rem; +} + +/* 资源情况 */ +.resources { + /* min-height: 18rem; */ + height: 34.4%; +} +.resources .inner .chart { + width: 100%; + height: 100%; + margin-top: 1rem; +} + +/* 告警统计 */ +.alarmType { + /* min-height: 25rem; */ + height: 46%; +} +.alarmType .inner .chart { + width: 100%; + height: 100%; + margin-top: 1rem; +} + +/* 跳转鼠标悬浮 */ +.toRouter:hover { + cursor: pointer; + color: #fff !important; +} +.toRouter:hover > *, +.toRouter:hover > * > * { + color: #fff !important; +} diff --git a/practical_training/views/dashboard/overview/hooks/useTopology.ts b/practical_training/views/dashboard/overview/hooks/useTopology.ts new file mode 100644 index 00000000..64c01c68 --- /dev/null +++ b/practical_training/views/dashboard/overview/hooks/useTopology.ts @@ -0,0 +1,172 @@ +import { parseDateToStr } from '@/utils/date-utils'; +import { computed, reactive, ref } from 'vue'; + +/**非网元元素 */ +export const notNeNodes = [ + '5GC', + 'DN', + 'UE', + 'Base', + 'lan', + 'lan1', + 'lan2', + 'lan3', + 'lan4', + 'lan5', + 'lan6', + 'lan7', + 'LAN', + 'NR', +]; + +/**图状态 */ +export const graphState = reactive>({ + /**当前图组名 */ + group: '5GC System Architecture', + /**图数据 */ + data: { + combos: [], + edges: [], + nodes: [], + }, +}); + +/**图实例对象 */ +export const graphG6 = ref(null); + +/**图点击选择 */ +export const graphNodeClickID = ref('UPF'); + +/**图节点网元信息状态 */ +export const graphNodeState = computed(() => + graphState.data.nodes.map((item: any) => ({ + id: item.id, + label: item.label, + neInfo: item.neInfo, + neState: item.neState, + })) +); + +/**图节点网元状态数量 */ +export const graphNodeStateNum = computed(() => { + let normal = 0; + let abnormal = 0; + for (const item of graphState.data.nodes) { + const neId = item.neState.neId; + if (neId) { + if (item.neState.online) { + normal += 1; + } else { + abnormal += 1; + } + } + } + return [normal, abnormal]; +}); + +/**网元状态请求标记 */ +export const neStateRequestMap = ref>(new Map()); + +/**neStateParse 网元状态 数据解析 */ +export function neStateParse(neType: string, data: Record) { + const { combos, edges, nodes } = graphState.data; + const node = nodes.find((item: Record) => item.id === neType); + + // 更新网元状态 + const newNeState = Object.assign(node.neState, data, { + refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'), + online: !!data.cpu, + }); + + // 通过 ID 查询节点实例 + const item = graphG6.value.findById(node.id); + if (item) { + const stateColor = newNeState.online ? '#52c41a' : '#f5222d'; // 状态颜色 + // 图片类型不能填充 + if (node.type.startsWith('image')) { + // 更新节点 + if (node.label !== newNeState.neName) { + graphG6.value.updateItem(item, { + label: newNeState.neName, + }); + } + // 设置状态 + graphG6.value.setItemState(item, 'top-right-dot', stateColor); + } else { + // 更新节点 + graphG6.value.updateItem(item, { + label: newNeState.neName, + // neState: newNeState, + style: { + fill: stateColor, // 填充色 + stroke: stateColor, // 填充色 + }, + // labelCfg: { + // style: { + // fill: '#ffffff', // 标签文本色 + // }, + // }, + }); + // 设置状态 + graphG6.value.setItemState(item, 'stroke', newNeState.online); + } + } + + // 设置边状态 + for (const edge of edges) { + const edgeSource: string = edge.source; + const edgeTarget: string = edge.target; + const neS = nodes.find((n: any) => n.id === edgeSource); + const neT = nodes.find((n: any) => n.id === edgeTarget); + // console.log(neS, edgeSource, neT, edgeTarget); + + if (neS && neT) { + // 通过 ID 查询节点实例 + // const item = graphG6.value.findById(edge.id); + // console.log( + // `${edgeSource} - ${edgeTarget}`, + // neS.neState.online && neT.neState.online + // ); + // const stateColor = neS.neState.online && neT.neState.online ? '#000000' : '#ff4d4f'; // 状态颜色 + // 更新边 + // graphG6.value.updateItem(item, { + // label: `${edgeSource} - ${edgeTarget}`, + // style: { + // stroke: stateColor, // 填充色 + // }, + // labelCfg: { + // style: { + // fill: '#ffffff', // 标签文本色 + // }, + // }, + // }); + // 设置状态 + graphG6.value.setItemState( + edge.id, + 'circle-move', + neS.neState.online && neT.neState.online + ); + } + if (neS && notNeNodes.includes(edgeTarget)) { + graphG6.value.setItemState(edge.id, 'line-dash', neS.neState.online); + } + if (neT && notNeNodes.includes(edgeSource)) { + graphG6.value.setItemState(edge.id, 'line-dash', neT.neState.online); + } + } + + // 请求标记复位 + neStateRequestMap.value.set(neType, false); +} + +/**属性复位 */ +export function topologyReset() { + graphState.data = { + combos: [], + edges: [], + nodes: [], + }; + graphG6.value = null; + graphNodeClickID.value = 'UPF'; + neStateRequestMap.value = new Map(); +} diff --git a/practical_training/views/dashboard/overview/hooks/useUPFTotalFlow.ts b/practical_training/views/dashboard/overview/hooks/useUPFTotalFlow.ts new file mode 100644 index 00000000..29aebbe9 --- /dev/null +++ b/practical_training/views/dashboard/overview/hooks/useUPFTotalFlow.ts @@ -0,0 +1,115 @@ +import { parseDateToStr } from '@/utils/date-utils'; +import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils'; +import { ref } from 'vue'; + +type FDType = { + /**时间 */ + lineXTime: string[]; + /**上行 N3 */ + lineYUp: number[]; + /**下行 N6 */ + lineYDown: number[]; + /**容量 */ + cap: number; +}; + +/**UPF-流量数据 */ +export const upfFlowData = ref({ + lineXTime: [], + lineYUp: [], + lineYDown: [], + cap: 0, +}); + +/**UPF-流量数据 数据解析 */ +export function upfFlowParse(data: Record) { + upfFlowData.value.lineXTime.push(parseDateToStr(+data['timeGroup'])); + const upN3 = parseSizeFromKbs(+data['UPF.03'], 5); + upfFlowData.value.lineYUp.push(upN3[0]); + const downN6 = parseSizeFromKbs(+data['UPF.06'], 5); + upfFlowData.value.lineYDown.push(downN6[0]); + upfFlowData.value.cap += 1; + // 超过 25 弹出 + if (upfFlowData.value.cap > 25) { + upfFlowData.value.lineXTime.shift(); + upfFlowData.value.lineYUp.shift(); + upfFlowData.value.lineYDown.shift(); + upfFlowData.value.cap -= 1; + } + // UPF-总流量数0天 当天24小时 + upfTFParse('0', { + up: upfTotalFlow.value['0'].up + +data['UPF.03'], + down: upfTotalFlow.value['0'].down + +data['UPF.06'], + }); +} + +type TFType = { + /**上行 N3 */ + up: number; + upFrom: string; + /**下行 N6 */ + down: number; + downFrom: string; + /**请求标记 */ + requestFlag: boolean; +}; + +/**UPF-总流量数 */ +export const upfTotalFlow = ref>({ + '0': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, + '7': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, + '30': { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }, +}); + +/**UPF-总流量数 数据解析 */ +export function upfTFParse(day: string, data: Record) { + let { up, down } = data; + upfTotalFlow.value[day] = { + up: up, + upFrom: parseSizeFromBits(up), + down: down, + downFrom: parseSizeFromBits(down), + requestFlag: false, + }; +} + +/**UPF-总流量数 选中 */ +export const upfTFActive = ref('0'); + +/**属性复位 */ +export function upfTotalFlowReset() { + upfFlowData.value = { + lineXTime: [], + lineYUp: [], + lineYDown: [], + cap: 0, + }; + for (const key of Object.keys(upfTotalFlow.value)) { + upfTotalFlow.value[key] = { + up: 0, + upFrom: '0 B', + down: 0, + downFrom: '0 B', + requestFlag: false, + }; + } + upfTFActive.value = '0'; +} diff --git a/practical_training/views/dashboard/overview/hooks/useUserActivity.ts b/practical_training/views/dashboard/overview/hooks/useUserActivity.ts new file mode 100644 index 00000000..5e307552 --- /dev/null +++ b/practical_training/views/dashboard/overview/hooks/useUserActivity.ts @@ -0,0 +1,148 @@ +import { ref } from 'vue'; + +/**ueEventAMFParse UE会话事件AMF 数据解析 */ +function ueEventAMFParse( + item: Record +): false | Record { + let evData: Record = item.eventJSON; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + } + } + + return { + eType: 'amf_ue', + eId: `amf_ue_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + type: item.eventType, + data: evData, + }; +} + +/**ueEventMMEParse UE会话事件MME 数据解析 */ +function ueEventMMEParse( + item: Record +): false | Record { + let evData: Record = item.eventJSON; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + } + } + + return { + eType: 'mme_ue', + eId: `mme_ue_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + type: item.eventType, + data: evData, + }; +} + +/**cdrEventIMSParse CDR会话事件IMS 数据解析 */ +function cdrEventIMSParse( + item: Record +): false | Record { + let evData: Record = item.cdrJSON || item.CDR; + if (typeof evData === 'string') { + try { + evData = JSON.parse(evData); + } catch (error) { + console.error(error); + return false; + } + } + + // 指定显示CDR类型MOC/MTSM + if (!['MOC', 'MTSM'].includes(evData.recordType)) { + return false; + } + + return { + eType: 'ims_cdr', + eId: `ims_cdr_${item.id}_${Date.now()}`, + eTime: +item.timestamp, + id: item.id, + data: evData, + }; +} + +/**eventListParse 事件列表解析 */ +export function eventListParse( + type: 'ims_cdr' | 'amf_ue' | 'mme_ue', + data: any +) { + eventTotal.value += data.total; + for (const item of data.rows) { + let v: false | Record = false; + if (type === 'ims_cdr') { + v = cdrEventIMSParse(item); + } + if (type === 'amf_ue') { + v = ueEventAMFParse(item); + } + if (type === 'mme_ue') { + v = ueEventMMEParse(item); + } + + if (v) { + eventData.value.push(v); + } + } + + // 有数据进行排序 + if (eventData.value.length > 5) { + eventData.value.sort((a, b) => b.eTime - a.eTime); + } + if (eventData.value.length > 0) { + eventId.value = eventData.value[0].eId; + } +} + +/**eventItemParseAndPush 事件项解析并添加 */ +export async function eventItemParseAndPush( + type: 'ims_cdr' | 'amf_ue' | 'mme_ue', + item: any +) { + let v: false | Record = false; + if (type === 'ims_cdr') { + v = cdrEventIMSParse(item); + } + if (type === 'amf_ue') { + v = ueEventAMFParse(item); + } + if (type === 'mme_ue') { + v = ueEventMMEParse(item); + } + + if (v) { + eventData.value.unshift(v); + eventTotal.value += 1; + eventId.value = v.eId; + await new Promise(resolve => setTimeout(resolve, 800)); + if (eventData.value.length > 20) { + eventData.value.pop(); + } + } +} + +/**CDR+UE事件数据 */ +export const eventData = ref[]>([]); +/**CDR+UE事件总量 */ +export const eventTotal = ref(0); +/**CDR/UE事件推送id */ +export const eventId = ref(''); + +/**属性复位 */ +export function userActivityReset() { + eventData.value = []; + eventTotal.value = 0; + eventId.value = ''; +} diff --git a/practical_training/views/dashboard/overview/hooks/useWS.ts b/practical_training/views/dashboard/overview/hooks/useWS.ts new file mode 100644 index 00000000..df85c983 --- /dev/null +++ b/practical_training/views/dashboard/overview/hooks/useWS.ts @@ -0,0 +1,204 @@ +import { RESULT_CODE_ERROR } from '@/constants/result-constants'; +import { OptionsType, WS } from '@/plugins/ws-websocket'; +import { onBeforeUnmount, onMounted } from 'vue'; +import { + eventListParse, + eventItemParseAndPush, + userActivityReset, +} from './useUserActivity'; +import { + upfTotalFlow, + upfTFParse, + upfFlowParse, + upfTotalFlowReset, +} from './useUPFTotalFlow'; +import { topologyReset, neStateParse } from './useTopology'; +import PQueue from 'p-queue'; + +/**websocket连接 */ +export default function useWS() { + const ws = new WS(); + const queue = new PQueue({ concurrency: 1, autoStart: true }); + + /**发消息 */ + function wsSend(data: Record) { + ws.send(data); + } + + /**接收数据后回调 */ + function wsMessage(res: Record) { + // console.log(res); + const { code, requestId, data } = res; + if (code === RESULT_CODE_ERROR) { + console.warn(res.msg); + return; + } + + // 网元状态 + if (requestId && requestId.startsWith('neState')) { + const neType = requestId.split('_')[1]; + neStateParse(neType, data); + return; + } + + // 普通信息 + switch (requestId) { + // AMF_UE会话事件 + case 'amf_1010': + if (Array.isArray(data.rows)) { + eventListParse('amf_ue', data); + } + break; + // MME_UE会话事件 + case 'mme_1011_001': + if (Array.isArray(data.rows)) { + eventListParse('mme_ue', data); + } + break; + // IMS_CDR会话事件 + case 'ims_1005_001': + if (Array.isArray(data.rows)) { + eventListParse('ims_cdr', data); + } + break; + //UPF-总流量数 + case 'upf_001_0': + upfTFParse('0', data); + break; + case 'upf_001_7': + upfTFParse('7', data); + break; + case 'upf_001_30': + upfTFParse('30', data); + break; + } + + // 订阅组信息 + if (!data?.groupId) { + return; + } + switch (data.groupId) { + // kpiEvent 指标UPF + case '12_001': + if (data.data) { + upfFlowParse(data.data); + } + break; + // AMF_UE会话事件 + case '1010': + if (data.data) { + queue.add(() => eventItemParseAndPush('amf_ue', data.data)); + } + break; + // MME_UE会话事件 + case '1011_001': + if (data.data) { + queue.add(() => eventItemParseAndPush('mme_ue', data.data)); + } + break; + // IMS_CDR会话事件 + case '1005_001': + if (data.data) { + queue.add(() => eventItemParseAndPush('ims_cdr', data.data)); + } + break; + } + } + + /**UPF-总流量数 发消息*/ + function upfTFSend(day: '0' | '7' | '30') { + // 请求标记检查避免重复发送 + if (upfTotalFlow.value[day].requestFlag) { + return; + } + upfTotalFlow.value[day].requestFlag = true; + + ws.send({ + requestId: `upf_001_${day}`, + type: 'upf_tf', + data: { + neType: 'UPF', + neId: '001', + day: Number(day), + }, + }); + } + + /**userActivitySend 用户行为事件基础列表数据 发消息*/ + function userActivitySend() { + // AMF_UE会话事件 + ws.send({ + requestId: 'amf_1010', + type: 'amf_ue', + data: { + neType: 'AMF', + neId: '001', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + // MME_UE会话事件 + ws.send({ + requestId: 'mme_1011_001', + type: 'mme_ue', + data: { + neType: 'MME', + neId: '001', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + // IMS_CDR会话事件 + ws.send({ + requestId: 'ims_1005_001', + type: 'ims_cdr', + data: { + neType: 'IMS', + neId: '001', + recordType: 'MOC', + sortField: 'timestamp', + sortOrder: 'desc', + pageNum: 1, + pageSize: 20, + }, + }); + } + + onMounted(() => { + const options: OptionsType = { + url: '/ws', + params: { + /**订阅通道组 + * + * 指标UPF (GroupID:12_neId) + * AMF_UE会话事件(GroupID:1010) + * MME_UE会话事件(GroupID:1011_neId) + * IMS_CDR会话事件(GroupID:1005_neId) + */ + subGroupID: '12_001,1010,1011_001,1005_001', + }, + onmessage: wsMessage, + onerror: (ev: any) => { + console.error(ev); + }, + }; + ws.connect(options); + }); + + onBeforeUnmount(() => { + ws.close(); + userActivityReset(); + upfTotalFlowReset(); + topologyReset(); + }); + + return { + wsSend, + userActivitySend, + upfTFSend, + }; +} diff --git a/practical_training/views/dashboard/overview/images/border.png b/practical_training/views/dashboard/overview/images/border.png new file mode 100644 index 0000000000000000000000000000000000000000..b854cea479a6d114c6b906d85684a7913ea5703e GIT binary patch literal 2418 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 Khid!K%s&AzyC`=6 literal 0 HcmV?d00001 diff --git a/practical_training/views/dashboard/overview/images/brand.png b/practical_training/views/dashboard/overview/images/brand.png new file mode 100644 index 0000000000000000000000000000000000000000..2f6fb6a099fdb49c59bbd5a3dc4b8dc82aaf44ec GIT binary patch literal 14403 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 A8~^|S literal 0 HcmV?d00001 diff --git a/practical_training/views/dashboard/overview/images/line.png b/practical_training/views/dashboard/overview/images/line.png new file mode 100644 index 0000000000000000000000000000000000000000..34e99aca630e1d8d6eb397f04e4b036f897e8fa4 GIT binary patch literal 237 zcmV0H3dQqa!Y1+3ILTu%iT5S+orP8%1n3nC3Gu=Sfbg#HdtC00000NkvXXu0mjf>9=FR literal 0 HcmV?d00001 diff --git a/practical_training/views/dashboard/overview/images/rect.png b/practical_training/views/dashboard/overview/images/rect.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0ebf00e7d7b0887cd6d585eaebbf50d8016365 GIT binary patch literal 1089 zcmeAS@N?(olHy`uVBq!ia0vp^D}eY72OE%l(De2k0|N_(r;B4q#hkadPxeWtN;q89 zzu>~_=%OT~Fp;&R@VxSeTQ(ktY|b}xFgnfhoTjDWa^Yp(^tZb$(jU(~{i!^3-KziJ zm#W{ZdEMLiw$|2o{+hqGc1Z?np3IzCS(v7`_Gc^C6jNJUWBv6vr#eL54mSS$>Ws|V zkNcQX#n+uVlWkmFdHcJV#_l2;ZS3Ir|@xEM7;Ss$SCmUN6@eRJ0{#^1scm zR06X8ZGE-n)I8gWn|ni-E2jsXTE{)bq;Zm3z$F&1Sq`4U8ktP0z6+LcjtY*H05NN< z%W?_HW%`?yc5nVnd*9Ak)%G9l&z!L~{=Azru;{<(i?=g(S{m=4DIm&!Pvvf;(%+jc z8b8+W{xNxGWp!Gei6Y}9?g_EXlyP3Cr=j#6jY5NQm%Tjy)E|`D*jJurkM(*s~h<{~2Pi{}` z4_&)+@xN{hKmdzcAW PG%$F&`njxgN@xNAXiLX# literal 0 HcmV?d00001 diff --git a/practical_training/views/dashboard/overview/index.vue b/practical_training/views/dashboard/overview/index.vue new file mode 100644 index 00000000..728d974c --- /dev/null +++ b/practical_training/views/dashboard/overview/index.vue @@ -0,0 +1,493 @@ + + + + + diff --git a/practical_training/views/dashboard/smfCDR/index.vue b/practical_training/views/dashboard/smfCDR/index.vue index 23c098f1..828d935f 100644 --- a/practical_training/views/dashboard/smfCDR/index.vue +++ b/practical_training/views/dashboard/smfCDR/index.vue @@ -5,7 +5,6 @@ import { Modal, message } from 'ant-design-vue/es'; import { SizeType } from 'ant-design-vue/es/config-provider'; import { MenuInfo } from 'ant-design-vue/es/menu/src/interface'; import { ColumnsType } from 'ant-design-vue/es/table'; -import useNeInfoStore from '@/store/modules/neinfo'; import useI18n from '@/hooks/useI18n'; import { RESULT_CODE_ERROR, @@ -24,9 +23,6 @@ const { t } = useI18n(); const ws = new WS(); const queue = new PQueue({ concurrency: 1, autoStart: true }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -458,34 +454,8 @@ function wsMessage(res: Record) { } onMounted(() => { - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'SMF') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); - } - }) - .finally(() => { - // 获取列表数据 - fnGetList(); - }); + // 获取列表数据 + fnGetList(); }); onBeforeUnmount(() => { @@ -505,15 +475,6 @@ onBeforeUnmount(() => { - - - - - []>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -434,33 +431,10 @@ function wsMessage(res: Record) { onMounted(() => { // 初始字典数据 - Promise.allSettled([getDict('cdr_cause_code')]).then(resArr => { - if (resArr[0].status === 'fulfilled') { - dict.cdrCauseCode = resArr[0].value; - } - }); - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'SMSC') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); + Promise.allSettled([getDict('cdr_cause_code')]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.cdrCauseCode = resArr[0].value; } }) .finally(() => { @@ -486,15 +460,6 @@ onBeforeUnmount(() => { - - - - - { > - + diff --git a/src/views/dashboard/imsCDR/index.vue b/src/views/dashboard/imsCDR/index.vue index 3405700a..be212ab3 100644 --- a/src/views/dashboard/imsCDR/index.vue +++ b/src/views/dashboard/imsCDR/index.vue @@ -11,7 +11,6 @@ import { RESULT_CODE_SUCCESS, } from '@/constants/result-constants'; import useDictStore from '@/store/modules/dict'; -import useNeInfoStore from '@/store/modules/neinfo'; import { delIMSDataCDR, exportIMSDataCDR, @@ -38,9 +37,6 @@ let dict: { cdrCallType: [], }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -468,31 +464,6 @@ onMounted(() => { if (resArr[1].status === 'fulfilled') { dict.cdrCallType = resArr[1].value; } - } - ); - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'IMS') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); - } }) .finally(() => { // 获取列表数据 @@ -517,15 +488,6 @@ onBeforeUnmount(() => { - - - - - { > - + diff --git a/src/views/dashboard/mmeUE/index.vue b/src/views/dashboard/mmeUE/index.vue index b6f4f842..b95d71ab 100644 --- a/src/views/dashboard/mmeUE/index.vue +++ b/src/views/dashboard/mmeUE/index.vue @@ -11,7 +11,6 @@ import { RESULT_CODE_SUCCESS, } from '@/constants/result-constants'; import useDictStore from '@/store/modules/dict'; -import useNeInfoStore from '@/store/modules/neinfo'; import { listMMEDataUE, delMMEDataUE, exportMMEDataUE } from '@/api/neData/mme'; import { parseDateToStr } from '@/utils/date-utils'; import { OptionsType, WS } from '@/plugins/ws-websocket'; @@ -23,9 +22,6 @@ const { getDict } = useDictStore(); const ws = new WS(); const queue = new PQueue({ concurrency: 1, autoStart: true }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**字典数据 */ let dict: { /**UE 事件认证代码类型 */ @@ -411,47 +407,23 @@ onMounted(() => { getDict('ue_auth_code'), getDict('ue_event_type'), getDict('ue_event_cm_state'), - ]).then(resArr => { - if (resArr[0].status === 'fulfilled') { - dict.ueAauthCode = resArr[0].value; - } - if (resArr[1].status === 'fulfilled') { - const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1])); - dict.ueEventType = ueEventType.map(item => { - if (item.value === 'cm-state') { - item.label = item.label.replace('CM', 'ECM'); - } - return item; - }); - } - if (resArr[2].status === 'fulfilled') { - dict.ueEventCmState = resArr[2].value; - } - }); - - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'MME') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; + ]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.ueAauthCode = resArr[0].value; + } + if (resArr[1].status === 'fulfilled') { + const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1])); + dict.ueEventType = ueEventType.map(item => { + if (item.value === 'cm-state') { + item.label = item.label.replace('CM', 'ECM'); } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, + return item; }); } + if (resArr[2].status === 'fulfilled') { + dict.ueEventCmState = resArr[2].value; + } }) .finally(() => { // 获取列表数据 @@ -476,15 +448,6 @@ onBeforeUnmount(() => { - - - - - { > - + { {{ t('views.dashboard.overview.upfFlowTotal.up') }} -

{{ upfTotalFlow[upfTFActive].upFrom }}

+

{{ upfTotalFlow[upfTFActive].up }}

{{ t('views.dashboard.overview.upfFlowTotal.down') }} -

{{ upfTotalFlow[upfTFActive].downFrom }}

+

{{ upfTotalFlow[upfTFActive].down }}

diff --git a/src/views/dashboard/smfCDR/index.vue b/src/views/dashboard/smfCDR/index.vue index 23c098f1..828d935f 100644 --- a/src/views/dashboard/smfCDR/index.vue +++ b/src/views/dashboard/smfCDR/index.vue @@ -5,7 +5,6 @@ import { Modal, message } from 'ant-design-vue/es'; import { SizeType } from 'ant-design-vue/es/config-provider'; import { MenuInfo } from 'ant-design-vue/es/menu/src/interface'; import { ColumnsType } from 'ant-design-vue/es/table'; -import useNeInfoStore from '@/store/modules/neinfo'; import useI18n from '@/hooks/useI18n'; import { RESULT_CODE_ERROR, @@ -24,9 +23,6 @@ const { t } = useI18n(); const ws = new WS(); const queue = new PQueue({ concurrency: 1, autoStart: true }); -/**网元可选 */ -let neOtions = ref[]>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -458,34 +454,8 @@ function wsMessage(res: Record) { } onMounted(() => { - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'SMF') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); - } - }) - .finally(() => { - // 获取列表数据 - fnGetList(); - }); + // 获取列表数据 + fnGetList(); }); onBeforeUnmount(() => { @@ -505,15 +475,6 @@ onBeforeUnmount(() => { - - - - - []>([]); - /**开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); @@ -434,33 +431,10 @@ function wsMessage(res: Record) { onMounted(() => { // 初始字典数据 - Promise.allSettled([getDict('cdr_cause_code')]).then(resArr => { - if (resArr[0].status === 'fulfilled') { - dict.cdrCauseCode = resArr[0].value; - } - }); - // 获取网元网元列表 - useNeInfoStore() - .fnNelist() - .then(res => { - if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) { - if (res.data.length > 0) { - let arr: Record[] = []; - res.data.forEach(i => { - if (i.neType === 'SMSC') { - arr.push({ value: i.neId, label: i.neName }); - } - }); - neOtions.value = arr; - if (arr.length > 0) { - queryParams.neId = arr[0].value; - } - } - } else { - message.warning({ - content: t('common.noData'), - duration: 2, - }); + Promise.allSettled([getDict('cdr_cause_code')]) + .then(resArr => { + if (resArr[0].status === 'fulfilled') { + dict.cdrCauseCode = resArr[0].value; } }) .finally(() => { @@ -486,15 +460,6 @@ onBeforeUnmount(() => { - - - - - { >
- +