# 基础表单定制

# 目标读者

本文档的目标读者为:本系统的开发和实施人员

# 概述

系统的菜单、表单、表单字段分组、表单字段均保存在数据库中,可以在界面上维护,也可以写成 CSV 种子数据随系统导入。本文按「菜单 → 表单 → 字段分组 → 字段」的顺序说明各自的配置方法,最后给出一套完整的 CSV 示例。

# 菜单

# 定义

系统界面左侧的菜单由 DynamicMenu 对象渲染,在界面上通过 开发配置 > 界面显示 > 菜单 维护。页面左侧是菜单树,点击某个节点后,右侧显示该菜单的编辑表单,可以保存、删除,或在其下创建新菜单:

菜单的属性如下:

属性 说明
上级菜单(parent) 为空表示顶级菜单
名称(name) 必填,租户内唯一,创建后不能修改。CSV 导入时用它定位菜单
类型(type) 菜单类型,见下文
显示名称(label) 必填,菜单上显示的文字
图标(icon) antd 图标名称,见下文
关联表单(form) 类型为 FORM 时,点击菜单要打开的表单
链接地址(link) 类型为 INTERNAL_LINK / EXTERNAL_LINK 时的地址
显示顺序(displaySequence) 越小越靠前
访问要求(accessRequirement) 可见性要求,取值为 USER、DEVELOPER、ADMIN 等访问要求的名称。界面上没有这个字段,只能通过 CSV 设置

菜单显示名称的翻译

侧边栏显示菜单时,会以 label 为 key 到 menu 翻译命名空间中查找翻译(在 开发配置 > 国际化 > 界面翻译 中维护),所以上面菜单树里看到的是 label 原文,侧边栏里看到的是翻译后的文字。

# 与表单的关联

菜单和表单的关联关系保存在菜单上:编辑菜单,把类型设为 FORM,在「关联表单」中选择要打开的表单即可。表单上没有「所属菜单」字段。

# 可见性

菜单是否显示,由菜单和表单各自的 accessRequirement 共同决定:

  • FORM 类型菜单:如果菜单设置了 accessRequirement,先检查当前用户是否满足;再检查关联表单的 accessRequirement(表单未设置时所有人都满足)。两者都通过才显示。因此表单菜单一般不需要单独设置 accessRequirement,由表单决定即可。
  • 菜单组、内部链接、外部链接:必须设置 accessRequirement。没有设置时,任何用户(包括管理员)都看不到这个菜单。
  • 菜单组只有在至少有一个可见的子菜单时才会显示。

注意

菜单的编辑界面上没有「访问要求」字段。在界面上新建的菜单组或链接菜单,因为没有 accessRequirement,保存后不会出现在任何人的侧边栏中。请通过 CSV 导入菜单并填写 accessRequirement.name 列(见 菜单定义的 CSV 文件)。

# 类型

当前系统支持的菜单类型包括:

  • MENU_GROUP 菜单组:包含子菜单,可以通过嵌套菜单组实现多级菜单
  • FORM 表单:点击后打开「关联表单」,关于表单的定义见 表单 章节
  • INTERNAL_LINK 内部链接、EXTERNAL_LINK 外部链接:菜单地址取 link 属性。内部链接的 link 为空时,该菜单不会显示

# 图标

菜单的图标使用 antd 的图标,填写图标组件名称即可(如 UserOutlined),无需包括 <> 部分。图标列表请查看 Ant Design 图标 (opens new window)

# 表单

# 定义

自定义表单保存在 DynamicForm 对象中,在界面上通过 开发配置 > 表单 > 表单 维护。下图是新建一个只显示已锁定用户的列表表单:

表单的属性如下:

属性 说明
类型(type) 必填,见 表单类型
名称(name) 必填,租户内唯一,创建后不能修改。菜单、字段、字段组都通过它引用表单
显示名称(label) 表单在页面上显示的标题
描述(description) 说明
关联对象类型(objectType) 表单所展示的领域对象
扩展信息(extInfo) JSON 格式的扩展属性,见 表单的 extInfo 支持
Form Hook(formHook) 表单级客制化动态逻辑,用于字段默认值、联动、显隐、只读、必填等,详见 表单客制化(Form Hook)
Form Hook 触发字段(formHookTriggerFields) 逗号分隔的字段名,这些字段的值在界面上变化时,重新执行 Form Hook
Data Hook(dataHook) 数据级客制化动态逻辑,用于对列表、详情返回的数据做变换
访问要求(accessRequirement) 可以使用该表单的用户范围,未设置时所有用户都可以使用

