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.
 

4.8 KiB

资源轨道 Items 显示修复

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

问题描述

资源轨道无法显示任何内容,虽然分镜数据中包含资源信息(items 字段中 itemType=2 的项),但 getStoryboardBoardByProjectId 函数错误地查找 storyboard.resources 字段(不存在),导致资源轨道的 items 数组为空。

症状

  • 分镜轨道、视频轨道、音效轨道等正常显示
  • 资源轨道完全空白,无任何块显示
  • 控制台日志显示资源轨道 itemsCount: 0

根本原因

数据结构不匹配

  1. 分镜数据结构mockStoryboards)使用 v3.0 统一关联表设计:

    {
      id: '018e1234-5678-7abc-8def-300000000001',
      items: [
        {
          itemType: 1,  // ElementTag
          elementTagId: '...',
        },
        {
          itemType: 2,  // Resource ✅ 资源数据在这里
          resourceId: '...',
        }
      ]
    }
    
  2. Mock 数据生成函数getStoryboardBoardByProjectId)错误地查找:

    if (storyboard.resources) {  // ❌ 这个字段不存在
      storyboard.resources.characters?.forEach(...)
    }
    
  3. 结果:资源轨道的 items 数组始终为空

解决方案

修复 Mock 数据生成逻辑

修改 client/src/mocks/storyboard-board.ts 中的 getStoryboardBoardByProjectId 函数:

修改前

// 2. 资源轨道项(从 storyboard.resources 获取)
if (storyboard.resources) {
  storyboard.resources.characters?.forEach((charRef) => {
    // ...
  });
}

修改后

// 2. 资源轨道项(从 storyboard.items 中提取 itemType=2 的资源项)
if (storyboard.items) {
  const resourceItems = storyboard.items.filter((item) => item.itemType === 2);
  resourceItems.forEach((resourceItem) => {
    if (resourceItem.resourceId) {
      items.push({
        id: `${storyboard.id}-resource-${resourceItem.resourceId}`,
        trackId: `track-resource-${projectId}`,
        itemType: 'storyboard',
        storyboardId: storyboard.id,
        startTime,
        endTime,
        displayOrder: resourceItem.displayOrder || 0,
        createdAt: resourceItem.createdAt || storyboard.createdAt,
        updatedAt: storyboard.updatedAt,
      });
    }
  });
}

关键改动

  1. 数据源:从 storyboard.resources 改为 storyboard.items
  2. 过滤条件:使用 itemType === 2 筛选资源项
  3. ID 生成:统一使用 ${storyboard.id}-resource-${resourceId} 格式
  4. 简化逻辑:不再区分角色、场景、道具、实拍,统一处理

技术细节

数据流

  1. 分镜数据mockStoryboards

    • 每个分镜包含 items 数组
    • itemsitemType=2 的项表示资源关联
  2. Mock 数据生成getStoryboardBoardByProjectId

    • 遍历所有分镜
    • items 中提取资源项
    • 生成资源轨道的 StoryboardBoardItem
  3. Mock APIstoryboardBoardApi.getByProjectId

    • trackId 分组 items
    • 返回包含 items 的 tracks
  4. 前端渲染StoryboardBoardTrack

    • 接收 track.items
    • 渲染资源块

资源轨道 Item 结构

{
  id: '018e1234-5678-7abc-8def-300000000001-resource-018e1234-5678-7abc-8def-200000000001',
  trackId: 'track-resource-018e1234-5678-7abc-8def-100000000001',
  itemType: 'storyboard',
  storyboardId: '018e1234-5678-7abc-8def-300000000001',
  startTime: 0,
  endTime: 4,
  displayOrder: 0,
}

测试验证

验证步骤

  1. 刷新浏览器,清除缓存
  2. 打开控制台,查看日志:
    [storyboardBoardApi] 初始化数据: {
      resourceTrackItems: 24  // ✅ 应该有 24 个(每个分镜至少 1 个资源)
    }
    
  3. 检查资源轨道是否显示分镜块

预期结果

  • 资源轨道显示 24 个分镜块
  • 每个块对应一个分镜的时间范围
  • 点击资源块时打开资源面板,显示该分镜的资源列表

相关文件

  • client/src/mocks/storyboard-board.ts - Mock 数据生成(已修复)
  • client/src/mocks/storyboards.ts - 分镜数据定义(使用 items 字段)
  • client/src/services/mock/storyboardBoardApi.ts - Mock API
  • client/src/hooks/useStoryboardBoardLogic.ts - 数据合并逻辑
  • client/src/components/features/storyboard-board/StoryboardBoardTrack.tsx - 轨道渲染

后续优化

  1. 统一数据结构文档,避免类似的字段不匹配问题
  2. 添加类型检查,确保 Mock 数据生成函数与实际数据结构一致
  3. 考虑添加单元测试验证 getStoryboardBoardByProjectId 的输出

参考文档