Browse Source

📝 docs(prd): 更新史诗006父子商品多规格支持文档

- 更新史诗状态:故事8已完成,故事9-10待开始
- 进度更新为8/10故事完成 (80.0%)
- 新增故事9:父子商品名称关联查询优化
- 新增故事10:购物车商品名称显示优化
- 更新完成定义和技术要点

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 month ago
parent
commit
523c25c3a5
1 changed files with 97 additions and 17 deletions
  1. 97 17
      docs/prd/epic-006-parent-child-goods-multi-spec-support.md

+ 97 - 17
docs/prd/epic-006-parent-child-goods-multi-spec-support.md

@@ -1,9 +1,9 @@
 # 史诗006:父子商品多规格支持 - 棕地增强
 
 ## 史诗状态
-**进度**: 7/8 故事完成 (87.5%)
-**最近更新**: 2025-12-13 (故事8:购物车页面规格切换功能已添加)
-**当前状态**: 故事1-7已完成,故事8待开始
+**进度**: 8/10 故事完成 (80.0%)
+**最近更新**: 2025-12-14 (新增故事9:父子商品名称关联查询优化)
+**当前状态**: 故事1-8已完成,故事9待开始,故事10待开始
 
 ### 完成概览
 - ✅ **故事1**: 管理后台父子商品配置功能 (已完成)
@@ -13,7 +13,9 @@
 - ✅ **故事5**: 父子商品多规格选择组件开发 (已完成)
 - ✅ **故事6**: 商品详情页规格选择集成 (已完成)
 - ✅ **故事7**: 购物车和订单规格支持 (已完成)
-- ⏳ **故事8**: 购物车页面规格切换功能 (待开始)
+- ✅ **故事8**: 购物车页面规格切换功能 (已完成)
+- ⏳ **故事9**: 父子商品名称关联查询优化 (待开始)
+- ⏳ **故事10**: 购物车商品名称显示优化 (待开始)
 
 ## 史诗目标
 新增父子商品多规格支持功能,在商品添加购物车或立即购买时,能同时支持单规格和多规格选择,以子商品作为多规格选项,并支持手动指定子商品。
@@ -54,7 +56,9 @@
   4. ✅ 购物车和订单正确记录规格信息(故事7已完成)
   5. ✅ 商品列表页保持整洁(只显示父商品)(故事4已完成)
   6. ✅ 多租户隔离机制保持完整(故事1-7已实现)
-  7. ⏳ 用户能在购物车页面切换规格(故事8待实现)
+  7. ✅ 用户能在购物车页面切换规格(故事8已实现)
+  8. ⏳ 父子商品名称通过关联查询获取,解决spuName字段同步问题(故事9待实现)
+  9. ⏳ 购物车中父子商品显示完整的组合名称(父商品名称 + 子商品规格名称)(故事10待实现)
 
 ## 设计决策
 
@@ -259,7 +263,7 @@
      - **创建的文件**:
        - `mini/tests/unit/contexts/CartContext.test.tsx` - 购物车规格支持测试文件
 
-8. **故事8:购物车页面规格切换功能** ⏳ **待开始**
+8. **故事8:购物车页面规格切换功能** ✅ **已完成 (2025-12-13)**
    - **问题背景**:当前购物车页面显示已添加的商品,但如果用户想切换同一父商品下的不同规格(子商品),需要删除现有商品,重新到商品详情页选择规格再添加,用户体验不够流畅。
    - **解决方案**:在购物车页面增加规格切换功能,允许用户直接切换同一父商品下的不同子商品规格。
    - **功能需求**:
@@ -280,17 +284,91 @@
      - 购物车总价正确重新计算
      - 库存不足的规格无法选择或给出提示
      - 现有单规格商品购物车体验不受影响
