feat:关键指标统计需求修改
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user