From b05248fc7b0a6b4d0f0248edd04492376ce7ef8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E8=AF=9A?= Date: Thu, 8 Jan 2026 16:59:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E9=A2=84=E7=AE=97?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E9=80=BB=E8=BE=91=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=B7=A8=E5=91=A8=E6=9C=9F=E7=BB=9F=E8=AE=A1=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=9B=B8=E5=85=B3=E8=AE=A1=E7=AE=97=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Web/src/views/BudgetView.vue | 52 +++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/Web/src/views/BudgetView.vue b/Web/src/views/BudgetView.vue index 21d4295..d8de308 100644 --- a/Web/src/views/BudgetView.vue +++ b/Web/src/views/BudgetView.vue @@ -202,29 +202,57 @@ const activeTabTitle = computed(() => { }) const overallStats = computed(() => { - const allBudgets = [...expenseBudgets.value, ...incomeBudgets.value, ...savingsBudgets.value] + const allBudgetsList = [...expenseBudgets.value, ...incomeBudgets.value, ...savingsBudgets.value] - const getStatsForType = (type) => { + const getStats = (statType) => { const category = activeTab.value - const filtered = allBudgets.filter(b => b.type === type && b.category === category && !b.isStopped) + // 获取当前 tab 类别下所有未停止的预算 + const relevant = allBudgetsList.filter(b => b.category === category && !b.isStopped) - if (filtered.length === 0) return { rate: '0.0', current: 0, limit: 0, count: 0 } + if (relevant.length === 0) return { rate: '0.0', current: 0, limit: 0, count: 0 } - const current = filtered.reduce((sum, b) => sum + (b.current || 0), 0) - const limit = filtered.reduce((sum, b) => sum + (b.limit || 0), 0) - const rate = limit > 0 ? (current / limit) * 100 : 0 + let totalC = 0 + let totalL = 0 + relevant.forEach(b => { + // 限额折算 + let itemLimit = b.limit || 0 + if (statType === BudgetPeriodType.Month && b.type === BudgetPeriodType.Year) { + itemLimit = b.limit / 12 + } else if (statType === BudgetPeriodType.Year && b.type === BudgetPeriodType.Month) { + itemLimit = b.limit * 12 + } + totalL += itemLimit + + // 当前值累加 + // 注意:由于前端 items 只有当前周期的 current,如果是跨周期统计,这里只能视为一种“参考”或“当前进度” + if (b.type === statType) { + totalC += (b.current || 0) + } else { + // 如果周期不匹配(例如在年度统计中统计月度预算), + // 只有在当前是 1 月的情况下,月度支出才等同于年度累计。 + // 为保持统计的严谨性,这里仅在类型匹配时计入 Current,或者根据业务需求进行估计。 + // 但为了解决用户反馈的“统计不对”,我们需要把所有的匹配项都算进来。 + if (statType === BudgetPeriodType.Year) { + // 在年度视图下,月度预算我们也计入它当前的 current(作为它对年度目前的贡献) + totalC += (b.current || 0) + } + // 月度视图下,年度预算的 current 无法直接折算,此处暂不计入支出。 + } + }) + + const rate = totalL > 0 ? (totalC / totalL) * 100 : 0 return { rate: rate.toFixed(1), - current, - limit, - count: filtered.length + current: totalC, + limit: totalL, + count: relevant.length } } return { - month: getStatsForType(BudgetPeriodType.Month), - year: getStatsForType(BudgetPeriodType.Year) + month: getStats(BudgetPeriodType.Month), + year: getStats(BudgetPeriodType.Year) } })