+   - **完成状态**:
+    - ✅ 功能实现完成:扩展CartContext支持规格切换逻辑,集成GoodsSpecSelector组件,添加库存验证和错误处理
+    - ✅ 测试通过:为CartContext添加switchSpec单元测试,为购物车页面添加规格切换组件测试,23个测试全部通过
+    - ✅ 文件变更完成:更新CartContext.tsx、购物车页面、测试文件等(详见下方文件变更列表)
+    - ✅ 多租户兼容性和向后兼容性已验证
+   - **文件变更**:
+    - **修改的文件**:
+      - `mini/src/contexts/CartContext.tsx` - 扩展CartContext,添加switchSpec函数,更新CartItem接口,修复数据迁移逻辑(parentGoodsId默认值从item.id改为0)
+      - `mini/src/pages/cart/index.tsx` - 集成GoodsSpecSelector组件,添加规格切换功能,清理多余的调试信息
+      - `mini/tests/unit/contexts/CartContext.test.tsx` - 添加switchSpec函数单元测试
+      - `mini/tests/unit/pages/cart/index.test.tsx` - 添加购物车页面规格切换组件测试,修复测试结构使用真实CartContext,解决空购物车状态测试问题,修复库存不足提示测试,添加7个完整的规格切换集成测试
+      - `mini/tests/__mocks__/taroMock.ts` - 扩展Taro API mock,添加request方法支持
+      - `mini/src/components/goods-spec-selector/index.tsx` - 改进错误处理,解析API响应体获取具体错误消息
+      - `mini/src/pages/goods-detail/index.tsx` - 修复parentGoodsId计算逻辑,正确处理父子商品关系
+      - `mini/tests/unit/pages/goods-detail/goods-detail.test.tsx` - 更新测试期望,添加parentGoodsId字段验证
+      - `docs/stories/006.008.cart-spec-switching.story.md` - 更新任务状态和开发记录
+9. **故事9:父子商品名称关联查询优化** ⏳ **待开始**
+   - **问题背景**:当前系统使用`spuName`字段冗余存储父商品名称,以优化查询性能。但存在数据一致性问题:当父商品名称更新时,不会自动同步更新子商品的`spuName`字段。这导致购物车、订单等场景显示的商品名称可能不一致。
+   - **解决方案**:采用关联实体查询方案,通过`parent`对象关联查询获取父商品信息,逐步减少对`spuName`冗余字段的依赖,从根本上解决数据一致性问题。
+   - **功能需求**:
+     - 完善商品详情API:确保`parent`对象包含完整的父商品信息(至少包含`id`、`name`字段)
+     - 更新商品Schema:将`parent`字段的类型从`z.any()`改为具体的`GoodsSchema`或精简版父商品Schema
+     - 前端适配:优先使用`goods.parent?.name`获取父商品名称,后备使用`goods.spuName`保持向后兼容
+     - 逐步迁移:更新商品管理UI、购物车等组件,减少对`spuName`字段的直接依赖
+     - 保持向后兼容:API继续返回`spuName`字段,但前端逐步减少使用
+   - **技术实现**:
+     - 后端:完善`GoodsServiceMt.getById`方法,确保`parent`对象包含必要字段;更新商品Schema类型定义
+     - 前端:创建商品名称格式化工具函数,优先使用`parent.name`,后备使用`spuName`
+     - 组件更新:更新`GoodsParentChildPanel`、`GoodsManagement`等组件使用新的名称获取方式
+     - 测试:添加关联查询的单元测试和集成测试,确保数据一致性
+   - **验收标准**:
+     - 商品详情API返回的`parent`对象包含完整的父商品基本信息(id、name等)
+     - 前端组件能正确通过`goods.parent?.name`获取父商品名称
+     - 保持向后兼容:现有依赖`spuName`的代码继续正常工作
+     - 父子商品名称显示正确,无数据不一致问题
+     - 所有测试通过,无回归问题
+   - **完成状态**:
+     - ⏳ 功能待实现
+     - ⏳ 技术方案待设计
+     - ⏳ 测试待编写
+   - **文件变更**:
+     - **待修改的文件**:
+       - `packages/goods-module-mt/src/schemas/*.schema.mt.ts` - 更新`parent`字段类型定义
+       - `packages/goods-module-mt/src/services/goods.service.mt.ts` - 确保`parent`对象包含完整信息
+       - `packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx` - 更新父商品名称获取逻辑
+       - `packages/goods-management-ui-mt/src/components/GoodsManagement.tsx` - 更新商品名称显示逻辑
+       - `mini/src/utils/formatGoodsName.ts` - 创建商品名称格式化工具函数
+     - **可能新建的文件**:
+       - `packages/goods-module-mt/src/schemas/parent-goods.schema.mt.ts` - 父商品精简Schema
+       - 相关测试文件
+10. **故事10:购物车商品名称显示优化** ⏳ **待开始**
+   - **问题背景**:父子商品在管理后台配置时,父商品使用完整商品名称(如"连衣裙"),子商品使用规格名称(如"红色 大码"、"蓝色 中码")。在当前实现中,购物车页面(`mini/src/pages/cart/index.tsx:253`)使用`goodsName = latestGoods?.name || item.name`显示商品名称,对于子商品只显示规格名称,而没有显示父商品名称。购物车页面已经将商品名称和规格名称分开显示(`goods-title`显示商品名称,`specs-text`显示规格名称),但子商品的商品名称显示的是规格名称,而不是父商品名称,导致商品信息显示不完整。
+   - **解决方案**:优化购物车中父子商品的显示方式,利用商品详情API返回的`parent`对象获取父商品名称,商品名称显示父商品名称,规格名称显示子商品规格名称,提供清晰完整的商品信息。
+   - **功能需求**:
+     - 购物车中显示父子商品时,商品名称显示父商品名称,规格名称显示子商品规格名称
+     - 对于单规格商品(非父子商品,`parentGoodsId === 0`),保持现有显示方式不变,直接显示商品名称
+     - 确保订单提交页面(`mini/src/pages/order-submit/index.tsx:277`)等所有显示商品名称的地方都遵循同样的显示逻辑
+     - 保持购物车中商品名称显示的一致性和清晰性
+   - **技术实现**:
+     - 修改购物车页面(`mini/src/pages/cart/index.tsx`)的商品名称显示逻辑,在`goodsName`计算时判断是否为子商品(通过`parentGoodsId !== 0`或`spuId > 0`)
+     - 如果是子商品,商品名称优先使用`parent?.name`获取父商品名称(通过故事9实现的关联查询),后备使用`spuName`字段
+     - 规格名称使用`latestGoods?.name || '选择规格'`显示子商品规格名称(子商品的`name`字段就是规格名称)
+     - 修改订单提交页面(`mini/src/pages/order-submit/index.tsx`)的商品名称显示逻辑,遵循同样的显示原则
+     - 使用故事9创建的商品名称格式化工具函数,统一处理父子商品名称获取逻辑
+     - 确保多租户兼容性:父子商品在同一租户下,商品详情API返回完整的`parent`对象
+     - **优化**:逐步移除`CartItem`接口中的`spec`字段,避免数据冗余(子商品的`name`字段已经包含规格信息)
+   - **验收标准**:
+     - 购物车中父子商品显示时,商品名称显示父商品名称,规格名称显示子商品规格名称
+     - 单规格商品显示保持不变
+     - 订单提交页面、订单详情页等所有相关页面显示一致
+     - 现有功能不受影响,无回归问题
+     - 父子商品信息显示清晰完整,用户能直观了解商品全貌
    - **完成状态**:
      - ⏳ 功能待实现
      - ⏳ 技术方案待设计
      - ⏳ 测试待编写
    - **文件变更**:
      - **待修改的文件**:
