|
@@ -0,0 +1,174 @@
|
|
|
|
|
+# Story 006.012: 商品详情页规格选择流程优化
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+Draft
|
|
|
|
|
+
|
|
|
|
|
+## Story
|
|
|
|
|
+**As a** 商品购买用户,
|
|
|
|
|
+**I want** 在商品详情页能一键完成规格选择和购物车/购买操作,
|
|
|
|
|
+**so that** 我可以更快速、更方便地完成商品购买流程
|
|
|
|
|
+
|
|
|
|
|
+## Acceptance Criteria
|
|
|
|
|
+1. 用户点击"加入购物车"或"立即购买"时,如果需要选择规格,自动弹出规格选择器
|
|
|
|
|
+2. 用户在规格选择器中选择规格和数量后,直接执行对应的购物车添加或购买操作
|
|
|
|
|
+3. 用户在页面上已选择的规格状态可以保持,下次弹出规格选择器时自动选中之前选择的规格,方便用户快速确认或修改选择
|
|
|
|
|
+4. 单规格商品的操作流程保持不变,不受影响
|
|
|
|
|
+5. 用户界面清晰显示当前选择的规格信息(如有)
|
|
|
|
|
+6. 操作流程流畅,无多余的弹窗关闭和重新点击步骤
|
|
|
|
|
+
|
|
|
|
|
+## Tasks / Subtasks
|
|
|
|
|
+- [ ] 任务1:分析当前商品详情页规格选择流程 (AC: 1, 6)
|
|
|
|
|
+ - [ ] 检查当前独立的"选择规格"按钮位置和逻辑(第443-460行)
|
|
|
|
|
+ - [ ] 分析handleAddToCart和handleBuyNow函数现有规格选择判断逻辑
|
|
|
|
|
+ - [ ] 确定多规格商品判断条件(hasSpecOptions和selectedSpec状态)
|
|
|
|
|
+- [ ] 任务2:重构规格选择状态管理和弹窗触发逻辑 (AC: 1, 3)
|
|
|
|
|
+ - [ ] 移除独立的"选择规格"按钮及相关UI元素
|
|
|
|
|
+ - [ ] 修改handleAddToCart和handleBuyNow函数,添加自动弹窗判断逻辑
|
|
|
|
|
+ - [ ] 添加规格选择上下文状态管理,记录用户选择后的目标操作
|
|
|
|
|
+ - [ ] 实现规格状态保持机制,下次弹出时自动选中上次选择
|
|
|
|
|
+- [ ] 任务3:扩展GoodsSpecSelector组件支持直接操作执行 (AC: 2)
|
|
|
|
|
+ - [ ] 扩展GoodsSpecSelector组件的onConfirm回调,支持执行目标操作
|
|
|
|
|
+ - [ ] 添加操作类型参数(add-to-cart或buy-now)到组件props
|
|
|
|
|
+ - [ ] 确保组件关闭逻辑正确处理用户取消操作
|
|
|
|
|
+ - [ ] 保持与现有onConfirm回调的向后兼容性
|
|
|
|
|
+- [ ] 任务4:优化用户界面显示当前选择规格信息 (AC: 5)
|
|
|
|
|
+ - [ ] 在操作按钮区域添加当前规格信息显示
|
|
|
|
|
+ - [ ] 确保单规格商品和无父子关系商品显示不受影响
|
|
|
|
|
+ - [ ] 优化价格显示,基于所选规格动态更新
|
|
|
|
|
+ - [ ] 添加规格状态提示(如"已选规格"或"选择规格")
|
|
|
|
|
+- [ ] 任务5:验证向后兼容性和单规格商品支持 (AC: 4)
|
|
|
|
|
+ - [ ] 测试单规格商品(无子商品)的操作流程保持不变
|
|
|
|
|
+ - [ ] 验证无父子关系商品的现有功能不受影响
|
|
|
|
|
+ - [ ] 确保多租户兼容性(父子商品在同一租户下)
|
|
|
|
|
+ - [ ] 验证所有API调用保持正确的tenantId参数传递
|
|
|
|
|
+- [ ] 任务6:编写和更新测试 (AC: 1-6)
|
|
|
|
|
+ - [ ] 更新商品详情页集成测试,验证新规格选择流程
|
|
|
|
|
+ - [ ] 为GoodsSpecSelector组件添加直接操作执行测试
|
|
|
|
|
+ - [ ] 添加规格状态保持机制测试
|
|
|
|
|
+ - [ ] 测试向后兼容性(单规格商品流程不变)
|
|
|
|
|
+ - [ ] 运行现有测试套件,确保无回归问题
|
|
|
|
|
+
|
|
|
|
|
+## Dev Notes
|
|
|
|
|
+
|
|
|
|
|
+### 先前故事洞察
|
|
|
|
|
+- **故事6(商品详情页规格选择集成)**:已成功集成GoodsSpecSelector组件到商品详情页,实现规格选择功能。当前页面包含独立的"选择规格"按钮(第443-460行),点击触发handleOpenSpecModal函数弹出规格选择器。规格选择状态通过selectedSpec和showSpecModal管理。"加入购物车"和"立即购买"按钮已支持规格选择,但需要用户先点击"选择规格"按钮选择规格,再点击操作按钮,流程为两步操作。本故事需要优化此流程,实现一键完成规格选择和购买操作。
|
|
|
|
|
+- **故事5(父子商品多规格选择组件开发)**:已实现GoodsSpecSelector组件,支持获取子商品列表作为规格选项,包含加载状态、错误处理和空状态显示。组件props包括parentGoodsId、visible、onClose、onConfirm、currentSpec、currentQuantity。本故事需要扩展此组件的onConfirm回调支持直接执行操作。
|
|
|
|
|
+- **故事9(父子商品名称关联查询优化)**:商品详情API不再返回spuName字段,使用parent对象获取父商品信息。规格选择应使用子商品的name字段作为规格名称。
|
|
|
|
|
+- [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#故事12]
|
|
|
|
|
+- [Source: docs/stories/006.006.goods-detail-spec-integration.story.md]
|
|
|
|
|
+- [Source: docs/stories/006.005.parent-child-goods-multi-spec-selector.story.md]
|
|
|
|
|
+
|
|
|
|
|
+### 数据模型
|
|
|
|
|
+- **商品实体 (`GoodsMt`)**:
|
|
|
|
|
+ - `spuId` 字段:0表示父商品或单规格商品,>0表示子商品
|
|
|
|
|
+ - `tenantId` 字段:租户ID,父子商品必须在同一租户下
|
|
|
|
|
+ - `name` 字段:商品名称,对于子商品就是规格名称
|
|
|
|
|
+ - `price` 字段:商品价格,子商品可能有与父商品不同的价格
|
|
|
|
|
+ - `stock` 字段:商品库存,子商品有独立的库存
|
|
|
|
|
+ - `state` 字段:状态(1可用,2不可用)
|
|
|
|
|
+ - [Source: docs/stories/006.006.goods-detail-spec-integration.story.md#76-85]
|
|
|
|
|
+
|
|
|
|
|
+- **父子关系约束**:
|
|
|
|
|
+ - 父子商品必须在同一租户下(`tenantId`相同)
|
|
|
|
|
+ - 子商品通过`spuId`字段关联到父商品
|
|
|
|
|
+ - 商品详情API返回`parent`对象包含父商品基本信息(id、name等)
|
|
|
|
|
+ - 公共商品列表API默认只返回父商品(spuId=0)
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#多租户支持]
|
|
|
|
|
+
|
|
|
|
|
+### API 规范
|
|
|
|
|
+- **获取子商品列表API** (`GET /api/v1/goods/{id}/children`):
|
|
|
|
|
+ - 功能:获取指定父商品的子商品列表,作为规格选项
|
|
|
|
|
+ - 返回:子商品数组,包含id、name、price、stock等字段
|
|
|
|
|
+ - 多租户过滤:自动包含tenantId参数,确保父子商品在同一租户下
|
|
|
|
|
+ - API路由:`packages/goods-module-mt/src/routes/public-goods-children.mt.ts`
|
|
|
|
|
+ - 路由聚合:通过`public-goods-aggregated.mt.ts`聚合(故事5已创建)
|
|
|
|
|
+ - [Source: docs/stories/006.006.goods-detail-spec-integration.story.md#88-91]
|
|
|
|
|
+
|
|
|
|
|
+- **商品详情API** (`GET /api/v1/goods/{id}`):
|
|
|
|
|
+ - 返回商品详情,父商品包含`children`字段(子商品列表),子商品包含`parent`对象
|
|
|
|
|
+ - API不再返回`spuName`字段,使用`parent.name`获取父商品名称
|
|
|
|
|
+ - 多租户过滤:自动包含tenantId参数
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#api设计]
|
|
|
|
|
+
|
|
|
|
|
+### 组件规范
|
|
|
|
|
+- **商品详情页 (`GoodsDetailPage`)**:
|
|
|
|
|
+ - 位置:`mini/src/pages/goods-detail/index.tsx`
|
|
|
|
|
+ - 当前状态:包含独立的"选择规格"按钮(第443-460行),点击调用`handleOpenSpecModal`函数
|
|
|
|
|
+ - 规格选择状态:`selectedSpec`(当前选择的规格),`showSpecModal`(规格选择器显示状态)
|
|
|
|
|
+ - 操作函数:`handleAddToCart`(第273-330行),`handleBuyNow`(第331-390行)
|
|
|
|
|
+ - 多规格判断:`hasSpecOptions`变量基于子商品数据是否存在
|
|
|
|
|
+ - 需要修改:移除独立"选择规格"按钮,重构操作函数添加自动弹窗逻辑,添加规格选择上下文
|
|
|
|
|
+ - [Source: mini/src/pages/goods-detail/index.tsx#L41-L45]
|
|
|
|
|
+ - [Source: mini/src/pages/goods-detail/index.tsx#L273-L330]
|
|
|
|
|
+ - [Source: mini/src/pages/goods-detail/index.tsx#L331-L390]
|
|
|
|
|
+
|
|
|
|
|
+- **规格选择器组件 (`GoodsSpecSelector`)**:
|
|
|
|
|
+ - 位置:`mini/src/components/goods-spec-selector/index.tsx`
|
|
|
|
|
+ - 当前props:`parentGoodsId`、`visible`、`onClose`、`onConfirm`、`currentSpec`、`currentQuantity`
|
|
|
|
|
+ - 功能:获取子商品列表作为规格选项,支持选择规格和数量
|
|
|
|
|
+ - API调用:`GET /api/v1/goods/{parentGoodsId}/children`获取子商品列表
|
|
|
|
|
+ - 需要扩展:支持`actionType`参数("add-to-cart"或"buy-now"),扩展`onConfirm`回调支持直接执行操作
|
|
|
|
|
+ - [Source: docs/stories/006.006.goods-detail-spec-integration.story.md#62-67]
|
|
|
|
|
+
|
|
|
|
|
+### 文件位置
|
|
|
|
|
+- **主要修改文件**:
|
|
|
|
|
+ - `mini/src/pages/goods-detail/index.tsx` - 移除独立"选择规格"按钮,重构操作函数,添加规格选择上下文
|
|
|
|
|
+ - `mini/src/components/goods-spec-selector/index.tsx` - 扩展组件支持直接操作执行
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#故事12]
|
|
|
|
|
+
|
|
|
|
|
+- **测试文件**:
|
|
|
|
|
+ - `mini/tests/unit/pages/goods-detail/goods-detail.test.tsx` - 更新集成测试验证新规格选择流程
|
|
|
|
|
+ - `mini/tests/unit/components/goods-spec-selector/goods-spec-selector.test.tsx` - 添加直接操作执行测试
|
|
|
|
|
+ - [Source: docs/architecture/testing-strategy.md#单元测试-unit-tests]
|
|
|
|
|
+
|
|
|
|
|
+- **相关文件**:
|
|
|
|
|
+ - `mini/src/contexts/CartContext.tsx` - 购物车上下文,已支持子商品添加
|
|
|
|
|
+ - `mini/src/api.ts` - API客户端配置
|
|
|
|
|
+ - `packages/goods-module-mt/src/routes/public-goods-aggregated.mt.ts` - 多租户商品API路由聚合
|
|
|
|
|
+
|
|
|
|
|
+### 技术约束
|
|
|
|
|
+- **多租户要求**:所有操作必须包含`tenantId`过滤,父子商品必须在同一租户下,API调用保持正确的租户上下文
|
|
|
|
|
+- **向后兼容性**:单规格商品(无子商品)的操作流程保持不变,现有功能不受影响
|
|
|
|
|
+- **性能考虑**:规格选择器弹出响应应快速,API调用应高效
|
|
|
|
|
+- **用户体验**:操作流程应流畅直观,减少用户操作步骤,保持规格选择状态
|
|
|
|
|
+- **小程序兼容性**:保持Taro小程序框架兼容性,确保在各平台正常工作
|
|
|
|
|
+- [Source: docs/architecture/tech-stack.md]
|
|
|
|
|
+- [Source: docs/architecture/source-tree.md]
|
|
|
|
|
+
|
|
|
|
|
+### 测试标准
|
|
|
|
|
+- **测试框架**:小程序使用Jest + Testing Library,商品管理界面使用Vitest + Testing Library
|
|
|
|
|
+- **测试位置**:`tests`文件夹与源码并列(例如:`mini/tests/unit/pages/goods-detail/`)
|
|
|
|
|
+- **单元测试位置**:`mini/tests/unit/pages/goods-detail/goods-detail.test.tsx`(商品详情页集成测试)
|
|
|
|
|
+- **组件测试位置**:`mini/tests/unit/components/goods-spec-selector/goods-spec-selector.test.tsx`
|
|
|
|
|
+- **测试覆盖率**:核心业务逻辑 > 80%,关键函数 > 90%
|
|
|
|
|
+- **测试策略**:验证新规格选择流程完整性、自动弹窗逻辑正确、规格状态保持、向后兼容性、无回归问题
|
|
|
|
|
+- **具体测试场景**:
|
|
|
|
|
+ 1. 多规格商品点击"加入购物车"自动弹出规格选择器
|
|
|
|
|
+ 2. 多规格商品点击"立即购买"自动弹出规格选择器
|
|
|
|
|
+ 3. 规格选择器中选择规格和数量后直接执行对应操作
|
|
|
|
|
+ 4. 规格状态保持,下次弹出自动选中上次选择
|
|
|
|
|
+ 5. 单规格商品操作流程保持不变(无弹窗)
|
|
|
|
|
+ 6. 无父子关系商品操作不受影响
|
|
|
|
|
+ 7. 用户取消规格选择后状态正确处理
|
|
|
|
|
+- **RPC客户端架构最佳实践**:使用单例模式的客户端管理器,在测试中正确mock客户端管理器的get()方法调用链
|
|
|
|
|
+- [Source: docs/architecture/testing-strategy.md#单元测试-unit-tests]
|
|
|
|
|
+- [Source: docs/architecture/coding-standards.md#rpc客户端架构最佳实践]
|
|
|
|
|
+
|
|
|
|
|
+## Change Log
|
|
|
|
|
+| Date | Version | Description | Author |
|
|
|
|
|
+|------|---------|-------------|--------|
|
|
|
|
|
+| 2025-12-15 | 1.0 | 初始故事创建 | Bob (Scrum Master) |
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+*此部分由开发代理在实施过程中填写*
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+
|
|
|
|
|
+## QA Results
|
|
|
|
|
+*此部分由QA代理在审查完成后填写*
|