NocoBase FlowEngine UI Schema 语法参考:用声明式 JSON 描述 Flow 配置面板
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
UI Schema 是 NocoBase FlowEngine 中用来描述前端组件的声明式协议,它基于 Formily Schema 2.0(类 JSON Schema 风格),是插件开发者在registerFlow中定义 Flow 配置面板 UI 的核心语法。本文将从基本用法、属性语义、字段交互模式到与 FlowSettings 渲染管线的源码级关联,系统讲解这套协议,帮助你在 NocoBase 2.0 中快速写出可运行的配置面板。
UI Schema 是什么
在 NocoBase 的 FlowEngine 中,Flow 的每个 Step 都可以通过uiSchema字段声明"这个步骤需要用户在设置面板里配置哪些参数、用什么组件来配置"。UI Schema 本质上是一棵描述组件树结构的 JSON,由type、x-component、x-decorator、x-display、x-pattern等关键字驱动,底层协议来自 Formily Schema 2.0。
UI Schema 节点类型的 TypeScript 定义如下(来源于文档,与 packages/core/flow-engine/src/types.ts 中ActionDefinition/StepDefinition的uiSchema字段类型一致):
interface ISchema { type: 'void' | 'string' | 'number' | 'object' | 'array'; name?: string; title?: any; // 包装器组件 ['x-decorator']?: string; // 包装器组件属性 ['x-decorator-props']?: any; // 组件 ['x-component']?: string; // 组件属性 ['x-component-props']?: any; // 展示状态,默认为 'visible' ['x-display']?: 'none' | 'hidden' | 'visible'; // 组件的子节点 ['x-content']?: any; // children 节点 schema properties?: Record<string, ISchema>; // 以下仅字段组件时使用 // 字段联动 ['x-reactions']?: SchemaReactions; // 字段 UI 交互模式,默认为 'editable' ['x-pattern']?: 'editable' | 'disabled' | 'readPretty'; // 字段校验 ['x-validator']?: Validator; // 默认数据 default?: any; }可以看到,UI Schema 把"布局结构"与"字段行为"分成两组关键字:x-decorator/x-component/x-content/properties负责描述 UI 结构与组合方式;x-reactions/x-pattern/x-validator/default仅在字段组件上生效,负责描述交互模式、联动、校验与默认值。
基本用法
最简单的组件
所有的原生 HTML 标签都可以直接转为 schema 写法:
{ type: 'void', 'x-component': 'h1', 'x-content': 'Hello, world!', }它等同于 JSX:
<h1>Hello, world!</h1>这里的x-component接受两类值:一是原生 HTML 标签名(如h1、div、input);二是注册过的 React 组件名(如Input、Select、Switch)。x-content相当于组件的 children 内容。
子组件
children 组件写在properties里,每个 key 即一个子 schema 节点:
{ type: 'void', 'x-component': 'div', 'x-component-props': { className: 'form-item' }, properties: { title: { type: 'string', 'x-component': 'input', }, }, }等同于 JSX:
<div className={'form-item'}> <input name={'title'} /> </div>注意:子节点的name不需要重复声明,它直接取properties的 key(title),这也是 Formily 表单字段取值路径的来源。
属性说明
type
节点的类型:
type SchemaTypes = 'string' | 'object' | 'array' | 'number' | 'boolean' | 'void';string/number/boolean:普通字段,对应表单控件的取值类型;object/array:复合字段,用于嵌套结构或数组型配置;void:纯 UI 节点(不产生数据),例如div、h1这类布局与展示元素。
name
schema 名称,用于字段标识。子节点的 name 就是properties的 key:
{ name: 'root', properties: { child1: { // 这里不需要再写 name }, }, }在 Flow 配置面板中,字段的name(即properties的 key)同时就是 Step 参数(stepParams)里的参数键,handler(ctx, params)中拿到的params就按这些 key 组织。
title
节点标题,通常用于表单字段的标签。配合'x-decorator': 'FormItem'时,title会显示为表单项的 label。
x-component
组件名称。可以是原生 HTML 标签,也可以是注册的 React 组件:
{ type: 'void', 'x-component': 'h1', 'x-content': 'Hello, world!', }在 FlowSettings 中,组件来源于 packages/core/flow-engine/src/flowSettings.ts 的组件注册表:FlowSettings.load()会动态导入@formily/antd-v5并注册Input、NumberPicker、Select、Switch、DatePicker、Radio、Checkbox等组件,插件也可以通过flowSettings.registerComponents({ MyComponent })或registerComponentLoaders注册自定义组件,之后即可在x-component中直接引用。
x-component-props
组件属性,会直接透传给x-component指向的组件:
{ type: 'void', 'x-component': 'Table', 'x-component-props': { loading: true, }, }x-decorator
包装器组件。x-decorator+x-component的组合,可以将两个组件放在一个 schema 节点里——降低结构复杂度,提高复用率。decorator 是"包裹在组件外层"的组件,负责承载布局、校验态、label 等公共能力。
比如表单场景里,FormItem就是 decorator:
{ type: 'void', 'x-component': 'div', properties: { title: { type: 'string', 'x-decorator': 'FormItem', 'x-component': 'Input', }, content: { type: 'string', 'x-decorator': 'FormItem', 'x-component': 'Input.TextArea', }, }, }等同于 JSX:
<div> <FormItem> <Input name={'title'} /> </FormItem> <FormItem> <Input.TextArea name={'content'} /> </FormItem> </div>在 Flow 配置面板的实际实现中,renderStepForm(见 packages/core/flow-engine/src/flowSettings.ts)会把步骤的uiSchema包进一个FormLayout(layout: 'vertical')中渲染,再交给SchemaField用x-decorator/x-component逐节点解析成真实的 React 元素。
x-display
组件的展示状态:
| 值 | 说明 |
|---|---|
'visible' | 显示组件(默认) |
'hidden' | 隐藏组件,但数据不隐藏 |
'none' | 隐藏组件,数据也隐藏 |
hidden与none的核心区别在于:hidden只是不渲染 UI,字段的值仍然参与表单提交与参数保存;none则连字段取值都会隐藏,适合"临时废弃某个配置项"的场景。
x-pattern
字段组件的交互模式:
| 值 | 说明 |
|---|---|
'editable' | 可编辑(默认) |
'disabled' | 不可编辑 |
'readPretty' | 友好阅读模式——比如单行文本组件在编辑模式下是<input />,友好阅读模式下是<div /> |
readPretty是 NocoBase/Formily 生态里非常有特色的模式:表单在"详情查看"场景下不会渲染一堆禁用的输入框,而是渲染为纯文本展示,视觉上更干净,也更利于只读场景的性能。
在 registerFlow 中使用
在插件开发中,uiSchema 主要用在registerFlow的配置面板里。每个字段通常用'x-decorator': 'FormItem'包裹,让配置项自动获得表单项的 label、校验态与错误提示:
MyModel.registerFlow({ key: 'flow1', on: 'beforeRender', steps: { editTitle: { title: '编辑标题', uiSchema: { title: { type: 'string', title: '标题', 'x-decorator': 'FormItem', 'x-component': 'Input', }, showBorder: { type: 'boolean', title: '显示边框', 'x-decorator': 'FormItem', 'x-component': 'Switch', }, color: { type: 'string', title: '颜色', 'x-decorator': 'FormItem', 'x-component': 'Select', enum: [ { label: '红色', value: 'red' }, { label: '蓝色', value: 'blue' }, { label: '绿色', value: 'green' }, ], }, }, handler(ctx, params) { ctx.model.props.title = params.title; ctx.model.props.showBorder = params.showBorder; ctx.model.props.color = params.color; }, }, }, });在这个示例里可以看到完整的闭环:uiSchema声明"配置什么"(三个字段)、handler声明"拿到配置后做什么"(把参数写回ctx.model.props)。用户在设置面板填写的值最终会以params的形式注入handler。
从源码看,registerFlow的steps会被 packages/core/flow-engine/src/FlowDefinition.ts 的FlowDefinition类实例化为FlowStep,FlowStep暴露了get uiSchema()读取步骤的 UI Schema;打开设置面板时,packages/core/flow-engine/src/utils/schema-utils.ts 的resolveStepUiSchema会解析并合并步骤的 uiSchema(支持uiSchema为静态对象或函数两种形式,函数可接收FlowRuntimeContext动态返回 schema),随后FlowSettings.open()据此渲染表单并保存参数。
uiSchema 的动态与合并能力
除了上面展示的静态对象形式,uiSchema还支持函数形式——这在需要"根据当前模型上下文动态决定配置项"时非常有用。相关类型定义在 packages/core/flow-engine/src/types.ts 中:
uiSchema?: | Record<string, ISchema> | ((ctx: FlowRuntimeContext<TModel>) => Record<string, ISchema> | Promise<Record<string, ISchema>>);对应的解析逻辑在 packages/core/flow-engine/src/utils/schema-utils.ts 的resolveUiSchema:如果uiSchema是函数,就以FlowRuntimeContext为参数调用并await结果;解析失败时降级返回空对象{}。
此外还有两个细节值得注意:
- action 的 schema 合并:当步骤设置了
use(引用一个已注册的ActionDefinition)时,resolveStepUiSchema会先尝试从 action 上取uiSchema,作为步骤自身 uiSchema 的兜底(步骤自身优先)。 - 表达式编译:
compileUiSchema支持对 schema 中的{{ }}模板表达式进行编译(作用域中可注入t等翻译/工具函数),并使用模块级缓存提升重复渲染性能;当 schema 中包含函数(如x-reactions闭包)时会自动禁用缓存以避免跨上下文复用旧闭包。
常用组件速查
以下是在 Flow 配置面板中开箱即用的常用组件(由FlowSettings.load()从@formily/antd-v5注册,packages/core/flow-engine/src/flowSettings.ts):
| 组件 | x-component | type | 说明 |
|---|---|---|---|
| 单行文本 | Input | string | 基础文本输入 |
| 多行文本 | Input.TextArea | string | 多行文本域 |
| 数字 | InputNumber | number | 数字输入 |
| 开关 | Switch | boolean | 布尔开关 |
| 下拉选择 | Select | string | 需配合enum提供选项 |
| 单选 | Radio.Group | string | 需配合enum提供选项 |
| 多选 | Checkbox.Group | string | 需配合enum提供选项 |
| 日期 | DatePicker | string | 日期选择器 |
补充说明:
- 上表
x-component列写的是 Formily 组件名;在部分版本/场景中InputNumber也被注册为NumberPicker(两者都已在FlowSettings.load()中注册),写作NumberPicker亦可。 Select/Radio.Group/Checkbox.Group的选项通过enum传入{ label, value }[]数组,与示例中color字段的写法一致。- 除了上述常用组件,
FlowSettings.load()还注册了Cascader、TreeSelect、Transfer、Upload、TimePicker、Password、ArrayTable、ArrayCards等更多组件,并支持通过registerComponents扩展自定义组件;FlowSettings.registerScopes则可以注册可在 schema 表达式中使用的变量与函数。
使用边界与建议
:::tip 提示
v2 对 uiSchema 语法是兼容的,不过使用场景有限——主要用在 Flow 的配置面板中描述表单 UI。大部分运行时的组件渲染推荐直接用 Antd 组件实现。
:::
这意味着:UI Schema 是"配置面板(settings)"场景的首选描述方式,它让插件作者用纯 JSON 就能产出与 Formily 表单体系无缝集成的配置界面;而组件正文的渲染、页面级布局等运行时 UI,则应直接使用 React 组件(如 Antd 组件)编写,不需要套一层 Schema。
相关链接
- FlowEngine 概述(插件开发) — registerFlow 中 uiSchema 的实际用法
- Flow 定义概览(Event/Action/Step) — registerFlow 的完整参数说明
- uiSchema 配置参考(补充页) — FlowEngine uiSchema 的配置参考入口
- FlowEngine 概述 — 理解 Model 与 Flow 的基本概念
- 源码参考:packages/core/flow-engine/src/types.ts、packages/core/flow-engine/src/utils/schema-utils.ts、packages/core/flow-engine/src/flowSettings.ts、packages/core/flow-engine/src/FlowDefinition.ts
- 测试参考:packages/core/flow-engine/src/tests/flowSettings.open.test.tsx(展示了
registerFlow+uiSchema打开设置面板的完整用例)
uiSchema 底层基于 Formily Schema 协议,字段行为(x-reactions联动、x-validator校验、x-pattern交互模式)与 Formily 保持一致,理解 Formily 的 Schema 模型有助于深入掌握这套语法的边界能力。
【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考