feat:关键仪表盘显示指标修改
This commit is contained in:
@@ -22,6 +22,7 @@ import type { Dayjs } from 'dayjs';
|
||||
import dayjs from 'dayjs';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import { generateColorRGBA } from '@/utils/generate-utils';
|
||||
import { parseSizeFromKbs } from '@/utils/parse-utils';
|
||||
import { LineOutlined, InfoCircleOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue';
|
||||
import { TableColumnType } from 'ant-design-vue';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
@@ -168,7 +169,8 @@ const TARGET_KPI_IDS: Record<NeType, string[]> = {
|
||||
// SMSC: ['SMSC.A.01', 'SMSC.A.02', 'SMSC.A.03'],
|
||||
};
|
||||
|
||||
const KPI_TITLE: Record<string, string> = {
|
||||
// 原始KPI标题(用于内部计算)
|
||||
const BASE_KPI_TITLE: Record<string, string> = {
|
||||
'AMF.02': '5G Registration Request',
|
||||
'AMF.03': '5G Registration Success',
|
||||
'UPF.04': 'UPF Downlink Throughput',
|
||||
@@ -183,6 +185,143 @@ const KPI_TITLE: Record<string, string> = {
|
||||
'MME.A.02':'4G Registration Success',
|
||||
};
|
||||
|
||||
// 计算型KPI定义
|
||||
interface CalculatedKPI {
|
||||
id: string;
|
||||
title: string;
|
||||
numerator: string; // 分子指标ID
|
||||
denominator: string; // 分母指标ID
|
||||
isPercentage: boolean; // 是否为百分比
|
||||
}
|
||||
|
||||
// 计算型KPI配置
|
||||
const CALCULATED_KPIS: Record<NeType, CalculatedKPI[]> = {
|
||||
AMF: [
|
||||
{
|
||||
id: 'AMF_5G_REG_SUCCESS_RATE',
|
||||
title: '5G Registration Success Rate',
|
||||
numerator: 'AMF.03',
|
||||
denominator: 'AMF.02',
|
||||
isPercentage: true
|
||||
}
|
||||
],
|
||||
UPF: [
|
||||
{
|
||||
id: 'UPF.04',
|
||||
title: 'UPF Downlink Throughput',
|
||||
numerator: 'UPF.04',
|
||||
denominator: '',
|
||||
isPercentage: false
|
||||
},
|
||||
{
|
||||
id: 'UPF.05',
|
||||
title: 'UPF Uplink Throughput',
|
||||
numerator: 'UPF.05',
|
||||
denominator: '',
|
||||
isPercentage: false
|
||||
}
|
||||
],
|
||||
IMS: [
|
||||
{
|
||||
id: 'IMS_REG_SUCCESS_RATE',
|
||||
title: 'IMS Registration Success Rate',
|
||||
numerator: 'SCSCF.03',
|
||||
denominator: 'SCSCF.04',
|
||||
isPercentage: true
|
||||
},
|
||||
{
|
||||
id: 'MO_CALL_SUCCESS_RATE',
|
||||
title: 'MO Call Success Rate',
|
||||
numerator: 'SCSCF.05',
|
||||
denominator: 'SCSCF.06',
|
||||
isPercentage: true
|
||||
},
|
||||
{
|
||||
id: 'MT_CALL_SUCCESS_RATE',
|
||||
title: 'MT Call Success Rate',
|
||||
numerator: 'SCSCF.07',
|
||||
denominator: 'SCSCF.08',
|
||||
isPercentage: true
|
||||
}
|
||||
],
|
||||
MME: [
|
||||
{
|
||||
id: 'MME_4G_REG_SUCCESS_RATE',
|
||||
title: '4G Registration Success Rate',
|
||||
numerator: 'MME.A.02',
|
||||
denominator: 'MME.A.01',
|
||||
isPercentage: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 显示用的KPI标题
|
||||
const KPI_TITLE: Record<string, string> = {};
|
||||
// 初始化显示标题
|
||||
Object.values(CALCULATED_KPIS).flat().forEach(kpi => {
|
||||
KPI_TITLE[kpi.id] = kpi.title;
|
||||
});
|
||||
|
||||
// UPF吞吐量指标ID列表
|
||||
const UPF_THROUGHPUT_KPIS = ['UPF.04', 'UPF.05'];
|
||||
|
||||
// 判断是否为UPF吞吐量指标
|
||||
const isUPFThroughputKPI = (kpiId: string): boolean => {
|
||||
return UPF_THROUGHPUT_KPIS.includes(kpiId);
|
||||
};
|
||||
|
||||
// 格式化UPF吞吐量数据 - 根据数据来源使用不同的时间间隔
|
||||
const formatUPFThroughput = (value: number, timeInterval: number = 900): number => {
|
||||
if (value === 0 || value === null || value === undefined) return 0;
|
||||
// 使用parseSizeFromKbs函数进行格式化,转换为Mbps
|
||||
const [formattedValue] = parseSizeFromKbs(value, timeInterval);
|
||||
return Number(formattedValue);
|
||||
};
|
||||
|
||||
// 判断当前选中的指标中是否包含UPF吞吐量指标
|
||||
const hasUPFThroughputKPIs = (): boolean => {
|
||||
return selectedKPIs.value.some(kpiId => isUPFThroughputKPI(kpiId));
|
||||
};
|
||||
|
||||
// 计算KPI值的函数
|
||||
const calculateKPIValue = (kpi: CalculatedKPI, rawData: Record<string, any>): number => {
|
||||
if (!kpi.denominator) {
|
||||
// 单一指标,如UPF吞吐量
|
||||
const value = Number(rawData[kpi.numerator]) || 0;
|
||||
return isUPFThroughputKPI(kpi.id) ? formatUPFThroughput(value, 900) : value;
|
||||
} else {
|
||||
// 计算型指标(百分比)
|
||||
const numerator = Number(rawData[kpi.numerator]) || 0;
|
||||
const denominator = Number(rawData[kpi.denominator]) || 0;
|
||||
|
||||
if (denominator === 0) return 0;
|
||||
|
||||
const percentage = (numerator / denominator) * 100;
|
||||
return Number(percentage.toFixed(2));
|
||||
}
|
||||
};
|
||||
|
||||
// 获取网元类型的所有计算型KPI
|
||||
const getCalculatedKPIsForNeType = (neType: NeType): CalculatedKPI[] => {
|
||||
return CALCULATED_KPIS[neType] || [];
|
||||
};
|
||||
|
||||
// 获取Y轴单位
|
||||
const getYAxisUnit = (): string => {
|
||||
const allKPIs = Object.values(CALCULATED_KPIS).flat();
|
||||
const hasUPF = allKPIs.some(kpi => isUPFThroughputKPI(kpi.id));
|
||||
const hasPercentage = allKPIs.some(kpi => kpi.isPercentage);
|
||||
|
||||
if (hasUPF && hasPercentage) {
|
||||
return ''; // 混合单位时不显示
|
||||
} else if (hasUPF) {
|
||||
return '(Mbps)';
|
||||
} else if (hasPercentage) {
|
||||
return '(%)';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
// 添加网元信息 store
|
||||
const neInfoStore = useNeInfoStore();
|
||||
|
||||
@@ -284,10 +423,19 @@ const wsMessage = (res: Record<string, any>) => {
|
||||
date: kpiEvent.timeGroup?.toString() || Date.now().toString(),
|
||||
};
|
||||
|
||||
// 为每个网元的每个指标添加数据
|
||||
for (const kpiId of TARGET_KPI_IDS[neType as NeType] || []) {
|
||||
const key = `${kpiId}_${neId}`;
|
||||
newData[key] = Number(kpiEvent[kpiId]) || 0;
|
||||
// 为每个网元的每个计算型指标添加数据
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType as NeType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
const key = `${kpi.id}_${neId}`;
|
||||
|
||||
if (isUPFThroughputKPI(kpi.id)) {
|
||||
// UPF吞吐量指标使用1分钟间隔
|
||||
const rawValue = Number(kpiEvent[kpi.numerator]) || 0;
|
||||
newData[key] = formatUPFThroughput(rawValue, 60);
|
||||
} else {
|
||||
// 其他计算型指标
|
||||
newData[key] = calculateKPIValue(kpi, kpiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新图表数据(只影响图表,不影响表格)
|
||||
@@ -381,12 +529,21 @@ const fetchChartData = async () => {
|
||||
.sort((a, b) => Number(a.timeGroup) - Number(b.timeGroup))
|
||||
.map(item => {
|
||||
const dataItem: ChartDataItem = { date: item.timeGroup.toString() };
|
||||
// 为每个网元的每个指标添加数据
|
||||
// 为每个网元的每个计算型指标添加数据
|
||||
for (const neType of ALL_NE_TYPES) {
|
||||
for (const ne of neList.value[neType]) {
|
||||
for (const kpiId of TARGET_KPI_IDS[neType]) {
|
||||
const key = `${kpiId}_${ne.neId}`;
|
||||
dataItem[key] = Number(item[kpiId]) || 0;
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
const key = `${kpi.id}_${ne.neId}`;
|
||||
|
||||
if (isUPFThroughputKPI(kpi.id)) {
|
||||
// UPF吞吐量指标使用15分钟间隔
|
||||
const rawValue = Number(item[kpi.numerator]) || 0;
|
||||
dataItem[key] = formatUPFThroughput(rawValue, 900);
|
||||
} else {
|
||||
// 其他计算型指标
|
||||
dataItem[key] = calculateKPIValue(kpi, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,6 +654,15 @@ const themeObserver = new MutationObserver(() => {
|
||||
color: splitLineColor,
|
||||
},
|
||||
},
|
||||
// 根据指标类型显示单位
|
||||
name: getYAxisUnit(),
|
||||
nameTextStyle: {
|
||||
fontSize: 12,
|
||||
padding: [0, 0, 0, 0],
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
@@ -550,11 +716,9 @@ const updateChart = () => {
|
||||
const series = [];
|
||||
for (const neType of ALL_NE_TYPES) {
|
||||
for (const ne of neList.value[neType]) {
|
||||
for (const kpiId of TARGET_KPI_IDS[neType]) {
|
||||
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
|
||||
if (!kpi) continue;
|
||||
|
||||
const key = `${kpiId}_${ne.neId}`;
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
const key = `${kpi.id}_${ne.neId}`;
|
||||
const color = kpiColors.get(key) || generateColorRGBA();
|
||||
kpiColors.set(key, color);
|
||||
|
||||
@@ -670,6 +834,15 @@ const updateChart = () => {
|
||||
color: getSplitLineColor(),
|
||||
},
|
||||
},
|
||||
// 根据指标类型显示单位
|
||||
name: getYAxisUnit(),
|
||||
nameTextStyle: {
|
||||
fontSize: 12,
|
||||
padding: [0, 0, 0, 0],
|
||||
color: document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
? '#CACADA'
|
||||
: '#333',
|
||||
},
|
||||
},
|
||||
series: series, //配置数据
|
||||
};
|
||||
@@ -741,7 +914,7 @@ onMounted(async () => {
|
||||
// 存储指标列信
|
||||
const kpiColumns = ref<KPIColumn[]>([]);
|
||||
// 添加选中指标的的状态
|
||||
const selectedKPIs = ref<string[]>(Object.values(TARGET_KPI_IDS).flat());
|
||||
const selectedKPIs = ref<string[]>(Object.values(CALCULATED_KPIS).flat().map(kpi => kpi.id));
|
||||
|
||||
// 获取网元指标
|
||||
const fetchSpecificKPI = async () => {
|
||||
@@ -753,36 +926,24 @@ const fetchSpecificKPI = async () => {
|
||||
try {
|
||||
let allKPIs: KPIColumn[] = [];
|
||||
|
||||
// 获取所有网元的指标
|
||||
// 为每个网元类型创建计算型KPI列
|
||||
for (const neType of ALL_NE_TYPES) {
|
||||
const res = await getKPITitle(neType.toUpperCase());
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType);
|
||||
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
const titleIDs = Object.values(TARGET_KPI_IDS).flat();
|
||||
// 只获取 TARGET_KPI_IDS 中定义的指标
|
||||
const filteredKPIs = res.data
|
||||
.filter(item => TARGET_KPI_IDS[neType].includes(item.kpiId))
|
||||
.map(item => {
|
||||
let title = item[`${language}Title`];
|
||||
if (titleIDs.includes(item.kpiId)) {
|
||||
title = KPI_TITLE[item.kpiId] || title;
|
||||
}
|
||||
return {
|
||||
title: title,
|
||||
dataIndex: item.kpiId,
|
||||
key: item.kpiId,
|
||||
kpiId: item.kpiId,
|
||||
for (const kpi of calculatedKPIs) {
|
||||
allKPIs.push({
|
||||
title: kpi.title,
|
||||
dataIndex: kpi.id,
|
||||
key: kpi.id,
|
||||
kpiId: kpi.id,
|
||||
neType: neType,
|
||||
};
|
||||
});
|
||||
|
||||
allKPIs = [...allKPIs, ...filteredKPIs];
|
||||
}
|
||||
}
|
||||
|
||||
kpiColumns.value = allKPIs;
|
||||
// 直接使用重要指标
|
||||
selectedKPIs.value = Object.values(TARGET_KPI_IDS).flat();
|
||||
// 使用计算型指标
|
||||
selectedKPIs.value = Object.values(CALCULATED_KPIS).flat().map(kpi => kpi.id);
|
||||
|
||||
if (kpiColumns.value.length === 0) {
|
||||
console.warn('No KPIs found');
|
||||
@@ -837,13 +998,12 @@ const updateChartData = (newData: ChartDataItem) => {
|
||||
},
|
||||
series: ALL_NE_TYPES.flatMap(type =>
|
||||
neList.value[type].map(ne =>
|
||||
TARGET_KPI_IDS[type].map(kpiId => {
|
||||
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
|
||||
const key = `${kpiId}_${ne.neId}`;
|
||||
getCalculatedKPIsForNeType(type).map(kpi => {
|
||||
const key = `${kpi.id}_${ne.neId}`;
|
||||
return {
|
||||
type: 'line',
|
||||
data: chartData.value.map(item => item[key] || 0),
|
||||
name: `${kpi?.title || kpiId}(${ne.neName})`,
|
||||
name: `${kpi.title}(${ne.neName})`,
|
||||
};
|
||||
})
|
||||
)
|
||||
@@ -878,12 +1038,10 @@ function fnInitKpiStatsData() {
|
||||
|
||||
for (const neType of ALL_NE_TYPES) {
|
||||
for (const ne of neList.value[neType]) {
|
||||
for (const kpiId of TARGET_KPI_IDS[neType]) {
|
||||
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
|
||||
if (!kpi) continue;
|
||||
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
kpiStats.value.push({
|
||||
kpiId: `${kpiId}_${ne.neId}`,
|
||||
kpiId: `${kpi.id}_${ne.neId}`,
|
||||
title: `${kpi.title}(${ne.neName})`,
|
||||
last1Day: '', // 空白显示,loading状态表示正在获取数据
|
||||
last7Days: '',
|
||||
@@ -952,39 +1110,86 @@ async function fnGetKpiStatsData() {
|
||||
const { neType, neId, success, data } = result;
|
||||
|
||||
if (success && data.length > 0) {
|
||||
// 为每个指标计算统计值
|
||||
for (const kpiId of TARGET_KPI_IDS[neType as NeType]) {
|
||||
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
|
||||
if (!kpi) continue;
|
||||
// 为每个计算型指标计算统计值
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType as NeType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
const key = `${kpi.id}_${neId}`;
|
||||
|
||||
const key = `${kpiId}_${neId}`;
|
||||
|
||||
// 根据时间范围筛选非零数据
|
||||
// 根据时间范围筛选有效数据(非零数据)
|
||||
const data1Day = data.filter((item: any) => {
|
||||
const itemTime = Number(item.timeGroup);
|
||||
const value = item[kpiId] ? Number(item[kpiId]) : 0;
|
||||
return itemTime >= day1_start && value !== 0;
|
||||
if (itemTime < day1_start) return false;
|
||||
|
||||
// 检查相关指标是否有有效数值
|
||||
if (kpi.isPercentage) {
|
||||
// 百分比指标:分母必须大于0
|
||||
const denominator = Number(item[kpi.denominator]) || 0;
|
||||
return denominator > 0;
|
||||
} else {
|
||||
// 其他指标:数值必须大于0
|
||||
const value = Number(item[kpi.numerator]) || 0;
|
||||
return value > 0;
|
||||
}
|
||||
});
|
||||
|
||||
const data7Days = data.filter((item: any) => {
|
||||
const itemTime = Number(item.timeGroup);
|
||||
const value = item[kpiId] ? Number(item[kpiId]) : 0;
|
||||
return itemTime >= day7_start && value !== 0;
|
||||
if (itemTime < day7_start) return false;
|
||||
|
||||
// 检查相关指标是否有有效数值
|
||||
if (kpi.isPercentage) {
|
||||
// 百分比指标:分母必须大于0
|
||||
const denominator = Number(item[kpi.denominator]) || 0;
|
||||
return denominator > 0;
|
||||
} else {
|
||||
// 其他指标:数值必须大于0
|
||||
const value = Number(item[kpi.numerator]) || 0;
|
||||
return value > 0;
|
||||
}
|
||||
});
|
||||
|
||||
const data30Days = data.filter((item: any) => {
|
||||
const itemTime = Number(item.timeGroup);
|
||||
const value = item[kpiId] ? Number(item[kpiId]) : 0;
|
||||
return itemTime >= day30_start && value !== 0;
|
||||
if (itemTime < day30_start) return false;
|
||||
|
||||
// 检查相关指标是否有有效数值
|
||||
if (kpi.isPercentage) {
|
||||
// 百分比指标:分母必须大于0
|
||||
const denominator = Number(item[kpi.denominator]) || 0;
|
||||
return denominator > 0;
|
||||
} else {
|
||||
// 其他指标:数值必须大于0
|
||||
const value = Number(item[kpi.numerator]) || 0;
|
||||
return value > 0;
|
||||
}
|
||||
});
|
||||
|
||||
// 计算统计值(只对非零数据进行计算,关键指标多为次数类使用累计值)
|
||||
// 计算统计值(传入的数据已经是有效数据)
|
||||
const calculateValue = (dataArray: any[]) => {
|
||||
if (dataArray.length === 0) return 0;
|
||||
|
||||
const values = dataArray.map((item: any) => Number(item[kpiId]));
|
||||
// 关键指标多为次数类,使用累计值
|
||||
return Number(values.reduce((sum, val) => sum + val, 0).toFixed(2));
|
||||
if (isUPFThroughputKPI(kpi.id)) {
|
||||
// UPF吞吐量指标:先格式化每个数据点,然后计算平均值
|
||||
const values = dataArray.map((item: any) => Number(item[kpi.numerator]) || 0);
|
||||
const formattedValues = values.map(val => formatUPFThroughput(val, 900));
|
||||
const average = formattedValues.reduce((sum, val) => sum + val, 0) / formattedValues.length;
|
||||
return Number(average.toFixed(2));
|
||||
} else if (kpi.isPercentage) {
|
||||
// 百分比指标:计算平均成功率(数据已经过滤,分母都大于0)
|
||||
const percentages = dataArray.map((item: any) => {
|
||||
const numerator = Number(item[kpi.numerator]) || 0;
|
||||
const denominator = Number(item[kpi.denominator]) || 0;
|
||||
return (numerator / denominator) * 100;
|
||||
});
|
||||
|
||||
const average = percentages.reduce((sum, val) => sum + val, 0) / percentages.length;
|
||||
return Number(average.toFixed(2));
|
||||
} else {
|
||||
// 其他指标:累计值(数据已经过滤,都是非零值)
|
||||
const values = dataArray.map((item: any) => Number(item[kpi.numerator]) || 0);
|
||||
const sum = values.reduce((sum, val) => sum + val, 0);
|
||||
return Number(sum.toFixed(2));
|
||||
}
|
||||
};
|
||||
|
||||
// 更新对应的统计数据
|
||||
@@ -997,8 +1202,9 @@ async function fnGetKpiStatsData() {
|
||||
}
|
||||
} else {
|
||||
// 如果获取失败,保持空白显示
|
||||
for (const kpiId of TARGET_KPI_IDS[neType as NeType]) {
|
||||
const key = `${kpiId}_${neId}`;
|
||||
const calculatedKPIs = getCalculatedKPIsForNeType(neType as NeType);
|
||||
for (const kpi of calculatedKPIs) {
|
||||
const key = `${kpi.id}_${neId}`;
|
||||
const statsIndex = kpiStats.value.findIndex((item: any) => item.kpiId === key);
|
||||
if (statsIndex !== -1) {
|
||||
kpiStats.value[statsIndex].last1Day = '';
|
||||
@@ -1077,8 +1283,18 @@ const statsColumns: TableColumnType<KPIStats>[] = [
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return '';
|
||||
}
|
||||
// 关键指标多为次数类,使用累计值
|
||||
// 根据指标类型显示不同单位
|
||||
const kpiId = record.kpiId.split('_')[0];
|
||||
const isUPFThroughput = isUPFThroughputKPI(kpiId);
|
||||
const isPercentage = Object.values(CALCULATED_KPIS).flat().find(kpi => kpi.id === kpiId)?.isPercentage;
|
||||
|
||||
if (isUPFThroughput) {
|
||||
return `${value} Mbps`;
|
||||
} else if (isPercentage) {
|
||||
return `${value}%`;
|
||||
} else {
|
||||
return `${value}`;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1093,8 +1309,18 @@ const statsColumns: TableColumnType<KPIStats>[] = [
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return '';
|
||||
}
|
||||
// 关键指标多为次数类,使用累计值
|
||||
// 根据指标类型显示不同单位
|
||||
const kpiId = record.kpiId.split('_')[0];
|
||||
const isUPFThroughput = isUPFThroughputKPI(kpiId);
|
||||
const isPercentage = Object.values(CALCULATED_KPIS).flat().find(kpi => kpi.id === kpiId)?.isPercentage;
|
||||
|
||||
if (isUPFThroughput) {
|
||||
return `${value} Mbps`;
|
||||
} else if (isPercentage) {
|
||||
return `${value}%`;
|
||||
} else {
|
||||
return `${value}`;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1109,8 +1335,18 @@ const statsColumns: TableColumnType<KPIStats>[] = [
|
||||
if (value === '' || value === null || value === undefined) {
|
||||
return '';
|
||||
}
|
||||
// 关键指标多为次数类,使用累计值
|
||||
// 根据指标类型显示不同单位
|
||||
const kpiId = record.kpiId.split('_')[0];
|
||||
const isUPFThroughput = isUPFThroughputKPI(kpiId);
|
||||
const isPercentage = Object.values(CALCULATED_KPIS).flat().find(kpi => kpi.id === kpiId)?.isPercentage;
|
||||
|
||||
if (isUPFThroughput) {
|
||||
return `${value} Mbps`;
|
||||
} else if (isPercentage) {
|
||||
return `${value}%`;
|
||||
} else {
|
||||
return `${value}`;
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user