songgaoshuai
2024-05-27 67ab7a04ad7cd2e3d9a3dcfd2d0604981080302f
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
@@ -3,11 +3,12 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -21,10 +22,7 @@
import org.dromara.workflow.domain.bo.ProcessInstanceBo;
import org.dromara.workflow.domain.bo.ProcessInvalidBo;
import org.dromara.workflow.domain.bo.TaskUrgingBo;
import org.dromara.workflow.domain.vo.ActHistoryInfoVo;
import org.dromara.workflow.domain.vo.GraphicInfoVo;
import org.dromara.workflow.domain.vo.ProcessInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.domain.vo.*;
import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator;
import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd;
import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd;
@@ -32,6 +30,8 @@
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.dromara.workflow.service.IActHiProcinstService;
import org.dromara.workflow.service.IActProcessInstanceService;
import org.dromara.workflow.service.IWfNodeConfigService;
import org.dromara.workflow.service.IWfTaskBackNodeService;
import org.dromara.workflow.utils.QueryUtils;
import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.bpmn.model.*;
@@ -53,13 +53,11 @@
import org.springframework.transaction.annotation.Transactional;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 流程实例 服务层实现
@@ -78,6 +76,8 @@
    private final IActHiProcinstService actHiProcinstService;
    private final ManagementService managementService;
    private final FlowEventStrategy flowEventStrategy;
    private final IWfTaskBackNodeService wfTaskBackNodeService;
    private final IWfNodeConfigService wfNodeConfigService;
    @Value("${flowable.activity-font-name}")
    private String activityFontName;
