需求:在流程最初的时候,以请假流程为例,需要自定义审核人以及审核方式是会签还是或签。
开始前先普及几个概念:
Asignee:受理人,该任务环节的受理人,如果是会签,会有多个受理人
CandidateUsers:候选人,该任务环节的受理人由候选人中产生。
Model设计
由于会签及或签需要自定义,会签的时候,用户任务节点是以多实例的方式存在的。那么,或签是否可以理解为多实例中,只需要有一个完成了就可以完成任务节点。
<userTask id="sid-8B06F53F-9A04-46DB-9BE9-82A9C933A0B7" name="审核视频" default="sid-89A4CB33-D854-4D79-BFB2-C2348E029E50"
activiti:assignee="${assignee}">
<extensionElements>
<activiti:executionListener event="start" class="com.hereur.activiti7.MultiInstanceTaskHandler"/>
</extensionElements>
<multiInstanceLoopCharacteristics
isSequential="false"
activiti:collection="assigneeList"
activiti:elementVariable="assignee">
<completionCondition>
<![CDATA[
${nrOfCompletedInstances/nrOfInstances >= signCounter && nrOfCompletedInstances > 0}
]]>
</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
以上节点为多实例用户任务节点,部分参数说明如下:
activiti:assignee 受理人,取自assigneeList
nrOfCompletedInstances 完成任务的实例个数
nrOfInstances 总的实例个数
signCounter 完成用户任务节点的条件
此处,完成任务的条件为 nrOfCompletedInstances / nrOfInstances >= signCounter 即可。
在启动流程实例的时候,设置好signCounter尤为重要。此处可考虑将signCounter设置为两个值:0 或签 1 会签。
即 完成任务的实例个数 除以 总的实例个数 大于等于 0 且 完成任务的实例个数 > 0 就可完成或签;对于会签,则必须 完成任务的实例个数 和 总实例个数 相除等于 1 才可完成任务节点。
测试设计
/**
* 启动流程实例
*/
@Test
public void testStartProcess() {
int signCounter = 0; // 0 或签 1 会签
Map<String, Object> variables = new HashMap<>();
List<String> users = Arrays.asList(new String[]{"system", "tough"});
variables.put("updateVideoCandidates", users);
// 如果是会签,设置assigneeList为该有的值;如果是或签,设置auditVideoCandidates为该有的值。
// 如果是会签,设置counterSign = 1;如果是或签,设置counterSign = 0
variables.put("assigneeList", users);
variables.put("signCounter", signCounter);
// 启动流程的时候指定候选人
ProcessInstance pi = processRuntime.start(ProcessPayloadBuilder.
start().
withProcessDefinitionKey("process").
withProcessDefinitionId("process:3:db3e054b-dfc8-11eb-a122-00d861a4d913").
withBusinessKey("Toughs2"). // 设置业务ID
withVariables(variables).
build());
System.out.println("流程实例ID:" + pi.getId());
}
/**
* *查询任务,并完成自己的任务
**/
@Test
public void testTask() {
Page<Task> taskPage = taskRuntime.tasks(Pageable.of(0, 10), TaskPayloadBuilder.tasks().build());
if (taskPage.getTotalItems() > 0) {
for (Task task : taskPage.getContent()) {
if (task.getAssignee() == null) {
taskRuntime.claim(TaskPayloadBuilder.
claim().
withTaskId(task.getId()).build());
System.out.println("任务:" + task);
}
Map<String, Object> variables = new HashMap<>();
variables.put("auditResult", 1);
taskRuntime.complete(TaskPayloadBuilder.
complete().
withVariables(variables).
withTaskId(task.getId()).build());
}
}
Page<Task> taskPage2 = taskRuntime.tasks(Pageable.of(0, 10));
if (taskPage2.getTotalItems() > 0) {
System.out.println("任务:" + taskPage2.getContent());
}
}
查看act_ru_task表可查看当前节点的受理人。