# 前端影响分析:storyboard_resources 废弃 ## 概述 本文档详细分析前端代码中受 `storyboard_resources` 废弃影响的所有文件。 ## 受影响文件清单 ### 📊 统计总览 | 类别 | 文件数 | 严重程度 | 说明 | |------|--------|---------|------| | API 服务层 | 1 | 🔴 高 | 核心 API 调用失效 | | 类型定义 | 1 | 🟡 中 | 类型定义过时 | | UI 组件 | 6 | 🔴 高 | 资源显示/操作失效 | | Hooks | 2 | 🔴 高 | 业务逻辑失效 | | 工具函数 | 1 | 🟡 中 | 状态计算不准确 | | Mock 数据 | 3 | 🟢 低 | 仅影响开发环境 | | **总计** | **14** | - | - | --- ## 详细分析 ### 1. API 服务层(1 个文件) #### 📄 `client/src/services/api/storyboards.ts` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 91-112 行 const syncStoryboardResources = async ( storyboardId: string, resources: StoryboardResources ) => { const desiredIds = collectResourceIds(resources); // ❌ 调用废弃的 GET 端点 const existing = (await apiClient.get( `/storyboards/${storyboardId}/resources` )) as ProjectResourceResponse[]; const existingIds = new Set(existing.map((r) => r.projectResourceId)); const toAdd = desiredIds.filter((id) => !existingIds.has(id)); const toRemove = Array.from(existingIds).filter((id) => !desiredIds.includes(id)); // ❌ 调用废弃的 POST 端点 if (toAdd.length > 0) { await apiClient.post(`/storyboards/${storyboardId}/resources/batch`, { resource_ids: toAdd, }); } // ❌ 调用废弃的 DELETE 端点 if (toRemove.length > 0) { await apiClient.delete(`/storyboards/${storyboardId}/resources/batch`, { data: { resource_ids: toRemove }, }); } }; // 第 194-196 行 async update(id: string, data: UpdateStoryboardDto): Promise { // ... if (data.resources) { await syncStoryboardResources(id, data.resources); // ❌ 调用失效 } // ... } ``` **影响**: - ❌ 更新分镜时无法同步资源关联 - ❌ 所有依赖此 API 的组件功能失效 - ❌ 3 个废弃 API 端点调用: - `GET /storyboards/{id}/resources` - `POST /storyboards/{id}/resources/batch` - `DELETE /storyboards/{id}/resources/batch` **修复方案**: 1. 删除 `syncStoryboardResources` 函数 2. 使用 `storyboard_items` API 替代 3. 修改 `update` 方法,移除 `resources` 同步逻辑 --- ### 2. 类型定义(1 个文件) #### 📄 `client/src/types/storyboard.ts` **严重程度**:🟡 中 **问题代码**: ```typescript // 第 14-20 行 export interface StoryboardResources { characters: StoryboardResourceItem[]; locations: StoryboardResourceItem[]; props: StoryboardResourceItem[]; footages?: StoryboardResourceItem[]; } // 第 21-26 行 export interface StoryboardResourceItem { resourceId: string; tagId?: string; tagLabel?: string; displayOrder: number; } // 第 48-52 行 export interface Storyboard { // ... /** 关联的资源(详情接口返回) */ resources?: StoryboardResources; // ❌ 废弃字段 /** v3.0 统一关联表 - 分镜元素关联项 */ items?: StoryboardItem[]; // ✅ 新字段 // ... } ``` **影响**: - ⚠️ 类型定义过时,但不会导致编译错误 - ⚠️ 开发者可能误用 `resources` 字段 - ⚠️ 代码提示会显示废弃字段 **修复方案**: 1. 标记 `resources` 字段为 `@deprecated` 2. 添加 JSDoc 注释说明迁移路径 3. 最终删除 `StoryboardResources` 和 `StoryboardResourceItem` 接口 --- ### 3. UI 组件(6 个文件) #### 📄 3.1 `client/src/components/features/preview/VideoGenerationPrecheck.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 62-64 行 const storyboardCharacters = storyboard.resources?.characters || []; storyboardCharacters.forEach((_sc) => { const resource = resources.find((r) => r.id === _sc.resourceId); // ... }); // 第 79-81 行 const storyboardLocations = storyboard.resources?.locations || []; storyboardLocations.forEach((sl) => { const resource = resources.find((r) => r.id === sl.resourceId); // ... }); // 第 96-98 行 const storyboardProps = storyboard.resources?.props || []; storyboardProps.forEach((sp) => { const resource = resources.find((r) => r.id === sp.resourceId); // ... }); ``` **影响**: - ❌ 视频生成前的资源完整性检查失效 - ❌ 无法检测缺失的角色/场景/道具资源 - ❌ 可能导致视频生成失败 **使用场景**: - 用户点击"生成视频"按钮前的预检查 - 显示缺失资源的警告信息 **修复方案**: ```typescript // 优先使用 items,降级到 resources const resources = storyboard.items ? getResourcesFromItems(storyboard.items) : storyboard.resources || { characters: [], locations: [], props: [] }; const storyboardCharacters = resources.characters || []; const storyboardLocations = resources.locations || []; const storyboardProps = resources.props || []; ``` --- #### 📄 3.2 `client/src/components/features/preview/StoryboardResourcesPreview.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 189-193 行 if (storyboard.resources) { characters = getResourceWithTag(storyboard.resources.characters, 'character'); locations = getResourceWithTag(storyboard.resources.locations, 'location'); props = getResourceWithTag(storyboard.resources.props, 'prop'); footages = getResourceWithTag(storyboard.resources.footages, 'footage'); } // 第 452-469 行 {renderResourceSection( , '角色', groupedResources.characters, 'character' )} {renderResourceSection( , '场景', groupedResources.locations, 'location' )} {renderResourceSection( , '道具', groupedResources.props, 'prop' )} ``` **影响**: - ❌ 分镜资源预览面板显示为空 - ❌ 无法查看分镜关联的角色/场景/道具 - ❌ 添加/移除资源功能失效 **使用场景**: - 分镜详情页的资源预览面板 - 显示当前分镜使用的所有资源 - 提供添加/移除资源的操作 **修复方案**: ```typescript const groupedResources = useMemo(() => { if (storyboard.items) { return getResourcesFromItems(storyboard.items); } return storyboard.resources || { characters: [], locations: [], props: [], footages: [] }; }, [storyboard]); ``` --- #### 📄 3.3 `client/src/components/features/storyboard/StoryboardList.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 89-92 行 characters: getResourceNames(s.resources?.characters), characterDialogues, locations: getResourceNames(s.resources?.locations), props: getResourceNames(s.resources?.props), ``` **影响**: - ❌ 分镜列表中资源信息显示为空 - ❌ 无法快速查看每个分镜使用的资源 - ❌ 列表筛选功能可能失效 **使用场景**: - 项目分镜列表页 - 显示每个分镜的资源摘要 - 支持按资源筛选分镜 **修复方案**: ```typescript const resources = s.items ? getResourcesFromItems(s.items) : s.resources || { characters: [], locations: [], props: [] }; characters: getResourceNames(resources.characters), locations: getResourceNames(resources.locations), props: getResourceNames(resources.props), ``` --- #### 📄 3.4 `client/src/components/features/storyboard/StoryboardEditForm.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 19-22 行 interface ResourceSelectorProps { type: 'character' | 'location' | 'prop'; icon: React.ReactNode; // ... } // 第 65-68 行 const ResourceSelector = ({ type, // ... }: ResourceSelectorProps) => { const typeMap: Record = { character: 1, location: 2, prop: 3 }; const numericType = typeMap[type]; // ... } ``` **影响**: - ⚠️ 资源选择器组件本身可能正常工作 - ❌ 但选择后的资源无法正确保存(依赖 `syncStoryboardResources`) - ❌ 表单提交后资源关联失败 **使用场景**: - 分镜编辑表单 - 选择角色/场景/道具资源 - 保存分镜时同步资源关联 **修复方案**: - 修改表单提交逻辑 - 使用 `storyboard_items` API 保存资源关联 - 不再依赖 `resources` 字段 --- #### 📄 3.5 `client/src/components/features/storyboard/ParseFlowDialog.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 1113-1125 行 const characters = item.resources?.characters ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; const allCharacters = Array.from(new Set([...characters, ...charNamesFromDialogues])); const locations = item.resources?.locations ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; const props = item.resources?.props ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; ``` **影响**: - ❌ 剧本解析流程中资源映射失败 - ❌ 无法将剧本中的角色/场景/道具映射到项目资源 - ❌ 自动创建分镜时资源关联缺失 **使用场景**: - 剧本解析流程 - 自动识别剧本中的资源 - 创建分镜时自动关联资源 **修复方案**: ```typescript const resources = item.items ? getResourcesFromItems(item.items) : item.resources || { characters: [], locations: [], props: [] }; const characters = resources.characters ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; const locations = resources.locations ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; const props = resources.props ?.map((c) => resourceMap.get(c.resourceId) || '') .filter(Boolean) || []; ``` --- #### 📄 3.6 `client/src/components/features/storyboard-board/StoryboardBoardItem.tsx` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 464-468 行 processV2Items(storyboard.resources.characters); processV2Items(storyboard.resources.locations); processV2Items(storyboard.resources.props); processV2Items(storyboard.resources.footages); ``` **影响**: - ❌ 分镜看板项显示异常 - ❌ 资源轨道显示为空 - ❌ 时间轴上的资源标记缺失 **使用场景**: - 分镜看板视图 - 显示分镜在时间轴上的位置 - 显示分镜关联的资源 **修复方案**: ```typescript const resources = storyboard.items ? getResourcesFromItems(storyboard.items) : storyboard.resources || { characters: [], locations: [], props: [], footages: [] }; processV2Items(resources.characters); processV2Items(resources.locations); processV2Items(resources.props); processV2Items(resources.footages); ``` --- ### 4. Hooks(2 个文件) #### 📄 4.1 `client/src/hooks/usePreviewActions.ts` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 49-52 行 const existingResources = currentStoryboard.resources || { characters: [], locations: [], props: [], footages: [] }; // 第 96-98 行 if (!currentStoryboard || !currentStoryboard.resources) return; const existingResources = currentStoryboard.resources; const updatedResources = { ...existingResources }; ``` **影响**: - ❌ 预览页面的资源添加功能失效 - ❌ 预览页面的资源移除功能失效 - ❌ 资源操作后无法正确更新状态 **使用场景**: - 分镜预览页面 - 快速添加/移除资源 - 实时更新资源列表 **修复方案**: ```typescript const resources = currentStoryboard.items ? getResourcesFromItems(currentStoryboard.items) : currentStoryboard.resources || { characters: [], locations: [], props: [], footages: [] }; const existingResources = resources; ``` --- #### 📄 4.2 `client/src/hooks/useStoryboardBoardLogic.ts` **严重程度**:🔴 高 **问题代码**: ```typescript // 第 823 行 console.log('[useStoryboardBoardLogic] 当前分镜资源:', storyboard.resources); // 第 837-839 行 const updatedResources = { ...(storyboard.resources || { characters: [], locations: [], props: [], footages: [] }), }; ``` **影响**: - ❌ 分镜看板逻辑中资源同步失败 - ❌ 拖拽分镜时资源信息丢失 - ❌ 看板状态计算不准确 **使用场景**: - 分镜看板的核心业务逻辑 - 处理分镜拖拽、排序、更新 - 维护看板状态一致性 **修复方案**: ```typescript const resources = storyboard.items ? getResourcesFromItems(storyboard.items) : storyboard.resources || { characters: [], locations: [], props: [], footages: [] }; console.log('[useStoryboardBoardLogic] 当前分镜资源:', resources); const updatedResources = { ...resources }; ``` --- ### 5. 工具函数(1 个文件) #### 📄 `client/src/utils/storyboard-board-status.ts` **严重程度**:🟡 中 **问题代码**: ```typescript // 第 44-50 行 if (storyboard.resources) { storyboard.resources.characters?.forEach((item) => relatedResourceIds.add(item.resourceId) ); storyboard.resources.locations?.forEach((item) => relatedResourceIds.add(item.resourceId) ); storyboard.resources.props?.forEach((item) => relatedResourceIds.add(item.resourceId) ); storyboard.resources.footages?.forEach((item) => relatedResourceIds.add(item.resourceId) ); } ``` **影响**: - ⚠️ 分镜状态计算不准确 - ⚠️ 资源完整性判断失效 - ⚠️ 看板状态指示器显示错误 **使用场景**: - 计算分镜的完成状态 - 判断资源是否完整 - 显示状态指示器(如:缺失资源警告) **修复方案**: ```typescript if (storyboard.items) { storyboard.items.forEach(item => { if (item.resourceId) { relatedResourceIds.add(item.resourceId); } }); } else if (storyboard.resources) { // 降级方案 storyboard.resources.characters?.forEach(item => relatedResourceIds.add(item.resourceId) ); storyboard.resources.locations?.forEach(item => relatedResourceIds.add(item.resourceId) ); storyboard.resources.props?.forEach(item => relatedResourceIds.add(item.resourceId) ); storyboard.resources.footages?.forEach(item => relatedResourceIds.add(item.resourceId) ); } ``` --- ### 6. Mock 数据(3 个文件) #### 📄 6.1 `client/src/services/mockApi.ts` **严重程度**:🟢 低 **问题代码**: ```typescript // 第 55 行 resources: mockStoryboard.resources, ``` **影响**: - ⚠️ 仅影响开发环境 - ⚠️ Mock 数据结构与实际 API 不一致 - ⚠️ 可能导致开发时的测试不准确 **修复方案**: ```typescript resources: mockStoryboard.resources, // 保留向后兼容 items: mockStoryboard.items, // 添加新字段 ``` --- #### 📄 6.2 `client/src/services/mock/storyboardApi.ts` **严重程度**:🟢 低 **问题代码**: ```typescript // 第 25 行 resources: mockStoryboard.resources, ``` **影响**:同 `mockApi.ts` **修复方案**:同 `mockApi.ts` --- #### 📄 6.3 `client/src/mocks/storyboard-board.ts` **严重程度**:🟢 低 **问题代码**: ```typescript // 第 7-8 行注释 * - 分镜看板数据实时从分镜及其关联表计算,无独立数据存储 * - 所有轨道数据都源自 storyboards 及其关联的 resources ``` **影响**: - ⚠️ 注释过时,但不影响功能 - ⚠️ 可能误导开发者 **修复方案**: ```typescript * - 分镜看板数据实时从分镜及其关联表计算,无独立数据存储 * - 所有轨道数据都源自 storyboards 及其关联的 items (v3.0) 或 resources (v2.0) ``` --- ## 修复优先级 ### 🔴 P0 - 立即修复(核心功能失效) 1. **API 服务层** - `client/src/services/api/storyboards.ts` - 影响:所有资源关联功能 2. **UI 组件 - 资源预览** - `client/src/components/features/preview/StoryboardResourcesPreview.tsx` - 影响:分镜详情页核心功能 3. **UI 组件 - 视频生成** - `client/src/components/features/preview/VideoGenerationPrecheck.tsx` - 影响:视频生成流程 ### 🟡 P1 - 高优先级(影响用户体验) 4. **Hooks - 预览操作** - `client/src/hooks/usePreviewActions.ts` - 影响:资源添加/移除功能 5. **Hooks - 看板逻辑** - `client/src/hooks/useStoryboardBoardLogic.ts` - 影响:分镜看板功能 6. **UI 组件 - 分镜列表** - `client/src/components/features/storyboard/StoryboardList.tsx` - 影响:列表显示 7. **UI 组件 - 看板项** - `client/src/components/features/storyboard-board/StoryboardBoardItem.tsx` - 影响:看板显示 ### 🟢 P2 - 中优先级(功能降级) 8. **UI 组件 - 编辑表单** - `client/src/components/features/storyboard/StoryboardEditForm.tsx` - 影响:资源选择器 9. **UI 组件 - 剧本解析** - `client/src/components/features/storyboard/ParseFlowDialog.tsx` - 影响:自动化流程 10. **工具函数 - 状态计算** - `client/src/utils/storyboard-board-status.ts` - 影响:状态指示器 11. **类型定义** - `client/src/types/storyboard.ts` - 影响:类型提示 ### ⚪ P3 - 低优先级(开发环境) 12. **Mock 数据** - `client/src/services/mockApi.ts` - `client/src/services/mock/storyboardApi.ts` - `client/src/mocks/storyboard-board.ts` - 影响:仅开发环境 --- ## 修复策略 ### 阶段 1:核心功能修复(P0) **目标**:恢复基本的资源关联功能 **步骤**: 1. 修复 API 服务层 2. 修复资源预览组件 3. 修复视频生成预检查 **预计工作量**:2-3 天 ### 阶段 2:用户体验修复(P1) **目标**:恢复完整的用户交互功能 **步骤**: 1. 修复 Hooks 2. 修复列表和看板显示 **预计工作量**:2-3 天 ### 阶段 3:功能完善(P2) **目标**:修复所有功能降级 **步骤**: 1. 修复编辑表单 2. 修复剧本解析 3. 修复工具函数 4. 更新类型定义 **预计工作量**:1-2 天 ### 阶段 4:清理优化(P3) **目标**:清理开发环境代码 **步骤**: 1. 更新 Mock 数据 2. 删除废弃代码 3. 更新文档 **预计工作量**:1 天 --- ## 总结 ### 关键数据 - **受影响文件总数**:14 个 - **核心功能失效**:6 个组件 + 2 个 Hooks + 1 个 API 服务 - **预计修复工作量**:6-9 天 - **风险等级**:🔴 高 ### 核心问题 1. **API 调用失效**:3 个废弃端点被调用 2. **数据结构不匹配**:`resources` vs `items` 3. **向后兼容缺失**:没有降级方案 4. **测试覆盖不足**:缺少端到端测试 ### 建议 1. **立即行动**:修复 P0 级别的文件 2. **向后兼容**:同时支持 `resources` 和 `items` 3. **增加测试**:编写端到端测试覆盖资源关联场景 4. **分阶段部署**:避免一次性破坏所有功能