提示

界面上的创建表单只包含「类型、名称、显示名称、描述、关联对象类型、扩展信息」。Form Hook、Form Hook 触发字段、Data Hook、访问要求需要通过 CSV 设置。在表单列表中点击「修改」,编辑弹窗中还会以子表的形式列出该表单的字段和字段组。

创建、编辑弹窗的标题按以下顺序取值(从菜单打开的页面,标题显示菜单名称):

  1. 表单的显示名称(label)
  2. extInfo 中的 domainTitle
  3. 关联对象名称的翻译(domainTitle 翻译命名空间)

# 表单类型

表单类型保存在 DynamicFormType 对象中,系统预置了 24 个类型。当前前端只为其中一部分提供了渲染器,把没有渲染器的类型挂到菜单上,页面只会显示 Unknown form 类型名。

类型 用途 当前前端
LIST 对象列表页面 支持
CREATE 对象创建表单 支持
UPDATE 对象编辑表单 支持
FINDER 列表上方的搜索区;也可以单独挂到菜单上 支持
DOMAIN 领域对象表单 支持
DEFAULT 通用表单,按字段定义渲染一组输入项 支持
MASTER_DETAIL_LIST 左树右表单的头行结构,见 头行结构表单定义 支持
TREE_LIST 树状列表 支持
DASHBOARD 仪表盘,详见 仪表盘 支持
AMIS 使用 AMIS Schema 描述的页面,见 AMIS 表单 支持
ACTION 对象动作的参数表单 支持
IFRAME 内嵌页面,地址取 extInfo 的 url 支持
SUB_TABLE 子表使用的表单,通过子表字段的 displayForm 按名称引用,按列表方式渲染 仅作子表
INLINE_DISPLAY 同上,旧版本用于内联详情 仅作子表
INLINE_EDITABLE_DISPLAY 同上,旧版本用于内联可编辑详情 仅作子表
DELETE 删除确认表单 未实现
INLINE_FULL_TEXT_SEARCH_LIST 内联全文检索结果 未实现
FULL_TEXT_SEARCH_LIST 全文检索结果 未实现
RELATED_DETAIL_LIST 关联详情列表 未实现
CARD_LIST 卡片列表 未实现
DYNAMIC_FRAME 动态框架 未实现
WIZARD 向导,1.0 起已移除(多步骤数据收集请使用 Form Hook) 已移除
GANTT 甘特图,1.0 起已移除 已移除
GANTT_TOOLTIP 甘特图详情卡片,1.0 起已移除 已移除

提示

「仅作子表」的三种类型没有独立的渲染器:子表字段按名称找到表单后,一律用列表方式渲染,和表单类型无关。前端插件可以通过 FrontendPluginManifest.forms 为任意表单类型注册自定义渲染器。

# AMIS 表单

平台内置 AMIS (opens new window) 低代码前端框架作为表单渲染器之一。类型为 AMIS 的表单,其 AMIS Schema 保存在表单 extInfo 的 amis 属性中。

# 能力

  • 可视化编辑:打开 AMIS 表单所在的页面后,如果当前用户对该表单有修改权限,页面上会出现浮动的「编辑」按钮。点击后进入 AMIS 可视化编辑器,保存后 Schema 写回表单 extInfo 的 amis 属性
  • 页面数据:打开页面时调用 GET /form/data/{formId},执行表单的 Data Hook,返回的对象作为 AMIS 页面的数据,Schema 中可以用 ${字段名} 引用。未配置 Data Hook 时页面数据为空
  • 统一鉴权:AMIS 组件发出的数据请求走平台统一请求通道,自动携带登录凭证

# 启用方式

  1. 在 开发配置 > 表单 > 表单 中创建表单,类型选择 AMIS
  2. 把表单挂到一个 FORM 类型的菜单上
  3. 从菜单打开页面,点击浮动的「编辑」按钮设计页面并保存

# 示例

下面的 Schema 显示 Data Hook 返回的 customerCount、vipCount 两个值:

{
  "type": "page",
  "title": "客户概况",
  "body": [
    { "type": "tpl", "tpl": "客户总数:${customerCount},其中 VIP 客户 ${vipCount} 个" }
  ]
}
1
2
3
4
5
6
7

# 表单字段分组

表单字段在对象的创建、编辑界面上,可以按可折叠的字段分组展示。

# 定义

字段分组保存在 DynamicFormGroup 对象中,在界面上通过 开发配置 > 表单 > 表单字段组 查看(下图隐藏了帮助信息、显示顺序等列,以便看全图标列):

