Files
EmailBill/openspec/changes/unified-popup-component/design.md
SunCheng a88556c784 fix
2026-02-15 10:10:28 +08:00

164 lines
6.0 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.
## 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 的默认动画
- 如有特殊需求,可能需要自定义动画