Files
EmailBill/openspec/changes/archive/2026-02-13-budget-page-v2/specs/budget-v2-data-loading/spec.md
SunCheng 162b6d02dd
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 26s
Docker Build & Deploy / Deploy to Production (push) Successful in 8s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
fix
2026-02-13 22:49:07 +08:00

227 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## ADDED Requirements
### Requirement: 支持三种业务类型的预算数据加载
预算页面 SHALL 支持加载支出预算、收入预算和存款计划三种业务类型的月度数据。
#### Scenario: 加载支出预算数据
- **WHEN** 用户切换到"支出" tab
- **THEN** 页面加载当前月份的支出预算列表
- **AND** 显示支出预算的统计信息(总预算、已支出、余额等)
#### Scenario: 加载收入预算数据
- **WHEN** 用户切换到"收入" tab
- **THEN** 页面加载当前月份的收入预算列表
- **AND** 显示收入预算的统计信息(总目标、已收入、差额等)
#### Scenario: 加载存款计划数据
- **WHEN** 用户切换到"计划" tab
- **THEN** 页面加载当前月份的存款计划列表
- **AND** 显示每个存款计划的统计信息(已存、目标、还差等)
### Requirement: 在主页面集中管理数据加载逻辑
数据加载逻辑 SHALL 在主页面Index.vue集中管理通过 props 传递给子模块。
#### Scenario: 主页面加载数据后传递给子模块
- **WHEN** 主页面完成数据加载
- **THEN** 将数据通过 props 传递给对应的子模块ExpenseBudgetContent、IncomeBudgetContent、SavingsBudgetContent
#### Scenario: 子模块不直接调用 API
- **WHEN** 子模块需要刷新数据
- **THEN** 触发事件通知主页面重新加载数据
- **AND** 主页面加载完成后通过 props 更新子模块
### Requirement: 统一的加载状态和错误处理
页面 SHALL 提供统一的加载状态和错误处理机制。
#### Scenario: 数据加载中显示加载状态
- **WHEN** 页面正在加载预算数据
- **THEN** 显示加载动画van-loading
#### Scenario: 数据加载失败显示错误信息
- **WHEN** 数据加载失败网络错误、API 错误等)
- **THEN** 显示错误提示van-empty with error image
- **AND** 提供"重试"按钮
#### Scenario: 点击重试按钮重新加载数据
- **WHEN** 用户点击"重试"按钮
- **THEN** 清除错误状态
- **AND** 重新加载当前月份和业务 tab 的数据
### Requirement: 支持月度预算数据加载
页面 SHALL 调用 `getBudgetList(year, month)` API 加载指定月份的预算列表。
#### Scenario: 加载当月预算列表
- **WHEN** 用户选择 2024年3月
- **THEN** 调用 `getBudgetList('2024-03-01')` 获取预算列表
- **AND** 按业务类型(支出/收入/存款)分组数据
#### Scenario: 加载月度分类统计
- **WHEN** 用户选择 2024年3月
- **THEN** 调用 `getCategoryStats(category, '2024-03-01')` 获取月度统计
- **AND** 显示月度使用率、趋势等信息
#### Scenario: 支持加载历史月份数据
- **WHEN** 用户选择 2023年12月
- **THEN** 调用 `getBudgetList('2023-12-01')` 获取历史月份的预算数据
- **AND** 正确显示历史数据
### Requirement: 加载未覆盖预算的分类
页面 SHALL 加载未设置预算的分类,并在页头显示警告图标(支出和收入 tabs
#### Scenario: 加载未覆盖分类列表
- **WHEN** 用户在支出 tab 下
- **THEN** 调用 `getUncoveredCategories(category, date)` 获取未设置预算的支出分类
- **AND** 如果存在未覆盖分类,在页头显示警告图标
#### Scenario: 点击警告图标显示未覆盖分类详情
- **WHEN** 用户点击页头的警告图标
- **THEN** 打开弹窗显示未覆盖分类列表
- **AND** 每个分类显示名称、交易笔数和总金额
#### Scenario: 存款计划 tab 不显示警告图标
- **WHEN** 用户切换到"计划" tab
- **THEN** 页头不显示警告图标(存款计划不需要覆盖所有分类)
#### Scenario: 未覆盖分类为空时不显示警告图标
- **WHEN** 当前月份所有分类都已设置预算
- **THEN** 页头不显示警告图标
### Requirement: 加载归档月份的总结
对于历史月份(已归档),页面 SHALL 支持加载和显示归档总结。
#### Scenario: 检测是否为归档月份
- **WHEN** 用户选择的月份早于当前月份
- **THEN** 页头显示归档图标comment-o
#### Scenario: 点击归档图标显示总结
- **WHEN** 用户点击页头的归档图标
- **THEN** 调用 `getArchiveSummary(date)` 获取归档总结
- **AND** 在弹窗中显示 AI 生成的总结内容(富文本)
#### Scenario: 归档总结为空时显示提示
- **WHEN** 用户点击归档图标,但该月份没有总结
- **THEN** 弹窗显示"暂无总结"
#### Scenario: 当前月不显示归档图标
- **WHEN** 用户查看当前月份的预算
- **THEN** 页头不显示归档图标
### Requirement: 存款计划支持独立日期切换
存款计划 SHALL 支持独立的日期切换功能,不受页头日期的影响。
#### Scenario: 存款计划卡片底部显示日期切换按钮
- **WHEN** 用户在"计划" tab 下
- **THEN** 每个存款计划卡片底部显示日期切换按钮(左箭头、日期标签、右箭头)
#### Scenario: 点击左箭头查看上一个周期的存款计划
- **WHEN** 用户点击存款计划卡片的左箭头
- **AND** 该存款计划是月度计划,当前显示 2024年3月
- **THEN** 调用 `getSavingsBudget(year, month, type)` 获取 2024年2月 的数据
- **AND** 更新该卡片的显示内容
#### Scenario: 点击右箭头查看下一个周期的存款计划
- **WHEN** 用户点击存款计划卡片的右箭头
- **AND** 下一个周期不是未来周期
- **THEN** 调用 `getSavingsBudget(year, month, type)` 获取下一个周期的数据
- **AND** 更新该卡片的显示内容
#### Scenario: 当前周期时禁用右箭头
- **WHEN** 存款计划卡片显示的是当前周期
- **THEN** 右箭头按钮不可点击
#### Scenario: 年度存款计划按年切换
- **WHEN** 用户点击年度存款计划的左箭头
- **AND** 当前显示 2024年
- **THEN** 调用 `getSavingsBudget(2023, 0, 'year')` 获取 2023年 的数据
#### Scenario: 月度存款计划按月切换
- **WHEN** 用户点击月度存款计划的左箭头
- **AND** 当前显示 2024年3月
- **THEN** 调用 `getSavingsBudget(2024, 2, 'month')` 获取 2024年2月 的数据
### Requirement: 下拉刷新重新加载所有数据
用户下拉刷新时,页面 SHALL 重新加载当前月份和业务 tab 的所有数据。
#### Scenario: 下拉刷新支出预算数据
- **WHEN** 用户在支出 tab 下下拉刷新
- **THEN** 重新调用 `getBudgetList``getCategoryStats``getUncoveredCategories`
- **AND** 刷新完成后显示提示"刷新成功"
#### Scenario: 下拉刷新存款计划数据
- **WHEN** 用户在计划 tab 下下拉刷新
- **THEN** 重新调用 `getBudgetList` 获取存款计划列表
- **AND** 刷新完成后显示提示"刷新成功"
#### Scenario: 刷新失败显示提示
- **WHEN** 下拉刷新时数据加载失败
- **THEN** 显示提示"刷新失败"
- **AND** 保留之前的数据(如果有)
### Requirement: 月份或业务 tab 切换时自动刷新数据
每次切换月份或业务 tab 时,页面 SHALL 自动刷新对应的数据。
#### Scenario: 切换月份时刷新数据
- **WHEN** 用户从 2024年3月 切换到 2024年2月
- **THEN** 自动加载 2024年2月 的预算数据
- **AND** 清除之前的数据和错误状态
#### Scenario: 从支出 tab 切换到收入 tab 时刷新数据
- **WHEN** 用户从支出 tab 切换到收入 tab
- **THEN** 自动加载收入预算数据和统计信息
- **AND** 保持当前月份不变
#### Scenario: 切换时清除旧的加载状态
- **WHEN** 用户切换月份或 tab
- **THEN** 清除之前的加载状态和错误信息
- **AND** 显示新的加载动画
### Requirement: 数据加载失败不影响其他功能
即使某些数据加载失败,页面 SHALL 仍然允许用户切换月份和业务 tab。
#### Scenario: 统计数据加载失败仍可查看列表
- **WHEN** `getCategoryStats` 加载失败
- **THEN** 显示错误提示
- **AND** 预算列表仍然正常显示(如果 `getBudgetList` 成功)
#### Scenario: 未覆盖分类加载失败不影响主功能
- **WHEN** `getUncoveredCategories` 加载失败
- **THEN** 页头不显示警告图标
- **AND** 其他功能(预算列表、统计等)仍然正常工作
#### Scenario: 部分数据加载失败时可重试
- **WHEN** 部分数据加载失败(如统计数据)
- **THEN** 用户可以点击"重试"按钮
- **AND** 只重新加载失败的部分(而非所有数据)
### Requirement: 支持全局事件刷新数据
页面 SHALL 监听全局 'transactions-changed' 事件,自动刷新数据。
#### Scenario: 接收全局事件后刷新数据
- **WHEN** 用户在其他页面添加或修改了预算记录
- **AND** 触发 'transactions-changed' 事件
- **THEN** 预算页面(如果处于激活状态)自动刷新数据
#### Scenario: 页面被缓存时不响应事件
- **WHEN** 预算页面被 keep-alive 缓存(不在当前显示)
- **AND** 触发 'transactions-changed' 事件
- **THEN** 不立即刷新数据(节省性能)
- **AND** 当用户返回预算页面时onActivated再刷新数据
### Requirement: 并发加载多个数据源
页面 SHALL 并发加载多个数据源(预算列表、统计、未覆盖分类等),提升加载速度。
#### Scenario: 并发加载预算列表和统计数据
- **WHEN** 用户切换到支出 tab
- **THEN** 同时调用 `getBudgetList``getCategoryStats``getUncoveredCategories`
- **AND** 等待所有请求完成后隐藏加载状态
#### Scenario: 某个请求失败不阻塞其他请求
- **WHEN** `getUncoveredCategories` 请求失败
- **THEN** 其他请求(`getBudgetList``getCategoryStats`)仍然继续
- **AND** 页面显示部分数据
#### Scenario: 所有请求失败显示错误
- **WHEN** 所有数据加载请求都失败
- **THEN** 显示错误提示和"重试"按钮
- **AND** 不显示任何数据