注意

当前版本在「表单字段组」页面点击创建、修改、详情,弹窗会一直停留在加载状态,无法编辑。可以在 开发配置 > 表单 > 表单 中「修改」某个表单,在编辑弹窗的「字段组」子表中查看该表单已有的分组;新增、修改分组请通过 CSV 导入。

包含字段组的表单在界面上的显示效果如下(开发定制 > 定时任务 > 创建,其中「Logics」分组已折叠):

提示

当前前端直接显示字段组的显示名称(label),不做翻译,所以上图中系统预置的分组名称是英文。自己定义的字段组,label 直接写中文即可。上图中的字段标签「Start date」同样是当前版本未翻译的界面文字,与字段组无关。

字段组的属性如下:

属性 说明
名称(name) 必填,同一表单内唯一,创建后不能修改
显示名称(label) 必填,分组标题
显示顺序(displaySequence) 越小越靠前
帮助信息(helpText) 分组的帮助信息
图标(icon) antd 图标名称,参见 图标
所属表单(form) 必填,创建后不能修改

字段通过自己的「所属字段组」属性归入某个分组。

注意

当前版本不能动态隐藏整个字段组:接口返回的字段组不带显示状态,表单客制化(Form Hook) 只能逐个控制字段的显示。即使用 Form Hook 把组内字段全部隐藏,分组标题仍会显示。

# 命名建议

字段组名称只要求在同一表单内唯一。为了便于在 CSV 中识别,建议按 <表单类型>_<对象名>_<分组名> 命名,例如创建客户表单的基本信息分组命名为 c_customers_basic,编辑表单的为 u_customers_basic。

# 表单字段

# 定义

表单字段保存在 DynamicFormField 对象中,在界面上通过 开发配置 > 表单 > 表单字段 维护(下图省略了扩展信息编辑框下方的空白部分):

字段的属性如下:

属性 说明
所属表单(form) 必填
所属字段组(group) 字段所在的分组,可为空
字段类型(fieldType) 必填,STATIC_FIELD 静态字段或 TRANSIENT_FIELD 瞬态字段
字段名称(fieldName) 必填。静态字段必须是关联对象上已有的字段名
显示名称(label) 必填
帮助信息(helpText) 显示在字段旁的帮助信息
Decides(decides) 逗号分隔的字段名,旧版本用于「本字段变化后刷新其他字段」。当前版本不生效(前端请求的 /column/refresh/{domainName} 接口不存在),字段联动请使用表单的 Form Hook 触发字段
字段显示类型(displayType) 控件类型,自由文本,取值见 显示控件。留空时按对象字段的类型自动选择
是否可为空(nullable) 表单中该字段是否可以为空
扩展信息(extInfo) JSON 格式的扩展属性,见 表单字段的 extInfo 支持
显示顺序(displaySequence) 必填,越小越靠前
可编辑(editable) 只对瞬态字段生效,界面上没有这个字段,只能通过 CSV 设置。静态字段如需只读,在 extInfo 的 meta 中设置 editable(创建表单)或 updatable(编辑表单)为 false

提示

截图中「字段类型」下拉框里的 Static field、字段标签 Decides 当前界面未翻译。

针对不同的表单类型,字段定义控制的内容如下:

  • 列表页面:显示哪些列、列的顺序、显示控件
  • 查询(FINDER)表单:显示哪些查询条件、顺序、显示控件
  • 创建、编辑表单:显示哪些字段、顺序、是否必填、帮助信息、显示控件、所属分组

# 显示控件

displayType 是自由文本,后端只做一步转换:如果填写的是旧版本的控件名称(如 Sub table、Single file),会转换成对应的 key(subTable、file),其余值原样传给前端。前端找不到对应控件时,字段位置会显示 Unsupported displayType: xxx。

当前前端支持的控件 key 如下:

key 控件
id 标识符
string 单行文本
text 多行文本
password 密码
integer、int、long 整数
decimal 小数
percentage 百分比
currency 货币
date 日期
dateRange 日期范围
datetime 日期时间
zonedDatetime 带时区的日期时间
boolean 开关
enum 枚举下拉
httpMethod HTTP 方法(枚举下拉)
valueSelect 值选择
link 链接,可用 extInfo 的 link 设置显示文字和打开方式
progress 进度条
icon 图标
treeSelect 树选择
roles 角色
code 代码编辑器
json JSON 编辑器
markdown Markdown 编辑器
stacktrace 堆栈信息
functionEditor 函数编辑器
file 单个文件
fileList 多个文件
image 图片
video 视频
object 单个对象选择
objects 多个对象选择
genericObject、genericObjects 任意类型对象的只读显示
array 一对多关联对象列表
subTable 子表,见 高级字段控件
relativeSubTable 按关联路径显示的子表,见 高级字段控件
authentication 用户信息(如创建人)的只读显示
popOverSteps 步骤状态
lineChart 折线图
tableChart 表格图

