feat:关键指标统计需求修改
This commit is contained in:
@@ -225,6 +225,9 @@ const fnRealTimeSwitch = (bool: boolean) => {
|
||||
}
|
||||
chartData.value = [];
|
||||
|
||||
// 初始化统计数据表格
|
||||
fnInitKpiStatsData();
|
||||
|
||||
tableLoading.value = true;
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
@@ -609,7 +612,7 @@ const updateChart = () => {
|
||||
kpiStats.value.map(item => [
|
||||
item.title,
|
||||
selectedRows.value.length === 0 ||
|
||||
selectedRows.value.includes(item.kpiId),
|
||||
selectedRows.value.includes(item.kpiId),
|
||||
])
|
||||
),
|
||||
show: false,
|
||||
@@ -687,6 +690,9 @@ onMounted(async () => {
|
||||
await fetchSpecificKPI();
|
||||
await nextTick();
|
||||
|
||||
// 初始化统计数据表格
|
||||
fnInitKpiStatsData();
|
||||
|
||||
const container = document.getElementById('chartContainer');
|
||||
if (container && !chart) {
|
||||
chart = echarts.init(container);
|
||||
@@ -835,6 +841,9 @@ const updateChartData = (newData: ChartDataItem) => {
|
||||
};
|
||||
chart.setOption(option);
|
||||
});
|
||||
|
||||
// 更新统计数据 - 重新获取完整的30天数据
|
||||
fnGetKpiStatsData();
|
||||
} catch (error) {
|
||||
console.error('Failed to update chart:', error);
|
||||
}
|
||||
@@ -844,54 +853,154 @@ const updateChartData = (newData: ChartDataItem) => {
|
||||
interface KPIStats {
|
||||
kpiId: string;
|
||||
title: string;
|
||||
max: number;
|
||||
min: number;
|
||||
avg: number;
|
||||
total: number;
|
||||
last1Day: number | string;
|
||||
last7Days: number | string;
|
||||
last30Days: number | string;
|
||||
}
|
||||
|
||||
// 添加计算属性,用于计算每个指标的最大值和最小值
|
||||
// 添加计算属性,用于计算每个指标的统计数据
|
||||
// 将 kpiStats 从计算属性改为响应式引用
|
||||
const kpiStats = ref<KPIStats[]>([]);
|
||||
|
||||
// 添加一个计算函数来更新统计数据
|
||||
const updateKpiStats = () => {
|
||||
if (!chartData.value.length || !kpiColumns.value.length) {
|
||||
kpiStats.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
/**初始化关键指标统计表格数据 */
|
||||
function fnInitKpiStatsData() {
|
||||
// 先初始化表格,显示指标×网元的列表和默认值
|
||||
kpiStats.value = [];
|
||||
|
||||
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 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({
|
||||
kpiId: key,
|
||||
kpiId: `${kpiId}_${ne.neId}`,
|
||||
title: `${kpi.title}(${ne.neId})`,
|
||||
max: Math.max(...values),
|
||||
min: Math.min(...values),
|
||||
avg: avg,
|
||||
total: total,
|
||||
last1Day: '-', // 默认值,显示加载中状态
|
||||
last7Days: '-',
|
||||
last30Days: '-',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新图表显示
|
||||
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'),
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
width: '50%',
|
||||
width: '40%',
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.kpiOverView.totalValue'),
|
||||
dataIndex: 'total',
|
||||
key: 'total',
|
||||
width: '12%',
|
||||
title: t('views.perfManage.customTarget.ago1'),
|
||||
dataIndex: 'last1Day',
|
||||
key: 'last1Day',
|
||||
width: '20%',
|
||||
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'),
|
||||
dataIndex: 'avg',
|
||||
key: 'avg',
|
||||
width: '12%',
|
||||
title: t('views.perfManage.customTarget.ago7'),
|
||||
dataIndex: 'last7Days',
|
||||
key: 'last7Days',
|
||||
width: '20%',
|
||||
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'),
|
||||
dataIndex: 'max',
|
||||
key: 'max',
|
||||
width: '12%',
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.kpiOverView.minValue'),
|
||||
dataIndex: 'min',
|
||||
key: 'min',
|
||||
width: '12%',
|
||||
title: t('views.perfManage.customTarget.ago30'),
|
||||
dataIndex: 'last30Days',
|
||||
key: 'last30Days',
|
||||
width: '20%',
|
||||
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 => [
|
||||
item.title,
|
||||
selectedRows.value.length === 0 ||
|
||||
selectedRows.value.includes(item.kpiId),
|
||||
selectedRows.value.includes(item.kpiId),
|
||||
])
|
||||
);
|
||||
|
||||
@@ -1028,60 +1157,6 @@ const tableRowConfig = computed(() => {
|
||||
:loading="tableLoading"
|
||||
: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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user