From f1208474f771a1c233d7425c8ed13fbaa0d521ac Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期三, 12 三月 2025 09:35:13 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/5.X' into 5.X

---
 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java |  363 +++++++++++++++++++--------------------------------
 1 files changed, 137 insertions(+), 226 deletions(-)

diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
index d7c4472..e48ffc8 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
+++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
@@ -2,43 +2,42 @@
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.dromara.common.core.domain.dto.RoleDTO;
 import org.dromara.common.core.domain.dto.UserDTO;
-import org.dromara.common.core.service.UserService;
 import org.dromara.common.core.utils.SpringUtils;
 import org.dromara.common.core.utils.StreamUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mail.utils.MailUtils;
-import org.dromara.common.satoken.utils.LoginHelper;
-import org.dromara.common.tenant.helper.TenantHelper;
-import org.dromara.common.websocket.dto.WebSocketMessageDto;
-import org.dromara.common.websocket.utils.WebSocketUtils;
-import org.dromara.workflow.common.constant.FlowConstant;
+import org.dromara.common.sse.dto.SseMessageDto;
+import org.dromara.common.sse.utils.SseMessageUtils;
+import org.dromara.warm.flow.core.constant.ExceptionCons;
+import org.dromara.warm.flow.core.dto.FlowParams;
+import org.dromara.warm.flow.core.entity.Node;
+import org.dromara.warm.flow.core.entity.Task;
+import org.dromara.warm.flow.core.entity.User;
+import org.dromara.warm.flow.core.enums.NodeType;
+import org.dromara.warm.flow.core.enums.SkipType;
+import org.dromara.warm.flow.core.service.NodeService;
+import org.dromara.warm.flow.core.service.TaskService;
+import org.dromara.warm.flow.core.service.UserService;
+import org.dromara.warm.flow.core.utils.AssertUtil;
+import org.dromara.warm.flow.orm.entity.FlowNode;
+import org.dromara.warm.flow.orm.entity.FlowTask;
+import org.dromara.warm.flow.orm.entity.FlowUser;
+import org.dromara.warm.flow.orm.mapper.FlowNodeMapper;
+import org.dromara.warm.flow.orm.mapper.FlowTaskMapper;
 import org.dromara.workflow.common.enums.MessageTypeEnum;
-import org.dromara.workflow.common.enums.TaskStatusEnum;
-import org.dromara.workflow.domain.ActHiTaskinst;
-import org.dromara.workflow.domain.vo.MultiInstanceVo;
-import org.dromara.workflow.domain.vo.ParticipantVo;
-import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd;
-import org.dromara.workflow.mapper.ActHiTaskinstMapper;
-import org.flowable.bpmn.model.BpmnModel;
-import org.flowable.bpmn.model.FlowNode;
-import org.flowable.common.engine.api.delegate.Expression;
-import org.flowable.engine.ProcessEngine;
-import org.flowable.engine.history.HistoricProcessInstance;
-import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
-import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
-import org.flowable.identitylink.api.history.HistoricIdentityLink;
-import org.flowable.task.api.Task;
-import org.flowable.task.api.TaskQuery;
-import org.flowable.task.api.history.HistoricTaskInstance;
-import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.dromara.workflow.service.IFlwTaskAssigneeService;
+import org.dromara.workflow.service.IFlwTaskService;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 
 /**
  * 宸ヤ綔娴佸伐鍏�
@@ -48,220 +47,84 @@
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class WorkflowUtils {
 
-    private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class);
-    private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class);
+    private static final IFlwTaskAssigneeService TASK_ASSIGNEE_SERVICE = SpringUtils.getBean(IFlwTaskAssigneeService.class);
+    private static final IFlwTaskService FLW_TASK_SERVICE = SpringUtils.getBean(IFlwTaskService.class);
+    private static final FlowNodeMapper FLOW_NODE_MAPPER = SpringUtils.getBean(FlowNodeMapper.class);
+    private static final FlowTaskMapper FLOW_TASK_MAPPER = SpringUtils.getBean(FlowTaskMapper.class);
+    private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class);
+    private static final TaskService TASK_SERVICE = SpringUtils.getBean(TaskService.class);
+    private static final NodeService NODE_SERVICE = SpringUtils.getBean(NodeService.class);
 
     /**
-     * 鍒涘缓涓�涓柊浠诲姟
-     *
-     * @param currentTask 鍙傛暟
+     * 鑾峰彇宸ヤ綔娴佺敤鎴穝ervice
      */