注意

旧版本文档中的 Array with details、Array Inline、Multiple select、Object multiple select、Tags、Tag list、Static field、Updated ids、Series、Cron expression、Object ids、Document、Grouped grand child、Url、Entity Attributes、Comments 在当前前端没有对应控件,填写后会显示 Unsupported displayType。前端插件可以通过 FrontendPluginManifest.fields 注册更多控件。

# 瞬态字段

瞬态字段是对象上不存在、也不会保存到数据库的字段,把字段类型设为 TRANSIENT_FIELD 即可。瞬态字段:

  • 必须填写字段显示类型(displayType),否则保存时报错
  • 字段的值由用户在界面上输入,或者由 Form Hook、Data Hook 提供,平台不做计算
  • 可以在 extInfo 中用 domainName 指定对象类型(配合 object、objects 控件选择该类型的对象),或用 enumClass 指定枚举类(配合 enum 控件生成下拉选项)
  • 可以用「可编辑」(editable)属性控制是否只读

瞬态字段最常用于 ACTION 类型的动作参数表单,例如系统预置的批量添加用户到用户组动作,其参数表单中的 user 字段就是 displayType 为 objects、extInfo 为 {"domainName": "User"} 的瞬态字段。

# 推荐做法

推荐在开发过程中,把菜单、表单、字段分组和字段的定义保存在 CSV 文件中,作为种子数据 (Seed Data) 随系统导入,这样系统启动时会自动读取并更新这些定义。关于种子数据的导入请参考 数据导入。

# 真实系统中的使用示例

下面以 快速上手教程 中的 Customers(客户)对象为例,给出一套菜单、表单、字段分组和字段的 CSV。表头与系统预置种子数据一致,列名后带 (*) 的列用于查找已有记录并更新,以 ; 开头的行是注释。

# 菜单定义的 CSV 文件

parent.name,label,icon,link,type,displaySequence,name(*),form.name,accessRequirement.name

; 一级菜单组:菜单组必须设置 accessRequirement,否则所有人都看不到
NULL,客户管理,TeamOutlined,,MENU_GROUP,10,CRM,,USER

; 表单菜单:不设置 accessRequirement,可见性由关联表单决定
CRM,客户,UserOutlined,,FORM,1,Customers,List of customers,
CRM,VIP 客户,CrownOutlined,,FORM,2,VIP customers,List of VIP customers,
1
2
3
4
5
6
7
8
  • name(*) 是菜单的唯一标识,parent.name 引用上级菜单的 name,NULL 表示顶级菜单
  • form.name 引用表单的名称,菜单与表单的关联在这里建立
  • accessRequirement.name 取值为访问要求的名称,系统预置 USER、DEVELOPER、ADMIN

提示

displaySequence 更小的菜单或字段会先显示

# 表单定义的 CSV 文件

name(*),label,description,objectType.shortName(*),type.name(*),formHook.name,formHookTriggerFields,dataHook.name,extInfo,accessRequirement.name

List of customers,客户,,Customers,LIST,,,,,USER
List of VIP customers,VIP 客户,只显示 VIP 分组的客户,Customers,LIST,,,,"{""listForm"": {""searchConditions"": {""group"": {""columnKey"": ""group"", ""matchMode"": ""="", ""value"": ""VIP""}}}}",USER
Create customer,新建客户,,Customers,CREATE,customer_form_hook,group,,,USER
Update customer,编辑客户,,Customers,UPDATE,customer_form_hook,group,,,USER
Find customers,,,Customers,FINDER,,,,,USER
1
2
3
4
5
6
7
  • type.name 取值见 表单类型
  • List of VIP customers 在 extInfo 中设置了默认过滤条件,只列出分组为 VIP 的客户
  • 创建、编辑表单配置了 Form Hook(customer_form_hook,需要事先在动态逻辑中创建)和触发字段 group:客户分组变化时重新执行 Form Hook
  • accessRequirement.name 为 USER,表示所有登录用户都可以使用这些表单

