# 基础表单定制

# 目标读者

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

# 概述

本系统的相关菜单、表单、字段分组、字段、向导、预定义过滤等均可进行客制化,具体客制化方法如下章节所述

# 菜单

# 定义

本系统的所有界面显示菜单均通过保存在系统数据库中的 Dynamic Menu 对象进行渲染,在界面上,可 通过菜单 Development > Menus 进行菜单的自定义。

对于菜单定义,需要创建如下的 Dynamic Menus 对象

Parent Menu: 菜单的父菜单,如果为空表示创建的是顶级菜单
Icon: 菜单的图标,详细请见下述
Label: 菜单的显示文字
Type: 菜单的类型,详细请见下述
Organization: 菜单的所属组织
Link: 对于外部和内部链接,菜单的链接地址
Form: 菜单关联的 Form 定义
Display Sequence: 菜单的显示顺序,越小显示越靠前
1
2
3
4
5
6
7
8

# 类型

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

  • External Link 外部链接: 系统会在新的窗口中打开该菜单 link 属性对应的网址
  • Internal Link 内部链接:系统会在当前窗口中打开该菜单 link 属性对应的网址, 该网址可以为相对路径
  • Menu Group 包含子菜单的菜单组,可通过定义菜单组实现多级菜单
  • Form 与某个显示对象的 Form(表单) 关联的菜单,关于表单的自定义可参考 表单定 义 章节

# 图标

菜单的图标使用 antd 的默认图标,只要填写图标的名称即可,无需包括 <> 部分,图标 列表请查看 Ant Design 图标 (opens new window)

# 多组织支持

系统支持不同组织定义不同的菜单字段的定义,只需要在创建菜单时,指定该菜单的所属组 织即可。

提示

如果某菜单的组织字段为空,则该菜单会适用于所有组织,但如果该菜单的父级菜单存在其 他组织不为空,且适用于当前用户的子菜单定义,则该组织字段为空的菜单不会显示。

举例如下:如菜单 subMenu1 与 subMenu2 均是 parentMenu1 的子菜单,subMenu1 的组织 为空, subMenu2 的组织为当前登陆用户的组织,则该用户仅会看到 subMenu2 菜单。

# 表单

# 定义

自定义表单保存在系统的 Dynamic Form 对象中,在界面上,可通过菜单 Development > Forms 进行表单的自定义。

对于表单定义,需要创建如下的 Dynamic form 对象,其核心字段如下所列

Name: 该菜单的名称
Description: 说明
Object Type: 所关联的 Domain 对象类型
Type: 菜单类型,具体详见后述
1
2
3
4

表单的其他更多属性字段请参见界面

对象的列表显示页面、编辑页面、创建页面及详细查询页面的显示字段信息均可通过自定义 表单进行客制化,系统支持的表单类型如下:

  • Table list 对象的列表页面
  • Create 对象的创建页面表单
  • Update 对象的编辑页面表单
  • Finder 对象的详细搜索页面
  • Wizard 多步骤表单数据收集器
  • Dashboard 仪表盘
  • Master detail list 左右结构的子母表单,其左边和右边的子表单需要使用 extInfo 进行配置
  • Inline full text search list 内联全文检索结果显示表单
  • Full text search list 全文检索结果显示表单
  • Inline display 内联详情显示表单
  • Related detail list 关联详情显示列表表单
  • Inline editable display 内联可编辑显示表单
  • Card list 卡片显示表单
  • Gantt 甘特图表单
  • Gantt tooltip 甘特图详情显示卡片表单
  • Sub table list 子表表单

每种表单均有其使用场景,关于甘特图表单的详细描述请参考 甘特图 章节 关于仪表盘的详细描述请参考 仪表盘 章节

# 树状视图节点图标

对于 Master Detail 布局的左边树状视图,系统支持在树节点上显示图标,只需要在后台 返回对象数据时,包含 icon 字段,该字段的值是一个 antd 的图标名称即可,如:

{
  "id": 1,
  "name": "root",
  "parent": null,
  "children": [],
  "icon": "SortAscendingOutlined"
}
1
2
3
4
5
6
7

这样前端渲染树节点时,就会显示 SortAscendingOutlined 对应的 antd 图标。

# 与菜单的关联

