package jnpf.flowable.util; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.ImmutableList; import jnpf.exception.WorkFlowException; import jnpf.flowable.entity.*; import jnpf.flowable.enums.*; import jnpf.flowable.model.flowable.FlowAbleUrl; import jnpf.flowable.model.flowable.FlowableHistoricModel; import jnpf.flowable.model.task.FlowMethod; import jnpf.flowable.model.task.FlowModel; import jnpf.flowable.model.templatenode.TaskNodeModel; import jnpf.flowable.model.templatenode.nodejson.AuxiliaryInfo; import jnpf.flowable.model.templatenode.nodejson.AuxiliaryInfoConfig; import jnpf.flowable.model.templatenode.nodejson.NodeModel; import jnpf.flowable.model.util.FlowNature; import jnpf.flowable.service.*; import jnpf.model.document.FlowFileModel; import jnpf.permission.entity.UserEntity; import jnpf.util.JsonUtil; import jnpf.util.StringUtil; import jnpf.util.UserProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.stream.Collectors; /** * 类的描述 * * @author JNPF@YinMai Info. Co., Ltd * @version 5.0.x * @since 2024/4/29 10:29 */ @Component public class NodeUtil { @Autowired private FlowAbleUrl flowAbleUrl; @Autowired private ServiceUtil serviceUtil; @Autowired private TaskUtil taskUtil; @Autowired private OperatorService operatorService; @Autowired private OperatorUtil operatorUtil; @Autowired private TaskService taskService; @Autowired private RevokeService revokeService; @Autowired private EventLogService eventLogService; @Autowired private TriggerRecordService triggerRecordService; public List getNodeList(FlowModel flowModel) throws WorkFlowException { List nodeList = new ArrayList<>(); TaskEntity taskEntity = flowModel.getTaskEntity(); // 终止后 任务详情的流程图,需全部置灰 if (ObjectUtil.equals(TaskStatusEnum.CANCEL.getCode(), taskEntity.getStatus())) { return nodeList; } RevokeEntity revokeEntity = revokeService.getRevokeTask(taskEntity.getId()); boolean isRevoke = revokeEntity != null; List nodeEntities = flowModel.getNodeEntityList(); // 当前节点 String currentNodeCode = StringUtil.isNotEmpty(taskEntity.getCurrentNodeCode()) ? taskEntity.getCurrentNodeCode() : ""; List currentNodes = new ArrayList<>(Arrays.asList(currentNodeCode.split(","))); // 未经过的节点 List tobePass = flowAbleUrl.getTobePass(taskEntity.getInstanceId()); if (currentNodeCode.equals(FlowNature.END_CODE)) { currentNodes = nodeEntities.stream() .filter(t -> NodeEnum.end.getType().equals(t.getNodeType())).map(TemplateNodeEntity::getNodeCode).collect(Collectors.toList()); } // 经过的节点 FlowMethod flowMethod = new FlowMethod(); flowMethod.setTobePass(tobePass); flowMethod.setCurrentNodes(currentNodes); flowMethod.setTaskId(taskEntity.getId()); flowMethod.setTaskEntity(taskEntity); flowMethod.setNodeEntityList(nodeEntities); List passed = this.getPassed(flowMethod); TemplateNodeEntity start = nodeEntities.stream().filter(e -> e.getNodeType().equals(NodeEnum.start.getType())).findFirst().orElse(null); if (start != null) { passed.add(start.getNodeCode()); } List triggerRecordList = triggerRecordService.getListByTaskId(taskEntity.getId()); List typeList = ImmutableList.of(NodeEnum.global.getType(), NodeEnum.connect.getType()); List divideList = Arrays.stream(DivideRuleEnum.values()).map(DivideRuleEnum::getType).collect(Collectors.toList()); divideList.addAll(typeList); flowMethod.setFlowModel(flowModel); flowMethod.setErrorRule(false); flowMethod.setExtraRule(true); // 节点 (-1没有经过,0.经过 1.当前 2.未经过) for (TemplateNodeEntity node : nodeEntities) { String nodeCode = node.getNodeCode(); // 跳过全局节点、连接线 if (divideList.contains(node.getNodeType())) { continue; } TaskNodeModel model = JsonUtil.getJsonToBean(node, TaskNodeModel.class); // 节点名称 NodeModel nodeModel = JsonUtil.getJsonToBean(node.getNodeJson(), NodeModel.class); model.setNodeName(nodeModel.getNodeName()); if (CollectionUtil.isNotEmpty(currentNodes)) { if (currentNodes.contains(nodeCode)) { model.setType(NodeTypeEnum.current.getType()); if (NodeEnum.end.getType().equals(node.getNodeType())) { model.setType(NodeTypeEnum.pass.getType()); } } } if (CollectionUtil.isNotEmpty(passed)) { if (passed.contains(nodeCode)) { model.setType(NodeTypeEnum.pass.getType()); } } TriggerRecordEntity triggerRecord = triggerRecordList.stream() .filter(e -> ObjectUtil.equals(e.getNodeCode(), nodeModel.getNodeId())).findFirst().orElse(null); if (null != triggerRecord) { String type = NodeTypeEnum.current.getType(); if (ObjectUtil.equals(triggerRecord.getStatus(), TriggerRecordEnum.PASSED.getCode())) { type = NodeTypeEnum.pass.getType(); } else if (ObjectUtil.equals(triggerRecord.getStatus(), TriggerRecordEnum.EXCEPTION.getCode())) { type = NodeTypeEnum.exception.getType(); } model.setType(type); } List userNameList = new ArrayList<>(); if (StringUtil.equals(node.getNodeType(), NodeEnum.start.getType())) { List userIds = new ArrayList<>(); userIds.add(taskEntity.getCreatorUserId()); List users = serviceUtil.getUserName(userIds); UserEntity user = users.get(0); userNameList.add(user.getRealName() + "/" + user.getAccount()); if (!TaskStatusEnum.TO_BE_SUBMIT.getCode().equals(taskEntity.getStatus())) { model.setType(NodeTypeEnum.pass.getType()); } } else if (StringUtil.equals(node.getNodeType(), NodeEnum.subFlow.getType())) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(TaskEntity::getParentId, taskEntity.getId()).eq(TaskEntity::getSubCode, node.getNodeCode()); List list = taskService.list(queryWrapper); List userIds; if (CollectionUtil.isNotEmpty(list)) { userIds = list.stream().map(TaskEntity::getCreatorUserId).collect(Collectors.toList()); } else { flowMethod.setNodeEntity(node); userIds = taskUtil.userListAll(flowMethod); } List users = serviceUtil.getUserName(userIds); if (CollectionUtil.isNotEmpty(users)) { for (UserEntity user : users) { userNameList.add(user.getRealName() + "/" + user.getAccount()); } } } else if (StringUtil.equals(node.getNodeType(), NodeEnum.approver.getType()) || StringUtil.equals(node.getNodeType(), NodeEnum.processing.getType())) { List userIds; List operatorList = operatorUtil.getByNodeCode(isRevoke ? revokeEntity.getTaskId() : taskEntity.getId(), node.getNodeCode()); Integer counterSign = nodeModel.getCounterSign(); // 获取生成经办的人 List statusList = ImmutableList.of(OperatorStateEnum.Revoke.getCode(), OperatorStateEnum.AddSign.getCode(), OperatorStateEnum.Assist.getCode()); List list = operatorList.stream().filter(e -> !statusList.contains(e.getStatus()) && ObjectUtil.equals(e.getParentId(), FlowNature.ParentId)).collect(Collectors.toList()); userIds = list.stream().map(OperatorEntity::getHandleId).collect(Collectors.toList()); // 依次审批 if (counterSign.equals(FlowNature.ImproperApprover)) { OperatorEntity last = list.stream().filter(e -> e.getCompletion().equals(FlowNature.Normal)).findFirst().orElse(null); if (null != last && StringUtil.isNotBlank(last.getHandleAll())) { String[] split = last.getHandleAll().split(","); userIds = Arrays.stream(split).collect(Collectors.toList()); } } // 经办处理人的id为0,为系统自动通过 if (userIds.contains(FlowNature.SYSTEM_CODE)) { // model.setUserName(FlowNature.SYSTEM_NAME); nodeList.add(model); continue; } if (CollectionUtil.isEmpty(userIds)) { flowMethod.setNodeEntity(node); userIds = taskUtil.userListAll(flowMethod); } if (CollectionUtil.isEmpty(userIds)) { nodeList.add(model); continue; } userIds = userIds.stream().distinct().sorted().collect(Collectors.toList()); List users = serviceUtil.getUserName(userIds); if (CollectionUtil.isNotEmpty(users)) { for (String userId : userIds) { UserEntity user = users.stream().filter(e -> e.getId().equals(userId)).findFirst().orElse(null); if (null != user) { userNameList.add(user.getRealName() + "/" + user.getAccount()); } } } } model.setUserName(String.join(",", userNameList)); nodeList.add(model); } return nodeList; } /** * 经过的节点 */ public List getPassed(FlowMethod flowMethod) { List tobePass = flowMethod.getTobePass(); List currentNodes = flowMethod.getCurrentNodes(); TaskEntity taskEntity = flowMethod.getTaskEntity(); String taskId = flowMethod.getTaskId(); List nodeEntityList = flowMethod.getNodeEntityList(); List resList = new ArrayList<>(); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().eq(OperatorEntity::getTaskId, taskId).ne(OperatorEntity::getStatus, OperatorStateEnum.Futility.getCode()); List operatorList = operatorService.list(wrapper); if (CollectionUtil.isNotEmpty(operatorList)) { List nodeCodes = operatorList.stream().map(OperatorEntity::getNodeCode) .filter(e -> !currentNodes.contains(e)).collect(Collectors.toList()); resList.addAll(nodeCodes); } QueryWrapper eventLogWrapper = new QueryWrapper<>(); eventLogWrapper.lambda().eq(EventLogEntity::getTaskId, taskId); eventLogWrapper.lambda().select(EventLogEntity::getId, EventLogEntity::getNodeCode); List eventLogList = eventLogService.list(eventLogWrapper); if (CollectionUtil.isNotEmpty(eventLogList)) { List nodeCodes = eventLogList.stream().map(EventLogEntity::getNodeCode) .filter(e -> !currentNodes.contains(e)).collect(Collectors.toList()); resList.addAll(nodeCodes); } RevokeEntity revokeEntity = revokeService.getRevokeTask(taskEntity.getId()); if (null != revokeEntity) { taskId = revokeEntity.getTaskId(); } if (!ObjectUtil.equals(TaskStatusEnum.BACKED.getCode(), taskEntity.getStatus())) { QueryWrapper taskWrapper = new QueryWrapper<>(); taskWrapper.lambda().eq(TaskEntity::getParentId, taskId); List subFlowList = taskService.list(taskWrapper); List historic = new ArrayList<>(); try { historic = flowAbleUrl.getHistoric(taskEntity.getInstanceId()).stream().map(FlowableHistoricModel::getCode).collect(Collectors.toList()); } catch (Exception e) { e.printStackTrace(); } if (CollectionUtil.isNotEmpty(subFlowList)) { List subCodes = subFlowList.stream().map(TaskEntity::getSubCode) .filter(e -> !currentNodes.contains(e) && !tobePass.contains(e)) .collect(Collectors.toList()); if (null != revokeEntity) { subCodes = subCodes.stream().filter(historic::contains).collect(Collectors.toList()); } resList.addAll(subCodes); } QueryWrapper eventWrapper = new QueryWrapper<>(); eventWrapper.lambda().eq(EventLogEntity::getTaskId, taskId); List eventList = eventLogService.list(eventWrapper); if (CollectionUtil.isNotEmpty(eventList)) { List eventCodes = eventList.stream().map(EventLogEntity::getNodeCode) .filter(e -> !currentNodes.contains(e) && !tobePass.contains(e)) .collect(Collectors.toList()); if (null != revokeEntity) { eventCodes = eventCodes.stream().filter(historic::contains).collect(Collectors.toList()); } resList.addAll(eventCodes); } // 撤销会跳过办理节点 if (null != revokeEntity) { List finalHistoric = historic; List processingList = nodeEntityList.stream() .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.processing.getType()) && !currentNodes.contains(e.getNodeCode()) && finalHistoric.contains(e.getNodeCode())) .map(TemplateNodeEntity::getNodeCode).collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(processingList)) { resList.addAll(processingList); } } } return resList; } /** * 辅助信息 添加归档文件信息 */ public void setFlowFile(NodeModel currentNode, TaskEntity taskEntity, Map nodeProperties) { List auxiliaryList = currentNode.getAuxiliaryInfo(); if (auxiliaryList.isEmpty()) { return; } long count = auxiliaryList.stream().filter(e -> ObjectUtil.equals(e.getConfig().getOn(), 0)).count(); if (count == auxiliaryList.size()) { nodeProperties.put("auxiliaryInfo", null); return; } AuxiliaryInfo auxiliary = auxiliaryList.stream().filter(e -> ObjectUtil.equals(e.getId(), 3)).findFirst().orElse(null); if (null == auxiliary) { return; } AuxiliaryInfoConfig auxiliaryConfig = auxiliary.getConfig(); if (!ObjectUtil.equals(auxiliaryConfig.getOn(), 1)) { return; } String templateId = taskEntity.getTemplateId(); FlowFileModel flowFileModel = FlowFileModel.builder().templateId(templateId).userId(UserProvider.getLoginUserId()) .dataRange(auxiliaryConfig.getDataRange()).build(); List> flowFile = serviceUtil.getFlowFile(flowFileModel); if (CollectionUtil.isEmpty(flowFile)) { return; } Object auxiliaryInfo = nodeProperties.get("auxiliaryInfo"); if (auxiliaryInfo instanceof List) { List> list = (List>) auxiliaryInfo; for (Map map : list) { if (ObjectUtil.equals(map.get("id"), 3)) { Map config = (Map) map.get("config"); config.put("fileList", flowFile); } } } } }