SWF(V6)开发指南
第1章 前言本文档描述基于SWF(V6)的工作流开发。
第2章 概述SWF V6基于EIPV6,其开发有如下特点:
1、工作流API均以Javasript函数的形式提供。
2、EIPService.getWfService()依然可以使用,但不建议supp_eip_swf组件之外的其他组件使用。
3、业务组件的提交流程(启动流程实例)、选择下一步承担人、结束活动等等 *** 作,只需调用一次SWF提供的JS方法。
4、SWF组件负责组织和传递“活动实例ID”等工作流常用参数,因此业务组件开发人员不必再在界面上获取、存储这些参数,以及在提交时再逐一获取并加入Ajax的参数中,从而可以有效地减轻开发人员的工作量。
5、以前版本需要由业务组件代码设置一些值到流程变量中,并由工作流保存和访问。在SWF V6中将流程变量分为两个部分:1、业务实体属性值;2、非业务实体属性值。其中业务实体属性值将不再保存到工作流的“流程变量表”中,而是由业务组件实现“业务实体属性值容器”来提供,从而减少了大量不必要的数据库记录插入、更新 *** 作,并可以避免业务属性值与对应流程变量(例如业务实体的“金额”与流程变量中的“金额”)可能不一致的问题。
流程定义部分暂略。
3.2 流程运行所涉及的开发 3.2.1 总述引入supp_swf.js
SWF
以javascript
形式提供的API均在…\eip\swf\js\supp_swf.js中,因此请在涉及流程 *** 作的页面需引入该文件,放在本页面js的后边,以免找不到流程相关的函数。这一点非常重要。
例如:
<script type="text/javascript">
LoadJS([
"/eip/swf/js/supp_swf.js",
],
true);
</script>
注意!
1、流程开发先要在应用配置好流程相关信息。
2、流程相关功能的API类如Supp.EIP.WF.XXX
👉业务单页面的规划
⭐新增与编辑是同一个页面文件、查看是一个页面文件,加流程时常用的情况如下:
新增与编辑页面: 增加【提交】按钮,是添加流程功能的第一步;列表页面:增加【流程跟催】按钮给最终用户使用,增加【流程管理】按钮给管理员使用;审核页面单独开发或者在查看或编辑页面上做: 增加【同意】【不同意】【高级审核】按钮,给审核人使用; 注意事项:由于高级审核在右侧时会挤占业务表单的区域,所以业务表单在开发时最多占80%的宽度,直接预留于流程高级审核的宽度。查看页面或单独提供知会或抄送的页面: 增加【好的,我知道了】给知会人、 *** 作人使用;重新提交页面可基于编辑页面也可以直接使用编辑页面:增加【放弃申请】【发起新申请】按钮,给申请人使用。⭐示例新闻动态样例功能各页面对应流程页面情况如下:
流程页面 | 物理文件 |
---|---|
申请页面 | news_addOrEdit.html |
重新提交页面 | news_addOrEdit.html |
审核页面 | news_audit_view_swf.html |
知会与抄送页面 | news_audit_view_swf.html |
列表页面 | news_list.html |
⭐流程相关按钮的i18n名称一览表
说明 | i18n |
---|---|
text : $.i18n.prop(“button-submit”, “提交”), | button-submit |
text : $.i18n.prop(“button-passProc”, “同意”), | button-passProc |
text : $.i18n.prop(“button-rejectProc”, “不同意”), | button-rejectProc |
text : $.i18n.prop(“button-advancedProc”, “高级审核”), | button-advancedProc |
text : $.i18n.prop(“button-okIKnowProc”, “好的,我知道了”), | button-okIKnowProc |
text : $.i18n.prop(“button-abort”, “放弃申请”), | button-abort |
text : $.i18n.prop(“button-resubmitProc”, “重新提交”) | button-resubmitProc |
text : $.i18n.prop(“button-newSubmitProc”, “发起新申请”), | button-newSubmitProc |
text : $.i18n.prop(“button-viewProcExam”, “查看审核意见”) | button-viewProcExam |
text : $.i18n.prop(“button-procTrace”, “流程跟催”), | button-procTrace |
text:$.i18n.prop(“button-procManage”, “流程管理”), | button-procManage |
流程跟催
Supp.EIP.WF.procTrace(procId);
用于普通用户查看并了解流程进度,可以发送提醒给当前待审核人,可以进行流程撤回 *** 作,还可以查看到流程更多的信息,若业务单发起过多次,还可以查看历次提交记录,甚至按照业务数据跨流程跟踪审核进度,主要服务于业务单的申请人或参与审核的人。
流程管理
Supp.EIP.WF.procManage(procId);
用于管理员监控与管理这个流程实例,包括:更换承担人,强制跳转、中止流程等管理功能,以及查看流程实例信息等监控功能。主要服务于业务管理员。
以前老系统管理员需要在独立的后台管理页面才能 *** 作,这次改进到业务单列表中增加了“流程管理” *** 作,可以发挥业务单列表页面的查询功能,使管理员更方便的定位到业务单,所见即所得的方式便可以进行流程管理。
⭐参考代码
{
id : "procTraceBtn",
text : $.i18n.prop("button-procTrace", "流程跟催"),
icon : "../../common/img/follow.png",
handler : function() {
var ids = Supp.EIP.Module.getJqgridSelectIds(JQGRID_ID);
if (ids.length == 1) {
var rowdata = Supp.EIP.Module.getJqgridRowdata(JQGRID_ID, ids[0]);
var procId = rowdata.procId;
if (procId == "" || procId == undefined) {
Supp.showWarning("业务单没有流程启动的记录!");
return;
}
Supp.EIP.WF.procTrace(procId);
} else {
Supp.showWarning("请选中一行进行 *** 作!");
}
},
{
id : "processManage",
text:$.i18n.prop("button-procManage", "流程管理"),
icon:"../../common/img/processM.png",
handler : function() {
var ids = Supp.EIP.Module.getJqgridSelectIds(JQGRID_ID);
if (ids.length == 1) {
var rowdata = Supp.EIP.Module.getJqgridRowdata(JQGRID_ID, ids[0]);
var procId = rowdata.procId;
if (procId == "" || procId == undefined) {
Supp.showWarning("业务单没有流程启动的记录!");
return;
}
Supp.EIP.WF.procManage(procId);
} else {
Supp.showWarning("请选中一行进行 *** 作!");
}
}
}
流程管理需要进行权限控制,前台页面的控制需要借助APP结构说明书中页面元素的注册。前台页面如果是load进来的页面,需要额外引入supp-eip-auth.js
,其他的因为大家同时通过LoadJS加载的js文件,这个里面自动引入了权限校验的js。
业务单中不再包括流程相关的属性(如: 选择流程),当用户完成业务数据表单的填制后,确定要提交申请时,点击【提交】按钮,将d出由流程引擎模块提供的启动流程对话框,完成流程启动后,由流程引擎通过JS返回值的方式将流程启动是否成功的结果给业务表单,当成功时,建议跳转到成功提示页面(由业务模块自己做),失败或取消 *** 作时停留在当前页面。详细说明如下:
👇申请页面按钮设计建议
申请页面一般只提供【提交】按钮,需要注意:提交前线执行保存。
Step1: 先做提交前的前台验证。
有些模块保存的难与提交的验证不同,提交时的检查更为严格,所以此处需要做的是前台可进行的提交前的检查;
Step2: 完成业务单的保存,以及后台要执行的提交前的验证。
无论是否可提交,均先执行保存动作。若保存不成功,则前台直接提示,不必往下进行了。保存成功后,若有一些提交前的验证是后台才可以进行的,则执行后台的检查,如果检查不通过,则作为 *** 作失败返回前台,并提示失败原因。
Step3: 调用工作流引擎提供的启动流程JS。
当调用此JS后,工作流引擎会根据当前业务单的信息查找可使用的流程,并默认选中第一个可用流程,d出询问对话框,请用户确认,此时用户可以放弃 *** 作,继续回到业务单的编辑页面;点击【确定】真正的发起申请,若没有可用的流程,由工作流引擎负责d出错误提示对话框;若出现错误,则工作流引擎会d出提示框显示出错的原因;若流程在启动过程中出现了异常,则工作流会回调业务声明的失败时的执行的JS方法;若成功启动流程,则回调业务声明的成功时执行的JS方法。
startProc
/**API
*启动流程.
* @param busiJson 业务单集合json数据(必填)
* @param success 成功后的回调函数(非必填)
* @param error 失败后的回调函数(非必填)
*/
function startProc(busiJson, success, error)
关于busiJson,要求使用工作流引擎提供的JS对象来构造后再传换为JSON对象传入,WfParms对象在supp_swf.js中定义如下:
/**
* 声明流程用到的对象
*/
var WfParms = function() {
//年度
var dbYear = "";
//应用id
var moduleId = "";
//业务对象id
var domainObjectId = "";
//公司编号
var companyNo = "";
//业务单id
var entityId = "";
//业务类型
var moduleBusiType = "";
//业务类名称
var entityName = "";
}
再使用getProcBusiJson方法将wfParms转化为json
/**
* 拼接业务json对象
* wfParms 业务对象
*
*/
function getProcBusiJson(wfParms)
代码示例
<!--创建按钮 -->
<div class="footerButton">
<div id="swfSubmitBtn" class="divButton"></div>
</div>
/**
* 创建页面的按钮
* @param data 对象信息
* @author gongjiwen
*/
function createButton(data) {
new Supp.Button({
type : "edit",
text : $.i18n.prop("button-submit", "提交"),
readerTo : "swfSubmitBtn",
handler : function() {
swfSubmitAudit();
}
})
}
//提交按钮执行方法
function swfSubmitAudit() {
//#2 保存后执行
function startProcSwf(resp){
//流程启动
var obj = resp.body;
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
Supp.EIP.WF.startProc(busiJson, function success(data) {
//刷新父窗口的grid
Supp.Util.refreshTabGrid(listTabId,tableId);
//关闭当前窗口(此处各业务按需开发)
Supp.EIP.Desktop.closeWindow();
}, function error() {
Supp.showWarning("流程启动失败!");
});
}
// #1:先走保存业务数据的方法
saveOrUpdate(startProcSwf);
}
以上便完成了流程的启动。业务在流程启动成功之后若要更新状态,则需通过流程定义:申请节点申请成功后的事件中配置动作,动作类应是IExecHandler接口的实现类完成业务单据状态修改等 *** 作(未来工作流引擎将提供标准动作,减少业务模块的定制开发量)。
3.2.4 审核页面审核按钮动态 设计说明在SWF V6中,上图的同意,不同意,高级审核按钮的名称根据业务的需求可能有所不同,比如同意叫拟同意,现在提供审核设置流程可可控制的 *** 作。
可控制内容:
1、审批按钮是否显示
2、审批按钮名称可配置
3、进入审核页面自动打开高级审核区域
/**
* 构造业务审批按钮
* @param buttonJson 生成按钮json
*/
swf.getOperationButton = function(buttonJson)
代码示例
注意!
1、下边这种的创建按钮的方式不是高级审批的方式,下边有同意、不同意、更多…等按钮
var buttonJson = {
passedBtn:"passBtn",
passedFun:function() {
Supp.EIP.WF.pass(busiJson, function successCallBack(json) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
}, function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
});
},
rejectedBtn:"rejectBtn",
rejectedFun:function() {
Supp.EIP.WF.reject(busiJson, function successCallBack(json) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
}, function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
});
},
advancedExamBtn:"advancedBtn",
advancedExamFun:function() {
//高级审核add by liug
Supp.EIP.WF.advancedExam(busiJson,
function successCallBack(json) {
Supp.EIP.Desktop.closeWindow();
}, function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
}
);
}
};
Supp.EIP.WF.getOperationButton(buttonJson);
3.2.5 审核页面
审核页面按钮设计建议
跟流程有关的主要有:同意、不同意、高级审核三个,高级审核点击后会根据应用配置中的布局设置出现在右侧或底部。
审核功能开发说明
同意
在SWF V6中,“同意” *** 作表示的是“选择前进方向并流向下一节点”,因此无论在流程定义中当前节点有多少离开转移(连接到其他节点的“线”),都按如下逻辑来判断:
如果用户要执行“同意” *** 作,那么将从当前节点的前进性质(正向)的转移中选择一条;如果只有一条离开转移线则不管该线是否前进方向都会无条件地被选择。
用户点击“同意”时,调用pass(…)函数即可。
/**
* 同意.
* @param busiJson 业务json字符串
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*
*/
function pass(busiJson, successCallBack, errorCallBack)
注:“活动实例ID”等参数会由supp_swf.js通过Supp.Util.getUrlParams()等获取,业务组件不必再负责“活动实例ID”、“待办事宜ID”等参数的组织和传递。
👇代码示例
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
//调用pass()函数来完成“同意” *** 作
Supp.EIP.WF.pass(busiJson,
function successCallBack(json) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
}
);
不同意(驳回)
在SWF V6中,“不同意(驳回)” *** 作表示的是“选择后退方向并流向下一节点”,因此无论在流程定义中当前节点有多少离开转移(连接到其他节点的“线”),都按如下逻辑来判断:
如果用户要执行“不同意(驳回)” *** 作,那么将从当前节点的后退性质(反向)的转移中选择一条;如果只有一条离开转移线则不管该线是否前进方向都会无条件地被选择。
用户点击“不同意(驳回)”按钮时,调用reject (…)函数即可。
API说明
/**
* 不同意(驳回).
* @param busiJson 业务json字符串
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*/
function reject(busiJson, successCallBack, errorCallBack)
代码示例
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
//调用reject()函数来完成“不同意” *** 作
Supp.EIP.WF.reject(busiJson,
function successCallBack(json) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
}
);
高级审核
用户可能会希望在审批表格中输入审批意见等等 *** 作,此时可以点击界面上的“高级审核”按钮。此功能将展示类似之前SWF版本的“审批表格”的功能。
用户点击“高级审核”之后所需要完成的 *** 作只需调用advancedExam(…)函数即可。
** API说明**
/**
* 高级审核.
* @param busiJson 业务json字符串
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*/
function advancedExam(busiJson, successCallBack, errorCallBack)
代码示例
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
Supp.EIP.WF.advancedExam(busiJson,
function successCallBack(json) {
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
}
);
3.2.6 知会与抄送页面
知会和抄送功能开发说明
在“知会”和“抄送”性质的界面上,需要提供“好的,我知道了”之类的按钮,用户点击之后就可以将相应的知会或抄送的待办事宜记录清除。
此功能只需调用confirmNotice (…)函数即可。
完成知会和抄送
/**
* 完成知会和抄送
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*/
function confirmNotice(successCallBack, errorCallBack)
Supp.EIP.WF.confirmNotice(
function successCallBack(json) {
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
}
);
3.2.7 重新提交页面
API说明
重新提交
/**
* 重新提交
* @param busiJson 业务json字符串
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*
*/
function resubmit(busiJson, successCallBack, errorCallBack)
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
//调用resubmit()函数来完成“重新提交” *** 作
Supp.EIP.WF.resubmit(busiJson,
function successCallBack(json) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
}
);
放弃申请
业务单申请人可以执行“放弃申请”,此 *** 作将执行“中止流程实例”的 *** 作。
此功能只需调用abortProc (…)函数即可。
/**
* 放弃申请
* @param successCallBack 成功回调函数
* @param errorCallBack 失败回调函
*
*/
function abortProc(successCallBack, errorCallBack)
Supp.EIP.WF.abortProc(
function successCallBack(json) {
Supp.EIP.Desktop.closeWindow();
},
function errorCallBack(json) {
Supp.alert("放弃申请失败!", Supp.alert.type.error);
}
);
发起新申请
针对已经放弃过申请的业务单,业务单申请人可以执行“发起新申请”。
此功能只需调用restartProc (…)函数即可。
API说明
/**
*/
function restartProc(busiJson, successCallBack, errorCallBack)
代码示例
var obj = resp.body;
//声明流程用到的对象
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = obj.dbYear;
parms.moduleId = obj.moduleId;
parms.domainObjectId = obj.domainObjectId;
parms.entityId = obj.newsId;
parms.companyNo = obj.companyNo;
parms.moduleBusiType = obj.moduleBusiType;
parms.entityName = obj.entityName;
//转换成流程用到的json格式的对象
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
//重新启动流程
Supp.EIP.WF.restartProc(busiJson,
function success(data) {
//关闭当前窗口
Supp.EIP.Desktop.closeWindow();
},
function error() {
Supp.showWarning(“流程启动失败.”);
});
查看审批意见
界面上可提供“查看审批意见”来显示已经存在的审批意见列表。
此功能只需调用viewProcExam (…)函数即可。
API说明
/**
*/
function viewProcExam()
代码示例
Supp.EIP.WF.viewProcExam (
function successCallBack(json) {},
function errorCallBack(json) {}
);
3.3 业务实体属性值容器(涉及的后台相关)
3.3.1 总述
在SWF V6之前的版本需要由业务组件代码设置一些值到流程变量中,并由工作流保存和访问,因此在流程启动时要执行多次流程变量设置的 *** 作。这种方式会导致工作流的“流程变量表”的记录很多,且存在频繁的查询和插入/更新 *** 作。
在SWF V6中将流程变量分为两个部分:1、业务实体属性值;2、非业务实体属性值。其中业务实体属性值部分将不再保存到工作流的“流程变量表”中,而是由业务组件实现“业务实体属性值容器”来提供,从而减少了大量不必要的数据库记录插入、更新 *** 作,并可以避免业务属性值与对应流程变量(例如业务实体的“金额”与流程变量中的“金额”)可能不一致的问题。
3.3.2 API说明
业务模块提供流程变量值的容器类,方法为继承AbstractPropRetriever类,流程中用到流程变量的地方会调用这里,在实际开发中需要继承这个类,并实现里面的方法。
package com.supporter.prj.eip.busi_entity.service;
/**
*/
public abstract class AbstractPropRetriever implements IPropRetriever, Cloneable {。。。}
继承后主要实现的内容:
/**
* 注入需要使用的Service.
/
@Autowired
private NewsService service;
/*
* 返回本实例所服务的业务实体类.
*/
@Override
public String getId() {
return News.class.getName();
}
@Override
protected Object getEntity(int budgetYear, Object entityId) {
String borrowId = (String) entityId;
return service.get(borrowId);
}
@Override
protected List < ? > getExtTableEntities(int dbYear, Object entityId) {
//注:在本场合中没有扩展表,直接返回null即可. 如果存在扩展表,那么逐一获取并加入一个List然后返回即可.
return null;
}
注意:
1、getId ,单一主表就可以满足流程变量的需求时,这里返回主表对应的业务实体类。如果业务有多张表时,此处可以返回业务对象ID值。要保证这个值在全系统的唯一,不可重复,这个值只有两个结果,要么是业务单实体类全路径,要么是业务对象ID,请不要返回其他值。
2、一定要使用@Service注解本类
3.3.3 代码示例
package com.supporter.prj.eip.news.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.supporter.prj.eip.busi_entity.service.AbstractPropRetriever;
import com.supporter.prj.meip_service.news.entity.News;
/**
News的IPropRetriever实现类.@author Arnold/
@Service
public class NewsPropRetriever extends AbstractPropRetriever {
/*
* 注入需要使用的Service.
/
@Autowired
private NewsService service;
/*
* 返回本实例所服务的业务实体类.
*/
@Override
public String getId() {
return News.class.getName();
}
@Override
protected Object getEntity(int budgetYear, Object entityId) {
String borrowId = (String) entityId;
return service.get(borrowId);
}
}
3.4 流程动作实现类(IExecHandler实现类)
3.4.1 总述
流程动作实现类的目的是用于执行一些特定的 *** 作,例如修改流程变量、修改业务单据的状态或其他属性值、发送JMS消息等等。其用法如下:
1、在业务组件中编写IExecHandler的实现类;
2、在“应用管理”(supp_eip_module)中注册;
3、在流程定义中的“动作设置”中配置。
经过以上三步就可以灵活地指定在流程实例运行的某个瞬间(例如离开某个节点、流程结束或者被中止时等等)完成某个特定的动作。
3.4.2 API说明
动作实现类要求实现IExecHandler接口或继承com.supporter.prj.eip_service.workflow.AbstractExecHandler抽象类(推荐的方式)。com.supporter.prj.eip_service.workflow.AbstractExecHandler中需要实现
的有三个方法:
import com.supporter.prj.eip_service.workflow.AbstractExecHandler;
import com.supporter.prj.eip_service.workflow.ExecContext;
/**
*/
public class DemoHandlerForIncreasingBudgetAmount extends AbstractExecHandler {
@Override
public String getDesc() {
return “”;
}
@Override
public Object execute(ExecContext execContext) {
}
@Override
public void executeProcVars(ExecContext execContext) {
}
3.4.3 代码示例
可以参见新闻动态的三个Handler实现类。
注:
1、executeProcVars(ExecContext execContext)方法说明
专门用于模拟计算流程下一步路径时执行的方法。与前面execute方法的区别是,只更新内存中的变量值,并未修改数据库中的任何值,对真实业务不会产生任何实际的影响。例如:动作是要执行一些业务逻辑处理,如:生成待支付,则只需写在execute方法中,本方法应该是空的方法体或者直接返回null。若当前动作需更改流程变量,在模拟计算流程下一步时,只需更改上下文环境变量中的该变量值。例如:获取员工级别,计算出员工级别后,将结果put到execContext中,而不是真正修改数据库中的流程变量值。
2、如果希望获取业务组件的某个Service实例,可以通过SpringContextHolder.getBean(???Service.class)的形式获取,但请注意不要出现跨组件调用类的情况。
3、工作流的事务是基于APP库的,如果动作实现类中是对其他库(例如年库)的 *** 作,将无法保证事务性,请采用其他方式(例如引入TCC柔性事务)来保证数据一致性。
4、ExecContext execContext是当前运行过程中储存流程变量值的一个容器在(Map),仅在本次请求中有效,当请求执行完成,下次请求时会重新初始化,常见的用法是获得流程中业务主键值((String) execContext.getProcVar(“newsId”);)、获得流程实例ID(String getProcId();)、获得指定变量的值(execContext.getProcVar(“变量名”);)、设置更新execContext中指定变量的值(void setProcVar(String procVarName, Object procVarVal);)
/**
用于示例将流程变量增加500.
*/
public class DemoHandlerForIncreasingBudgetAmount extends AbstractExecHandler {
@Override
public String getDesc() {
return “将budgetAmount流程变量增加500”;
}
@Override
public Object execute(ExecContext execContext) {
final int INCR_AMOUNT = 500;
String procVarName = "budgetAmount";
double budgetAmount = execContext.getProcVarDouble(procVarName);
double newAmount = budgetAmount + INCR_AMOUNT;
System.out.println("执行:" + this.getClass().getName() + ":" + getDesc() + ", budgetAmount的新值为:" + newAmount);
execContext.setProcVar(procVarName, newAmount);
return null;
}
3.4.4:补充(非公司文档说明,项目中出现的问题)
没有查到已办业务单错误信息的原因,service中没有实现已办查询的方法。
代码示例:
@Service
public class OveBimRepViewProvider implements IBusiEntityViewerProvider{//实现这个接口
@Override
public String getId() {
return OverseasBimonthlyReportEntity.class.getName();//实体类名称
}
@Override
public String getViewerUrl(int dbYer, Object entityId) {//年度 主键
//已办查看页面
return “/oa/overseas_bimonthly_report/overseas_bimonthly_report_view.html?reportId=”+entityId;
}
}
1.1 流程适用范围开发
1.1.1 编辑页面
页面编号:proc_def_busi_auth_panel
页面名称:流程业务适用范围
页面URL:
/eip/swf/busi_auth/busi_auth.html?moduleId=#{moduleId}&busiType=#{busiType}
说明:
1.1.2 查看页面
页面编号:proc_def_busi_auth_panel_view
页面名称:流程业务适用范围
页面URL:
/eip/swf/busi_auth/busi_auth_view.html?moduleId=#{moduleId}&busiType=#{busiType}
4.1关于中国电工项目的流程事项
中电项目统一采用高级审批的方式,审批页面底部按钮上方需要添加审批意见和高级审批区域。
页面添加高级审批的div:
Js页面添加加载审批页面div的代码:
注意:需要传入流程ID👇
var url = Supp.Util.getSystemUrl() + “eip/swf/widget/his_exam_list_cneec.html”;
$(“#divViewExam”).loadPage(url, {procId: resp.procId});
创建高级审批的按钮:
function createButton(resp) {
var parms = new Supp.EIP.WF.WfParms();
parms.dbYear = resp.dbYear;
parms.moduleId = resp.moduleId;
parms.domainObjectId = resp.domainObjectId;
parms.entityId = resp.reportId;
parms.companyNo = resp.companyNo;
parms.moduleBusiType = resp.moduleBusiType;
parms.entityName = resp.entityName;
var busiJson = Supp.EIP.WF.getProcBusiJson(parms);
//高级审核
Supp.EIP.WF.advancedExam(busiJson,
function successCallBack(json) {
Supp.EIP.Desktop.closeWindow();
}, function errorCallBack(json) {
Supp.alert("审批失败!", Supp.alert.type.error);
});
}
2.高级审批中,验证通过后才能正常提交的解决方案。
在一些业务中,下一步的承担人可能需要业务的审批人员动态选择,若不选择,为空时流程也能正常走通,因为系统中从在空角色。解决方案:在高级审批的div上加上遮掩,然后加上div聚焦的方法,鼠标悬停在审批div上边时进行验证,使其不能点击,验证通过后再取消遮掩,使其可以点击确认按钮提交流程。
如以上审批页面Html代码实例 中的绿色代码段,就是遮掩的div。
Js实现代码段:
$(“#div_AdvacedExam”).mouseover(function(){//jquery的mouseover事件
var result = accountAndMail();//验证是否填写了账号信息
if( !result ){//验证不通过 加遮掩
$(“#div_AdvacedExam_inDiv”).addClass(“shadow”);
$(“#div_AdvacedExam_inDiv”).show();
}else{//验证通过 取消遮掩
$(“#div_AdvacedExam_inDiv”).removeClass(“shadow”);
$(“#div_AdvacedExam_inDiv”).hide();
}
});
CSS实现代码段:
4.2 在流程管理中点击流程标题跳转到查看页面
在service加上方法:
@Servicepublic class OveBimRepViewProvider implements IBusiEntityViewerProvider{ @Override
public String getId() {
return OverseasBimonthlyReportEntity.class.getName();
}
@Override
public String getViewerUrl(int dbYer, Object entityId) {
return "/oa/overseas_bimonthly_report/overseas_bimonthly_report_view.html?reportId="+entityId;
}
}4.3 多个流程下,根据元数据中的字段值的判断条件启动不同的流程
1.先从这个路径下进去配置条件后边的moduleId是应用ID。
http://192.168.100.180/eip/eip/swf/busi_auth/busi_auth.html?moduleId=PREREVIEW
2.然后添加判断条件就行了。
4.4 获取流程节点的审批结果,列表形式
url: Supp.Util.getSystemUrl() + "service/oa/his_exam/getExamGrid",
datatype: "json",
postData: {
procId: procId
},
colModel: [{
label: '主键',
name: 'wfProcId',
key: true,
hidden: true
},
{
label: '流程节点',
name: 'wfActName',
sortable: false
},
{
label: '审批人',
name: 'empNameDisplay',
sortable: false
},
{
label: '审批意见',
name: 'opinionDesc',
sortable: false
},
{
label: '审批时间',
name: 'examDateStr',
sortable: false
}],
gridId: "#jqGrid_reviewOpion",
gridType: "edit_grid",
emptyType: "edit",
mtype: "POST",
autowidth: true,
rownumbers: false,
// 是否显示行号
multiselect: false,
// 是否支持多选
sortname: "",
// 默认按哪一列排序
sortorder: "desc",
// 排序方式
gridComplete: function() { // 表格加载完执行的函数
},
});4.4根据元数据字段启动不同的流程
4.4.1 eip升级后的的使用方式
如果有类型管理找到类型管理下“适用流程”
如果是自己开发的业务需要嵌入连接
eip/swf/busi_auth/busi_auth.html?moduleId=&domainObjectId=&busiType=
也可根据不同的业务类型走不同的流程。。。。
busiType该字段可以在启动流程的时候定义,然后在流程适用范围上写上对应的就行了。
4.5、swf6.0.6流程非法 *** 作导致这条业务单为草稿状态但是不能提交流程了,显示该流程已存在。处理方式,在supp_app库中找到swf_proc表,找到业务单的主键,然后在表中搜索这条主键数据,删掉。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)