如果希望用户点击某菜单时,系统直接渲染某表单,则需要在菜单定义中编辑菜单的 Form 字段。

# 表单字段分组

表单字段在对象的创建和编辑界面上,可以可折叠的字段分组进行展示,且系统支持在字段 组的级别,使用动态逻辑自定义该字段组是否显示。关于动态逻辑的详情可参考 动态逻辑 章节。

# 定义

自定义表单字段分组保存在系统的 Dynamic Form Group 对象中,在界面上,可通过菜单 Development > Form field groups 来进行表单字段分组的客制化。

对于表单字段分组,需要创建如下的 Dynamic form field group 对象

Name: 字段组的名称标示,创建后无法修改
Label: 字段组在前台的显示标签
Display Sequence: 字段组的显示顺序,越小其在表单中显示越靠前
Help Text: 在前台显示的该字段组的帮助信息
Icon: 在前台显示的,该字段组的图标
Enable Roles: 该表单组的启用角色,只有该角色的用户才能看到该字段组
Enable Logic: 该表单组的显示动态逻辑,在满足 Enable Roles 的前提下,会运行该段动态逻辑来最终决定是否显示该字段组
Form: 该字段组关联的表单
1
2
3
4
5
6
7
8

关于显示图标的说明请参考 图标说明 章节

# 动态显示逻辑定义

字段组的显示逻辑在系统中,以 FORM_GROUP_ENABLE_LOGIC 类型的 DynamicLogic 进行 定义。

# 注入变量

代码运行时,系统会注入如下的上下文变量

变量名称 变量类型 描述
application grails.core.GrailsApplication grails 应用上下文
userContext grails.plugin.springsecurity.userdetails.GrailsUser 当前操作的用户信息
objectType tech.muyan.DomainClass 表单关联的 Domain 对象信息
formType tech.muyan.enums.FormType 表单类型,CREATE 或 UPDATE
objectId java.lang.Long 运行的目标 domain 对象 id
object <? extends DefaultGrailsDomainClass> 运行的目标 domain 对象
group tech.muyan.dynamic.form.DynamicFormGroup 当前待判断的字段组对象

注意

针对创建字段组显示逻辑的判断逻辑中,注入的 objectId 和 object 对象为 null, 如果 在创建和编辑的字段组定义中,复用判断逻辑,请在代码中考虑这两个注入变量为空或者不为空两种情况。

# 返回结果

Enable Logic 运行后的返回结果的结构如下,如果返回 Map 中,key 为 result 的元素的

  • 值为 "editable", 则表现显示该字段组,且为可编辑模式;
  • 值为 "readonly" 则表示显示该字段组,但为只读模式;
  • 值为 "hide" 则表示隐藏该字段组;
// 表示该字段组在界面上的显示模式,可编辑, 隐藏或者只读
return [result: editable | readonly | hide]
1

# 命名规范

为避免在系统中不同表单的字段组名称冲突,各表单字段组的命名需满足如下规范:

<表单类型>_<Domain 类名称>_<字段组内部名称>

其中:

  • 表单类型:对于创建表单为 c,对于编辑表单为 u
  • Domain 类名称:使用该表单关联的 Domain 类的名称,默认不包含 package,如果不包 含 package 的类名称有冲突,则使用包含 package 的全名称。
  • 字段组内部名称:简短的字段组描述,全部使用小写,不包含空格,不同部分之间使用下 划线分隔。

如创建用户的表单的 basic 组需命名为 c_user_basic

# 表单字段

# 定义

自定义表单字段保存在系统的 Dynamic Form Field 对象中,在界面上,可通过菜单 Development > Form fields 来进行表单字段的客制化。

对于表单字段定义,需要创建如下的 Dynamic form field 对象

Organization: 所属对象,当前未使用
Form: 字段所属的 Form 定义
Field Name: 字段名称,需要与 Domain 中定义的字段名称完全匹配
Display Sequence: 字段的显示顺序,越小其在表单中显示越靠前
Label: 字段的显示名称
Help Text: 在页面显示的该字段的帮助信息
Field Type: 字段类型,是 Domain 中定义的静态字段还是界面创建的动态字段
Nullable: 表单中该字段是否可以为空
Transient Expression:当字段类型为瞬态字段时必填,用于计算瞬态字段的值
Display Type:字段显示类型,用于控制字段在表单中的显示组件。和 ClientSideType 类似,不同的是 ClientSideType 是与某个 domain 对象绑定,而 Display Type 是与某个 Form 绑定。从设计的角度看以后优先使用 Display Type,而不是 ClientSideType。
1
2
3
4
5
6
7
8
9
10

