# RFC 139: 编辑器数据层统一与分镜看板可扩展重构 > **状态**: 🟡 提议 > **创建日期**: 2026-02-25 > **目标启动日期**: 2026-02-26 > **目标完成日期**: 2026-03-20 > **作者**: Codex(基于现网代码分析) --- ## 1. 摘要 当前 `ProjectPage` 及其子面板存在明显的数据域割裂问题: - 同一业务域被多套 Hook/接口重复拉取。 - 分镜看板仍以全量数据为中心,分页能力未真正落地。 - 资源面板、预览面板、右侧编辑器对资源信息的来源不统一。 - `200+` 分镜场景下,当前链路会出现数据截断和性能退化风险。 本 RFC 提出“统一编辑器数据层 + 分镜看板窗口化加载 + 增量写接口”的完整重构方案,目标是在不牺牲功能的前提下显著降低重复请求、提升可维护性与规模上限。 --- ## 2. 现状与问题 ## 2.1 现状(关键调用链) 1. 页面顶层:`ProjectPage.tsx` 同时拉 `useProject/useStoryboards/useScreenplays`。 2. 分镜看板:`useStoryboardBoardLogic` 同时拉 `useStoryboardBoardSkeleton/useStoryboardBoard/useStoryboardsWithDialogues/useResourceLibraryResources(4次)`。 3. 预览面板:`usePreviewData` 再次拉 `useStoryboardsWithDialogues`、`useProjectElementsForPicker`、`useResourceLibraryResources`、多类详情接口。 4. 分镜列表:`StoryboardList` 独立拉 `useStoryboards`、`useScreenplays`。 5. 资源相关:`useResources`(`resourceApi`)与 `useResourceLibraryResources` 并存。 6. 左/中/右布局区域对同一资源详情有重复读取(`CenterArea` 与 `RightSidebar` 都调用 `useResource`)。 ## 2.2 已识别的高优先级问题 ### P0 1. 分镜列表请求存在上限风险:`storyboards` 当前固定 `pageSize=100`。 2. 分镜看板主链仍是全量读取,未使用窗口化分页。 3. `storyboardBoardApi.update` 仍是占位实现,不具备真实持久化语义。 4. `useScreenplays` query key 未包含参数,存在缓存串用风险。 ### P1 1. 同一数据在多个面板重复聚合与重复转换。 2. `useStoryboardsWithDialogues` 通过“分镜 + 看板字幕轨”二次拼接,导致数据依赖方向反转。 3. 资源域存在两套模型与两套入口,增加维护复杂度与认知成本。 --- ## 3. 重构目标 1. 统一编辑器数据入口,避免同域重复请求。 2. 支持 `200~500` 分镜可用(滚动、拖拽、选择、预览稳定)。 3. 分镜看板实现窗口化读取与增量更新。 4. 资源域统一数据模型与缓存策略。 5. 将“面板逻辑”与“数据获取逻辑”分离,提升可测试性与可演进性。 --- ## 4. 非目标(本轮不做) 1. 不重做 UI/视觉设计。 2. 不更改核心业务语义(分镜、资源、标签、对白定义)。 3. 不在本 RFC 内覆盖移动端专门优化。 4. 不引入新的状态管理库(继续使用 Zustand + TanStack Query)。 --- ## 5. 设计原则 1. 单一事实源:每个业务域只有一个 canonical source。 2. 读写分离:读取窗口化、写入增量化。 3. 参数即身份:Query Key 必须完整表达查询语义。 4. 渐进迁移:允许旧组件短期并存,但由统一 facade 对外。 5. 可回滚:每个阶段可独立开关,出现回归可快速切回。 --- ## 6. 目标架构(推荐) ## 6.1 编辑器工作区数据层 新增聚合 Hook(前端 facade): ```ts useEditorWorkspaceData(projectId) ``` 对外统一提供: 1. `projectMeta`:项目/父项目/剧本目录摘要。 2. `storyboardSkeleton`:分镜顺序与时长骨架。 3. `storyboardWindow`:当前可视窗口轨道元素。 4. `storyboardDetailMap`:按需加载的分镜详情。 5. `resourceIndex`:统一资源索引(character/location/prop/footage)。 6. `selectionContext`:当前选中分镜/轨道元素/资源的规范化上下文。 面板(资源、预览、右侧编辑器、分镜看板)只消费 selector,不直接各自拼装跨域数据。 ## 6.2 分镜域数据分层 1. `Skeleton`(轻量):`id/orderIndex/duration/totalDuration`。 2. `Window`(中量):按 `startIndex/endIndex + overscan` 返回轨道元素。 3. `Detail`(重):点击或编辑时按需拉单分镜详情(含 items、资源映射)。 ## 6.3 资源域统一 以 `resource-library` 为主模型,废弃编辑器主链对 `useResources` 的依赖。 统一输出 `ResourceViewModel`,避免各处重复转换。 --- ## 7. API 设计调整 ## 7.1 读接口(建议) 1. 保留并强化 - `GET /projects/{id}/storyboard-board/skeleton` 2. 新增或替换(窗口化) - `GET /projects/{id}/storyboard-board/window?startIndex=...&endIndex=...&trackTypes=...` 3. 详情按需 - `GET /storyboards/{id}?includeItems=true` 4. 资源统一索引(可选聚合接口) - `GET /projects/{id}/resource-library/index?types=character,location,prop,footage&search=...` ## 7.2 写接口(建议) 严格禁止“整板全量回写”,仅保留增量语义: 1. `POST /projects/{id}/storyboard-board/reorder` 2. `PATCH /storyboards/{id}`(时长/标题/描述) 3. `POST /storyboards/{id}/items` 4. `PATCH /storyboard-items/{itemId}`(位置/可见性/层级等) 5. `DELETE /storyboard-items/{itemId}` --- ## 8. 前端重构方案 ## 8.1 Query Key 规范化 示例: ```ts screenplayKeys.list(projectId, params) storyboardBoardKeys.window(projectId, startIndex, endIndex, trackTypes) resourceKeys.index(projectId, { types, search, page, pageSize }) ``` 要求: 1. Key 必须包含所有影响结果的参数。 2. 禁止同 key 复用不同分页条件。 3. selector 层禁止直接 `any` 映射,统一 ViewModel。 ## 8.2 组件职责重分配 1. `ProjectPage`:只做路由与工作区生命周期,不直接驱动业务判断请求。 2. `StoryboardBoardPanel`:只关心渲染与交互,数据通过 `useEditorWorkspaceData` 注入。 3. `PreviewPanel` 与 `RightSidebar`:统一消费 `selectionContext + resourceIndex/detail`。 4. `ProjectResourcePanel`:基于统一资源索引与筛选参数,不再二次拼装。 ## 8.3 逐步淘汰 1. 逐步移除 `useStoryboardsWithDialogues`。 2. 逐步将 `useResources/useResource` 迁移到资源库统一域。 3. 将 `updateStoryboardBoard` 全量写路径替换为增量 mutation。 --- ## 9. 分阶段实施计划 ## 阶段 0(2026-02-26 ~ 2026-02-27):止血修复 1. 修复 `useScreenplays` key 参数缺失。 2. 修复 `storyboards` 固定 `pageSize=100`。 3. 标注 `storyboardBoardApi.update` 为受控禁用路径(仅本地乐观用途,不作为持久化)。 退出标准: 1. 不再出现 `screenplays` 缓存串用。 2. 分镜列表可读取 `>100` 数据。 ## 阶段 1(2026-02-28 ~ 2026-03-04):统一读模型 1. 新建 `useEditorWorkspaceData` facade。 2. 接入 skeleton + window 读取。 3. 预览、看板、资源面板切换到 facade selector。 退出标准: 1. 同一 project 在一次进入流程中,不再出现同域重复网络请求。 2. 面板间切换无额外全量刷新。 ## 阶段 2(2026-03-05 ~ 2026-03-10):增量写模型 1. 引入 item 级更新 mutation。 2. 分镜重排与时长更新仅走增量接口。 3. 移除全量 tracks 回写依赖。 退出标准: 1. 拖拽/改时长/增删资源条目均可持久化。 2. 无全量 payload 写回。 ## 阶段 3(2026-03-11 ~ 2026-03-15):资源域收敛 1. 将编辑器资源读取统一到 `resource-library`。 2. 清理 `useResources` 在编辑器主链的使用点。 3. 统一 `ResourceViewModel`。 退出标准: 1. 资源面板、预览、右侧属性使用同一资源缓存域。 2. 资源点击联动不再触发跨模型补丁代码。 ## 阶段 4(2026-03-16 ~ 2026-03-20):收尾与观测 1. 性能回归测试与错误率监控。 2. 移除临时兼容分支与无效 Hook。 3. 完成文档与开发指南更新。 --- ## 10. 验收标准(DoD) ## 10.1 功能验收 1. 资源面板点击资源后,预览与右侧编辑器联动一致。 2. 分镜看板点击分镜/元素后,选择态与内容态一致。 3. 分镜列表排序与看板顺序无错位。 4. 剧本目录、分镜稿列表、看板入口数据源一致。 ## 10.2 性能验收(`200` 分镜基线) 1. 首屏仅拉 skeleton + 首窗口数据。 2. 水平滚动仅触发窗口增量请求。 3. 看板操作不触发全量列表重拉。 4. `200` 分镜下交互无明显卡顿(主观可用 + 性能面板无持续长任务尖峰)。 ## 10.3 工程验收 1. Query key 全量参数化通过 code review。 2. 不再存在整板全量持久化调用。 3. 关键链路具备最少集成测试覆盖(看板排序、资源联动、分镜详情按需拉取)。 --- ## 11. 风险与回滚 ## 11.1 主要风险 1. 旧组件依赖隐式字段,迁移期间出现联动回归。 2. 增量写接口上线顺序不当,导致乐观更新与服务端状态不一致。 3. 资源模型统一时出现类型映射缺漏(尤其标签字段)。 ## 11.2 回滚策略 1. 阶段开关:`workspaceDataFacadeEnabled`、`storyboardWindowEnabled`、`incrementalBoardMutationEnabled`。 2. 每阶段保留一条旧链路兜底,发布后观察 24 小时再清理。 3. 出现 P0 回归时,按开关回退到前一稳定阶段,不回退数据库结构。 --- ## 12. 影响范围(预估) ## 12.1 前端 1. `client/src/pages/ProjectPage.tsx` 2. `client/src/hooks/useStoryboardBoardLogic.ts` 3. `client/src/hooks/useStoryboardsWithDialogues.ts`(逐步废弃) 4. `client/src/components/features/preview/hooks/usePreviewData.ts` 5. `client/src/components/features/project/ProjectResourcePanel.tsx` 6. `client/src/hooks/api/useScreenplays.ts` 7. `client/src/hooks/api/useStoryboardBoard.ts` 8. `client/src/hooks/api/useResources.ts`(编辑器主链移除) ## 12.2 后端(如配套实施) 1. `storyboard-board` 读取窗口化接口。 2. `storyboard-items` 增量更新接口能力完善。 3. 资源库聚合索引接口(可选)。 --- ## 13. 任务清单(执行版) - [ ] Phase 0: 修复 `useScreenplays` key 参数化 - [ ] Phase 0: 取消 `storyboards` 固定 `pageSize=100` - [ ] Phase 1: 新建 `useEditorWorkspaceData` - [ ] Phase 1: 接入 skeleton + window 读链路 - [ ] Phase 1: 迁移 `PreviewPanel`/`StoryboardBoardPanel`/`ProjectResourcePanel` 到 facade selector - [ ] Phase 2: 替换全量看板写入为增量 mutation - [ ] Phase 2: 加入看板拖拽/排序/时长变更集成测试 - [ ] Phase 3: 统一资源域并移除编辑器主链 `useResources` - [ ] Phase 4: 清理遗留 Hook 与兼容分支 - [ ] Phase 4: 更新开发文档与故障排查手册 --- ## 14. 参考 1. `docs/client/changelogs/2026-02-08-storyboard-board-optimization.md` 2. `docs/client/changelogs/2026-01-31-storyboard-performance-optimization.md` 3. `docs/client/rfcs/132-screenplay-resources-refactor.md` 4. `docs/architecture/adrs/003-storyboard-board-orderindex-optimization.md`