プロジェクトアドレス:activiti-ワークフロー
一般的な承認フローには拒否機能があり、activitiが提供するインターフェースはそれを拒否しません。この記事では、activitiが提供するインターフェースを拡張することにより、プロセス拒否機能を実装します。メインコードは次のとおりです。
String processInstanceId = taskCurrent.getProcessInstanceId();
FlowElement targetFlowElement = null;
if (StringUtil.isNotEmpty(processRejectParam.getTargetNodeId())) {
//找到目标节点元素
targetFlowElement = bpmnModel.getMainProcess().getFlowElement(processRejectParam.getTargetNodeId());
} else {
//开始节点的下一个节点
targetFlowElement = BpmnUtil.startEventNextTaskId(bpmnModel);
}
//当前待审批节点定义Id集合
List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
if (CollectionUtil.isNotEmpty(taskList)) {
BpmnModel newBpmnModel = bpmnModel;
Map<String, List<SequenceFlow>> stringListMap = BpmnUtil.invokeSequenceFlows(newBpmnModel, taskList, targetFlowElement);
for (Task task : taskList) {
//记录原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
//当前节点
oriSequenceFlows.addAll(stringListMap.get(task.getTaskDefinitionKey()));
FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
try {
Map<String, Object> variables = new HashMap<>();
//当前操作节点
if(task.getId().equals(taskCurrent.getId())){
//设置当前审批人为提交人
taskService.setAssignee(task.getId(), userId);
// 保存任务评价
if (StringUtil.isNotEmpty(rejectComment)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), rejectComment);
}
//设置节点状态
taskService.setVariablesLocal(task.getId(), variables);
//完成
taskService.complete(task.getId());
}else{
//完成
taskService.complete(task.getId());
//删除任务
historyService.deleteHistoricTaskInstance(task.getId());
}
} catch (Exception e) {
e.printStackTrace();
throw new ProcessException("流程撤回异常,异常原因:" + e.getMessage());
} finally {
//恢复原方向
currentFlowNode.setOutgoingFlows(oriSequenceFlows);
}
}
}
invokeSequenceFlowsメソッド、特定のコードをプロジェクトで表示できます。
/**
* 处理撤回连线 可能存在分支
* @param bpmnModel
* @param taskList
* @param targetFlowElement
* @return
*/
public static Map<String,List<SequenceFlow>> invokeSequenceFlows(BpmnModel bpmnModel , List<Task> taskList, FlowElement targetFlowElement) {
Map<String,List<SequenceFlow>> flowElements = new HashMap<>(2);
//并行网关
ParallelGateway parallelGateway = new ParallelGateway();
parallelGateway.setId("parallelGateway" + targetFlowElement.getId());
parallelGateway.setBehavior(new ParallelGatewayActivityBehavior());
List<SequenceFlow> parallelSequenceFlowInCome = new ArrayList<>();
for (Task task : taskList) {
//当前节点
FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
flowElements.put(currentFlowNode.getId(),currentFlowNode.getOutgoingFlows());
//重新绘制流程图,从当前节点到到并行网关
List<SequenceFlow> parallelSequenceFlowList = new ArrayList<>();
SequenceFlow parallelSequenceFlow = new SequenceFlow();
parallelSequenceFlow.setId("newSequenceFlowId" + System.currentTimeMillis());
parallelSequenceFlow.setSourceFlowElement(currentFlowNode);
parallelSequenceFlow.setTargetFlowElement(parallelGateway);
parallelSequenceFlowList.add(parallelSequenceFlow);
parallelSequenceFlowInCome.add(parallelSequenceFlow);
currentFlowNode.setOutgoingFlows(parallelSequenceFlowList);
}
//重新绘制流程图,从并行网关到开始节点
List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
//绘制连线,加入流程信息,并组装到流程图
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId" + targetFlowElement.getId());
newSequenceFlow.setSourceFlowElement(parallelGateway);
newSequenceFlow.setTargetFlowElement(targetFlowElement);
newSequenceFlowList.add(newSequenceFlow);
parallelGateway.setIncomingFlows(parallelSequenceFlowInCome);
parallelGateway.setOutgoingFlows(newSequenceFlowList);
return flowElements;
}
いくつかのアイデアを整理し、ターゲットノードの定義IDを渡すオプションを拒否します。そうでない場合は、デフォルトで開始ノードの次のノードを選択します。現在、複数の承認タスクがある場合、今回実行したタスクが完了すると他の操作は実行されず、完了後に他のタスクは削除されます(承認トレースは残されません)。
主にinvokeSequenceFlowsによって処理される現在の承認プロセスには、複数のタスクが含まれる場合があります。処理方法は、現在のノードの前のタスクに並列ゲートウェイを追加し、現在の承認ノードをゲートウェイに接続し、ゲートウェイをターゲットノードに接続することです。このように、現在の承認タスクの数に関係なく、並列ゲートウェイは、前のノードがすべて完了するのを待ってから、後続のノードに進み、現在の承認タスクがすべて実行されるようにします。
おそらくプロセスはこのようなものです
この方法は、撤退(イニシエーター操作)にも使用され、問題が発生する可能性があり、多くのテストが必要になります。