针对不同的表单类型,系统支持的字段可自定义的属性如下:

  • 对象列表页面

  • 对象详细搜索页面

    • 具体显示字段列表
    • 字段的显示顺序
  • 对象创建页面表单

    • 具体显示字段列表
    • 字段的显示顺序
    • 字段是否必填
    • 字段的填写帮助
  • 对象编辑页面表单

    • 具体显示字段列表
    • 字段的显示顺序
    • 字段是否必填
    • 字段的填写帮助

# 瞬态字段

瞬态字段是指在表单中不需要在数据库中保存的字段。在系统中,瞬态字段的定义与普通字段基本一致,只是在定义时,需要将字段的 Field Type 设置为 Transient Field,同时声明该字段的计算表达式以及显示组件类型。

其计算表达式需为合法的 Groovy 代码,可以使用 object 引用到当前渲染的对象,如 object.parent.label 表示当前渲染对象的 parent 属性的 label 属性

# 与表单的关联

如果希望用户点击某菜单时,系统直接渲染某表单,则需要将该表单的 menu 属性设置为该 菜单。

# 推荐做法

推荐在开发过程中,将各菜单、表单及表单字段的定义保存在 CSV 文件中,作为种子数据 (Seed Data) 保存在系统中,这样系统启动时,会自动读取各定义并进行更新。关于种子数 据的导入相关信息请参考文档 数据导入

# 真实系统中的使用示例

如下列出了一个真实系统中,包括了菜单、表单和表单字段客制化的 CSV 数据范例:

# 菜单定义的 csv 文件

 


 


 

parentMenu.label(*),label(*),icon,organization.name(*),link,type,displaySequence

;; Master data parent menu
NULL,Master data,DatabaseOutlined,NULL,,MENU_GROUP,3

;; User
Master data,User,UserOutlined,NULL,,FORM,1
1
2
3
4
5
6
7

上述 csv 文件定义了两个菜单,具体信息如下所述:

  • 第1行,定义了导入数据各列定义,系统会根据如下几个字段来查找当前系统 中的记录并进行更新
    • parentMenu.label: 父菜单的 label
    • label: 当前待导入菜单的 label
    • organization.name: 菜单关联的组织名称
  • 第4行,定义了一个菜单,其
    • parentMenu 为空,该菜单会显示为顶层菜单,
    • 其 Organization 为 null, 表示该菜单适用于所有组织
    • 其 Label 为 Master Data, 该 Label 即该菜单的显示文字
    • 其类型为 MENU_GROUP, 即包含子菜单的菜单组,
    • 显示图标为 DatabaseOutlined
    • 该菜单的显示顺序通过 displaySequence 定义,为 3
  • 第 7 行定义了一个菜单,其
    • parentMenu 为第 4 行定义的 Master data
    • 其 Label 为 User
    • 其 Organization 为 null, 表示该菜单适用于所有组织
    • 其类型为 Form, 与某个 Form 关联,具体的关联关系在 Form 中进行定义
    • 显示图标为 UserOutlined
    • 该菜单的显示顺序使用 displaySequence 定义,为 1

提示

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

# 表单定义的 csv 文件

 

 
 
 
 

name(*),description,objectType.shortName(*),organization.name(*),type(*),menu.label,importEnable,exportEnable,extInfo
; User, groups, roles etc
List of users,,User,NULL,LIST,User,Y,Y,
Create user,,User,NULL,CREATE,NULL,Y,Y,
Update user,,User,NULL,UPDATE,NULL,Y,Y,
Find user,,User,NULL,FINDER,NULL,Y,Y,
1
2
3
4
5
6

上述 CSV 文件定义了 4 个表单,分别是:

  • List of users: User 对象的列表页面表单
  • Create user: 创建 User 对象的页面表单
  • Update user: 更新 User 对象的页面表单
  • Find user: User 对象的详细搜索页面的字段定义

