# 史诗006：父子商品多规格支持 - 棕地增强

## 史诗状态
**进度**: 4/7 故事完成 (57%)
**最近更新**: 2025-12-12 (故事4：商品API父子商品支持优化已完成)
**当前状态**: 故事1-4已完成，故事5-7待实现

### 完成概览
- ✅ **故事1**: 管理后台父子商品配置功能 (已完成)
- ✅ **故事2**: 父子商品管理UI体验优化 (已完成)
- ✅ **故事3**: 子商品行内编辑功能 (已完成)
- ✅ **故事4**: 商品API父子商品支持优化 (已完成)
- ⏳ **故事5**: 父子商品多规格选择组件开发 (待实现)
- ⏳ **故事6**: 商品详情页规格选择集成 (待实现)
- ⏳ **故事7**: 购物车和订单规格支持 (待实现)

## 史诗目标
新增父子商品多规格支持功能，在商品添加购物车或立即购买时，能同时支持单规格和多规格选择，以子商品作为多规格选项，并支持手动指定子商品。

## 史诗描述

### 现有系统上下文
- **数据库支持**：商品表已有父子商品关系字段（spuId/spuName）
- **Schema支持**：所有商品Schema（Admin/User/Public）都包含spuId/spuName字段
- **UI实现**（故事2已完成）：
  - 商品管理UI已集成统一的父子商品管理面板（`GoodsParentChildPanel.tsx`）
  - 支持创建模式和编辑模式的不同行为
  - 包含子商品列表管理（`ChildGoodsList.tsx`）和批量创建（`BatchSpecCreatorInline.tsx`）组件
- **前端组件**：已有`GoodsSpecSelector`组件但被注释，购物车支持spec字段但无规格选择逻辑
- **技术栈**：TypeORM + Hono + React + Taro小程序 + 多租户架构
- **API路由**：
  - 小程序：使用`publicGoodsRoutesMt`（公共商品路由）
  - 管理后台：使用`adminGoodsRoutesMt`（已聚合父子商品管理API）
- **多租户特性**：商品实体有tenantId字段，API路由支持租户隔离和数据权限
- **已完成功能**（故事1-2）：
  - 管理员父子商品配置功能
  - 父子商品管理UI体验优化
  - 父子商品管理API（获取子商品列表、设为父商品、解除关系、批量创建）

### 增强详情
- **管理后台**（故事1-2已完成）：新增父子商品配置界面，支持手动关联已有商品和批量创建子商品
- **前端**：父子商品的多规格选择界面和逻辑，支持多租户环境
- **API调整**：
  - 故事2已完成：管理员父子商品管理API（获取子商品列表、设为父商品、解除关系、批量创建）
  - 故事4部分已实现：公共商品列表API已默认只返回父商品（spuId=0）
  - 故事4待实现：商品详情API父子商品支持优化、查询性能优化
  - **API策略**：公共API默认过滤只显示父商品，管理员API保持完整视图但支持spuId参数过滤
- **集成点**：多租户商品模块、商品管理UI、商品详情页、购物车系统、订单提交流程
- **成功标准**：
  1. ✅ 管理员能配置父子商品关系（故事1-2已完成）
  2. ✅ 管理员能直接在父子商品管理面板中编辑子商品信息（故事3已完成）
  3. ⏳ 用户能在商品详情页选择子商品作为规格（故事5-6待实现）
  4. ⏳ 购物车和订单正确记录规格信息（故事7待实现）
  5. ✅ 商品列表页保持整洁（只显示父商品）（故事4已完成）
  6. ✅ 多租户隔离机制保持完整（故事1-4已实现）

## 设计决策

### 1. 规格概念澄清
- **规格 = 子商品的名称**：子商品的`name`字段作为规格名称
- **规格选择 = 选择子商品**：选择规格时实际选择对应的子商品
- **购物车逻辑简化**：
  - 如果选择规格：使用子商品的`id`、`name`、`price`、`stock`
  - 如果不选择规格：使用父商品的`id`、`name`、`price`、`stock`
  - **关键洞察**：`name`字段已经包含完整的规格信息，`spec`字段可能暂时不需要
- **核心优势**：购物车和订单系统几乎不需要修改

### 2. 商品列表展示策略
- **商品列表页**（首页、分类页、搜索页）：只显示父商品（spuId=0）
- **商品详情页**：显示父商品详情 + 规格选择器（子商品作为选项）
- **单规格商品**：保持现有行为不变（spuId=0且无子商品）

