From a2bfff579085490ab78029f2a452b62ddd221165 Mon Sep 17 00:00:00 2001 From: SunCheng Date: Tue, 20 Jan 2026 19:56:29 +0800 Subject: [PATCH] 1 --- .../components/Budget/BudgetChartAnalysis.vue | 187 ++++-------------- Web/src/components/ContributionHeatmap.vue | 4 +- Web/src/views/BillAnalysisView.vue | 6 +- Web/src/views/ClassificationBatch.vue | 6 +- Web/src/views/ClassificationEdit.vue | 6 +- Web/src/views/ClassificationNLP.vue | 6 +- Web/src/views/ClassificationSmart.vue | 12 +- Web/src/views/LogView.vue | 6 +- Web/src/views/PeriodicRecord.vue | 6 +- Web/src/views/ScheduledTasksView.vue | 6 +- Web/src/views/StatisticsView.vue | 6 + Web/src/views/UnconfirmedClassification.vue | 6 +- 12 files changed, 92 insertions(+), 165 deletions(-) diff --git a/Web/src/components/Budget/BudgetChartAnalysis.vue b/Web/src/components/Budget/BudgetChartAnalysis.vue index 54f74fb..08cce98 100644 --- a/Web/src/components/Budget/BudgetChartAnalysis.vue +++ b/Web/src/components/Budget/BudgetChartAnalysis.vue @@ -79,26 +79,6 @@ ref="burndownChartRef" class="chart-body burndown-chart" /> -
-
- - ▼ - - {{ monthVarianceExpanded ? '收起偏差分析' : '展开偏差分析' }} -
-
-
@@ -119,25 +99,26 @@ ref="yearBurndownChartRef" class="chart-body burndown-chart" /> -
-
- - ▼ - - {{ yearVarianceExpanded ? '收起偏差分析' : '展开偏差分析' }} +
+ + +
+
+
+ 偏差分析 +
+
+ 预算执行偏差排行
@@ -177,18 +158,13 @@ const props = defineProps({ const monthGaugeRef = ref(null) const yearGaugeRef = ref(null) -const monthVarianceChartRef = ref(null) -const yearVarianceChartRef = ref(null) +const varianceChartRef = ref(null) const burndownChartRef = ref(null) const yearBurndownChartRef = ref(null) -const monthVarianceExpanded = ref(false) -const yearVarianceExpanded = ref(false) - let monthGaugeChart = null let yearGaugeChart = null -let monthVarianceChart = null -let yearVarianceChart = null +let varianceChart = null let burndownChart = null let yearBurndownChart = null @@ -298,19 +274,12 @@ const updateCharts = () => { updateSingleGauge(yearGaugeChart, props.overallStats.year, isExpense) if (props.budgets.length > 0) { - // Update Variance Charts - if (!monthVarianceChart && monthVarianceChartRef.value && monthVarianceExpanded.value) { - monthVarianceChart = echarts.init(monthVarianceChartRef.value) + // Update Variance Chart + if (!varianceChart && varianceChartRef.value) { + varianceChart = echarts.init(varianceChartRef.value) } - if (monthVarianceChart) { - updateVarianceChart(monthVarianceChart, monthBudgets.value) - } - - if (!yearVarianceChart && yearVarianceChartRef.value && yearVarianceExpanded.value) { - yearVarianceChart = echarts.init(yearVarianceChartRef.value) - } - if (yearVarianceChart) { - updateVarianceChart(yearVarianceChart, yearBudgets.value) + if (varianceChart) { + updateVarianceChart(varianceChart, props.budgets) } // 更新燃尽图/积累图 @@ -334,7 +303,7 @@ const updateVarianceChart = (chart, budgets) => { const current = b.current || 0 const diff = current - limit return { - name: b.name, + name: b.name + (b.type === 2 ? ' (年)' : ''), value: diff, limit: limit, current: current @@ -825,58 +794,15 @@ watch(() => props.activeTab, () => { setTimeout(() => { burndownChart?.resize() yearBurndownChart?.resize() - monthVarianceChart?.resize() - yearVarianceChart?.resize() + varianceChart?.resize() }, 100) }) }) -// 监听展开/折叠状态 -watch(() => monthVarianceExpanded.value, (expanded) => { - if (expanded) { - nextTick(() => { - if (monthVarianceChartRef.value) { - if (!monthVarianceChart) { - monthVarianceChart = echarts.init(monthVarianceChartRef.value) - } - updateVarianceChart(monthVarianceChart, monthBudgets.value) - monthVarianceChart.resize() - } - }) - } else { - // 收起时销毁图表实例,释放内存 - if (monthVarianceChart) { - monthVarianceChart.dispose() - monthVarianceChart = null - } - } -}) - -watch(() => yearVarianceExpanded.value, (expanded) => { - if (expanded) { - nextTick(() => { - if (yearVarianceChartRef.value) { - if (!yearVarianceChart) { - yearVarianceChart = echarts.init(yearVarianceChartRef.value) - } - updateVarianceChart(yearVarianceChart, yearBudgets.value) - yearVarianceChart.resize() - } - }) - } else { - // 收起时销毁图表实例,释放内存 - if (yearVarianceChart) { - yearVarianceChart.dispose() - yearVarianceChart = null - } - } -}) - const handleResize = () => { monthGaugeChart?.resize() yearGaugeChart?.resize() - monthVarianceChart?.resize() - yearVarianceChart?.resize() + varianceChart?.resize() burndownChart?.resize() yearBurndownChart?.resize() } @@ -888,9 +814,11 @@ onMounted(() => { yearGaugeChart = initGaugeChart(yearGaugeChart, yearGaugeRef.value, props.overallStats.year, isExpense) // 只在有数据时初始化柱状图 if (props.budgets.length > 0) { - // Variance charts are initialized when expanded, or if we want to init them eagerly? - // Based on watch logic, we init when expanded. - // But updateCharts logic tries to update if exists. + // 初始化偏差图 + if (varianceChartRef.value) { + varianceChart = echarts.init(varianceChartRef.value) + updateVarianceChart(varianceChart, props.budgets) + } // 初始化燃尽图/积累图 if (burndownChartRef.value) { @@ -911,8 +839,7 @@ onUnmounted(() => { window.removeEventListener('resize', handleResize) monthGaugeChart?.dispose() yearGaugeChart?.dispose() - monthVarianceChart?.dispose() - yearVarianceChart?.dispose() + varianceChart?.dispose() burndownChart?.dispose() yearBurndownChart?.dispose() }) @@ -1016,51 +943,5 @@ onUnmounted(() => { color: var(--van-primary-color); } -.expand-toggle-row { - display: flex; - justify-content: center; - align-items: center; - padding: 0; -} - -.expand-toggle { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 4px 12px; - border-radius: 6px; - transition: background-color 0.2s ease; - user-select: none; -} - -.expand-toggle:hover { - background-color: rgba(0, 0, 0, 0.05); -} - -.expand-toggle:active { - background-color: rgba(0, 0, 0, 0.1); -} - -.expand-icon { - display: inline-block; - font-size: 12px; - color: var(--van-text-color-2); - transition: transform 0.2s ease; - transform-origin: center; -} - -.expand-icon.expanded { - transform: rotate(180deg); -} - -.expand-text { - font-size: 12px; - color: var(--van-text-color-2); - transition: color 0.2s ease; -} - -.expand-toggle:hover .expand-text { - color: var(--van-text-color); -} - \ No newline at end of file +/* expand styles removed as they are no longer used */ + diff --git a/Web/src/components/ContributionHeatmap.vue b/Web/src/components/ContributionHeatmap.vue index 2b1ccb7..842b098 100644 --- a/Web/src/components/ContributionHeatmap.vue +++ b/Web/src/components/ContributionHeatmap.vue @@ -398,7 +398,7 @@ onMounted(() => { .heatmap-cell { width: 15px; height: 15px; - border-radius: 2px; + border-radius: 3px; background-color: var(--van-gray-2); box-sizing: border-box; } @@ -441,6 +441,6 @@ onMounted(() => { .legend-item { width: 15px; height: 15px; - border-radius: 2px; + border-radius: 3px; } diff --git a/Web/src/views/BillAnalysisView.vue b/Web/src/views/BillAnalysisView.vue index 8ddb214..6bd50b3 100644 --- a/Web/src/views/BillAnalysisView.vue +++ b/Web/src/views/BillAnalysisView.vue @@ -141,7 +141,11 @@ const quickQuestions = [ // 返回 const onClickLeft = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } // 点击提示词按钮 diff --git a/Web/src/views/ClassificationBatch.vue b/Web/src/views/ClassificationBatch.vue index 27424fa..1179230 100644 --- a/Web/src/views/ClassificationBatch.vue +++ b/Web/src/views/ClassificationBatch.vue @@ -106,7 +106,11 @@ const onLoad = async () => { // 返回上一页 const handleBack = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } // 页面加载 diff --git a/Web/src/views/ClassificationEdit.vue b/Web/src/views/ClassificationEdit.vue index 6aa3bc8..f2f65ff 100644 --- a/Web/src/views/ClassificationEdit.vue +++ b/Web/src/views/ClassificationEdit.vue @@ -202,7 +202,11 @@ const handleBack = () => { currentType.value = null categories.value = [] } else { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } } diff --git a/Web/src/views/ClassificationNLP.vue b/Web/src/views/ClassificationNLP.vue index 37ea263..0cb97eb 100644 --- a/Web/src/views/ClassificationNLP.vue +++ b/Web/src/views/ClassificationNLP.vue @@ -104,7 +104,11 @@ const showRecordsList = ref(false) // 控制记录列表弹窗 // 返回按钮 const onClickLeft = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } // 将带目标分类的记录转换为普通交易记录格式供列表显示 diff --git a/Web/src/views/ClassificationSmart.vue b/Web/src/views/ClassificationSmart.vue index d12a048..cbb45cd 100644 --- a/Web/src/views/ClassificationSmart.vue +++ b/Web/src/views/ClassificationSmart.vue @@ -110,11 +110,19 @@ const onClickLeft = () => { message: '有未保存的分类结果,确定要离开吗?' }) .then(() => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } }) .catch(() => {}) } else { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } } diff --git a/Web/src/views/LogView.vue b/Web/src/views/LogView.vue index 3987c3a..51a7927 100644 --- a/Web/src/views/LogView.vue +++ b/Web/src/views/LogView.vue @@ -129,7 +129,11 @@ const dateOptions = ref([{ text: '全部日期', value: '' }]) * 返回上一页 */ const handleBack = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } /** diff --git a/Web/src/views/PeriodicRecord.vue b/Web/src/views/PeriodicRecord.vue index 0c9951e..4b6a5c5 100644 --- a/Web/src/views/PeriodicRecord.vue +++ b/Web/src/views/PeriodicRecord.vue @@ -365,7 +365,11 @@ const onLoad = () => { // 返回上一页 const handleBack = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } // 获取周期类型文本 diff --git a/Web/src/views/ScheduledTasksView.vue b/Web/src/views/ScheduledTasksView.vue index 241d520..d7c4d9f 100644 --- a/Web/src/views/ScheduledTasksView.vue +++ b/Web/src/views/ScheduledTasksView.vue @@ -119,7 +119,11 @@ onMounted(() => { }) const onClickLeft = () => { - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } const handleExecute = async (task) => { diff --git a/Web/src/views/StatisticsView.vue b/Web/src/views/StatisticsView.vue index 94edc76..e7d9947 100644 --- a/Web/src/views/StatisticsView.vue +++ b/Web/src/views/StatisticsView.vue @@ -152,6 +152,12 @@

收入 + + ¥{{ formatMoney(monthlyData.totalIncome) }} +

{ - router.back() + if (window.history.length > 1) { + router.back() + } else { + router.replace('/') + } } const handleConfirmSelected = async () => {