|
@@ -1,9 +1,9 @@
|
|
|
# 史诗006:父子商品多规格支持 - 棕地增强
|
|
# 史诗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**: 管理后台父子商品配置功能 (已完成)
|
|
- ✅ **故事1**: 管理后台父子商品配置功能 (已完成)
|
|
@@ -13,7 +13,9 @@
|
|
|
- ✅ **故事5**: 父子商品多规格选择组件开发 (已完成)
|
|
- ✅ **故事5**: 父子商品多规格选择组件开发 (已完成)
|
|
|
- ✅ **故事6**: 商品详情页规格选择集成 (已完成)
|
|
- ✅ **故事6**: 商品详情页规格选择集成 (已完成)
|
|
|
- ✅ **故事7**: 购物车和订单规格支持 (已完成)
|
|
- ✅ **故事7**: 购物车和订单规格支持 (已完成)
|
|
|
-- ⏳ **故事8**: 购物车页面规格切换功能 (待开始)
|
|
|
|
|
|
|
+- ✅ **故事8**: 购物车页面规格切换功能 (已完成)
|
|
|
|
|
+- ⏳ **故事9**: 父子商品名称关联查询优化 (待开始)
|
|
|
|
|
+- ⏳ **故事10**: 购物车商品名称显示优化 (待开始)
|
|
|
|
|
|
|
|
## 史诗目标
|
|
## 史诗目标
|
|
|
新增父子商品多规格支持功能,在商品添加购物车或立即购买时,能同时支持单规格和多规格选择,以子商品作为多规格选项,并支持手动指定子商品。
|
|
新增父子商品多规格支持功能,在商品添加购物车或立即购买时,能同时支持单规格和多规格选择,以子商品作为多规格选项,并支持手动指定子商品。
|
|
@@ -54,7 +56,9 @@
|
|
|
4. ✅ 购物车和订单正确记录规格信息(故事7已完成)
|
|
4. ✅ 购物车和订单正确记录规格信息(故事7已完成)
|
|
|
5. ✅ 商品列表页保持整洁(只显示父商品)(故事4已完成)
|
|
5. ✅ 商品列表页保持整洁(只显示父商品)(故事4已完成)
|
|
|
6. ✅ 多租户隔离机制保持完整(故事1-7已实现)
|
|
6. ✅ 多租户隔离机制保持完整(故事1-7已实现)
|
|
|
- 7. ⏳ 用户能在购物车页面切换规格(故事8待实现)
|
|
|
|
|
|
|
+ 7. ✅ 用户能在购物车页面切换规格(故事8已实现)
|
|
|
|
|
+ 8. ⏳ 父子商品名称通过关联查询获取,解决spuName字段同步问题(故事9待实现)
|
|
|
|
|
+ 9. ⏳ 购物车中父子商品显示完整的组合名称(父商品名称 + 子商品规格名称)(故事10待实现)
|
|
|
|
|
|
|
|
## 设计决策
|
|
## 设计决策
|
|
|
|
|
|
|
@@ -259,7 +263,7 @@
|
|
|
- **创建的文件**:
|
|
- **创建的文件**:
|
|
|
- `mini/tests/unit/contexts/CartContext.test.tsx` - 购物车规格支持测试文件
|
|
- `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已确保)
|
|
- [x] 现有API保持向后兼容,新增端点不影响现有功能(故事2、4、7已确保)
|
|
@@ -305,19 +383,19 @@
|
|
|
- **回滚计划**:移除新增API端点,恢复原有逻辑,保持多租户完整性
|
|
- **回滚计划**:移除新增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] 性能测试通过,无明显性能下降(故事4添加数据库索引优化)
|
|
|
- [x] 文档适当更新(史诗文档已更新)
|
|
- [x] 文档适当更新(史诗文档已更新)
|
|
|
-- [x] 现有功能无回归(故事1-7验证通过)
|
|
|
|
|
|
|
+- [x] 现有功能无回归(故事1-8验证通过)
|
|
|
|
|
|
|
|
## 技术要点
|
|
## 技术要点
|
|
|
|
|
|
|
|
### 数据库层面
|
|
### 数据库层面
|
|
|
- 利用现有`spuId`字段:0表示父商品或单规格商品,>0表示子商品
|
|
- 利用现有`spuId`字段:0表示父商品或单规格商品,>0表示子商品
|
|
|
-- `spuName`字段存储父商品名称,便于展示
|
|
|
|
|
|
|
+- `spuName`字段存储父商品名称(冗余字段,逐步淘汰,改用关联查询)
|
|
|
|
|
|
|
|
### 多租户支持
|
|
### 多租户支持
|
|
|
- 所有操作必须包含tenantId过滤
|
|
- 所有操作必须包含tenantId过滤
|
|
@@ -337,7 +415,9 @@
|
|
|
- **关键**:`name`字段已经包含完整规格信息,`spec`字段可暂时忽略或设置为相同值
|
|
- **关键**:`name`字段已经包含完整规格信息,`spec`字段可暂时忽略或设置为相同值
|
|
|
- **商品详情页**:父商品信息展示,规格选择后使用选中商品的信息
|
|
- **商品详情页**:父商品信息展示,规格选择后使用选中商品的信息
|
|
|
- **最大优势**:购物车和订单逻辑几乎不需要修改,只需正确选择商品
|
|
- **最大优势**:购物车和订单逻辑几乎不需要修改,只需正确选择商品
|
|
|
-- **购物车页面规格切换**(故事8):用户可在购物车页面直接切换同一父商品下的不同规格,无需删除重选,提升用户体验
|
|
|
|
|
|
|
+- **购物车页面规格切换**(故事8,已完成):用户可在购物车页面直接切换同一父商品下的不同规格,无需删除重选,提升用户体验
|
|
|
|
|
+- **父子商品名称关联查询**(故事9):通过关联查询获取父商品信息,解决`spuName`字段同步问题,逐步淘汰冗余字段
|
|
|
|
|
+- **商品名称显示优化**(故事10):购物车中父子商品分开显示,商品名称显示父商品名称,规格名称显示子商品规格名称,提供清晰完整的商品信息
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
**史诗创建时间**:2025-12-06
|
|
**史诗创建时间**:2025-12-06
|