使用应用开发平台的设计器开发业务对象,全程配置,简单易学,但不够灵活。
配置业务对象时使用的业务语意,需要预先定义,遇到未考虑的业务场景,则无法处理。
业务对象设计器,目标是实现常见的80%业务语意,利用开放的插件开发,实现剩余20%的功能。
界面加载、及用户与界面交互时,系统会调用插件接口方法,即触发插件事件,通知插件工作;
插件通过实现事件接口方法,捕获插件事件,完成对此事件的干预。
下一代金蝶云,是B/S结构的,使用不同的客户端(PC端、移动端),通过网络连接到统一的服务端。
用户看到的交互界面,是运行在客户端的,而业务逻辑和业务插件,则运行在服务端;
业务插件,也是运行在服务端,没办法直接获取到客户端界面上控件,不能直接控制前端控件。
但插件可以通过系统封装的视图模型接口IFormView,间接的访问、控制前端界面;
通过系统封装的各种控件代理对象,间接的访问、控制前端界面上的控件;这些运行在服务端的控件代理对象,称为控件编程模型,或简称为控件、编程模型等。
插件可以通过this.getView()方法,获取表单的视图模型接口实例;
可以通过this.getView().getControl(String key)方法,获取到控件编程模型实例;
表单的界面与数据,是分离:
- 界面显示在客户端浏览器或者移动端,在服务端会提供视图模型及;
- 数据存储在服务端,在服务端;
动态表单、单据、基础资料设计完毕,系统会为界面创建一个主实体模型,包含界面上全部的字段、单据体;
运行时,系统会基于主实体模型中的结构,创建一个界面数据包,存储用户在界面上录入的字段值;
另外,系统封装了数据模型接口,访问界面数据。
因此,完整的数据模型包含如下部分:
- 界面数据模型接口:IDataModel,提供了各种方法,访问界面数据;
- 主实体模型:MainEntityType,一个界面对应一个主实体模型,包含:
- 实体:EntityType,对应单据体、子单据体等;
- 属性:DynamicProperty,对应字段;
- 界面数据包:DynamicObject,包含界面各单据体、字段值;
不同的业务对象类型,提供特定的业务功能,有适用的应用场景。
系统为各种业务对象类型、各种应用场景,封装了相应的插件接口、事件方法,定义了抽象插件基类,实现最基本的插件接口。
进行业务功能设计时,首先需要根据业务需求特点,分析业务应用场景,选择业务对象类型;
如果需要进行插件开发,则根据前面确定好的业务对象类型及应用场景,从下表中选择对应插件基类进行扩展:
业务对象类型 | 应用场景 | 预置的Java插件基类 |
动态表单 | PC端界面 | AbstractFormPlugin |
移动端界面 | AbstractMobFormPlugin | |
单据 基础资料 | PC端界面 | AbstractBillPlugIn |
移动端界面 | AbstractMobBillPlugIn | |
单据列表 | AbstractListPlugin | |
树形单据列表 | AbstractTreeListPlugin | |
树形基础资料列表 | StandardTreeListPlugin | |
移动端单据列表 | AbstractMobListPlugin | |
业务操作 | AbstractOperationServicePlugIn | |
单据转换 | AbstractConvertPlugIn | |
关联反写 | AbstractWriteBackPlugIn | |
生成凭证 | AbstractBuildVchPlugin | |
报表 | 界面 | 暂缺 |
| 取数 | 暂缺 |
有交互界面的应用场景(如表单、单据列表等),在界面加载、关闭时,会触发相应的插件事件;
另外,用户与界面,以及界面上的控件交互时,也会触发插件事件。
各种控件有自己的功能特点,适用不同的业务需求,提供相应的插件事件;
在进行功能设计时,需要根据业务需求,选用合适的控件,确定需要重写的插件接口方法,响应插件事件。
后面的控件与字段章节,将详细列出各种控件的功能特定及支持的插件事件,供您参考。
- 特别说明:
没有交互界面的应用场景(如单据操作、单据转换、关联反写、生产凭证等),不会与用户发生交互,其插件事件是由服务引擎按顺序触发的。
这些应用场景,不需要关注事件源、控件;只需要根据业务需求,捕获合适的插件事件即可。
系统会在适当的时机,调用插件接口的方法,传入上下文参数,触发插件事件。
不同的插件事件,触发的时机、传入的上下文参数、可以控制的功能,差异非常大。
因此,必须根据业务需求,选择合适的插件事件响应。
后文会详细介绍各种应用场景、字段、控件,提供的插件事件,及其触发时机、事件参数。
本节介绍业务插件如何响应(捕捉)插件事件:
-
-
-
- 无交互界面的场景
-
-
没有交互界面的应用场景,插件基类已经实现了必要的插件接口,插件只需要扩展插件基类,重写事件方法即可完成事件的捕捉:
Java |
|
package kd.bos.metadata.botp;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn; import kd.bos.entity.plugin.args.BeforeOperationArgs;
public class WriteBackRuleOpPlug extends AbstractOperationServicePlugIn { @Override public void beforeExecuteOperationTransaction(BeforeOperationArgs e) { // TODO : 在此添加业务逻辑 } } |
说明:插件基类AbstractOperationServicePlugIn已经实现业务操作插件接口,插件直接重写需要响应的事件方法即可。
-
-
-
- 有交互界面的场景
-
-
有交互界面的应用场景,插件基类实现了表单界面支持的插件接口,但没有实现各种控件的插件接口。
如果只是要捕获表单界面事件,则扩展插件基类,重写表单事件方法即可。
如果要捕获各种控件事件,则需要:
- 在插件类定义,实现控件支持的插件事件接口,例如树形控件支持的节点勾选插件事件接口TreeNodeCheckListener;
- 实现控件的插件事件接口中的方法,完成事件的捕捉;
- 在表单界面插件registerListener事件,向控件实例注册本插件实例,完成控件与插件实例的绑定:控件事件发生时,即触发其所绑定的插件事件;
如下例,插件需要响应树形控件的节点勾选treeNodeCheck事件:
Java |
|
package kd.bos.plugin.sample.dynamicform.pcform.control.template;
import java.util.EventObject; import java.util.List;
import kd.bos.dataentity.utils.StringUtils; import kd.bos.form.control.TreeView; import kd.bos.form.control.events.TreeNodeCheckEvent; import kd.bos.form.control.events.TreeNodeCheckListener; import kd.bos.form.plugin.AbstractFormPlugin;
public class TreeViewTreeNodeCheck extends AbstractFormPlugin implements TreeNodeCheckListener {
private final static String KEY_TREEVIEW1 = "treeviewap1";
@Override public void registerListener(EventObject e) { super.registerListener(e);
// 侦听树节点勾选事件 TreeView treeView = this.getView().getControl(KEY_TREEVIEW1); treeView.addTreeNodeCheckListener(this); }
@Override public void beforeBindData(EventObject e) { super.beforeBindData(e); TreeView treeView = this.getView().getControl(KEY_TREEVIEW1); treeView.setMulti(true); // 支持多选 }
@Override public void treeNodeCheck(TreeNodeCheckEvent arg0) { TreeView treeView = (TreeView) arg0.getSource(); if (StringUtils.equals(treeView.getKey(), KEY_TREEVIEW1)){ List<String> selectNodeIds = treeView.getTreeState().getCheckedNodeIds(); // TODO 在此添加业务逻辑 } } } |
说明:插件基类AbstractFormPlugin没有实现树形控件的节点点击事件接口TreeNodeCheckListener,插件需要自行实现。