-    public static TaskEntity createNewTask(Task currentTask) {
-        TaskEntity task = null;
-        if (ObjectUtil.isNotEmpty(currentTask)) {
-            task = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask();
-            task.setCategory(currentTask.getCategory());
-            task.setDescription(currentTask.getDescription());
-            task.setAssignee(currentTask.getAssignee());
-            task.setName(currentTask.getName());
-            task.setProcessDefinitionId(currentTask.getProcessDefinitionId());
-            task.setProcessInstanceId(currentTask.getProcessInstanceId());
-            task.setTaskDefinitionKey(currentTask.getTaskDefinitionKey());
-            task.setPriority(currentTask.getPriority());
-            task.setCreateTime(new Date());
-            task.setTenantId(TenantHelper.getTenantId());
-            PROCESS_ENGINE.getTaskService().saveTask(task);
-        }
-        if (ObjectUtil.isNotNull(task)) {
-            UpdateHiTaskInstCmd updateHiTaskInstCmd = new UpdateHiTaskInstCmd(Collections.singletonList(task.getId()), task.getProcessDefinitionId(), task.getProcessInstanceId());
-            PROCESS_ENGINE.getManagementService().executeCommand(updateHiTaskInstCmd);
-        }
-        return task;
+    public static UserService getFlowUserService() {
+        return USER_SERVICE;
     }
 
     /**
-     * 鎶勯�佷换鍔�
+     * 鏋勫缓宸ヤ綔娴佺敤鎴�
      *
-     * @param parentTaskList 鐖剁骇浠诲姟
-     * @param userIds        浜哄憳id
+     * @param userList 鍔炵悊鐢ㄦ埛
+     * @param taskId   浠诲姟ID
+     * @return 鐢ㄦ埛
      */
-    public static void createCopyTask(List<Task> parentTaskList, List<Long> userIds) {
-        List<Task> list = new ArrayList<>();
-        String tenantId = TenantHelper.getTenantId();
-        for (Task parentTask : parentTaskList) {
-            for (Long userId : userIds) {
-                TaskEntity newTask = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask();
-                newTask.setParentTaskId(parentTask.getId());
-                newTask.setAssignee(userId.toString());
-                newTask.setName("銆愭妱閫併��-" + parentTask.getName());
-                newTask.setProcessDefinitionId(parentTask.getProcessDefinitionId());
-                newTask.setProcessInstanceId(parentTask.getProcessInstanceId());
-                newTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey());
-                newTask.setTenantId(tenantId);
-                list.add(newTask);
+    public static Set<User> buildUser(List<User> userList, Long taskId) {
+        if (CollUtil.isEmpty(userList)) {
+            return Set.of();
+        }
+        Set<User> list = new HashSet<>();
+        Set<String> processedBySet = new HashSet<>();
+        for (User user : userList) {
+            // 鏍规嵁 processedBy 鍓嶇紑鍒ゆ柇澶勭悊浜虹被鍨嬶紝鍒嗗埆鑾峰彇鐢ㄦ埛鍒楄〃
+            List<UserDTO> users = TASK_ASSIGNEE_SERVICE.fetchUsersByStorageId(user.getProcessedBy());
+            // 杞崲涓� FlowUser 骞舵坊鍔犲埌缁撴灉闆嗗悎
+            if (CollUtil.isNotEmpty(users)) {
+                users.forEach(dto -> {
+                    String processedBy = String.valueOf(dto.getUserId());
+                    if (!processedBySet.contains(processedBy)) {
+                        FlowUser flowUser = new FlowUser();
+                        flowUser.setType(user.getType());
+                        flowUser.setProcessedBy(processedBy);
+                        flowUser.setAssociated(taskId);
+                        list.add(flowUser);
+                        processedBySet.add(processedBy);
+                    }
+                });
             }
         }
-        PROCESS_ENGINE.getTaskService().bulkSaveTasks(list);
-        if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(parentTaskList)) {
-            String processInstanceId = parentTaskList.get(0).getProcessInstanceId();
-            String processDefinitionId = parentTaskList.get(0).getProcessDefinitionId();
-            List<String> taskIds = StreamUtils.toList(list, Task::getId);
-            ActHiTaskinst actHiTaskinst = new ActHiTaskinst();
-            actHiTaskinst.setProcDefId(processDefinitionId);
-            actHiTaskinst.setProcInstId(processInstanceId);
-            actHiTaskinst.setScopeType(TaskStatusEnum.COPY.getStatus());
-            actHiTaskinst.setTenantId(tenantId);
-            LambdaUpdateWrapper<ActHiTaskinst> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.in(ActHiTaskinst::getId, taskIds);
-            ACT_HI_TASKINST_MAPPER.update(actHiTaskinst, updateWrapper);
-            for (Task task : list) {
-                PROCESS_ENGINE.getTaskService().addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), StrUtil.EMPTY);
-            }
-        }
-    }
-
-    /**
-     * 鑾峰彇褰撳墠浠诲姟鍙備笌鑰�
-     *
-     * @param taskId 浠诲姟id
-     */
-    public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) {
-        ParticipantVo participantVo = new ParticipantVo();
-        List<HistoricIdentityLink> linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId);
-        Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
-        if (task != null && CollUtil.isNotEmpty(linksForTask)) {
-            List<HistoricIdentityLink> groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId()));
-            if (CollUtil.isNotEmpty(groupList)) {
-                List<Long> groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId()));
-                List<Long> userIds = userService.selectUserIdsByRoleIds(groupIds);
-                if (CollUtil.isNotEmpty(userIds)) {
-                    participantVo.setGroupIds(groupIds);
-                    List<UserDTO> userList = userService.selectListByIds(userIds);
-                    if (CollUtil.isNotEmpty(userList)) {
-                        List<Long> userIdList = StreamUtils.toList(userList, UserDTO::getUserId);
-                        List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
-                        participantVo.setCandidate(userIdList);
-                        participantVo.setCandidateName(nickNames);
-                        participantVo.setClaim(!StringUtils.isBlank(task.getAssignee()));
-                    }
-                }
-            } else {
-                List<HistoricIdentityLink> candidateList = StreamUtils.filter(linksForTask, e -> FlowConstant.CANDIDATE.equals(e.getType()));
-                List<Long> userIdList = new ArrayList<>();
-                for (HistoricIdentityLink historicIdentityLink : linksForTask) {
-                    try {
-                        userIdList.add(Long.valueOf(historicIdentityLink.getUserId()));
-                    } catch (NumberFormatException ignored) {
-
-                    }
-                }
-                List<UserDTO> userList = userService.selectListByIds(userIdList);
-                if (CollUtil.isNotEmpty(userList)) {
-                    List<Long> userIds = StreamUtils.toList(userList, UserDTO::getUserId);
-                    List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
-                    participantVo.setCandidate(userIds);
-                    participantVo.setCandidateName(nickNames);
-                    // 鍒ゆ柇褰撳墠浠诲姟鏄惁鍏锋湁澶氫釜鍔炵悊浜�
-                    if (CollUtil.isNotEmpty(candidateList) && candidateList.size() > 1) {
-                        // 濡傛灉 assignee 瀛樺湪锛屽垯璁剧疆褰撳墠浠诲姟宸茬粡琚棰�
-                        participantVo.setClaim(StringUtils.isNotBlank(task.getAssignee()));
-                    }
-                }
-            }
-        }
-        return participantVo;
-    }
-
-    /**
-     * 鍒ゆ柇褰撳墠鑺傜偣鏄惁涓轰細绛捐妭鐐�
-     *
-     * @param processDefinitionId 娴佺▼瀹氫箟id
-     * @param taskDefinitionKey   娴佺▼瀹氫箟id
-     */
-    public static MultiInstanceVo isMultiInstance(String processDefinitionId, String taskDefinitionKey) {
-        BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId);
-        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey);
-        MultiInstanceVo multiInstanceVo = new MultiInstanceVo();
-        //鍒ゆ柇鏄惁涓哄苟琛屼細绛捐妭鐐�
-        if (flowNode.getBehavior() instanceof ParallelMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) {
-            Expression collectionExpression = behavior.getCollectionExpression();
-            String assigneeList = collectionExpression.getExpressionText();
-            String assignee = behavior.getCollectionElementVariable();
-            multiInstanceVo.setType(behavior);
-            multiInstanceVo.setAssignee(assignee);
-            multiInstanceVo.setAssigneeList(assigneeList);
-            return multiInstanceVo;
-            //鍒ゆ柇鏄惁涓轰覆琛屼細绛捐妭鐐�
-        } else if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) {
-            Expression collectionExpression = behavior.getCollectionExpression();
-            String assigneeList = collectionExpression.getExpressionText();
-            String assignee = behavior.getCollectionElementVariable();
-            multiInstanceVo.setType(behavior);
-            multiInstanceVo.setAssignee(assignee);
-            multiInstanceVo.setAssigneeList(assigneeList);
-            return multiInstanceVo;
-        }
-        return null;
-    }
-
-    /**
-     * 鑾峰彇褰撳墠娴佺▼鐘舵��
-     *
-     * @param taskId 浠诲姟id
-     */
-    public static String getBusinessStatusByTaskId(String taskId) {
-        HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().taskId(taskId).singleResult();
-        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(historicTaskInstance.getProcessInstanceId()).singleResult();
-        return historicProcessInstance.getBusinessStatus();
-    }
-
-    /**
-     * 鑾峰彇褰撳墠娴佺▼鐘舵��
-     *
-     * @param businessKey 涓氬姟id
-     */
-    public static String getBusinessStatus(String businessKey) {
-        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
-        return historicProcessInstance.getBusinessStatus();
+        return list;
     }
 
     /**
      * 鍙戦�佹秷鎭�
      *
-     * @param list        浠诲姟
-     * @param name        娴佺▼鍚嶇О
+     * @param flowName    娴佺▼瀹氫箟鍚嶇О
      * @param messageType 娑堟伅绫诲瀷
      * @param message     娑堟伅鍐呭锛屼负绌哄垯鍙戦�侀粯璁ら厤缃殑娑堟伅鍐呭
      */
