166 lines
6.3 KiB
Markdown
166 lines
6.3 KiB
Markdown
|
|
## Context
|
|||
|
|
|
|||
|
|
EmailBill 是一个预算跟踪应用,包含 .NET 10 后端和 Vue 3 前端。预算模块负责计算和展示预算执行情况,包括收入、支出和存款计划。
|
|||
|
|
|
|||
|
|
**当前问题**:
|
|||
|
|
1. 预算收入的实际金额计算错误,`BudgetRepository.GetCurrentAmountAsync` 方法查询交易记录时可能存在过滤条件问题
|
|||
|
|
2. 存款计划卡片缺少透明度,用户无法了解"计划存款"金额的计算依据
|
|||
|
|
3. 预算页面的卡片样式与统计页面不一致,影响视觉统一性
|
|||
|
|
|
|||
|
|
**技术栈**:
|
|||
|
|
- 后端:.NET 10, FreeSql ORM, xUnit 测试
|
|||
|
|
- 前端:Vue 3 Composition API, Vant UI, SCSS
|
|||
|
|
- 数据库:SQLite
|
|||
|
|
|
|||
|
|
**约束**:
|
|||
|
|
- 保持向后兼容,不破坏现有 API 契约
|
|||
|
|
- 遵循项目现有的代码风格(中文注释、文件作用域命名空间)
|
|||
|
|
- 样式修改需保持暗色主题兼容性
|
|||
|
|
|
|||
|
|
## Goals / Non-Goals
|
|||
|
|
|
|||
|
|
**Goals:**
|
|||
|
|
- 修复收入预算实际金额的计算错误,确保数据准确性
|
|||
|
|
- 为存款计划添加明细展示功能,提升透明度
|
|||
|
|
- 统一预算页面与统计页面的卡片样式,提升 UI 一致性
|
|||
|
|
- 添加单元测试覆盖修复的逻辑
|
|||
|
|
|
|||
|
|
**Non-Goals:**
|
|||
|
|
- 不重构整个预算计算系统
|
|||
|
|
- 不改变预算数据模型结构
|
|||
|
|
- 不修改其他页面的卡片样式
|
|||
|
|
- 不改变存款计划的计算算法本身
|
|||
|
|
|
|||
|
|
## Decisions
|
|||
|
|
|
|||
|
|
### 决策 1:问题 1 的修复策略
|
|||
|
|
|
|||
|
|
**决定**:采用 TDD(测试驱动开发)方式修复计算错误
|
|||
|
|
|
|||
|
|
**方案对比**:
|
|||
|
|
- **方案 A(选择)**:先编写失败的单元测试复现 bug,然后修复代码,最后验证测试通过
|
|||
|
|
- ✅ 确保 bug 被正确理解和修复
|
|||
|
|
- ✅ 防止回归
|
|||
|
|
- ⏱️ 需要额外编写测试
|
|||
|
|
- **方案 B**:直接修复代码,手动验证
|
|||
|
|
- ❌ 无法保证不引入新问题
|
|||
|
|
- ❌ 缺少回归保护
|
|||
|
|
|
|||
|
|
**实施细节**:
|
|||
|
|
1. 在 `WebApi.Test/` 中创建测试用例,使用实际数据复现"家庭年终奖金"的计算错误
|
|||
|
|
2. 诊断 `BudgetRepository.GetCurrentAmountAsync` 的查询条件:
|
|||
|
|
- 检查 `SelectedCategories` 的 `Contains` 匹配逻辑
|
|||
|
|
- 验证日期范围过滤是否正确(`>=` 和 `<=`)
|
|||
|
|
- 确认 `TransactionType` 过滤条件
|
|||
|
|
3. 修复后运行测试验证
|
|||
|
|
|
|||
|
|
### 决策 2:存款计划明细的数据来源
|
|||
|
|
|
|||
|
|
**决定**:前端计算明细,不新增后端 API
|
|||
|
|
|
|||
|
|
**方案对比**:
|
|||
|
|
- **方案 A(选择)**:前端基于现有数据计算明细
|
|||
|
|
- ✅ 不增加后端复杂度
|
|||
|
|
- ✅ 响应速度快
|
|||
|
|
- ⚠️ 前端需要理解计算逻辑
|
|||
|
|
- **方案 B**:新增后端 API 返回计算明细
|
|||
|
|
- ⏱️ 需要设计新的 DTO 和 API
|
|||
|
|
- 🔄 增加网络往返
|
|||
|
|
|
|||
|
|
**实施细节**:
|
|||
|
|
1. 明细弹窗展示内容:
|
|||
|
|
- **收入预算总计**:所有收入预算的限额和实际值
|
|||
|
|
- **支出预算总计**:所有支出预算的限额和实际值
|
|||
|
|
- **计划存款公式**:`收入预算 - 支出预算 = 计划存款`
|
|||
|
|
- **实际存款**:从 budget 对象获取
|
|||
|
|
- **差额**:`计划存款 - 实际存款`
|
|||
|
|
2. 使用 Vant 的 Popup 组件实现弹窗
|
|||
|
|
3. 在 `BudgetCard.vue` 的 `header-actions` slot 添加"明细"图标按钮(`icon="info"`)
|
|||
|
|
|
|||
|
|
### 决策 3:样式统一的方案
|
|||
|
|
|
|||
|
|
**决定**:直接修改 `.chart-card` 样式,使其继承或匹配 `.common-card`
|
|||
|
|
|
|||
|
|
**方案对比**:
|
|||
|
|
- **方案 A(选择)**:修改 `BudgetChartAnalysis.vue` 中的 `.chart-card` 样式
|
|||
|
|
- ✅ 改动最小,影响范围可控
|
|||
|
|
- ✅ 立即见效
|
|||
|
|
- **方案 B**:将所有预算卡片改为使用 `.common-card` 类
|
|||
|
|
- ⏱️ 需要大量 HTML 结构修改
|
|||
|
|
- ⚠️ 可能影响现有布局逻辑
|
|||
|
|
- **方案 C**:创建新的统一卡片组件
|
|||
|
|
- 🔄 过度设计
|
|||
|
|
- ⏱️ 需要重构多个页面
|
|||
|
|
|
|||
|
|
**实施细节**:
|
|||
|
|
1. 修改 `Web/src/components/Budget/BudgetChartAnalysis.vue` 的 `.chart-card` 样式:
|
|||
|
|
```scss
|
|||
|
|
.chart-card {
|
|||
|
|
background: var(--van-background-2);
|
|||
|
|
border-radius: 16px; // 改为 16px
|
|||
|
|
padding: 16px;
|
|||
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); // 统一阴影
|
|||
|
|
border: 1px solid var(--van-border-color); // 添加边框
|
|||
|
|
margin: 0 12px 16px; // 添加边距
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
2. 检查 `.gauge-card` 的特殊样式是否需要保留
|
|||
|
|
3. 验证暗色主题下的效果
|
|||
|
|
|
|||
|
|
## Risks / Trade-offs
|
|||
|
|
|
|||
|
|
**风险 1:问题 1 的修复可能影响其他预算类型**
|
|||
|
|
- **缓解**:编写覆盖支出、收入、存款三种类型的测试用例
|
|||
|
|
- **回退**:保留 git 历史,可快速回滚
|
|||
|
|
|
|||
|
|
**风险 2:明细弹窗的计算逻辑可能与后端不一致**
|
|||
|
|
- **缓解**:参考 `BudgetSavingsService.cs` 的计算逻辑,确保前端实现一致
|
|||
|
|
- **验证**:与后端计算结果进行对比测试
|
|||
|
|
|
|||
|
|
**风险 3:样式修改可能在某些设备或浏览器上显示异常**
|
|||
|
|
- **缓解**:修改后在浏览器中测试深色/浅色主题
|
|||
|
|
- **回退**:样式改动独立 commit,可快速回滚
|
|||
|
|
|
|||
|
|
**权衡:前端计算 vs 后端计算**
|
|||
|
|
- 选择前端计算明细可以减少 API 开销,但增加了前端复杂度
|
|||
|
|
- 如果未来计算逻辑变得更复杂,可能需要迁移到后端
|
|||
|
|
|
|||
|
|
## Migration Plan
|
|||
|
|
|
|||
|
|
**部署步骤**:
|
|||
|
|
1. 后端修复和测试:
|
|||
|
|
- 运行 `dotnet test` 确保所有测试通过
|
|||
|
|
- 构建后端:`dotnet build`
|
|||
|
|
2. 前端修改:
|
|||
|
|
- 运行 `pnpm lint` 检查代码风格
|
|||
|
|
- 构建前端:`pnpm build`
|
|||
|
|
3. 浏览器验证:
|
|||
|
|
- 测试收入预算的实际金额显示
|
|||
|
|
- 测试存款计划明细弹窗
|
|||
|
|
- 验证卡片样式一致性
|
|||
|
|
|
|||
|
|
**回滚策略**:
|
|||
|
|
- 所有改动都在独立分支,可快速回滚
|
|||
|
|
- 数据库无结构变更,无需数据迁移
|
|||
|
|
|
|||
|
|
**验证清单**:
|
|||
|
|
- [ ] 收入预算的"家庭年终奖金"实际金额正确显示
|
|||
|
|
- [ ] 存款计划卡片有明细按钮,点击显示计算详情
|
|||
|
|
- [ ] 预算页面的卡片样式与统计页面一致
|
|||
|
|
- [ ] 所有单元测试通过
|
|||
|
|
- [ ] 前端 ESLint 无错误
|
|||
|
|
|
|||
|
|
## Open Questions
|
|||
|
|
|
|||
|
|
1. **问题 1 的具体原因**:`SelectedCategories` 匹配问题还是日期范围问题?
|
|||
|
|
- 需要查看实际数据库中的 `TransactionRecord` 和 `BudgetRecord` 数据
|
|||
|
|
- 建议在修复前添加详细的日志输出
|
|||
|
|
|
|||
|
|
2. **明细弹窗是否需要支持历史月份查询?**
|
|||
|
|
- 当前设计仅展示当前周期的明细
|
|||
|
|
- 如果需要历史查询,可能需要后端 API 支持
|
|||
|
|
|
|||
|
|
3. **样式修改是否需要同步到其他使用 `.chart-card` 的组件?**
|
|||
|
|
- 需要检查是否有其他页面使用了相同的类名
|
|||
|
|
- 建议全局搜索 `.chart-card` 确认影响范围
|