### 3. API设计
- **公共商品列表API**（`/api/v1/goods`）：默认只返回父商品（spuId=0）
- **商品详情API**（`/api/v1/goods/:id`）：
  - 父商品：返回商品详情 + 子商品列表（作为规格选项）
  - 子商品：返回子商品详情 + 父商品基本信息
- **新增API**（故事2已实现）：
  - `GET /api/v1/goods/:id/children` - 获取指定父商品的子商品列表
  - `POST /api/v1/goods/:id/set-as-parent` - 将普通商品设为父商品
  - `DELETE /api/v1/goods/:id/parent` - 解除子商品的父子关系
  - `POST /api/v1/goods/batch-create-children` - 批量创建子商品（支持事务）
- **API聚合策略**：通过`admin-goods-aggregated.mt.ts`聚合基础CRUD和父子商品管理路由，保持`adminGoodsRoutesMt`名称不变，前端代码无需修改
- **管理员商品API策略**：
  - 默认显示所有商品（包括父子商品），保持完整管理视图
  - 支持`spuId`查询参数过滤，管理员可通过`spuId=0`只查看父商品
  - 在管理员商品管理列表页面添加父子商品关系展示和筛选功能
  - 添加"只显示父商品"筛选选项，提升管理体验

### 4. 父子商品配置方式
1. **手动关联**：在创建/编辑父商品时，选择已有商品作为子商品
2. **批量创建**：创建父商品时，同时创建多个子商品规格（如不同颜色、尺寸等）

## 故事

1. **故事1：管理后台父子商品配置功能** ✅ **已完成 (2025-12-07)**
   - 在商品管理UI中添加spuId/spuName字段表单控件
   - 新增子商品关联选择器，支持选择已有商品作为子商品
   - 新增批量子商品创建功能，支持统一创建多个子商品规格
   - 父子商品关系展示和编辑界面
   - **验收标准**：管理员能成功配置父子商品关系
   - **完成状态**：
     - ✅ 功能实现完成
     - ✅ 单元测试通过（31个测试用例）
     - ✅ 集成测试通过（后端6个 + 前端5个）
     - ✅ 代码已提交并推送到远程仓库

2. **故事2：父子商品管理UI体验优化** ✅ **已完成 (2025-12-10)**
   - 在商品创建和编辑页面都添加统一的父子商品管理面板
   - 面板智能支持创建模式和编辑模式的不同行为
   - 创建模式：支持设为父商品、选择父商品、批量创建子商品规格模板
   - 编辑模式：支持父子关系列表展示、子商品管理、关系解除
   - 将批量创建子商品功能整合到面板中，支持创建时批量创建
   - 面板与表单数据实时同步，确保提交数据一致性
   - **API实现**：在现有`adminGoodsRoutesMt`中聚合父子商品管理API（获取子商品列表、设为父商品、解除关系、批量创建）
   - **验收标准**：管理员能在创建和编辑时一次性完成商品和规格配置，提高工作效率；前端代码无需修改即可使用新API
   - **完成状态**：
     - ✅ 父子商品管理API实现完成（17个集成测试全部通过）
     - ✅ `GoodsParentChildPanel.tsx`组件已创建并支持创建/编辑模式
     - ✅ `ChildGoodsList.tsx`和`BatchSpecCreatorInline.tsx`组件已创建并集成到面板中
     - ✅ `GoodsManagement.tsx`已集成新面板到创建和编辑表单
     - ✅ 表单数据同步和提交逻辑已实现
     - ✅ 保持与现有功能的兼容性，平滑迁移用户体验
   - **技术实现细节**：
     - **API聚合**：通过`admin-goods-aggregated.mt.ts`聚合基础CRUD和父子商品管理路由，保持`adminGoodsRoutesMt`名称不变
     - **面板设计**：采用标签页设计（关系视图、批量创建、管理子商品），支持不同模式下的差异化行为
     - **数据同步**：通过`onDataChange`回调实现面板与表单数据的实时同步
     - **批量创建**：支持事务处理，子商品继承父商品的分类、供应商、商户等信息

