From 69e3afc7707d467b758858b52d3784947f7a502b Mon Sep 17 00:00:00 2001 From: 疯狂的狮子Li <15040126243@163.com> Date: 星期一, 20 五月 2024 10:25:23 +0800 Subject: [PATCH] !538 ♥️发布 5.2.0-BETA 公测版本 Merge pull request !538 from 疯狂的狮子Li/dev --- ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java | 683 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 683 insertions(+), 0 deletions(-) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java new file mode 100644 index 0000000..b64c79e --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java @@ -0,0 +1,683 @@ +package org.dromara.workflow.service.impl; + +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.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +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.workflow.common.enums.TaskStatusEnum; +import org.dromara.workflow.domain.ActHiProcinst; +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.*; +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.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.*; +import org.flowable.engine.*; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.runtime.ProcessInstanceQuery; +import org.flowable.engine.task.Attachment; +import org.flowable.engine.task.Comment; +import org.flowable.task.api.Task; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.awt.*; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 娴佺▼瀹炰緥 鏈嶅姟灞傚疄鐜� + * + * @author may + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class ActProcessInstanceServiceImpl implements IActProcessInstanceService { + + private final RepositoryService repositoryService; + private final RuntimeService runtimeService; + private final HistoryService historyService; + private final TaskService taskService; + 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; + + @Value("${flowable.label-font-name}") + private String labelFontName; + + @Value("${flowable.annotation-font-name}") + private String annotationFontName; + + /** + * 鍒嗛〉鏌ヨ姝e湪杩愯鐨勬祦绋嬪疄渚� + * + * @param bo 鍙傛暟 + */ + @Override + public TableDataInfo<ProcessInstanceVo> getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) { + List<ProcessInstanceVo> list = new ArrayList<>(); + ProcessInstanceQuery query = QueryUtils.instanceQuery(); + if (StringUtils.isNotBlank(bo.getName())) { + query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); + } + if (StringUtils.isNotBlank(bo.getKey())) { + query.processDefinitionKey(bo.getKey()); + } + if (StringUtils.isNotBlank(bo.getStartUserId())) { + query.startedBy(bo.getStartUserId()); + } + if (StringUtils.isNotBlank(bo.getBusinessKey())) { + query.processInstanceBusinessKey(bo.getBusinessKey()); + } + if (StringUtils.isNotBlank(bo.getCategoryCode())) { + query.processDefinitionCategory(bo.getCategoryCode()); + } + query.orderByStartTime().desc(); + List<ProcessInstance> processInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); + for (ProcessInstance processInstance : processInstances) { + ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); + processInstanceVo.setIsSuspended(processInstance.isSuspended()); + 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(); + TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build(); + build.setRows(list); + build.setTotal(count); + return build; + } + + /** + * 鍒嗛〉鏌ヨ宸茬粨鏉熺殑娴佺▼瀹炰緥 + * + * @param bo 鍙傛暟 + */ + @Override + public TableDataInfo<ProcessInstanceVo> getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) { + List<ProcessInstanceVo> list = new ArrayList<>(); + HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery() + .finished().orderByProcessInstanceEndTime().desc(); + if (StringUtils.isNotEmpty(bo.getName())) { + query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); + } + if (StringUtils.isNotBlank(bo.getKey())) { + query.processDefinitionKey(bo.getKey()); + } + if (StringUtils.isNotEmpty(bo.getStartUserId())) { + query.startedBy(bo.getStartUserId()); + } + if (StringUtils.isNotBlank(bo.getBusinessKey())) { + query.processInstanceBusinessKey(bo.getBusinessKey()); + } + if (StringUtils.isNotBlank(bo.getCategoryCode())) { + query.processDefinitionCategory(bo.getCategoryCode()); + } + List<HistoricProcessInstance> historicProcessInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); + for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) { + ProcessInstanceVo processInstanceVo = BeanUtil.toBean(historicProcessInstance, ProcessInstanceVo.class); + 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(); + TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build(); + build.setRows(list); + build.setTotal(count); + return build; + } + + /** + * 閫氳繃娴佺▼瀹炰緥id鑾峰彇鍘嗗彶娴佺▼鍥� + * + * @param processInstanceId 娴佺▼瀹炰緥id + */ + @SneakyThrows + @Override + public String getHistoryImage(String processInstanceId) { + String processDefinitionId; + // 鑾峰彇褰撳墠鐨勬祦绋嬪疄渚� + ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult(); + // 濡傛灉娴佺▼宸茬粡缁撴潫锛屽垯寰楀埌缁撴潫鑺傜偣 + if (Objects.isNull(processInstance)) { + HistoricProcessInstance pi = QueryUtils.hisInstanceQuery(processInstanceId).singleResult(); + processDefinitionId = pi.getProcessDefinitionId(); + } else { + // 鏍规嵁娴佺▼瀹炰緥ID鑾峰緱褰撳墠澶勪簬娲诲姩鐘舵�佺殑ActivityId鍚堥泦 + ProcessInstance pi = QueryUtils.instanceQuery(processInstanceId).singleResult(); + processDefinitionId = pi.getProcessDefinitionId(); + } + + // 鑾峰緱娲诲姩鐨勮妭鐐� + List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list(); + + List<String> highLightedFlows = new ArrayList<>(); + List<String> highLightedNodes = new ArrayList<>(); + //楂樹寒 + for (HistoricActivityInstance tempActivity : highLightedFlowList) { + if (FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType())) { + //楂樹寒绾� + highLightedFlows.add(tempActivity.getActivityId()); + } else { + //楂樹寒鑺傜偣 + if (tempActivity.getEndTime() == null) { + highLightedNodes.add(Color.RED.toString() + tempActivity.getActivityId()); + } else { + highLightedNodes.add(tempActivity.getActivityId()); + } + } + } + List<String> highLightedNodeList = new ArrayList<>(); + //杩愯涓殑鑺傜偣 + List<String> redNodeCollect = StreamUtils.filter(highLightedNodes, e -> e.contains(Color.RED.toString())); + //鎺掗櫎涓庤繍琛屼腑鐩稿悓鐨勮妭鐐� + for (String nodeId : highLightedNodes) { + if (!nodeId.contains(Color.RED.toString()) && !redNodeCollect.contains(Color.RED + nodeId)) { + highLightedNodeList.add(nodeId); + } + } + highLightedNodeList.addAll(redNodeCollect); + 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(IoUtil.readBytes(inputStream)); + } + + /** + * 閫氳繃娴佺▼瀹炰緥id鑾峰彇鍘嗗彶娴佺▼鍥捐繍琛屼腑锛屽巻鍙茬瓑鑺傜偣 + * + * @param processInstanceId 娴佺▼瀹炰緥id + */ + @Override + public Map<String, Object> getHistoryList(String processInstanceId) { + Map<String, Object> map = new HashMap<>(); + List<Map<String, Object>> taskList = new ArrayList<>(); + HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult(); + StringBuilder xml = new StringBuilder(); + ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId()); + // 鑾峰彇鑺傜偣 + List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list(); + for (HistoricActivityInstance tempActivity : highLightedFlowList) { + Map<String, Object> task = new HashMap<>(); + if (!FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType()) && + !FlowConstant.PARALLEL_GATEWAY.equals(tempActivity.getActivityType()) && + !FlowConstant.EXCLUSIVE_GATEWAY.equals(tempActivity.getActivityType()) && + !FlowConstant.INCLUSIVE_GATEWAY.equals(tempActivity.getActivityType()) + ) { + task.put("key", tempActivity.getActivityId()); + task.put("completed", tempActivity.getEndTime() != null); + task.put("activityType", tempActivity.getActivityType()); + taskList.add(task); + } + } + ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult(); + if (processInstance != null) { + taskList = taskList.stream().filter(e -> !e.get("activityType").equals(FlowConstant.END_EVENT)).collect(Collectors.toList()); + } + //鏌ヨ鍑鸿繍琛屼腑鑺傜偣 + List<Map<String, Object>> runtimeNodeList = taskList.stream().filter(e -> !(Boolean) e.get("completed")).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(runtimeNodeList)) { + Iterator<Map<String, Object>> iterator = taskList.iterator(); + while (iterator.hasNext()) { + Map<String, Object> next = iterator.next(); + runtimeNodeList.stream().filter(t -> t.get("key").equals(next.get("key")) && (Boolean) next.get("completed")).findFirst().ifPresent(t -> iterator.remove()); + } + } + map.put("taskList", taskList); + List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId); + map.put("historyList", historyTaskList); + InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); + xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8)); + map.put("xml", xml.toString()); + return map; + } + + /** + * 鑾峰彇鍘嗗彶浠诲姟鑺傜偣淇℃伅 + * + * @param processInstanceId 娴佺▼瀹炰緥id + */ + private List<ActHistoryInfoVo> getHistoryTaskList(String processInstanceId) { + //鏌ヨ浠诲姟鍔炵悊璁板綍 + List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list(); + list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed()); + List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>(); + for (HistoricTaskInstance historicTaskInstance : list) { + ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); + BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); + actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "寰呭鐞�" : "宸插鐞�"); + if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { + actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); + } + actHistoryInfoVoList.add(actHistoryInfoVo); + } + List<ActHistoryInfoVo> historyInfoVoList = new ArrayList<>(); + Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey); + for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) { + ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo(); + BeanUtils.copyProperties(entry.getValue().get(0), historyInfoVo); + actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst() + .ifPresent(e -> { + historyInfoVo.setStatus("寰呭鐞�"); + 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); + } + return historyInfoVoList; + } + + /** + * 鑾峰彇瀹℃壒璁板綍 + * + * @param processInstanceId 娴佺▼瀹炰緥id + */ + @Override + 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()); + List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>(); + List<Comment> processInstanceComments = taskService.getProcessInstanceComments(processInstanceId); + //闄勪欢 + List<Attachment> attachmentList = taskService.getProcessInstanceAttachments(processInstanceId); + for (HistoricTaskInstance historicTaskInstance : list) { + ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); + BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); + if (actHistoryInfoVo.getEndTime() == null) { + actHistoryInfoVo.setStatus(TaskStatusEnum.WAITING.getStatus()); + actHistoryInfoVo.setStatusName(TaskStatusEnum.WAITING.getDesc()); + } + if (CollUtil.isNotEmpty(processInstanceComments)) { + processInstanceComments.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).findFirst().ifPresent(e -> { + actHistoryInfoVo.setComment(e.getFullMessage()); + actHistoryInfoVo.setStatus(e.getType()); + actHistoryInfoVo.setStatusName(TaskStatusEnum.findByStatus(e.getType())); + }); + } + if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { + actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); + } + //闄勪欢 + if (CollUtil.isNotEmpty(attachmentList)) { + List<Attachment> attachments = attachmentList.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(attachments)) { + 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); + } + // 瀹℃壒璁板綍 + 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); + actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst() + .ifPresent(e -> { + actHistoryInfoVo.setStatus("宸插鐞�"); + actHistoryInfoVo.setStartTime(e.getStartTime()); + }); + actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst() + .ifPresent(e -> { + actHistoryInfoVo.setStatus("寰呭鐞�"); + actHistoryInfoVo.setStartTime(e.getStartTime()); + actHistoryInfoVo.setEndTime(null); + actHistoryInfoVo.setRunDuration(null); + }); + } + List<ActHistoryInfoVo> recordList = new ArrayList<>(); + // 寰呭姙鐞� + recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null)); + // 宸插姙鐞� + recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null)); + + return recordList; + } + + /** + * 浠诲姟瀹屾垚鏃堕棿澶勭悊 + * + * @param time 鏃堕棿 + */ + private String getDuration(long time) { + + long day = time / (24 * 60 * 60 * 1000); + long hour = (time / (60 * 60 * 1000) - day * 24); + long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60); + long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); + + if (day > 0) { + return day + "澶�" + hour + "灏忔椂" + minute + "鍒嗛挓"; + } + if (hour > 0) { + return hour + "灏忔椂" + minute + "鍒嗛挓"; + } + if (minute > 0) { + return minute + "鍒嗛挓"; + } + if (second > 0) { + return second + "绉�"; + } else { + return 0 + "绉�"; + } + } + + /** + * 浣滃簾娴佺▼瀹炰緥锛屼笉浼氬垹闄ゅ巻鍙茶褰�(鍒犻櫎杩愯涓殑瀹炰緥) + * + * @param processInvalidBo 鍙傛暟 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) { + try { + List<Task> list = QueryUtils.taskQuery(processInvalidBo.getProcessInstanceId()).list(); + List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); + if (CollUtil.isNotEmpty(subTasks)) { + subTasks.forEach(e -> taskService.deleteTask(e.getId())); + } + String deleteReason = LoginHelper.getLoginUser().getNickname() + "浣滃簾浜嗗綋鍓嶇敵璇凤紒"; + if (StringUtils.isNotBlank(processInvalidBo.getDeleteReason())) { + deleteReason = LoginHelper.getLoginUser().getNickname() + "浣滃簾鐞嗙敱:" + processInvalidBo.getDeleteReason(); + } + 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(); + 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); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 杩愯涓殑瀹炰緥 鍒犻櫎绋嬪疄渚嬶紝鍒犻櫎鍘嗗彶璁板綍锛屽垹闄や笟鍔′笌娴佺▼鍏宠仈淇℃伅 + * + * @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) { + try { + // 1.鍒犻櫎杩愯涓祦绋嬪疄渚� + List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys); + if (CollUtil.isEmpty(actHiProcinsts)) { + log.warn("褰撳墠涓氬姟ID:{}鏌ヨ鍒版祦绋嬪疄渚嬩负绌猴紒", businessKeys); + return false; + } + List<String> processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId); + 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()); + } + } + + /** + * 宸插畬鎴愮殑瀹炰緥 鍒犻櫎绋嬪疄渚嬶紝鍒犻櫎鍘嗗彶璁板綍锛屽垹闄や笟鍔′笌娴佺▼鍏宠仈淇℃伅 + * + * @param processInstanceIds 娴佺▼瀹炰緥id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) { + try { + historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); + wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); + return true; + } catch (Exception e) { + e.printStackTrace(); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 鎾ら攢娴佺▼鐢宠 + * + * @param processInstanceId 娴佺▼瀹炰緥id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean cancelProcessApply(String processInstanceId) { + try { + ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId) + .startedBy(String.valueOf(LoginHelper.getUserId())).singleResult(); + if (ObjectUtil.isNull(processInstance)) { + throw new ServiceException("鎮ㄤ笉鏄祦绋嬪彂璧蜂汉,鎾ら攢澶辫触!"); + } + if (processInstance.isSuspended()) { + throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); + } + 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); + List<String> nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey); + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(processInstanceId) + .moveActivityIdsToSingleActivityId(nodeIds, historicTaskInstance.getTaskDefinitionKey()).changeState(); + Task task = QueryUtils.taskQuery(processInstanceId).list().get(0); + taskService.setAssignee(task.getId(), historicTaskInstance.getAssignee()); + //鑾峰彇骞惰缃戝叧鎵ц鍚庝繚鐣欑殑鎵ц瀹炰緥鏁版嵁 + ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId()); + List<ExecutionEntity> executionEntities = managementService.executeCommand(childByExecutionIdCmd); + //鍒犻櫎娴佺▼瀹炰緥鍨冨溇鏁版嵁 + for (ExecutionEntity executionEntity : executionEntities) { + DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); + 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); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + throw new ServiceException("鎾ら攢澶辫触:" + e.getMessage()); + } + } + + /** + * 鍒嗛〉鏌ヨ褰撳墠鐧诲綍浜哄崟鎹� + * + * @param bo 鍙傛暟 + */ + @Override + public TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) { + List<ProcessInstanceVo> list = new ArrayList<>(); + HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery(); + query.startedBy(String.valueOf(LoginHelper.getUserId())); + if (StringUtils.isNotBlank(bo.getName())) { + query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); + } + if (StringUtils.isNotBlank(bo.getKey())) { + query.processDefinitionKey(bo.getKey()); + } + if (StringUtils.isNotBlank(bo.getBusinessKey())) { + query.processInstanceBusinessKey(bo.getBusinessKey()); + } + if (StringUtils.isNotBlank(bo.getCategoryCode())) { + query.processDefinitionCategory(bo.getCategoryCode()); + } + query.orderByProcessInstanceStartTime().desc(); + List<HistoricProcessInstance> historicProcessInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); + List<TaskVo> taskVoList = new ArrayList<>(); + if (CollUtil.isNotEmpty(historicProcessInstanceList)) { + List<String> processInstanceIds = StreamUtils.toList(historicProcessInstanceList, HistoricProcessInstance::getId); + List<Task> taskList = QueryUtils.taskQuery(processInstanceIds).list(); + for (Task task : taskList) { + taskVoList.add(BeanUtil.toBean(task, TaskVo.class)); + } + } + for (HistoricProcessInstance processInstance : historicProcessInstanceList) { + ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); + processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus())); + if (CollUtil.isNotEmpty(taskVoList)) { + List<TaskVo> collect = StreamUtils.filter(taskVoList, e -> e.getProcessInstanceId().equals(processInstance.getId())); + processInstanceVo.setTaskVoList(CollUtil.isNotEmpty(collect) ? collect : Collections.emptyList()); + } + 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(); + TableDataInfo<ProcessInstanceVo> build = TableDataInfo.build(); + build.setRows(list); + build.setTotal(count); + return build; + } + + /** + * 浠诲姟鍌姙(缁欏綋鍓嶄换鍔″姙鐞嗕汉鍙戦�佺珯鍐呬俊锛岄偖浠讹紝鐭俊绛�) + * + * @param taskUrgingBo 浠诲姟鍌姙 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean taskUrging(TaskUrgingBo taskUrgingBo) { + try { + ProcessInstance processInstance = QueryUtils.instanceQuery(taskUrgingBo.getProcessInstanceId()).singleResult(); + if (processInstance == null) { + throw new ServiceException("浠诲姟宸茬粨鏉燂紒"); + } + String message = taskUrgingBo.getMessage(); + if (StringUtils.isBlank(message)) { + message = "鎮ㄧ殑銆�" + processInstance.getName() + "銆戝崟鎹繕鏈鎵癸紝璇锋偍鍙婃椂澶勭悊銆�"; + } + List<Task> list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list(); + WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message); + } catch (ServiceException e) { + throw new ServiceException(e.getMessage()); + } + return true; + } +} -- Gitblit v1.9.3