## Context **当前状态**: - 系统中真正显示交易账单的页面: TransactionsRecord.vue, EmailRecord.vue, calendarV2/TransactionList.vue - `BillListComponent` 是统一的账单列表组件,位于 `Web/src/components/Bill/BillListComponent.vue` - TransactionsRecord.vue 和 EmailRecord.vue 已使用 `BillListComponent` - calendarV2/TransactionList.vue 使用自定义实现,有特殊的 UI 风格和交互(自定义 header、Smart 按钮) **背景**: - `BillListComponent` 提供完整的账单列表功能:筛选、排序、分页、左滑删除、多选、Iconify 图标支持 - 支持两种数据模式:API 模式(组件自动加载)和 Custom 模式(父组件传入数据) - 已在 `/balance` 页面(TransactionsRecord.vue)和 EmailRecord.vue 成功使用 **约束**: - 必须保持 calendarV2 的现有功能不变 - 需要保留自定义 header (Items 计数、Smart 按钮) - 接受 UI 风格变化(从自定义卡片样式改为 BillListComponent 统一样式) - 不能修改 `BillListComponent` 本身(除非发现 bug) **实际发现**: 经过代码审查,发现原设计文档中列出的其他 5 个页面并非账单列表: - MessageView.vue: 系统消息列表 (notifications) - PeriodicRecord.vue: 周期性账单规则列表 (periodic billing rules) - ClassificationEdit.vue: 分类管理列表 (categories) - budgetV2/Index.vue: 预算卡片列表 (budget cards) ## Goals / Non-Goals **Goals:** - 将 calendarV2/TransactionList.vue 迁移至使用 `BillListComponent` - 统一账单列表的视觉设计和交互体验 - 减少代码重复,提高可维护性(从 403 行减少到 177 行) - 保留日历视图的特定功能(自定义 header、Smart 按钮) **Non-Goals:** - 不修改 `BillListComponent` 的核心功能 - 不改变业务逻辑或数据流 - 不涉及后端 API 修改 - 不迁移非账单列表页面(MessageView、PeriodicRecord、ClassificationEdit、budgetV2) ## Decisions ### 决策 1: 使用 Custom 数据模式 **决定**: 所有迁移页面使用 `data-source="custom"` 模式 **理由**: - 每个页面有特定的数据加载逻辑(如 EmailRecord 加载关联账单、PeriodicRecord 加载周期性账单) - Custom 模式允许父组件完全控制数据加载和筛选 - 避免修改 `BillListComponent` 的 API 加载逻辑 **替代方案**: - 使用 API 模式并扩展 `BillListComponent` 支持不同 API endpoint → 拒绝,因为会增加组件复杂度 ### 决策 2: 保留自定义 header 和 Smart 按钮 **决定**: calendarV2/TransactionList.vue 保留原有的自定义 header 部分 **理由**: - 日历视图需要显示 Items 计数 - Smart 按钮是日历视图的特殊功能 - BillListComponent 只替换列表部分,不影响 header **实现**: - 在 template 中保留 txn-header 部分 - 将 BillListComponent 放在 header 下方 - 保留 header 相关的样式定义 ### 决策 3: 保留特定事件处理 **决定**: 每个页面保留自己的事件处理逻辑,通过 `@click`、`@delete` 等 props 传递 **理由**: - 不同页面对点击、删除的处理不同 - `BillListComponent` 已支持事件派发机制 - 保持业务逻辑在父组件中,组件只负责展示 ### 决策 4: 禁用不需要的功能 **决定**: 通过 props 控制功能开关(如 `:enable-filter="false"`、`:show-checkbox="false"`) **理由**: - 不是所有页面都需要筛选栏和多选功能 - `BillListComponent` 已提供灵活的配置选项 - 保持页面简洁,符合原设计 ## Risks / Trade-offs ### 风险 1: 业务逻辑遗漏 **风险**: 迁移过程中可能遗漏某些特定业务逻辑(如特殊的删除回调、数据刷新机制) **缓解**: - 迁移前仔细审查每个页面的现有实现 - 保留所有事件监听器(如 `transaction-deleted` 全局事件) - 每个页面迁移后进行完整功能测试 ### 风险 2: UI 细节差异 **风险**: `BillListComponent` 的样式可能与某些页面的原设计有细微差异 **缓解**: - 使用 Custom 数据模式,保持数据加载逻辑不变 - 如果发现样式问题,优先通过 CSS 覆盖解决 - 必要时可以考虑为 `BillListComponent` 添加样式 prop(但需谨慎) ### 风险 3: 性能影响 **风险**: `BillListComponent` 可能比某些轻量级自定义实现更重 **缓解**: - `BillListComponent` 已经过优化,支持虚拟滚动和分页 - Custom 模式下父组件完全控制数据加载,不会有额外请求 - 监控迁移后的页面性能指标 ### Trade-off: 灵活性 vs 一致性 **取舍**: 采用统一组件会牺牲一定的定制灵活性 **接受理由**: 一致性和可维护性的收益大于灵活性的损失 **风险控制**: Custom 数据模式提供足够的业务逻辑控制空间 ## Migration Plan ### 阶段 1: 准备(已完成) - ✓ 分析所有账单列表页面 - ✓ 确认 `BillListComponent` 功能完整性 - ✓ 制定迁移顺序 ### 阶段 2: 逐页迁移 每个页面遵循以下步骤: 1. **备份**: 保留原实现作为注释(如果需要回滚) 2. **替换**: 用 `BillListComponent` 替换自定义列表 3. **适配**: 调整数据格式和事件处理 4. **测试**: 验证所有功能(点击、删除、筛选、分页) 5. **清理**: 移除废弃代码和样式 ### 阶段 3: 验收 - 所有 6 个页面迁移完成 - 功能回归测试通过 - 视觉一致性检查通过 - 代码审查通过 ### 回滚策略 - 每个页面独立迁移,可以单独回滚 - Git commit 以页面为单位,便于 revert - 如果某个页面迁移失败,不影响其他页面 ## Open Questions 1. **budgetV2/Index.vue 的双列表问题**: 该页面有 "已使用预算列表" 和 "未分类账单列表" 两个列表,是否都需要迁移? - **初步决定**: 都迁移,使用两个 `BillListComponent` 实例 2. **calendarV2/modules/TransactionList.vue**: 该组件本身是一个列表组件,是否需要完全替换还是部分复用? - **初步决定**: 完全替换为 `BillListComponent`,因为注释已建议使用统一组件 3. **图标映射**: 某些页面可能使用特定的分类图标,是否需要特殊处理? - **初步决定**: `BillListComponent` 已支持 Iconify 和 API 加载的图标映射,应该覆盖大部分场景