# 表单开发进阶
# 编码基础
# formData简介
1.formData是表单绑定实体的对象,包含实体中所有的元素;当实体存在强/弱关联关系时,formData中也会存在另一个关联实体的对象或是数组对象。
2.formData是表单提交时对象,在视图新增、修改、流程表单提交时都会将formData上传至后端接口。
3.表单内的组件字段元素都存放在formData中,表单设计器的js编辑器中都可使用this.formData.XXX(组件字段)拿到当前组件的值完成一系列场景实现。例如:
组件赋予默认值:
业务规则中实现金额计算:
表单提交前事件进行组件赋值
# 强关联对象
强关联对象指实体之间通过关联字段连线建立关联关系,实体模型中建立1:n、n:1、双向1:n模型关系后,可在表单与视图中体现出来。
如上图所示:ITeacher与IStudent建立双向一对n强关联关系,建立持久化实体ITeacher、IStudent的表单,在ITeacher表单中拖进子表格控件,绑定IStudent的视图,即可在ITeacher表单中添加IStudent实体数据,通过关联关系将数据提交至数据库。
同时在IStudent实体中每条数据都会加载Iteacher的关联实体,在IStudent的视图中,可以添加绑定Iteacher的列字段,如下图为教师名称绑定列名ITeacher.name字段,这样每条IStudent数据都可以展示关联的ITeacher信息。
当Iteacher中的数据删除时,IStudent中绑定的关联关系数据也会同步删除。
# 弱关联对象
弱关联对象指实体之间没有建立连线关联关系,实现在一个实体表单内引用另一个数据实体的数据。
如下图场景所示:
采购明细实体与产品价目实体是两个没有关联关系的实体,采购明细表单中产品名称下拉框只需绑定产品价目数据实体,便可将产品价目表中的数据引入到该下拉框中。
同时在当前表单生成一个系统对象__productNameObject
,可为单价和单位组件设置默认值,该默认值就为这个系统对象中的单价和单位字段值。
当选择产品名称后,该产品的单价和单位也会随之匹配显示在表单页面上,实现联动效果。
# 系统对象
系统对象指当前表单内所生成的系统已有对象。例如当引入选人组件并绑定数据实体字段后,会生成人员Object实体,该实体中含有人员详细信息字段,以供后续赋值使用。机构组件、上传组件等在绑定完实体字段后都可生成系统对象
此外,下拉选择组件绑定数据实体字段后,为它的数据来源绑定数据实体,也可生成系统对象。生成的系统对象可用this.formData.系统对象名
拿到该对象数据。
# 获取组件对象
获取组件对象信息可通过Api this.Api.getElement('fieldName')
来实现。
如下场景所示。获取到选择类型的组件对象,可以设置其options值或是遍历操作options值;
//为单选框options赋值
this.Api.getElement('operateType').setOptions(this.options);
//遍历选择组件operateType的选择值内容,当选择组件operateType值不为open时,把其选择值都设为禁用
this.Api.getElement('operateType').options.forEach(item => {
if (this.formData.operateType !== 'open') item.disabled = true
})
# 控制组件的隐藏显示
1.绑定实体和字段的控件使用示例如下:
this.Api.setVisible(false,['name','age','field_54844201']) //隐藏控件 (第二个参数是字段名数组)
this.Api.setVisible(true,['name','age','field_54844201']) //显示控件 (第二个参数是字段名数组)
2.无绑定字段的控件, 如button, tabs, html 等使用如下示例:
this.Api.hideElements(['button_83039646','html_69028416']) //隐藏控件 (参数是控件名)
this.Api.showElements(['button_83039646','html_69028416']) //显示控件 (参数是控件名)
3.也可使用布局组件标签页进行控制标签页内的组件的显示与隐藏,输入显示条件,即可根据返回值true/false来进行组件的显示与隐藏。
# 设置选择类组件的选择范围
这里以下拉选择组件为例,选择组件的数据来源可以选择为数据字典,数据字典可以去AFCenter的组织权限中心》通用管理》字典管理中创建字典类型与字典项,创建完成后便可在此处选择到所选数据;
选择组件的数据来源可选为数据实体,绑定已有的数据实体,控制显示字段与值字段即可选用数据实体中的数据。
选择组件的数据来源可以选择为自定义数据绑定选择组件,自定义的数据通常在表单高级设置中设置变量,变量格式固定,如下
[
{
'label':'钢笔',
'value':'pen'
},
{
'label':'尺子',
'value':'ruler'
}
]
也可在表单的js事件中使用API为选择组件设置options值,如下:
# 表单提交前-调接口阻止提交
场景:表单提交前,调用接口,确认一下数据是否满足条件,不满足则不允许提交
方法:在高级设置的事件中,选择表单提交前事件,代码如下:
const result = await new Promise((resolve, reject) => {
resolve(this.Ajax.get('/api/afc/dict-types', {}, false))
})
if (result.total > 10) {
alert('不满足条件,阻止提交')
return false
}
效果图:
# 组件嵌套
组件嵌套通常是指在一个父表单上通过子表格嵌套另一个视图,或是使用按钮打开表单或视图弹窗等场景。
# parentFormData
例如在Iteacher的表单中放入绑定IStudent的子表格组件,在IStudent的视图中就可通过this.parentFormData
拿到作为父表单的ITeacher表单中formData的数据。如下图所示,在子表格行操作按钮中写下触发事件在控制台打印this.parentFormData
参数,即可看到ITeacher的formData数据展示在控制台中。
# opener
上诉场景,在IStudent的视图中可通过按钮触发事件拿到this.opener
内的参数,this.opener
指的是拿到父表单内所有元素信息,包括formData,事件函数,API,组件元素等信息;
如若ITeacher表单嵌套在其他表单中,可以在IStudent中写成this.opener.opener
,拿到Iteacher表单的父表单的页面元素信息,多层嵌套关系,以此内推。
此外,也可在当前表单中通过this.opener
拿到当前表单的视图内的所有元素信息;如下图所示:
# 使用弹出窗口进行参数传递
表单或视图按钮上可绑定弹出窗口事件,在打开弹窗中可进行参数传递。
上图为代码块打开弹窗传参,也可使用配置化打开弹窗。
传递的参数formData_name
需要在打开的表单或视图的高级设置中添加外部参数formData_name
;
定义完参数后就可以使用this.formData_name
拿到父表单/视图中传递的参数。
# 使用页面容器
表单编辑器下,高级组件中可使用页面容器组件,该组件可绑定表单资源或视图资源,绑定成功后,即可在当前页面展示出所绑定的表单或视图。
示例场景一:学生信息表单页面使用页面容器绑定教师信息表单资源,在查看学生详细信息时展示出该名学生班主任的信息(注:此时,教师与学生的实体模型关系为双向1:n,为页面容器绑定教师实体字段即可);
示例场景二:页面容器绑定视图,在表单中显示视图查询数据,可把页面容器嵌套入标签页,通过切换标签页达到查看不同的页面容器绑定视图所查询的数据。
该场景实现需要编写js脚本来实现,详细步骤如下:
1.新增教师视图为女教师视图,将默认教师视图作为男教师视图,在男教师视图中找到视图设置=》高级设置=》新增视图查询前事件,编写视图默认查询条件根据性别值为男来查询数据的js代码如下:
同上在女教师视图中创建视图查询前事件,将默认查询条件值改为女即可;
2.在主表单中拖进两个页面容器组件与一个标签页组件,两个页面容器分别绑定刚刚创建的男教师视图与女教师视图;在标签页组件基础属性中新增一个标签页,将两个标签页改名为男教师
与女教师
;分别将两个页面容器拖入对应标签页中。
3.编写视图查询js脚本。当前场景是表单加载后默认展示第一个标签页的视图数据,所以在表单高级设置中创建表单加载后事件,调用getFrame('页面容器组件编码')
方法拿到容器组件属性在调用他的doQuery
方法,达到默认加载页面查询数据的目的;
当标签页切换时也需要去查询视图数据,所以在标签页组件的高级中创建切换标签事件,当标签页切换时执行不同视图的查询事件。
综上步骤,即可实现所展示场景。
# 控件通用
# label
# 1.不显示label
- 在标题处,取消勾选标签
场景:地区选择时,使用省市区字典联动,只展示第一个标签,后续的都不显示
设置及效果图:
# 2.label宽度
- 调整label宽度,可以通过修改表单的标签宽度,也可以直接修改组件自带的标签宽度属性(组件优先级高于表单)
方法1. 在表单设置的 基础设置 修改 标签宽度(对整个表单的控件统一管理),单位px
设置及效果图:
方法2. 在高级里修改标签宽度,单位px
场景:几个相关联的省市区控件之间距离,设置得稍小于其他控件,可以通过调整标签宽度
设置及效果图:
# 3.动态label
场景:通过切换开关,动态显示住址label
效果图:
步骤1. 设置变量,在表单设置的高级设置里,添加名为v_label的变量,默认值为’住址‘
步骤2. 给标题绑定变量v_label
步骤3. 添加业务规则,动态修改变量v_label
# 控件
# 1.设置宽度
影响控件宽度的方法涉及以下三种
方法1. 在基础配置项的组件宽度处选择比例(控件占当前行的比例)
场景:年级和班级平分一行,各占组件宽度的1/2
设置及效果图:两个控件的组件宽度选择1/2
方法2. 高级的组件宽度上输入合适的数据
- 默认100%,百分比表示 控件宽度显示本身的百分之几
- XX px,直接配置固定宽度
设置及效果图:
方法3. 通过样式的左右外边距调整控件的缩进距离
效果图:
# 默认值
# 1.介绍规则
规则:在字段未设置值的情况下,默认显示;如果后续对字段进行修改可覆盖默认值
- 基础的默认值点击“D”,在弹框中可以选择不同类型的默认值
# 2. 设置常量
常量,允许输入 字符串 ,数字 ,json 对象。
方法:可以在默认值输入框中直接输入;或者点击“D”打开弹框,在常量中输入
场景:所在地默认江苏
效果图:
# 3. 设置变量
变量,分为变量和参数
- 变量,有如下几类
- 在表单高级设置处自定义的变量(v_开头)
- 系统变量,有当前时间
- 流程相关变量
- 当前用户的相关变量
- 参数,在表单高级设置处添加的参数字段(当前表单可以使用参数默认值),由引用表单的参数传入
场景1:默认选人组件显示当前登录账号对应的用户
方法: 点击标题的“D”打开弹框,在变量中选择员工Id
效果图:
场景2:说明数据来源,在视图中添加数据时默认值为 “视图”
步骤1. 在表单设置—高级设置添加参数名称为form_source,默认值为 “无”
步骤2:给数据来源的控件的默认值绑定form_source参数
步骤3:在视图tab下的视图设置—高级设置添加名称为page_source的参数默认值为 "视图"
步骤4:在视图设置的动作设置—工具栏表格上 编辑新增行添加参数名为from_source值为this.page_source
效果图:打开新增弹框,数据来源默认值为“视图”
场景3:说明数据来源,在资源容器引用表单时默认值为 “资源容器”,(前两步骤的图示请参考场景2)
步骤1. 在表单设置—高级设置添加参数名称为form_source,默认值为 “无”
步骤2:给数据来源的控件的默认值绑定form_source参数
步骤3:在引用表单的资源容器中的高级—扩展属性,添加名称为form_source值为 “资源容器”的属性
效果图:
场景4:说明数据来源,在菜单配置处时默认值为 “菜单”,(前两步骤的图示请参考场景2)
步骤1. 在表单设置—高级设置添加参数名称为form_source,默认值为 “无”
步骤2:给数据来源的控件的默认值绑定form_source参数
步骤3:添加资源页面,输入参数:form_source=菜单
步骤4:配置菜单,选择添加的资源页面
步骤5:角色授权
- 变量,有如下几类
效果图:刷新页面,打开对应路径的菜单
# 4. 设置表单实体/字段
表单实体字段,分为表单的持久化字段 和扩展的实体字段(例如选人组件绑定的字段filed2以及其扩展的实体字段__filed2Object.phoneNumber)
场景:手机号默认为参与选手的手机号信息
效果图:在参与选手组件上选择一个员工,手机号组件也跟着显示其手机号
如果员工需要配置手机号,在机构管理的员工信息处添加
# 5. 设置表达式
- 表达式,支持简单的js语句
场景:信息描述的默认值为 前面几个控件的 拼接内容
方法:在默认值的表达式中写入如下代码:
'欢迎来自'+ (this.formData.filed1 || '中国') + '的参赛选手:' + this.formData.__filed2Object.name
效果图:
# 校验
校验功能是在防止用户犯错的前提下,尽可能让用户更早地发现并纠正错误
# 1.静态校验
可以在控件的验证处,选择需要的校验,可以选择一项或多项。如果不能满足需求,可以在限定输入格式处选择自定义正则,输入正确的正则表达式。
必填
不允许重复:调用接口进行重复验证
限定字数
限定数字范围
限定输入格式:可选中,打开弹框并选择对应的正则表达式或自定义
场景1:编码输入框要求不能为空,不能重复,且字数不能大于10,操作如下:
效果图:
场景 2:年龄(数字控件)要求范围在0-150之间
效果图:
场景3:身份证号校验
方法:选择和点击限定输入格式,在弹框左边选项中选择身份证号。可以修改错误提示,也可以测试效果
效果图:
场景4:输入ABCD中的某个正确选项
方法,打开限定输入格式弹框,选择自定义正则,输入对应的正则表达式
效果图:
# 2. 动态校验
方法1:使用校验API,改变校验规则
this.Api.setValidator('filed', [{
validator: (rule, value, callback) => {
if (true) {
callback('不符合') // callback()方法带参数表示不符合校验
}
else {
callback() // 不带参数,表示通过校验,必须要写!!
}
}
}])
场景:选择联系方式为邮箱或者手机号的时候,校验规则变更为对应的
分别在表单加载前和切换联系方式的时候修改校验规则
步骤1. 表单加载前,代码如下:
this.Api.setValidator('filed4', [{
validator: (rule, val, callback) => {
if (val && !/^1[3-9]\d{9}$/.test(val)) {
callback('不符合手机号格式')
} else {
callback()
}
}
}])
步骤2. 切换联系方式时的事件代码如下:
// value是开关切换的值,val是filed4的输入值
this.Api.setValidator('filed4', [{
validator: (rule, val, callback) => {
if (val && value == 'true' && !/^[0-9A-Za-z][\.-_0-9A-Za-z]*@[0-9A-Za-z]+(\.[0-9A-Za-z]+)+$/.test(val)) {
callback('不符合邮箱格式')
} else if (val && value == 'false' && !/^1[3-9]\d{9}$/.test(val)) {
callback('不符合手机号格式')
} else {
callback()
}
}
}])
效果图:
方法2:添加自定义校验事件
- 自定义校验事件:打开弹框,自定义方法,return的字符串会直接显示为错误提示;return null或false或直接不写则表示校验通过(字符串用单引号)
效果图:
场景1:修改密码
给新密码添加自定义校验事件
代码如下:
if (value === this.formData.filed3) {
return '校验不通过'
}
场景2:调用重复接口校验
给字段2添加自定义校验事件
代码如下:
const result = await this.Ajax.post('/api/lowcode/models/exist?entityName=page_form_common.general_attribute.general_attr&resourceType=formx',{
'condition':{
'and':{
'items':[
{'maxValue':{},
'minValue':{},
'op':'=',
'propertyName':'filed2',
'propertyValue':value}]
}},
'pkMap':{'id':null},
}, false
)
if (result) {
return '校验不通过'
}
# 表单状态设置控件状态
- 用户可以根据场景自定义表单控件在新增、编辑和查看时,是读写、只读、禁用或隐藏状态
方法1:点击控件上的设置按钮,切换控件状态,如下图:
方法2:在表单设置的表单状态下选择(与组件的设置自动同步)
效果图:
# JS设置控件状态
使用API设置控件状态
// 显示
this.Api.setVisible(true, ['filed'])
// 隐藏
this.Api.setVisible(false, ['filed'])
// 只读
this.Api.setReadonly(true, ['filed'])
// 取消只读
this.Api.setReadonly(false, ['filed'])
// 禁用
this.Api.setDisabled(true, ['filed'])
// 取消禁用
this.Api.setDisabled(false, ['filed'])
场景1:根据开关切换控件的显示与隐藏
给开关组件添加事件
代码块内容如下:
if (value === 'true') { this.Api.setVisible(true, ['filed1']) } else { this.Api.setVisible(false, ['filed1']) }
效果图:
场景2:根据开关控件切换只读与读写
给开关控件添加事件(图示参考场景1)
代码块如下:
if (value === 'true') { this.Api.setReadonly(true, ['filed3']) // 只读 } else { this.Api.setReadonly(false, ['filed3']) }
效果图:
场景3:根据开关控件切换禁用
给开关控件添加事件(图示参考场景1)
代码块如下:
if (value === 'true') { this.Api.setDisabled(true, ['filed2']) // 禁用 } else { this.Api.setDisabled(false, ['filed2']) }
效果图:
# JS设置选择类控件的提交值和显示值
使用API给选择组件设置options和绑定值
// 设置下拉列表,当选框,多选框 的options方法示例
this.Api.getElement('filed1').setOptions(this.options)
// 绑定值可以直接赋值
this.formData.filed1 = XXX
场景:点击不同的按钮,下拉组件切换对应的值
给已做按钮添加事件
this.Api.getElement('filed1').setOptions([{id: 'did', label: '已做'}])
this.formData.filed1 = 'did'
给未做按钮添加事件
this.Api.getElement('filed1').setOptions([{id: 'undo', label: '未做'}])
this.formData.filed1 = 'undo'
效果图:
# 控件
# 高开容器
# 1.引入高开组件:
功能:在低开表单中,使用高开容器组件来引用高开页面
在高开模块标识中选择模块。
前提:引入的高开资源是已配置好的,如果从头搭建一个微前端页面并添加代理,具体详见配置微前端资源
在高开页面标识选择页面,也可自定义输入
场景:在低开表单中引入高开组件
步骤1. 在高开页面标识选择微前端模块myApp
步骤2. 在页面标识中输入demo
前提:页面标识是微前端项目中对外暴露的页面
- 高开页面的代码:
<template>
<div>
<el-descriptions class="margin-top" title="用户信息" :column="3" border>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
用户名
</template>
{{ user.name }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-location-outline"></i>
居住地
</template>
{{ user.address }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
身份
</template>
<el-tag size="small">{{ user.status }}</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script>
export default {
name: 'name', // 和菜单代码一致即可开启页面缓存
data(){
return {
user: {
name: '曾用名',
address: '杭州市',
status: '学生'
}
}
}
</script>
效果图:
# 2. 低开给高开组件传参
功能:在高开页面中,使用低开表单传入的参数
步骤1. 在高级的扩展属性里添加参数的属性名和属性值
在高开页面中的props接参(避免与data中的属性名重名)
props: { user: { type: Object, default: () => {} }, },
场景:在高开页面中,使用低开表单传入的参数
步骤1. 添加属性名为user,值为v_user的变量,v_user的默认值如下:
{
name: 'kooriookami',
phoneNumber: '18100000000',
address: '苏州市',
status: '学生'
}
步骤2. 页面接收参数user(这里的user要与高开容器的属性名user对应)
props: {
user: {
type: Object,
// 默认值
default: () => {
return {
name: '曾用名',
address: '杭州市',
status: '学生'
}
}
},
}
高开页面代码:
<template>
<div>
<el-descriptions class="margin-top" title="用户信息" :column="3" border>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
用户名
</template>
{{ user.name }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-location-outline"></i>
居住地
</template>
{{ user.address }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
身份
</template>
<el-tag size="small">{{ user.status }}</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script>
export default {
name: 'name', // 和菜单代码一致即可开启页面缓存
props: {
user: {
type: Object,
default: () => {
return {
name: '曾用名',
address: '杭州市',
status: '学生'
}
}
},
},
}
</script>
效果图:
# 3. ⾼开组件修改低开传⼊参数
功能:在已有传参的高开页面中,修改低开传入的参数
步骤1. 给高开容器添加事件-属性值变化时,并在代码块中修改V_user的值
this.v_user = value
步骤2. 高开页面中修改参数,需要触发dataChange事件,代码如下:
this.$emit('dataChange', user)
场景:在已有传参的高开页面中,修改低开传入的参数
步骤1. 给高开容器控件添加事件(属性值变化时)
步骤2. 高开页面中触发dataChange事件,代码如下:
<template>
<div>
<el-descriptions class="margin-top" title="用户信息" :column="3" border>
<template slot="extra">
<el-button type="primary" size="small" @click="changeStatus">修改身份</el-button>
</template>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
用户名
</template>
{{ user.name }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-location-outline"></i>
居住地
</template>
{{ user.address }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
身份
</template>
<el-tag size="small">{{ user.status }}</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<script>
export default {
name: 'name', // 和菜单代码一致即可开启页面缓存
props: {
user: {
type: Object,
default: () => {
return {
name: '曾用名',
address: '杭州市',
status: '学生'
}
}
},
},
methods:{
changeStatus() {
const user = {
...this.user,
status: '打工人'
}
this.$emit('dataChange', user)
}
}
}
</script>
效果图:点击按钮,页面数据改变
# 资源容器
功能:资源容器控件,可以通过 页面资源配置项 选择 对应的表单或视图,达到在表单中引用其他资源的目的。
# 1. 引用表单
功能:在一个表单中引用另一个表单
场景:在学生信息表单中展示教师信息
前提:场馆预约表和顾客信息表信息表的实体为单向1:1的关系
步骤1. 生成顾客信息表单页面
步骤2. 绑定1:1的字段
步骤3. 在资源容器控件的页面资源中,选中类型为表单的选项
效果图:查看视图的某条数据
# 2.引用视图
功能:在表单中引用视图,并加载视图数据
在资源容器控件的页面资源中,选中类型为视图的选项
加载视图数据,在表单设置中添加事件(表单加载前)
场景:自定义查询表单—在视图中打开一个关联的表单
前提:打开的关联表单是下拉组件在数据来源绑定的数据实体。即:先加载<假日时长>表单,更新视图,并添加视图数据;表单中的<放假时长>为下拉框,数据来源绑定的是<假日时长>的实体
步骤1. 首先在视图的显示字段—添加显示列(行程推荐)
步骤2. 点击<格式>按钮,弹框中选择<自定义>,可以自定义一个点击按钮
<el-button type="text" >查看</el-button>
步骤3. 链接里打开查询的表单
Api.openDialog({
id: 'page_form_complex.festival_time',
resourceType: 'form',
dialog: {
title: '',
width: '90%',
top: '15vh',
modal: true,
mode: 'dialog'
},
props: {
status: 'view', // 查询状态
detailData: formData.__restObject
}
})
步骤4. 在对应的表单中配置入参和赋值
高级设置—参数-添加同名参数(detailData),并在事件—添加表单加载前事件
if (this.detailData && this.detailData.id) {
this.formData = this.detailData
}
效果图:回到资源容器,点击查看按钮,可以打开查询表单
# 3. 访问表单和视图内的数据和⽅法
访问表单
// 绑定资源容器的字段对应的就是整个表单的数据 this.formData.field_42461708 // 使用API获取表单的方法 this.Api.getFrameAsync('field_42461708').then(el => { console.log(el.Api, '======引用表单') })
场景:点击按钮时,打印引用表单的数据和方法
方法:给按钮添加事件,如下图:
效果图:打印结果如下
访问视图
// 绑定资源容器的字段对应的就是整个视图表格的数据 this.formData.field_89356555 // 使用API获取视图的方法 this.Api.getFrameAsync('field_89356555').then(el => { console.log(el.Api, '======引用视图') })
场景:点击按钮时,打印引用视图的数据和方法
方法:给按钮添加事件,如下图:
效果图:打印结果如下
# Vue组件
组件本身是一个template模板,可以添加一些简单的表达式和行内样式,举例如下:
<div style="color: red">选中的值:{{formData.filed1}}</div>
# 特殊样式的录⼊控件
场景:使用vue组件编写一个特殊样式的录入控件
- 在Vue模板中添加如下代码
<div class="mb-20">
<el-input placeholder="请输入内容" v-model="formData.filed1">
<el-select v-model="formData.filed2" slot="prepend" placeholder="请选择" style="width:100px;">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
<i
class="el-icon-edit"
slot="suffix">
</i>
</el-input>
</div>
效果图:
# HTML组件
html模板中的内容会被当做html标签解析,这里只能使用原生的控件
# 特殊样式的录⼊控件
场景描述:用html开发一个滑块组件
- 滑块样式。在内容-HTML编辑中添加如下代码块:
范围(1-10):<input id="range_123" type="range" max="10" min="1" value="0">
- 提交代码前,将录入的值赋给持久化字段, 添加表单提交前事件。代码块如下:
// 获取组件的值
const range = document.getElementById("range_123").value
this.formData.filed3 = range
回显组件的值
添加表单加载后事件,代码块如下:
// 将filed3的值赋给滑块控件
document.getElementById("range_123").value = this.formData.filed3 || 0
效果图:
# 标签页
# 1. Tab的位置与样式
配置项—基础-标签样式(默认/card/border-card)、标签位置(靠上 /靠右/ 靠下/ 靠左)
# 2. 动态控制标签页的显示与隐藏
在标签页的显示条件栏编辑,这里的条件表达式返回的必须是布尔值true/false,例如
true/false ;//布尔值
this.xx=='xxx'?true:false ;//三目,(注:字符串不能出现双引号)
this.v_xxx;//参数或者变量,必须是布尔型
场景:学校、年级和班级信息要按照顺序填写
在年级标签页的显示条件中,配置学校是否有值
!!this.formData.filed1
在班级标签页的现实条件中,配置年级是否有值
!!this.formData.filed2
效果图:
# 3. 控制tab能否被选中
场景:要求tab的内容按顺序填写
- 给标签添加事件-切换标签,代码块如下
// 前者没有信息,后者不能选中
if (!this.formData.filed1 && activeName === '2' || !this.formData.filed2 && activeName === '3') {
// 点击切换无效
return new Promise((resolve, rejects) => {
rejects()
})
}
else {
// 可以切换
return true
}
效果图:
# 面板分割
# 1. 静态设置
配置项-左面板宽度
# 2. 动态设置
使用js设置左面板的比例,1为整块面板
this.split_18410582_key = 1 / 4
场景:点击按钮动态切换面板分配
给按钮添加点击事件代码块如下:
// 四分之一按钮 this.split_18410582_key = 1 / 4 // 三分之一按钮 this.split_18410582_key = 1 / 3 // 二分之一按钮 this.split_18410582_key = 1 / 2 // 三分之二按钮 this.split_18410582_key = 2 / 3
效果图:
# 分组控制
按条件显示分组
配置项—基础-标签页-显示条件,写入一个结果为布尔值的表达式即可。详情参考<动态控制标签页的显示与隐藏>
# 导航树
# 1. 配置数据
在树面板选择模型关系或指定树形json
- 静态数据——指定树形json
在指定树形json里配置常量或者变量符合规范的值,参考如下,
配置项—标签键名,eg: label
配置项—绑定值名,eg: value
配置项—子级键名,eg: children
[{
"id":"10",
"label":"中国",
"value":"zg",
"children":[{
"id":"1",
"label":"上汽",
"value":"sq",
"type":"4S"
}, {
"id":"2",
"label":"吉利",
"value":"jl",
"type":"4S"
}]
}]
- 动态数据——模型关系
步骤1. 在模型关系里选择绑定的实体
步骤2. 在节点配置处 点击高亮的编辑图标,配置显示字段和图标
# 2.点击事件
事件1:节点点击
在高级里添加事件(节点被点击时),选择代码块,可以获取到当前点击节点的数据node
事件2:菜单点击
步骤1. 节点配置-点击高亮的编辑图标,切换tab到菜单配置,可以添加多个菜单
步骤2. 在高级里添加事件(菜单被点击时),选择代码块,可以获取到当前点击节点的数据action(菜单的action类型)和node
或者在高级里添加事件(菜单被点击时),选择打开新窗口,可以选择表单并传参
# 3. 案例参考
场景描述:左侧导航树,右侧视图(树表联动)。点击导航树节点,更新右侧视图数据;点击节点菜单,打开添加表单添加数据。
前提:先加载<假日时长>表单,更新视图,并添加视图数据;再更新<节假日>表单,其中控件<放假时长>为下拉框,数据来源绑定的是<假日时长>的实体
配置过程:
步骤1. 左侧导航树组件—动态数据选择<假日时长>实体,节点配置的基础配置-显示字段(time)和菜单配置添加action(add)
步骤2. 配置菜单 点击事件,在高级设置处添加事件(菜单被点击时),动作选择打开新窗口。添加参数,选择(添加)变量v_currentnode_id
步骤3. 被引用表单配置入参,<节假日>表单的高级设置添加参数v_currentnode_id
并绑定<放假时长>控件的默认值
步骤4. 在被引用表单页面,添加并配置导航树视图
在视图设置的高级设置,添加参数(rest)
在视图设置的高级设置—快速筛选,添加删选条件(放假时长);默认值选择参数rest;显示选择隐藏
步骤5. 右侧资源容器组件 的 页面资源绑定<导航树视图>,高级的扩展属性添加参数rest,绑定的值为新建的变量(v_currentnode_id)
步骤6. 建立联系—导航树添加节点被点击事件—修改传参并使用Api操作视图查询
this.v_currentnode_id = node.time
this.Api.getFrameAsync('field_14841241').then(el => {
el.Api.doQuery()
})
效果图:在预览页面,可以点击节点,右侧视图相应更新;点击菜单,弹出添加弹框,保存成功自动刷新数据。
# 下拉选择组件
# 1.选择数据源为业务字典
可以选择已有的业务字典;然后下拉选择组件选项会渲染成此字典的字典项选择列表 ;
# 2.选择数据源为数据实体
可以选择数据实体,指定值字段 和显示字段 ;然后下拉选择组件选项根据显示字段渲染成选择列表;
# 3.选择数据范围为静态数据
可以自定义数据;绑定变量选择常量,添加code 和 name 对应值,然后会自动生成一个变量;
这个变量还可以转化为业务字典;转化成功后,可以在Afcenter组织权限中心--->通用管理--->业务字典中进行查看
使用脚本和变量动态的设置选择数据
例如一个通过按钮点击动态设置下拉选项的选项
效果展示:
步骤1.设置一个变量
在表单设置-》点击高级设置-》变量-》添加一个变量
步骤2.下拉选择绑定此变量
步骤3.按钮添加事件给变量赋值
在按钮的右侧的配置项,点击高级-》添加事件-》选择代码块
下面是代码给变量赋值
其中disabled:true 设置选项禁用
this.v_options = [{ "code": "aa", "name": "AAA", "disabled":true, }, { "code": "bb", "name": "BBB" }, { "code": "cc", "name": "CCC" }]
# 4.选择数据范围控制
例如:过滤出数据实体的code等于当前表单的code数据
# 5.业务字典级联选择 -父字典为空时禁用
例如:省市级联
效果展示:
步骤1.设置省下拉选择
步骤2.设置市下拉选择
字典类型选择市,父字典选择绑定变量为字段,选择省,然后勾选为空时禁用
# 6.多选设置
勾选允许多选可以选择多个选项
# 7.输入搜索
在右侧配置高级里开启能否搜索,下拉组件可以搜索到选择项;
# 8.设置下拉组默认选中值
例如在在表单加载后给下拉组件赋予默认值
this.formData.name = 'aa' //给下拉组件绑定的值赋予绑定数据源的值字段就可以默认值回显;其中字典和自定义的值字端为code
# 9.事件 - 选中事件
如果你想在下拉组件值变化时做一些其他的代码处理,可以在右侧配置项高级里添加事件
# 10.显示下拉组件label
如果你想把下拉组件显示的值在单行文本中显示;
效果展示:
步骤1.如果单行文本显示下拉组件省显示的label;可以单行文本默认值选址字段为sheng下的name(其实就formData.__shengObject.name);
说明:当组件绑定数据源时,formData中的属性还会生成一个__XXXObject属性,__XXXObject是一个选中值详细信息的对象;
步骤2.如果单行文本显示下拉组件省和市的拼接的label;可以单行文本默认值选择表达式;表达式内容如下:
this.formData.__shengObject.name + this.formData.__shiObject.name
# 单选组件
同单选组件使用;
# 多选框组件
同单选组件使用;
# 多选框设置默认值
多选框设置默认值时,多个值需要逗号隔开
例如在在表单加载后给多选框组件赋予默认值
this.formData.nameEntry = 'zhangsan,lisi' //其中zhangsan,lisi 为绑定数据实体的值字段code
# 日期选择
注意日期组件在绑定的实体的属性选择为TimeStamp
# 1.默认值 设置为当前时间
默认值选择变量为当前时间
# 2.时间类型设置
设置时间类型,组件会显示不同的时间选择页面,可以选择日、月、年或者日期时间
# 3.时间格式设置
时间格式是绑定数据显示格式,下面是对应的值
例如选择时间格式为 年-月-日 时:分:秒 ,那么绑定的数据显示为2023-04-10 00:00:00
{
label: '年',
value: 'yyyy',
},
{
label: '年-月',
value: 'yyyy-MM',
},
{
label: '年-月-日',
value: 'yyyy-MM-dd',
},
{
label: '年-月-日 时:分',
value: 'yyyy-MM-dd HH:mm',
},
{
label: '年-月-日 时:分:秒',
value: 'yyyy-MM-dd HH:mm:ss',
},
# 4.设置可选时间范围
静态设置
可以选择确定的时间设置时间可选时间范围
动态设置
可以选择绑定变量,动态设置时间可选时间范围
# 5.时间操作Api
//时间单位unit
//值 简写
//years y
//months M
//weeks w
//days d
//hours h
//minutes m
//seconds s
//milliseconds ms
this.Moment().format(format) //当前时间并格式化 例如YYYY-MM-DD HH:mm:ss
this.Moment(date).add(n,unit).format(format) //计算距离时间 + n/years/months/weeks/days ...
this.Moment(date).subtract(n,unit).format(format) //计算距离时间 - n/years/months/weeks/days ...
# 弹窗选择
# 1.弹窗标题,设置弹窗大小
在弹窗选择组件右侧配置项高级-》弹窗设置 中设置标题、高度 ...
# 2.向弹出窗口传递参数传递
例如,我们要做一个在表单中输入code为'zhangsan'然后点击弹窗选择在打开的视图中默认展示code=zhangsan 的过滤结果。
效果展示:
步骤1.在右侧配置项点击高级-》添加参数 -》定义参数名和选择参数值
步骤2.在绑定的视图中,点击视图设置-》点击高级设置 -》参数 -》中添加一个刚才定义的参数(必须一样) user_code
步骤3. 使用穿过来的参数;
点击视图设置-》点击快速筛选 -》添加筛选条件 默认值选择参数 user_code
# 3.选择确定前对选择数据校验
例如我们只能让用户选择code为zhangsan的数据提交,选择其他的不符合条件的数据进行提示;
效果展示:
步骤1.需要在弹窗选择绑定的视图添加禁用控制;
点击视图设置-》动作设置-》弹窗按钮 -》点击确定按钮的编辑-》禁用控制-》使用方法控制中编写以下代码
// selectedItems 为选中的数据
if(this.selectedItems.length){
//根据自己需求判断
if(this.selectedItems[0].code !== 'zhangsan'){
//提示不合法选择
this.$message({
message: '请选择code为zhangsan的数据',
type: 'warning'
});
//禁用确定按钮
return true
}
}else{
return false
}
# 4.弹窗选择设置默认值
例如我们在表单加载后设置弹窗选择默认值
效果展示:
步骤1.在表单加载后事件编写以下代码
//1.设置绑定实体的 值字段的值
this.formData.name = 'wangwu'
//2.同时设置_XXXObject的值为对应值字端的详情数据对象
this.formData.__nameObject = {
"id": "7",
"code": "wangwu",
"name": "王五"
}
# 机构选择
# 1.默认当前用户所在机构
右侧配置项默认值-》变量-〉选择用户机构ID
# 2.展示模式
展示模式有按钮 和 搜索选择 ;可以根据自己需求选择配置;
例如:当配置按钮模式选择多个机构后,在子表格中会显示选择的机构信息;
效果图:
步骤1.建立实体关系1->n ,通过pid进行关联
步骤2.配置机构选择组件
勾选允许多选,展示模式选择按钮
步骤3.给子表格数据赋值
其中selectedArr为已选的机构数组数据
console.log(selectedArr, '机构数据')
this.formData.orglists = selectedArr.map(item=>{
return {
code:item.code,
name:item.name
}
})
# 3.设置可选范围
可以通过配置当前用户所在部门、指定范围设置可选的机构范围;
还可以通过变量动态设置可选范围;
步骤1.点击表单设置-》高级设置-》变量 -》添加一个变量;设置可选机构范围;
[
{id: 'org', label: '机构', rangeMode: 'dimension', rangeData: {dimensionCode: 'def_dimension'}, // 某个维度的机构
// {id: 'org', label: '机构', rangeMode: 'rootOrgs', rangeData: {ids: '1,2,3'}}, // 以ids为根节点,展示本机构及子机构
// {id: 'org', label: '机构', rangeMode: 'orgs', rangeData: {ids: '1,2,3'}}, // 展示ids对应的机构
]
// 注:ids为id用英文逗号拼接的字符串
步骤2.范围选择选择新的变量v_orgs
# 人员选择
# 1.默认当前用户
在右侧配置项默认值-》变量-》选择员工Id
# 2.作为流程参与者
在右侧配置项开启流程参与者后,可以通过选人组件选的人作为其他流程的参与者;可以通过xpath可以点击复制变量名;
例如:我们在某一个环节通过选人组件选择人员数据后,作为下一个环节的参与者时
效果显示:
步骤1.在流程中定义相关数据
双击流程空白处,设置相关数据,名称为点击xpath复制的变量名;
步骤2.流程设置参与者为相关数据
# 3.展示模式
展示模式有按钮 和 搜索选择 ;可以根据自己需求选择配置;
例如:我们做一个这样的例子;用户通过按钮模式选择多个人,然后在表单子表格中显示选择的人员的数据信息
效果图如下:
步骤1.建立实体关系1->n
步骤2.配置选人组件
展示模式选择按钮;
步骤3.给子表格赋值
在选人组件右侧配置项-》点击高级-》添加事件
其中selectedArr为已选人员的信息数组
console.log(selectedArr, 'selectedArr')
this.formData.userlists = selectedArr.map(item=>{
return {
code:item.code,
name:item.name
}
})
# 4.设置可选范围
在右侧配置项范围选择可以设置可选范围;默认所有可选,展示机构主维度的树形模式。
如果需要通过动态限制选择范围或者从人员、机构和角色多角度展示可选指定范围;
效果展示:
步骤1.点击表单设置-》高级设置-》变量中添加变量
变量可从三种模式(机构、人员、角色)添加,以数组形式,可写多个(机构的三种类型只可选其一):
[
{id: 'org', label: '机构', rangeMode: 'dimension', rangeData: {dimensionCode: 'def_dimension'}, // 某个维度的机构
// {id: 'org', label: '机构', rangeMode: 'rootOrgs', rangeData: {ids: '1,2,3'}}, // 以ids为根节点,展示本机构及子机构下的员工
// {id: 'org', label: '机构', rangeMode: 'orgs', rangeData: {ids: '1,2,3'}}, // 以ids为父节点,展示本机构下的员工
{id: 'role', label: '角色', rangeMode: 'roles', rangeData: {ids: '1,2,3'}}, // 以ids为父节点,展示其下的员工
{id: 'emp', label: '人员', rangeMode: 'emps', rangeData: {ids: '1,2,3'}} // 展示ids对应的员工
]
// 注:ids为id用英文逗号拼接的字符串
步骤2.范围选择变量刚才添加的变量v_user
# 附件上传
# 1.按钮模式上传多个附件在子表格回显附件信息
例如我们做一个这样的例子;员工通过按钮模式上传多个附件,然后在表单子表格中显示上传的附件信息;
效果图如下:
步骤1.建立实体关系
人员和附件1-》n ,通过userid关联
步骤2.配置附件上传组件
展示模式选择按钮;选择允许上传的文件类型
步骤3.给子表格赋值
其中fileList 为上传成功的附件列表;把附件列表的信息根据自己的业务处理赋予子表格数据
console.log(response, file, fileList, '附件上传')
const authorization = file.headers.Authorization
this.formData.filetest2s = fileList.map(item => {
return {
fileid: item.fileId,
fileName: item.fileName,
Authorization: authorization
}
})
# 2.权限控制删除按钮
场景:上传的附件只能当前用户进行删除操作
案例1:使用上传附件的按钮权限控制功能,写入正确的代码控制权限
效果图:
步骤:使用上传附件(filed1)的表格模式,在高级的操作按钮控制添加代码
// 上传附件的创建者 当前用户
formData.__filed1Object.createUser === Context.user.employeeCode
切换用户就可以看到非本用户上传的附件不能删除
案例2:使用上传附件的按钮模式+子表格实现
使用附件上传组件和子表格实现,其他功能仿照附件的表格信息模式
效果图:
步骤1:建立实体关系,同1.按钮模式上传多个附件在子表格回显附件信息
人员和附件1-》n ,通过userid关联
步骤2:n端生成子表格视图,效果如下:
动作设置的行内操作,删除系统按钮,添加两个自定义按钮,下载和删除
下载按钮的动作选择执行代码,代码如下
this.Api.downloadAttachment(formData.fileid,formData.fileName)
删除按钮的动作也选择执行代码,并做禁用控制,代码如下
// 执行代码
this.$confirm('是否确认删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.data = this.data.filter(i => i.id !== formData.id)
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
});
// 禁用控制代码
formData.createUser !== JSON.parse(localStorage.getItem('user'))?.userName
配置图片如下:
步骤3:1端生成页面,一个附件上传组件的按钮模式,一个子表格绑定刚生成的子表格视图(绑定n端字段),效果如下:
给上传组件添加上传成功事件,如下图:
至此,在1端视图里,可以看到添加数据会回显在子表格中;编辑页面中非当前用户的数据在子表格中删除禁用。
# 3.自定义上传地址
如果我们需要上传附件后额外自己处理上传的附件,可以配置上传地址,后端定义一个上传controller接口api;
注意接收值和返回值必须保持一样;函数内部可以添加自己处理附件的逻辑
@Autowired
private IAttachmentService attachmentService;
/**
* 上传附件
*
* @param attachments 附件
* @return 附件列表
* @throws Exception
*/
@PostMapping(value = "/attachments/actions/upload/test", consumes = MULTIPART_FORM_DATA_VALUE)
@ApiOperation("上传附件")
public List<FileStore> uploadAttachments(@ApiParam("模型实体名称") @RequestParam(name = "entityName", required = false) String entityName,
@ApiParam("实体ID") @RequestParam(name = "entityId", required = false) String entityId,
@ApiParam("附件") @RequestParam("attachments") List<MultipartFile> attachments) throws Exception {
if (StringUtils.isBlank(entityName)) {
entityName = "lowcode-model";
}
if (StringUtils.isBlank(entityId)) {
entityId = "default";
}
//自定义处理附件逻辑
//XXXXXX
return attachmentService.uploadAttachments(null, entityName, entityId, attachments);
}
然后配置上传地址为自己定义的接口api地址
# 树形选择
# 1.数据来源
# 一对多关系树
例如:供应商和商品是1—》n实体关系,我们配置一个选择供应商下的商品的下拉树;
效果展示:
步骤1.建立一对多关联实体
步骤2.数据来源绑定实体选择1-》n的 n的一方实体(即是叶子结点绑定的值);树面板选择模型关系,根节点选择1-》n的 1的一方实体;
步骤3.节点配置;配置显示字段,选择想要的图标
# 自关联关系树
例如我们配置一个实体根据自己的父id自关联的选择下拉树
步骤1.建立自关联实体通过pid进行关联
步骤2.数据来源绑定实体选择自关联实体;树面板选择模型关系,根节点选择自关联实体;
步骤3.节点配置;配置显示字段,选择想要的图标
# json数据构建树
例如我们不建实体关系,想用静态json数据创建下拉树
步骤1.点击表单设置-》高级设置 -》变量 -》添加一个变量v_treeJson
其中children 为子级数组;type 给结点设置一个标记类型;
[{
"id":"10",
"label":"中国",
"value":"zg",
"children":[{
"id":"1",
"label":"上汽",
"value":"sq",
"type":"4S"},
{"id":"2",
"label":"吉利",
"value":"jl",
"type":"4S",
}]
}]
步骤2.树面板选择指定树形json ;指定树形json绑定刚才定义的变量v_treeJson;指定子级键名字端;节点类型设置可选节点的type类型(例如type:"4S")
例如想默认选中所有数据,点击勾选默认全选
前提:在静态数据且多选时
效果图:
# 2.展现方式
展示方式有树形 /层进;通过右侧展示模式选择配置
树形和层进展示样式
# 3.控制可选中节点
如果我们想控制哪些节点可选择;例如:我们要控制只能选择节点名称为上汽的节点,选择其他的节点给出错误提示
效果展示:
步骤1.可以在右侧配置项高级中添加事件选择allowSelect;
步骤2.编写控制代码
console.log(node, callback, 'node')
if (node.label !== '上汽') {
this.$message({
message: '请选择名称为上汽的数据',
type: 'warning'
});
//返回false;节点不可选择
callback(false)
}
else {
//返回true ;节点可选择
callback(true)
}
# 自动编号
例如我们想按照表单中的字段数据生成递增的编号;
根据不同供应商的code 递增的生成编号;
效果展示:
步骤1.编号规则配置选择字段 ,分组为供应商信息对应字段;
步骤2.编号规则配置选择自增,分组为供应商信息对应字段;
# 子表格
说明:子表格一般 绑定字段为实体1-》n自动生成的1:n数组;
# 1.编辑模式
在右侧配置项编辑模式中配置;可选 行内 、弹窗、 行内/弹窗
# 行内
点击新增,在子表格中出现一行编辑框
# 弹窗
点击新增,弹出一个编辑窗口
# 行内/弹窗
点击新增,弹出一个编辑窗口,点击子表格中已有的行数据,可以行内编辑
# 2.子表格编辑原理
为了方便看子表格中数据格式,可以在编码模式template下写代码,暂时调试页面 ;
# 新增时
当新增一条数据时,我们可以看到这条数据处了基本信息,还有一个额外的字段__operate_type:"add";标记此条数据是新增的;
# 删除时
当删除一条数据时,我们看到页面中子表格数据删除了但是子表格的数组长度并没有减1,这条删除记录还在,只不过有一个额外的字段**__operate_type:"delete"**;标记此条数据是删除的;
所以我们要注意,删除一条数据后,不能直接用子表格数据给其他数据赋值,要过滤掉__operate_type:"delete"的数据;
# 3.使用js修改子表格数据
例如在表单加载后给子表格数据赋值
效果展示
步骤1.点击表单设置-》点击高级设置-》事件-》选择表单加载后,给子表格字段赋值
this.formData.commoditys = [
{
"id": "4",
"code": "b1",
"name": "笔记本",
"supId": "2"
},
{
"id": "5",
"code": "b2",
"name": "工具刀",
"supId": "2"
},
{
"id": "6",
"code": "b3",
"name": "日历",
"supId": "2"
}
]
//注意:可能回遇到子表格数据直接修改但是页面子表格渲染并没有变化的现象;我们可以给子表格数据赋于一个新的数组对象,使其引用地址改变进而使子表格重新渲染;
//const newArr = [{id:'1',name:'aa'}]
//this.formData.commoditys = [...newArr]