From e304f4d3fa21e01c481d8947f7cecbc4d82918ed Mon Sep 17 00:00:00 2001 From: MaysWind Date: Fri, 16 Jan 2026 01:20:29 +0800 Subject: [PATCH] display all data in statistics & analysis and hide percentages with values below zero --- src/components/base/PieChartBase.ts | 26 ++++++---- .../desktop/AccountAndCategorySankeyChart.vue | 2 +- src/components/desktop/AxisChart.vue | 2 +- src/components/desktop/PieChart.vue | 9 ++-- src/components/desktop/RadarChart.vue | 21 ++++---- src/components/mobile/PieChart.vue | 50 +++++++++++-------- .../insights/tabs/ExplorerChartTab.vue | 1 - .../desktop/statistics/TransactionPage.vue | 4 +- .../mobile/statistics/TransactionPage.vue | 3 +- 9 files changed, 67 insertions(+), 51 deletions(-) diff --git a/src/components/base/PieChartBase.ts b/src/components/base/PieChartBase.ts index 5d9dd983..320cbb56 100644 --- a/src/components/base/PieChartBase.ts +++ b/src/components/base/PieChartBase.ts @@ -13,8 +13,9 @@ export interface CommonPieChartDataItem { name: string; displayName: string; value: number; + actualValue: number; percent: number; - actualPercent: number; + paintPercent: number; color: ColorStyleValue; sourceItem: Record; displayPercent?: string; @@ -30,7 +31,6 @@ export interface CommonPieChartProps { percentField?: string; colorField?: string; hiddenField?: string; - minValidPercent?: number; amountValue?: boolean; defaultCurrency?: string; showValue?: boolean; @@ -55,32 +55,38 @@ export function usePieChartBase(props: CommonPieChartProps) { } const validItems: CommonPieChartDataItem[] = []; + let accumulatedPaintPercent: number = 0; for (const item of props.items) { const value = item[props.valueField]; const percent = props.percentField ? item[props.percentField] : -1; - if (isNumber(value) && value > 0 && - (!props.hiddenField || !item[props.hiddenField]) && - (!props.minValidPercent || value / totalValidValue > props.minValidPercent)) { + if (isNumber(value) && + (!props.hiddenField || !item[props.hiddenField])) { const finalItem: CommonPieChartDataItem = { id: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string, name: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string, displayName: item[props.nameField] as string, - value: value, - percent: (isNumber(percent) && percent >= 0) ? percent : (value / totalValidValue * 100), - actualPercent: value / totalValidValue, + value: value > 0 ? value : 0, + actualValue: value, + percent: (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0), + paintPercent: value > 0 ? value / totalValidValue : 0, color: getDisplayColor((props.colorField && item[props.colorField]) ? item[props.colorField] as ColorValue : DEFAULT_CHART_COLORS[validItems.length % DEFAULT_CHART_COLORS.length]), sourceItem: item }; - finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01'); - finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(finalItem.value, props.defaultCurrency) : finalItem.value.toString(); + accumulatedPaintPercent += finalItem.paintPercent; + finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01'); + finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString(); validItems.push(finalItem); } } + if (validItems.length > 0) { + validItems[validItems.length - 1]!.paintPercent += 1 - accumulatedPaintPercent; + } + return validItems; }); diff --git a/src/components/desktop/AccountAndCategorySankeyChart.vue b/src/components/desktop/AccountAndCategorySankeyChart.vue index 9ee3f41d..4ccdb6bc 100644 --- a/src/components/desktop/AccountAndCategorySankeyChart.vue +++ b/src/components/desktop/AccountAndCategorySankeyChart.vue @@ -267,7 +267,7 @@ const chartOptions = computed(() => { } if (isNumber(dataItem.percent) && dataItem.percent > 0) { - const displayPercent = formatPercentToLocalizedNumerals(dataItem.percent, 2, '<0.01'); + const displayPercent = formatPercentToLocalizedNumerals(dataItem.percent, 2, '<0.01'); tooltip += `(${displayPercent})`; } diff --git a/src/components/desktop/AxisChart.vue b/src/components/desktop/AxisChart.vue index 5ca5980d..d1f6bc5c 100644 --- a/src/components/desktop/AxisChart.vue +++ b/src/components/desktop/AxisChart.vue @@ -396,7 +396,7 @@ function getItemName(name: string): string { function getDisplayValue(value: number): string { if (props.oneHundredPercentStacked) { - return formatPercentToLocalizedNumerals(value, 2, '<0.01'); + return formatPercentToLocalizedNumerals(value, 2, '<0.01'); } if (props.amountValue) { diff --git a/src/components/desktop/PieChart.vue b/src/components/desktop/PieChart.vue index bd88b0d8..dd9d48d8 100644 --- a/src/components/desktop/PieChart.vue +++ b/src/components/desktop/PieChart.vue @@ -142,11 +142,14 @@ const chartOptions = computed(() => { tooltip += `
${name}

`; } - if (props.showValue && props.showPercent) { + const showValue = props.showValue; + const showPercent = props.showPercent && params.value && (params.value as number) > 0; + + if (showValue && showPercent) { tooltip += `
${value}(${percent})
`; - } else if (props.showValue && !props.showPercent) { + } else if (showValue && !showPercent) { tooltip += `
${value}
`; - } else if (!props.showValue && props.showPercent) { + } else if (!showValue && showPercent) { tooltip += `
${percent}
`; } diff --git a/src/components/desktop/RadarChart.vue b/src/components/desktop/RadarChart.vue index a8c4479a..8c2f90db 100644 --- a/src/components/desktop/RadarChart.vue +++ b/src/components/desktop/RadarChart.vue @@ -37,7 +37,6 @@ const props = defineProps<{ percentField?: string; colorField?: string; hiddenField?: string; - minValidPercent?: number; amountValue?: boolean; defaultCurrency?: string; showValue?: boolean; @@ -74,14 +73,13 @@ const radarData = computed(() => { const value = item[props.valueField]; const percent = props.percentField ? item[props.percentField] : -1; - if (isNumber(value) && value > 0 && - (!props.hiddenField || !item[props.hiddenField]) && - (!props.minValidPercent || value / totalValidValue > props.minValidPercent)) { + if (isNumber(value) && + (!props.hiddenField || !item[props.hiddenField])) { const name = item[props.nameField] as string; const color = getDisplayColor((props.colorField && item[props.colorField]) ? item[props.colorField] as ColorValue : DEFAULT_CHART_COLORS[indicators.length % DEFAULT_CHART_COLORS.length]); - const finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value / totalValidValue * 100); - const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01'); + const finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0); + const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01'); const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString(); indicators.push({ @@ -90,16 +88,19 @@ const radarData = computed(() => { color: isDarkMode.value ? '#ccc' : '#333' }); - values.push(value); + values.push(value > 0 ? value : 0); tooltip += '
'; tooltip += `${name}`; - if (props.showValue && props.showPercent) { + const showValue = props.showValue; + const showPercent = props.showPercent && value > 0; + + if (showValue && showPercent) { tooltip += `(${displayPercent})${displayValue}`; - } else if (props.showValue && !props.showPercent) { + } else if (showValue && !showPercent) { tooltip += `${displayValue}`; - } else if (!props.showValue && props.showPercent) { + } else if (!showValue && showPercent) { tooltip += `${displayPercent}`; } diff --git a/src/components/mobile/PieChart.vue b/src/components/mobile/PieChart.vue index ac355d5a..f20dcea8 100644 --- a/src/components/mobile/PieChart.vue +++ b/src/components/mobile/PieChart.vue @@ -3,18 +3,19 @@ - - +
-

+

Percent @@ -53,7 +54,7 @@ :style="getColorStyle(selectedItem?.color, '--f7-chip-outline-border-color')" v-else-if="!skeleton">

-

+

@@ -99,6 +100,7 @@ const emit = defineEmits<{ const { tt } = useI18n(); const { selectedIndex, validItems } = usePieChartBase(props); +const minPaintPercent = 0.0001; // 0.01% const diameter: number = 100; const circumference: number = diameter * Math.PI; @@ -106,7 +108,9 @@ const totalValidValue = computed(() => { let totalValidValue = 0; for (const item of validItems.value) { - totalValidValue += item.value; + if (item.actualValue > 0 && item.paintPercent > minPaintPercent) { + totalValidValue += item.value; + } } return totalValidValue; @@ -122,11 +126,17 @@ const itemCommonDashOffset = computed(() => { for (let i = 0; i < Math.min(selectedIndex.value + 1, validItems.value.length); i++) { const item = validItems.value[i] as CommonPieChartDataItem; - if (item.actualPercent > 0) { + if (item.actualValue > 0 && item.paintPercent > minPaintPercent) { if (i === selectedIndex.value) { - offset += -circumference * (1 - item.actualPercent) / 2; + offset += -circumference * (1 - item.paintPercent) / 2; } else { - offset += -circumference * (1 - item.actualPercent); + offset += -circumference * (1 - item.paintPercent); + } + } else { + if (i === selectedIndex.value) { + offset += -circumference / 2; + } else { + offset += -circumference; } } } @@ -147,7 +157,7 @@ function getColorStyle(color: ColorStyleValue, additionalFieldName?: string): Re } function getItemStrokeDash(item: CommonPieChartDataItem): string { - const length = item.actualPercent * circumference; + const length = item.paintPercent * circumference; return `${length} ${circumference - length}`; } @@ -159,7 +169,7 @@ function getItemDashOffset(item: CommonPieChartDataItem, items: CommonPieChartDa break; } - allPreviousPercent += curItem.actualPercent; + allPreviousPercent += curItem.paintPercent > 0 ? curItem.paintPercent : 0; } if (offset) { diff --git a/src/views/desktop/insights/tabs/ExplorerChartTab.vue b/src/views/desktop/insights/tabs/ExplorerChartTab.vue index 2f4c781b..e2ebd1a9 100644 --- a/src/views/desktop/insights/tabs/ExplorerChartTab.vue +++ b/src/views/desktop/insights/tabs/ExplorerChartTab.vue @@ -117,7 +117,6 @@ />
{{ item.name }} - {{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }} + {{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }} {{ getDisplayAmount(item.totalAmount, defaultCurrency) }}
@@ -351,7 +350,6 @@ />
{{ item.name }} - {{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }} + {{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }}