# Bug修复交接文档 **日期**: 2026-02-14 **变更名称**: `fix-budget-and-ui-bugs` **OpenSpec路径**: `openspec/changes/fix-budget-and-ui-bugs/` **状态**: 已创建变更目录,待创建artifacts --- ## 发现的Bug汇总 (共6个) ### Bug #1: 统计页面路由无法跳转 **影响**: 底部导航栏 **问题**: 点击底部导航的"统计"标签后无法正常跳转 **原因**: 导航栏配置的路由可能不正确,实际统计页面路由是 `/statistics-v2` **位置**: `Web/src/router/index.js` 和底部导航配置 --- ### Bug #2: 删除账单功能无响应 **影响**: 日历页面账单详情弹窗 **问题**: 点击账单详情弹窗中的"删除"按钮后,弹窗不关闭,账单未被删除 **原因**: 删除按钮的点击事件可能未正确绑定,或需要二次确认对话框但未弹出 **位置**: 日历页面的账单详情组件 --- ### Bug #3: Console警告 van-datetime-picker组件未找到 **影响**: 全局 **问题**: 控制台显示 `Failed to resolve component: van-datetime-picker` **原因**: Vant组件未正确导入或注册 **位置**: 全局组件注册 --- ### Bug #4: 预算明细弹窗显示"暂无数据" ⭐⭐⭐ **影响**: 预算页面(支出/收入标签) **问题**: 点击"使用情况"或"完成情况"旁的感叹号图标,弹出的"预算额度/实际详情"对话框显示"暂无数据" **根本原因**: 1. ✅ **后端Service层**正确生成了 `Description` 字段 - `BudgetStatsService.cs` 第280行和495行调用 `GenerateMonthlyDescription` 和 `GenerateYearlyDescription` - 生成HTML格式的详细描述(包含表格和计算公式) 2. ✅ **后端DTO层**有 `Description` 字段 - `Service/Budget/BudgetService.cs` 第525行:`public string Description { get; set; } = string.Empty;` 3. ❌ **Application层丢失数据** - `Application/BudgetApplication.cs` 第80-96行在映射时**没有包含 `Description` 字段** 4. ❌ **API响应DTO缺少字段** - `Application/Dto/BudgetDto.cs` 第64-70行的 `BudgetStatsDetail` 类**没有定义 `Description` 属性** **前端显示逻辑**: - `Web/src/components/Budget/BudgetChartAnalysis.vue` 第199-203行 - 弹窗内容: `v-html="activeDescTab === 'month' ? (overallStats.month?.description || '

暂无数据

