|
@@ -0,0 +1,155 @@
|
|
|
|
|
+# Story 006.011: 子商品删除功能实现
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+Draft
|
|
|
|
|
+
|
|
|
|
|
+## Story
|
|
|
|
|
+**As a** 管理员,
|
|
|
|
|
+**I want** 在父子商品管理面板中删除不需要的子商品规格,
|
|
|
|
|
+**so that** 我能管理商品规格清单,保持商品数据的整洁和准确
|
|
|
|
|
+
|
|
|
|
|
+## Acceptance Criteria
|
|
|
|
|
+1. 管理员能在父子商品管理面板中成功删除子商品
|
|
|
|
|
+2. 删除前有确认提示,防止误操作
|
|
|
|
|
+3. 删除后子商品列表实时更新
|
|
|
|
|
+4. 删除操作仅影响当前租户的数据,多租户隔离保持完整
|
|
|
|
|
+5. 现有功能不受影响,无回归问题
|
|
|
|
|
+
|
|
|
|
|
+## Tasks / Subtasks
|
|
|
|
|
+- [ ] 任务1:在GoodsParentChildPanel组件中添加onDeleteChild回调函数 (AC: 1, 2, 3)
|
|
|
|
|
+ - [ ] 检查GoodsParentChildPanel当前是否传递onDeleteChild回调给ChildGoodsList组件
|
|
|
|
|
+ - [ ] 在GoodsParentChildPanel组件中添加onDeleteChild回调函数处理子商品删除逻辑
|
|
|
|
|
+ - [ ] 实现删除确认对话框,使用现有Dialog组件防止误操作
|
|
|
|
|
+ - [ ] 添加删除状态管理(加载中、错误处理)
|
|
|
|
|
+- [ ] 任务2:调用商品删除API实现子商品实体删除 (AC: 1, 3, 4)
|
|
|
|
|
+ - [ ] 使用商品删除API:`DELETE /api/v1/goods/:id`(通用商品删除API)
|
|
|
|
|
+ - [ ] 添加API调用Mutation,包含完整的错误处理和加载状态
|
|
|
|
|
+ - [ ] 验证商品必须是子商品(spuId > 0)且在当前租户下
|
|
|
|
|
+ - [ ] 删除成功后调用refetch刷新子商品列表数据
|
|
|
|
|
+ - [ ] 更新本地状态(如需要)
|
|
|
|
|
+- [ ] 任务3:更新ChildGoodsList组件删除按钮的视觉反馈 (AC: 1, 2)
|
|
|
|
|
+ - [ ] 确保删除按钮在点击时有适当的视觉反馈
|
|
|
|
|
+ - [ ] 在删除操作期间禁用按钮,防止重复点击
|
|
|
|
|
+ - [ ] 添加加载状态指示器
|
|
|
|
|
+- [ ] 任务4:编写和更新测试 (AC: 5)
|
|
|
|
|
+ - [ ] 为GoodsParentChildPanel添加子商品删除功能的单元测试
|
|
|
|
|
+ - [ ] 更新ChildGoodsList单元测试,验证onDeleteChild回调传递
|
|
|
|
|
+ - [ ] 添加集成测试验证删除流程的完整性
|
|
|
|
|
+ - [ ] 运行现有测试套件,确保无回归问题
|
|
|
|
|
+- [ ] 任务5:验证多租户兼容性和向后兼容性 (AC: 4, 5)
|
|
|
|
|
+ - [ ] 验证删除操作仅影响当前租户的数据
|
|
|
|
|
+ - [ ] 确保父子商品在同一租户下的约束
|
|
|
|
|
+ - [ ] 验证单规格商品和无父子关系的商品功能不受影响
|
|
|
|
|
+ - [ ] 进行端到端测试验证完整删除流程
|
|
|
|
|
+
|
|
|
|
|
+## Dev Notes
|
|
|
|
|
+
|
|
|
|
|
+### 先前故事洞察
|
|
|
|
|
+- **故事2(父子商品管理UI体验优化)**:已实现父子商品管理API,包括解除父子关系API(`DELETE /api/v1/goods/:id/parent`),GoodsParentChildPanel组件已包含removeParentMutation用于解除当前商品的父子关系。**重要区别**:解除父子关系是使子商品成为独立商品,而本故事需要实现的是**删除子商品实体**功能
|
|
|
|
|
+- **故事3(子商品行内编辑功能)**:已扩展ChildGoodsList组件支持行内编辑,组件包含删除按钮但onDeleteChild回调未由父组件提供,导致删除操作无效。本故事需要实现此回调以支持子商品实体删除
|
|
|
|
|
+- **故事9(父子商品名称关联查询优化)**:商品详情API不再返回spuName字段,使用parent对象获取父商品信息。删除子商品实体后,需确保父子商品关系数据清理
|
|
|
|
|
+- **故事10(购物车商品名称显示优化)**:购物车使用parent.name获取父商品名称。删除子商品实体后,需确保购物车中相关子商品引用得到适当处理(如购物车项失效或清理)
|
|
|
|
|
+- [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#故事11]
|
|
|
|
|
+- [Source: docs/stories/006.002.parent-child-goods-ui-optimization.story.md]
|
|
|
|
|
+- [Source: docs/stories/006.003.child-goods-inline-edit.story.md]
|
|
|
|
|
+
|
|
|
|
|
+### 数据模型
|
|
|
|
|
+- **商品实体 (`GoodsMt`)**:
|
|
|
|
|
+ - `spuId` 字段:0表示父商品或单规格商品,>0表示子商品
|
|
|
|
|
+ - `spuName` 字段:父商品名称(冗余字段,保留在实体中保持向后兼容性,但从API响应中移除)
|
|
|
|
|
+ - `tenantId` 字段:租户ID,父子商品必须在同一租户下
|
|
|
|
|
+ - `name` 字段:商品名称,对于子商品就是规格名称
|
|
|
|
|
+ - [Source: packages/goods-module-mt/src/entities/goods.entity.mt.ts#L76-L81]
|
|
|
|
|
+
|
|
|
|
|
+- **父子关系约束**:
|
|
|
|
|
+ - 父子商品必须在同一租户下(`tenantId`相同)
|
|
|
|
|
+ - 子商品通过`spuId`字段关联到父商品
|
|
|
|
|
+ - 解除父子关系:将子商品的`spuId`设为0,`spuName`设为null(故事2已实现)
|
|
|
|
|
+ - **本故事操作**:删除子商品实体(永久删除,非解除关系)
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#多租户支持]
|
|
|
|
|
+
|
|
|
|
|
+### API 规范
|
|
|
|
|
+- **商品删除API** (`DELETE /api/v1/goods/:id`):
|
|
|
|
|
+ - 功能:完全删除商品实体,包括数据库记录和相关关联数据
|
|
|
|
|
+ - 验证:商品必须存在,必须在当前租户下,需验证权限
|
|
|
|
|
+ - 响应:返回删除成功状态(通常为204 No Content或200 OK)
|
|
|
|
|
+ - 错误处理:404错误(商品不存在)、403错误(权限不足)、租户权限错误
|
|
|
|
|
+ - 特殊考虑:删除子商品时需验证是否为子商品(`spuId > 0`),但API本身可能不限制
|
|
|
|
|
+ - **业务决策**:本故事使用商品删除API永久删除子商品实体,而非解除父子关系API
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#故事11]
|
|
|
|
|
+
|
|
|
|
|
+### 组件规范
|
|
|
|
|
+- **GoodsParentChildPanel组件**:
|
|
|
|
|
+ - 位置:`packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx`
|
|
|
|
|
+ - 当前状态:已包含removeParentMutation用于解除当前商品的父子关系,但未为ChildGoodsList组件提供onDeleteChild回调
|
|
|
|
|
+ - 需要添加:onDeleteChild回调函数、删除确认对话框、删除状态管理
|
|
|
|
|
+ - [Source: packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx#L143-L170]
|
|
|
|
|
+
|
|
|
|
|
+- **ChildGoodsList组件**:
|
|
|
|
|
+ - 位置:`packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx`
|
|
|
|
|
+ - 当前状态:包含删除按钮,点击调用onDeleteChild回调,但父组件未提供此回调
|
|
|
|
|
+ - 删除按钮:使用Trash2图标,点击触发handleDelete函数
|
|
|
|
|
+ - 需要:父组件传递onDeleteChild回调,删除期间视觉反馈
|
|
|
|
|
+ - [Source: packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx#L143-L147]
|
|
|
|
|
+ - [Source: packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx#L262-L270]
|
|
|
|
|
+
|
|
|
|
|
+- **对话框组件**:
|
|
|
|
|
+ - 使用现有Dialog组件实现删除确认
|
|
|
|
|
+ - 确认提示信息:"确定要永久删除这个子商品规格吗?此操作将删除商品实体,包括所有相关数据,无法恢复。"
|
|
|
|
|
+ - 按钮:"取消"和"确定删除"
|
|
|
|
|
+ - [Source: packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx#L11]
|
|
|
|
|
+
|
|
|
|
|
+### 文件位置
|
|
|
|
|
+- **主要修改文件**:
|
|
|
|
|
+ - `packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx` - 添加onDeleteChild回调函数,实现删除确认对话框和API调用
|
|
|
|
|
+ - `packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx` - 可能优化删除按钮的视觉反馈
|
|
|
|
|
+ - [Source: docs/prd/epic-006-parent-child-goods-multi-spec-support.md#故事11]
|
|
|
|
|
+
|
|
|
|
|
+- **测试文件**:
|
|
|
|
|
+ - `packages/goods-management-ui-mt/tests/unit/GoodsParentChildPanel.test.tsx` - 添加子商品删除功能测试
|
|
|
|
|
+ - `packages/goods-management-ui-mt/tests/unit/ChildGoodsList.test.tsx` - 更新测试验证onDeleteChild回调传递
|
|
|
|
|
+ - `packages/goods-management-ui-mt/tests/integration/goods-management.integration.test.tsx` - 可能添加集成测试
|
|
|
|
|
+ - [Source: docs/architecture/testing-strategy.md#单元测试-unit-tests]
|
|
|
|
|
+
|
|
|
|
|
+- **API测试文件**:
|
|
|
|
|
+ - 商品删除API (`DELETE /api/v1/goods/:id`) 是通用CRUD API的一部分,测试包含在通用CRUD测试中
|
|
|
|
|
+ - 如需验证商品删除功能,可参考现有商品API测试套件
|
|
|
|
|
+ - [Source: docs/architecture/testing-strategy.md#集成测试-integration-tests]
|
|
|
|
|
+
|
|
|
|
|
+### 技术约束
|
|
|
|
|
+- **多租户要求**:所有操作必须包含`tenantId`过滤,父子商品必须在同一租户下,删除操作仅影响当前租户数据
|
|
|
|
|
+- **向后兼容性**:现有功能不受影响,数据库实体保留`spuName`字段,仅从API响应中移除
|
|
|
|
|
+- **性能考虑**:删除操作应快速响应,列表刷新不应显著影响页面性能
|
|
|
|
|
+- **数据一致性**:删除子商品实体后,需确保父子商品关系清理,相关数据(如购物车中的子商品引用)应适当处理
|
|
|
|
|
+- [Source: docs/architecture/tech-stack.md]
|
|
|
|
|
+- [Source: docs/architecture/source-tree.md]
|
|
|
|
|
+
|
|
|
|
|
+### 测试标准
|
|
|
|
|
+- **测试框架**:商品管理界面使用Vitest + Testing Library
|
|
|
|
|
+- **测试位置**:`tests`文件夹与源码并列(例如:`packages/goods-management-ui-mt/tests/unit/`)
|
|
|
|
|
+- **单元测试位置**:`packages/goods-management-ui-mt/tests/unit/`目录下对应组件测试文件
|
|
|
|
|
+- **集成测试位置**:`packages/goods-management-ui-mt/tests/integration/`目录
|
|
|
|
|
+- **测试覆盖率**:核心业务逻辑 > 80%,关键函数 > 90%
|
|
|
|
|
+- **测试策略**:验证删除功能完整性、确认对话框工作正常、API调用正确、多租户兼容性、无回归问题
|
|
|
|
|
+- **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代理在审查完成后填写*
|