package jnpf.flowable.util; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.google.common.collect.ImmutableList; import jnpf.flowable.entity.*; import jnpf.flowable.enums.*; import jnpf.flowable.mapper.*; import jnpf.flowable.model.record.ProgressModel; import jnpf.flowable.model.record.RecordVo; import jnpf.flowable.model.record.UserItem; import jnpf.flowable.model.task.FlowModel; import jnpf.flowable.model.templatenode.nodejson.NodeModel; import jnpf.flowable.model.util.FlowNature; import jnpf.permission.entity.UserEntity; import jnpf.util.JsonUtil; import jnpf.util.RandomUtil; import jnpf.util.StringUtil; import jnpf.util.UploaderUtil; 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/26 17:05 */ @Component public class RecordUtil { @Autowired private ServiceUtil serviceUtil; @Autowired private RecordMapper recordMapper; @Autowired private CirculateMapper circulateMapper; @Autowired private OperatorMapper operatorMapper; @Autowired private NodeRecordMapper nodeRecordMapper; @Autowired private TriggerTaskMapper triggerTaskMapper; @Autowired private EventLogMapper eventLogMapper; /** * 获取流转记录 * * @param records 流转记录集合 */ public List getRecordList(List records) { return getRecordList(records, new ArrayList<>()); } /** * 获取流转记录 * * @param records 流转记录集合 */ public List getRecordList(List records, List nodeEntities) { List vos = new ArrayList<>(); if (CollectionUtil.isNotEmpty(records)) { List userList = serviceUtil.getUserName(records.stream().map(RecordEntity::getHandleId).collect(Collectors.toList())); for (RecordEntity record : records) { String nodeCode = record.getNodeCode(); RecordVo vo = JsonUtil.getJsonToBean(record, RecordVo.class); UserEntity userEntity = userList.stream().filter(t -> t.getId().equals(record.getHandleId())).findFirst().orElse(null); vo.setUserName(userEntity != null ? userEntity.getRealName() + "/" + userEntity.getAccount() : ""); if (userEntity != null) { vo.setHeadIcon(UploaderUtil.uploaderImg(userEntity.getHeadIcon())); } // 设置流转操作人 String handleUserId = record.getHandleUserId(); if (StringUtil.isNotEmpty(handleUserId)) { List userIds = Arrays.stream(handleUserId.split(",")).collect(Collectors.toList()); List handleUserList = serviceUtil.getUserName(userIds); List handleUserName = new ArrayList<>(); for (String userId : userIds) { UserEntity user = handleUserList.stream().filter(t -> t.getId().equals(userId)).findFirst().orElse(null); if (null != user) { handleUserName.add(user.getRealName() + "/" + user.getAccount()); } } if (CollectionUtil.isNotEmpty(handleUserName)) { vo.setHandleUserName(String.join(",", handleUserName)); } } if (record.getExpandField() != null) { List> expandField = JsonUtil.getJsonToListMap(record.getExpandField()); vo.setApprovalField(expandField); } TemplateNodeEntity templateNode = nodeEntities.stream().filter(e -> Objects.equals(nodeCode, e.getNodeCode())).findFirst().orElse(null); if (templateNode != null) { vo.setIsOutSideNode(Objects.equals(templateNode.getNodeType(), NodeEnum.outside.getType())); } vos.add(vo); } } return vos; } /** * 进度 * * @param flowModel 参数 */ public List getProgressList(FlowModel flowModel) { List progressList = new ArrayList<>(); String opType = flowModel.getOpType(); TaskEntity taskEntity = flowModel.getTaskEntity(); RecordEntity recordEntity = flowModel.getRecordEntity(); List nodeEntities = flowModel.getNodeEntityList(); List nodeRecordList = nodeRecordMapper.getList(taskEntity.getId()); List operatorList = operatorMapper.getList(taskEntity.getId()); List recordList = recordMapper.getList(taskEntity.getId()); List eventLogList = eventLogMapper.getList(taskEntity.getId()); List circulateList = circulateMapper.getList(taskEntity.getId()); List userIds = new ArrayList<>(); List operatorUserIds = operatorList.stream().map(OperatorEntity::getHandleId).collect(Collectors.toList()); List recordUserIds = recordList.stream().map(RecordEntity::getHandleId).collect(Collectors.toList()); userIds.addAll(operatorUserIds); userIds.addAll(recordUserIds); userIds = userIds.stream().distinct().collect(Collectors.toList()); List users = serviceUtil.getUserName(userIds, false); for (NodeRecordEntity nodeRecord : nodeRecordList) { TemplateNodeEntity nodeEntity = nodeEntities.stream().filter(e -> e.getNodeCode().equals(nodeRecord.getNodeCode())).findFirst().orElse(null); if (null == nodeEntity) { continue; } NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class); if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) { continue; } ProgressModel model = new ProgressModel(); model.setId(RandomUtil.uuId()); model.setStartTime(nodeRecord.getCreatorTime().getTime()); model.setNodeId(nodeRecord.getNodeId()); model.setNodeCode(nodeRecord.getNodeCode()); model.setNodeName(nodeRecord.getNodeName()); model.setNodeType(NodeEnum.approver.getType()); model.setNodeStatus(nodeRecord.getNodeStatus()); boolean isCirculate = circulateList.stream().anyMatch(e -> e.getNodeId().equals(nodeRecord.getNodeId())); model.setIsCirculate(isCirculate); if (nodeModel.getType().equals(NodeEnum.start.getType())) { model.setNodeType(NodeEnum.start.getType()); progressList.add(model); continue; } if (nodeModel.getType().equals(NodeEnum.outside.getType())) { model.setNodeType(NodeEnum.outside.getType()); progressList.add(model); continue; } model.setCounterSign(nodeModel.getCounterSign()); model.setAssigneeType(nodeModel.getAssigneeType()); List records = recordList.stream() .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId()) && Objects.equals(e.getNodeId(), nodeRecord.getNodeId())) .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed()).collect(Collectors.toList()); model.setApproverCount(records.size()); List items = new ArrayList<>(); for (int i = 0; i < records.size(); i++) { UserItem item = new UserItem(); RecordEntity record = records.get(i); UserEntity user = users.stream().filter(e -> ObjectUtil.equals(record.getHandleId(), e.getId())).findFirst().orElse(null); if (user != null) { item.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon())); item.setUserId(user.getId()); item.setUserName(user.getRealName()); } else { item.setHeadIcon(UploaderUtil.uploaderImg(FlowNature.SYSTEM_HEAD_ICON)); item.setUserId(FlowNature.SYSTEM_CODE); item.setUserName(FlowNature.SYSTEM_NAME); } item.setHandleType(record.getHandleType()); items.add(item); if (i == 3) { break; } } model.setApprover(items); // 判断是否存在任务流程 model.setShowTaskFlow(triggerTaskMapper.existTriggerTask(taskEntity.getId(), model.getNodeId())); progressList.add(model); } // 当前节点 List status = ImmutableList.of(TaskStatusEnum.RECALL.getCode(), TaskStatusEnum.BACKED.getCode(), TaskStatusEnum.CANCEL.getCode()); if (taskEntity.getEndTime() == null && !status.contains(taskEntity.getStatus())) { String currentNodeCode = taskEntity.getCurrentNodeCode(); if (StringUtil.isNotBlank(currentNodeCode)) { List currentCodeList = Arrays.stream(currentNodeCode.split(",")).collect(Collectors.toList()); for (int i = 0; i < currentCodeList.size(); i++) { String nodeCode = currentCodeList.get(i); TemplateNodeEntity nodeEntity = nodeEntities.stream().filter(e -> e.getNodeCode().equals(nodeCode)).findFirst().orElse(null); if (null == nodeEntity) { continue; } NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class); if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) { continue; } boolean isProcessing = ObjectUtil.equals(nodeEntity.getNodeType(), NodeEnum.processing.getType()); boolean isOutside = ObjectUtil.equals(nodeEntity.getNodeType(), NodeEnum.outside.getType()); ProgressModel model = new ProgressModel(); model.setId(RandomUtil.uuId()); model.setNodeCode(nodeCode); model.setNodeName(nodeModel.getNodeName()); model.setNodeType(isProcessing ? NodeEnum.processing.getType() : isOutside ? NodeEnum.outside.getType() : NodeEnum.approver.getType()); model.setNodeStatus(isProcessing ? NodeStateEnum.transact.getCode() : NodeStateEnum.approval.getCode()); model.setCounterSign(nodeModel.getCounterSign()); model.setAssigneeType(nodeModel.getAssigneeType()); List operators = operatorList.stream() .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId()) && !(ObjectUtil.equals(e.getCompletion(), FlowNature.Action) && null == e.getHandleTime() && !ObjectUtil.equals(e.getParentId(), FlowNature.ParentId)) && !Objects.equals(e.getStatus(), OperatorStateEnum.Assist.getCode()) && !Objects.equals(e.getStatus(), OperatorStateEnum.Futility.getCode()) ).sorted(Comparator.comparing(OperatorEntity::getCreatorTime, Comparator.reverseOrder()) .thenComparing(OperatorEntity::getCompletion)) .collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(operators)) { OperatorEntity operator = operators.get(0); String nodeId = operator.getNodeId(); model.setStartTime(operator.getCreatorTime().getTime()); operators = operators.stream().filter(e -> ObjectUtil.equals(e.getNodeId(), nodeId)).collect(Collectors.toList()); // 触发节点选择同步,变更为等待中状态 if (ObjectUtil.equals(operator.getStatus(), OperatorStateEnum.Waiting.getCode())) { model.setNodeStatus(NodeStateEnum.wait.getCode()); } model.setNodeId(nodeId); boolean isCirculate = circulateList.stream().anyMatch(e -> e.getNodeId().equals(nodeId)); model.setIsCirculate(isCirculate); } else { List eventLogs = eventLogList.stream().filter(e -> Objects.equals(e.getNodeCode(), nodeCode)).sorted(Comparator.comparing(EventLogEntity::getCreatorTime, Comparator.reverseOrder())).collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(eventLogs)) { EventLogEntity eventLog = eventLogs.get(0); String nodeId = eventLog.getNodeId(); model.setStartTime(eventLog.getCreatorTime().getTime()); model.setOutSideStatus(Objects.equals(eventLog.getStatus(), 0)); model.setErrorTip(eventLog.getResult()); model.setErrorData(eventLog.getData()); model.setNodeId(nodeId); if (Objects.equals(OpTypeEnum.LaunchDetail.getType(), opType)) { model.setIsRetry(true); } if (Objects.equals(OpTypeEnum.Done.getType(), opType)) { if (recordEntity != null && Objects.equals(recordEntity.getNodeCode(), eventLog.getUpNode())) { model.setIsRetry(true); } } } } List records = recordList.stream() .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId())) .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed()).collect(Collectors.toList()); List items = new ArrayList<>(); for (OperatorEntity operator : operators) { UserItem item = new UserItem(); UserEntity user = users.stream().filter(e -> ObjectUtil.equals(operator.getHandleId(), e.getId())).findFirst().orElse(null); if (user != null) { item.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon())); item.setUserId(user.getId()); item.setUserName(user.getRealName()); } else { if (ObjectUtil.equals(operator.getHandleId(), FlowNature.SYSTEM_CODE)) { item.setHeadIcon(FlowNature.SYSTEM_HEAD_ICON); item.setUserName(FlowNature.SYSTEM_NAME); item.setUserId(FlowNature.SYSTEM_CODE); } } if (null != operator.getHandleStatus() && null != operator.getHandleTime()) { item.setHandleType(operator.getHandleStatus()); } else { RecordEntity record = records.stream().sorted(Comparator.comparing(RecordEntity::getId).reversed()) .filter(e -> ObjectUtil.equals(e.getOperatorId(), operator.getId()) && ObjectUtil.equals(e.getNodeId(), operator.getNodeId()) && !ObjectUtil.equals(e.getStatus(), FlowNature.Invalid) && !ObjectUtil.equals(e.getHandleType(), RecordEnum.back.getCode())) .findFirst().orElse(null); if (null != record) { item.setHandleType(record.getHandleType()); } else { // -1.待审 -2.未审 -3.待办理 -4.未办理(暂未用到) item.setHandleType(isProcessing ? -3 : -1); } } items.add(item); } model.setApproverCount(items.size()); items = items.stream().sorted(Comparator.comparing(UserItem::getHandleType)).collect(Collectors.toList()); if (items.size() > 4) { items = items.subList(0, 4); } model.setApprover(items); progressList.add(model); } } } // 添加结束节点 if (taskEntity.getEndTime() != null) { ProgressModel model = new ProgressModel(); model.setId(RandomUtil.uuId()); model.setStartTime(taskEntity.getEndTime().getTime()); model.setNodeType(NodeEnum.end.getType()); model.setNodeName(FlowNature.END_NAME); progressList.add(model); } return progressList; } }