# 表单字段组定义的 CSV 文件

displaySequence,name(*),label,icon,form.name(*),helpText
1,c_customers_basic,基本信息,UserOutlined,Create customer,客户的基本资料
2,c_customers_extra,补充信息,ProfileOutlined,Create customer,
1,u_customers_basic,基本信息,UserOutlined,Update customer,客户的基本资料
2,u_customers_extra,补充信息,ProfileOutlined,Update customer,
1
2
3
4
5

分别为创建表单和编辑表单定义了「基本信息」「补充信息」两个分组。

# 表单字段定义的 CSV 文件

form.name(*),fieldName(*),label,displaySequence,helpText,fieldType,nullable,group.name,extInfo,displayType,editable

; 列表
List of customers,name,客户名称,1,,STATIC_FIELD,,,,,
List of customers,companyName,公司,2,,STATIC_FIELD,,,,,
List of customers,group,客户分组,3,,STATIC_FIELD,,,,,
List of VIP customers,name,客户名称,1,,STATIC_FIELD,,,,,
List of VIP customers,companyName,公司,2,,STATIC_FIELD,,,,,

; 创建
Create customer,name,客户名称,1,,STATIC_FIELD,,c_customers_basic,,,
Create customer,contactInfo,联系方式,2,手机号或邮箱,STATIC_FIELD,,c_customers_basic,,,
Create customer,group,客户分组,3,,STATIC_FIELD,,c_customers_basic,,,
Create customer,companyName,公司,4,,STATIC_FIELD,Y,c_customers_extra,,,
Create customer,position,职位,5,,STATIC_FIELD,Y,c_customers_extra,,,
Create customer,birthday,生日,6,,STATIC_FIELD,Y,c_customers_extra,,,

; 编辑:客户名称只读
Update customer,name,客户名称,1,,STATIC_FIELD,,u_customers_basic,"{""meta"": {""updatable"": false}}",,
Update customer,contactInfo,联系方式,2,手机号或邮箱,STATIC_FIELD,,u_customers_basic,,,
Update customer,group,客户分组,3,,STATIC_FIELD,,u_customers_basic,,,
Update customer,companyName,公司,4,,STATIC_FIELD,Y,u_customers_extra,,,
Update customer,position,职位,5,,STATIC_FIELD,Y,u_customers_extra,,,
Update customer,birthday,生日,6,,STATIC_FIELD,Y,u_customers_extra,,,

; 查询
Find customers,name,客户名称,1,,STATIC_FIELD,,,,,
Find customers,group,客户分组,2,,STATIC_FIELD,,,,,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • form.name 与 fieldName 一起定位一条字段定义
  • nullable 为 Y 表示该字段在表单中可以不填
  • group.name 引用上一节定义的字段组,把字段归入对应分组
  • 编辑表单中的 name 字段通过 extInfo 的 meta.updatable 设为只读

# 头行结构表单定义

MASTER_DETAIL_LIST 类型的表单显示为左右结构,布局是固定的:

  • 左侧是关联对象的树,宽 500px。对象需要有 parent 字段来表示上下级,节点标题取对象的标签字段(labelField),同级节点按 displaySequence 排序;表单配置了 Data Hook 时,树的数据由 Data Hook 返回
  • 点击树节点后,右侧显示该对象的编辑(UPDATE)表单,带「保存」「删除」「创建」按钮;点击「创建」时右侧切换为创建(CREATE)表单

开发配置 > 界面显示 > 菜单 页面就是一个头行结构表单。

树节点图标

如果对象上有 icon 字段,其值为 antd 图标名称(如 SortAscendingOutlined),树节点前会显示该图标。

旧版本的 Simple list 左侧、detailFormType / detailField / detailUpdatable 配置 1.0 起已不再生效。

# 表单的 extInfo 支持

表单的 extInfo 是一段 JSON,用于定制表单的扩展属性。extInfo 中可以使用 动态匹配条件 中的时间类占位符,返回给前端前会被替换。

# 通用属性

{
    /** 表单标题。仅在表单的 label(显示名称)为空时使用;两者都为空时显示对象名称的翻译 */
    /** Form title. Used only when the form's label is empty; if both are empty, the translated domain name is shown */
    "domainTitle"?: string;
    /** 表单内字段是否横向排列(标签与输入框在同一行) */
    /** Whether fields are laid out horizontally (label and input on the same line) */
    "horizontal"?: boolean;
}
1
2
3
4
5
6
7

# LIST 表单属性

