此功能以Activiti5.22为基础版本进行设计实现。其他版本仅做参考。
第一、需开启用户任务会签功能
1、会签串行(用户任务结点以三条横线标识)
2、会签并行(用户任务结点以三条竖线标识)
第二、启动时设置
private Map checkAndParseStartVar(Process process, Map processVar) {
Assert.isTrue (!CollectionUtils.isEmpty(processVar), "流程变量信息为空");
Map map = new HashMap<>(processVar.size() + 4);
List userTasks = process.getFlowElements().stream()
.filter(flowElement -> flowElement instanceof UserTask)
.map(flowElement -> (UserTask)flowElement)
.collect(Collectors.toList());
for (Entry entry : processVar.entrySet()) {
ProcessVarDTO dto = entry.getValue();
Assert.notNull (dto , "键值["
+ entry.getKey() + "]对应的值为空");
boolean isMultiInstance = userTasks.stream()
.filter(userTask -> Objects.nonNull(userTask.getLoopCharacteristics()))
.map(UserTask::getLoopCharacteristics)
.anyMatch(multiInstanceLoopCharacteristics -> {
String key = multiInstanceLoopCharacteristics.getInputDataItem();
key = key.replace("${", Symbol.EMPTY).replace("}", Symbol.EMPTY).trim();
return key.equals(entry.getKey());
});
if (dto.getLongVal() != null) {
map.put(entry.getKey(), dto.getLongVal());
} else if (dto.getDoubleVal() != null) {
map.put(entry.getKey(), dto.getDoubleVal());
} else if (!CollectionUtils.isEmpty(dto.getCandidate())) {
String candidate = dto.getCandidate().toString();
candidate = candidate.substring(1, candidate.length() - 1)
.replaceAll("\\D+", ",");
map.put(entry.getKey(), isMultiInstance ? Lists.newArrayList(dto.getCandidate()) : candidate);
} else if (dto.getStringVal() != null) {
map.put(entry.getKey(), isMultiInstance ? Lists.newArrayList(dto.getStringVal().split(Symbol.COMMA)) : dto.getStringVal().trim());
} else {
Assert.isTrue(false, "未获取到键[" + entry.getKey() + "]对应的值");
}
}
return map;
}
第三、会签任务一票否决(主要针对并行任务)
/**
* 会签结点任务一票否决
* @param task 当前任务
* @param variables 参数
* @param isPass 审批结果(true通过,false驳回)
*/
private void executeCompleteTask(Task task, Map variables, boolean isPass){
// 获取流程实例对象
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
// 获取流程定义对象,主要用于判断流程任务结点是否为会签结点
Process process = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId())
.getProcessById(historicProcessInstance.getProcessDefinitionKey());
if(isPass) { // 审批通过,将后续会签结点中人员转换为集合
process.getFlowElements().stream()
.filter(flowElement -> flowElement instanceof UserTask) // 过滤用户任务结点
.map(flowElement -> (UserTask) flowElement)// 转换为用户任务
.filter(userTask -> Objects.nonNull(userTask.getLoopCharacteristics()))// 是否为支持会签功能
.map(UserTask::getLoopCharacteristics)// 获取会签配置信息
.map(MultiInstanceLoopCharacteristics::getInputDataItem) // 获取会签配置信息中的人员参数
.forEach(key -> {
String varName = key.replace("${","").replace("}", "");
if (!variables.containsKey(varName)) {
return;
}
// 将参数值更新为集合
variables.put(varName, Collections.singletonList(variables.get(varName)));
});
}
// 获取当前任务结点
Optional userTask = process.getFlowElements().stream()
.filter(flowElement -> task.getTaskDefinitionKey().equals(flowElement.getId()))
.map(flowElement -> (UserTask)flowElement)
.findAny();
boolean isMultiTask = userTask.isPresent() // 存在
&& Objects.nonNull(userTask.get().getLoopCharacteristics()); // 为会签结点
List tempPvmTransitions = Lists.newArrayList();
TransitionImpl newTransition = null;
ActivityImpl endActivity = null;
ActivityImpl currentActivity = null;
if(!isPass // 拒绝
&& isMultiTask // 会签结点
) {
// 获取结束结点
Optional optional = process.getFlowElements().stream()
.filter(flowElement -> flowElement instanceof EndEvent)
.findFirst();
if(!optional.isPresent()){
return;
}
// 获取已部署流程定义对象
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService)
.getDeployedProcessDefinition(task.getProcessDefinitionId());
// 获取已部署流程定义中的结束对象
endActivity = processDefinitionEntity.findActivity(optional.get().getId());
// 获取已部署流程定义中的当前任务对象
currentActivity = processDefinitionEntity.findActivity(task.getTaskDefinitionKey());
// 临时存放当前流出
List currentActivityPvmTransitions = currentActivity.getOutgoingTransitions();
tempPvmTransitions.addAll(currentActivityPvmTransitions);
// 清空当前任务结点上的流出
currentActivityPvmTransitions.clear();
// 新增当前任务结点流出至结束结点
newTransition = currentActivity.createOutgoingTransition();
newTransition.setDestination(endActivity);
// 设置会签任务结点完成条件
taskService.setVariable(task.getId(), "nrOfInstances", userTask.get().getLoopCharacteristics().isSequential() ? 0 : 1);
}
// 执行任务审批
taskService.complete(task.getId(), variables);
if(isPass // 通过
|| !isMultiTask // 非会签结点
){
return;
}
// 还原任务结点流出设置
// 先清空当前任务结点临时流出(流出至结束结点)
endActivity.getIncomingTransitions().remove(newTransition);
currentActivity.getOutgoingTransitions().clear();
// 再设置原来的流出
currentActivity.getOutgoingTransitions().addAll(tempPvmTransitions);
}
第四步、调整界面
以上步骤即可实现会签一票否决。