Explorar el Código

📝 docs(prd): 优化史诗006故事9和故事10内容

- 明确故事9目标为故事10的购物车显示做准备
- 从goods.schema.mt.ts中移除spuName字段,API不再返回该字段
- 故事9和故事10不再使用spuName后备逻辑,直接使用parent.name
- 移除创建formatGoodsName.ts工具函数的描述
- 更新史诗上下文和数据库层面描述

🤖 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 hace 1 mes
padre
commit
78799e6e0d

+ 27 - 26
docs/prd/epic-006-parent-child-goods-multi-spec-support.md

@@ -2,7 +2,7 @@
 
 ## 史诗状态
 **进度**: 8/10 故事完成 (80.0%)
-**最近更新**: 2025-12-14 (新增故事9:父子商品名称关联查询优化)
+**最近更新**: 2025-12-14 (新增故事9:父子商品名称关联查询优化(为购物车显示做准备))
 **当前状态**: 故事1-8已完成,故事9待开始,故事10待开始
 
 ### 完成概览
@@ -14,7 +14,7 @@
 - ✅ **故事6**: 商品详情页规格选择集成 (已完成)
 - ✅ **故事7**: 购物车和订单规格支持 (已完成)
 - ✅ **故事8**: 购物车页面规格切换功能 (已完成)
-- ⏳ **故事9**: 父子商品名称关联查询优化 (待开始)
+- ⏳ **故事9**: 父子商品名称关联查询优化(为购物车显示做准备) (待开始)
 - ⏳ **故事10**: 购物车商品名称显示优化 (待开始)
 
 ## 史诗目标
@@ -24,7 +24,7 @@
 
 ### 现有系统上下文
 - **数据库支持**:商品表已有父子商品关系字段(spuId/spuName)
-- **Schema支持**:所有商品Schema(Admin/User/Public)都包含spuId/spuName字段
+- **Schema支持**:所有商品Schema(Admin/User/Public)都包含spuId字段,spuName字段将在故事9中移除,改用parent对象关联查询
 - **UI实现**(故事2已完成):
   - 商品管理UI已集成统一的父子商品管理面板(`GoodsParentChildPanel.tsx`)
   - 支持创建模式和编辑模式的不同行为
@@ -57,7 +57,7 @@
   5. ✅ 商品列表页保持整洁(只显示父商品)(故事4已完成)
   6. ✅ 多租户隔离机制保持完整(故事1-7已实现)
   7. ✅ 用户能在购物车页面切换规格(故事8已实现)
-  8. ⏳ 父子商品名称通过关联查询获取,解决spuName字段同步问题(故事9待实现)
+  8. ⏳ 父子商品名称通过关联查询获取,为购物车显示提供准确父商品名称(故事9待实现)
   9. ⏳ 购物车中父子商品显示完整的组合名称(父商品名称 + 子商品规格名称)(故事10待实现)
 
 ## 设计决策
@@ -300,26 +300,28 @@
       - `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`冗余字段的依赖,从根本上解决数据一致性问题。
+9. **故事9:父子商品名称关联查询优化(为购物车显示做准备)** ⏳ **待开始**
+   - **问题背景**:故事10"购物车商品名称显示优化"需要在购物车中分开显示父子商品:商品名称显示父商品名称,规格名称显示子商品规格名称。当前系统使用`spuName`字段冗余存储父商品名称,但存在数据一致性问题:当父商品名称更新时,不会自动同步更新子商品的`spuName`字段。这导致购物车等场景显示的商品名称可能不一致。**故事9的目标是为故事10提供基础支持**,建立可靠的父子商品名称关联查询机制。
+   - **解决方案**:采用关联实体查询方案,通过`parent`对象关联查询获取父商品信息,为购物车提供准确、实时的父商品名称,解决`spuName`字段的数据一致性问题。
    - **功能需求**:
-     - 完善商品详情API:确保`parent`对象包含完整的父商品信息(至少包含`id`、`name`字段)
-     - 更新商品Schema:将`parent`字段的类型从`z.any()`改为具体的`GoodsSchema`或精简版父商品Schema
-     - 前端适配:优先使用`goods.parent?.name`获取父商品名称,后备使用`goods.spuName`保持向后兼容
-     - 逐步迁移:更新商品管理UI、购物车等组件,减少对`spuName`字段的直接依赖
-     - 保持向后兼容:API继续返回`spuName`字段,但前端逐步减少使用
+     - **核心目标**:为故事10的小程序购物车名称显示提供数据基础
+     - 完善商品详情API:确保返回的`parent`对象包含完整的父商品基本信息(至少包含`id`、`name`字段)
+     - 更新商品Schema:将`parent`字段的类型从`z.any()`改为具体的父商品Schema,确保类型安全
+     - **小程序购物车适配**:确保购物车页面能通过`goods.parent?.name`获取父商品名称,用于故事10的商品名称显示优化
+     - API不再返回`spuName`字段,前端使用`parent.name`获取父商品名称
+     - **优先关注小程序端**:管理后台的更新可以后续进行,故事9主要服务于小程序购物车需求
    - **技术实现**:
-     - 后端:完善`GoodsServiceMt.getById`方法,确保`parent`对象包含必要字段;更新商品Schema类型定义
-     - 前端:创建商品名称格式化工具函数,优先使用`parent.name`,后备使用`spuName`
-     - 组件更新:更新`GoodsParentChildPanel`、`GoodsManagement`等组件使用新的名称获取方式
-     - 测试:添加关联查询的单元测试和集成测试,确保数据一致性
+     - 后端:完善`GoodsServiceMt.getById`方法,确保`parent`对象包含必要字段;更新商品Schema类型定义,并从商品Schema中移除`spuName`字段
+     - **小程序端适配**:购物车页面直接使用`goods.parent?.name`获取父商品名称,不再依赖`spuName`字段,无需专门的工具函数
+     - **购物车数据准备**:确保购物车中使用的商品数据包含完整的`parent`对象信息
+     - 测试:添加关联查询的单元测试和集成测试,确保数据一致性和购物车可用性
    - **验收标准**:
      - 商品详情API返回的`parent`对象包含完整的父商品基本信息(id、name等)
