# 预演台统一重构:分析、设计与执行方案 ## 0. 结论先行 当前问题不是“高频工作流样式还不够精致”,而是产品结构上同时维护了两套入口: - 高频工作流:真实高频工作流,布局清晰,用户已经反复调试到可用。 - 旧分裂工作台:功能覆盖更广,但布局、样式和交互边界长期没有同步,已经出现样式 bug、功能 bug、滚动问题和空白问题。 继续在两套页面上各自修复,会让同一份场景数据拥有两套操作语义,之后每次新增能力都要重复接线、重复测试、重复修复。 本轮方向确定为: > 删除“高频工作流”和“旧分裂工作台”这两个产品层级,把所有能力合并到一个统一的“预演台”工作区。布局、视觉和交互以已经验证过的高频工作流方案为主;从 DirectorDesk 只吸收真正有价值的场景编排能力,尤其是轨迹绘制与轨迹播放,不复制它的表面结构。 “预演台”是产品名称。内部可以继续保留 `layout / pose / animate / camera` 作为能力状态,但它们只能是同一工作区中的上下文,不再是两套工作台。 ## 1. 反复犯错的问题 ### 1.1 把参考产品的表面结构当成了产品答案 错误表现: - 看到 DirectorDesk 的左侧布景、右侧摄影机、底部时间轴,就把“多面板旧分裂工作台”整体搬过来。 - 只复制了组件形状、标题和分栏,没有先确认我们的用户真正高频的任务顺序。 - 参考产品里真正有价值的能力(轨迹、路径、基于距离的步行动画、镜头连续性)反而没有成为主线。 修复思路: - 参考产品只提取“能力和原则”,不提取它的页面壳。 - 先问用户在当前产品里最常做什么,再决定入口、密度和默认视图。 - 对 DirectorDesk 的吸收清单只保留:自由手绘轨迹、轨迹简化、按距离分配时间、路径朝向、演员/摄影机路径可视化、同一场景多视图观察。 - 明确不复制:独立桌面应用的菜单层级、复杂资源管理、与本项目无关的深度导出和外部工程概念。 ### 1.2 把“功能完整”误解成“再造一个页面 错误表现: - 为了补齐布景、姿态、动画、摄影机,新增旧分裂工作台。 - 结果是高频工作流和旧分裂工作台分别拥有一部分能力,任何一边都不是完整事实来源。 - 同一个操作在两套页面上可能使用不同的保存、选择、视口和检查器路径。 修复思路: - 功能完整不等于页面分裂。 - 所有场景修改都必须进入同一套 `commit / history / save coordinator` 链路。 - 所有对象、灯光、摄影机、资产、姿态、关键帧和输出都在同一个预演台布局中可达。 - 复杂功能通过同一页面里的分区、抽屉、工具栏、检查器和时间轴渐进展开,而不是增加第二个工作台。 ### 1.3 先修局部样式,后补产品信息架构 错误表现: - 不断调整圆角、颜色、间距、按钮样式。 - 但页面仍然有两套入口,用户不知道该进入哪一个。 - 旧分裂工作台中的功能不在高频工作流出现,导致“看起来有功能,实际上找不到”。 修复思路: - 顺序固定为:信息架构 -> 任务路径 -> 状态模型 -> 组件布局 -> 视觉细节。 - 页面只有一个产品入口,先解决“在哪里做”再解决“看起来怎样”。 - 视觉规范以高频工作流当前已验证的密度、面板、颜色、对象列表和视口胶囊切换为基线。 ### 1.4 通过重新实现,破坏已经修好的行为 错误表现: - 修复 UI 时把保存、撤销、模型加载、上下文恢复、对象摆位等已稳定链路一起改动。 - 为了“统一”,把刻意放宽的产品规则重新收紧。 - 用逐个报错、逐个补洞的方式开发,最后无法确认完整流程是否可靠。 修复思路: - 统一页面只替换产品壳,不重写已稳定的场景数据和保存底座。 - 保留 `touchPrevisScene`、`commit`、`stagedTransaction`、保存协调器、模型加载诊断和 WebGL 恢复机制。 - 每轮修改后跑完整流程:打开、加对象、选中、摆位、画轨迹、播放、保存、回写、关闭、重开。 - 不以“某一个错误消失”为完成标准,而以端到端流程通过为标准。 ### 1.5 把轨迹当成动画的附属细节,而不是核心能力 错误表现: - 目前主要依靠零散 transform 关键帧和简单折线显示。 - 用户无法像导演在场地上画走位一样直接表达动作。 - 轨迹时间可能受鼠标事件数量、停顿和绘制速度影响,导致播放速度不稳定。 修复思路: - 轨迹是预演台的核心编辑对象,必须有明显的“画轨迹”入口。 - 轨迹采样后先做三维简化,再按路径距离分配时间,不能按 pointer event 间隔直接写时间。 - 演员沿轨迹移动时默认按路径方向转向;摄影机轨迹至少保证位置连续,并保留原镜头朝向。 - 轨迹必须能在导演视角、机位视角和时间轴播放中被验证。 ## 2. 用户调教出来的产品设计原则 这些不是装饰偏好,而是预演台的产品约束: 1. 高频工作流是 99% 用户使用的真实入口,所有功能必须进入主工作流。 2. 不允许用“高级模式”作为缺功能的借口;高级能力必须在同一个预演台中自然出现。 3. UI 需要高端、专业、有质感,但不能靠装饰遮盖信息架构问题。 4. 画布节点必须有真实场景缩略图或可靠的实时预览,不用空白文字占位冒充完成。 5. 新演员必须默认拥有可区分的颜色,颜色可直接编辑。 6. 对象、摄影机、灯光、资产、环境、姿态、运镜、动画和输出必须在同一场景事实源中工作。 7. 操作必须可逆、可保存、可重开,不能出现“界面看起来成功但数据没有保存”。 8. 功能入口应该面向任务:添加角色、搭景、画轨迹、设计镜头、调整动作、输出,而不是面向内部代码模块。 9. 不用重复造同一套 UI。一个布局、一个状态模型、一个保存链路、一个测试入口。 10. 重构不得把已经明确放宽的产品规则重新收紧,例如素材删除不因为引用关系被拦截。 ## 3. DirectorDesk 真正值得吸收的东西 ### 吸收 - **自由手绘路径**:在地面或物体表面直接拖出演员/摄影机路线。 - **路径点清理和简化**:去掉高频采样噪声,同时保留拐角和闭环形状。 - **基于距离的时间分配**:相同路径不因鼠标快慢、帧率或事件密度而改变播放速度。 - **连续路径与途经点停留**:后续可支持停留点、分段速度和连续曲线。 - **路径方向**:演员沿路径方向朝向;摄影机可选择沿路径、看向目标或保持镜头方向。 - **路径可视化**:轨迹线、起点、终点、当前播放位置、选中状态要一眼可见。 - **位置和动作分离**:路线控制空间移动,动作片段控制走路/跑步/姿势,二者可以独立调整。 - **多视图验证**:导演视角调整空间关系,机位视角检查最终画面,时间轴检查连续性。 ### 不吸收 - 不复制 DirectorDesk 的独立应用信息架构。 - 不复制与本项目无关的资源目录、导出协议和菜单层级。 - 不为了“看起来像”而保留第二个高级页面。 - 不把桌面端复杂能力一次性全部塞进首屏;复杂选项放入检查器和可展开工具。 ## 4. 统一预演台设计 ### 4.1 统一产品结构 名称:**预演台**。 单一全屏工作区: - 顶部:关闭、场景标题、撤销/重做、保存状态、渲染模式、生成白膜、回写构图。 - 左侧:场景对象、摄影机、灯光、道具库、画布资产、轨迹目标入口。 - 中间:主 3D 视口;导演视角/机位视角/正交视图切换;对象和轨迹直接可见。 - 右侧:当前镜头与选中对象检查器;景别、运镜、时长、帧率、姿态、体型、颜色、变换、灯光、镜头参数和生成提示词。 - 底部:时间轴按需展开;镜头条、对象轨道、摄影机轨道、关键帧、播放和 Auto Key 都在这里。 没有“高频工作流 / 旧分裂工作台”切换按钮,也没有“进入旧分裂工作台”的隐藏入口。 ### 4.2 统一页面中的上下文 内部仍可以使用 `layout / pose / animate / camera` 作为能力上下文,但它们只影响: - 当前检查器优先展示什么。 - 是否显示时间轴和 Auto Key。 - 渲染模式有哪些。 - 当前工具栏的默认工具。 它们不能切换到另一套页面,也不能改变对象数据的来源。 ### 4.3 主任务顺序 1. 选镜头或创建镜头。 2. 从左侧添加演员、道具、资产、灯光和摄影机。 3. 在中间视口拖动对象,或点击“画轨迹”直接绘制走位。 4. 在右侧调整姿态、体型、颜色和镜头参数。 5. 在底部时间轴播放、补关键帧、查看轨迹连续性。 6. 在机位视角确认画面。 7. 生成白膜或回写构图。 每一步都应在同一个页面完成,不需要跳转或换工作台。 ### 4.4 轨迹交互 - 选中演员或摄影机后,工具栏出现“画轨迹”。 - 点击后进入绘制态:视口进入路径采样,OrbitControls 暂停,鼠标/触摸拖动生成地面路径。 - 绘制中显示临时路径和起点/终点。 - 松开后按当前镜头时长生成路径关键帧。 - 演员:按路径方向生成水平朝向,保留当前高度、缩放和姿态/动作。 - 摄影机:写入连续位置关键帧,默认保留当前旋转;后续再提供“沿路朝向 / 看向主体”的切换。 - 再次绘制覆盖该对象当前轨迹,撤销可以恢复旧轨迹。 - 没有选中可移动对象时,按钮给出明确提示,不进入半成品状态。 ## 5. 数据与实现边界 ### 保留 - `PrevisScene`、`PrevisObject`、`PrevisCamera`、`PrevisLight`。 - 现有 transform keyframe 结构,轨迹首版直接编译为关键帧,避免引入第二套持久化格式。 - `previs-animation-semantics.ts` 的动画编辑语义。 - 保存协调器、草稿恢复、页面卸载保护、诊断事件和视口 capture/record。 - 既有对象颜色、actor archetype、actorProfile、motionClips 和 boneTracks。 ### 新增 - `previs-path.ts`: - 三维点清理与 Ramer-Douglas-Peucker 简化。 - 按路径距离计算 waypoint 时间。 - 轨迹关键帧生成。 - 路径方向和 yaw 计算。 - 视口绘制态:仅在显式绘制轨迹时接管 pointer 事件。 - 轨迹预览:临时线、已保存路径、当前播放点。 - 单元测试覆盖:简化、距离计时、退化路径、方向角连续性、关键帧生成。 ### 不新增 - 不再增加 第二套模式状态。 - 不再保留一套只为“旧分裂工作台”服务的 JSX 和 CSS。 - 不建立第二个场景编辑器 store。 - 不把路径采样事件直接持久化为大量 pointer 记录。 ## 6. 重构阶段与验收门 ### Phase 1:先写统一事实源 - 删除顶部快速/高级切换。 - 统一预演台默认显示场景对象、摄影机、灯光、资产、镜头检查器。 - 将原旧分裂工作台中仍有价值的工具接入现有 `pv-*` 布局。 - 删除重复 JSX 和对应的高级 CSS。 成功标志:项目中只剩一个预演台 UI 分支,搜索不到“高频工作流/旧分裂工作台”产品入口。 ### Phase 2:轨迹基础能力 - 增加纯函数路径库和单元测试。 - 视口增加显式画轨迹态。 - 演员和摄影机轨迹编译为已有关键帧。 - 播放头和轨迹预览同步。 成功标志:能在同一页面画演员路线、播放并撤销;摄影机路线能在导演视角看到。 ### Phase 3:布局与体验收敛 - 左侧补齐旧分裂工作台里的对象、灯光、模型资产和道具入口。 - 右侧补齐对象/灯光/镜头检查器和提示词输出。 - 底部时间轴按动画上下文展开,不再用页面切换表达“高级”。 - 统一按钮、焦点、触控尺寸、滚动容器和空状态。 成功标志:用户不需要记住功能属于哪一种工作台;所有高频能力在一个页面可发现。 ### Phase 4:测试和清理 - 更新 Chrome E2E:不再点击旧分裂工作台;默认打开即验证统一界面。 - 保留对象添加、撤销、模型加载、上下文丢失恢复、保存失败重试等 P0 场景。 - 增加轨迹的纯函数测试和至少一条浏览器轨迹 smoke。 - 删除无引用的高级组件、样式、旧命名和测试描述。 成功标志:TypeScript、ESLint、单元测试、Vite build、Chrome E2E 全部通过;完整流程可从打开走到保存、关闭和重开。 ## 7. 明确的完成标准 - 用户只看到一个产品:预演台。 - 高频工作流中已验证的布局和视觉成为全局基线。 - 布景、演员、姿态、动画、摄影机、灯光、资产、环境、提示词和输出全部可达。 - 轨迹绘制成为一等交互,不是隐藏在高级模式里的补充按钮。 - 轨迹播放速度由路径距离和镜头时长决定,不由鼠标事件或绘制速度决定。 - 新演员颜色自动区分且可编辑。 - 画布卡片、模型加载、保存恢复和输出链路没有回归。 - 没有“进入旧分裂工作台”或“切换高频工作流”的产品级文案、按钮和双份页面。 ## 8. 本轮 IA 实施记录(2026-10-05) ### 已落地的左右面板职责 - 左侧只负责场景层级、对象、摄影机、灯光、道具和资源浏览;移除重复的摄影机、灯光、道具库添加入口,避免同一动作在多个面板出现。 - 中央只负责真实 WebGL 视口、对象操作、视角工具和轨迹绘制;移除旧的视图胶囊,视图状态统一由视口工具层管理。 - 右侧只负责当前选择上下文:选中对象显示对象检查器,选中灯光显示灯光检查器,选中摄影机显示摄影机检查器,无选择时才显示镜头设计上下文。 - 底部只负责时间、播放、Auto Key、镜头条、对象轨道和关键帧;不在左右面板复制时间控制。 - 移动端将右侧检查器变成滑入抽屉,通过显式打开/关闭按钮进入,不牺牲检查器能力,也不压缩主视口到不可用尺寸。 ### 覆盖层与响应式纠错记录 - 下拉菜单、工具提示和检查器抽屉使用明确的层级、边界和碰撞策略;打开菜单时不遮盖错误面板,Escape 可关闭,焦点回到触发控件。 - 本轮曾将移动工具声明放在 media block 外并多写一个 `}`,导致 Vite 在 `canvas-previs-workbench.css:1415` 失败。修正方式是把移动端工具栏、轨迹按钮和时间轴声明收回同一个 `@media (max-width: 860px)`,再以生产构建验证 CSS 结构。 - 移动端保留 176-200px 左侧层级栏、单列视口和 280px 时间轴下限;右侧检查器使用不超过 92vw 的抽屉,避免面板相互覆盖。 ### 当前验收状态(截至 2026-10-05) - 已通过:TypeScript、目标 ESLint、`git diff --check`、Vite production build、轨迹纯函数测试(`npx --yes bun test test/previs-path.test.ts`,5 tests / 12 assertions)。 - 已通过:完整 Chrome P0 E2E,A-F 共 62/62 断言通过;覆盖统一工作台启动、真实 WebGL、添加/撤销、动画时间轴、模型成功加载、模型失败重试、加载中删除、WebGL context loss/restore、保存失败提示、重试入口和关闭保护。 - 已通过:桌面结构探针(1680×932):左/右面板各 272px,中央 canvas 约 1132×879;DOM 中 `.pv-viewport-toolbar`、取景模式组和 canvas 各 1 个,旧 Dock 与视图胶囊均为 0。 - 已通过:窄屏结构探针(390×844):左层级栏 176px,主视口约 299px,右检查器以约 359px 抽屉停在屏幕外,工具栏位于主视口内;未发现面板几何重叠。开发环境仅出现已知 Ant Design/Three 弃用提示,无运行时异常。 - 已通过:精确旧双工作台/旧产品入口扫描为 0 命中;保留的历史文档术语不构成运行时入口。 - 尚未覆盖:浏览器内真实轨迹拖拽、轨迹取消/预览/播放、轨迹撤销和演员/摄影机轨迹持久化重载;保存成功后的重开闭环;保存失败后实际点击“重试保存”并确认恢复;移动端截图级视觉验收;完整下拉碰撞与焦点回归。 - 不能宣称完成的门禁:上述浏览器轨迹与持久化闭环仍需专门 smoke;本轮已证明轨迹算法和基础 pointer 取消逻辑,但没有把它们扩大解释为完整端到端通过。 ### 下一轮验收顺序 1. 在稳定的本地预演台页面完成浏览器轨迹绘制、取消、距离计时、预览、播放、撤销、镜头切换、模式切换和保存重载闭环。 2. 补保存成功重开、保存失败后重试成功,以及导出动作的浏览器断言。 3. 补移动端实际截图和打开检查器抽屉后的边界/焦点/Escape 断言。 4. 扫描源代码、测试和文档,确认不存在旧的双页面入口、路由、分支或产品级名称。 5. 最后再次运行 TypeScript、ESLint、轨迹测试、Vite build、E2E 和 `git diff --check`。