gssong
2024-06-02 512b5204bc717b78bfbb76afaf81076de9a9f302
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
@@ -16,7 +16,7 @@
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.common.enums.BusinessStatusEnum;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.workflow.domain.bo.ProcessInstanceBo;
@@ -26,8 +26,7 @@
import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator;
import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd;
import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd;
import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.dromara.workflow.flowable.handler.FlowProcessEventHandler;
import org.dromara.workflow.service.IActHiProcinstService;
import org.dromara.workflow.service.IActProcessInstanceService;
import org.dromara.workflow.service.IWfNodeConfigService;
@@ -75,9 +74,9 @@
    private final TaskService taskService;
    private final IActHiProcinstService actHiProcinstService;
    private final ManagementService managementService;
    private final FlowEventStrategy flowEventStrategy;
    private final IWfTaskBackNodeService wfTaskBackNodeService;
    private final IWfNodeConfigService wfNodeConfigService;
    private final FlowProcessEventHandler flowProcessEventHandler;
    @Value("${flowable.activity-font-name}")
    private String activityFontName;
@@ -184,28 +183,28 @@
    }
    /**
     * 通过流程实例id获取历史流程图
     * 通过业务id获取历史流程图
     *
     * @param processInstanceId 流程实例id
     * @param businessKey 业务id
     */
    @SneakyThrows
    @Override
    public String getHistoryImage(String processInstanceId) {
    public String getHistoryImage(String businessKey) {
        String processDefinitionId;
        // 获取当前的流程实例
        ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult();
        ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey).singleResult();
        // 如果流程已经结束,则得到结束节点
        if (Objects.isNull(processInstance)) {
            HistoricProcessInstance pi = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
            HistoricProcessInstance pi = QueryUtils.hisInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        } else {
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = QueryUtils.instanceQuery(processInstanceId).singleResult();
            ProcessInstance pi = QueryUtils.instanceQuery(processInstance.getProcessInstanceId()).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }
        // 获得活动的节点
        List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
        List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstance.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
        List<String> highLightedFlows = new ArrayList<>();
        List<String> highLightedNodes = new ArrayList<>();
@@ -240,15 +239,16 @@
    }
    /**
     * 通过流程实例id获取历史流程图运行中,历史等节点
     * 通过业务id获取历史流程图运行中,历史等节点
     *
     * @param processInstanceId 流程实例id
     * @param businessKey 业务id
     */
    @Override
    public Map<String, Object> getHistoryList(String processInstanceId) {
    public Map<String, Object> getHistoryList(String businessKey) {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> taskList = new ArrayList<>();
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
        String processInstanceId = historicProcessInstance.getId();
        StringBuilder xml = new StringBuilder();
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
        // 获取节点
@@ -333,14 +333,15 @@
    /**
     * 获取审批记录
     *
     * @param processInstanceId 流程实例id
     * @param businessKey 业务id
     */
    @Override
    public Map<String, Object> getHistoryRecord(String processInstanceId) {
        Map<String, Object> map = new HashMap<>();
    public List<ActHistoryInfoVo> getHistoryRecord(String businessKey) {
        // 查询任务办理记录
        List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
        List<HistoricTaskInstance> list = QueryUtils.hisTaskBusinessKeyQuery(businessKey).orderByHistoricTaskInstanceEndTime().desc().list();
        list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
        String processInstanceId = historicProcessInstance.getId();
        List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>();
        List<Comment> processInstanceComments = taskService.getProcessInstanceComments(processInstanceId);
        //附件
@@ -378,16 +379,7 @@
            }
            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);
@@ -403,39 +395,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;
    }
    /**
@@ -475,7 +442,8 @@
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) {
        try {
            List<Task> list = QueryUtils.taskQuery(processInvalidBo.getProcessInstanceId()).list();
            List<Task> list = QueryUtils.taskQuery().processInstanceBusinessKey(processInvalidBo.getBusinessKey()).list();
            String processInstanceId = list.get(0).getProcessInstanceId();
            List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
            if (CollUtil.isNotEmpty(subTasks)) {
                subTasks.forEach(e -> taskService.deleteTask(e.getId()));
@@ -487,14 +455,13 @@
            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();
            HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
            BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
            runtimeService.updateBusinessStatus(processInvalidBo.getProcessInstanceId(), BusinessStatusEnum.INVALID.getStatus());
            runtimeService.deleteProcessInstance(processInvalidBo.getProcessInstanceId(), deleteReason);
            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
            if (processHandler != null) {
                processHandler.handleProcess(historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
            }
            runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.INVALID.getStatus());
            runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
            //流程作废监听
            flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(),
                historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -505,40 +472,11 @@
    /**
     * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
     *
     * @param processInstanceIds 流程实例id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRunAndHisInstance(List<String> processInstanceIds) {
        try {
            // 1.删除运行中流程实例
            List<Task> list = QueryUtils.taskQuery(processInstanceIds).list();
            List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
            if (CollUtil.isNotEmpty(subTasks)) {
                subTasks.forEach(e -> taskService.deleteTask(e.getId()));
            }
            runtimeService.bulkDeleteProcessInstances(processInstanceIds, LoginHelper.getUserId() + "删除了当前流程申请");
            // 2.删除历史记录
            List<HistoricProcessInstance> historicProcessInstanceList = QueryUtils.hisInstanceQuery(new HashSet<>(processInstanceIds)).list();
            if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
                historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
            }
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * 按照业务id删除 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
     *
     * @param businessKeys 业务id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRunAndHisInstanceByBusinessKeys(List<String> businessKeys) {
    public boolean deleteRunAndHisInstance(List<String> businessKeys) {
        try {
            // 1.删除运行中流程实例
            List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
@@ -569,12 +507,18 @@
    /**
     * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
     *
     * @param processInstanceIds 流程实例id
     * @param businessKeys 业务id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) {
    public boolean deleteFinishAndHisInstance(List<String> businessKeys) {
        try {
            List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
            if (CollUtil.isEmpty(actHiProcinsts)) {
                log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys);
                return false;
            }
            List<String> processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId);
            historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
@@ -587,13 +531,13 @@
    /**
     * 撤销流程申请
     *
     * @param processInstanceId 流程实例id
     * @param businessKey 业务id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelProcessApply(String processInstanceId) {
    public boolean cancelProcessApply(String businessKey) {
        try {
            ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId)
            ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey)
                .startedBy(String.valueOf(LoginHelper.getUserId())).singleResult();
            if (ObjectUtil.isNull(processInstance)) {
                throw new ServiceException("您不是流程发起人,撤销失败!");
@@ -601,13 +545,14 @@
            if (processInstance.isSuspended()) {
                throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
            }
            String processInstanceId = processInstance.getId();
            BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus());
            List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
            for (Task task : taskList) {
                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)
@@ -623,10 +568,9 @@
                managementService.executeCommand(deleteExecutionCmd);
            }
            runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus());
            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
            if (processHandler != null) {
                processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
            }
            //流程作废监听
            flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(),
                processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
            return true;
        } catch (Exception e) {
            e.printStackTrace();