-     - 前端组件能正确通过`goods.parent?.name`获取父商品名称
-     - 保持向后兼容:现有依赖`spuName`的代码继续正常工作
-     - 父子商品名称显示确,无数据不一致问题
+     - 购物车页面能正确通过`goods.parent?.name`获取父商品名称(为故事10做准备)
+     - API不再返回`spuName`字段,前端代码直接使用`parent.name`获取父商品名称
+     - 父子商品名称显示确,无数据不一致问题
      - 所有测试通过,无回归问题
+     - **故事10能顺利基于故事9的实现完成购物车商品名称显示优化**
    - **完成状态**:
      - ⏳ 功能待实现
      - ⏳ 技术方案待设计
@@ -328,9 +330,9 @@
      - **待修改的文件**:
        - `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
        - 相关测试文件
@@ -344,10 +346,10 @@
      - 保持购物车中商品名称显示的一致性和清晰性
    - **技术实现**:
      - 修改购物车页面(`mini/src/pages/cart/index.tsx`)的商品名称显示逻辑,在`goodsName`计算时判断是否为子商品(通过`parentGoodsId !== 0`或`spuId > 0`)
-     - 如果是子商品,商品名称优先使用`parent?.name`获取父商品名称(通过故事9实现的关联查询),后备使用`spuName`字段
+     - 如果是子商品,商品名称直接使用`parent.name`获取父商品名称(通过故事9实现的关联查询),不再使用`spuName`字段
      - 规格名称使用`latestGoods?.name || '选择规格'`显示子商品规格名称(子商品的`name`字段就是规格名称)
      - 修改订单提交页面(`mini/src/pages/order-submit/index.tsx`)的商品名称显示逻辑,遵循同样的显示原则
-     - 使用故事9创建的商品名称格式化工具函数,统一处理父子商品名称获取逻辑
+     - 直接使用`parent.name`获取父商品名称,不再依赖`spuName`字段,统一处理父子商品名称获取逻辑
      - 确保多租户兼容性:父子商品在同一租户下,商品详情API返回完整的`parent`对象
      - **优化**:逐步移除`CartItem`接口中的`spec`字段,避免数据冗余(子商品的`name`字段已经包含规格信息)
    - **验收标准**:
@@ -367,8 +369,7 @@
        - `mini/src/pages/goods-detail/index.tsx` - 移除添加购物车时设置`spec`字段的逻辑
        - `mini/src/contexts/CartContext.tsx` - 移除`CartItem`接口中的`spec`字段,更新`switchSpec`函数
        - 其他可能显示商品名称的订单相关组件
-     - **可能新建的文件**:
-       - `mini/src/utils/formatGoodsName.ts` - 商品名称格式化工具函数(统一处理父子商品名称组合逻辑)
+     - **可能新建的文件**:无(无需新建工具函数,直接使用`parent.name`)
 
 ## 兼容性要求
 - [x] 现有API保持向后兼容,新增端点不影响现有功能(故事2、4、7已确保)
@@ -395,7 +396,7 @@
 
 ### 数据库层面
 - 利用现有`spuId`字段:0表示父商品或单规格商品,>0表示子商品
-- `spuName`字段存储父商品名称(冗余字段,逐步淘汰,改用关联查询)
+- `spuName`字段存储父商品名称(冗余字段,故事9中移除,改用关联查询)
 
 ### 多租户支持
 - 所有操作必须包含tenantId过滤
@@ -416,7 +417,7 @@
 - **商品详情页**:父商品信息展示,规格选择后使用选中商品的信息
 - **最大优势**:购物车和订单逻辑几乎不需要修改,只需正确选择商品
 - **购物车页面规格切换**(故事8,已完成):用户可在购物车页面直接切换同一父商品下的不同规格,无需删除重选,提升用户体验
-- **父子商品名称关联查询**(故事9):通过关联查询获取父商品信息,解决`spuName`字段同步问题,逐步淘汰冗余字段
+- **父子商品名称关联查询**(故事9):通过关联查询获取父商品信息,为故事10的购物车商品名称显示提供准确数据,解决`spuName`字段同步问题
 - **商品名称显示优化**(故事10):购物车中父子商品分开显示,商品名称显示父商品名称,规格名称显示子商品规格名称,提供清晰完整的商品信息
 
 ---

+ 0 - 8
packages/goods-module-mt/src/schemas/goods.schema.mt.ts

@@ -88,10 +88,6 @@ export const GoodsSchema = z.object({
     description: '主商品ID',
     example: 0
   }),
-  spuName: z.string().max(255, '主商品名称最多255个字符').nullable().optional().openapi({
-    description: '主商品名称',
-    example: 'iPhone系列'
-  }),
   childGoodsIds: z.array(z.number().int().positive('子商品ID必须为正整数')).optional().default([]).openapi({
     description: '子商品ID列表',
     example: [2, 3, 4]
@@ -205,10 +201,6 @@ export const CreateGoodsDto = z.object({
     description: '主商品ID',
     example: 0
   }),
-  spuName: z.string().max(255, '主商品名称最多255个字符').nullable().optional().openapi({
-    description: '主商品名称',
-    example: 'iPhone系列'
-  }),
   lowestBuy: z.number().int().positive('最小起购量必须为正整数').default(1).openapi({
     description: '最小起购量',
     example: 1