## Context 项目中已有 `PopupContainer.vue` 通用弹窗组件(位于 `Web/src/components/PopupContainer.vue`),但其样式设计与 `TransactionDetailSheet.vue` 不同: - PopupContainer: 使用 Vant 主题变量,默认高度 80%,标准化的布局 - TransactionDetailSheet: 使用 Inter 字体,16px 圆角,纯白背景(#ffffff / #18181b),更现代化的视觉风格 `TransactionDetailSheet.vue` 当前实现(位于 `Web/src/components/Transaction/TransactionDetailSheet.vue`): - 直接使用 `van-popup` + 自定义样式 - 头部:自定义标题 + 关闭按钮(`.sheet-header`) - 内容区域:金额、表单字段、分类选择器(无固定滚动容器) - 底部操作按钮:删除、保存(`.actions-section`) - 样式特点:`borderTopLeftRadius: 16px`, Inter 字体, `#ffffff` 背景, `gap: 24px` 当前问题:头部和底部未固定,内容较多时滚动体验不佳。 ## Goals / Non-Goals **Goals:** - 创建 `PopupContainerV2.vue` 通用组件,采用 TransactionDetailSheet 的样式风格 - 提供固定头部(标题 + 可选关闭按钮)、可滚动内容、固定底部的布局能力 - 支持暗色模式(`#18181b` 背景) - 将 TransactionDetailSheet 重构为使用 PopupContainerV2 - 保持 TransactionDetailSheet 所有现有功能和对外 API 不变 **Non-Goals:** - 不修改现有的 `PopupContainer.vue`(v1 版本保持不变) - 不强制项目中其他组件迁移到 v2(自愿迁移) - 不改变 TransactionDetailSheet 的业务逻辑 - 不引入新的 UI 库或依赖 ## Decisions ### 决策 1:创建新组件 PopupContainerV2 而不是修改 PopupContainer **选择**: 创建新的 `PopupContainerV2.vue` 组件 **理由**: - PopupContainer 已在项目中广泛使用(CategoryBillPopup 等),修改可能影响现有组件 - TransactionDetailSheet 的样式风格更现代,适合作为新版本 - v1 和 v2 可以并存,逐步迁移,降低风险 - **替代方案**: 直接修改 PopupContainer → 不采用,破坏性太大,需要验证所有使用方 ### 决策 2:PopupContainerV2 的样式来源 **选择**: 完全采用 TransactionDetailSheet 的样式风格 **理由**: - TransactionDetailSheet 的样式已经过验证,用户体验良好 - Inter 字体、16px 圆角、纯白背景是现代化设计趋势 - 保持样式一致性,避免混合不同的设计语言 - **替代方案**: 混合 PopupContainer 和 TransactionDetailSheet 的样式 → 不采用,会导致样式不统一 ### 决策 3:PopupContainerV2 的 API 设计 **选择**: 提供 title prop、default 插槽、footer 插槽,关闭按钮默认显示 **理由**: - title prop 简化使用,覆盖 80% 场景 - default 插槽放可滚动内容,最大灵活性 - footer 插槽放固定底部操作按钮 - 关闭按钮默认显示,符合 TransactionDetailSheet 的行为 - **替代方案**: 提供 header 插槽替代 title prop → 不采用,增加使用复杂度,大多数场景只需简单标题 ### 决策 4:内容区域的 padding 处理 **选择**: PopupContainerV2 的内容插槽不提供默认 padding,由使用方控制 **理由**: - TransactionDetailSheet 的不同区域有不同的 padding 需求(金额区域 16px 16px 24px,表单区域 0 16px 16px) - 组件不应预设 padding,保持灵活性 - 使用方可以根据内容自行调整间距 - **替代方案**: 提供统一的 padding → 不采用,会限制布局灵活性 ### 决策 5:TransactionDetailSheet 的迁移策略 **选择**: 完全移除原有的头部和外层布局代码,使用 PopupContainerV2 的插槽 **理由**: - 避免代码重复,减少维护成本 - PopupContainerV2 已提供所有需要的布局能力 - 保持 TransactionDetailSheet 的职责单一(业务逻辑) - **替代方案**: 保留部分原有代码 → 不采用,会造成样式冲突和维护混乱 ## Risks / Trade-offs ### 风险 1:新增 PopupContainerV2 组件增加项目复杂度 **缓解措施**: - 在组件文件顶部添加清晰的文档注释,说明 v1 和 v2 的区别 - v2 组件设计简洁,API 清晰,易于理解和使用 - 在使用 TransactionDetailSheet 时验证 v2 的稳定性后,再考虑推广到其他组件 ### 风险 2:样式迁移可能遗漏细节 **缓解措施**: - 仔细对比 TransactionDetailSheet 的原有样式 - 使用 Chrome DevTools 对比重构前后的渲染效果 - 验证暗色模式的样式一致性 ### 风险 3:日期选择器(van-datetime-picker)的嵌套弹窗可能存在 z-index 冲突 **缓解措施**: van-datetime-picker 使用 `teleport="body"`,应与 PopupContainerV2 的弹窗层级独立,测试时重点验证 ### Trade-off 1:创建 v2 而不是统一到一个组件 **影响**: 项目中会同时存在两个弹窗组件,增加学习成本 **权衡**: 保护现有代码稳定性的收益大于维护两个组件的成本,且 v2 可以逐步替代 v1 ### Trade-off 2:PopupContainerV2 不提供默认 padding **影响**: 使用方需要自行管理内容区域的间距 **权衡**: 灵活性优于便利性,避免样式冲突