前两章节介绍了表单控件相关的脚本开发能力,通过脚本控制表单控件基本行为,设置与获取控件绑定的数据对象等;本章进一步介绍表单控件的事件机制,与事件绑定操作的脚本扩展能力。本章介绍表单控件的事件机制,与事件绑定操作的脚本扩展能力。
同时本章还补充介绍前端调用restful API、文件下载、DWF表单打开、对象数据查询与动态参数控件等高级脚本能力。
1. 脚本基础
...
1脚本基础
(一)表单控件事件机制
事件(Event)是UI页面重要概念,负责响应用户与页面元素的交互,常见的UI事件如表格控件行单双击事件、文本框值修改事件、文本框鼠标失去焦点事件、鼠标悬停事件等;DWF的表单定制过程也支持这些事件的定义,只是不同的表单控件所支持事件类型不一样,如表格控件所支持单双击事件,在文本框控件中就没有,而文本框只有值改变、鼠标获取焦点与失去焦点等事件;DWF大部分控件都封装支持了事件,而且事件绑定的操作也能基于脚本进行二次开发扩展,DWF表单中控件事件定义示例如下图所示:
...
如上列举了DWF表单中常用的”文本控件“与”表格控件“的事件支持,其它表单控件的事件支持就不展开说明。
...
(二)前端restful接口调用
DWF是前后端分离的体系结构,前端通过restful API调用后端。在登录DWF后,点击右上角的“API说明”可获得restful API的详细说明。
...
(1)modeler模型服务 restful API,通过下面的函数调用模型服务,从而操控DWF模型数据:
this.dwf_modeler_axios()函数是DWF模型restful 服务脚本调用总入口,该脚本调用示例说明如下:
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
//获取当前登录用户 var curUserId = this.user.userId; //调用的参数,参见API说明 let param = { }; //调用modeler端的restful API this.dwf_modeler_axios(`/dwf/v1/org/users/${curUserId}/groups`).then(rtnOBJ => { // 在回调中处理rtnOBJ值… this.msgbox.success("调用成功"); }); |
...
(2)app对象服务 restful API,通过下面的函数调用对象服务,从而超控DWF所有的业务对象数据:
this.dwf_axios()函数是DWF对象restful 服务脚本调用总入口,该脚本调用示例说明如下:
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
let param = { }; this.dwf_axios.post(`/dwf/v1/omf/entities/${this.className}/objects/count`,param).then(initRes => { //在回调中处理 this.msgbox.success("调用成功"); }); |
...
(3)通用restful API,需要调用DWF之外的其它restful API时,可使用以下函数:
this.axios()函数是DWF之外其它异构的restful 服务脚本调用总入口,调用其它通用的restful 服务器时要注意,即不要将ip地址和端口号写死,否则服务器迁移功能就会失效,可以使用“this.env.serverIp”和地址无关来实现动态调用,该脚本调用示例说明如下:
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
//调用其它服务器的restful API var curServerIP = this.env.serverIp; var param = {…}; this.axios.post(`${curServerIP}/[其他接入点路径]`,param).then(rtnOBJ => { //回调处理… this.msgbox.success("调用成功"); }); |
...
(三)文件下载
文件下载是比较常见的功能需求,DWF单对象表单是已支持通过”附件“控件实现文件(包括图片)的上传、下载与在线浏览功能,但有时在多对象控件或其它页面中存在使用DWF”附件“控件之外的文件下载需求,此时就需要利用的文件下载的脚本能力,如下所示”下载“设备图片的脚本示例:
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
clientScript: if (this.selectedObjs && this.selectedObjs.length > 0){ console.log(this); fileURL=`http://${this.env.serverIp}:9090/dwf/v1/omf/classes/${this.className}/objects/${this.selectedObjs[0].oid}/attributes/assetImg/bytes?attachment=true&0`; console.log(fileURL) window.open(fileURL); } |
...
(四)脚本中动态执行其他操作
存在这种情况,希望在脚本中动态执行一些其他操作,例如:在前端脚本中根据对象所处的状态,打开不同类型的其他表单,此时可以通过下面的调用完成目标:
...
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
this.getOperation('Asset', 'oprAi').then(res => { var operation = res.data.data; this.executeOperation(operation).then((opr) => { this.freshData() }); }) |
...
(五)对象数据查询
DWF前端提供灵活的业务数据查询脚本API,这里对常见的实体类对象查询API进行说明,如下脚本示例,其中说明了”ES6字符串转换机制“与”this.handleQueryData()“函数调用:
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
//查询条件 let queryConditon = { targetClass:"Part", query:{query:`and obj.id='${this.obj.name}'`}, //ES6字符串转换机制,即在``中间变量可通过${}引入; fresh: true //是否从后台强制刷新查询 }; //进行后端数据查询,在回调函数中处理查询结果 this.handleQueryData(queryConditon).then(res => { //针对res值(查询返回值)直接处理… }); |
...
(六)动态参数控件
动态参数控件作用是运行时通过动态传入Form表单的UI元素(属性字段)构成,即时根据传入渲染出表单页面,然后手动录入值后再通过脚本获取录入的数据对象,最后脚本再灵活处理这些数据,如新增或修改保存到系统中;该控件在脚本中有比较灵活的应用场景,支持在modeler中少定制很多表单,而是通过脚本逻辑动态构造表单UI元素Schema构成,具体动态参数控件使用与脚本处理如下示例:
图-表单中定义动态参数控件
...
(1)动态参数控件基础
- 控件页面显示字段元数据设置
- 字段必选属性
- name:字段名称
- value:字段取值
- 字段扩展属性
- type:数据类型,具体支持常用的”int/整形"、”datetime/日期“与”string/字符串“等
- default:缺省值,需要和数据类型匹配
- label:页面中字段显示名
- required:布尔值,表示对应参数是否必须填写
- tips:字符串,给用户的提示文本
- 字段必选属性
- 控件布局方式:
- 表格(多列)布局:即多字段按照水平从左至右(支持2列/3列/4列设置)垂直从上至下顺序布局,
- 垂直浮动布局:即多字段按照垂直从上至下水平固定一列浮动布局。
- 控件脚本函数:
- addin.setValue():作用是设置控件的页面显示字段元数据,脚本示例:[{"name": "name","label":"商品名称" ,"type": "string", "tips":"请输入","default":"","required": true},{...}]
- addin.getValue():作用是获取控件的页面显示字段所有数据,包括元素据与具体value值,脚本返回示例如:[{"name": "name","label":"商品名称" ,"type": "string", "tips":"请输入","default":"","required": true,"value": "桌子"},{...}]
- addin.getKVValue():作用是获取控件的页面字段对应的Key/Value键值对json集合对象,即不包括元素据,脚本返回示例如:{"number": 1,"date":"2020-03-01 10:30:00" ,"name": "桌子", "price":100,"type":"家具","description": "测试数据..."}
...
(2)动态参数控件脚本示例
上图中”设置动态参数Schema“按钮操作,通过如下脚本执行,即时渲染出的表单控件显示页面如下所示:
...
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
clientScript: //动态参数控件对象 var addin = this.getAddinById('C70A786EDBB04E3B99CC2F8AF26F67E0'); //获取控件全部数据(包括原schema与新输入值) var formValue = addin.getValue(); /*获取控件KV键值对数据,即不包括原schema元数据,返回数据如下: {"number": 1,"date":"2020-03-01 10:30:00" ,"name": "桌子", "price":100,"type":"家具","description": "测试数据..."} */ var formOBJ = addin.getKVValue(); //TODO:针对formOBJ的后续处理 |
...
脚本案例
在设备管理案例中,设备详情页中针对产品结构部位选择联动设备的工单列表,在教学案例设备管理模块中有个”设备详情页“,如下图所示,该页面上侧为设备基础属性区,左下为设备的产品结构显示区,右下为设备的工单列表区。本案例主要介绍左树右表控制工单自动刷新的场景。
图-设备详情页及树节点单击事件定义
...
(一)设备管理中工单与设备及零部件的模型关系
图-设备管理数据模型
通过上面树模型类图,可了解到工单(WorkOrder)有”故障设备(assetOid)“与”故障部位(partOid)"两个属性,其中“故障部位”允许为空,但“故障设备”不能为空;
一个“设备(Asset)”存在多个“工单(WorkOrder)”,如果同时故障部位不为空,那么表示相同“设备(Asset)”与“部位(Part)”也可存在多个“工单(WorkOrder)”。
...
(二)右下侧工单列表刷新显示逻辑
通过上面的“设备管理数据模型”截图与“设备详情页”截图,可理解如果不选择产品结构中的“部位”,那么右(下)侧工单列表的过滤逻辑仅与当前设备相关,如果选择产品结构中部位后,会多增加基于“部位”的二次工单过滤,如下图所示:
...
信息 |
---|
上图中表格过滤条件(“and obj.assetOid = '$obj.oid'” )通过表单自带的“过滤条件生成器”交互产生,其中“ obj.”表示对应的数据库中的工单表,其中“$obj.oid”表示当前设备对象变量。 |
...
(三)左侧设备部位结构树节点选择事件脚本
上图中如果不选择左侧设备部位树节点,那么右侧的工单列表会显示所有故障设备为与当前设备的所有工单,但如果选择了左侧“故障部位”导航树的部位,那么右侧工单列表会过滤刷新,即仅显示工单故障部位为当前左侧导航树所选部位的工单;左侧设备部位树提供了树节点单击选择事件机制,且树节点单击选择事件的脚本可绑定开发脚本,通过脚本可灵活处理表单特定逻辑,如下面脚本示意了通过树节点单击选择事件刷新右侧工单列表;
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
clientScript: //左下侧的产品结构表示(工单涉及)部位的树 tree = this.getAddinById("5E181498CEC545B1B6FA571B5DB68532"); //右下侧的工单列表 list = this.getAddinById("847A1B03A10642BE9C8740E942751D6B"); console.log("tree:",tree); //前端调试输出 nodes = tree.getSelected(); //导航树所选部位节点 if (nodes.length > 0){ console.log("nodes:", nodes) if ('relation_rightOid' in nodes[0]){//判断选择的是非根节点 /*两个过滤条件,除了所属设备(obj.assettOid),还需所属部位(obj.partOid) 其中${nodes[0].right_id},表示当前所选产品结构树的零部件节点,且取其中一个节点, 节点对象实际绑定的关系对象,因此right_id是具体子件的id;*/ list.freshData(`and obj.assettOid = '${this.obj.oid}' and obj.partOid like '${nodes[0].right_id}%'`); } else {//判断选择的是根节点 //表示工单不体现(零部件)部位,只与整体设备相关 list.freshData(`and obj.assettOid = '${this.obj.oid}'`); } } |
...
小结
本章主要介绍了表单控件事件机制与相关的高级脚本能力,重点需掌握如下相关的脚本基础:
...
本章是前端脚本介绍最后一章,下一章开始介绍后端脚本能力与典型案例场景说明。
...
示例模型包
View file | ||||
---|---|---|---|---|
|
View file | ||||
---|---|---|---|---|
|