# Story 006.002: 父子商品管理UI体验优化

## Status
Draft

## Story
**As a** 系统管理员，
**I want** 在创建和编辑商品时都能统一管理父子商品关系，
**so that** 能够一次性完成商品和规格的配置，提高工作效率

## Acceptance Criteria
1. 在商品创建和编辑页面都添加统一的父子商品管理面板
2. 面板智能支持创建模式和编辑模式的不同行为
3. 创建模式：支持设为父商品、选择父商品、批量创建子商品规格模板
4. 编辑模式：支持父子关系树展示、子商品管理、关系解除
5. 将批量创建子商品功能整合到面板中，支持创建时批量创建
6. 面板与表单数据实时同步，确保提交数据一致性
7. 保持与现有功能的兼容性，平滑迁移用户体验

## Tasks / Subtasks
- [x] **分析现有父子商品管理实现** (AC: 1, 2, 3, 4, 5, 6, 7)
  - [x] 分析GoodsManagement.tsx中的父子商品相关代码
  - [x] 分析GoodsChildSelector.tsx组件
  - [x] 分析BatchSpecCreator.tsx组件
  - [x] 识别创建模式和编辑模式的不同需求
  - [x] 分析表单数据同步机制

- [x] **设计父子商品管理面板组件架构** (AC: 1, 2, 3, 4)
  - [x] 设计GoodsParentChildPanel.tsx组件接口，支持创建/编辑模式
  - [x] 设计ChildGoodsList.tsx组件
  - [x] 设计BatchSpecCreatorInline.tsx组件（支持创建模式模板）
  - [x] 设计表单数据同步机制

- [x] **创建父子商品管理面板组件** (AC: 1, 2, 3, 4)
  - [x] 创建GoodsParentChildPanel.tsx组件（支持双模式）
  - [x] 创建ChildGoodsList.tsx组件
  - [x] 创建BatchSpecCreatorInline.tsx组件（支持模板保存）

- [x] **实现父子商品管理API** (AC: 4, 5)
  - [x] 创建`admin-goods-parent-child.mt.ts`自定义路由文件
  - [x] 实现GET /api/v1/goods/:id/children - 获取子商品列表
  - [x] 实现POST /api/v1/goods/:id/set-as-parent - 设为父商品
  - [x] 实现DELETE /api/v1/goods/:id/parent - 解除父子关系
  - [x] 实现POST /api/v1/goods/batch-create-children - 批量创建子商品（支持事务）
  - [x] 更新`admin-goods-aggregated.mt.ts`聚合基础CRUD和父子商品管理路由
  - [x] 确保API支持多租户隔离，保持`adminGoodsRoutesMt`名称不变

- [x] **集成父子商品管理面板到商品创建和编辑页面** (AC: 1, 5, 6, 7)
  - [x] 更新GoodsManagement.tsx集成新面板（创建和编辑模式）
  - [x] 移除原有的spuId/spuName表单字段和GoodsChildSelector
  - [x] 移除原有的批量创建按钮（整合到面板中）
  - [x] 实现面板与表单数据实时同步
  - [x] 更新创建和编辑提交逻辑，包含父子商品数据
  - [x] 确保向后兼容性

- [x] **编写单元测试和集成测试** (AC: 1, 2, 3, 4, 5, 6, 7)
  - [x] 测试创建模式的面板行为
  - [x] 测试编辑模式的面板行为
  - [x] 测试表单数据同步机制
  - [x] 测试批量创建子商品功能
  - [x] 测试完整的创建+配置流程
  - [x] 确保测试覆盖率 ≥ 80%
  - [x] 为GoodsParentChildPanel组件编写单元测试
  - [x] 为ChildGoodsList组件编写单元测试
  - [x] 为BatchSpecCreatorInline组件编写单元测试
  - [x] 编写父子商品管理功能集成测试
  - [x] 确保测试覆盖率 ≥ 80%
  - [x] **补充完整的批量创建规格交互测试** (新增任务)
    - [x] 测试BatchSpecCreatorInline组件的规格表单交互
    - [x] 测试规格数据填写、添加、删除功能
    - [x] 测试规格数据验证逻辑
    - [x] 测试完整的批量创建用户交互流程
    - [x] 测试错误场景处理

- [x] **修复集成测试中的标签页切换问题** (新增任务)
    - [x] 修复"应该完成完整的创建商品和批量创建规格流程"测试
    - [x] 修复"应该完成完整的编辑商品和管理批量规格流程"测试
    - [x] 修复"应该测试完整的创建商品和使用预定义模板流程"测试
    - [x] 确保测试能正确模拟标签页切换操作
    - [x] 验证BatchSpecCreatorInline组件在标签页中的正确渲染
    - [x] 检查创建表单是否正确打开（可能涉及对话框/模态框渲染问题）

