由流程向导生成的功能是一打开功能,就显示一个流程的信息,有时候需要一打开功能,就显示多个流程的信息,例如下面的界面
在这个功能中,可以新加一条业务数据、新建一个流程、启动流程、流转等
并且定义了事件,在启动和流转之后,将该流程的处理环节和处理人回写到业务数据中并修改单据状态
1.新建
可以直接在grid列表中新建一条数据,这里设置了单据状态默认值为“未审批”,用来做流程的业务数据,当然需要自己执行“启动流转”,或者双击列表数据操作后面会介绍
2.新建流程
在listActivity.w文件中,通过按钮调用,调用justep.Shell.showPage方法,打开流程的启动界面,代码如下
Model.prototype.button1Click = function(event) { var url = "$UI/demo/listProcess/process/listProcess/mainActivity.a"; justep.Shell.showPage({ url : url, title : "订单" }); };
这样就实现了在列表流程中新建一个流程,跟直接从功能树列表中打开流程功能一样的
3.启动流程
在listActivity.w文件中放一个process组件,调用这个组件的start方法,启动流程
不需要设置process组件的data属性,autoClose、autoStart、autoSave、autoFilter都设置为false
代码如下,第3个参数传列表data的行ID
var dList = this.comp("mainData"); if (dList.getValue("fStatus") == "未审批") { this.comp("process1").start(null, null, dList.getCurrentRowID(), null); dList.refreshData(); } else { alert("流转已经启动"); }
因为已经启动了的流程不能再次启动,所以,为避免重复启动,添加了适当的判断代码
4.处理流程
处理流程就是对流程进行流转、回退等操作,方法是点击处理流程按钮时,调用justep.Shell.showPage方法打开流程当前环节对应的w文件,在界面上进行流转、回退等操作。
例如:流程的当前环节如果是订单申请(orderReportActivity),就打开/UI2/demo/listProcess/process/listProcess/orderReportActivity.w文件
流程的当前环节如果是订单审核(reviewedActivity),就打开/UI2/demo/listProcess/process/listProcess/reviewedActivity.w
那么,如何获得流程的当前环节等信息呢
这就需要,访问sa_task表,这里是定义了一个action(taskDataAction),在action中用KSQL设置过滤返回数据,设置过滤条件为
(SA_Task.sKindID=’tkTask’ or SA_Task.sKindID=’tkExecutor’ or SA_Task.sKindID IS NULL)
and (SA_Task.sStatusID=’tesReady’ or SA_Task.sStatusID=’tesExecuting’)
and (SA_Task.sTypeID IS NULL or SA_Task.sTypeID <> ‘WORKREMIND’)
注意还有sData1的过滤,需要从页面中传当前记录的rowid,因此action中要有一个参数String sData1
action对应的java代码如下:
public static Table taskData(String sData1){ String ksql="Select task,task.sEURL,task.sActivityName from SA_Task task where task.sData1 = '"+sData1+"' and (task.sKindID='tkTask' or task.sKindID='tkExecutor' or task.sKindID IS NULL) " + "and (task.sStatusID='tesReady' or task.sStatusID='tesExecuting') " + "and (task.sTypeID IS NULL or task.sTypeID <> 'WORKREMIND')"; Table table = KSQL.select(ksql, null, "/system/data", null); return table; }
经过上面的设置,返回的Table里面就是当前流程的当前环节的记录了。当然如果流程复杂,当前环节有多个,又都流转给了当前登录者或所在的机构,返回的Table里面的记录就不只一条了。需要先执行executeTaskAction
调用executeTaskAction的代码如下:
Model.prototype.executeTask = function(taskID,executorFID){ var executor= ""; var params = new biz.Request.ActionParam(); params.setString("task", taskID); params.setString("executor", executorFID); var options = {}; options.context = this.getContext(); options.action = "executeTaskAction"; options.parameters = params; options.directExecute = true; options.callback = function(options) { if (options.state) { executor = options.response; } else { options.ignoreError = false; } }; biz.Request.sendBizRequest(options); return executor; };
处理流程的代码如下(调用了执行executeTaskAction的js函数)
var dList = this.comp("mainData"); var sData1 = dList.getCurrentRowID(); var context = this.getContext(); var currentPersonID = context.getCurrentPersonID(); var personMemberFIDs = context.getAllPersonMemberFIDs(); var taskData = this.comp("taskData"); // 定义action参数,请求taskDataAction获取当前环节的数据信息 var param = new biz.Request.ActionParam(); param.setString("sData1", sData1); biz.Request.sendBizRequest({ "context" : context, "action" : "taskDataAction", "parameters" : param, "callback" : function(callbackData) { if (callbackData.state) { taskData.clear(); taskData.loadData(callbackData.response); taskData.first(); } else alert("任务数据获取失败"); } }); // 当有数据返回时获取对已经的任务进行处理 var title,taskID,url,status,executorFID,executorPersonID =null; //一人或一个部门执行的 if (taskData.getCount()===1) { title = taskData.getValue("sActivityName");// 获得当前环节名称,作为页面的标题 taskID = taskData.getValue("task");// 获得任务ID,url中的参数 url = taskData.getValue("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 executorPersonID = taskData.getValue("sExecutorPersonID"); if (executorPersonID === currentPersonID) {// 如果执行者是否当前人 justep.Shell.showPage({ url : url, title : title }); // 调用justep.Shell.showPage方法打开流程当前环节对应的w文件 }else { status = taskData.getValue("sStatusID"); executorFID = taskData.getValue("sExecutorFID"); if (status === "tesReady" && (personMemberFIDs.toString().indexOf(executorFID) > -1)) {// 判断执行者是否是当前操作者的所有人员成员所在的组织 var executor = this.executeTask(taskID,executorFID); justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); } else { alert("任务应由其他人处理"); } } } //多人或者多门户执行的 else if(taskData.getCount() > 1 ){ var tasks = taskData.find(['sExecutorPersonID'],[currentPersonID],false,false,false); //当前的人的任务 if(tasks && tasks.length === 1){ taskID = tasks[0].val("task");// 获得任务ID,url中的参数 executorFID = tasks[0].val("sExecutorFID"); var executor = this.executeTask(taskID,executorFID); // title = tasks[0].val("sActivityName"); url = tasks[0].val("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); // 调用justep.Shell.showPage方法打开流程当前环节对应的w文件 } else{ //当前人所在的组织的任务 var me = this; taskData.each(function(param){ status = param.row.val("sStatusID"); executorFID = param.row.val("sExecutorFID"); if(status === "tesReady" && (personMemberFIDs.toString().indexOf(executorFID) > -1)){ taskID = param.row.val("task"); title = param.row.val("sActivityName"); url = param.row.val("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 param.cancel = true; } }); var executor = me.executeTask(taskID,executorFID); justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); } } else { alert("流转未启动、已完成"); }
上面的代码只处理了返回的Table里面的一条记录,如果超过一条记录,请酌情处理
url中的参数,等同于从待办任务中打开功能时传递的参数
5.打开已结束的流程
对于已经结束的流程打开的方法不同于处理流程打开页面的方法。
处理流程打开页面的方法的方法是传入任务ID,系统根据任务ID,计算出业务数据ID,通过将process组件的autoFilter属性为true,让系统使用业务数据ID过滤数据。
已经结束的流程没有当前任务ID了,所以不使用上面的方法,而是使用直接传入业务数据ID,直接过滤的方式
新建listActivityDetail.w文件,可以继承自/UI2/demo/listProcess/process/listProcess/mainActivity.w文件,将process组件的autoFilter属性设置为false,bizData组件的autoLoad属性设置为false。
listActivity.w文件中打开已经结束的流程的代码如下
var dList = this.comp("mainData"); var url = "$UI/demo/listProcess/process/listProcess/listActivityDetial.a?_pagePattern=readonly"; justep.Shell.showPage({ url : url, process:"/demo/listProcess/process/listProcess/listProcessProcess", activity:"listActivity", title : "已完成订单", rowid : dList.getCurrentRowID() });
其中参数rowid就是当前业务数据的ID,作为参数传给listActivityDetail.w
listActivityDetail.w文件的model的onParamsReceive事件里面获取参数rowid,进行数据过滤代码如下
Model.prototype.modelParamsReceive = function(event){ this.sData1 = this.getContext().getRequestParameter("rowid");//获得传入的业务数据ID var data = this.comp("mainData"); data.setFilter("filter1", "DE_Order = '"+this.sData1+"'");//给data设置过滤条件 data.refreshData();//刷新数据 };
在listActivityDetail.w中查看流程和流程记录可以调用process组件中提供的API
this.comp("process").showChart(this.process, this.sData1);//查看流程图 this.comp("process").processRecord(null,this.process, this.sData1);//查看流程记录
由于两个API都需要传process和sData1的值,所以这里通过实例变量去设置的
实例遍历的定义代码如下:
var Model = function(){ this.callParent(); this.sData1 = ""; this.process = this.getContext().getCurrentProcess(); };
6.定义流程事件,回写业务数据
如果流程每个环节都要执行的可以将代码应该该流程的事件中,不用在每个环节上的事件中实现
这列在流程启动和流转后去进行业务数据的会写可以在onAfterStart和onAfterAdvance中处理
public static void listProcessProcessAfterStart() { updateBizRecord(); } public static void listProcessProcessAfterAdvance() { updateBizRecord(); } public static void updateBizRecord() { String sExecutorNames = "", sActivityNames = "", fStatus; //判断是否流转都最后,如果是状态设置为已完成,不是设置为审批中 if (!ProcessUtils.isFlowToEnd()) { ProcessControl flowControl = (ProcessControl)ContextHelper.getActionContext().getParameter("control"); for (ProcessControlItem to : flowControl.getFlowTos()) { for (OrgUnit ect : to.getExecutors()) { sExecutorNames = sExecutorNames + CommonUtils.getNameOfFile(ect.getFName()) + " "; } sActivityNames = to.getTask().getActivityName(); } fStatus = "审批中"; }else{ fStatus = "已完成"; } String key = ProcessUtils.getProcessData1(); String sConceptName = ProcessUtils.getProcessData2(); String sDataModel = ProcessUtils.getProcessData3(); String ksql = "update " + sConceptName + " o set o.fExecutePerson='" + sExecutorNames + "',o.fExecuteActivity='" + sActivityNames + "',o.fStatus='" + fStatus + "' where o='" + key +"'"; KSQL.executeUpdate(ksql, null, sDataModel, null); }
实现更新业务数据,需要知道业务数据的概念、ID及数据模块,因此使用sData2存放业务数据的概念,使用sData3存放数据模块,再加上系统自动将业务数据ID存入sData1,通过在启动规则中设置sData2和sData3就可以实现更新业务数据了。
7.双击列表中的记录,进行处理
至此,在业务数据中已经记录了流程的状态,根据这个状态,可以实现双击列表中的某条记录,对其进行相应的处理。
例如:对于没有启动的流程——流程状态为空,执行启动流程;
对于已经启动了,还未结束的流程——流程状态为审批中,执行处理流程,打开当前环节对应的页面;
对于已经流转结束的流程——流程状态为已完成,打开listActivityDetail.w文件。显示业务数据。
代码如下,在本例中使用了fStatus存放流程状态
Model.prototype.grid1RowDblClick = function(event) { var dList = this.comp("mainData"); if (dList.getValue("fStatus") == "未审批") { this.startFlow(); } else if (dList.getValue("fStatus") == "已完成") { // alert("流转已经完成,使用新页面显示"); var url = "$UI/demo/listProcess/process/listProcess/listActivityDetial.a?_pagePattern=readonly"; justep.Shell.showPage({ url : url, process:"/demo/listProcess/process/listProcess/listProcessProcess", activity:"listActivity", title : "已完成订单", rowid : dList.getCurrentRowID() }); } else { this.advanceFlow(); } }; Model.prototype.startFlow = function() { var dList = this.comp("mainData"); if (dList.getValue("fStatus") == "未审批") { this.comp("process1").start(null, null, dList.getCurrentRowID(), null); dList.refreshData(); } else { alert("流转已经启动"); } }; Model.prototype.executeTask = function(taskID,executorFID){ var executor= ""; var params = new biz.Request.ActionParam(); params.setString("task", taskID); params.setString("executor", executorFID); var options = {}; options.context = this.getContext(); options.action = "executeTaskAction"; options.parameters = params; options.directExecute = true; options.callback = function(options) { if (options.state) { executor = options.response; } else { options.ignoreError = false; } }; biz.Request.sendBizRequest(options); return executor; }; Model.prototype.advanceFlow = function() { var dList = this.comp("mainData"); var sData1 = dList.getCurrentRowID(); var context = this.getContext(); var currentPersonID = context.getCurrentPersonID(); var personMemberFIDs = context.getAllPersonMemberFIDs(); var taskData = this.comp("taskData"); // 定义action参数,请求taskDataAction获取当前环节的数据信息 var param = new biz.Request.ActionParam(); param.setString("sData1", sData1); biz.Request.sendBizRequest({ "context" : context, "action" : "taskDataAction", "parameters" : param, "callback" : function(callbackData) { if (callbackData.state) { taskData.clear(); taskData.loadData(callbackData.response); taskData.first(); } else alert("任务数据获取失败"); } }); // 当有数据返回时获取对已经的任务进行处理 var title,taskID,url,status,executorFID,executorPersonID =null; //一人或一个部门执行的 if (taskData.getCount()===1) { title = taskData.getValue("sActivityName");// 获得当前环节名称,作为页面的标题 taskID = taskData.getValue("task");// 获得任务ID,url中的参数 url = taskData.getValue("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 executorPersonID = taskData.getValue("sExecutorPersonID"); if (executorPersonID === currentPersonID) {// 如果执行者是否当前人 justep.Shell.showPage({ url : url, title : title }); // 调用justep.Shell.showPage方法打开流程当前环节对应的w文件 }else { status = taskData.getValue("sStatusID"); executorFID = taskData.getValue("sExecutorFID"); if (status === "tesReady" && (personMemberFIDs.toString().indexOf(executorFID) > -1)) {// 判断执行者是否是当前操作者的所有人员成员所在的组织 var executor = this.executeTask(taskID,executorFID); justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); } else { alert("任务应由其他人处理"); } } } //多人或者多门户执行的 else if(taskData.getCount() > 1 ){ var tasks = taskData.find(['sExecutorPersonID'],[currentPersonID],false,false,false); //当前的人的任务 if(tasks && tasks.length === 1){ taskID = tasks[0].val("task");// 获得任务ID,url中的参数 executorFID = tasks[0].val("sExecutorFID"); var executor = this.executeTask(taskID,executorFID); // title = tasks[0].val("sActivityName"); url = tasks[0].val("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); // 调用justep.Shell.showPage方法打开流程当前环节对应的w文件 } else{ //当前人所在的组织的任务 var me = this; taskData.each(function(param){ status = param.row.val("sStatusID"); executorFID = param.row.val("sExecutorFID"); if(status === "tesReady" && (personMemberFIDs.toString().indexOf(executorFID) > -1)){ taskID = param.row.val("task"); title = param.row.val("sActivityName"); url = param.row.val("sEURL");// 获得当前环节的url url = url + "?task=" + taskID + "&_pagePattern=write";// _pagePattern=write是必须的,表示要处理这个任务 param.cancel = true; } }); var executor = me.executeTask(taskID,executorFID); justep.Shell.showPage({ url : url, title : title, executor : executor || "" }); } } else { alert("流转未启动、已完成"); } };
其中3和4中的启动流程和处理流程的代码就是startFlow和advanceFlow方法
8.流转后,刷新列表数据
流转后,当前环节页面自动关闭,显示出列表流程的页面,此时会触发/UI2/demo/listProcess/process/listProcess/listActivity.w中model的onActive事件,在这个事件中刷新列表数据,代码如下
评一波