-       - `mini/src/contexts/CartContext.tsx` - 扩展规格切换功能
-       - `mini/src/components/CartItem.tsx`(或类似组件)- 集成规格选择器
-       - `mini/tests/unit/contexts/CartContext.test.tsx` - 添加规格切换测试
+       - `mini/src/pages/cart/index.tsx` - 修改商品名称显示逻辑(第253行`goodsName`计算),移除对`item.spec`的依赖
+       - `mini/src/pages/order-submit/index.tsx` - 修改商品名称显示逻辑(第277行`item.name`显示)
+       - `mini/src/pages/goods-detail/index.tsx` - 移除添加购物车时设置`spec`字段的逻辑
+       - `mini/src/contexts/CartContext.tsx` - 移除`CartItem`接口中的`spec`字段,更新`switchSpec`函数
+       - 其他可能显示商品名称的订单相关组件
      - **可能新建的文件**:
-       - 购物车规格切换组件(如果需要)
+       - `mini/src/utils/formatGoodsName.ts` - 商品名称格式化工具函数(统一处理父子商品名称组合逻辑
 
 ## 兼容性要求
 - [x] 现有API保持向后兼容,新增端点不影响现有功能(故事2、4、7已确保)
@@ -305,19 +383,19 @@
 - **回滚计划**:移除新增API端点,恢复原有逻辑,保持多租户完整性
 
 ## 完成定义
-- [x] 所有故事完成,验收标准满足(7/8完成,故事8待实现)
-- [x] 现有功能通过测试验证(故事1-7测试通过)
-- [x] API变更经过兼容性测试(故事2-7 API测试通过)
-- [x] 多租户隔离机制保持完整(故事1-7已实现)
+- [x] 所有故事完成,验收标准满足(8/10完成,故事9-10待实现)
+- [x] 现有功能通过测试验证(故事1-8测试通过)
+- [x] API变更经过兼容性测试(故事2-8 API测试通过)
+- [x] 多租户隔离机制保持完整(故事1-8已实现)
 - [x] 性能测试通过,无明显性能下降(故事4添加数据库索引优化)
 - [x] 文档适当更新(史诗文档已更新)
-- [x] 现有功能无回归(故事1-7验证通过)
+- [x] 现有功能无回归(故事1-8验证通过)
 
 ## 技术要点
 
 ### 数据库层面
 - 利用现有`spuId`字段:0表示父商品或单规格商品,>0表示子商品
-- `spuName`字段存储父商品名称,便于展示
+- `spuName`字段存储父商品名称(冗余字段,逐步淘汰,改用关联查询)
 
 ### 多租户支持
 - 所有操作必须包含tenantId过滤
@@ -337,7 +415,9 @@
   - **关键**:`name`字段已经包含完整规格信息,`spec`字段可暂时忽略或设置为相同值
 - **商品详情页**:父商品信息展示,规格选择后使用选中商品的信息
 - **最大优势**:购物车和订单逻辑几乎不需要修改,只需正确选择商品
-- **购物车页面规格切换**(故事8):用户可在购物车页面直接切换同一父商品下的不同规格,无需删除重选,提升用户体验
+- **购物车页面规格切换**(故事8,已完成):用户可在购物车页面直接切换同一父商品下的不同规格,无需删除重选,提升用户体验
+- **父子商品名称关联查询**(故事9):通过关联查询获取父商品信息,解决`spuName`字段同步问题,逐步淘汰冗余字段
+- **商品名称显示优化**(故事10):购物车中父子商品分开显示,商品名称显示父商品名称,规格名称显示子商品规格名称,提供清晰完整的商品信息
 
 ---
 **史诗创建时间**:2025-12-06