更多细节如下所述:

  • 第1行:待导入数据各列定义,系统会根据如下几个字段来查 找当前系统中的记录并进行更新
    • name: 表单名称
    • objectType.shortName: 表单关联的对象类型
    • organization.name: 表单关联的组织名称
    • type: 表单的类型
  • 3-6行:分别定义了用户的列表、创建、更新及查找页面的表单,详述如下:
    • 所有表单的 organization.name 字段为 NULL 表示这些表单定义适用于所有组织

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

 
 
 
 

displaySequence,name(*),label,icon,enableRoles,enableLogic.name,form.name,helpText
1,c_user_basic,Basic Information,UserAddOutlined,"ROLE_ADMIN,ROLE_DEVELOPER",,Create user,Basic information
1,u_user_basic,Basic Information,UserOutlined,"ROLE_USER,ROLE_ADMIN,ROLE_DEVELOPER",,Update user,Basic information
2,u_user_advanced,Advanced Information,UserOutlined,"ROLE_ADMIN,ROLE_DEVELOPER",u_user_advanced_group_display_logic,Update user,Advanced information
1
2
3
4

更多细节如下所述:

  • 第 1 行:待导入数据各列定义,系统会根据如下字段来查找当前系统中的记录并进行更新
    • name: 表单字段组的名称
  • 第 2 行:定义了创建用户的表单中的 c_user_basic 这个字段组
  • 第 3-4 行:定义了编辑用户的表单中的 u_user_advanced 和 u_user_basic 两个字段组,
    • u_user_basic 显示给具有 ROLE_ADMIN, ROLE_DEVELOPER 和 ROLE_USER 角色的用户。
    • u_user_advanced 只显示给具有 ROLE_ADMIN 和 ROLE_DEVELOPER 角色的用户。
    • 字段组 u_user_advanced 组与名为 u_user_advanced_group_display_logic 的动态逻 辑关联,会进一步使用该动态逻辑来判断是否需要显示该字段组。

# 表单字段定义的 csv 文件

 


 
 









 





 

 







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

; User
;; List form
NULL,List of users,username,1,Username,,STATIC_FIELD,,,,
NULL,List of users,organization,2,Organization,,STATIC_FIELD,,,,
NULL,List of users,enabled,3,Active,,STATIC_FIELD,,,,
NULL,List of users,accountLocked,4,Locked,,STATIC_FIELD,,,,
NULL,List of users,accountExpired,5,Expired,,STATIC_FIELD,,,,
NULL,List of users,passwordExpired,6,Password expired,,STATIC_FIELD,,,,
NULL,List of users,groups,7,Groups,,STATIC_FIELD,,,,

;; Create form
NULL,Create user,username,1,Username,,STATIC_FIELD,,c_user_basic,
NULL,Create user,password,2,Password,,STATIC_FIELD,,c_user_basic,
NULL,Create user,organization,3,Organization,,STATIC_FIELD,,c_user_basic,

;; Update form
NULL,Update user,username,1,Username,,STATIC_FIELD,,u_user_basic,
NULL,Update user,password,2,Password,,STATIC_FIELD,Y,u_user_basic,
NULL,Update user,organization,3,Organization,,STATIC_FIELD,,u_user_basic,
NULL,Update user,passwordExpired,4,Password expired,Set password of user to expired,STATIC_FIELD,,u_user_advanced,
NULL,Update user,accountLocked,5,Locked,Lock this account from login,STATIC_FIELD,,u_user_advanced,
NULL,Update user,accountExpired,6,Expired,Set this account to expiry ,STATIC_FIELD,,u_user_advanced,
NULL,Update user,groups,7,Groups,,STATIC_FIELD,,u_user_advanced,

;; Finder form 
NULL,Find user,username,1,Username,,STATIC_FIELD,,,,
NULL,Find user,organization,2,Organization,,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
29

上述 csv 文件定义了如下的字段定义:

  • 针对 List of users 表单,定义如下字段: username, organization, enabled, accountLocked, accountExpired, passwordExpired, groups
  • 针对 Create user 表单,定义如下字段:username, password, organization
  • 针对 Update user 表单,定义如下字段:username, password, organization, passwordExpired, accountLocked, accountExpired, groups
  • 针对 Finder user 表单,定义如下字段: username, organization