') : ..."` **修复方案**: 1. 在 `BudgetStatsDetail` (Application/Dto/BudgetDto.cs:64-70) 添加 `Description` 字段 2. 在 `BudgetApplication.GetCategoryStatsAsync` (Application/BudgetApplication.cs:80-96) 映射 `Description` 字段 --- ### Bug #5: 燃尽图显示为直线 ⭐⭐⭐ **影响**: 预算页面(支出/收入/计划)的月度和年度燃尽图 **问题**: 实际燃尽/积累线显示为直线,无法看到真实的支出/收入趋势波动 **根本原因**: 1. ✅ **后端Service层**正确计算并填充了 `Trend` 字段 - `BudgetStatsService.cs` 第231行: `result.Trend.Add(adjustedAccumulated);` - Trend是每日/每月累计金额的数组 2. ✅ **后端DTO层**有 `Trend` 字段 - `Service/Budget/BudgetService.cs` 第520行:`public List Trend { get; set; } = [];` 3. ❌ **Application层丢失数据** - `Application/BudgetApplication.cs` 第80-96行在映射时**没有包含 `Trend` 字段** 4. ❌ **API响应DTO缺少字段** - `Application/Dto/BudgetDto.cs` 第64-70行的 `BudgetStatsDetail` 类**没有定义 `Trend` 属性** **前端Fallback行为**: - `Web/src/components/Budget/BudgetChartAnalysis.vue` 第591行: `const trend = props.overallStats.month.trend || []` - 当 `trend.length === 0` 时(第603行和第629行),使用线性估算: - 支出: `actualRemaining = totalBudget - (currentExpense * i / currentDay)` (第616行) - 收入: `actualAccumulated = Math.min(totalBudget, currentExpense * i / currentDay)` (第638行) - 导致"实际燃尽/积累"线是一条**直线** **修复方案**: 1. 在 `BudgetStatsDetail` (Application/Dto/BudgetDto.cs:64-70) 添加 `Trend` 字段 2. 在 `BudgetApplication.GetCategoryStatsAsync` (Application/BudgetApplication.cs:80-96) 映射 `Trend` 字段 --- ### Bug #6: 预算卡片金额与关联账单列表金额不一致 ⭐ **影响**: 预算页面,点击预算卡片的"查询关联账单"按钮 **问题**: 显示的关联账单列表中的金额总和,与预算卡片上显示的"实际"金额不一致 **可能原因**: 1. **日期范围不一致**: - 预算卡片 `current`: 使用 `GetPeriodRange` 计算(BudgetService.cs:410-432) - 月度: 当月1号 00:00:00 到当月最后一天 23:59:59 - 年度: 当年1月1号到12月31日 23:59:59 - 关联账单查询: 使用 `budget.periodStart` 和 `budget.periodEnd` (BudgetCard.vue:470-471) - **如果两者不一致,会导致查询范围不同** 2. **硬性预算的虚拟消耗**: - 标记为📌的硬性预算(生活费、车贷等),如果没有实际交易记录,后端按天数比例虚拟累加金额(BudgetService.cs:376-405) - 前端查询账单列表只能查到实际交易记录,查不到虚拟消耗 - **导致: 卡片显示金额 > 账单列表金额总和** **需要验证**: 1. `BudgetResult` 中 `PeriodStart` 和 `PeriodEnd` 的赋值逻辑 2. 硬性预算虚拟消耗的处理 3. 前端是否需要显示虚拟消耗提示 **修复思路**: - 选项1: 确保 `periodStart/periodEnd` 与 `GetPeriodRange` 一致 - 选项2: 在账单列表中显示虚拟消耗的说明/提示 - 选项3: 提供切换按钮,允许显示/隐藏虚拟消耗 --- ## 共性问题分析 **Bug #4 和 #5 的共同根源**: - `Application/Dto/BudgetDto.cs` 中 `BudgetStatsDetail` 类(第64-70行)定义不完整 - 缺少字段: - `Description` (string) - 用于明细弹窗 - `Trend` (List) - 用于燃尽图 **当前定义**: ```csharp public record BudgetStatsDetail { public decimal Limit { get; init; } public decimal Current { get; init; } public decimal Remaining { get; init; } public decimal UsagePercentage { get; init; } } ``` **需要补充**: ```csharp public record BudgetStatsDetail { public decimal Limit { get; init; } public decimal Current { get; init; } public decimal Remaining { get; init; } public decimal UsagePercentage { get; init; } public List Trend { get; init; } = new(); // ⬅️ 新增 public string Description { get; init; } = string.Empty; // ⬅️ 新增 } ``` --- ## 关键文件清单 ### 后端文件 - `Service/Budget/BudgetStatsService.cs` - 统计计算逻辑,生成Description和Trend - `Service/Budget/BudgetService.cs` - BudgetStatsDto定义(含Description和Trend) - `Application/BudgetApplication.cs` - DTO映射逻辑(需要修改) - `Application/Dto/BudgetDto.cs` - API响应DTO定义(需要修改) - `WebApi/Controllers/BudgetController.cs` - API控制器 ### 前端文件 - `Web/src/components/Budget/BudgetChartAnalysis.vue` - 图表和明细弹窗组件 - `Web/src/components/Budget/BudgetCard.vue` - 预算卡片组件,包含账单查询逻辑 - `Web/src/router/index.js` - 路由配置(Bug #1) --- ## 下一步行动 ### 立即执行 ```bash cd D:/codes/others/EmailBill openspec status --change "fix-budget-and-ui-bugs" ``` ### OpenSpec工作流 1. 使用 `/opsx-continue` 或 `/opsx-ff` 继续创建artifacts 2. 变更已创建在: `openspec/changes/fix-budget-and-ui-bugs/` 3. 需要创建的artifacts (按schema要求): - Problem Statement - Tasks - 其他必要的artifacts ### 优先级建议 1. **高优先级 (P0)**: Bug #4, #5 - 影响核心功能,修复简单(只需补充DTO字段) 2. **中优先级 (P1)**: Bug #1, #2 - 影响用户体验 3. **低优先级 (P2)**: Bug #3, #6 - 影响较小或需要更多分析 --- ## 测试验证点 修复后需要验证: 1. ✅ 预算明细弹窗显示完整的HTML表格和计算公式 2. ✅ 燃尽图显示真实的波动曲线而非直线 3. ✅ 底部导航可以正常跳转到统计页面 4. ✅ 删除账单功能正常工作 5. ✅ 控制台无van-datetime-picker警告 6. ✅ 预算卡片金额与账单列表金额一致(或有明确说明差异原因) --- ## 联系信息 - 前端服务: http://localhost:5173 - 后端服务: http://localhost:5000 - 浏览器已打开,测试环境就绪 --- **生成时间**: 2026-02-14 10:30 **Token使用**: 96418/200000 (48%) **下一个Agent**: 请继续 OpenSpec 工作流创建 artifacts 并实施修复