Files
EmailBill/openspec/changes/unified-popup-component/design.md

164 lines
6.0 KiB
Markdown
Raw Normal View History

2026-02-15 10:10:28 +08:00
## Context
当前前端项目使用 Vue 3 + Vant UI 构建,虽然已有封装的 `PopupContainer.vue` 组件,但项目中存在多种弹窗实现方式:
1. **PopupContainer.vue**: 统一的底部弹出式弹窗,支持标题、副标题、固定头部/页脚、内容滚动
2. **AddClassifyDialog.vue**: 基于 `van-dialog` 的独立对话框组件,用于新增分类
3. **CategoryBillPopup.vue**: 基于 `van-popup` 的独立底部弹窗组件,用于展示分类账单列表
4. **直接使用 van-dialog**: 多个视图文件中直接使用(如 ClassificationEdit.vue、BillAnalysisView.vue
5. **直接使用 van-popup**: 多个视图文件中用于选择器、表单等场景(如 PeriodicRecord.vue、statisticsV2/Index.vue
这种分散的实现导致:
- 弹窗风格不统一(标题样式、圆角、间距、字体大小等)
- 代码重复度高,维护成本高
- 用户体验不一致
## Goals / Non-Goals
**Goals:**
- 统一所有弹窗组件使用 `PopupContainer` 或其扩展组件
- 确保弹窗的视觉风格和交互行为一致
- 减少代码重复,提高可维护性
- 扩展 `PopupContainer` 功能以覆盖现有所有使用场景
**Non-Goals:**
- 不修改 Vant UI 组件库本身
- 不改变弹窗的业务逻辑(仅重构 UI 层)
- 不影响后端 API
## Decisions
### 1. 扩展现有 PopupContainer 组件而非创建新组件
**选择理由:**
- `PopupContainer.vue` 已有成熟的底部弹窗布局和样式
- 仅需扩展其功能即可覆盖大部分使用场景
- 避免引入新的组件,减少学习成本
**扩展点:**
- 添加 `confirm``cancel` 事件,支持简单确认对话框场景
- 添加 `showConfirmButton``showCancelButton` props控制按钮显示
- 添加 `confirmText``cancelText` props自定义按钮文本
- 保留插槽机制,支持复杂表单场景
### 2. 保留 PopupContainer 的插槽设计
**选择理由:**
- 插槽提供最大的灵活性,支持任意复杂的内容
- 现有代码已使用插槽模式header-actions、footer保持向后兼容
- 避免 API 过度设计,保持组件简洁
### 3. 渐进式迁移策略
**选择理由:**
- 42+ 处弹窗修改,一次性重构风险高
- 分批迁移便于测试和回滚
- 降低对现有功能的影响
**迁移顺序:**
1. 扩展 `PopupContainer` 组件
2. 迁移 `AddClassifyDialog.vue``CategoryBillPopup.vue`
3. 迁移 `views/` 目录中的弹窗,按功能模块分批
### 4. 不删除 AddClassifyDialog 和 CategoryBillPopup 组件文件
**选择理由:**
- 这两个组件封装了特定的业务逻辑(如表单验证、数据加载)
- 可以将它们改造为使用 `PopupContainer` 的组合组件,保留业务逻辑
- 避免破坏其他引用这些组件的地方
**改造方式:**
-`AddClassifyDialog.vue` 改造为使用 `PopupContainer` 的组合组件
-`CategoryBillPopup.vue` 改造为使用 `PopupContainer` 的组合组件
- 组件 API 保持不变,仅内部实现变更
### 5. 使用 Vant UI 的 CSS 变量
**选择理由:**
- 项目已使用 Vant UI保持视觉一致性
- 支持深色/浅色主题切换
- 减少自定义 CSS 代码量
## Risks / Trade-offs
### 1. 扩展 PopupContainer 可能导致 API 膨胀
**风险**: 扩展功能过多后,组件变得复杂,难以维护
**缓解措施**:
- 保持核心 API 简洁,使用插槽处理复杂场景
- 添加清晰的文档和示例
- 考虑拆分为多个专用组件(如 ConfirmDialog、FormDialog如果过于复杂
### 2. 迁移过程中可能引入 Bug
**风险**: 重构可能破坏现有功能
**缓解措施**:
- 渐进式迁移,每批迁移后进行完整测试
- 保留旧代码作为参考,直到新代码稳定
- 重点测试弹窗的打开/关闭、表单验证、数据加载等交互
### 3. 某些场景可能不适用 PopupContainer
**风险**: 一些特殊的弹窗场景(如全屏弹窗、居中弹窗)无法用底部弹窗实现
**缓解措施**:
- 识别这些特殊场景,评估是否需要保留 `van-dialog` 或创建新的专用组件
- 优先统一常见场景,特殊场景可以例外
### 4. 性能影响
**风险**: 组件封装层可能增加轻微的性能开销
**缓解措施**:
- 保持组件轻量化,避免不必要的响应式依赖
- 使用 Vue 3 的 `<script setup>` 语法,减少运行时开销
- 进行性能测试,确保没有明显退化
## Migration Plan
### 阶段 1: 扩展 PopupContainer 组件
1. 添加确认对话框相关 props`showConfirmButton``showCancelButton``confirmText``cancelText`
2. 添加 `confirm``cancel` 事件
3. 更新样式,确保与现有设计一致
4. 编写组件文档和示例
### 阶段 2: 改造现有封装组件
1. 改造 `AddClassifyDialog.vue`,使用 `PopupContainer` 实现
2. 改造 `CategoryBillPopup.vue`,使用 `PopupContainer` 实现
3. 测试改造后的组件功能
### 阶段 3: 迁移 views/ 目录中的弹窗
按功能模块分批迁移:
1. 分类相关视图ClassificationEdit.vue、ClassificationBatch.vue 等)
2. 账单相关视图PeriodicRecord.vue、TransactionsRecord.vue 等)
3. 统计相关视图statisticsV2/Index.vue 等)
4. 预算相关视图budgetV2/*.vue
5. 其他视图BillAnalysisView.vue、calendarV2/Index.vue 等)
### 阶段 4: 验证和优化
1. 全量测试所有弹窗功能
2. 性能测试和优化
3. 代码审查和清理
4. 更新文档
### 回滚策略
- 使用 Git 分支进行开发,主分支保持稳定
- 每个阶段完成后打 Tag便于快速回滚
- 保留旧的实现代码,直到新代码完全稳定
## Open Questions
1. 是否需要创建专门的 `ConfirmDialog` 组件?
- 当前考虑扩展 `PopupContainer` 以支持确认对话框场景
- 如果确认对话框的使用场景较多且简单,可以考虑独立组件
2. 如何处理全屏弹窗场景?
- 识别项目中是否存在全屏弹窗需求
- 如有,评估是否需要扩展 `PopupContainer` 或创建新组件
3. 弹窗动画是否需要统一?
- 当前依赖 Vant UI 的默认动画
- 如有特殊需求,可能需要自定义动画