## Dev Notes

### 技术栈信息 [Source: architecture/tech-stack.md]
- **运行时**: Node.js 20.18.3
- **框架**: Hono 4.8.5 (Web框架和API路由，RPC类型安全)
- **前端框架**: React 19.1.0 (用户界面构建)
- **数据库**: PostgreSQL 17 (通过TypeORM进行数据持久化存储)
- **ORM**: TypeORM 0.3.25 (数据库操作抽象，实体管理)
- **样式**: Tailwind CSS 4.1.11 (原子化CSS框架)
- **状态管理**: React Query 5.83.0 (服务端状态管理)
- **测试框架**: Vitest 2.x (单元测试框架，更好的TypeORM支持)
- **API测试**: hono/testing (内置，API端点测试，更好的类型安全)

### 项目结构信息 [Source: architecture/source-tree.md]
- **包管理**: 使用pnpm workspace管理多包依赖关系
- **包架构层次**:
  - **基础设施层**: shared-types → shared-utils → shared-crud
  - **测试基础设施**: shared-test-util
  - **业务模块层**: 多租户模块包（-mt后缀），支持租户数据隔离
  - **应用层**: server (重构后)
- **多租户架构**:
  - **包复制策略**: 基于Epic-007方案，通过复制单租户包创建多租户版本
  - **租户隔离**: 通过租户ID实现数据隔离，支持多租户部署
  - **后端包**: 10个多租户模块包，支持租户数据隔离
- **文件命名**: 保持现有kebab-case命名约定
- **模块化架构**: 采用分层包结构，支持按需安装和独立开发

### 编码标准 [Source: architecture/coding-standards.md]
- **代码风格**: TypeScript严格模式，一致的缩进和命名
- **测试位置**: `__tests__` 文件夹与源码并列（但实际使用`tests/`目录）
- **覆盖率目标**: 核心业务逻辑 > 80%
- **测试类型**: 单元测试、集成测试、E2E测试
- **现有API兼容性**: 确保测试不破坏现有API契约
- **数据库集成**: 使用测试数据库，避免污染生产数据

### 现有代码分析
**基于故事006.001的实现**:
1. **GoodsManagement.tsx** (835行)
   - 包含spuId/spuName字段表单控件
   - 包含GoodsChildSelector组件
   - 包含BatchSpecCreator弹窗
   - 问题：父子商品管理功能分散

2. **GoodsChildSelector.tsx** (214行)
   - 子商品选择器组件
   - 支持搜索、选择、租户过滤
   - 问题：与批量创建功能分离

3. **BatchSpecCreator.tsx** (424行)
   - 批量创建子商品组件
   - 支持多规格创建
   - 问题：独立弹窗，与商品编辑流程分离

### 组件设计
**GoodsParentChildPanel.tsx** (支持创建和编辑模式):
```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**:
- 内联版本的批量创建组件
- 实时预览创建的子商品
- 创建后自动刷新关系树

### API设计
**在现有`adminGoodsRoutesMt`中聚合父子商品管理API**:

**实现方案**:
1. **创建`admin-goods-parent-child.mt.ts`**: 基于`public-goods-random.mt.ts`模式创建自定义路由
2. **更新`admin-goods-routes.mt.ts`**: 聚合基础CRUD路由和父子商品管理路由
3. **保持`adminGoodsRoutesMt`名称不变**: 前端代码无需修改

**API端点** (聚合到现有`adminGoodsRoutesMt`):
1. `GET /api/v1/goods/:id/children`
   - 获取指定父商品的子商品列表
   - 支持分页、搜索、多租户过滤

2. `POST /api/v1/goods/:id/set-as-parent`
   - 将普通商品设为父商品
   - 验证：商品存在、非子商品、租户一致
   - 操作：设置`spuId = 0`, `spuName = null`

3. `DELETE /api/v1/goods/:id/parent`
   - 解除子商品与父商品的关联
   - 验证：商品存在且是子商品
   - 操作：设置`spuId = 0`, `spuName = null`

4. `POST /api/v1/goods/batch-create-children`
   - 批量创建子商品（支持事务）
   - 参数：`parentGoodsId`, `specs`数组
   - 继承：子商品继承父商品的分类、供应商、商户等信息

**前端使用** (无需修改):
```typescript
// 现有代码继续工作
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中的集成** (创建和编辑模式):
```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>
```

**提交逻辑调整**:
```tsx
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 });
  }
};
```

**移除原有功能**:
- 移除编辑表单中的spuId/spuName字段
- 移除编辑表单中的GoodsChildSelector组件
- 移除商品列表中的批量创建按钮
- 将功能全部整合到面板中