@@ -120,8 +120,20 @@
            processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus()));
            list.add(processInstanceVo);
        }
        if (CollUtil.isNotEmpty(list)) {
            List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
            List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
            for (ProcessInstanceVo processInstanceVo : list) {
                if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
                    wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
                }
            }
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
        TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
        build.setRows(list);
        build.setTotal(count);
        return build;
    }
    /**
@@ -155,8 +167,20 @@
            processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(historicProcessInstance.getBusinessStatus()));
            list.add(processInstanceVo);
        }
        if (CollUtil.isNotEmpty(list)) {
            List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
            List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
            for (ProcessInstanceVo processInstanceVo : list) {
                if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
                    wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
                }
            }
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
        TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
        build.setRows(list);
        build.setTotal(count);
        return build;
    }
    /**
@@ -212,7 +236,7 @@
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        CustomDefaultProcessDiagramGenerator diagramGenerator = new CustomDefaultProcessDiagramGenerator();
        InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodeList, highLightedFlows, activityFontName, labelFontName, annotationFontName, null, 1.0, true);
        return Base64.encode(IOUtils.toByteArray(inputStream));
        return Base64.encode(IoUtil.readBytes(inputStream));
    }
    /**
@@ -258,14 +282,9 @@
        map.put("taskList", taskList);
        List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId);
        map.put("historyList", historyTaskList);
        InputStream inputStream;
        try {
            inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
            xml.append(IOUtils.toString(inputStream, String.valueOf(StandardCharsets.UTF_8)));
            map.put("xml", xml.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
        xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
        map.put("xml", xml.toString());
        return map;
    }
@@ -299,6 +318,12 @@
                    historyInfoVo.setStartTime(e.getStartTime());
                    historyInfoVo.setEndTime(null);
                    historyInfoVo.setRunDuration(null);
                    if (ObjectUtil.isEmpty(e.getAssignee())) {
                        ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId());
                        if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                            historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                        }
                    }
                });
            historyInfoVoList.add(historyInfoVo);
        }
@@ -311,8 +336,7 @@
     * @param processInstanceId 流程实例id
     */
    @Override
    public Map<String, Object> getHistoryRecord(String processInstanceId) {
        Map<String, Object> map = new HashMap<>();
    public List<ActHistoryInfoVo> getHistoryRecord(String processInstanceId) {
        // 查询任务办理记录
        List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
        list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
@@ -337,11 +361,6 @@
            if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
                actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
            }
            try {
                actHistoryInfoVo.setAssignee(StringUtils.isNotBlank(historicTaskInstance.getAssignee()) ? Long.valueOf(historicTaskInstance.getAssignee()) : null);
            } catch (NumberFormatException ignored) {
                log.warn("当前任务【{}】,办理人转换人员ID【{}】异常!", historicTaskInstance.getName(), historicTaskInstance.getAssignee());
            }
            //附件
            if (CollUtil.isNotEmpty(attachmentList)) {
                List<Attachment> attachments = attachmentList.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).collect(Collectors.toList());
@@ -349,25 +368,19 @@
                    actHistoryInfoVo.setAttachmentList(attachments);
                }
            }
            //设置人员id
            if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) {
                ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId());
                if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                    actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                }
            }
            actHistoryInfoVoList.add(actHistoryInfoVo);
        }
        List<ActHistoryInfoVo> collect = new ArrayList<>();
        // 待办理
        List<ActHistoryInfoVo> waitingTask = StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null);
        // 已办理
        List<ActHistoryInfoVo> finishTask = StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null);
        collect.addAll(waitingTask);
        collect.addAll(finishTask);
        // 审批记录
        map.put("historyRecordList", collect);
        List<ActHistoryInfoVo> nodeInfoList = new ArrayList<>();
        Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
        for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
            ActHistoryInfoVo actHistoryInfoVo = BeanUtil.toBean(entry.getValue().get(0), ActHistoryInfoVo.class);
            String nickName = entry.getValue().stream().filter(e -> StringUtils.isNotBlank(e.getNickName()) && e.getEndTime() == null).map(ActHistoryInfoVo::getNickName).toList().stream().distinct().collect(Collectors.joining(StringUtils.SEPARATOR));
            if (StringUtils.isNotBlank(nickName)) {
                actHistoryInfoVo.setNickName(nickName);
            }
            actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst()
                .ifPresent(e -> {
                    actHistoryInfoVo.setStatus("已处理");
@@ -380,39 +393,14 @@
                    actHistoryInfoVo.setEndTime(null);
                    actHistoryInfoVo.setRunDuration(null);
                });
            nodeInfoList.add(actHistoryInfoVo);
        }
        // 节点信息
        map.put("nodeListInfo", nodeInfoList);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(list.get(0).getProcessDefinitionId());
        List<GraphicInfoVo> graphicInfoVos = new ArrayList<>();
        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
        //节点图形信息
        buildGraphicInfo(flowElements, graphicInfoVos, bpmnModel);
        map.put("graphicInfoVos", graphicInfoVos);
        return map;
    }
        List<ActHistoryInfoVo> recordList = new ArrayList<>();
        // 待办理
        recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null));
        // 已办理
        recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null));
    /**
     * 构建节点图形信息
     *
     * @param flowElements 节点
     */
    private static void buildGraphicInfo(Collection<FlowElement> flowElements, List<GraphicInfoVo> graphicInfoVos, BpmnModel bpmnModel) {
        for (FlowElement flowElement : flowElements) {
            if (flowElement instanceof SubProcess) {
                Collection<FlowElement> subFlowElements = ((SubProcess) flowElement).getFlowElements();
                buildGraphicInfo(subFlowElements, graphicInfoVos, bpmnModel);
            } else {
                if (flowElement instanceof UserTask) {
                    GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowElement.getId());
                    GraphicInfoVo graphicInfoVo = BeanUtil.toBean(graphicInfo, GraphicInfoVo.class);
                    graphicInfoVo.setNodeId(flowElement.getId());
                    graphicInfoVo.setNodeName(flowElement.getName());
                    graphicInfoVos.add(graphicInfoVo);
                }
            }
        }
        return recordList;
    }
    /**
@@ -464,10 +452,8 @@
            for (Task task : StreamUtils.filter(list, e -> StringUtils.isBlank(e.getParentTaskId()))) {
                taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.INVALID.getStatus(), deleteReason);
            }
            HistoricProcessInstance historicProcessInstance =  QueryUtils.hisInstanceQuery(processInvalidBo.getProcessInstanceId()).singleResult();
            if (ObjectUtil.isNotEmpty(historicProcessInstance) && BusinessStatusEnum.FINISH.getStatus().equals(historicProcessInstance.getBusinessStatus())) {
                throw new ServiceException("该单据已完成申请!");
            }
            HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInvalidBo.getProcessInstanceId()).singleResult();
            BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
            runtimeService.updateBusinessStatus(processInvalidBo.getProcessInstanceId(), BusinessStatusEnum.INVALID.getStatus());
            runtimeService.deleteProcessInstance(processInvalidBo.getProcessInstanceId(), deleteReason);
            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
@@ -502,6 +488,7 @@
            if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
                historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
            }
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -536,6 +523,7 @@
            if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
                historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
            }
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -553,6 +541,7 @@
    public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) {
        try {
            historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -577,15 +566,13 @@
            if (processInstance.isSuspended()) {
                throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
            }
            if (BusinessStatusEnum.CANCEL.getStatus().equals(processInstance.getBusinessStatus())) {
                throw new ServiceException("该单据已撤销!");
            }
            BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus());
            List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
            for (Task task : taskList) {
                taskService.setAssignee(task.getId(), String.valueOf(LoginHelper.getUserId()));
                taskService.setAssignee(task.getId(), null);
                taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.CANCEL.getStatus(), LoginHelper.getLoginUser().getNickname() + ":撤销申请");
            }
            HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
            HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
            List<String> nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey);
            runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstanceId)
@@ -621,7 +608,7 @@
    public TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) {
        List<ProcessInstanceVo> list = new ArrayList<>();
        HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery();
        query.startedBy(bo.getStartUserId());
        query.startedBy(String.valueOf(LoginHelper.getUserId()));
        if (StringUtils.isNotBlank(bo.getName())) {
            query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%");
        }
@@ -653,8 +640,20 @@
            }
            list.add(processInstanceVo);
        }
        if (CollUtil.isNotEmpty(list)) {
            List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
            List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
            for (ProcessInstanceVo processInstanceVo : list) {
                if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
                    wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
                }
            }
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
        TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build();
        build.setRows(list);
        build.setTotal(count);
        return build;
    }
    /**