From 98e4d39cdfc9dedfc39797a48e4e4b957405576f Mon Sep 17 00:00:00 2001 From: zhongzm Date: Fri, 19 Sep 2025 09:18:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B5=81=E9=87=8F=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96MB=E3=80=81GB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/traffic-utils.ts | 114 +++++++++++++++++++++++++++ src/views/dashboard/smfCDR/index.vue | 31 ++++---- 2 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 src/utils/traffic-utils.ts diff --git a/src/utils/traffic-utils.ts b/src/utils/traffic-utils.ts new file mode 100644 index 00000000..7ef574d5 --- /dev/null +++ b/src/utils/traffic-utils.ts @@ -0,0 +1,114 @@ +/** + * 流量数据转换工具类 + * 提供字节(byte)到MB/GB的转换功能 + */ + +/** + * 流量转换结果类型 + */ +export interface TrafficConversionResult { + /** 转换后的数值 */ + value: number; + /** 单位 */ + unit: 'MB' | 'GB'; + /** 格式化后的字符串 */ + formatted: string; +} + +/** + * 将字节转换为MB或GB + * @param bytes 字节数 + * @param precision 小数点精度,默认为2位 + * @returns 转换结果对象 + */ +export function convertBytesToTraffic(bytes: number | string, precision: number = 2): TrafficConversionResult { + // 处理输入参数 + const numBytes = typeof bytes === 'string' ? parseFloat(bytes) : bytes; + + // 处理无效输入 + if (isNaN(numBytes) || numBytes < 0) { + return { + value: 0, + unit: 'MB', + formatted: '0 MB' + }; + } + + // 转换常量 + const MB = 1024 * 1024; // 1MB = 1024 * 1024 bytes + const GB = 1024 * 1024 * 1024; // 1GB = 1024 * 1024 * 1024 bytes + + // 如果大于等于1GB,转换为GB + if (numBytes >= GB) { + const value = parseFloat((numBytes / GB).toFixed(precision)); + return { + value, + unit: 'GB', + formatted: `${value} GB` + }; + } + + // 否则转换为MB(包括KB也转换为MB) + const value = parseFloat((numBytes / MB).toFixed(precision)); + return { + value, + unit: 'MB', + formatted: `${value} MB` + }; +} + +/** + * 批量转换流量数据 + * @param dataList 包含流量字段的数据数组 + * @param fields 需要转换的字段名数组 + * @param precision 小数点精度,默认为2位 + * @returns 转换后的数据数组 + */ +export function convertTrafficFields( + dataList: Record[], + fields: string[], + precision: number = 2 +): Record[] { + return dataList.map(item => { + const convertedItem = { ...item }; + + fields.forEach(field => { + if (item[field] !== undefined && item[field] !== null) { + const conversion = convertBytesToTraffic(item[field], precision); + convertedItem[`${field}_converted`] = conversion; + } + }); + + return convertedItem; + }); +} + +/** + * 格式化流量显示(简化版本,直接返回格式化字符串) + * @param bytes 字节数 + * @param precision 小数点精度,默认为2位 + * @returns 格式化后的流量字符串 + */ +export function formatTraffic(bytes: number | string, precision: number = 2): string { + return convertBytesToTraffic(bytes, precision).formatted; +} + +/** + * 计算总流量(上行+下行) + * @param uplink 上行流量(字节) + * @param downlink 下行流量(字节) + * @param precision 小数点精度,默认为2位 + * @returns 总流量的转换结果 + */ +export function calculateTotalTraffic( + uplink: number | string, + downlink: number | string, + precision: number = 2 +): TrafficConversionResult { + const uplinkBytes = typeof uplink === 'string' ? parseFloat(uplink) : uplink; + const downlinkBytes = typeof downlink === 'string' ? parseFloat(downlink) : downlink; + + const totalBytes = (isNaN(uplinkBytes) ? 0 : uplinkBytes) + (isNaN(downlinkBytes) ? 0 : downlinkBytes); + + return convertBytesToTraffic(totalBytes, precision); +} diff --git a/src/views/dashboard/smfCDR/index.vue b/src/views/dashboard/smfCDR/index.vue index a466b599..0b0fecf2 100644 --- a/src/views/dashboard/smfCDR/index.vue +++ b/src/views/dashboard/smfCDR/index.vue @@ -21,6 +21,7 @@ import PQueue from 'p-queue'; import saveAs from 'file-saver'; import dayjs, { type Dayjs } from 'dayjs'; import { useClipboard } from '@vueuse/core'; +import { formatTraffic } from '@/utils/traffic-utils'; const { copy } = useClipboard({ legacy: true }); const { t } = useI18n(); const neListStore = useNeListStore(); @@ -155,7 +156,7 @@ let tableColumns = ref([ !Array.isArray(listOfMultipleUnitUsage) || listOfMultipleUnitUsage.length < 1 ) { - return 0; + return formatTraffic(0); } let dataVolumeUplink = 0; for (const v of listOfMultipleUnitUsage) { @@ -165,7 +166,7 @@ let tableColumns = ref([ } } } - return dataVolumeUplink; + return formatTraffic(dataVolumeUplink); }, }, { @@ -180,7 +181,7 @@ let tableColumns = ref([ !Array.isArray(listOfMultipleUnitUsage) || listOfMultipleUnitUsage.length < 1 ) { - return 0; + return formatTraffic(0); } let dataVolumeDownlink = 0; for (const v of listOfMultipleUnitUsage) { @@ -190,7 +191,7 @@ let tableColumns = ref([ } } } - return dataVolumeDownlink; + return formatTraffic(dataVolumeDownlink); }, }, { @@ -205,7 +206,7 @@ let tableColumns = ref([ !Array.isArray(listOfMultipleUnitUsage) || listOfMultipleUnitUsage.length < 1 ) { - return 0; + return formatTraffic(0); } let dataTotalVolume = 0; for (const v of listOfMultipleUnitUsage) { @@ -215,7 +216,7 @@ let tableColumns = ref([ } } } - return dataTotalVolume; + return formatTraffic(dataTotalVolume); }, }, { @@ -812,15 +813,15 @@ onBeforeUnmount(() => {
Data Total Volume: - {{ udata.dataTotalVolume }} + {{ formatTraffic(udata.dataTotalVolume || 0) }}
Data Volume Downlink: - {{ udata.dataVolumeDownlink }} + {{ formatTraffic(udata.dataVolumeDownlink || 0) }}
Data Volume Uplink: - {{ udata.dataVolumeUplink }} + {{ formatTraffic(udata.dataVolumeUplink || 0) }}