-    public static void sendMessage(List<Task> list, String name, List<String> messageType, String message, UserService userService) {
-        Set<Long> userIds = new HashSet<>();
+    public static void sendMessage(String flowName, Long instId, List<String> messageType, String message) {
+        List<UserDTO> userList = new ArrayList<>();
+        List<FlowTask> list = FLW_TASK_SERVICE.selectByInstId(instId);
         if (StringUtils.isBlank(message)) {
-            message = "鏈夋柊鐨勩��" + name + "銆戝崟鎹凡缁忔彁浜よ嚦鎮ㄧ殑寰呭姙锛岃鎮ㄥ強鏃跺鐞嗐��";
+            message = "鏈夋柊鐨勩��" + flowName + "銆戝崟鎹凡缁忔彁浜よ嚦鎮紝璇锋偍鍙婃椂澶勭悊銆�";
         }
-        for (Task t : list) {
-            ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService);
-            if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
-                List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
-                if (CollUtil.isNotEmpty(userIdList)) {
-                    userIds.addAll(userIdList);
-                }
-            }
-            List<Long> candidate = taskParticipant.getCandidate();
-            if (CollUtil.isNotEmpty(candidate)) {
-                userIds.addAll(candidate);
+        for (Task task : list) {
+            List<UserDTO> users = FLW_TASK_SERVICE.currentTaskAllUser(task.getId());
+            if (CollUtil.isNotEmpty(users)) {
+                userList.addAll(users);
             }
         }
-        if (CollUtil.isNotEmpty(userIds)) {
-            List<UserDTO> userList = userService.selectListByIds(new ArrayList<>(userIds));
+        if (CollUtil.isNotEmpty(userList)) {
             for (String code : messageType) {
                 MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
                 if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
                     switch (messageTypeEnum) {
                         case SYSTEM_MESSAGE:
-                            WebSocketMessageDto dto = new WebSocketMessageDto();
-                            dto.setSessionKeys(new ArrayList<>(userIds));
+                            SseMessageDto dto = new SseMessageDto();
+                            dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList()));
                             dto.setMessage(message);
-                            WebSocketUtils.publishMessage(dto);
+                            SseMessageUtils.publishMessage(dto);
                             break;
                         case EMAIL_MESSAGE:
                             MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "鍗曟嵁瀹℃壒鎻愰啋", message);
@@ -269,6 +132,8 @@
                         case SMS_MESSAGE:
                             //todo 鐭俊鍙戦��
                             break;
+                        default:
+                            throw new IllegalStateException("Unexpected value: " + messageTypeEnum);
                     }
                 }
             }
