feat:关键指标统计需求修改

This commit is contained in:
zhongzm
2025-08-22 17:12:26 +08:00
parent 194ad023bd
commit 7e5864b97b

View File

@@ -225,6 +225,9 @@ const fnRealTimeSwitch = (bool: boolean) => {
} }
chartData.value = []; chartData.value = [];
// 初始化统计数据表格
fnInitKpiStatsData();
tableLoading.value = true; tableLoading.value = true;
const options: OptionsType = { const options: OptionsType = {
url: '/ws', url: '/ws',
@@ -609,7 +612,7 @@ const updateChart = () => {
kpiStats.value.map(item => [ kpiStats.value.map(item => [
item.title, item.title,
selectedRows.value.length === 0 || selectedRows.value.length === 0 ||
selectedRows.value.includes(item.kpiId), selectedRows.value.includes(item.kpiId),
]) ])
), ),
show: false, show: false,
@@ -687,6 +690,9 @@ onMounted(async () => {
await fetchSpecificKPI(); await fetchSpecificKPI();
await nextTick(); await nextTick();
// 初始化统计数据表格
fnInitKpiStatsData();
const container = document.getElementById('chartContainer'); const container = document.getElementById('chartContainer');
if (container && !chart) { if (container && !chart) {
chart = echarts.init(container); chart = echarts.init(container);
@@ -835,6 +841,9 @@ const updateChartData = (newData: ChartDataItem) => {
}; };
chart.setOption(option); chart.setOption(option);
}); });
// 更新统计数据 - 重新获取完整的30天数据
fnGetKpiStatsData();
} catch (error) { } catch (error) {
console.error('Failed to update chart:', error); console.error('Failed to update chart:', error);
} }
@@ -844,54 +853,154 @@ const updateChartData = (newData: ChartDataItem) => {
interface KPIStats { interface KPIStats {
kpiId: string; kpiId: string;
title: string; title: string;
max: number; last1Day: number | string;
min: number; last7Days: number | string;
avg: number; last30Days: number | string;
total: number;
} }
// 添加计算属性,用于计算每个指标的最大值和最小值 // 添加计算属性,用于计算每个指标的统计数据
// 将 kpiStats 从计算属性改为响应式引用 // 将 kpiStats 从计算属性改为响应式引用
const kpiStats = ref<KPIStats[]>([]); const kpiStats = ref<KPIStats[]>([]);
// 添加一个计算函数来更新统计数据 /**初始化关键指标统计表格数据 */
const updateKpiStats = () => { function fnInitKpiStatsData() {
if (!chartData.value.length || !kpiColumns.value.length) { // 先初始化表格,显示指标×网元的列表和默认值
kpiStats.value = [];
return;
}
kpiStats.value = []; kpiStats.value = [];
for (const neType of ALL_NE_TYPES) { for (const neType of ALL_NE_TYPES) {
for (const ne of neList.value[neType]) { for (const ne of neList.value[neType]) {
for (const kpiId of TARGET_KPI_IDS[neType]) { for (const kpiId of TARGET_KPI_IDS[neType]) {
const kpi = kpiColumns.value.find(col => col.kpiId === kpiId); const kpi = kpiColumns.value.find(col => col.kpiId === kpiId);
if (!kpi) continue; if (!kpi) continue;
const key = `${kpiId}_${ne.neId}`;
const values = chartData.value.map(item => Number(item[key]) || 0);
if (values.length === 0) continue;
const total = Number(
values.reduce((sum, val) => sum + val, 0).toFixed(2)
);
const avg = Number((total / values.length).toFixed(2));
kpiStats.value.push({ kpiStats.value.push({
kpiId: key, kpiId: `${kpiId}_${ne.neId}`,
title: `${kpi.title}(${ne.neId})`, title: `${kpi.title}(${ne.neId})`,
max: Math.max(...values), last1Day: '-', // 默认值,显示加载中状态
min: Math.min(...values), last7Days: '-',
avg: avg, last30Days: '-',
total: total,
}); });
} }
} }
} }
}
// 更新图表显示 /**获取关键指标近期统计数据 */
updateChartLegendSelect(); async function fnGetKpiStatsData() {
if (!kpiColumns.value.length) {
return;
}
const now = new Date();
const now_ms = now.getTime();
const day1_start = now_ms - (1 * 24 * 60 * 60 * 1000); // 1天前
const day7_start = now_ms - (7 * 24 * 60 * 60 * 1000); // 7天前
const day30_start = now_ms - (30 * 24 * 60 * 60 * 1000); // 30天前
try {
// 为每个网元的每个指标分别获取近30天的数据
for (const neType of ALL_NE_TYPES) {
for (const ne of neList.value[neType]) {
// 请求近30天的数据
const params = {
neType,
neId: ne.neId,
startTime: String(day30_start),
endTime: String(now_ms),
sortField: 'timeGroup',
sortOrder: 'asc',
interval: 60 * 15,
kpiIds: TARGET_KPI_IDS[neType].join(','),
};
try {
const res = await listKPIData(params);
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
// 为每个指标计算统计值
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 data1Day = res.data.filter((item: any) => {
const itemTime = Number(item.timeGroup);
const value = item[kpiId] ? Number(item[kpiId]) : 0;
return itemTime >= day1_start && value !== 0;
});
const data7Days = res.data.filter((item: any) => {
const itemTime = Number(item.timeGroup);
const value = item[kpiId] ? Number(item[kpiId]) : 0;
return itemTime >= day7_start && value !== 0;
});
const data30Days = res.data.filter((item: any) => {
const itemTime = Number(item.timeGroup);
const value = item[kpiId] ? Number(item[kpiId]) : 0;
return itemTime >= day30_start && 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));
};
// 更新对应的统计数据
const statsIndex = kpiStats.value.findIndex((item: any) => item.kpiId === key);
if (statsIndex !== -1) {
kpiStats.value[statsIndex].last1Day = calculateValue(data1Day);
kpiStats.value[statsIndex].last7Days = calculateValue(data7Days);
kpiStats.value[statsIndex].last30Days = calculateValue(data30Days);
}
}
}
} catch (error) {
console.error(`获取网元${ne.neId}统计数据失败:`, error);
// 如果获取失败,保持默认值
for (const kpiId of TARGET_KPI_IDS[neType]) {
const key = `${kpiId}_${ne.neId}`;
const statsIndex = kpiStats.value.findIndex((item: any) => item.kpiId === key);
if (statsIndex !== -1) {
kpiStats.value[statsIndex].last1Day = '-';
kpiStats.value[statsIndex].last7Days = '-';
kpiStats.value[statsIndex].last30Days = '-';
}
}
}
}
}
// 更新图表显示
updateChartLegendSelect();
} catch (error) {
console.error('获取统计数据失败:', error);
// 如果获取失败,保持默认值
for (const statsItem of kpiStats.value) {
statsItem.last1Day = '-';
statsItem.last7Days = '-';
statsItem.last30Days = '-';
}
}
}
// 添加一个计算函数来更新统计数据(保持向后兼容)
const updateKpiStats = () => {
if (!kpiColumns.value.length) {
kpiStats.value = [];
return;
}
// 初始化统计数据
fnInitKpiStatsData();
// 获取统计数据
fnGetKpiStatsData();
}; };
// 添加表列定义 // 添加表列定义
@@ -917,35 +1026,55 @@ const statsColumns: TableColumnType<KPIStats>[] = [
title: t('views.perfManage.kpiOverView.kpiName'), title: t('views.perfManage.kpiOverView.kpiName'),
dataIndex: 'title', dataIndex: 'title',
key: 'title', key: 'title',
width: '50%', width: '40%',
}, },
{ {
title: t('views.perfManage.kpiOverView.totalValue'), title: t('views.perfManage.customTarget.ago1'),
dataIndex: 'total', dataIndex: 'last1Day',
key: 'total', key: 'last1Day',
width: '12%', width: '20%',
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
customRender: ({ record }: { record: KPIStats }) => {
const value = record.last1Day;
// 如果是默认值,直接显示
if (value === '-') {
return value;
}
// 关键指标多为次数类,使用累计值
return `${value} ${t('views.perfManage.customTarget.total')}`;
},
}, },
{ {
title: t('views.perfManage.kpiOverView.avgValue'), title: t('views.perfManage.customTarget.ago7'),
dataIndex: 'avg', dataIndex: 'last7Days',
key: 'avg', key: 'last7Days',
width: '12%', width: '20%',
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
customRender: ({ record }: { record: KPIStats }) => {
const value = record.last7Days;
// 如果是默认值,直接显示
if (value === '-') {
return value;
}
// 关键指标多为次数类,使用累计值
return `${value} ${t('views.perfManage.customTarget.total')}`;
},
}, },
{ {
title: t('views.perfManage.kpiOverView.maxValue'), title: t('views.perfManage.customTarget.ago30'),
dataIndex: 'max', dataIndex: 'last30Days',
key: 'max', key: 'last30Days',
width: '12%', width: '20%',
sortDirections: ['ascend', 'descend'],
},
{
title: t('views.perfManage.kpiOverView.minValue'),
dataIndex: 'min',
key: 'min',
width: '12%',
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
customRender: ({ record }: { record: KPIStats }) => {
const value = record.last30Days;
// 如果是默认值,直接显示
if (value === '-') {
return value;
}
// 关键指标多为次数类,使用累计值
return `${value} ${t('views.perfManage.customTarget.total')}`;
},
}, },
]; ];
@@ -974,7 +1103,7 @@ const updateChartLegendSelect = () => {
kpiStats.value.map(item => [ kpiStats.value.map(item => [
item.title, item.title,
selectedRows.value.length === 0 || selectedRows.value.length === 0 ||
selectedRows.value.includes(item.kpiId), selectedRows.value.includes(item.kpiId),
]) ])
); );
@@ -1028,60 +1157,6 @@ const tableRowConfig = computed(() => {
:loading="tableLoading" :loading="tableLoading"
:custom-row="tableRowConfig" :custom-row="tableRowConfig"
> >
<template #headerCell="{ column }">
<template v-if="column.key === 'total'">
<span>
{{ t('views.perfManage.kpiOverView.totalValue') }}
<a-tooltip placement="bottom">
<template #title>
<span>
{{ t('views.perfManage.kpiOverView.totalValueTip') }}
</span>
</template>
<InfoCircleOutlined />
</a-tooltip>
</span>
</template>
<template v-if="column.key === 'avg'">
<span>
{{ t('views.perfManage.kpiOverView.avgValue') }}
<a-tooltip placement="bottom">
<template #title>
<span>
{{ t('views.perfManage.kpiOverView.avgValueTip') }}
</span>
</template>
<InfoCircleOutlined />
</a-tooltip>
</span>
</template>
<template v-if="column.key === 'max'">
<span>
{{ t('views.perfManage.kpiOverView.maxValue') }}
<a-tooltip placement="bottom">
<template #title>
<span>
{{ t('views.perfManage.kpiOverView.maxValueTip') }}
</span>
</template>
<InfoCircleOutlined />
</a-tooltip>
</span>
</template>
<template v-if="column.key === 'min'">
<span>
{{ t('views.perfManage.kpiOverView.minValue') }}
<a-tooltip placement="bottom">
<template #title>
<span>
{{ t('views.perfManage.kpiOverView.minValueTip') }}
</span>
</template>
<InfoCircleOutlined />
</a-tooltip>
</span>
</template>
</template>
</a-table> </a-table>
</div> </div>
</div> </div>