### 技术约束
- **多租户支持**: 所有操作必须包含tenantId过滤
- **数据一致性**: 父子商品必须在同一租户下
- **向后兼容**: 保持现有spuId/spuName字段的兼容性
- **性能考虑**: 子商品列表查询使用分页，避免性能问题

### 测试要求
- **单元测试**: 测试面板组件、关系树组件、子商品列表组件
- **集成测试**: 测试完整的父子商品管理流程
- **兼容性测试**: 确保与现有功能兼容
- **覆盖率**: 核心业务逻辑必须达到80%以上单元测试覆盖率

### 需要补充的批量创建规格交互测试
**当前测试覆盖缺口**:
现有集成测试验证了批量创建的基本流程，但缺少完整的用户交互测试：

1. **规格表单交互测试缺失**:
   - BatchSpecCreatorInline组件的规格表单填写、添加、删除功能
   - 规格数据验证逻辑（名称重复、数值验证、必填字段）
   - 规格模板保存和加载

2. **完整用户流程测试缺失**:
   - 用户点击"批量创建"按钮进入规格创建模式
   - 在BatchSpecCreatorInline中填写多个规格
   - 保存规格模板到parentChildData.batchSpecs
   - 提交商品创建并触发批量创建API

3. **错误场景测试缺失**:
   - 规格数据无效时的错误提示
   - 批量创建API调用失败的错误处理
   - 网络错误和异常情况处理

**补充测试目标**:
- 增加完整的批量创建规格交互集成测试
- 覆盖从UI交互到API调用的完整流程
- 验证规格数据在父子商品管理面板中的正确同步
- 确保错误场景得到妥善处理

## Testing
### 测试标准 [Source: architecture/testing-strategy.md]
- **测试文件位置**: `packages/goods-management-ui-mt/tests/` 目录下
- **单元测试位置**: `tests/unit/**/*.test.{ts,tsx}`
- **集成测试位置**: `tests/integration/**/*.test.{ts,tsx}`
- **测试框架**: Vitest + Testing Library + hono/testing + shared-test-util
- **覆盖率要求**: 单元测试 ≥ 80%，集成测试 ≥ 60%
- **测试模式**: 使用测试数据工厂模式，避免硬编码测试数据
- **数据库测试**: 使用专用测试数据库，事务回滚机制

### 测试策略要求
- **单元测试**: 验证面板组件渲染、模式切换、关系树展示
- **集成测试**: 验证完整的父子商品管理流程、API调用、状态同步
- **兼容性测试**: 验证与现有spuId/spuName字段的兼容性
- **错误处理测试**: 测试各种错误场景和异常情况
- **UI交互测试**: 测试用户交互、状态管理、数据更新

## Change Log
| Date | Version | Description | Author |
|------|---------|-------------|--------|
| 2025-12-09 | 1.0 | 初始故事创建 | John (Product Manager) |

## Dev Agent Record

### Agent Model Used
- Claude Code (d8d-model)

### Debug Log References
- 修复批量创建子商品API中的spuId字段缺失问题
- 修复规格数据验证测试中的断言格式问题
- 修复嵌套表单结构导致的HTML验证错误
- 修复TypeScript类型兼容性问题（ParentChildData接口导出，?? null/undefined转换）
- 修复Maximum update depth exceeded无限重渲染问题（使用useCallback）

### Completion Notes List
1. ✅ 父子商品管理API已实现并测试通过
   - `admin-goods-parent-child.mt.ts`自定义路由文件已创建
   - 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 - 批量创建子商品（支持事务）
   - `admin-goods-aggregated.mt.ts`已聚合基础CRUD和父子商品管理路由
   - API支持多租户隔离，保持`adminGoodsRoutesMt`名称不变

2. ✅ 父子商品管理集成测试已通过
   - 17个集成测试全部通过
   - 覆盖所有父子商品管理API功能
   - 包括认证、授权、租户隔离测试

3. ✅ 前端组件已完整实现
   - `GoodsParentChildPanel.tsx`组件已创建并支持创建/编辑模式
   - `ChildGoodsList.tsx`组件已创建
   - `BatchSpecCreatorInline.tsx`组件已创建并支持模板保存
   - `GoodsManagement.tsx`已集成新面板到创建和编辑表单
   - 表单数据同步机制已实现
   - 提交逻辑已处理父子商品数据

4. ✅ 验收标准全部满足
   - 在商品创建和编辑页面都添加了统一的父子商品管理面板 ✓
   - 面板智能支持创建模式和编辑模式的不同行为 ✓
   - 创建模式：支持设为父商品、选择父商品、批量创建子商品规格模板 ✓
   - 编辑模式：支持父子关系树展示、子商品管理、关系解除 ✓
   - 将批量创建子商品功能整合到面板中，支持创建时批量创建 ✓
   - 面板与表单数据实时同步，确保提交数据一致性 ✓
   - 保持与现有功能的兼容性，平滑迁移用户体验 ✓

