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.
 

11 KiB

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 再次拉 useStoryboardsWithDialoguesuseProjectElementsForPickeruseResourceLibraryResources、多类详情接口。
  4. 分镜列表:StoryboardList 独立拉 useStoryboardsuseScreenplays
  5. 资源相关:useResourcesresourceApi)与 useResourceLibraryResources 并存。
  6. 左/中/右布局区域对同一资源详情有重复读取(CenterAreaRightSidebar 都调用 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):

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 规范化

示例:

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. PreviewPanelRightSidebar:统一消费 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. 阶段开关:workspaceDataFacadeEnabledstoryboardWindowEnabledincrementalBoardMutationEnabled
  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