fix: 看板ws黄金指标UPF

This commit is contained in:
TsMask
2024-03-21 10:10:02 +08:00
parent 4ae5f64da3
commit d15b75e8fd
5 changed files with 258 additions and 164 deletions

View File

@@ -1,9 +1,9 @@
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants'; import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { request } from '@/plugins/http-fetch'; import { request } from '@/plugins/http-fetch';
import { parseDateToStr } from '@/utils/date-utils';
import { parseObjLineToHump } from '@/utils/parse-utils'; import { parseObjLineToHump } from '@/utils/parse-utils';
/** /**
* Todo 废弃
* 查询黄金指标数据 * 查询黄金指标数据
* @param query 查询参数 * @param query 查询参数
* @returns object * @returns object
@@ -110,6 +110,7 @@ export async function getKPITitle(neType: string) {
} }
/** /**
* Todo 废弃
* 查询UPF上下行速率数据 * 查询UPF上下行速率数据
* @param query 查询参数 * @param query 查询参数
* @returns object * @returns object

View File

@@ -122,9 +122,11 @@ export function parseSizeFromKBs(size: number): string {
/** /**
* 字节数转换速率 * 字节数转换速率
* @param sizeByte 数值大小 * @param sizeByte 数值大小
* @returns * @returns [值,单位]
*/ */
export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any { export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
sizeByte = Number(sizeByte) || 0;
timeInterval = Number(timeInterval) || 1;
// let realBit:any=((sizeByte * 8) / timeInterval); // let realBit:any=((sizeByte * 8) / timeInterval);
// if (realBit >= 0 && realBit < 1000) { // if (realBit >= 0 && realBit < 1000) {
// return [realBit.toFixed(2),' bits/sec']; // return [realBit.toFixed(2),' bits/sec'];

View File

@@ -1,10 +1,6 @@
<template>
<div ref="upfFlow" class="chart-container"></div>
</template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { listUPFData } from '@/api/perfManage/goldTarget'; import { listKPIData } from '@/api/perfManage/goldTarget';
import { parseSizeFromKbs } from '@/utils/parse-utils';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { import {
TooltipComponent, TooltipComponent,
@@ -20,6 +16,8 @@ import { CanvasRenderer } from 'echarts/renderers';
import { markRaw } from 'vue'; import { markRaw } from 'vue';
import useI18n from '@/hooks/useI18n'; import useI18n from '@/hooks/useI18n';
import { parseDateToStr } from '@/utils/date-utils'; import { parseDateToStr } from '@/utils/date-utils';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { upfFlowData, upfFlowParse } from '../../hooks/useUPFTotalFlow';
const { t } = useI18n(); const { t } = useI18n();
@@ -39,9 +37,6 @@ type EChartsOption = echarts.ComposeOption<
| LineSeriesOption | LineSeriesOption
>; >;
/**定时器ID */
const timeoutId = ref<any>(null);
/**图DOM节点实例对象 */ /**图DOM节点实例对象 */
const upfFlow = ref<HTMLElement | undefined>(undefined); const upfFlow = ref<HTMLElement | undefined>(undefined);
@@ -69,125 +64,130 @@ function fnDesign(container: HTMLElement | undefined, option: EChartsOption) {
} }
//渲染速率图 //渲染速率图
function initPicture() { function handleRanderChart() {
clearTimeout(timeoutId.value); const { lineXTime, lineYUp, lineYDown } = upfFlowData.value;
let queryArr: any = []; var yAxisSeries: any = [
const initTime: Date = new Date(); {
const startTime: Date = new Date(initTime); name: t('views.dashboard.overview.upfFlow.up'),
startTime.setHours(0, 0, 0, 0); // 设置为今天的0点 type: 'line',
const endTime: Date = new Date(initTime); color: 'rgba(250, 219, 20)',
endTime.setHours(23, 59, 59, 59); // 设置为今天的12点 smooth: true,
queryArr = [parseDateToStr(startTime), parseDateToStr(endTime)]; areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
listUPFData(queryArr).then(res => { {
timeoutId.value = setTimeout(() => { offset: 0,
initPicture(); // 5秒后再次获取数据 color: 'rgba(250, 219, 20, .5)',
}, 5000); },
let timeArr: any = []; {
let upValue: any = []; offset: 1,
let downValue: any = []; color: 'rgba(250, 219, 20, 0.5)',
},
res.upData.map((item: any) => { ]),
timeArr.push(item.timestamp); shadowColor: 'rgba(0, 0, 0, 0.1)',
upValue.push(parseSizeFromKbs(item.value, item.granularity)[0]); shadowBlur: 10,
});
res.downData.map((item: any) => {
downValue.push(parseSizeFromKbs(item.value, item.granularity)[0]);
});
var charts = {
unit: '(Mbps)',
names: [
t('views.dashboard.overview.upfFlow.up'),
t('views.dashboard.overview.upfFlow.down'),
],
lineX: timeArr,
value: [upValue, downValue],
};
var color = ['rgba(250, 219, 20', 'rgba(92, 123, 217'];
var lineY: any = [];
for (var i = 0; i < charts.names.length; i++) {
var x = i;
if (x > color.length - 1) {
x = color.length - 1;
}
var data = {
name: charts.names[i],
type: 'line',
color: color[x] + ')',
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: color[x] + ', .5)',
},
{
offset: 1,
color: color[x] + ', 0.5)',
},
]),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
symbol: 'circle',
symbolSize: 5,
formatter: '{b}',
data: charts.value[i],
};
lineY.push(data);
}
const optionData: EChartsOption = {
tooltip: {
show: true, //是否显示提示框组件
trigger: 'axis',
//formatter:'{a0}:{c0}<br>{a1}:{c1}'
formatter: function (param: any) {
var tip = '';
if (param !== null && param.length > 0) {
tip += param[0].name + '<br />';
for (var i = 0; i < param.length; i++) {
tip +=
param[i].marker +
param[i].seriesName +
': ' +
param[i].value +
'<br />';
}
}
return tip;
},
}, },
legend: { symbol: 'circle',
data: charts.names, symbolSize: 5,
textStyle: { formatter: '{b}',
fontSize: 12, data: lineYUp,
},
{
name: t('views.dashboard.overview.upfFlow.down'),
type: 'line',
color: 'rgba(92, 123, 217)',
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(92, 123, 217, .5)',
},
{
offset: 1,
color: 'rgba(92, 123, 217, 0.5)',
},
]),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
symbol: 'circle',
symbolSize: 5,
formatter: '{b}',
data: lineYDown,
},
];
const optionData: EChartsOption = {
tooltip: {
show: true, //是否显示提示框组件
trigger: 'axis',
//formatter:'{a0}:{c0}<br>{a1}:{c1}'
formatter: function (param: any) {
var tip = '';
if (param !== null && param.length > 0) {
tip += param[0].name + '<br />';
for (var i = 0; i < param.length; i++) {
tip +=
param[i].marker +
param[i].seriesName +
': ' +
param[i].value +
'<br />';
}
}
return tip;
},
},
legend: {
data: yAxisSeries.map((s: any) => s.name),
textStyle: {
fontSize: 12,
color: 'rgb(0,253,255,0.6)',
},
left: 'center', // 设置图例居中
},
grid: {
top: '14%',
left: '4%',
right: '4%',
bottom: '12%',
containLabel: true,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: lineXTime,
axisLabel: {
formatter: function (params: any) {
return params.split(' ')[1];
},
fontSize: 14,
},
axisLine: {
lineStyle: {
color: 'rgb(0,253,255,0.6)', color: 'rgb(0,253,255,0.6)',
}, },
left: 'center',
}, // 设置图例居中
grid: {
top: '14%',
left: '4%',
right: '4%',
bottom: '12%',
containLabel: true,
}, },
xAxis: { },
type: 'category', yAxis: [
boundaryGap: false, {
data: charts.lineX, name: '(Mbps)',
nameTextStyle: {
fontSize: 12, // 设置文字距离x轴的距离
padding: [0, -10, 0, 0], // 设置名称在x轴方向上的偏移
},
type: 'value',
// splitNumber: 4,
min: 0,
//max: 300,
axisLabel: { axisLabel: {
formatter: function (params: any) { formatter: '{value}',
return params.split(' ')[1]; },
splitLine: {
lineStyle: {
color: 'rgb(23,255,243,0.3)',
}, },
fontSize: 14,
}, },
axisLine: { axisLine: {
lineStyle: { lineStyle: {
@@ -195,48 +195,94 @@ function initPicture() {
}, },
}, },
}, },
yAxis: [ ],
{ series: yAxisSeries,
name: charts.unit, };
nameTextStyle: { fnDesign(upfFlow.value, optionData);
fontSize: 12, // 设置文字距离x轴的距离
padding: [0, -10, 0, 0], // 设置名称在x轴方向上的偏移
},
type: 'value',
// splitNumber: 4,
min: 0,
//max: 300,
axisLabel: {
formatter: '{value}',
},
splitLine: {
lineStyle: {
color: 'rgb(23,255,243,0.3)',
},
},
axisLine: {
lineStyle: {
color: 'rgb(0,253,255,0.6)',
},
},
},
],
series: lineY,
};
fnDesign(upfFlow.value, optionData);
});
} }
onMounted(() => { /**查询初始UPF数据 */
initPicture(); function fnGetInitData() {
}); // 查询10分钟前的
const nowDate: Date = new Date();
const tenMinutesAgo = new Date(nowDate.getTime() - 5 * 60 * 1000);
/**组件实例被卸载之后调用 */ listKPIData({
onUnmounted(() => { neType: 'UPF',
clearTimeout(timeoutId.value); neId: '001',
startTime: parseDateToStr(tenMinutesAgo),
endTime: parseDateToStr(nowDate),
// startTime: '2024-03-20 19:50:00',
// endTime: '2024-03-20 19:55:00',
interval: 5, // 5秒
sortField: 'timeGroup',
sortOrder: 'asc',
})
.then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
for (const item of res.data) {
upfFlowParse(item);
}
}
})
.finally(() => {
handleRanderChart();
});
}
watch(
() => upfFlowData.value,
v => {
upfFlowChart.value.setOption({
xAxis: {
data: v.lineXTime,
},
series: [
{
data: v.lineYUp,
},
{
data: v.lineYDown,
},
],
});
},
{
deep: true,
}
);
onMounted(() => {
fnGetInitData();
// setInterval(() => {
// upfFlowData.value.lineXTime.push(parseDateToStr(new Date()));
// const upN3 = parseSizeFromKbs(+145452, 5);
// upfFlowData.value.lineYUp.push(upN3[0]);
// const downN6 = parseSizeFromKbs(+232343, 5);
// upfFlowData.value.lineYDown.push(downN6[0]);
// upfFlowChart.value.setOption({
// xAxis: {
// data: upfFlowData.value.lineXTime,
// },
// series: [
// {
// data: upfFlowData.value.lineYUp,
// },
// {
// data: upfFlowData.value.lineYDown,
// },
// ],
// });
// }, 5000);
}); });
</script> </script>
<template>
<div ref="upfFlow" class="chart-container"></div>
</template>
<style lang="less" scoped> <style lang="less" scoped>
.chart-container { .chart-container {
/* 设置图表容器大小和位置 */ /* 设置图表容器大小和位置 */

View File

@@ -1,6 +1,40 @@
import { parseSizeFromBits } from '@/utils/parse-utils'; import { parseSizeFromBits, parseSizeFromKbs } from '@/utils/parse-utils';
import { ref } from 'vue'; import { ref } from 'vue';
/**UPF-流量数据 */
export const upfFlowData = ref<{
/**时间 */
lineXTime: string[];
/**上行 N3 */
lineYUp: number[];
/**下行 N6 */
lineYDown: number[];
/**容量 */
cap: number;
}>({
lineXTime: [],
lineYUp: [],
lineYDown: [],
cap: 0,
});
/**UPF-流量数据 数据解析 */
export function upfFlowParse(data: Record<string, string>) {
upfFlowData.value.lineXTime.push(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;
}
}
type TFType = { type TFType = {
/**上行 N3 */ /**上行 N3 */
up: string; up: string;

View File

@@ -8,7 +8,7 @@ import {
eventTotal, eventTotal,
eventId, eventId,
} from './useUserActivity'; } from './useUserActivity';
import { upfTotalFlow, upfTFParse } from './useUPFTotalFlow'; import { upfTotalFlow, upfTFParse, upfFlowParse } from './useUPFTotalFlow';
import { neStateParse } from './useTopology'; import { neStateParse } from './useTopology';
import PQueue from 'p-queue'; import PQueue from 'p-queue';
@@ -102,6 +102,12 @@ export default function useWS() {
return; return;
} }
switch (data.groupId) { switch (data.groupId) {
// kpiEvent 指标UPF
case '12':
if (data.data) {
upfFlowParse(data.data);
}
break;
// ueEvent UE会话事件 // ueEvent UE会话事件
case '1010': case '1010':
if (data.data) { if (data.data) {
@@ -112,7 +118,9 @@ export default function useWS() {
eventTotal.value += 1; eventTotal.value += 1;
eventId.value = v.eId; eventId.value = v.eId;
await new Promise(resolve => setTimeout(resolve, 800)); await new Promise(resolve => setTimeout(resolve, 800));
eventData.value.pop(); if (eventData.value.length > 20) {
eventData.value.pop();
}
} }
}); });
} }
@@ -127,7 +135,9 @@ export default function useWS() {
eventTotal.value += 1; eventTotal.value += 1;
eventId.value = v.eId; eventId.value = v.eId;
await new Promise(resolve => setTimeout(resolve, 800)); await new Promise(resolve => setTimeout(resolve, 800));
eventData.value.pop(); if (eventData.value.length > 20) {
eventData.value.pop();
}
} }
}); });
} }
@@ -201,10 +211,11 @@ export default function useWS() {
params: { params: {
/**订阅通道组 /**订阅通道组
* *
* 指标UPF (GroupID:12)
* UE会话事件-AMF (GroupID:1010) * UE会话事件-AMF (GroupID:1010)
* CDR会话事件-IMS (GroupID:1005) * CDR会话事件-IMS (GroupID:1005)
*/ */
subGroupID: '1010,1005', subGroupID: '12,1010,1005',
}, },
onmessage: wsMessage, onmessage: wsMessage,
onerror: wsError, onerror: wsError,