多步向导

开发版运行时把向导当成导航与校验协议,而不是换了样式的标签页。

编排结构

向导是 layout: "wizard"rootgroupsection 节点。它的直接子节点必须是 layout: "page" 的 group 或 section。

{
  "id": "onboarding",
  "kind": "group",
  "label": "创建 Workspace",
  "layout": "wizard",
  "children": ["identity-page", "contact-page", "review-page"]
}

页面的 pageRole 默认为 "form"。最后一页可以设置为 "review",用于展示本地化汇总和返回编辑链接。Designer 可以直接创建这套结构,作者能添加、移动、重命名和配置步骤,不需要编辑原始 JSON。

编译器会拒绝有歧义的结构:空向导、非 page 子节点、孤立 page、嵌套向导、重复字段组中的 page,以及位置错误或重复的 review 页。

分支与校验

给页面添加普通 visible 规则即可分支。进度和导航只计算当前可见页面。

“下一步”先同步校验当前页;配置宿主校验后,再调用 { kind: "page", nodeId }。宿主如果返回当前页以外的字段错误,响应会按非法结果关闭。隐藏页面的同步错误不会阻塞当前分支,无头 evaluateFormValue 使用相同规则。

主操作只在最后一个可见页面出现。最终提交仍执行表单级校验;如果错误属于前面的页面,Renderer 会自动返回该页并聚焦对应控件。

不污染表单值的恢复协议

导航状态不写入受控表单值。宿主单独保存与编译结果绑定的 checkpoint:

const created = createFormWizardCheckpoint(
  plan,
  'onboarding',
  'contact-page',
  ['identity-page'],
);

if (created.ok) {
  await checkpointStore.put(runId, created.checkpoint);
}
<FormRenderer
  plan={plan}
  value={value}
  onChange={setValue}
  wizardCheckpoints={checkpoints}
  onWizardCheckpointChange={({ checkpoint }) => {
    setCheckpoints((current) => ({
      ...current,
      [checkpoint.wizardId]: checkpoint,
    }));
  }}
/>

restoreFormWizardCheckpoint 会拒绝不同的 digest、revision、wizard 或 page。持久化、恢复令牌、权限和保留周期仍由宿主负责。

Vue 转发 wizardCheckpoints 并触发 wizardCheckpointChange;Web Component 提供同名属性,并触发 wizard-checkpoint-change

在 Playground 中打开“组织创建向导”,可以测试企业条件分支、页面级宿主校验、确认页、移动布局和受控 checkpoint 更新。

完整 API、校验规则和宿主边界见仓库文档 docs/wizards.md