Draft
As a 系统管理员, I want 在创建和编辑商品时都能统一管理父子商品关系, so that 能够一次性完成商品和规格的配置,提高工作效率
[x] 分析现有父子商品管理实现 (AC: 1, 2, 3, 4, 5, 6, 7)
[x] 设计父子商品管理面板组件架构 (AC: 1, 2, 3, 4)
[x] 创建父子商品管理面板组件 (AC: 1, 2, 3, 4)
[x] 实现父子商品管理API (AC: 4, 5)
admin-goods-parent-child.mt.ts自定义路由文件admin-goods-aggregated.mt.ts聚合基础CRUD和父子商品管理路由adminGoodsRoutesMt名称不变[x] 集成父子商品管理面板到商品创建和编辑页面 (AC: 1, 5, 6, 7)
[x] 编写单元测试和集成测试 (AC: 1, 2, 3, 4, 5, 6, 7)
[x] 修复集成测试中的标签页切换问题 (新增任务)
__tests__ 文件夹与源码并列(但实际使用tests/目录)基于故事006.001的实现:
GoodsManagement.tsx (835行)
GoodsChildSelector.tsx (214行)
BatchSpecCreator.tsx (424行)
GoodsParentChildPanel.tsx (支持创建和编辑模式):
interface GoodsParentChildPanelProps {
// 基础属性
mode: 'create' | 'edit'; // 创建模式或编辑模式
goodsId?: number; // 当前商品ID(编辑模式)
goodsName?: string; // 当前商品名称
// 父子商品数据(双向绑定)
spuId?: number; // 父商品ID
spuName?: string; // 父商品名称
childGoodsIds?: number[]; // 子商品ID列表
batchSpecs?: BatchSpecTemplate[]; // 批量创建规格模板(创建模式)
// 回调函数
onDataChange?: (data: ParentChildData) => void; // 数据变化回调
onUpdate?: () => void; // 更新回调(编辑模式)
// 其他
tenantId?: number; // 租户ID
disabled?: boolean; // 是否禁用
}
interface ParentChildData {
spuId: number;
spuName: string | null;
childGoodsIds: number[];
batchSpecs?: BatchSpecTemplate[];
}
interface BatchSpecTemplate {
name: string;
price: number;
costPrice: number;
stock: number;
sort: number;
}
enum PanelMode {
VIEW = 'view', // 查看模式
BATCH_CREATE = 'batch', // 批量创建模式
MANAGE_CHILDREN = 'manage' // 管理子商品模式
}
GoodsRelationshipTree.tsx:
ChildGoodsList.tsx:
BatchSpecCreatorInline.tsx:
在现有adminGoodsRoutesMt中聚合父子商品管理API:
实现方案:
admin-goods-parent-child.mt.ts: 基于public-goods-random.mt.ts模式创建自定义路由admin-goods-routes.mt.ts: 聚合基础CRUD路由和父子商品管理路由adminGoodsRoutesMt名称不变: 前端代码无需修改API端点 (聚合到现有adminGoodsRoutesMt):
GET /api/v1/goods/:id/children
POST /api/v1/goods/:id/set-as-parent
spuId = 0, spuName = nullDELETE /api/v1/goods/:id/parent
spuId = 0, spuName = nullPOST /api/v1/goods/batch-create-children
parentGoodsId, specs数组前端使用 (无需修改):
// 现有代码继续工作
import { adminGoodsRoutesMt } from '@d8d/goods-module-mt';
const goodsClient = hc<typeof adminGoodsRoutesMt>('/api/v1/goods');
// 原有调用
await goodsClient.index.$get({ query: { page: 1 } });
// 新增调用
await goodsClient[':id'].children.$get({ param: { id: 123 } });
await goodsClient[':id'].setAsParent.$post({ param: { id: 123 } });
await goodsClient[':id'].parent.$delete({ param: { id: 456 } });
await goodsClient.batchCreateChildren.$post({ json: { ... } });
优势:
adminGoodsRoutesMt名称和导入方式不变credit-balance-module-mt聚合模式在GoodsManagement.tsx中的集成 (创建和编辑模式):
// 在商品表单之后添加面板(创建和编辑都显示)
<div className="mt-6 pt-6 border-t">
<GoodsParentChildPanel
mode={isCreateForm ? 'create' : 'edit'}
goodsId={isCreateForm ? undefined : editingGoods?.id}
goodsName={isCreateForm ? createForm.watch('name') : editingGoods?.name}
spuId={isCreateForm ? createForm.watch('spuId') : editingGoods?.spuId}
spuName={isCreateForm ? createForm.watch('spuName') : editingGoods?.spuName}
childGoodsIds={isCreateForm ? createForm.watch('childGoodsIds') : editingGoods?.childGoods?.map(c => c.id) || []}
onDataChange={(data) => {
// 实时同步数据到表单
if (isCreateForm) {
createForm.setValue('spuId', data.spuId);
createForm.setValue('spuName', data.spuName);
createForm.setValue('childGoodsIds', data.childGoodsIds);
// 保存批量创建模板
setBatchSpecs(data.batchSpecs || []);
}
}}
onUpdate={refetch}
/>
</div>
提交逻辑调整:
const handleSubmit = (data: CreateRequest | UpdateRequest) => {
// 合并表单数据和面板数据
const submitData = {
...data,
spuId: parentChildData?.spuId || 0,
spuName: parentChildData?.spuName || null,
childGoodsIds: parentChildData?.childGoodsIds || [],
};
if (isCreateForm) {
// 创建模式:可能需要批量创建子商品
createMutation.mutate(submitData, {
onSuccess: (result) => {
// 如果创建成功且有批量创建模板,创建子商品
if (batchSpecs.length > 0 && result.id) {
batchCreateChildren(result.id, batchSpecs);
}
}
});
} else if (editingGoods) {
updateMutation.mutate({ id: editingGoods.id, data: submitData as UpdateRequest });
}
};
移除原有功能:
当前测试覆盖缺口: 现有集成测试验证了批量创建的基本流程,但缺少完整的用户交互测试:
规格表单交互测试缺失:
完整用户流程测试缺失:
错误场景测试缺失:
补充测试目标:
packages/goods-management-ui-mt/tests/ 目录下tests/unit/**/*.test.{ts,tsx}tests/integration/**/*.test.{ts,tsx}| Date | Version | Description | Author |
|---|---|---|---|
| 2025-12-09 | 1.0 | 初始故事创建 | John (Product Manager) |
✅ 父子商品管理API已实现并测试通过
admin-goods-parent-child.mt.ts自定义路由文件已创建admin-goods-aggregated.mt.ts已聚合基础CRUD和父子商品管理路由adminGoodsRoutesMt名称不变✅ 父子商品管理集成测试已通过
✅ 前端组件已完整实现
GoodsParentChildPanel.tsx组件已创建并支持创建/编辑模式ChildGoodsList.tsx组件已创建BatchSpecCreatorInline.tsx组件已创建并支持模板保存GoodsManagement.tsx已集成新面板到创建和编辑表单✅ 验收标准全部满足
✅ 补充的批量创建规格交互测试已完成
✅ 增强功能:添加规格名称重复验证
✅ 修复集成测试中的标签页切换逻辑
✅ 修复嵌套表单结构问题
GoodsManagement.tsx的商品创建/编辑表单中移除GoodsParentChildPanel"create-goods-form"和"edit-goods-form"form属性将对话框按钮与相应表单关联handleParentChildDataChange回调函数,使用useCallback避免无限重渲染GoodsParentChildPanel.tsx中导出ParentChildData和BatchSpecTemplate接口类型?? null和?? undefined转换)✅ 修复Maximum update depth exceeded无限重渲染问题
handleParentChildDataChange回调函数在每次渲染时重新创建,导致无限循环useCallback包装handleParentChildDataChange回调函数,依赖项为[setParentChildData]GoodsManagement.tsx中将handleParentChildDataChange函数用useCallback包装[setParentChildData],确保函数引用稳定新增/修改的后端文件:
packages/goods-module-mt/src/routes/admin-goods-parent-child.mt.ts (新增)packages/goods-module-mt/src/routes/admin-goods-aggregated.mt.ts (新增)packages/goods-module-mt/src/routes/index.mt.ts (修改)新增/修改的前端文件:
packages/goods-management-ui-mt/src/components/GoodsParentChildPanel.tsx (新增)packages/goods-management-ui-mt/src/components/ChildGoodsList.tsx (新增)packages/goods-management-ui-mt/src/components/BatchSpecCreatorInline.tsx (新增)packages/goods-management-ui-mt/src/components/GoodsManagement.tsx (修改)测试文件:
packages/goods-module-mt/tests/integration/admin-goods-parent-child.integration.test.ts (新增)packages/goods-management-ui-mt/tests/unit/GoodsParentChildPanel.test.tsx (新增)packages/goods-management-ui-mt/tests/unit/ChildGoodsList.test.tsx (新增)packages/goods-management-ui-mt/tests/unit/BatchSpecCreatorInline.test.tsx (新增)| Date | Version | Description | Author |
|---|---|---|---|
| 2025-12-09 | 1.0 | 初始故事创建 | John (Product Manager) |
| 2025-12-09 | 1.1 | 实现父子商品管理API和集成测试 | James (Developer) |
| 2025-12-10 | 1.2 | 完成前端组件实现和集成,所有任务完成 | James (Developer) |
| 2025-12-10 | 1.3 | 删除未使用的GoodsRelationshipTree组件 | James (Developer) |
| 2025-12-12 | 1.4 | 完成补充的批量创建规格交互测试 | James (Developer) |
| 2025-12-12 | 1.5 | 增强功能:添加规格名称重复验证 | James (Developer) |
| 2025-12-12 | 1.6 | 记录集成测试中的标签页切换问题 | James (Developer) |
| 2025-12-12 | 1.7 | 修复嵌套表单结构问题,移除嵌套表单 | James (Developer) |
✅ 已完成 - 所有测试通过,故事验收标准全部满足
此部分由QA代理在审查完成后填写