跳到主要内容

UI Schemas(UI 架构)

概览

  • UI Schema 用于为资源字段提供前端呈现与表单行为的“覆盖层”配置。
  • 支持多层覆盖:DEFAULT → TENANT → ROLE → USER,后者优先级更高,按顺序进行深度合并。
  • 典型场景:为某租户下的某角色或某用户定制字段的组件类型、默认值、校验与列表/表单显示行为。

结构约定(覆盖层 schemaJson)

  • 顶层对象包含 fields:一个以字段名为键的映射。
  • 每个字段对应一个 FieldConfig,其中包含以 x- 开头的 UI 属性。

示例:

{
"fields": {
"status": {
"x-component": "Select",
"x-options": ["Open", "Closed", "Pending"],
"x-default-value": "Open",
"x-label": "Status",
"x-visible": true,
"x-required": true
}
}
}

说明:

  • 合并策略以键为单位对 fields.<fieldName> 进行深度合并。
  • x-options 支持两种形态:
    • 简单数组:如上面的 string[](常用于快速选择项);
    • 对象:{ choices: Array<Choice>, defaultValue?: any, ... }(在部分模块中常用,尤其是 Select)。

字段级 UI 属性(FieldConfig)

以下为通用且已在多模块中使用的 x- 属性清单:

  • x-component:组件类型

    • 取值(不区分大小写,示例按首字母大写):TextTextareaNumberBooleanSelectDateDateTimeEmailUrl
    • 若未指定,前端可按字段数据类型推断默认组件。
  • x-label:自定义显示标签(string

  • x-default-value:默认值(string | number | boolean | null

    • x-options.defaultValue 二选一即可,若同时存在,以更高优先级覆盖层的值为准。
  • x-visible:是否显示(boolean

  • x-required:是否必填(boolean

    • 也可能根据模型的 isNullable === false 判定必填。
  • x-tooltip:提示信息(string

  • x-placeholder:占位文本(string

  • x-options:组件配置(支持两种形态)

    • 简单数组:string[](快速提供选择项)
    • 对象:Record<string, any>,常见字段:
      • choices: Array<{ id: string; name: string } | string>
      • defaultValue: 组件层面的默认值
      • multiple: boolean(多选)
      • 其他组件特定的 props(如 min/max/step 对 Number;日期格式对 Date/DateTime 等)。
  • x-order:排序权重(number

    • 用于控制字段在列表/表单中的显示顺序。
  • x-form-hidden:在表单隐藏该字段(boolean

  • x-list-hidden:在列表/表格隐藏该字段(boolean

校验相关(可选,按组件类型适用)

  • x-minLength:最小长度(number,适用于 Text/Textarea/Email/Url
  • x-maxLength:最大长度(number,适用于 Text/Textarea/Email/Url
  • x-min:最小值(number,适用于 Number
  • x-max:最大值(number,适用于 Number
  • x-email:邮箱格式校验(boolean,适用于 Email

列表筛选相关(在部分应用中使用)

  • x-filter-choices:列表筛选项(Array<{ id: string; name: string } | string>),用于构建筛选器选择项。

合并与优先级

  • 覆盖层获取顺序:DEFAULT → TENANT → ROLE → USER
  • 合并策略:Map 深度合并,数组/标量覆盖(后者优先)。
  • 角色层支持按请求中的角色顺序进行合并,以保持预期覆盖顺序。

API(覆盖层)

  • 基础路径:/metadata/ui-schema-overlays(网关路由到后端 Controller/api/v1/ui-schema-overlays
  • 支持分页与筛选:scopeType, tenantId, scopeKey, resourceName, page, pageSize
  • CRUD:GET /, GET /{id}, POST /, PUT /{id}, DELETE /{id}
  • JSON 校验:GET /validate?json=<schemaJson>

覆盖层对象(UiSchemaOverlay)

常用字段:

  • scopeTypeDEFAULT | TENANT | ROLE | USER(缺省为 DEFAULT
  • scopeKey:范围键(ROLE 为角色名,USER 为用户ID)
  • resourceId:实体ID(可选;若不提供可用 resourceName
  • resourceName:实体名(可选;若不提供可用 resourceId
  • schemaJson:覆盖层 JSON(字符串,必须是合法 JSON);为空时可由服务端根据实体字段自动生成默认 UI Schema
  • tenantId:租户ID(创建时由服务端按请求头写入)

查询覆盖层列表

  • GET /ui-schema-overlays
  • 权限:admin
  • 请求头:AuthorizationX-Tenant-Id
  • 查询参数:
    • scopeTypescopeKeyresourceName(可选)
    • page(从 1 开始,默认 1)、pageSize(默认 20)

创建覆盖层(可自动生成默认 schemaJson)

  • POST /ui-schema-overlays
  • 权限:admin
  • 请求头:AuthorizationX-Tenant-Id
  • 规则:
    • resourceIdresourceName 至少提供一个(用于定位实体并生成默认 UI Schema)
    • schemaJson 为空或空白时,服务端会根据实体字段生成默认 schemaJson
    • schemaJson 非空时必须是合法 JSON,否则返回 INVALID_JSON

示例:

curl -X POST \
"${API_BASE}/metadata/ui-schema-overlays" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Id: tenant-abc123" \
-H "Content-Type: application/json" \
-d '{
"scopeType": "TENANT",
"resourceName": "customers",
"schemaJson": "{ \"fields\": { \"email\": { \"x-component\": \"Email\", \"x-required\": true } } }"
}'

更新 / 删除 / 校验 JSON

  • PUT /ui-schema-overlays/{id}:更新覆盖层(需提供合法 JSON 的 schemaJson
  • DELETE /ui-schema-overlays/{id}:删除覆盖层
  • GET /ui-schema-overlays/validate?json=<schemaJson>:校验 schemaJson 是否为合法 JSON(合法返回 200,否则 400)

示例

1. Select 组件(对象形态 x-options)

{
"fields": {
"category": {
"x-component": "Select",
"x-label": "分类",
"x-required": true,
"x-options": {
"choices": [
{ "id": "electronics", "name": "电子" },
{ "id": "books", "name": "图书" }
],
"multiple": false,
"defaultValue": "electronics"
}
}
}
}

2. Number 组件(包含范围与占位)

{
"fields": {
"age": {
"x-component": "Number",
"x-label": "年龄",
"x-required": true,
"x-min": 0,
"x-max": 120,
"x-placeholder": "请输入年龄"
}
}
}

3. 简单数组形态的 x-options(快速选择)

{
"fields": {
"status": {
"x-component": "Select",
"x-options": ["Open", "Closed", "Pending"],
"x-default-value": "Open"
}
}
}

兼容性与建议

  • x-options 两种形态均受支持;若需要更丰富的 props,推荐使用对象形态。
  • 为提升查询性能,建议在后端为 (tenantId, scopeType, resourceName) 等组合建立索引。
  • 前端编辑器可按组件类型动态显示更适合的属性(如 Number 的范围、Select 的多选)。

统一 UiSchema DSL(列表 / 表单 / 详情等)

在覆盖层 schemaJson 之外,前端还定义了一套统一的 UiSchema DSL,用于描述资源的列表页、表单页、详情页、关联子表以及动作按钮等配置,主要类型定义见前端 /ui/web/src/ui-schema-new/types.ts

顶层结构(UiSchema):

  • version:版本号(字符串,例如 "1.0"
  • id:可选,Schema 自身 ID
  • resource:资源名(例如 "orders"
  • i18n:多语言文案字典
  • security:安全配置
    • roles:允许访问的角色列表
    • permissions:权限键值对
  • defaults:全局默认行为
    • perPage:默认每页条数
    • rowClick:列表行点击行为(edit | show | expand | none
  • list:列表配置(ListConfig
  • form:表单配置(FormConfig,包含 create / edit
  • show:详情页配置(ShowConfig
  • actions:动作定义列表(ActionDef[]
  • views:预置视图列表(ViewDef[]
  • metrics:嵌入的指标配置(MetricDef[]

列表配置(ListConfig):

  • title:列表标题
  • columns:列定义数组(ColumnDef[]
    • source:字段名
    • label:列标题
    • type:类型(文本/数字/日期等,按前端约定)
    • sortable:是否可排序
    • width:列宽
    • format:格式化字符串(如日期/数字格式)
    • component:单元格组件名
    • props:透传组件的属性
  • defaultSort:默认排序 { field, order }
  • filters:筛选条件定义(FilterDef[]
    • component:筛选控件类型(TextInput/NumberInput/BooleanInput/SelectInput/DatetimeInput/SearchInput/ReferenceInput
    • choices:本地枚举值(字符串/数组/对象均可)
    • props:组件 props
  • filterDefaultValues:筛选默认值
  • toolbar:工具栏动作 { actions: ActionRef[] }
  • rowActions:行级动作列表
  • selection:多选配置 { enabled: boolean }
  • data:数据源配置(DataSourceDef
  • perPage:每页条数(如未设置则回退到 defaults.perPage
  • rowClick:行点击行为(如未设置则回退到 defaults.rowClick

表单配置(FormConfig):

  • create / edit:分别对应新建/编辑页(FormPage
  • FormPage
    • title:页面标题
    • layout:分区布局(SectionDef[]
    • submit:提交行为配置(SubmitDef
  • SectionDef
    • id:分区 ID
    • title:分区标题
    • cols:分区总列数(12 栅格)
    • fields:表单字段列表(FormFieldDef[]
  • FormFieldDef
    • source:字段名
    • label:标签
    • component:输入组件名
    • props:组件 props
    • visibleIf:可见性表达式
    • disabledIf:禁用表达式
    • validate:校验规则数组(类型、文案、附加参数)
    • optionsSource:选项来源(远程接口或本地 choices)

详情页配置(ShowConfig):

  • title:详情标题
  • layout:分区布局(ShowSectionDef[]
  • toolbar:工具栏动作
  • related:关联子表配置(RelatedDef[]

关联子表(RelatedDef):

  • id:子表 ID
  • title:标题
  • resource:关联资源名
  • target:关联字段(如外键)
  • filter:过滤条件(JSON 或字符串模板)
  • sort:排序配置
  • perPage:每页条数
  • columns:列定义
  • data:数据源配置

动作定义(ActionDef):

  • id:动作 ID(供引用)
  • label:按钮文案
  • icon:图标名
  • kind:动作类型(link/dialog/mutation/download/custom
  • if:执行条件表达式
  • confirm:确认文案
  • payload:请求负载模板(字符串或对象)
  • request:请求定义(RequestDef
  • onSuccess / onError:成功/失败后的动作引用列表(ActionRef[]
  • feedback:用户提示文案 { success, error }
  • inputs:动作触发时需要采集的输入项(ActionInputDef[]
  • client:可选的前端本地执行配置(如通过 dataProvider 更新)

请求定义(RequestDef):

  • url:请求地址
  • method:HTTP 方法(默认 POST
  • headers:请求头
  • paramsTemplate:查询参数模板
  • bodyTemplate:请求体模板

数据源定义(DataSourceDef):

  • query
    • url:数据查询地址
    • method:HTTP 方法
    • params:静态查询参数
  • transform:可选的转换表达式或转换器名称

一般推荐做法:

  • UiSchema DSL 描述整页布局、动作与数据源。
  • UI Schema 覆盖层 做字段粒度的细节覆写(组件类型、显示/隐藏、校验等),二者可以配合使用。