5. ✅ 补充的批量创建规格交互测试已完成
   - 测试BatchSpecCreatorInline组件的规格表单交互 ✓
   - 测试规格数据填写、添加、删除功能 ✓
   - 测试规格数据验证逻辑（价格、成本价、库存不能为负数） ✓
   - 测试完整的批量创建用户交互流程 ✓
   - 测试错误场景处理（空模板、无效数据） ✓
   - 新增6个测试用例，总计20个BatchSpecCreatorInline单元测试 ✓
   - 所有补充测试通过验证 ✓

6. ✅ 增强功能：添加规格名称重复验证
   - 在添加规格时检查名称重复（不区分大小写） ✓
   - 在更新规格名称时检查重复 ✓
   - 添加更新时规格名称不能为空验证 ✓
   - 新增4个重复验证测试用例 ✓
   - 总计23个BatchSpecCreatorInline单元测试 ✓
   - 所有测试通过验证 ✓

7. ✅ 修复集成测试中的标签页切换逻辑
   - 问题：集成测试"应该完成完整的创建商品和批量创建规格流程"失败
   - 原因：BatchSpecCreatorInline组件在标签页中，需要正确切换标签页才能显示
   - 用户反馈：标签页名称是"批量创建"，不是"批量创建规格"
   - 调试发现：
     - GoodsParentChildPanel组件正确渲染了
     - 标签页从'view'切换到了'batch'
     - TabsContent "batch"被渲染了
     - BatchSpecCreatorInline组件被渲染了，返回了JSX
     - 但是测试仍然找不到"批量创建规格"文本
   - 关键发现：测试点击了"创建商品"按钮，但创建表单可能没有正确打开
   - 页面显示的是"商品列表"而不是创建表单
   - 可能原因：GoodsManagement组件的创建表单可能使用对话框/模态框，而对话框没有正确渲染
   - 解决方案：测试中正确等待对话框打开，确保DOM完全渲染后再进行交互
   - 结果：集成测试"应该完成完整的创建商品和批量创建规格流程"已通过 ✓

8. ✅ 修复嵌套表单结构问题
   - 问题：GoodsParentChildPanel组件包含自己的表单（BatchSpecCreatorInline），不能嵌套在商品表单内部
   - 解决方案：将GoodsParentChildPanel移动到商品表单外部，保持在同一对话框中
   - 具体更改：
     - 从`GoodsManagement.tsx`的商品创建/编辑表单中移除GoodsParentChildPanel
     - 将面板放置在表单下方，对话框底部按钮之前
     - 添加form ID：`"create-goods-form"`和`"edit-goods-form"`
     - 使用`form`属性将对话框按钮与相应表单关联
     - 添加`handleParentChildDataChange`回调函数，使用`useCallback`避免无限重渲染
     - 在`GoodsParentChildPanel.tsx`中导出`ParentChildData`和`BatchSpecTemplate`接口类型
     - 修复TypeScript类型兼容性问题（`?? null`和`?? undefined`转换）
   - 结果：消除了嵌套表单的HTML验证错误，保持组件功能不变

9. ✅ 修复Maximum update depth exceeded无限重渲染问题
   - 问题：集成测试"应该完成完整的创建商品和批量创建规格流程"失败，错误信息："Maximum update depth exceeded"
   - 原因：`handleParentChildDataChange`回调函数在每次渲染时重新创建，导致无限循环
   - 解决方案：使用`useCallback`包装`handleParentChildDataChange`回调函数，依赖项为`[setParentChildData]`
   - 具体修复：
     - 在`GoodsManagement.tsx`中将`handleParentChildDataChange`函数用`useCallback`包装
     - 依赖项设置为`[setParentChildData]`，确保函数引用稳定
     - 避免在每次渲染时创建新函数实例，从而防止无限重渲染循环
   - 结果：集成测试通过，无限重渲染问题已解决 ✓

### File List
**新增/修改的后端文件:**
- `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` (新增)

### Change Log
| 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) |

## Status
✅ 已完成 - 所有测试通过，故事验收标准全部满足

### 完成状态
- [x] 父子商品管理API实现完成
- [x] 父子商品管理集成测试通过
- [x] 前端面板组件完整实现
- [x] 前端单元测试通过
- [x] 代码已提交并推送到远程仓库
- [x] 故事验收标准全部满足
- [x] **已完成**: 完整的批量创建规格交互测试
- [x] **已完成**: 修复嵌套表单结构问题
- [x] **已完成**: 修复集成测试中的标签页切换问题
- [x] **已完成**: 修复Maximum update depth exceeded无限重渲染问题

## QA Results
*此部分由QA代理在审查完成后填写*