From 745efe1222e5945600c7ef16c5a9635829ba7017 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 26 Oct 2025 02:01:51 +0800 Subject: [PATCH] add radar chart for categorical analysis on desktop version --- src/components/desktop/RadarChart.vue | 179 ++++++++++++++++++ src/core/statistics.ts | 26 ++- src/desktop-main.ts | 5 +- src/locales/de.json | 1 + src/locales/en.json | 1 + src/locales/es.json | 1 + src/locales/fr.json | 1 + src/locales/helpers.ts | 2 +- src/locales/it.json | 1 + src/locales/ja.json | 1 + src/locales/ko.json | 1 + src/locales/nl.json | 1 + src/locales/pt_BR.json | 1 + src/locales/ru.json | 1 + src/locales/th.json | 1 + src/locales/uk.json | 1 + src/locales/vi.json | 1 + src/locales/zh_Hans.json | 1 + src/locales/zh_Hant.json | 1 + src/stores/statistics.ts | 4 +- .../desktop/statistics/TransactionPage.vue | 28 ++- 21 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 src/components/desktop/RadarChart.vue diff --git a/src/components/desktop/RadarChart.vue b/src/components/desktop/RadarChart.vue new file mode 100644 index 00000000..059e34fd --- /dev/null +++ b/src/components/desktop/RadarChart.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/src/core/statistics.ts b/src/core/statistics.ts index 6def1dec..0be0ecd8 100644 --- a/src/core/statistics.ts +++ b/src/core/statistics.ts @@ -7,25 +7,37 @@ export enum StatisticsAnalysisType { } export class CategoricalChartType implements TypeAndName { - private static readonly allInstances: CategoricalChartType[] = []; + private static readonly allInstancesForAll: CategoricalChartType[] = []; + private static readonly allInstancesForDesktop: CategoricalChartType[] = []; - public static readonly Pie = new CategoricalChartType(0, 'Pie Chart'); - public static readonly Bar = new CategoricalChartType(1, 'Bar Chart'); + public static readonly Pie = new CategoricalChartType(0, 'Pie Chart', false); + public static readonly Bar = new CategoricalChartType(1, 'Bar Chart', false); + public static readonly Radar = new CategoricalChartType(2, 'Radar Chart', true); public static readonly Default = CategoricalChartType.Pie; public readonly type: number; public readonly name: string; + public readonly desktopOnly: boolean = false; - private constructor(type: number, name: string) { + private constructor(type: number, name: string, desktopOnly: boolean) { this.type = type; this.name = name; + this.desktopOnly = desktopOnly; - CategoricalChartType.allInstances.push(this); + if (!desktopOnly) { + CategoricalChartType.allInstancesForAll.push(this); + } + + CategoricalChartType.allInstancesForDesktop.push(this); } - public static values(): CategoricalChartType[] { - return CategoricalChartType.allInstances; + public static values(withDesktopOnlyChart: boolean): CategoricalChartType[] { + if (withDesktopOnlyChart) { + return CategoricalChartType.allInstancesForDesktop; + } else { + return CategoricalChartType.allInstancesForAll; + } } } diff --git a/src/desktop-main.ts b/src/desktop-main.ts index 7b3c3548..2b6aff6c 100644 --- a/src/desktop-main.ts +++ b/src/desktop-main.ts @@ -52,7 +52,7 @@ import 'vuetify/styles'; import * as echarts from 'echarts/core'; import { CanvasRenderer } from 'echarts/renderers'; -import { LineChart, BarChart, PieChart, CandlestickChart } from 'echarts/charts'; +import { LineChart, BarChart, PieChart, CandlestickChart, RadarChart } from 'echarts/charts'; import { GridComponent, TooltipComponent, @@ -99,6 +99,7 @@ import StepsBar from '@/components/desktop/StepsBar.vue'; import ConfirmDialog from '@/components/desktop/ConfirmDialog.vue'; import SnackBar from '@/components/desktop/SnackBar.vue'; import PieChartComponent from '@/components/desktop/PieChart.vue'; +import RadarChartComponent from '@/components/desktop/RadarChart.vue'; import MonthlyTrendsChart from '@/components/desktop/MonthlyTrendsChart.vue'; import DateRangeSelectionDialog from '@/components/desktop/DateRangeSelectionDialog.vue'; import MonthSelectionDialog from '@/components/desktop/MonthSelectionDialog.vue'; @@ -496,6 +497,7 @@ echarts.use([ BarChart, PieChart, CandlestickChart, + RadarChart, GridComponent, TooltipComponent, LegendComponent @@ -536,6 +538,7 @@ app.component('StepsBar', StepsBar); app.component('ConfirmDialog', ConfirmDialog); app.component('SnackBar', SnackBar); app.component('PieChart', PieChartComponent); +app.component('RadarChart', RadarChartComponent); app.component('MonthlyTrendsChart', MonthlyTrendsChart); app.component('DateRangeSelectionDialog', DateRangeSelectionDialog); app.component('MonthSelectionDialog', MonthSelectionDialog); diff --git a/src/locales/de.json b/src/locales/de.json index 11172bef..789c284b 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1512,6 +1512,7 @@ "Not between": "Nicht zwischen", "Pie Chart": "Tortendiagramm", "Bar Chart": "Balkendiagramm", + "Radar Chart": "Radar Chart", "Area Chart": "Flächendiagramm", "Column Chart": "Säulendiagramm", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/en.json b/src/locales/en.json index 3788e1b4..50419b44 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1512,6 +1512,7 @@ "Not between": "Not between", "Pie Chart": "Pie Chart", "Bar Chart": "Bar Chart", + "Radar Chart": "Radar Chart", "Area Chart": "Area Chart", "Column Chart": "Column Chart", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/es.json b/src/locales/es.json index 8aef13b2..97857298 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1512,6 +1512,7 @@ "Not between": "No entre", "Pie Chart": "Gráfico circular", "Bar Chart": "Gráfico de barras", + "Radar Chart": "Radar Chart", "Area Chart": "Gráfico de área", "Column Chart": "Gráfico de columnas", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/fr.json b/src/locales/fr.json index 59a9974d..9e276df8 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1512,6 +1512,7 @@ "Not between": "Pas entre", "Pie Chart": "Graphique en secteurs", "Bar Chart": "Graphique en barres", + "Radar Chart": "Radar Chart", "Area Chart": "Graphique en aires", "Column Chart": "Graphique en colonnes", "Candlestick Chart": "Graphique en chandelier", diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index 5590e72c..0aed63aa 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -2349,7 +2349,7 @@ export function useI18n() { getAllIncomeAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Income), getAllAccountCategories, getAllAccountTypes: () => getLocalizedDisplayNameAndType(AccountType.values()), - getAllCategoricalChartTypes: () => getLocalizedDisplayNameAndType(CategoricalChartType.values()), + getAllCategoricalChartTypes: (withDesktopOnlyChart?: boolean) => getLocalizedDisplayNameAndType(CategoricalChartType.values(!!withDesktopOnlyChart)), getAllTrendChartTypes: () => getLocalizedDisplayNameAndType(TrendChartType.values()), getAllAccountBalanceTrendChartTypes: () => getLocalizedDisplayNameAndType(AccountBalanceTrendChartType.values()), getAllStatisticsChartDataTypes: (analysisType: StatisticsAnalysisType) => getLocalizedDisplayNameAndType(ChartDataType.values(analysisType)), diff --git a/src/locales/it.json b/src/locales/it.json index 2a9a0074..3459b162 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1512,6 +1512,7 @@ "Not between": "Non tra", "Pie Chart": "Grafico a torta", "Bar Chart": "Grafico a barre", + "Radar Chart": "Radar Chart", "Area Chart": "Grafico ad area", "Column Chart": "Grafico a colonne", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/ja.json b/src/locales/ja.json index 8d2e9333..b2a3e1ef 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1512,6 +1512,7 @@ "Not between": "間ではない", "Pie Chart": "円グラフ", "Bar Chart": "棒グラフ", + "Radar Chart": "Radar Chart", "Area Chart": "エリアチャート", "Column Chart": "列チャート", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/ko.json b/src/locales/ko.json index dfe07018..9100726c 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1512,6 +1512,7 @@ "Not between": "사이 아님", "Pie Chart": "원형 차트", "Bar Chart": "막대 차트", + "Radar Chart": "Radar Chart", "Area Chart": "영역 차트", "Column Chart": "세로 막대 차트", "Candlestick Chart": "캠들스틱 차트", diff --git a/src/locales/nl.json b/src/locales/nl.json index 6fbea4b8..3cf4e7ae 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1512,6 +1512,7 @@ "Not between": "Niet tussen", "Pie Chart": "Cirkeldiagram", "Bar Chart": "Balkdiagram", + "Radar Chart": "Radar Chart", "Area Chart": "Vlakdiagram", "Column Chart": "Kolomdiagram", "Candlestick Chart": "Candlestickdiagram", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index 9d6b78d0..3c5155e4 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -1512,6 +1512,7 @@ "Not between": "Não entre", "Pie Chart": "Gráfico de Pizza", "Bar Chart": "Gráfico de Barras", + "Radar Chart": "Radar Chart", "Area Chart": "Gráfico de Área", "Column Chart": "Gráfico de Colunas", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/ru.json b/src/locales/ru.json index 4baea46a..c542757f 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1512,6 +1512,7 @@ "Not between": "Не между", "Pie Chart": "Круговая диаграмма", "Bar Chart": "Гистограмма", + "Radar Chart": "Radar Chart", "Area Chart": "Диаграмма с областями", "Column Chart": "Столбчатая диаграмма", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/th.json b/src/locales/th.json index 9aa7d08a..1067be19 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -1512,6 +1512,7 @@ "Not between": "ไม่อยู่ระหว่าง", "Pie Chart": "กราฟวงกลม", "Bar Chart": "กราฟแท่ง", + "Radar Chart": "Radar Chart", "Area Chart": "กราฟพื้นที่", "Column Chart": "กราฟคอลัมน์", "Candlestick Chart": "กราฟแท่งเทียน", diff --git a/src/locales/uk.json b/src/locales/uk.json index 95ab8aba..e6062325 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1512,6 +1512,7 @@ "Not between": "Не між", "Pie Chart": "Кругова діаграма", "Bar Chart": "Гістограма", + "Radar Chart": "Radar Chart", "Area Chart": "Діаграма з областями", "Column Chart": "Стовпчикова діаграма", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/vi.json b/src/locales/vi.json index 22b78e7f..0dcca923 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1512,6 +1512,7 @@ "Not between": "Không giữa", "Pie Chart": "Biểu đồ tròn", "Bar Chart": "Biểu đồ cột", + "Radar Chart": "Radar Chart", "Area Chart": "Biểu đồ diện tích", "Column Chart": "Biểu đồ cột", "Candlestick Chart": "Candlestick Chart", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 2cca7b6d..d7f2e985 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1512,6 +1512,7 @@ "Not between": "不介于", "Pie Chart": "饼图", "Bar Chart": "条形图", + "Radar Chart": "雷达图", "Area Chart": "面积图", "Column Chart": "柱状图", "Candlestick Chart": "K线图", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 3398d713..5c73a97a 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1512,6 +1512,7 @@ "Not between": "不介於", "Pie Chart": "圓餅圖", "Bar Chart": "長條圖", + "Radar Chart": "雷達圖", "Area Chart": "面積圖", "Column Chart": "柱狀圖", "Candlestick Chart": "K線圖", diff --git a/src/stores/statistics.ts b/src/stores/statistics.ts index d4fe5e44..d174812a 100644 --- a/src/stores/statistics.ts +++ b/src/stores/statistics.ts @@ -700,7 +700,9 @@ export const useStatisticsStore = defineStore('statistics', () => { transactionStatisticsFilter.value.categoricalChartType = settingsStore.appSettings.statistics.defaultCategoricalChartType; } - if (transactionStatisticsFilter.value.categoricalChartType !== CategoricalChartType.Pie.type && transactionStatisticsFilter.value.categoricalChartType !== CategoricalChartType.Bar.type) { + if (transactionStatisticsFilter.value.categoricalChartType !== CategoricalChartType.Pie.type && + transactionStatisticsFilter.value.categoricalChartType !== CategoricalChartType.Bar.type && + transactionStatisticsFilter.value.categoricalChartType !== CategoricalChartType.Radar.type) { transactionStatisticsFilter.value.categoricalChartType = CategoricalChartType.Default.type; } diff --git a/src/views/desktop/statistics/TransactionPage.vue b/src/views/desktop/statistics/TransactionPage.vue index 7afda184..3df8251c 100644 --- a/src/views/desktop/statistics/TransactionPage.vue +++ b/src/views/desktop/statistics/TransactionPage.vue @@ -263,6 +263,32 @@ + + + + + (() => { const allChartTypes = computed(() => { if (analysisType.value === StatisticsAnalysisType.CategoricalAnalysis) { - return getAllCategoricalChartTypes(); + return getAllCategoricalChartTypes(true); } else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) { return getAllTrendChartTypes(); } else {