# 资源轨道分镜预览修复 **日期**: 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 逻辑,处理占位项: ```typescript // 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. 避免在多个地方维护占位项逻辑