fix
This commit is contained in:
2
openspec/changes/fix-budget-and-ui-bugs/.openspec.yaml
Normal file
2
openspec/changes/fix-budget-and-ui-bugs/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-14
|
||||
143
openspec/changes/fix-budget-and-ui-bugs/design.md
Normal file
143
openspec/changes/fix-budget-and-ui-bugs/design.md
Normal file
@@ -0,0 +1,143 @@
|
||||
## Context
|
||||
|
||||
**当前状态**:
|
||||
- 后端 `BudgetStatsService` 已正确计算 `Description` (HTML格式明细) 和 `Trend` (每日累计金额数组)
|
||||
- Service 层的 `BudgetStatsDto` 包含这两个字段
|
||||
- **问题**: Application 层在映射 DTO 时丢失了这两个字段,导致 API 响应不完整
|
||||
- 前端使用 fallback 逻辑(线性估算)来弥补缺失数据,导致燃尽图显示为直线
|
||||
|
||||
**约束**:
|
||||
- 修复必须向后兼容,不能破坏现有 API 契约
|
||||
- 优先修复 Bug #4 和 #5(高优先级),因为修复简单且影响大
|
||||
- 前端已有完整的数据处理逻辑,只需后端提供正确数据
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 修复 `BudgetStatsDetail` DTO 定义,添加 `Description` 和 `Trend` 字段
|
||||
- 修复 `BudgetApplication.GetCategoryStatsAsync` 中的 DTO 映射逻辑
|
||||
- 修复前端路由配置和 Vant 组件注册问题
|
||||
- 分析并修复账单删除功能和金额不一致问题
|
||||
- 添加单元测试覆盖修复场景
|
||||
|
||||
**Non-Goals:**
|
||||
- 不重构 `BudgetStatsService` 的计算逻辑(已验证正确)
|
||||
- 不改变前端图表组件的渲染逻辑(已有完整支持)
|
||||
- 不修改 API 路由或版本化(向后兼容)
|
||||
|
||||
## Decisions
|
||||
|
||||
### 决策 1: 使用 `init` 关键字而非 `set` 来定义新字段
|
||||
**理由**: `BudgetStatsDetail` 是 `record` 类型,遵循不可变对象模式。使用 `init` 确保字段只能在对象初始化时设置。
|
||||
|
||||
**替代方案**:
|
||||
- 改用 `class` + `set` → 违背现有代码风格,且失去 record 的值语义
|
||||
- 保持 `record` + `set` → C# 9+ 允许,但不符合不可变设计原则
|
||||
|
||||
### 决策 2: 在 Application 层映射时直接赋值,不做转换
|
||||
**理由**: Service 层的 `BudgetStatsDto.Trend` 和 `Description` 已经是目标格式(`List<decimal?>` 和 `string`),无需额外处理。
|
||||
|
||||
**实现**:
|
||||
```csharp
|
||||
Month = new BudgetStatsDetail
|
||||
{
|
||||
Limit = stats.Month.Limit,
|
||||
Current = stats.Month.Current,
|
||||
Remaining = stats.Month.Remaining,
|
||||
UsagePercentage = stats.Month.UsagePercentage,
|
||||
Trend = stats.Month.Trend, // ⬅️ 新增
|
||||
Description = stats.Month.Description // ⬅️ 新增
|
||||
}
|
||||
```
|
||||
|
||||
### 决策 3: Bug #1 (路由跳转) - 修改底部导航配置而非路由定义
|
||||
**理由**: 经验证,`/statistics-v2` 路由已存在且正常工作。问题出在底部导航组件中硬编码了错误的路由路径。
|
||||
|
||||
**定位策略**:
|
||||
1. 搜索底部导航组件代码 (通常包含 `van-tabbar` 或 `router-link`)
|
||||
2. 检查"统计"标签的 `to` 属性或 `path` 配置
|
||||
3. 修改为 `/statistics-v2`
|
||||
|
||||
### 决策 4: Bug #2 (删除功能) - 添加确认对话框而非直接删除
|
||||
**理由**: 删除操作是破坏性的,应符合最佳实践要求用户确认。
|
||||
|
||||
**实现**:
|
||||
```vue
|
||||
const handleDelete = async () => {
|
||||
const confirmed = await showConfirmDialog({
|
||||
title: '确认删除',
|
||||
message: '确定要删除这条账单吗?此操作无法撤销。'
|
||||
})
|
||||
if (confirmed) {
|
||||
await deleteBill(billId)
|
||||
closePopup()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 决策 5: Bug #3 (组件警告) - 按需导入而非全局注册
|
||||
**理由**: Vant 推荐使用按需导入,减少打包体积。全局注册可能是遗漏导致的警告。
|
||||
|
||||
**验证步骤**:
|
||||
1. 检查 `main.ts` 或全局插件文件是否有 `DatetimePicker` 导入
|
||||
2. 如果缺失,添加 `import { DatetimePicker } from 'vant'; app.use(DatetimePicker);`
|
||||
3. 或在使用组件的文件中局部导入
|
||||
|
||||
### 决策 6: Bug #6 (金额不一致) - 先验证是否虚拟消耗导致
|
||||
**理由**: Bug-handoff 文档指出硬性预算 (📌标记) 会产生虚拟消耗,这是设计行为而非 bug。
|
||||
|
||||
**验证逻辑**:
|
||||
1. 检查不一致的预算是否标记为硬性预算
|
||||
2. 检查 `BudgetService.GetPeriodRange` 返回的日期范围是否与 `periodStart/periodEnd` 一致
|
||||
3. 如果是虚拟消耗:在前端账单列表中添加提示说明
|
||||
4. 如果是日期范围问题:修复 `BudgetResult` 的赋值逻辑
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### 风险 1: API 响应体积增大
|
||||
**问题**: 新增 `Trend` 数组(月度31个元素,年度12个元素)会增加响应大小。
|
||||
|
||||
**缓解措施**:
|
||||
- `Trend` 数据是前端绘制图表必需的,体积增长合理
|
||||
- 考虑后续添加 gzip 压缩到 API 响应(可选优化)
|
||||
|
||||
### 风险 2: 前端可能依赖旧的 fallback 逻辑
|
||||
**问题**: 如果前端代码中有显式检查 `trend.length === 0` 的逻辑,可能会在修复后仍执行 fallback。
|
||||
|
||||
**缓解措施**:
|
||||
- 在修复后端后,验证前端 `BudgetChartAnalysis.vue:603` 和 `629` 行的条件是否正确处理非空 trend
|
||||
- 如果逻辑有问题,修改为 `if (!trend || trend.length === 0)`
|
||||
|
||||
### 风险 3: 测试覆盖不足可能导致回归
|
||||
**问题**: 现有测试可能未覆盖 DTO 映射场景。
|
||||
|
||||
**缓解措施**:
|
||||
- 在 `WebApi.Test` 中添加针对 `BudgetApplication.GetCategoryStatsAsync` 的单元测试
|
||||
- 验证返回的 DTO 包含非空的 `Description` 和 `Trend`
|
||||
- 使用 `FluentAssertions` 编写清晰的断言
|
||||
|
||||
## Migration Plan
|
||||
|
||||
**部署步骤**:
|
||||
1. 部署后端更新(向后兼容,前端可继续使用旧逻辑)
|
||||
2. 验证 API 响应包含新字段 (使用 Swagger 或浏览器开发工具)
|
||||
3. 前端无需额外部署(已支持新字段,会自动切换到真实数据)
|
||||
4. 清除浏览器缓存以确保使用最新前端代码
|
||||
|
||||
**回滚策略**:
|
||||
- 如果新版本出现问题,回滚到上一个 commit
|
||||
- API 是向后兼容的(只添加字段),旧版前端仍可正常工作
|
||||
|
||||
**验证清单**:
|
||||
- [ ] 预算明细弹窗显示完整的 HTML 表格
|
||||
- [ ] 燃尽图显示波动曲线而非直线
|
||||
- [ ] 底部导航"统计"按钮正常跳转
|
||||
- [ ] 删除账单功能弹出确认对话框并正常工作
|
||||
- [ ] 控制台无 `van-datetime-picker` 警告
|
||||
- [ ] 金额不一致问题已分析并修复或说明
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Bug #6 金额不一致的根本原因**: 需要在测试环境中验证是否为虚拟消耗导致,还是日期范围计算错误。
|
||||
2. **前端 fallback 逻辑是否需要移除**: 当前 fallback 作为容错机制保留是否合理?还是应在有真实数据时完全禁用?
|
||||
3. **是否需要添加 E2E 测试**: 当前只计划单元测试,是否需要添加端到端测试覆盖完整流程?
|
||||
42
openspec/changes/fix-budget-and-ui-bugs/proposal.md
Normal file
42
openspec/changes/fix-budget-and-ui-bugs/proposal.md
Normal file
@@ -0,0 +1,42 @@
|
||||
## Why
|
||||
|
||||
修复预算统计模块的6个影响用户体验的bug,其中包括2个高优先级数据丢失问题(预算明细弹窗显示"暂无数据"、燃尽图显示为直线)和4个UI/交互问题(路由跳转失败、删除功能无响应、控制台警告、金额不一致)。这些bug影响了核心预算跟踪功能的可用性和准确性。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 修复后端 Application 层 DTO 映射缺失,补充 `Description` 和 `Trend` 字段到 API 响应
|
||||
- 修复前端路由配置,确保底部导航栏"统计"按钮跳转到正确路由
|
||||
- 修复日历页面账单删除功能的事件绑定
|
||||
- 修复 Vant 组件 `van-datetime-picker` 的全局注册问题
|
||||
- 分析并修复预算卡片金额与关联账单列表金额不一致问题
|
||||
- 添加后端和前端单元测试覆盖修复的场景
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
<!-- 无新功能,仅修复现有功能 -->
|
||||
|
||||
### Modified Capabilities
|
||||
- `budget-stats`: 修复预算统计API响应缺失 `Description` 和 `Trend` 字段,确保前端能正确展示明细弹窗和燃尽图
|
||||
- `bill-management`: 修复账单删除功能的事件处理逻辑
|
||||
- `navigation`: 修复前端路由配置和底部导航栏跳转
|
||||
|
||||
## Impact
|
||||
|
||||
**后端文件**:
|
||||
- `Application/Dto/BudgetDto.cs` - 修改 `BudgetStatsDetail` 添加字段
|
||||
- `Application/BudgetApplication.cs` - 修改 DTO 映射逻辑
|
||||
- `WebApi.Test/` - 添加新的测试用例覆盖修复场景
|
||||
|
||||
**前端文件**:
|
||||
- `Web/src/router/index.js` - 修复路由配置
|
||||
- `Web/src/components/Budget/BudgetChartAnalysis.vue` - 验证数据正确使用
|
||||
- `Web/src/components/Budget/BudgetCard.vue` - 分析账单金额不一致问题
|
||||
- `Web/src/main.ts` 或全局组件注册文件 - 修复 Vant 组件注册
|
||||
- 日历页面账单详情组件 - 修复删除按钮事件绑定
|
||||
|
||||
**API影响**:
|
||||
- GET `/api/budget/stats/{category}` 响应结构变更(新增字段,向后兼容)
|
||||
|
||||
**依赖**:
|
||||
- 无外部依赖变更
|
||||
@@ -0,0 +1,40 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Bill deletion requires user confirmation
|
||||
账单删除操作 MUST 要求用户显式确认,防止误操作导致数据丢失。删除确认对话框 SHALL 明确告知用户操作的不可逆性。
|
||||
|
||||
#### Scenario: User confirms bill deletion
|
||||
- **WHEN** 用户在日历页面的账单详情弹窗中点击"删除"按钮
|
||||
- **THEN** 系统弹出确认对话框,标题为"确认删除"
|
||||
- **AND** 对话框消息包含警告文本(如"确定要删除这条账单吗?此操作无法撤销。")
|
||||
- **AND** 对话框提供"确认"和"取消"两个按钮
|
||||
|
||||
#### Scenario: User confirms deletion
|
||||
- **WHEN** 用户在确认对话框中点击"确认"按钮
|
||||
- **THEN** 系统调用删除 API (`DELETE /api/bill/{id}`)
|
||||
- **AND** 删除成功后关闭账单详情弹窗
|
||||
- **AND** 日历视图自动刷新,删除的账单不再显示
|
||||
|
||||
#### Scenario: User cancels deletion
|
||||
- **WHEN** 用户在确认对话框中点击"取消"按钮
|
||||
- **THEN** 对话框关闭,账单详情弹窗保持打开状态
|
||||
- **AND** 账单未被删除
|
||||
|
||||
#### Scenario: Deletion fails due to server error
|
||||
- **WHEN** 用户确认删除,但后端返回错误(如网络异常或 500 错误)
|
||||
- **THEN** 系统显示错误提示(如"删除失败,请稍后重试")
|
||||
- **AND** 账单详情弹窗保持打开状态
|
||||
- **AND** 账单仍存在于系统中
|
||||
|
||||
### Requirement: Delete button event binding must be functional
|
||||
日历页面账单详情组件中的删除按钮 MUST 正确绑定点击事件处理函数,确保用户点击时能够触发删除流程。
|
||||
|
||||
#### Scenario: Delete button click triggers handler
|
||||
- **WHEN** 账单详情弹窗渲染完成
|
||||
- **THEN** "删除"按钮的 `@click` 或 `onClick` 事件绑定到正确的处理函数(如 `handleDelete`)
|
||||
- **AND** 点击按钮时控制台无 JavaScript 错误
|
||||
|
||||
#### Scenario: Button is not disabled during loading
|
||||
- **WHEN** 账单详情弹窗首次加载时
|
||||
- **THEN** "删除"按钮的 `disabled` 属性为 `false`(除非账单正在删除中)
|
||||
- **AND** 按钮可以正常响应点击事件
|
||||
@@ -0,0 +1,48 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Budget statistics API response includes complete data
|
||||
预算统计 API (`GET /api/budget/stats/{category}`) SHALL 返回完整的统计数据,包括用于前端图表渲染的 `Trend` 数组和用于明细弹窗的 `Description` HTML 内容。
|
||||
|
||||
响应结构中的 `Month` 和 `Year` 对象 MUST 包含以下字段:
|
||||
- `Limit`: 预算限额
|
||||
- `Current`: 当前实际金额
|
||||
- `Remaining`: 剩余金额
|
||||
- `UsagePercentage`: 使用百分比
|
||||
- `Trend`: 每日/每月累计金额数组 (`List<decimal?>`)
|
||||
- `Description`: HTML 格式的详细说明,包含计算公式和数据表格 (`string`)
|
||||
|
||||
#### Scenario: Monthly stats with trend data
|
||||
- **WHEN** 客户端请求月度预算统计 `GET /api/budget/stats/food?date=2026-02`
|
||||
- **THEN** 响应的 `month` 对象包含 `trend` 数组,长度等于该月天数(如28/29/30/31)
|
||||
- **AND** `trend` 数组每个元素表示截至该天的累计金额(支出类为递减,收入类为递增)
|
||||
- **AND** `trend` 数组中未到达的日期对应的元素为 `null`
|
||||
|
||||
#### Scenario: Monthly stats with description
|
||||
- **WHEN** 客户端请求月度预算统计 `GET /api/budget/stats/food?date=2026-02`
|
||||
- **THEN** 响应的 `month` 对象包含 `description` 字段
|
||||
- **AND** `description` 是 HTML 格式字符串,包含 `<table>` 标签展示明细数据
|
||||
- **AND** `description` 包含计算公式说明(如"剩余 = 限额 - 已用")
|
||||
|
||||
#### Scenario: Yearly stats with trend data
|
||||
- **WHEN** 客户端请求年度预算统计 `GET /api/budget/stats/salary?date=2026`
|
||||
- **THEN** 响应的 `year` 对象包含 `trend` 数组,长度为12(代表12个月)
|
||||
- **AND** `trend` 数组每个元素表示截至该月的累计金额
|
||||
- **AND** `trend` 数组中未到达的月份对应的元素为 `null`
|
||||
|
||||
#### Scenario: Yearly stats with description
|
||||
- **WHEN** 客户端请求年度预算统计 `GET /api/budget/stats/salary?date=2026`
|
||||
- **THEN** 响应的 `year` 对象包含 `description` 字段
|
||||
- **AND** `description` 是 HTML 格式字符串,包含年度统计明细
|
||||
|
||||
### Requirement: DTO mapping preserves all Service layer data
|
||||
Application 层的 `BudgetApplication.GetCategoryStatsAsync` 方法在将 Service 层的 `BudgetStatsDto` 映射到 API 响应 DTO 时,MUST 保留所有数据字段,不得丢失 `Trend` 和 `Description`。
|
||||
|
||||
#### Scenario: Mapping from Service DTO to API DTO
|
||||
- **WHEN** `BudgetApplication.GetCategoryStatsAsync` 接收到 Service 层返回的 `BudgetStatsDto`
|
||||
- **THEN** 映射后的 `BudgetStatsDetail` 对象包含 `Trend` 字段,其值等于 `BudgetStatsDto.Month.Trend` 或 `BudgetStatsDto.Year.Trend`
|
||||
- **AND** 映射后的 `BudgetStatsDetail` 对象包含 `Description` 字段,其值等于 `BudgetStatsDto.Month.Description` 或 `BudgetStatsDto.Year.Description`
|
||||
|
||||
#### Scenario: API response schema validation
|
||||
- **WHEN** 前端调用 `/api/budget/stats/{category}` 并解析 JSON 响应
|
||||
- **THEN** TypeScript 类型检查不报错,响应对象符合 `BudgetStatsResponse` 接口定义
|
||||
- **AND** `month.trend` 和 `month.description` 字段存在且非 `undefined`
|
||||
@@ -0,0 +1,37 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Bottom navigation statistics tab routes correctly
|
||||
底部导航栏的"统计"标签 MUST 正确配置路由路径,点击后能够跳转到统计页面 (`/statistics-v2`)。
|
||||
|
||||
#### Scenario: User clicks statistics tab in bottom navigation
|
||||
- **WHEN** 用户在应用底部导航栏点击"统计"图标或标签
|
||||
- **THEN** 浏览器 URL 变更为 `/statistics-v2`
|
||||
- **AND** 页面渲染统计页面组件(如 `StatisticsV2.vue`)
|
||||
- **AND** 底部导航栏的"统计"标签高亮显示为激活状态
|
||||
|
||||
#### Scenario: Direct URL access to statistics page
|
||||
- **WHEN** 用户直接在浏览器地址栏输入 `/statistics-v2` 并访问
|
||||
- **THEN** 应用正确渲染统计页面
|
||||
- **AND** 底部导航栏的"统计"标签高亮显示为激活状态
|
||||
|
||||
#### Scenario: Navigation tab configuration matches route definition
|
||||
- **WHEN** 前端代码加载时
|
||||
- **THEN** 底部导航组件(`van-tabbar` 或自定义组件)中"统计"标签的 `to` 或 `path` 属性值为 `/statistics-v2`
|
||||
- **AND** 路由配置文件 (`router/index.js`) 中存在 `path: '/statistics-v2'` 的路由定义
|
||||
|
||||
### Requirement: Vant DatetimePicker component must be registered
|
||||
Vant UI 库的 `van-datetime-picker` 组件 MUST 正确注册,以避免控制台出现 "Failed to resolve component" 警告。
|
||||
|
||||
#### Scenario: DatetimePicker used in application
|
||||
- **WHEN** 应用中任何页面使用 `<van-datetime-picker>` 组件
|
||||
- **THEN** 组件正常渲染,无控制台错误或警告
|
||||
- **AND** 控制台不显示 "Failed to resolve component: van-datetime-picker" 消息
|
||||
|
||||
#### Scenario: Global component registration in main.ts
|
||||
- **WHEN** 应用启动时执行 `main.ts` 或全局插件文件
|
||||
- **THEN** `DatetimePicker` 组件已通过 `app.use(DatetimePicker)` 全局注册
|
||||
- **OR** 在使用组件的文件中已通过 `import { DatetimePicker } from 'vant'` 和 `components: { VanDatetimePicker: DatetimePicker }` 局部注册
|
||||
|
||||
#### Scenario: No missing component warnings after fix
|
||||
- **WHEN** 用户浏览应用的所有页面(日历、预算、统计等)
|
||||
- **THEN** 浏览器开发者工具控制台中无任何 Vant 组件相关的警告或错误
|
||||
65
openspec/changes/fix-budget-and-ui-bugs/tasks.md
Normal file
65
openspec/changes/fix-budget-and-ui-bugs/tasks.md
Normal file
@@ -0,0 +1,65 @@
|
||||
## 1. Backend: Fix Budget Stats DTO and Mapping (Bug #4 & #5 - High Priority)
|
||||
|
||||
- [x] 1.1 在 `Application/Dto/BudgetDto.cs` 的 `BudgetStatsDetail` record 中添加 `Trend` 字段(`List<decimal?>`,使用 `init`)
|
||||
- [x] 1.2 在 `Application/Dto/BudgetDto.cs` 的 `BudgetStatsDetail` record 中添加 `Description` 字段(`string`,使用 `init`)
|
||||
- [x] 1.3 在 `Application/BudgetApplication.cs` 的 `GetCategoryStatsAsync` 方法中,映射 `Month` 对象时添加 `Trend = stats.Month.Trend`
|
||||
- [x] 1.4 在 `Application/BudgetApplication.cs` 的 `GetCategoryStatsAsync` 方法中,映射 `Month` 对象时添加 `Description = stats.Month.Description`
|
||||
- [x] 1.5 在 `Application/BudgetApplication.cs` 的 `GetCategoryStatsAsync` 方法中,映射 `Year` 对象时添加 `Trend = stats.Year.Trend`
|
||||
- [x] 1.6 在 `Application/BudgetApplication.cs` 的 `GetCategoryStatsAsync` 方法中,映射 `Year` 对象时添加 `Description = stats.Year.Description`
|
||||
|
||||
## 2. Backend: Add Unit Tests for DTO Mapping
|
||||
|
||||
- [x] 2.1 在 `WebApi.Test/` 中创建 `BudgetApplicationTests.cs` 测试类(如果不存在)
|
||||
- [x] 2.2 编写测试用例 `GetCategoryStatsAsync_Should_Include_Trend_And_Description_In_Month_Stats`
|
||||
- [x] 2.3 编写测试用例 `GetCategoryStatsAsync_Should_Include_Trend_And_Description_In_Year_Stats`
|
||||
- [x] 2.4 运行测试并验证通过:`dotnet test --filter "FullyQualifiedName~BudgetApplicationTests"`
|
||||
|
||||
## 3. Frontend: Fix Navigation Routes (Bug #1)
|
||||
|
||||
- [x] 3.1 使用 `grep` 搜索底部导航组件代码(搜索关键字 `van-tabbar` 或 `统计`)
|
||||
- [x] 3.2 定位"统计"标签的路由配置(检查 `to` 或 `path` 属性)
|
||||
- [x] 3.3 修改路由路径为 `/statistics-v2`
|
||||
- [x] 3.4 验证路由配置文件 `Web/src/router/index.js` 中存在 `/statistics-v2` 路由定义
|
||||
|
||||
## 4. Frontend: Fix Bill Deletion Function (Bug #2)
|
||||
|
||||
- [x] 4.1 使用 `grep` 搜索日历页面的账单详情组件(搜索关键字 `删除` 或 `delete`)
|
||||
- [x] 4.2 定位删除按钮的点击事件绑定(检查 `@click` 或 `onClick`)
|
||||
- [x] 4.3 实现 `handleDelete` 函数,使用 `showConfirmDialog` 显示确认对话框
|
||||
- [x] 4.4 在确认后调用删除 API 并关闭弹窗,刷新日历视图
|
||||
- [x] 4.5 在取消时关闭对话框但保持弹窗打开
|
||||
- [x] 4.6 处理删除失败场景,显示错误提示
|
||||
|
||||
## 5. Frontend: Fix Vant DatetimePicker Registration (Bug #3)
|
||||
|
||||
- [x] 5.1 检查 `Web/src/main.ts` 或全局组件注册文件
|
||||
- [x] 5.2 验证是否导入 `DatetimePicker`(`import { DatetimePicker } from 'vant'`)
|
||||
- [x] 5.3 如果缺失,添加全局注册 `app.use(DatetimePicker)`
|
||||
- [ ] 5.4 启动前端开发服务器,验证控制台无 "Failed to resolve component" 警告
|
||||
|
||||
## 6. Frontend: Verify Budget Chart Renders Correctly After Backend Fix
|
||||
|
||||
- [ ] 6.1 启动后端和前端服务
|
||||
- [ ] 6.2 打开预算页面,点击"使用情况"或"完成情况"旁的感叹号图标
|
||||
- [ ] 6.3 验证明细弹窗显示完整的 HTML 表格(非"暂无数据")
|
||||
- [ ] 6.4 验证燃尽图显示波动曲线(非直线)
|
||||
- [x] 6.5 检查前端 `BudgetChartAnalysis.vue:603` 和 `:629` 行的 fallback 逻辑是否仍触发(如需修改条件检查)
|
||||
|
||||
## 7. Investigation: Budget Card Amount Mismatch (Bug #6 - Low Priority)
|
||||
|
||||
- [ ] 7.1 在测试环境中打开预算页面,点击预算卡片的"查询关联账单"按钮
|
||||
- [ ] 7.2 对比预算卡片显示的"实际"金额与账单列表金额总和
|
||||
- [ ] 7.3 检查不一致的预算是否标记为硬性预算(📌)
|
||||
- [ ] 7.4 如果是硬性预算,验证虚拟消耗的计算逻辑(`BudgetService.cs:376-405`)
|
||||
- [ ] 7.5 检查 `BudgetResult` 中 `PeriodStart` 和 `PeriodEnd` 的赋值是否与 `GetPeriodRange` 一致
|
||||
- [ ] 7.6 如果是虚拟消耗导致,考虑在前端账单列表中添加提示说明(可选)
|
||||
- [ ] 7.7 如果是日期范围问题,修复 `BudgetResult` 的赋值逻辑
|
||||
|
||||
## 8. End-to-End Verification
|
||||
|
||||
- [x] 8.1 运行后端所有测试:`dotnet test`
|
||||
- [x] 8.2 运行前端 lint:`cd Web && pnpm lint`
|
||||
- [x] 8.3 构建前端:`cd Web && pnpm build`
|
||||
- [ ] 8.4 手动测试所有修复的 bug(按 bug-handoff-document.md 中的验证清单)
|
||||
- [ ] 8.5 清除浏览器缓存并重新测试
|
||||
- [ ] 8.6 验证控制台无错误或警告
|
||||
Reference in New Issue
Block a user