3. **故事3：子商品行内编辑功能** ✅ **已完成 (2025-12-11)**
   - **问题背景**：当前在商品编辑对话框中，管理子商品时，点击编辑按钮直接调用更新API，并没有切换成更新表单
   - **解决方案**：在子商品列表中实现行内编辑功能，点击编辑时将当前行切换为可编辑状态
   - **功能需求**：
     - 在`ChildGoodsList.tsx`组件中添加行内编辑模式
     - 点击编辑按钮时，当前行切换为表单输入模式
     - 支持编辑子商品的基本信息：名称、价格、成本价、库存、排序、状态
     - 提供保存和取消按钮，保存时调用更新API
     - 编辑完成后自动刷新子商品列表
   - **技术实现**：
     - 扩展`ChildGoodsList`组件，支持`editingChildId`状态管理
     - 添加行内编辑表单，复用现有商品表单验证逻辑
     - 集成商品更新API调用
     - 保持与现有父子商品管理面板的集成
   - **验收标准**：管理员能在父子商品管理面板中直接编辑子商品信息，无需跳转到其他页面，编辑体验流畅自然
   - **完成状态**：
     - ✅ 成功扩展了`ChildGoodsList`组件，添加了行内编辑功能
     - ✅ 实现了`ChildGoodsInlineEditForm`组件，支持所有必需字段的编辑
     - ✅ 集成了商品更新API调用，包含完整的错误处理和加载状态
     - ✅ 实现了编辑完成后的自动刷新逻辑
     - ✅ 修改了`handleEdit`函数逻辑：行内编辑现在优先于`onEditChild`回调
     - ✅ 添加了`enableInlineEdit`配置选项，支持灵活控制行内编辑行为
     - ✅ 添加了完整的单元测试，覆盖编辑模式切换、表单验证、API调用等场景
     - ✅ 更新了现有测试文件，确保向后兼容性
   - **文件变更**：
     - **新建文件**：
       - `packages/goods-management-ui-mt/src/components/ChildGoodsInlineEditForm.tsx` - 行内编辑表单组件
       - `packages/goods-management-ui-mt/tests/unit/ChildGoodsInlineEditForm.test.tsx` - 行内编辑表单测试
     - **修改文件**：
       - `packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx` - 扩展行内编辑功能
       - `packages/goods-management-ui-mt/tests/unit/ChildGoodsList.test.tsx` - 更新测试，添加行内编辑功能测试
       - `docs/stories/006.003.child-goods-inline-edit.story.md` - 更新任务状态和开发记录

4. **故事4：商品API父子商品支持优化** ✅ **已完成 (2025-12-12)**
   - **已完成功能**：
     - ✅ 商品详情API：根据商品类型返回相应数据（父商品+子商品列表或子商品+父商品信息）
     - ✅ 管理员商品API：增强父子商品关系展示和查询优化，**不默认过滤父商品**（管理员需要完整视图）
     - ✅ 商品列表查询性能优化：添加spuId字段数据库索引
     - ✅ 添加spuId查询参数支持，管理员可通过`spuId=0`过滤只显示父商品
     - ✅ **API架构增强**：扩展shared-crud支持自定义服务工厂和独立的listFilters/detailFilters配置
     - ✅ **商品模块路由优化**：
       - 公共商品路由：listFilters: { state: 1, spuId: 0 }, detailFilters: { state: 1 }
       - 管理员商品路由：listFilters: {}, detailFilters: {}（无过滤）
     - ✅ **向后兼容性**：修复详情查询过滤逻辑，当没有提供detailFilters时使用defaultFilters
     - ✅ **Schema扩展**：更新商品Schema支持children和parent字段
     - ✅ **测试完善**：添加完整的集成测试，修复现有测试
   - **技术实现细节**：
     - **shared-crud扩展**：添加serviceFactory、listFilters、detailFilters选项，支持自定义商品服务
     - **过滤逻辑优化**：列表查询使用listFilters（优先）或defaultFilters，详情查询使用detailFilters（优先）或defaultFilters
     - **数据库索引**：添加spuId字段索引和复合索引`@Index(['tenantId', 'spuId'])`优化查询性能
     - **自定义商品服务**：GoodsServiceMt支持父子商品详情返回，包含租户ID过滤确保数据安全
     - **API测试**：添加shared-crud集成测试验证listFilters和detailFilters功能
   - **验收标准**：API变更保持向后兼容，商品详情包含完整的父子商品信息，商品列表查询性能良好，管理员可灵活过滤父子商品，所有测试通过
   - **完成状态**：
     - ✅ 功能实现完成
     - ✅ 扩展shared-crud支持自定义服务工厂和独立过滤配置
     - ✅ 更新商品模块路由使用新的过滤选项
     - ✅ 添加spuId字段数据库索引优化查询性能
     - ✅ 修复详情查询过滤逻辑，保持向后兼容性
     - ✅ 更新商品Schema支持children和parent字段
     - ✅ 修复测试用例中的权限错误期望值
     - ✅ 添加完整的集成测试验证父子商品功能
     - ✅ 代码已提交并推送到远程仓库

