fix:仪表盘数据对接修改
This commit is contained in:
@@ -95,7 +95,7 @@ export function doGetCheckCode() {
|
||||
/** Get dashboard gauge data */
|
||||
export function fetchDashboardData() {
|
||||
return request<Api.Dashboard.GaugeData>({
|
||||
url: '/u/cdr/getOne',
|
||||
url: '/u/account/dashboard',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
22
src/typings/api.d.ts
vendored
22
src/typings/api.d.ts
vendored
@@ -443,18 +443,18 @@ declare namespace Api {
|
||||
namespace Dashboard {
|
||||
/** Dashboard gauge data */
|
||||
interface GaugeData {
|
||||
/** Remaining credit amount */
|
||||
remainingCredit: number;
|
||||
/** Used credit amount */
|
||||
usedCredit: number;
|
||||
/** Remaining flow amount (MB) */
|
||||
remainingFlow: number;
|
||||
/** Used flow amount (MB) */
|
||||
usedFlow: number;
|
||||
/** Current traffic rate (MB/s) */
|
||||
trafficRate: number;
|
||||
/** Peak traffic rate (MB/s) */
|
||||
/** Balance amount */
|
||||
balance: number;
|
||||
/** Total traffic amount (bytes) */
|
||||
traffic: number;
|
||||
/** Used traffic amount (bytes) */
|
||||
trafficUsed: number;
|
||||
/** Current traffic rate (B/s) */
|
||||
activity: number;
|
||||
/** Peak traffic rate (B/s) */
|
||||
peakTrafficRate: number;
|
||||
/** Number of connected devices */
|
||||
clientNum: number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ defineOptions({
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
interface GaugeData {
|
||||
// 本地界面显示用的数据类型
|
||||
interface GaugeDisplayData {
|
||||
id: number;
|
||||
title: string;
|
||||
value: number;
|
||||
@@ -24,25 +25,61 @@ interface GaugeData {
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// 添加速率单位转换函数
|
||||
const formatSpeed = (speedBps: number): { value: number; unit: string } => {
|
||||
// 处理 0 值、undefined 或 null 的情况
|
||||
if (!speedBps || speedBps === 0) {
|
||||
return { value: 0, unit: 'B/s' };
|
||||
}
|
||||
|
||||
if (speedBps < 1024) {
|
||||
return { value: Number(speedBps.toFixed(2)), unit: 'B/s' };
|
||||
} else if (speedBps < 1024 * 1024) {
|
||||
return { value: Number((speedBps / 1024).toFixed(2)), unit: 'KB/s' };
|
||||
} else if (speedBps < 1024 * 1024 * 1024) {
|
||||
return { value: Number((speedBps / (1024 * 1024)).toFixed(2)), unit: 'MB/s' };
|
||||
} else {
|
||||
return { value: Number((speedBps / (1024 * 1024 * 1024)).toFixed(2)), unit: 'GB/s' };
|
||||
}
|
||||
};
|
||||
|
||||
// 添加流量单位转换函数
|
||||
const formatTraffic = (bytes: number): { value: number; unit: string } => {
|
||||
// 处理 0 值、undefined 或 null 的情况
|
||||
if (!bytes || bytes === 0) {
|
||||
return { value: 0, unit: 'B' };
|
||||
}
|
||||
|
||||
if (bytes < 1024) {
|
||||
return { value: Number(bytes.toFixed(2)), unit: 'B' };
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return { value: Number((bytes / 1024).toFixed(2)), unit: 'KB' };
|
||||
} else if (bytes < 1024 * 1024 * 1024) {
|
||||
return { value: Number((bytes / (1024 * 1024)).toFixed(2)), unit: 'MB' };
|
||||
} else {
|
||||
return { value: Number((bytes / (1024 * 1024 * 1024)).toFixed(2)), unit: 'GB' };
|
||||
}
|
||||
};
|
||||
|
||||
// 使用 ref 来存储基础数据
|
||||
const baseData = ref([
|
||||
const baseData = ref<GaugeDisplayData[]>([
|
||||
{
|
||||
id: 0,
|
||||
title: t('page.headerbanner.Remainingcredit'),
|
||||
value: 23,
|
||||
value: 0,
|
||||
max: 100,
|
||||
unit: '元',
|
||||
description: t('page.headerbanner.monthphonebill'),
|
||||
subTitle: t('page.headerbanner.Used')+'77元'
|
||||
subTitle: t('page.headerbanner.deviceCount') + ': 0台'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: t('page.headerbanner.Flowremaining'),
|
||||
value: 890,
|
||||
value: 0,
|
||||
max: 1024,
|
||||
unit: 'MB',
|
||||
unit: 'B',
|
||||
description: t('page.headerbanner.monthflowr'),
|
||||
subTitle: t('page.headerbanner.Used')+'134MB'
|
||||
subTitle: t('page.headerbanner.Used') + ': 0B'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@@ -59,7 +96,7 @@ const baseData = ref([
|
||||
const gaugeData = computed(() => baseData.value);
|
||||
|
||||
// 仪盘配置生成函数
|
||||
const getGaugeOptions = (data: GaugeData): ECOption => ({
|
||||
const getGaugeOptions = (data: GaugeDisplayData): ECOption => ({
|
||||
backgroundColor: 'transparent',
|
||||
series: [{
|
||||
name: data.title,
|
||||
@@ -134,7 +171,7 @@ const { domRef: gauge3Ref, updateOptions: updateGauge3 } = useEcharts(() => getG
|
||||
});
|
||||
|
||||
// 更新单个图表的数据
|
||||
const updateGaugeData = (opts: ECOption, data: GaugeData) => {
|
||||
const updateGaugeData = (opts: ECOption, data: GaugeDisplayData) => {
|
||||
if (!opts.series || !Array.isArray(opts.series)) {
|
||||
opts.series = [{
|
||||
name: data.title,
|
||||
@@ -191,82 +228,97 @@ const updateGaugeData = (opts: ECOption, data: GaugeData) => {
|
||||
return opts;
|
||||
};
|
||||
|
||||
// 更新图表数据
|
||||
async function mockData() {
|
||||
updateGauge1(opts => updateGaugeData(opts, gaugeData.value[0]));
|
||||
updateGauge2(opts => updateGaugeData(opts, gaugeData.value[1]));
|
||||
updateGauge3(opts => updateGaugeData(opts, gaugeData.value[2]));
|
||||
}
|
||||
|
||||
// 更新语言
|
||||
function updateLocale() {
|
||||
updateGauge1((opts) => updateGaugeData(opts, gaugeData.value[0]));
|
||||
updateGauge2((opts) => updateGaugeData(opts, gaugeData.value[1]));
|
||||
updateGauge3((opts) => updateGaugeData(opts, gaugeData.value[2]));
|
||||
}
|
||||
|
||||
// 添加速度格式化函数
|
||||
function formatSpeed(bytesPerSecond: number): { value: number; unit: string } {
|
||||
// 处理 0 值、undefined 或 null 的情况
|
||||
if (!bytesPerSecond || bytesPerSecond === 0) {
|
||||
return { value: 0, unit: 'B/s' };
|
||||
}
|
||||
|
||||
if (bytesPerSecond < 1024) {
|
||||
return { value: Number(bytesPerSecond.toFixed(2)), unit: 'B/s' };
|
||||
} else if (bytesPerSecond < 1024 * 1024) {
|
||||
return { value: Number((bytesPerSecond / 1024).toFixed(2)), unit: 'KB/s' };
|
||||
} else if (bytesPerSecond < 1024 * 1024 * 1024) {
|
||||
return { value: Number((bytesPerSecond / (1024 * 1024)).toFixed(2)), unit: 'MB/s' };
|
||||
} else {
|
||||
return { value: Number((bytesPerSecond / (1024 * 1024 * 1024)).toFixed(2)), unit: 'GB/s' };
|
||||
}
|
||||
}
|
||||
// 添加峰值速率的 ref
|
||||
const peakTrafficRate = ref(0);
|
||||
|
||||
// 修改 mockDataUpdate 函数
|
||||
async function mockDataUpdate() {
|
||||
// 获取实际数据
|
||||
const data = await authStore.getDashboardData();
|
||||
if (data) {
|
||||
// 更新话费数据
|
||||
baseData.value[0] = {
|
||||
...baseData.value[0],
|
||||
value: data.remainingCredit,
|
||||
subTitle: t('page.headerbanner.Used') + `: ${data.usedCredit}元`
|
||||
};
|
||||
try {
|
||||
const response = await authStore.getDashboardData();
|
||||
if (response) {
|
||||
// 更新余额和设备数据
|
||||
baseData.value[0] = {
|
||||
...baseData.value[0],
|
||||
value: response.balance,
|
||||
max: Math.max(response.balance, 100),
|
||||
subTitle: t('page.headerbanner.deviceCount') + `: ${response.clientNum}台`
|
||||
};
|
||||
|
||||
// 更新流量数据
|
||||
baseData.value[1] = {
|
||||
...baseData.value[1],
|
||||
value: data.remainingFlow,
|
||||
subTitle: t('page.headerbanner.Used') + `: ${data.usedFlow}MB`
|
||||
};
|
||||
// 先计算剩余流量(字节单位)
|
||||
const totalTraffic = response.traffic; // 总流量(字节)
|
||||
const usedTraffic = response.trafficUsed; // 已用流量(字节)
|
||||
|
||||
// 格式化当前速度和峰值速度
|
||||
const currentSpeed = formatSpeed(data.trafficRate || 0);
|
||||
const peakSpeed = formatSpeed(data.peakTrafficRate || 0);
|
||||
// 计算剩余流量,确保不会出现负数
|
||||
const remainingTraffic = Math.max(0, totalTraffic - usedTraffic); // 剩余流量(字节)
|
||||
|
||||
// 设置一个最小的最大值,避免当速度为0时仪表盘显示异常
|
||||
const minMax = 1024; // 1KB/s 作为最小最大值
|
||||
const dynamicMax = Math.max(
|
||||
currentSpeed.value * 1.5,
|
||||
peakSpeed.value,
|
||||
minMax
|
||||
);
|
||||
// 计算进度比例,确保在 0-1 之间
|
||||
const progressRatio = Math.min(1, Math.max(0, remainingTraffic / totalTraffic));
|
||||
|
||||
// 更新速率数据
|
||||
baseData.value[2] = {
|
||||
...baseData.value[2],
|
||||
value: currentSpeed.value,
|
||||
unit: currentSpeed.unit,
|
||||
max: dynamicMax,
|
||||
subTitle: t('page.headerbanner.maxspeed') + `: ${peakSpeed.value}${peakSpeed.unit}`
|
||||
};
|
||||
// 格式化流量显示
|
||||
const formattedTotal = formatTraffic(totalTraffic);
|
||||
const formattedUsed = formatTraffic(usedTraffic);
|
||||
const formattedRemaining = formatTraffic(remainingTraffic);
|
||||
|
||||
// 更新表
|
||||
updateGauge1(opts => updateGaugeData(opts, baseData.value[0]));
|
||||
updateGauge2(opts => updateGaugeData(opts, baseData.value[1]));
|
||||
updateGauge3(opts => updateGaugeData(opts, baseData.value[2]));
|
||||
// 更新流量数据显示
|
||||
baseData.value[1] = {
|
||||
...baseData.value[1],
|
||||
value: formattedRemaining.value, // 仪表盘显示剩余流量
|
||||
unit: formattedRemaining.unit, // 使用转换后的单位
|
||||
max: formattedTotal.value, // 最大值为总流量
|
||||
description: `${t('page.headerbanner.monthflowr')} (${formattedTotal.value}${formattedTotal.unit})`, // 显示总流量
|
||||
subTitle: t('page.headerbanner.Used') + `: ${formattedUsed.value}${formattedUsed.unit}` // 显示已用流量
|
||||
};
|
||||
|
||||
// 更新仪表盘的进度比例
|
||||
updateGauge2(opts => {
|
||||
if (opts.series && Array.isArray(opts.series)) {
|
||||
const series = opts.series[0] as any;
|
||||
if (series.axisLine) {
|
||||
series.axisLine.lineStyle.color = [
|
||||
[progressRatio, '#4284f5'],
|
||||
[1, '#0c47a7']
|
||||
];
|
||||
}
|
||||
}
|
||||
return updateGaugeData(opts, baseData.value[1]);
|
||||
});
|
||||
|
||||
// 获取当前速率
|
||||
const currentActivity = Number(response.activity ?? 0);
|
||||
|
||||
// 更新峰值速率
|
||||
if (currentActivity > peakTrafficRate.value) {
|
||||
peakTrafficRate.value = currentActivity;
|
||||
}
|
||||
|
||||
// 格式化当前速度和峰值速度
|
||||
const currentSpeed = formatSpeed(currentActivity);
|
||||
const peakSpeed = formatSpeed(peakTrafficRate.value);
|
||||
|
||||
// 设置速率的最大值
|
||||
const minMax = 1024; // 1KB/s 作为最小最大值
|
||||
const dynamicMax = Math.max(
|
||||
currentSpeed.value * 1.5,
|
||||
peakSpeed.value,
|
||||
minMax
|
||||
);
|
||||
|
||||
// 更新速率数据
|
||||
baseData.value[2] = {
|
||||
...baseData.value[2],
|
||||
value: currentSpeed.value,
|
||||
unit: currentSpeed.unit,
|
||||
max: dynamicMax,
|
||||
subTitle: t('page.headerbanner.maxspeed') + `: ${peakSpeed.value}${peakSpeed.unit}`
|
||||
};
|
||||
|
||||
// 更新图表
|
||||
updateGauge1(opts => updateGaugeData(opts, baseData.value[0]));
|
||||
updateGauge2(opts => updateGaugeData(opts, baseData.value[1]));
|
||||
updateGauge3(opts => updateGaugeData(opts, baseData.value[2]));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch dashboard data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +327,7 @@ let timer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
// 初始化
|
||||
async function init() {
|
||||
await mockData();
|
||||
// 立即执行一次
|
||||
// 立即执行一次数据更新
|
||||
await mockDataUpdate();
|
||||
// 设置定期执行的定时器
|
||||
timer = setInterval(mockDataUpdate, 30000);
|
||||
@@ -288,18 +339,29 @@ onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
peakTrafficRate.value = 0;
|
||||
});
|
||||
|
||||
// 监听语言变化
|
||||
watch(
|
||||
() => appStore.locale,
|
||||
() => {
|
||||
updateLocale();
|
||||
//updateLocale();
|
||||
}
|
||||
);
|
||||
|
||||
// 初始化
|
||||
init();
|
||||
|
||||
// 导出更新数据的方法
|
||||
const updateDashboard = async () => {
|
||||
await mockDataUpdate();
|
||||
};
|
||||
|
||||
// 将方法暴露给父组件
|
||||
defineExpose({
|
||||
updateDashboard
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user