ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
@@ -99,4 +99,14 @@ * æ¨¡åæ è¯keyå½åè§èæ£åè¡¨è¾¾å¼ */ String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$"; /** * ç¨æ·ä»»å¡ */ String USER_TASK = "userTask"; /** * ä¼ç¾ */ String MULTI_INSTANCE = "multiInstance"; } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java
@@ -1,5 +1,6 @@ package org.dromara.workflow.controller; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; @@ -12,10 +13,12 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.web.core.BaseController; import org.dromara.workflow.domain.WfTaskBackNode; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.TaskVo; import org.dromara.workflow.domain.vo.VariableVo; import org.dromara.workflow.service.IActTaskService; import org.dromara.workflow.service.IWfTaskBackNodeService; import org.dromara.workflow.utils.QueryUtils; import org.flowable.engine.TaskService; import org.springframework.validation.annotation.Validated; @@ -23,7 +26,6 @@ import java.util.List; import java.util.Map; import java.util.Set; /** * ä»»å¡ç®¡ç æ§å¶å± @@ -39,6 +41,8 @@ private final IActTaskService actTaskService; private final TaskService taskService; private final IWfTaskBackNodeService iWfTaskBackNodeService; /** @@ -220,7 +224,7 @@ @Log(title = "ä»»å¡ç®¡ç", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping("/backProcess") public R<String> backProcess(@RequestBody BackProcessBo backProcessBo) { public R<String> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) { return R.ok(actTaskService.backProcess(backProcessBo)); } @@ -264,7 +268,7 @@ * @param processInstanceId æµç¨å®ä¾id */ @GetMapping("/getTaskNodeList/{processInstanceId}") public R<Set<TaskVo>> getNodeList(@PathVariable String processInstanceId) { return R.ok(actTaskService.getTaskNodeList(processInstanceId)); public R<List<WfTaskBackNode>> getNodeList(@PathVariable String processInstanceId) { return R.ok(CollUtil.reverse(iWfTaskBackNodeService.getListByInstanceId(processInstanceId))); } } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,61 @@ package org.dromara.workflow.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import org.dromara.common.tenant.core.TenantEntity; import java.io.Serial; /** * èç¹é©³åè®°å½ wf_task_back_node * * @author may * @date 2024-03-13 */ @Data @EqualsAndHashCode(callSuper = true) @TableName("wf_task_back_node") public class WfTaskBackNode extends TenantEntity { @Serial private static final long serialVersionUID = 1L; /** * ä¸»é® */ @TableId(value = "id") private Long id; /** * å®ä¾id */ private String instanceId; /** * èç¹id */ private String nodeId; /** * èç¹åç§° */ private String nodeName; /** * æåº */ private Integer orderNo; /** * èç¹ç±»å */ private String taskType; /** * åç人 */ private String assignee; } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
@@ -34,6 +34,7 @@ /** * 驳åçèç¹id(ç®åæªä½¿ç¨ï¼ç´æ¥é©³åå°ç³è¯·äºº) */ @NotBlank(message = "驳åçèç¹ä¸è½ä¸ºç©º", groups = AddGroup.class) private String targetActivityId; /** ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ package org.dromara.workflow.mapper; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.workflow.domain.WfTaskBackNode; /** * èç¹é©³åè®°å½Mapperæ¥å£ * * @author may * @date 2024-03-13 */ public interface WfTaskBackNodeMapper extends BaseMapperPlus<WfTaskBackNode, WfTaskBackNode> { } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java
@@ -8,7 +8,6 @@ import java.util.List; import java.util.Map; import java.util.Set; /** * ä»»å¡ æå¡å± @@ -143,12 +142,4 @@ * @return ç»æ */ List<VariableVo> getInstanceVariable(String taskId); /** * è·åå¯é©³åå¾ä»»å¡èç¹ * * @param processInstanceId æµç¨å®ä¾id * @return ç»æ */ Set<TaskVo> getTaskNodeList(String processInstanceId); } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,65 @@ package org.dromara.workflow.service; import org.dromara.workflow.domain.WfTaskBackNode; import org.flowable.task.api.Task; import java.util.List; /** * èç¹é©³åè®°å½Serviceæ¥å£ * * @author may * @date 2024-03-13 */ public interface IWfTaskBackNodeService { /** * è®°å½å®¡æ¹èç¹ * * @param task ä»»å¡ */ void recordExecuteNode(Task task); /** * ææµç¨å®ä¾idæ¥è¯¢ * * @param processInstanceId æµç¨å®ä¾id * @return ç»æ */ List<WfTaskBackNode> getListByInstanceId(String processInstanceId); /** * æç §æµç¨å®ä¾idï¼èç¹idæ¥è¯¢ * * @param processInstanceId æµç¨å®ä¾id * @param nodeId èç¹id * @return ç»æ */ WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId); /** * å é¤é©³ååçèç¹ * * @param processInstanceId æµç¨å®ä¾id * @param targetActivityId èç¹id * @return ç»æ */ boolean deleteBackTaskNode(String processInstanceId, String targetActivityId); /** * ææµç¨å®ä¾idå é¤ * * @param processInstanceId æµç¨å®ä¾id * @return ç»æ */ boolean deleteByInstanceId(String processInstanceId); /** * ææµç¨å®ä¾idå é¤ * * @param processInstanceIds æµç¨å®ä¾id * @return ç»æ */ boolean deleteByInstanceIds(List<String> processInstanceIds); } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
@@ -32,6 +32,7 @@ import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler; import org.dromara.workflow.service.IActHiProcinstService; import org.dromara.workflow.service.IActProcessInstanceService; import org.dromara.workflow.service.IWfTaskBackNodeService; import org.dromara.workflow.utils.QueryUtils; import org.dromara.workflow.utils.WorkflowUtils; import org.flowable.bpmn.model.*; @@ -77,6 +78,7 @@ private final IActHiProcinstService actHiProcinstService; private final ManagementService managementService; private final FlowEventStrategy flowEventStrategy; private final IWfTaskBackNodeService iWfTaskBackNodeService; @Value("${flowable.activity-font-name}") private String activityFontName; @@ -500,6 +502,7 @@ if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) { historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); } iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); return true; } catch (Exception e) { e.printStackTrace(); @@ -534,6 +537,7 @@ if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) { historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); } iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); return true; } catch (Exception e) { e.printStackTrace(); @@ -551,6 +555,7 @@ public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) { try { historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); return true; } catch (Exception e) { e.printStackTrace(); ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
@@ -19,6 +19,8 @@ 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.ActHiTaskinst; import org.dromara.workflow.domain.WfTaskBackNode; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.MultiInstanceVo; import org.dromara.workflow.domain.vo.TaskVo; @@ -28,8 +30,10 @@ import org.dromara.workflow.flowable.strategy.FlowEventStrategy; import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler; import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler; import org.dromara.workflow.mapper.ActHiTaskinstMapper; import org.dromara.workflow.mapper.ActTaskMapper; import org.dromara.workflow.service.IActTaskService; import org.dromara.workflow.service.IWfTaskBackNodeService; import org.dromara.workflow.utils.QueryUtils; import org.dromara.workflow.utils.WorkflowUtils; import org.flowable.common.engine.api.FlowableObjectNotFoundException; @@ -71,6 +75,8 @@ private final ManagementService managementService; private final FlowEventStrategy flowEventStrategy; private final ActTaskMapper actTaskMapper; private final IWfTaskBackNodeService iWfTaskBackNodeService; private final ActHiTaskinstMapper actHiTaskinstMapper; /** * å¯å¨ä»»å¡ @@ -187,12 +193,14 @@ //åçæè§ taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "åæ" : completeTaskBo.getMessage()); //åçä»»å¡ taskService.setAssignee(task.getId(),userId); taskService.setAssignee(task.getId(), userId); if (CollUtil.isNotEmpty(completeTaskBo.getVariables())) { taskService.complete(completeTaskBo.getTaskId(), completeTaskBo.getVariables()); } else { taskService.complete(completeTaskBo.getTaskId()); } //è®°å½æ§è¡è¿çæµç¨ä»»å¡èç¹ iWfTaskBackNodeService.recordExecuteNode(task); ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); if (pi == null) { UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus()); @@ -204,8 +212,7 @@ List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(completeTaskBo.getWfCopyList())) { TaskEntity newTask = WorkflowUtils.createNewTask(task); taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "ãæéãç»" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName))); taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "ãæéãç»" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName))); taskService.complete(newTask.getId()); List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); WorkflowUtils.createCopyTask(taskList, StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserId)); @@ -244,12 +251,7 @@ String userId = String.valueOf(LoginHelper.getUserId()); queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus()); queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId()); queryWrapper.and(w1 -> w1.eq("t.assignee_", userId) .or(w2 -> w2.isNull("t.assignee_") .apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' " + "and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN " + getInParam(roleIds) + " ) ))", userId)) ); queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' " + "and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN " + getInParam(roleIds) + " ) ))", userId))); if (StringUtils.isNotBlank(taskBo.getName())) { queryWrapper.like("t.name_", taskBo.getName()); } @@ -444,8 +446,7 @@ if (task.isSuspended()) { throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); } HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery() .processInstanceId(task.getProcessInstanceId()).singleResult(); HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus()); try { if (StringUtils.isBlank(terminationBo.getComment())) { @@ -480,8 +481,7 @@ */ @Override public boolean transferTask(TransmitBo transmitBo) { Task task = QueryUtils.taskQuery().taskId(transmitBo.getTaskId()) .taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult(); Task task = QueryUtils.taskQuery().taskId(transmitBo.getTaskId()).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult(); if (ObjectUtil.isEmpty(task)) { throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); } @@ -607,7 +607,8 @@ @Transactional(rollbackFor = Exception.class) public String backProcess(BackProcessBo backProcessBo) { TaskQuery query = QueryUtils.taskQuery(); Task task = query.taskId(backProcessBo.getTaskId()).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult(); String userId = String.valueOf(LoginHelper.getUserId()); Task task = query.taskId(backProcessBo.getTaskId()).taskCandidateOrAssigned(userId).singleResult(); if (ObjectUtil.isEmpty(task)) { throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); } @@ -624,20 +625,33 @@ BusinessStatusEnum.checkBackStatus(processInstance.getBusinessStatus()); //夿æ¯å¦æå¤ä¸ªä»»å¡ List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list(); //ç³è¯·äººèç¹ HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0); String backTaskDefinitionKey = historicTaskInstance.getTaskDefinitionKey(); String backTaskDefinitionKey = backProcessBo.getTargetActivityId(); taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.BACK.getStatus(), StringUtils.isNotBlank(backProcessBo.getMessage()) ? backProcessBo.getMessage() : "éå"); if (taskList.size() > 1) { //å½åå¤ä¸ªä»»å¡é©³åå°å个èç¹ runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()), backTaskDefinitionKey).changeState(); ActHiTaskinst actHiTaskinst = new ActHiTaskinst(); actHiTaskinst.setAssignee(userId); actHiTaskinst.setId(task.getId()); actHiTaskinstMapper.updateById(actHiTaskinst); } else { //å½åå个èç¹é©³åå个èç¹ runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdTo(task.getTaskDefinitionKey(), backTaskDefinitionKey).changeState(); } //å é¤å¹¶è¡ç¯èæªåçè®°å½ MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); if (multiInstance == null && taskList.size() > 1) { List<Task> tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey())); actHiTaskinstMapper.deleteBatchIds(StreamUtils.toList(tasks, Task::getId)); } List<HistoricTaskInstance> instanceList = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list(); List<Task> list = QueryUtils.taskQuery(processInstanceId).list(); for (Task t : list) { taskService.setAssignee(t.getId(), historicTaskInstance.getAssignee()); instanceList.stream().filter(e -> e.getTaskDefinitionKey().equals(t.getTaskDefinitionKey())).findFirst().ifPresent(e -> { taskService.setAssignee(t.getId(), e.getAssignee()); }); } //åéæ¶æ¯ String message = "æ¨çã" + processInstance.getName() + "ã忮已ç»è¢«é©³åï¼è¯·æ¨æ³¨ææ¥æ¶ã"; @@ -647,11 +661,17 @@ DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); managementService.executeCommand(deleteExecutionCmd); } runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus()); FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey()); if (processHandler != null) { processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false); WfTaskBackNode wfTaskBackNode = iWfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId()); if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) { runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus()); FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey()); if (processHandler != null) { processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false); } } //å é¤é©³ååçæµç¨èç¹ iWfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId()); } catch (Exception e) { throw new ServiceException(e.getMessage()); } @@ -696,25 +716,5 @@ } } return variableVoList; } /** * è·åå¯é©³åå¾ä»»å¡èç¹ * * @param processInstanceId æµç¨å®ä¾id */ @Override public Set<TaskVo> getTaskNodeList(String processInstanceId) { Set<TaskVo> list = new HashSet<>(); List<HistoricTaskInstance> historicTaskInstances = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list(); for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { if (historicTaskInstance.getEndTime() != null) { TaskVo taskVo = new TaskVo(); taskVo.setName(historicTaskInstance.getName()); taskVo.setTaskDefinitionKey(historicTaskInstance.getTaskDefinitionKey()); list.add(taskVo); } } return list; } } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,141 @@ package org.dromara.workflow.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.workflow.domain.WfTaskBackNode; import org.dromara.workflow.domain.vo.MultiInstanceVo; import org.dromara.workflow.mapper.WfTaskBackNodeMapper; import org.dromara.workflow.service.IWfTaskBackNodeService; import org.dromara.workflow.utils.WorkflowUtils; import org.flowable.task.api.Task; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; import static org.dromara.workflow.common.constant.FlowConstant.MULTI_INSTANCE; import static org.dromara.workflow.common.constant.FlowConstant.USER_TASK; /** * èç¹é©³åè®°å½Serviceä¸å¡å±å¤ç * * @author may * @date 2024-03-13 */ @RequiredArgsConstructor @Service public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService { private final WfTaskBackNodeMapper wfTaskBackNodeMapper; @Override @Transactional(rollbackFor = Exception.class) public void recordExecuteNode(Task task) { List<WfTaskBackNode> list = getListByInstanceId(task.getProcessInstanceId()); WfTaskBackNode wfTaskBackNode = new WfTaskBackNode(); wfTaskBackNode.setNodeId(task.getTaskDefinitionKey()); wfTaskBackNode.setNodeName(task.getName()); wfTaskBackNode.setInstanceId(task.getProcessInstanceId()); wfTaskBackNode.setAssignee(String.valueOf(LoginHelper.getUserId())); MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); if (ObjectUtil.isNotEmpty(multiInstance)) { wfTaskBackNode.setTaskType(MULTI_INSTANCE); } else { wfTaskBackNode.setTaskType(USER_TASK); } if (CollectionUtil.isEmpty(list)) { wfTaskBackNode.setOrderNo(0); wfTaskBackNodeMapper.insert(wfTaskBackNode); } else { WfTaskBackNode taskNode = list.stream().filter(e -> e.getNodeId().equals(wfTaskBackNode.getNodeId()) && e.getOrderNo() == 0).findFirst().orElse(null); if (ObjectUtil.isEmpty(taskNode)) { wfTaskBackNode.setOrderNo(list.get(0).getOrderNo() + 1); WfTaskBackNode node = getListByInstanceIdAndNodeId(wfTaskBackNode.getInstanceId(), wfTaskBackNode.getNodeId()); if (ObjectUtil.isNotEmpty(node)) { node.setAssignee(node.getAssignee() + StringUtils.SEPARATOR + LoginHelper.getUserId()); wfTaskBackNodeMapper.updateById(node); } else { wfTaskBackNodeMapper.insert(wfTaskBackNode); } } } } @Override public List<WfTaskBackNode> getListByInstanceId(String processInstanceId) { LambdaQueryWrapper<WfTaskBackNode> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); wrapper.orderByDesc(WfTaskBackNode::getOrderNo); return wfTaskBackNodeMapper.selectList(wrapper); } @Override public WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId) { LambdaQueryWrapper<WfTaskBackNode> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); queryWrapper.eq(WfTaskBackNode::getNodeId, nodeId); return wfTaskBackNodeMapper.selectOne(queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public boolean deleteBackTaskNode(String processInstanceId, String targetActivityId) { try { LambdaQueryWrapper<WfTaskBackNode> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); queryWrapper.eq(WfTaskBackNode::getNodeId, targetActivityId); WfTaskBackNode actTaskNode = wfTaskBackNodeMapper.selectOne(queryWrapper); if (ObjectUtil.isNotNull(actTaskNode)) { Integer orderNo = actTaskNode.getOrderNo(); List<WfTaskBackNode> taskNodeList = getListByInstanceId(processInstanceId); List<Long> ids = new ArrayList<>(); if (CollectionUtil.isNotEmpty(taskNodeList)) { for (WfTaskBackNode taskNode : taskNodeList) { if (taskNode.getOrderNo() >= orderNo) { ids.add(taskNode.getId()); } } } if (CollectionUtil.isNotEmpty(ids)) { wfTaskBackNodeMapper.deleteBatchIds(ids); } } return true; } catch (Exception e) { e.printStackTrace(); throw new ServiceException("å é¤å¤±è´¥"); } } @Override @Transactional(rollbackFor = Exception.class) public boolean deleteByInstanceId(String processInstanceId) { LambdaQueryWrapper<WfTaskBackNode> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); List<WfTaskBackNode> list = wfTaskBackNodeMapper.selectList(wrapper); int delete = wfTaskBackNodeMapper.delete(wrapper); if (list.size() != delete) { throw new ServiceException("å é¤å¤±è´¥"); } return true; } @Override public boolean deleteByInstanceIds(List<String> processInstanceIds) { LambdaQueryWrapper<WfTaskBackNode> wrapper = new LambdaQueryWrapper<>(); wrapper.in(WfTaskBackNode::getInstanceId, processInstanceIds); List<WfTaskBackNode> list = wfTaskBackNodeMapper.selectList(wrapper); int delete = wfTaskBackNodeMapper.delete(wrapper); if (list.size() != delete) { throw new ServiceException("å é¤å¤±è´¥"); } return true; } } ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.dromara.workflow.mapper.WfTaskBackNodeMapper"> </mapper> script/sql/flowable.sql
@@ -58,6 +58,26 @@ ) engine=innodb comment= 'æµç¨åç±»'; INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, sysdate(), 1, sysdate()); DROP TABLE if EXISTS wf_task_back_node; create table wf_task_back_node ( id varchar(255) not null primary key, node_id varchar(255) not null comment 'èç¹id', node_name varchar(255) not null comment 'èç¹åç§°', order_no int not null comment 'æåº', instance_id varchar(255) null comment 'æµç¨å®ä¾id', task_type varchar(255) not null comment 'èç¹ç±»å', assignee varchar(2000) not null comment '审æ¹äºº', tenant_id varchar(20) default '000000' null comment 'ç§æ·ç¼å·', create_dept bigint null comment 'å建é¨é¨', create_by bigint null comment 'å建è ', create_time datetime null comment 'å建æ¶é´', update_by bigint null comment 'æ´æ°è ', update_time datetime null comment 'æ´æ°æ¶é´' ) comment 'èç¹å®¡æ¹è®°å½'; INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请åç³è¯·', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'demo:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请åç³è¯·èå'); INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请åç³è¯·æ¥è¯¢', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:query', '#', 103, 1, sysdate(), NULL, NULL, '');