bug-analysis-dcm-cell-cross-film-issue.md 2.1 KB

DcmCell 胶片间图像显示错误 Bug 分析

问题描述

用户在胶片1上拖拽一个图像,切换到胶片2时,这个图像也会显示在胶片2上。

根本原因分析

1. 共享渲染引擎问题

// 所有 DcmCell 实例共享同一个渲染引擎
const engineId = 'myRenderingEngineForPrint';
let engine: RenderingEngine | null = cornerstone.getRenderingEngines()?.find(en => en.id === engineId) || null;

2. viewport ID 生成不唯一

// 当前的 viewport ID 生成方式
const viewportId = useMemo(() => `stackViewport-${imageId}-${uuidv4()}`, []);

问题

  • 在组件初始化时,imageId 可能为 null 或相同值
  • 这导致不同胶片的不同格子可能生成相同的 viewport ID 前缀
  • uuidv4() 只在组件挂载时生成一次,但由于依赖数组为空 [],无法保证真正的唯一性

3. 渲染引擎状态污染

  • 共享的渲染引擎在不同胶片间切换时保持了之前的状态
  • 当新的 DcmCell 组件挂载时,可能会复用已有的 viewport 或产生冲突

解决方案

1. 改进 viewport ID 生成策略

// 使用胶片ID + 格子索引 + UUID 确保唯一性
const viewportId = useMemo(() => 
  `stackViewport-${currentFilm.id}-${indexOfCell}-${uuidv4()}`, 
  [currentFilm.id, indexOfCell]
);

2. 分离渲染引擎或改进清理机制

// 方案A: 每个胶片使用独立的渲染引擎
const engineId = `renderingEngine-${currentFilm.id}`;

// 方案B: 改进现有引擎的 viewport 清理机制
// 在组件卸载时确保完全清理 viewport

3. 加强状态隔离

  • 确保每个 DcmCell 的状态完全独立
  • 在 imageId 变化时正确清理之前的图像状态
  • 避免在不同组件间共享 viewport 实例

4. 优化 useEffect 依赖

// 移除 currentImageId 从依赖数组,避免无限循环
useEffect(() => {
  // ...
}, [imageId, stackViewport]);

修复步骤

  1. 修改 viewport ID 生成逻辑,确保唯一性
  2. 改进组件卸载时的清理机制
  3. 优化 useEffect 依赖数组
  4. 测试胶片间切换的图像隔离性