You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

3.6 KiB

资源轨道分镜预览修复

日期: 2026-02-04
类型: Bug Fix
影响范围: 分镜看板 - 资源轨道点击交互

问题描述

点击资源轨道的元素时,只有前3个分镜能够正确显示分镜资源预览(StoryboardResourcesPreview),其他分镜的资源轨道块点击后无反应。

根本原因

数据层与渲染层的不一致

  1. 渲染层(StoryboardBoardTrack 组件):

    • 为每个分镜生成 itemsToRender,包含占位项
    • 占位项用于没有真实数据的分镜,ID 格式为 resource-${storyboardId}
  2. 数据层(useStoryboardBoardLogic):

    • handleSelectItem 查找时使用原始 tracks[].items(来自 API)
    • 原始数据不包含占位项
  3. 问题表现

    • 前3个分镜在 API 返回的 trackItems 中有真实数据 → 能找到 → 正常工作
    • 后面的分镜只有占位项(仅存在于渲染层)→ 找不到 → isResourceTrackItem = false → 无反应

解决方案

handleSelectItem 中添加 fallback 逻辑,处理占位项:

// Fallback: 处理资源轨道占位项(不在 trackItems 中,仅存在于渲染层)
if (!clickedItem && !isResourceTrackItem && id.startsWith('resource-')) {
  console.log('[handleSelectItem] 未找到资源轨道项,尝试 fallback 处理占位项');
  const storyboardId = id.replace(/^resource-/, '');
  const storyboardTrack = typedTracks.find((t) => t.type === 'storyboard');
  const storyboard = storyboardTrack?.items.find((i) => i.id.toString() === storyboardId);

  if (storyboard) {
    console.log('[handleSelectItem] Fallback 成功:找到对应分镜', storyboard);
    isResourceTrackItem = true;
    clickedItem = {
      id: id,
      storyboardId: storyboardId,
      startTime: storyboard.startTime,
      endTime: storyboard.endTime,
      trackId: '',
      projectId: '',
      content: '',
    } as StoryboardBoardItemType;
  } else {
    console.warn('[handleSelectItem] Fallback 失败:未找到对应分镜', storyboardId);
  }
}

修复逻辑

  1. 检测占位项:当找不到 clickedItem 且 ID 是 resource- 格式时
  2. 提取分镜 ID:从 resource-${storyboardId} 中提取 storyboardId
  3. 查找分镜:在分镜轨道中查找对应的分镜
  4. 构造虚拟 item:如果找到分镜,构造一个虚拟的 clickedItem
  5. 标记为资源轨道项:设置 isResourceTrackItem = true

改进点

  1. 不影响现有逻辑:有真实数据的分镜仍然走原有查找逻辑
  2. 兼容占位项:为占位项提供 fallback 处理
  3. 详细的日志:便于调试和追踪问题
  4. 健壮的错误处理:当找不到分镜时输出警告

测试验证

修复后,所有资源轨道块(包括占位块)点击时都应该:

  1. 打开资源面板
  2. 显示对应分镜的资源总览(StoryboardResourcesPreview)
  3. 清除具体资源选中状态
  4. 输出详细的调试日志

影响文件

  • client/src/hooks/useStoryboardBoardLogic.ts - 在 handleSelectItem 函数中添加占位项 fallback 逻辑

相关组件

  • StoryboardBoardPanel - 分镜看板面板
  • StoryboardBoardTrack - 分镜看板轨道(生成占位项)
  • PreviewPanel - 预览面板
  • StoryboardResourcesPreview - 分镜资源总览组件

技术细节

为什么不在数据层添加占位项?

  1. 占位项是 UI 层的概念,用于填充视觉空白
  2. 数据层应该保持纯净,只包含真实数据
  3. Fallback 方案更简单,不需要修改数据结构
  4. 避免在多个地方维护占位项逻辑