@@ -276,20 +141,66 @@
     }
 
     /**
-     * 鏍规嵁浠诲姟id鏌ヨ 褰撳墠鐢ㄦ埛鐨勪换鍔★紝妫�鏌� 褰撳墠浜哄憳 鏄惁鏄 taskId 鐨勫姙鐞嗕汉
+     * 椹冲洖
      *
-     * @param taskId 浠诲姟id
-     * @return 缁撴灉
+     * @param message        瀹℃壒鎰忚
+     * @param instanceId     娴佺▼瀹炰緥id
+     * @param targetNodeCode 鐩爣鑺傜偣
+     * @param flowStatus     娴佺▼鐘舵��
+     * @param flowHisStatus  鑺傜偣鎿嶄綔鐘舵��
      */
-    public static Task getTaskByCurrentUser(String taskId) {
-        TaskQuery taskQuery = QueryUtils.taskQuery();
-        taskQuery.taskId(taskId).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId()));
-
-        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
-        if (CollUtil.isNotEmpty(roles)) {
-            List<String> groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
-            taskQuery.taskCandidateGroupIn(groupIds);
+    public static void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) {
+        List<FlowTask> list = FLW_TASK_SERVICE.selectByInstId(instanceId);
+        if (CollUtil.isNotEmpty(list)) {
+            List<FlowTask> tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode));
+            if (list.size() == tasks.size()) {
+                return;
+            }
         }
