基于开源项目KonBAI / RuoYi-Flowable-Plus使用的部分功能调整。当任务设置为多人或签时,实际仅需要一人确认通过,就会流转至下一流程,并且将所有的或签审批节点都展示出来。当或签选择人数过多时,会导致流转记录非常的长。
设计流程图
在审批节点设置审批人为多名指定用户、审批方式为或签。
审批通过结果
其余审批人并没有操作审批通过,而办理时间更新为实际办理人的办理时间。
代码示例
操作审批通过,事件为HISTORIC_PROCESS_INSTANCE_ENDED时,会将或签节点的加入历史节点表中ACT_HI_ACTINST中,并将实际未签的节点设置DELETE_REASON_=MI_END。以此为依据,在展示流程详情时进行过滤。
测试时还发现,会签节点最后一个审批人也会被标记为MI_END,目前暂未知道原因,只能对会签类型的流程详情进行排除。
/**
* 获取流程历史任务信息
*/
private List<WfProcNodeVo> historyProcNodeList(String procInsId) {
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_EVENT_END, BpmnXMLConstants.ELEMENT_TASK_USER))
.orderByHistoricActivityInstanceStartTime().desc()
.orderByHistoricActivityInstanceEndTime().desc()
.list();
// 中间代码省略...
List<WfProcNodeVo> elementVoList = new ArrayList<>();
for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
// 排除删除原因为MI_END的节点
if (activityInstance.getDeleteReason() != null && "MI_END".equals(activityInstance.getDeleteReason())) {
boolean sequentialMultiInstance = FlowableUtils.isSequentialMultiInstance(repositoryService, activityInstance.getProcessDefinitionId(), activityInstance.getActivityId());
if (!sequentialMultiInstance) {
// 如果是会签节点,则不跳过该任务;如果是或签节点,跳过该任务
continue;
}
}
WfProcNodeVo elementVo = new WfProcNodeVo();
// 中间代码省略...
elementVoList.add(elementVo);
}
return elementVoList;
}
当前节点是否是会签节点方法
/**
* 查询当前节点是否是会签节点
* @param processDefinitionId
* @param taskDefinitionKey
* @return
*/
public static boolean isSequentialMultiInstance(RepositoryService repositoryService, String processDefinitionId, String taskDefinitionKey) {
boolean res = false;
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey);
// 判断是否是并行会签节点 (或签) ParallelMultiInstanceBehavior
if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior) {
res = true;
}
return res;
}