VideoGaga 的专业创作模式被拆成七个步骤:故事设定、参数配置、场景角色道具、分镜、视频与配音等。页面拆开以后,每一步的界面更容易理解,但状态也随之散落到组件内部。
最初的实现可以完成单个页面的交互,却逐渐出现三个问题:
- 从一个步骤切换到另一个步骤时,前面的输入可能丢失。
- 多个组件分别维护项目进度,对“当前完成到哪一步”产生不同理解。
- 页面组件同时承担渲染、请求和数据转换,修改一处容易影响其他步骤。
把状态从页面里拿出来
在提交 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 行。代码量并没有简单减少,但页面组件的职责明显收窄了。
七步流程没有消失
这次重构没有为了“看起来简单”而强行减少业务步骤。七步仍然存在,变化的是它们共享同一份项目状态和进度定义。
我从中得到的经验是:多步骤表单的复杂度不只来自步骤数量,更来自状态所有权。如果每个页面都认为自己拥有完整状态,流程越长,数据不一致的概率越高。先确定项目级真源,再拆页面和组件,通常比继续增加页面间参数更可靠。
统一状态模型解决了页面间的协作问题,但刷新、返回和跨页面导航仍然会暴露持久化边界,这也成为下一阶段要处理的问题。