-        return taskQuery.singleResult();
+        for (FlowTask task : list) {
+            List<UserDTO> userList = FLW_TASK_SERVICE.currentTaskAllUser(task.getId());
+            FlowParams flowParams = FlowParams.build();
+            flowParams.nodeCode(targetNodeCode);
+            flowParams.message(message);
+            flowParams.skipType(SkipType.PASS.getKey());
+            flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus);
+            flowParams.ignore(true);
+            //瑙e喅浼氱娌℃潈闄愰棶棰�
+            if (CollUtil.isNotEmpty(userList)) {
+                flowParams.handler(userList.get(0).getUserId().toString());
+            }
+            TASK_SERVICE.skip(task.getId(), flowParams);
+        }
+        //瑙e喅浼氱澶氫汉瀹℃壒闂
+        backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus);
+    }
+
+    /**
+     * 鐢宠浜鸿妭鐐圭紪鐮�
+     *
+     * @param definitionId 娴佺▼瀹氫箟id
+     * @return 鐢宠浜鸿妭鐐圭紪鐮�
+     */
+    public static String applyNodeCode(Long definitionId) {
+        //鑾峰彇宸插彂甯冪殑娴佺▼鑺傜偣
+        List<FlowNode> flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, definitionId));
+        AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE);
+        Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null);
+        AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE);
+        Node nextNode = NODE_SERVICE.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey());
+        return nextNode.getNodeCode();
+    }
+
+    /**
+     * 鍒犻櫎杩愯涓殑浠诲姟
+     *
+     * @param taskIds 浠诲姟id
+     */
+    public static void deleteRunTask(List<Long> taskIds) {
+        if (CollUtil.isEmpty(taskIds)) {
+            return;
+        }
+        USER_SERVICE.deleteByTaskIds(taskIds);
+        FLOW_TASK_MAPPER.deleteByIds(taskIds);
     }
 }

--
Gitblit v1.9.3