更多细节如下所述:

  • 第 1 行:待导入数据各列定义,系统会根据如下几个字段来查找当前系统中的记录并进行更新
    • organization.name: 组织名称
    • form.name: 字段关联的表单的名称
    • fieldName: 字段名称
  • 第 5 行:定义 username 字段,displaySequence 为 1, 字段类型为 STATIC_FIELD, 关 联的表单的名称为 List of users
  • 第 23 行: 定义 password 字段在 update form 中,nullable 为 true, 即在更新用户 时,密码可以留空
  • 分别针对创建和更新用户的表单字段,设置了对应的字段组信息,通过字段组名称在列 group.name 中进行指定。

# 头行结构表单定义

系统支持使用 MASTER_DETAIL_LIST 类型的 dynamic form 实现子母表单,该类型的表单界面显示 为左右结构,左边为 master 表单,右边为 detail 表单。

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

  • Simple list: 简单列表
  • Tree list: 树状列表

注意

Master 表单为 simple list 的情况,当前只在 Inbox 页面使用,还没有完成对其的客制化使用支持。

提示

当前系统遵循如下的约定: 如果 MASTER_DETAIL_LIST 类型的 form 的元数据中,包含名为 children 的 字段, 则会默认将其左边的 master 部分显示为树型控件。

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

  • Inline display: 内嵌显示表单
  • Update: 编辑表单
  • Full text search list: 全文检索搜索及结果显示表单

头行结构表单使用如下的 extInfo 进行定制,相关的定制属性包括

  • detailFormType
  • detailField
  • detailUpdatable

List 类型的表单还支持使用 domainTitle 来定制在列表的表头中 显示的 domain 的标题。

