From 88aea40885fb39c686739ef79581ef204ce762cb Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 17 Jun 2025 20:02:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20kpi=E8=8F=9C=E5=8D=95=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E9=A2=84=E8=AE=BE1h/1d/7d/15d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/i18n/locales/en-US.ts | 9 +- src/i18n/locales/zh-CN.ts | 9 +- src/views/perfManage/goldTarget/index.vue | 193 ++++++++++++++------ src/views/perfManage/kpiCReport/index.vue | 37 +++- src/views/perfManage/kpiKeyTarget/index.vue | 37 +++- src/views/perfManage/kpiOverView/index.vue | 108 ++++++----- 6 files changed, 267 insertions(+), 126 deletions(-) diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 30397ea9..5f6da6c0 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -1001,8 +1001,13 @@ export default { expression:'Expression', description:' Description', kpiSet:' Statistical Settings', - sixHoursAgo:'Six hours ago', - threeHoursAgo:'Three hours ago', + new1Hour:'Within current hour', + ago1Hour:'Last 1 hour', + ago3Hour:'Last 3 hour', + ago6Hour:'Last 6 hour', + ago1Day:'Last 1 day', + ago7Day:'Last 7 day', + ago15Day:'Last 15 day', delCustomTip:'Confirm deletion of data item with record Custom Indicator {num}?', delCustom:' Successfully delete record number {num} custom indicator', addCustom:' Add custom indicator', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 9e0a5350..9c42fcd7 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -1001,8 +1001,13 @@ export default { expression:'计算公式', description:'描述', kpiSet:'统计设置', - sixHoursAgo:'6小时前', - threeHoursAgo:'3小时前', + new1Hour:'当前小时内', + ago1Hour:'过去1小时', + ago3Hour:'过去3小时', + ago6Hour:'过去6小时', + ago1Day:'过去1天', + ago7Day:'过去7天', + ago15Day:'过去15天', delCustomTip:'确认删除自定义指标项为 {num} 的数据项?', delCustom:'成功删除记录编号为 {num} 自定义指标', addCustom:'添加自定义指标', diff --git a/src/views/perfManage/goldTarget/index.vue b/src/views/perfManage/goldTarget/index.vue index 297ce986..0404a76d 100644 --- a/src/views/perfManage/goldTarget/index.vue +++ b/src/views/perfManage/goldTarget/index.vue @@ -83,6 +83,40 @@ let neCascaderOptions = ref[]>([]); /**记录开始结束时间 */ let queryRangePicker = ref<[string, string]>(['', '']); +//日期快捷选择 +const ranges = ref([ + { + label: t('views.perfManage.customTarget.new1Hour'), + value: [dayjs().startOf('day'), dayjs()], + }, + { + label: t('views.perfManage.customTarget.ago1Hour'), + value: [dayjs().subtract(1, 'hour').startOf('hour'), dayjs().endOf('hour')], + }, + // { + // label: t('views.perfManage.customTarget.ago3Hour'), + // value: [dayjs().subtract(3, 'hours'), dayjs()], + // }, + // { + // label: t('views.perfManage.customTarget.ago6Hour'), + // value: [dayjs().subtract(6, 'hours'), dayjs()], + // }, + { + label: t('views.perfManage.customTarget.ago1Day'), + value: [ + dayjs().subtract(1, 'day').startOf('day'), + dayjs().subtract(1, 'day'), + ], + }, + { + label: t('views.perfManage.customTarget.ago7Day'), + value: [dayjs().subtract(7, 'day').startOf('day'), dayjs()], + }, + { + label: t('views.perfManage.customTarget.ago15Day'), + value: [dayjs().subtract(15, 'day').startOf('day'), dayjs()], + }, +]); /**表格字段列 */ let tableColumns = ref([]); @@ -145,7 +179,7 @@ function fnTableSize({ key }: MenuInfo) { } /**选中的网元信息 */ -let selectedNes = ref<{neType: string, neId: string}[]>([]); +let selectedNes = ref<{ neType: string; neId: string }[]>([]); /**查询参数 */ let queryParams: any = reactive({ @@ -314,7 +348,7 @@ function fnRecordExport() { } /**可选网元列表 */ -let availableNeIds = ref<{label: string, value: string}[]>([]); +let availableNeIds = ref<{ label: string; value: string }[]>([]); // 添加类型定义 interface KPIStats { @@ -330,7 +364,10 @@ interface KPIStats { } /**处理网元类型变化 */ -function handleNeTypeChange(value: SelectValue, option: DefaultOptionType | DefaultOptionType[]) { +function handleNeTypeChange( + value: SelectValue, + option: DefaultOptionType | DefaultOptionType[] +) { if (!value) { state.neType = ''; state.neIds = []; @@ -343,11 +380,17 @@ function handleNeTypeChange(value: SelectValue, option: DefaultOptionType | Defa state.neIds = []; // 清空已选网元 // 根据选择的网元类型更新可选的网元ID列表 - const neTypeOption = neCascaderOptions.value.find(item => item.value === value); - if (neTypeOption && neTypeOption.children && neTypeOption.children.length > 0) { + const neTypeOption = neCascaderOptions.value.find( + item => item.value === value + ); + if ( + neTypeOption && + neTypeOption.children && + neTypeOption.children.length > 0 + ) { availableNeIds.value = neTypeOption.children.map((ne: any) => ({ label: `${ne.label}`, - value: ne.neId + value: ne.neId, })); // 默认选择第一个网元 @@ -361,7 +404,10 @@ function handleNeTypeChange(value: SelectValue, option: DefaultOptionType | Defa } /**处理网元ID变化 */ -function handleNeIdsChange(value: SelectValue, option: DefaultOptionType | DefaultOptionType[]) { +function handleNeIdsChange( + value: SelectValue, + option: DefaultOptionType | DefaultOptionType[] +) { if (!value || (Array.isArray(value) && value.length === 0)) { state.neIds = []; queryParams.neIds = []; @@ -370,12 +416,12 @@ function handleNeIdsChange(value: SelectValue, option: DefaultOptionType | Defau const values = Array.isArray(value) ? value : [value]; state.neIds = values as string[]; - queryParams.neIds = [...values as string[]]; + queryParams.neIds = [...(values as string[])]; // 更新选中的网元信息 selectedNes.value = (values as string[]).map(neId => ({ neType: state.neType, - neId: neId + neId: neId, })); } @@ -458,7 +504,7 @@ async function fnGetList() { ...queryParams, neId: neId, startTime: queryRangePicker.value[0], - endTime: queryRangePicker.value[1] + endTime: queryRangePicker.value[1], }; // 不需要将neIds发送到后端 delete params.neIds; @@ -469,7 +515,7 @@ async function fnGetList() { return res.data.map(item => ({ ...item, _neId: neId, - neName: `${state.neType}-${neId}` + neName: `${state.neType}-${neId}`, })); } return []; @@ -519,7 +565,7 @@ async function fnGetList() { values.length > 0 ? Number((total / values.length).toFixed(2)) : 0; kpiStats.value.push({ - kpiId: `${columns.key}_${neId}`, // 使用组合ID来唯一标识指标-网元对 + kpiId: `${columns.key}_${neId}`, // 使用组合ID来唯一标识指标-网元对 title: `${columns.title}(${neId})`, // 在标题中显示网元ID rawKpiId: columns.key, rawKpiTitle: columns.title, @@ -564,16 +610,19 @@ function fnRanderChart() { return [pt[0], '10%']; }, confine: true, // 限制 tooltip 显示范围 - backgroundColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? 'rgba(48, 48, 48, 0.8)' - : 'rgba(255, 255, 255, 0.9)', - borderColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#555' - : '#ddd', + backgroundColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? 'rgba(48, 48, 48, 0.8)' + : 'rgba(255, 255, 255, 0.9)', + borderColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#555' + : '#ddd', textStyle: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, }, xAxis: { @@ -582,9 +631,10 @@ function fnRanderChart() { boundaryGap: false, data: [], // 数据x轴 axisLabel: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitLine: { show: true, @@ -599,9 +649,10 @@ function fnRanderChart() { boundaryGap: [0, '100%'], axisLabel: { formatter: '{value}', - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitNumber: 5, scale: true, @@ -719,7 +770,9 @@ function fnRanderChartData() { } // 获取所有时间点并格式化 - const timePoints = [...new Set(tableState.data.map(item => item.timeGroup))].sort(); + const timePoints = [ + ...new Set(tableState.data.map(item => item.timeGroup)), + ].sort(); chartDataXAxisData = timePoints.map(time => parseDateToStr(+time)); // 填充数据 @@ -755,7 +808,10 @@ function fnRanderChartData() { type: 'category', boundaryGap: false, axisLabel: { - color: document.documentElement.getAttribute('data-theme') === 'dark' ? '#CACADA' : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitLine: { show: true, @@ -808,16 +864,19 @@ function fnRealTimeSwitch(bool: any) { return [pt[0], '10%']; }, confine: true, - backgroundColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? 'rgba(48, 48, 48, 0.8)' - : 'rgba(255, 255, 255, 0.9)', - borderColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#555' - : '#ddd', + backgroundColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? 'rgba(48, 48, 48, 0.8)' + : 'rgba(255, 255, 255, 0.9)', + borderColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#555' + : '#ddd', textStyle: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, }, xAxis: { @@ -825,9 +884,10 @@ function fnRealTimeSwitch(bool: any) { boundaryGap: false, data: [], axisLabel: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitLine: { show: true, @@ -841,9 +901,10 @@ function fnRealTimeSwitch(bool: any) { boundaryGap: [0, '100%'], axisLabel: { formatter: '{value}', - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitNumber: 5, scale: true, @@ -887,7 +948,9 @@ function fnRealTimeSwitch(bool: any) { * 指标(GroupID:10_neType_neId) * 为所有选中的网元创建订阅 */ - subGroupID: state.neIds.map(neId => `10_${state.neType}_${neId}`).join(','), + subGroupID: state.neIds + .map(neId => `10_${state.neType}_${neId}`) + .join(','), }, onmessage: wsMessage, onerror: wsError, @@ -1036,7 +1099,10 @@ function wsMessage(res: Record) { type: 'category', boundaryGap: false, axisLabel: { - color: document.documentElement.getAttribute('data-theme') === 'dark' ? '#CACADA' : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, splitLine: { show: true, @@ -1213,7 +1279,9 @@ function handleSearch() { // 检查是否选择了网元类型和网元ID if (!state.neType) { message.warning({ - content: t('views.perfManage.goldTarget.selectNeTypeFirst') || '请先选择网元类型', + content: + t('views.perfManage.goldTarget.selectNeTypeFirst') || + '请先选择网元类型', duration: 2, }); return; @@ -1221,7 +1289,9 @@ function handleSearch() { if (state.neIds.length === 0) { message.warning({ - content: t('views.perfManage.goldTarget.selectNeIdsFirst') || '请选择至少一个网元', + content: + t('views.perfManage.goldTarget.selectNeIdsFirst') || + '请选择至少一个网元', duration: 2, }); return; @@ -1270,17 +1340,19 @@ onMounted(() => { // 获取该类型下的网元ID列表 availableNeIds.value = item.children.map((ne: any) => ({ label: `${ne.label}`, - value: ne.neId + value: ne.neId, })); // 默认选择第一个网元 const info = item.children[0]; state.neIds = [info.neId]; queryParams.neIds = [info.neId]; - selectedNes.value = [{ - neType: item.value, - neId: info.neId - }]; + selectedNes.value = [ + { + neType: item.value, + neId: info.neId, + }, + ]; } else { const item = neCascaderOptions.value[0]; state.neType = item.value; @@ -1289,17 +1361,19 @@ onMounted(() => { // 获取该类型下的网元ID列表 availableNeIds.value = item.children.map((ne: any) => ({ label: `${ne.label}`, - value: ne.neId + value: ne.neId, })); // 默认选择第一个网元 const info = item.children[0]; state.neIds = [info.neId]; queryParams.neIds = [info.neId]; - selectedNes.value = [{ - neType: item.value, - neId: info.neId - }]; + selectedNes.value = [ + { + neType: item.value, + neId: info.neId, + }, + ]; } // 查询当前小时 @@ -1353,7 +1427,7 @@ onBeforeUnmount(() => { @change="handleNeTypeChange" :field-names="{ label: 'label', - value: 'value' + value: 'value', }" :allow-clear="false" /> @@ -1380,6 +1454,7 @@ onBeforeUnmount(() => { (['', '']); /**时间选择 */ const ranges = ref([ { - label: t('views.perfManage.customTarget.sixHoursAgo'), - value: [dayjs().subtract(6, 'hours'), dayjs()], - }, - { - label: t('views.perfManage.customTarget.threeHoursAgo'), - value: [dayjs().subtract(3, 'hours'), dayjs()], - }, - { - label: t('views.monitor.monitor.today'), + label: t('views.perfManage.customTarget.new1Hour'), value: [dayjs().startOf('day'), dayjs()], }, + { + label: t('views.perfManage.customTarget.ago1Hour'), + value: [dayjs().subtract(1, 'hour').startOf('hour'), dayjs().endOf('hour')], + }, + // { + // label: t('views.perfManage.customTarget.ago3Hour'), + // value: [dayjs().subtract(3, 'hours'), dayjs()], + // }, + // { + // label: t('views.perfManage.customTarget.ago6Hour'), + // value: [dayjs().subtract(6, 'hours'), dayjs()], + // }, + { + label: t('views.perfManage.customTarget.ago1Day'), + value: [ + dayjs().subtract(1, 'day').startOf('day'), + dayjs().subtract(1, 'day'), + ], + }, + { + label: t('views.perfManage.customTarget.ago7Day'), + value: [dayjs().subtract(7, 'day').startOf('day'), dayjs()], + }, + { + label: t('views.perfManage.customTarget.ago15Day'), + value: [dayjs().subtract(15, 'day').startOf('day'), dayjs()], + }, ]); /**表格字段列 */ diff --git a/src/views/perfManage/kpiKeyTarget/index.vue b/src/views/perfManage/kpiKeyTarget/index.vue index 2aa67c6d..50a09ed4 100644 --- a/src/views/perfManage/kpiKeyTarget/index.vue +++ b/src/views/perfManage/kpiKeyTarget/index.vue @@ -36,17 +36,36 @@ const neInfoStore = useNeInfoStore(); //日期快捷选择 const ranges = ref([ { - label: t('views.perfManage.customTarget.sixHoursAgo'), - value: [dayjs().subtract(6, 'hours'), dayjs()], - }, - { - label: t('views.perfManage.customTarget.threeHoursAgo'), - value: [dayjs().subtract(3, 'hours'), dayjs()], - }, - { - label: t('views.monitor.monitor.today'), + label: t('views.perfManage.customTarget.new1Hour'), value: [dayjs().startOf('day'), dayjs()], }, + { + label: t('views.perfManage.customTarget.ago1Hour'), + value: [dayjs().subtract(1, 'hour').startOf('hour'), dayjs().endOf('hour')], + }, + // { + // label: t('views.perfManage.customTarget.ago3Hour'), + // value: [dayjs().subtract(3, 'hours'), dayjs()], + // }, + // { + // label: t('views.perfManage.customTarget.ago6Hour'), + // value: [dayjs().subtract(6, 'hours'), dayjs()], + // }, + { + label: t('views.perfManage.customTarget.ago1Day'), + value: [ + dayjs().subtract(1, 'day').startOf('day'), + dayjs().subtract(1, 'day'), + ], + }, + { + label: t('views.perfManage.customTarget.ago7Day'), + value: [dayjs().subtract(7, 'day').startOf('day'), dayjs()], + }, + { + label: t('views.perfManage.customTarget.ago15Day'), + value: [dayjs().subtract(15, 'day').startOf('day'), dayjs()], + }, ]); //WebSocket连接 const ws = ref(null); diff --git a/src/views/perfManage/kpiOverView/index.vue b/src/views/perfManage/kpiOverView/index.vue index b9d5b75a..5181e5a0 100644 --- a/src/views/perfManage/kpiOverView/index.vue +++ b/src/views/perfManage/kpiOverView/index.vue @@ -58,30 +58,38 @@ echarts.use([ const ws = ref(null); //时间选择 -// let ranges = ref>({ -// [t('views.perfManage.customTarget.sixHoursAgo')]: [ -// dayjs().subtract(6, 'hours'), -// dayjs(), -// ], -// [t('views.perfManage.customTarget.threeHoursAgo')]: [ -// dayjs().subtract(3, 'hours'), -// dayjs(), -// ], -// [t('views.monitor.monitor.today')]: [dayjs().startOf('day'), dayjs()], -// }); const ranges = ref([ { - label: t('views.perfManage.customTarget.sixHoursAgo'), - value: [dayjs().subtract(6, 'hours'), dayjs()], - }, - { - label: t('views.perfManage.customTarget.threeHoursAgo'), - value: [dayjs().subtract(3, 'hours'), dayjs()], - }, - { - label: t('views.monitor.monitor.today'), + label: t('views.perfManage.customTarget.new1Hour'), value: [dayjs().startOf('day'), dayjs()], }, + { + label: t('views.perfManage.customTarget.ago1Hour'), + value: [dayjs().subtract(1, 'hour').startOf('hour'), dayjs().endOf('hour')], + }, + // { + // label: t('views.perfManage.customTarget.ago3Hour'), + // value: [dayjs().subtract(3, 'hours'), dayjs()], + // }, + // { + // label: t('views.perfManage.customTarget.ago6Hour'), + // value: [dayjs().subtract(6, 'hours'), dayjs()], + // }, + { + label: t('views.perfManage.customTarget.ago1Day'), + value: [ + dayjs().subtract(1, 'day').startOf('day'), + dayjs().subtract(1, 'day'), + ], + }, + { + label: t('views.perfManage.customTarget.ago7Day'), + value: [dayjs().subtract(7, 'day').startOf('day'), dayjs()], + }, + { + label: t('views.perfManage.customTarget.ago15Day'), + value: [dayjs().subtract(15, 'day').startOf('day'), dayjs()], + }, ]); //日期范围响应式变量 const dateRange = ref<[string, string]>([ @@ -152,10 +160,10 @@ const KPI_TITLE: Record = { const neInfoStore = useNeInfoStore(); // 添加网元列表相关变量 -const neList = ref>({ +const neList = ref>({ AMF: [], UPF: [], - IMS: [] + IMS: [], }); // 添加获取网元列表的函数 @@ -174,7 +182,7 @@ const fetchNeList = async () => { if (ALL_NE_TYPES.includes(neType)) { neList.value[neType].push({ neId: ne.neId, - neName: ne.neName + neName: ne.neName, }); } }); @@ -324,7 +332,7 @@ const fetchChartData = async () => { return res.data.map(item => ({ ...item, _neId: ne.neId, - neName: `${neType}-${ne.neId}` + neName: `${neType}-${ne.neId}`, })); } return []; @@ -551,24 +559,28 @@ const updateChart = () => { left: 'center', // 添加文字颜色配置,根据主题切换 textStyle: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, }, tooltip: { trigger: 'axis', confine: true, - backgroundColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? 'rgba(48, 48, 48, 0.8)' - : 'rgba(255, 255, 255, 0.9)', - borderColor: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#555' - : '#ddd', + backgroundColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? 'rgba(48, 48, 48, 0.8)' + : 'rgba(255, 255, 255, 0.9)', + borderColor: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#555' + : '#ddd', textStyle: { - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);', }, @@ -583,7 +595,8 @@ const updateChart = () => { selected: Object.fromEntries( kpiStats.value.map(item => [ item.title, - selectedRows.value.length === 0 || selectedRows.value.includes(item.kpiId) + selectedRows.value.length === 0 || + selectedRows.value.includes(item.kpiId), ]) ), show: false, @@ -606,7 +619,7 @@ const updateChart = () => { dayjs(Number(item.date)).format('YYYY-MM-DD HH:mm:ss') ), axisLabel: { - // formatter: '{value}', + // formatter: '{value}', color: document.documentElement.getAttribute('data-theme') === 'dark' ? '#CACADA' @@ -623,9 +636,10 @@ const updateChart = () => { type: 'value', axisLabel: { formatter: '{value}', - color: document.documentElement.getAttribute('data-theme') === 'dark' - ? '#CACADA' - : '#333', + color: + document.documentElement.getAttribute('data-theme') === 'dark' + ? '#CACADA' + : '#333', }, // 添加自计算的分割段数 splitNumber: 5, @@ -642,7 +656,8 @@ const updateChart = () => { }; if (chart) { requestAnimationFrame(() => { - if (chart) { // 添加额外的空值检查 + if (chart) { + // 添加额外的空值检查 chart.setOption(option, true); chart.resize(); } @@ -729,7 +744,7 @@ const fetchSpecificKPI = async () => { key: item.kpiId, kpiId: item.kpiId, neType: neType, - } + }; }); allKPIs = [...allKPIs, ...filteredKPIs]; @@ -845,7 +860,9 @@ const updateKpiStats = () => { if (values.length === 0) continue; - const total = Number(values.reduce((sum, val) => sum + val, 0).toFixed(2)); + const total = Number( + values.reduce((sum, val) => sum + val, 0).toFixed(2) + ); const avg = Number((total / values.length).toFixed(2)); kpiStats.value.push({ @@ -943,7 +960,8 @@ const updateChartLegendSelect = () => { const legendSelected = Object.fromEntries( kpiStats.value.map(item => [ item.title, - selectedRows.value.length === 0 || selectedRows.value.includes(item.kpiId) + selectedRows.value.length === 0 || + selectedRows.value.includes(item.kpiId), ]) );