Appearance
Feature: AI 生成状态机
一句话目标
用户在任意节点点击生成后,系统调用 AI API 完成生成,结果自动填充节点,全程有明确的状态反馈。
行为约束
约束 1:状态转换规则
节点生成状态仅允许以下转换,任何其他转换为非法:
idle→generating(点击生成按钮)generating→done(API 成功返回)generating→error(API 抛出异常)done→idle(用户修改 prompt 或重新生成时隐式重置)error→generating(用户重试)
约束 2:generating 期间禁止重复提交
前置条件: 节点状态为 generating行为: 当前请求被取消,新请求立即发起 后置条件: 旧请求的回调被忽略,不更新节点状态
约束 3:generating 期间展示 loading
前置条件: 节点状态为 generating行为: 节点内容区显示 loading 状态 后置条件: 生成完成(done/error)后 loading 消失
约束 4:生成结果填充
前置条件: API 成功返回且请求未被 abort 行为: 结果写入节点数据(TextNode → content,ImageNode → imageUrl/results,VideoNode → videoUrl) 后置条件: 节点状态变为 done
约束 5:API 错误不丢失用户输入
前置条件: API 调用失败(网络错误或 ApiError) 行为: 节点状态变为 error,显示 toast 错误信息 后置条件: prompt、现有内容、已上传的文件均保持不变
约束 6:不兼容上游输入的处理
前置条件: 下游节点有上游连线,但上游节点类型与当前模型不兼容 行为: 生成时忽略不兼容的上游输入,toast 提示用户(如"当前模型不支持视频输入") 后置条件: 生成正常发起,仅携带兼容的上游输入和用户自身的 prompt
详见 ADR-008
约束 7:组件卸载时清理
前置条件: 用户在 generating 期间离开画布或删除节点 行为: onUnmounted 中 abort 当前请求 后置条件: 不会有悬挂的 Promise 回调更新已卸载的组件
状态机
idle ──[点击生成]-→ generating ──[成功]-→ done
↑ │
│ └──[失败]-→ error
│ │
└──────[修改重试]───────────────────┘
done ──[重新生成]-→ generatingAcceptance Criteria
- [x] AC-01:节点初始状态为
idle - [x] AC-02:点击生成后立即进入
generating,按钮禁用 - [ ] AC-03:
generating期间节点内容区显示 loading - [x] AC-04:API 成功后进入
done,结果写入节点,loading 消失 - [x] AC-05:API 失败后进入
error,不丢失用户输入,loading 消失 - [x] AC-06:连续点击生成时,abort 旧请求,发起新请求
- [x] AC-07:组件卸载时 abort 进行中的请求
- [x] AC-08:生成时注入上游节点数据到请求参数 → 详见 data-flow
- [x] AC-09:不兼容的上游输入被静默跳过 → 详见 data-flow 约束 6
BDD Scenarios
gherkin
Feature: AI 生成状态机
Scenario: 正常生成文本
Given 一个文本节点处于 idle 状态
And 已输入 prompt "写一段产品介绍"
When 用户点击生成按钮
Then 节点状态变为 generating
And 生成按钮变为禁用
When AI 生成成功返回
Then 节点状态变为 done
And 内容区显示生成结果
Scenario: 生成失败保持用户输入
Given 一个文本节点处于 idle 状态
And 已输入 prompt "测试失败"
When 用户点击生成按钮
And API 请求失败
Then 节点状态变为 error
And prompt 输入保持 "测试失败" 不变
And 显示错误 toast
Scenario: 连续点击 abort 旧请求
Given 一个文本节点处于 generating 状态(第一次请求)
When 用户再次点击生成
Then 第一次请求被 abort
And 发起新的生成请求TDD 单元测试要点
针对各节点的 onGenerate 逻辑:
- [x] idle → generating 状态转换正确
- [x] 成功后 status=done 且 result 被写入
- [x] 失败后 status=error 且 prompt 保持不变
- [ ] abort 后旧回调不更新状态
Out of Scope
- 生成结果的版本历史
- 多变体并行生成的进度展示
- 流式生成(streaming)