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.
6.3 KiB
6.3 KiB
资源轨道数据源重构:从 resources 字段迁移到 storyboard_items
日期:2026-02-02
类型:重构 + Bug 修复
影响范围:分镜看板资源轨道显示
问题描述
资源轨道无法显示分镜的资源数据(角色、场景、道具、实拍)。
根本原因
-
数据源不匹配:
- 组件期望从
storyboard.resources读取数据(v2.0 格式) - 后端架构使用
storyboard_items统一关联表(v3.0 格式)
- 组件期望从
-
类型定义缺失:
Storyboard接口缺少items字段定义- Mock 数据中的
items字段无法被 TypeScript 识别
-
Mock 数据不完整:
- 分镜数据只包含
item_type=1(剧本元素标签) - 缺少
item_type=2(资源关联)的数据
- 分镜数据只包含
解决方案
1. 补充类型定义
文件:client/src/types/storyboard.ts
export interface Storyboard {
// ... 其他字段
/** v3.0 统一关联表 - 分镜元素关联项 */
items?: StoryboardItem[];
}
export interface StoryboardItem {
itemId: string;
itemType: 1 | 2; // 1=ElementTag, 2=Resource
elementTagId?: string; // item_type=1 时使用
resourceId?: string; // item_type=2 时使用
elementName: string;
tagLabel?: string;
coverUrl?: string;
isVisible: boolean;
spatialPosition?: string;
actionDescription?: string;
displayOrder: number;
zIndex: number;
metadata?: Record<string, unknown>;
createdAt: string;
}
2. 补充 Mock 数据
文件:client/src/mocks/storyboards.ts
为每个分镜的 items 数组添加资源类型的关联数据:
items: [
// 剧本元素标签(item_type=1)
{
itemId: '...',
itemType: 1,
elementTagId: '...',
elementName: '孙悟空',
// ...
},
// 资源关联(item_type=2)- 新增
{
itemId: '...',
itemType: 2,
resourceId: '018e1234-5678-7abc-8def-200000000001', // 指向 project_resources
elementName: '孙悟空',
tagLabel: '青年',
coverUrl: 'https://...',
isVisible: true,
displayOrder: 0,
zIndex: 1,
createdAt: '...'
}
]
3. 重构资源轨道渲染逻辑
文件:client/src/components/features/storyboard-board/StoryboardBoardItem.tsx
修改前:
// 从 storyboard.resources 读取
storyboard.resources?.characters
storyboard.resources?.locations
修改后:
// 从 storyboard.items 过滤资源类型
const resourceItems = (storyboard.items || []).filter(
(item) => item.itemType === 2 // ItemType.RESOURCE
);
// 按资源类型分组
const characterItems = resourceItems.filter((item) => {
const resource = resources.find((r) => r.id === item.resourceId);
return resource && resource.type === 'character';
});
数据流向
分镜数据 (mockStoryboards)
↓
storyboard.items (包含 itemType=1 和 itemType=2)
↓
过滤 itemType=2 (资源关联)
↓
按 resourceId 查找 project_resources
↓
按资源类型分组 (character/location/prop/footage)
↓
渲染到资源轨道的四行
已完成的修改
文件清单
-
✅
client/src/types/storyboard.ts- 添加
Storyboard.items字段 - 添加
StoryboardItem接口定义
- 添加
-
✅
client/src/mocks/storyboards.ts- 为前 3 个分镜补充资源类型的 items 数据
-
✅
client/src/components/features/storyboard-board/StoryboardBoardItem.tsx- 修改资源轨道数据源:从
storyboard.resources改为storyboard.items - 添加资源类型过滤和分组逻辑
- 添加调试日志
- 修改资源轨道数据源:从
待完成的工作
1. 补充剩余分镜的资源数据
文件:client/src/mocks/storyboards.ts
当前只为前 3 个分镜添加了资源数据,需要为剩余 21 个分镜补充:
// 第 4 个分镜:金色符咒
items: [
// ... 现有的 elementTag items
// 需要添加资源关联 items
{
itemId: '018e1234-5678-7abc-8def-400000000105',
itemType: 2,
resourceId: '...', // 对应的资源 ID
elementName: '...',
tagLabel: '...',
// ...
}
]
2. 验证数据显示
打开浏览器控制台,检查日志输出:
[StoryboardBoardItem] 资源轨道数据: {
storyboardId: "...",
totalItems: X,
resourceItems: Y,
items: [...]
}
[StoryboardBoardItem] 资源分组结果: {
characterItems: N,
locationItems: M,
propItems: P,
footageItems: F
}
如果 resourceItems: 0,说明:
- Mock 数据中没有
itemType=2的数据 - 或者
storyboard.items为空
3. 移除调试日志
确认功能正常后,移除以下调试代码:
// StoryboardBoardItem.tsx
console.log('[StoryboardBoardItem] 资源轨道数据:', ...);
console.log('[StoryboardBoardItem] 资源分组结果:', ...);
console.log(`[renderResourceRow] ${label}:`, ...);
架构优势
v3.0 统一关联表的优势
- 数据一致性:所有分镜元素(标签、资源)统一管理
- 冗余字段优化:
elementName、tagLabel、coverUrl冗余存储,查询无需 JOIN - 扩展性强:未来添加新元素类型(如音效、对白)无需修改表结构
- 性能优化:单表查询,避免多表 JOIN
与 v2.0 的对比
| 维度 | v2.0 (resources 字段) | v3.0 (storyboard_items 表) |
|---|---|---|
| 数据源 | storyboard.resources | storyboard.items |
| 查询性能 | 需要 JOIN 多表 | 单表查询(冗余字段) |
| 扩展性 | 需修改字段结构 | 只需添加 itemType |
| 数据一致性 | 分散管理 | 统一管理 |
相关文档
后续优化建议
- 批量生成工具:编写脚本批量为所有分镜生成资源关联数据
- 类型安全:使用
ItemType枚举替代魔法数字1和2 - 数据验证:添加 Zod schema 验证
storyboard.items数据格式 - API 集成:对接后端 API,替换 mock 数据
变更记录:
- 2026-02-02:初始版本,记录资源轨道数据源重构过程