feat: 优化预算统计逻辑,支持跨周期统计并修复相关计算问题
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 16s
Docker Build & Deploy / Deploy to Production (push) Successful in 10s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s

This commit is contained in:
孙诚
2026-01-08 16:59:30 +08:00
parent 343570d4bc
commit b05248fc7b

View File

@@ -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)
}
})