5. **故事5：父子商品多规格选择组件开发** ⏳ **待实现**
   - 激活并增强现有的`GoodsSpecSelector`组件
   - 支持父子商品关系，以子商品名称作为规格选项显示
   - 规格选择实际选择对应的子商品ID
   - 适配多租户商品数据查询
   - **验收标准**：规格选择器能正确显示子商品名称作为规格，并能选择对应的子商品

6. **故事6：商品详情页规格选择集成** ⏳ **待实现**
   - 在商品详情页集成规格选择组件
   - "立即购买"和"加入购物车"支持规格选择
   - 规格选择后使用子商品的价格和库存信息
   - 多租户环境下的商品规格数据获取
   - **验收标准**：用户能在商品详情页成功选择规格，系统使用正确的子商品价格和库存

7. **故事7：购物车和订单规格支持** ⏳ **待实现**
   - **购物车最小化修改**：适配`addToCart`逻辑，支持添加子商品（使用子商品信息填充CartItem）
   - **规格信息显示**：购物车和订单中通过`name`字段显示完整规格信息
   - **订单系统兼容**：订单创建使用商品ID（可能是子商品ID），保持现有逻辑
   - **多租户兼容性**：确保父子商品在同一租户下
   - **验收标准**：购物车能正确添加子商品，订单显示完整商品名称，现有单规格商品不受影响

## 兼容性要求
- [ ] 现有API保持向后兼容，新增端点不影响现有功能
- [ ] 数据库schema向后兼容，利用现有spuId字段
- [ ] UI变更遵循现有设计模式
- [ ] 性能影响最小化，特别是商品列表查询
- [ ] 多租户隔离机制保持完整

## 风险缓解
- **主要风险**：API变更影响现有客户端，规格选择逻辑影响购物车功能
- **缓解措施**：逐步集成，保持向后兼容，现有无规格商品继续正常工作
- **回滚计划**：移除新增API端点，恢复原有逻辑，保持多租户完整性

## 完成定义
- [ ] 所有故事完成，验收标准满足（4/7完成）
- [x] 现有功能通过测试验证（故事1-4测试通过）
- [x] API变更经过兼容性测试（故事2-4 API测试通过）
- [x] 多租户隔离机制保持完整（故事1-4已实现）
- [x] 性能测试通过，无明显性能下降（故事4添加数据库索引优化）
- [x] 文档适当更新（史诗文档已更新）
- [x] 现有功能无回归（故事1-4验证通过）

## 技术要点

### 数据库层面
- 利用现有`spuId`字段：0表示父商品或单规格商品，>0表示子商品
- `spuName`字段存储父商品名称，便于展示

### 多租户支持
- 所有操作必须包含tenantId过滤
- 父子商品必须在同一租户下
- 数据权限机制保持完整

### 性能考虑
- 商品列表查询添加`spuId=0`条件
- 子商品列表查询使用分页
- 规格选择器数据懒加载

### 前端适配
- **规格选择器**：显示子商品名称作为规格选项，选择时使用子商品信息
- **购物车逻辑极致简化**：
  - 如果选择规格：`CartItem`使用子商品的`id`、`name`、`price`、`stock`
  - 如果不选择规格：`CartItem`使用父商品的`id`、`name`、`price`、`stock`
  - **关键**：`name`字段已经包含完整规格信息，`spec`字段可暂时忽略或设置为相同值
- **商品详情页**：父商品信息展示，规格选择后使用选中商品的信息
- **最大优势**：购物车和订单逻辑几乎不需要修改，只需正确选择商品

---
**史诗创建时间**：2025-12-06
**创建人**：John (Product Manager)
**技术栈**：TypeORM + Hono + React + Taro小程序 + 多租户架构
**优先级**：高（支持电商核心功能）