{
    /** 数据刷新模式。当前只有 realtime 生效:列表会订阅数据变化并实时刷新;其他取值等同不设置 */
    /** Data refresh mode. Only realtime takes effect: the list subscribes to data changes and refreshes in real time; other values are the same as not setting it */
    "dataRefreshMode"?: "realtime";

    /** 点击列表右上角「创建」按钮时使用的创建表单名称,不设置时使用该对象的 CREATE 表单 */
    /** Name of the create form used by the "Create" button of the list; defaults to the CREATE form of the domain */
    "createFormName"?: string;

    /** 点击行内「修改」时使用的编辑表单名称,不设置时使用该对象的 UPDATE 表单 */
    /** Name of the update form used by the row "Edit" link; defaults to the UPDATE form of the domain */
    "updateFormName"?: string;

    /** 列表上方搜索区使用的查询表单名称,不设置时使用该对象的 FINDER 表单 */
    /** Name of the finder form used by the search panel; defaults to the FINDER form of the domain */
    "finderFormName"?: string;

    "listForm"?: {
      /** 是否隐藏列表上方的搜索区 */
      /** Whether to hide the search panel above the list */
      "disableSearchPanel"?: boolean;
      /** 默认过滤条件,格式与动态过滤的 conditions 相同;用户在搜索区输入同名条件时会覆盖这里的条件 */
      /** Default filter conditions, same format as dynamic filter conditions; a search condition with the same key entered by the user overrides it */
      "searchConditions"?: {
        "fieldName": {
          "columnKey": "fieldName",
          "matchMode": "=",
          "value": xxx
        }
      };
    };

    /** 行内编辑时是否按表单字段的 decides 刷新其他列(decides 当前版本不生效) */
    /** Whether inline editing refreshes the columns listed in the field's decides (decides does not work in the current version) */
    "enableRefreshColumn"?: boolean;

    /** 操作列宽度,默认 120 */
    /** Width of the operations column, default 120 */
    "operationsColumnWidth"?: number;

    /** 覆盖列表的按钮权限,只影响按钮是否显示,后端仍按对象权限校验;create 为 false 时隐藏「创建」按钮 */
    /** Overrides list button permissions; only affects button visibility, the backend still checks domain permissions; create=false hides the "Create" button */
    "permissions"?: {
      "create"?: boolean;
      "view"?: boolean;
      "update"?: boolean;
      "delete"?: boolean;
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 默认过滤条件

列表表单可以通过 extInfo 中的 listForm.searchConditions 设置默认过滤条件,用户在界面上看不到这些条件。条件的格式与 动态过滤 的 conditions 相同:

// 列表表单的默认过滤条件写在 extInfo.listForm.searchConditions 中
// Default filter conditions of a list form go into extInfo.listForm.searchConditions
{
  "listForm": {
    "searchConditions" : {
      // key 是列名称: status
      // key is the column name: status
      "status": {
        // 过滤的目标列
        // The target column for filtering
        "columnKey": "status",
        // 匹配规则:等于
        // Matching rule: equals
        "matchMode": "=",
        // 匹配的目标值: SUCCESS
        // The target value to match: SUCCESS
        "value": "SUCCESS"
      },
      // key 是列名称: type
      // key is the column name: type
      "type": {
        // 过滤的目标列, 与上一行的 key 相同
        // The target column for filtering, same as the key in the previous line
        "columnKey": "type",
        // 过滤的匹配规则:isOneOf (是其中某一个)
        // Filtering matching rule: isOneOf (is one of them)
        "matchMode": "isOneOf",
        // 过滤的目标值: [FINDER, UPDATE]
        // The target values for filtering: [FINDER, UPDATE]
        "value": [
          "FINDER",
          "UPDATE"
        ]
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

注意

  • 默认过滤条件只在前端请求列表数据时附加,如果用户在搜索区输入了同一字段的条件,会覆盖这里的条件。TREE_LIST 右侧的列表、作为子表内嵌显示的列表不读取这个配置。它不是权限控制手段,需要限制数据访问时请使用对象权限或 Data Hook
  • 旧版本写在 extInfo 顶层的 conditions 1.0 起已不再生效,需要改写到 listForm.searchConditions 中

# TREE_LIST 表单属性

TREE_LIST 表单左侧显示一棵树,右侧显示列表,点击树节点后按该节点过滤列表。必须配置 treeTable.domainFilterField,否则页面只显示 domainFilterField is not defined:

{
  "treeTable": {
    // 列表对象上指向树形对象的字段名,该字段必须是这个表单的字段;
    // 树形对象的类型由该字段的关联类型决定
    "domainFilterField": "category",
    // 可选:树形对象上的字段名,会作为查询条件显示在树的上方,
    // 全部填写后才按这些字段(等于匹配)加载树
    "treeFilterFields": ["catalog"]
  }
}
1
2
3
4
5
6
7
8
9
10

# IFRAME 表单属性

{
  // 内嵌页面的地址
  "url": "https://example.com/report"
}
1
2
3
4

# MASTER_DETAIL_LIST 表单属性

{
  /** MASTER_DETAIL_LIST 表单当前没有可配置的 extInfo 属性。 */
  /** MASTER_DETAIL_LIST forms currently have no configurable extInfo properties. */
  /** 左侧固定为对象的树,右侧固定为该对象的 UPDATE / CREATE 表单。 */
  /** The left side is always the object tree, the right side is always the UPDATE / CREATE form of the object. */
  /** 旧版本的 detailFormType、detailField、detailUpdatable 已不再生效。 */
  /** The legacy detailFormType, detailField and detailUpdatable are no longer used. */
}
1
2
3
4
5
6
7

# DASHBOARD 表单属性

{
  /** DASHBOARD 表单当前没有可配置的 extInfo 属性,旧版本的 refreshInterval 已不再生效。 */
  /** DASHBOARD forms currently have no configurable extInfo properties; the legacy refreshInterval is no longer used. */
}
1
2
3

# 表单字段的 extInfo 支持

表单字段的 extInfo 同样是一段 JSON,用于定制字段的扩展属性。

# 通用属性

所有类型的字段,其 extInfo 中均可使用的扩展属性如下

{
  // 隐藏字段的标签,只显示控件本身
  // Hides the field label and shows only the control
  "hideLabel"?: boolean;

  // 字段标签与只读值的 CSS 样式,例如 {"color": "#cf1322"}
  // CSS styles of the field label and of the read-only value, e.g. {"color": "#cf1322"}
  "labelStyle"?: object;
  "valueStyle"?: object;

  // meta 用于覆盖系统自动生成的表单字段的元数据,或者补充某一些属性,如 title, dataIndex, editable, updatable, elementType 等
  // meta is used to override the metadata of automatically generated form fields or to supplement certain properties such as title, dataIndex, editable, updatable, elementType, etc.
  // 在运行时,系统会将 meta 中的属性覆盖或者补充到系统自动生成的表单字段的元数据中
  // At runtime, the system will override or supplement the metadata of automatically generated form fields with the properties in meta
  "meta"?: {
      // 字段名
      // Field name
      "key": string;
      // 字段显示名
      // Field display name
      "title": string;
      // 字段在表单中的名字,应该和 key 一致
      // The name of the field in the form, should be the same as key
      "dataIndex": string;
      // 在创建表单中是否可编辑,false 时显示为只读
      // Whether the field is editable in create forms; false renders it read-only
      "editable"?: boolean;
      // 在编辑表单中是否可编辑,false 时显示为只读
      // Whether the field is editable in update forms; false renders it read-only
      "updatable"?: boolean;
      ...
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 数字字段

integer、int、long、decimal 控件支持以下属性(suffix 只对这几种生效,percentage 固定显示 %,currency 不读取 suffix):

{
  // 最小值、最大值,超出时提示错误
  "min": 0,
  "max": 100,
  // 输入框后显示的单位
  "suffix": "元"
}
1
2
3
4
5
6
7

# file 字段

{
  /** file、fileList、image、video 控件当前不读取 extInfo。 */
  /** The file, fileList, image and video controls currently do not read extInfo. */
  /** 旧版本的 accept、maxSizeMB、maxCount、totalMaxSizeMB 已不再生效。 */
  /** The legacy accept, maxSizeMB, maxCount and totalMaxSizeMB are no longer used. */
}
1
2
3
4
5

# code 字段

displayType 为 code、json、markdown 等代码类控件时,可以通过如下的 extInfo 设定高亮语法

{
  /** 代码编辑器控件显示时的高亮语法 */
  /** Syntax highlighting when displaying the code editor control */
  /** 不设置时使用字段的显示类型(code、json、markdown 等) */
  /** Defaults to the field's display type (code, json, markdown, ...) */
  "codeLanguage"?: "css" | "javascript" | "markdown" | "groovy" .....,
}
1
2
3
4
5
6

# object 字段

对于对象选择控件(object、objects),可以使用如下的 extInfo:

{
    /** 候选项的过滤条件
     * 控件加载时用该条件查询前 20 条作为默认选项;输入关键字搜索时也会带上该条件
     */
    /** Filter conditions of the candidate options
     * Used to query the first 20 records as default options when the control loads, and also applied to keyword search
     */
    "defaultOptionsCondition"?: {
        "fieldName" : {
            /** 匹配的值 */
            /** Matching value */
            "value": xxxx,
            /** 匹配的字段名称, 支持 dot(.) 方式引用关联字段的某字段
             * 如 organization.name 引用 organization 字段的 name
             */
            /** Matching field name, supports referencing associated fields using dot (.) notation
             * For example, organization.name refers to the name field of the organization
             */
            "columnKey": "xxx",
            /** 匹配规则 */
            /** Matching rule */
            "matchMode": matchMode
        }
    },
    /** 输入关键字搜索时最多返回的候选项数量,默认 20 */
    /** Maximum number of candidates returned by keyword search, default 20 */
    "objectOptionsLimit"?: number,
    /** 在下拉框底部显示「创建」「编辑」按钮,用于直接新建被关联的对象。当前版本只有单选控件的「创建」可用 */
    /** Shows "Create" and "Edit" buttons at the bottom of the dropdown. Currently only "Create" of single-object controls works */
    "enableObjectOperations"?: boolean,
    /** 通过上述「创建」按钮打开的创建表单中,各字段的默认值查询条件;key 为被关联对象的对象类型字段名,取查询到的第一条 */
    /** Default value conditions for the create form opened by the "Create" button; each key is an object field of the target domain, the first match is used */
    "createFormDefaultValueConditions"?: {
        "fieldName": { "columnKey": "xxx", "matchMode": "=", "value": xxx }
    },
    /** 覆盖上述创建表单中字段的属性,例如 {"owner": {"disabled": true}} */
    /** Overrides field properties in that create form, e.g. {"owner": {"disabled": true}} */
    "overwriteCreateFormFieldProps"?: object
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 一对多的对象字段

displayType 为 array 时(一对多的对象字段),可以使用如下的 extInfo 定义关联列表的显示

{
  /** 显示关联对象列表时使用的表单名称,不设置时使用关联对象的 LIST 表单 */
  /** Name of the form used to display the associated objects; defaults to the LIST form of the associated domain */
  "displayForm"?: "Form used to display the list of objects"
}
1
2
3
4

# 子表字段

displayType 为 subTable 或 relativeSubTable 时的配置,详见 高级字段控件

// 1. 子表字段(表单字段)的 extInfo
// 1. extInfo of the sub-table form field
{
  /** 子表使用的表单名称(决定子表显示哪些列),不设置时使用子对象的 LIST 表单 */
  /** Name of the form rendering the sub-table (decides the columns); defaults to the LIST form of the child domain */
  "displayForm"?: "UserGroup Sub Table Form For User",
  /** 仅 relativeSubTable 使用:从当前对象出发的一对多字段路径,用点号分隔 */
  /** Only for relativeSubTable: path of a one-to-many field starting from the current object, separated by dots */
  "subTable"?: {
    "relativeNamePath"?: "customer.contacts"
  }
}

// 2. displayForm 指向的那个表单的 extInfo(行操作权限等写在这里,不是写在字段上)
// 2. extInfo of the form referenced by displayForm (row permissions etc. go here, not on the field)
{
  "subTable"?: {
    /** 是否可修改、新增、删除行;设置后覆盖默认值(默认可修改;带 mappedBy 的一对多子表要求主对象已保存才可删除,且当前不显示「创建」按钮) */
    /** Whether rows can be updated, created, deleted; overrides the defaults (updatable by default; for one-to-many with mappedBy, delete requires the owner to be saved and the "Create" button is currently not shown) */
    "updatable"?: true | false,
    "creatable"?: true | false,
    "deletable"?: true | false,
    /** 是否可拖拽排序 */
    /** Whether rows can be reordered by drag and drop */
    "dragSort"?: true | false,
    /** 为 true 时「创建」按钮放在表格底部(默认在顶部);可拖拽排序的子表中新增行也追加到末尾 */
    /** When true the "Create" button is placed at the bottom (top by default); in drag-sortable sub-tables new rows are appended */
    "asc"?: true | false,
    /** 在操作列中提供行级对象动作,只读状态下也显示操作列 */
    /** Offers row-level object actions in the operations column, which is shown even when read-only */
    "enableActions"?: true | false
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Last Updated: 2026/9/24 14:27:35