VideoGaga 的专业创作模式被拆成七个步骤:故事设定、参数配置、场景角色道具、分镜、视频与配音等。页面拆开以后,每一步的界面更容易理解,但状态也随之散落到组件内部。

最初的实现可以完成单个页面的交互,却逐渐出现三个问题:

  1. 从一个步骤切换到另一个步骤时,前面的输入可能丢失。
  2. 多个组件分别维护项目进度,对“当前完成到哪一步”产生不同理解。
  3. 页面组件同时承担渲染、请求和数据转换,修改一处容易影响其他步骤。

把状态从页面里拿出来

在提交 6968961 中,我把工作流状态集中到了 Zustand store,并以 projectKey 作为隔离单位。每个项目拥有一份独立状态:

type ProjectState = {
  storySetting: StorySettingState;
  params: WorkflowParamsState;
  progress: Record<number, "done" | "skipped">;
};

页面不再直接拼装整份项目数据,而是通过 setStorySetting、setWorkflowParams、setStepStatus 等动作更新自己负责的部分。这样既避免了不同项目互相覆盖,也让每个步骤只关心自己的输入和输出。

这次调整同时把请求与状态逻辑从大型页面组件迁入 hooks 和 service:

  • useStorySetting 管理故事设定;
  • useAssets 管理场景、角色和道具;
  • useStoryboards 管理分镜;
  • useProjectState 负责项目级状态;
  • service 层封装 API 调用。

提交最终涉及 33 个文件,新增 1368 行、删除 922 行。代码量并没有简单减少,但页面组件的职责明显收窄了。

七步流程没有消失

这次重构没有为了“看起来简单”而强行减少业务步骤。七步仍然存在,变化的是它们共享同一份项目状态和进度定义。

我从中得到的经验是:多步骤表单的复杂度不只来自步骤数量,更来自状态所有权。如果每个页面都认为自己拥有完整状态,流程越长,数据不一致的概率越高。先确定项目级真源,再拆页面和组件,通常比继续增加页面间参数更可靠。

统一状态模型解决了页面间的协作问题,但刷新、返回和跨页面导航仍然会暴露持久化边界,这也成为下一阶段要处理的问题。