{
    /** form 默认的隐含过滤条件, 该过滤条件不会在界面上显示, 用户不可见 */
    "conditions": {
        "fieldName": {
            /** 匹配的值 */
            "value": xxxx,
            /** 匹配的字段名称, 支持 dot(.) 方式引用关联字段的某字段 */
            /** 如 organization.name 引用 organization 字段的 name */
            "columnKey": "xxx",
            /** 匹配规则 */
            "matchMode": matchMode
        }
    },
    /** 列表类型表单的表头中显示的 domain 标题,如果不想显示 domainTitle, 将其设置为空字符串即可 */
    "domainTitle"?: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 动态过滤

# 动态过滤定义

动态过滤(Dynamic Filter)是显示在列表页面中,用于用户快速的对列表附加过滤条件的客制化。

其显示效果如下图:

Dynamic Filter 显示效果

通过菜单 Development > Menu and Form > Filter 维护动态过滤的定义,其创建和编辑表单如下:

Dynamic Filter 创建及编辑

相关字段说明如下:

字段 描述
Organization 所属组织,只能是允许客制化的组织
Name 名称,在组织内唯一,创建后不允许修改
Label 界面显示名称
Icon 界面显示时,名称前显示的小图标
Display sequence 界面显示的顺序,越小越靠前
Description 界面上鼠标放到名称上时候显示的帮助信息
Applies to 关联的 Domain 类型
Enable for roles 限制哪些用户可以看到该动态 filter, 如果希望所有用户均可用,设置为 ROLE_USER
Is default 是否为默认 filter, 默认 filter 是用户进入列表页面,系统自动应用的 filter
Conditions 过滤的条件定义

Condition 的定义使用一段 JSON 格式来描述匹配规则,采用如下的格式:

// 下面的动态过滤条件的说明:
// 1. 状态字段等于 SUCCESS
// 2. type 是 FINDER, UPDATE 中的一个
{
  "status": {  // key 是列名称: status
    "columnKey": "status", // 过滤的目标列
    "matchMode": "=",      // 匹配规则:等于
    "value": "SUCCESS",    // 匹配的目标值: SUCCESS
  },
  "type": { // key 是列名称: type
    "columnKey": "type",           // 过滤的目标列, 与上一行的 key 相同
    "matchMode": "isOneOf",        // 过滤的匹配规则:isOneOf (是其中某一个)
    "value": ["FINDER", "UPDATE"]  // 过滤的目标值: [FINDER, UPDATE]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

对匹配的相关模式,规则等的详细描述如下。

# 可用匹配模式

如下列出了可用的匹配模式

匹配模式 说明 适用数据类型
= 等于 除一对多,多对多关联的所有类型
!= 不等于 除一对多,多对多关联的所有类型
> 大于 数字
< 小于 数字
>= 大于等于 数字
<= 小于等于 数字
after 日期, 在 ... 之后 日期
before 日期, 在 ... 之前 日期
afterOrEqual 日期,等于 ... 或在 ... 之后 日期
beforeOrEqual 日期,等于 ... 或在 ... 之前 日期
isOneOf 是其中的某一个 除一对多,多对多关联的所有类型
isNotAnyOf 不是列表中的任一个 除一对多,多对多关联的所有类型
endsWith 以 ... 结尾 字符
startsWith 以 ... 开头 字符
contains 包含 ... 字符
notContains 不包含 ... 字符
hasNoRelated 该字段不包含关联数据 一对多关联
hasRelated 该字段包含关联数据 一对多关联
isNotEmpty 不为空 除一对多,多对多关联的所有类型
isEmpty 为空 除一对多,多对多关联的所有类型

# 不同字段类型匹配

# 关联关系的匹配

  • 一对多关联关系支持 hasRelated 和 hasNoRelated 的匹配,分别表示关联多端是否有关联对象。
  • 一对一关联关系支持 =, !=, isOneOf, isNotAnyOf, isNotEmpty, isEmpty 类型的匹配。

# Enum 字段的匹配

Enum 字段的匹配值使用 Enum 定义的 name 进行匹配, 比如如下的 Enum 定义,使用 ONLY_LABEL_FIELD, EXCLUDE_ARRAY_COLUMNS, ALL_COLUMNS 这三个值进行匹配

enum FetchType {
  ONLY_LABEL_FIELD("Fetch label field"),
  EXCLUDE_ARRAY_COLUMNS("Fetch columns not of type array"),
  ALL_COLUMNS("Fetch all columns");
}
1
2
3
4
5

# 其他类型字段的匹配

  • boolean 字段的匹配值直接使用不带引号的 true 和 false
  • 数字类型的匹配值直接使用不带引号的数字
  • 如果匹配的值要求是数组,则使用 [] 将匹配值包含其中
  • 日期时间的匹配请使用如下格式: yyyy-MM-dd HH:mm:ss (2021-08-23 07:57:49)
  • 不带时间的日期匹配请使用如下格式: yyyy-MM-dd

提示

Dynamic Filter 的 conditions 字段格式与页面往后台发送的搜索请求中的搜索条件的格 式一致。

开发时,可以先使用界面上的搜索功能,设定正确的搜索条件,然后监控页面往后台发送的 POST 搜索请求中的请求数据 body,使用该请求数据作为预定义的 Dynamic Filter 的 conditions 字段值。

# 动态匹配条件

在 Dynamic Filter 的匹配条件中,可以使用如下的动态匹配条件

占位符 匹配条件说明
${currentUsername} 当前登陆用户的用户名
${currentOrganization} 当前登陆用户的所属组织名称
${currentHour} 当前小时零分的时间
${currentDay} 当前日期零点的时间
${currentWeek} 当前星期的星期一的零点
${currentMonth} 当前月的第一天零点
${currentQuarter} 当前季度第一天的零点
${currentYear} 当前年的一月一日零点
${currentUserGroups} 当前用户所属的所有用户组名称列表

提示

当前用户所属用户组是一个列表,在格式化为过滤条件的时候,会被格式化为 ['groups', 'group2'] 的格式, 因此需要将其作为一个列表进行条件匹配。 如下是一个使用 isOneOf 规则进行匹配的例子:

"{
  "conditions": {
    "directFavoriteGroups.name": {
      "value": "${currentUserGroups}",
      "columnKey": "directFavoriteGroups.name",
      "matchMode": "isOneOf"
    }
  }
}"
1
2
3
4
5
6
7
8
9

# 表单的 extInfo 支持

系统支持在 extInfo 字段中,使用 json 定制表单的扩展属性,详述如下

# 通用属性

{
    /** form 默认的隐含过滤条件, 该过滤条件不会在界面上显示, 用户不可见 */
    "conditions": {
        "fieldName": {
            /** 匹配的值 */
            "value": xxxx,
            /** 匹配的字段名称, 支持 dot(.) 方式引用关联字段的某字段 */
            /** 如 organization.name 引用 organization 字段的 name */
            "columnKey": "xxx",
            /** 匹配规则 */
            "matchMode": matchMode
        }
    },
    /** 列表类型表单的表头中显示的 domain 标题,如果不想显示 domainTitle, 将其设置为空字符串即可 */
    "domainTitle"?: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# List form 属性

{
    /** 是否支持 realtime 实时刷新数据模式,当前为 beta 功能,只支持在列表页面启用 */
    /** 默认的显示模式,realtime: 默认实时模式,manual: 手动刷新模式,不支持实时模式(默认模式) */
    /** auto 默认手动刷新模式,可切换为实时模式,disable: 禁用,等同不设置 */
    "dataRefreshMode"?: "auto" | "realtime" | "manual" | "disable";

    /** 默认显示模式 */
    "defaultTableMode"?: "table-list" | "card-list";

    /** card Form 每行的显示条数 */
    "defaultRecordsPerRow"?: number;

    /** 指定在该表单显示页面上方点击创建按钮使用的创建表单名称 */
    "createFormName"?: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# MasterDetail From 属性

{
  /** 对于 master detail 类型的 form, 其detail 部分的组件 form 类型 */
  /** 当前经测试可正常工作的可选值为 INLINE_DISPLAY | FULL_TEXT_SEARCH_LIST | Update */
  "detailFormType": formType;
  /** 对于 master detail 类型的 form, 其 detail 部分的组件对应的字段的名称*/
  "detailField"?: string;
  /** 对于 master detail 类型的 form, 其 detail 部分的组件是否显示为可编辑组件 */
  "detailUpdatable"?: boolean;
}
1
2
3
4
5
6
7
8

# Dashboard From 属性

{
  /** dashboard的自动刷新间隔 */
  "refreshInterval"?: number;
}
1
2
3

# Gantt From 属性

{
  /** 甘特图相关配置 */
  "gantt"?: {
    /** 默认显示的甘特图中的开始时间, ISO8601 和 GB/T 7408-2005格式,例如 2023-05-22T00:00:00+08:00 */
    "viewDateStart"?: string;
    /** 默认显示的甘特图的时间长度, ISO8601 和 GB/T 7408-2005 格式,例如 P5D */
    "viewDuration"?: string;
    /** 左侧行列表展示字段,默认显示 gantt 表单关联领域模型的所有字段 */
    "rowListDisplayColumns"?: [{
      // 字段名
      "key": string,
      // 显示名
      "title": string,
    }];
    /** 任务展示字段,默认显示被 hover 的 task 领域模型的所有字段 */
    "tooltipDisplayColumns"?: [{
      // 字段名
      "key": string,
      // 显示名
      "title": string,
    }];
    /** 任务组字段 */
    "taskGroupColumnKey"?: string;
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 默认动态过滤

默认过滤是 form 中定义的,用于对返回数据施加的隐含过滤条件,用户在界面上, 不会看到该过滤条件的定义,也无法删除该过滤条件。

默认过滤通过 DynamicForm 对象的 extInfo 中的 conditions 字段进行定制,该字段 需要符合标准的 json 语法, 具体定义的语法与上一章节动态过滤中的描述一致。

"conditions" : {
  "status": { // key 是列名称: status
    "columnKey": "status", // 过滤的目标列
    "matchMode": "=", // 匹配规则:等于
    "value": "SUCCESS", // 匹配的目标值: SUCCESS
  },
  "type": { // key 是列名称: type
    "columnKey": "type", // 过滤的目标列, 与上一行的 key 相同
    "matchMode": "isOneOf", // 过滤的匹配规则:isOneOf (是其中某一个)
    "value": [
      "FINDER",
      "UPDATE"
    ] // 过滤的目标值: [FINDER, UPDATE]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 表单字段的 extInfo 支持

系统支持在 extInfo 字段中,使用 json 定制表单字段的扩展属性,详述如下:

# 通用属性

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

{
  // 设定本字段是否显示右边的 detailPanel,
  // 无该属性时,值为 false, 本属性为 true 时,
  // 需要对应字段控件实现了右边详情面板的显示控件
  "hasDetailPanel"?: true | false;

  // 设置某字段支持按需显示,此处的设置值是支持按需显示的字段在全部内容未显示前,显示的概要信息
  // 对于设置了该属性的表单字段,如果从后端返回的数据中,此处所设置的字段的值为 null, 则在前端针对该对象,不启用按需显示
  // 举例如下:
  // 如对于文章对象,其内容 (content) 字段可能非常长,为了前端的用户体验考虑,考虑针对该字段启用按需显示,
  // 此时可以在 content 表单字段的 extInfo 中设置如下:
  // "summayField": "summaryContent"
  // 表示使用名为 summaryContent 的字段作为 content 字段显示全部内容前的摘要字段,此时:
  // 1. 如果后端返回的数据中,summaryContent 字段的值不为 null, 则在前端默认不显示全部 content 字段的内容,
          只显示 summaryContent 字段,用户可点击界面控件,以查看 content 字段的内容
  // 2. 如果后端返回的数据中,summaryContent 字段的值为 null, 则在前端不启用按需显示,
          直接显示 content 字段的内容
  "summayField"?: string;

  // meta 用于覆盖系统自动生成的表单字段的元数据,或者补充某一些属性,如 title, dataIndex, editable, updatable, elementType 等
  // 在运行时,系统会将 meta 中的属性覆盖或者补充到系统自动生成的表单字段的元数据中
  "meta"?: {
      // 字段名
      "key": string;
      // 字段显示名
      "title": string;
      // 字段在表单中的名字,应该和 key 一致
      "dataIndex": string;
      // 可编辑
      "editable"?: boolean;
      // 可更新
      "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
33
34

# file 字段

type 为 file 或 tech_muyan_storage_StorageFieldValue 时,可使用如下的 json 来设定控件的相关属性

{
  /** 接受的附件类型, 可参考 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept  */
  "accept"?: string;
  /** 单个的最大文件大小, 单位 MB */
  "maxSizeMB"?: number;
  /** multiple 为 true 时, 单个字段中, 可上传的最大文件数量, 如果没有设置,默认为 20 */
  /** multiple 根据关联关系的类型或者动态字段定义 (Dynamic Field Instance) 中的 multiple 属性确定 */
  "maxCount"?: number;
  /** 总的文件大小, 单位 MB */
  "totalMaxSizeMB"?: number;
}
1
2
3
4
5
6
7
8
9
10

# code 字段

type 为 code 时,可以通过如下的 extInfo 设定高亮语法

{
  /** 代码编辑器控件显示时的高亮语法 */
  "codeLanguage"?: "css" | "javascript" | "markdown" | "groovy" .....,
  /** 是否在图标后,同时显示代码开始的 20 个字符 */
  "showBrief"?: boolean;
}
1
2
3
4
5

# object 字段

对于对象选择控件,可以使用如下的 extInfo 定义来设定其选择控件中的默认选项

{
    /** 默认显示的 options 的过滤条件 */
    /** 系统打开页面时, 系统会使用该查询条件查询对象列表并作为对象选择控件的默认选项 */
    "defaultOptionsCondition"?: {
        "fieldName" : {
            /** 匹配的值 */
            "value": xxxx,
            /** 匹配的字段名称, 支持 dot(.) 方式引用关联字段的某字段 */
            /** 如 organization.name 引用 organization 字段的 name */
            "columnKey": "xxx",
            /** 匹配规则 */
            "matchMode": matchMode
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 一对多的对象字段

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

{
  /** 在弹出抽屉中显示的关联对象列表中,显示时所使用的 form 名称 */
  "displayForm"?: "Form used to display the list of objects"
}
1
2
3

# 子表字段

type 为 sub table 时(子表字段),可以使用如下的 extInfo 定义来设定其关联列表的显示

{
  /** 子表中的显示字段定义的表单名 */
  "displayForm"?: "Form used to display the list of objects",
  /** 子表控件的相关属性 */
  "subTable"?: {
    /** 子表中是否可创建、编辑、删除、搜索现有行 */
    "updatable"?: true | false,
    "creatable"?: true | false,
    "deletable"?: true | false,
    "searchModal"?: true | false,
    /** 子表中的排序字段,默认为 displaySequence, 可以设置为其他字段 */
    "sortBy"?: "排序字段的 key"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
最后更新: 2024/5/26 15:43:38