From 5360ec6ec3bf356a554df624e884a0bb1090fa4b Mon Sep 17 00:00:00 2001
From: gssong <1742057357@qq.com>
Date: 星期日, 17 三月 2024 18:25:20 +0800
Subject: [PATCH] add 添加节点审批记录,调整流程驳回
---
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java | 65 ++++++++
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java | 12 +
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java | 13 +
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java | 5
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java | 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java | 141 +++++++++++++++++
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java | 10 +
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java | 61 +++++++
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java | 84 +++++-----
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml | 7
script/sql/flowable.sql | 20 ++
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java | 9 -
12 files changed, 373 insertions(+), 55 deletions(-)
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
index 1e9d79b..77996ae 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
+++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
@@ -99,4 +99,14 @@
* 妯″瀷鏍囪瘑key鍛藉悕瑙勮寖姝e垯琛ㄨ揪寮�
*/
String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$";
+
+ /**
+ * 鐢ㄦ埛浠诲姟
+ */
+ String USER_TASK = "userTask";
+
+ /**
+ * 浼氱
+ */
+ String MULTI_INSTANCE = "multiInstance";
}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java
index 9f50cdc..d494959 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java
+++ b/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)));
}
}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java
new file mode 100644
index 0000000..6f59727
--- /dev/null
+++ b/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;
+
+}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
index 7ac6b38..d0f4369 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
+++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
@@ -34,6 +34,7 @@
/**
* 椹冲洖鐨勮妭鐐筰d(鐩墠鏈娇鐢紝鐩存帴椹冲洖鍒扮敵璇蜂汉)
*/
+ @NotBlank(message = "椹冲洖鐨勮妭鐐逛笉鑳戒负绌�", groups = AddGroup.class)
private String targetActivityId;
/**
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java
new file mode 100644
index 0000000..9b291fe
--- /dev/null
+++ b/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> {
+}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java
index 72a5ea1..45c3de2 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java
+++ b/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);
}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java
new file mode 100644
index 0000000..97f9406
--- /dev/null
+++ b/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);
+
+ /**
+ * 鎸夋祦绋嬪疄渚媔d鏌ヨ
+ *
+ * @param processInstanceId 娴佺▼瀹炰緥id
+ * @return 缁撴灉
+ */
+ List<WfTaskBackNode> getListByInstanceId(String processInstanceId);
+
+ /**
+ * 鎸夌収娴佺▼瀹炰緥id锛岃妭鐐筰d鏌ヨ
+ *
+ * @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);
+
+ /**
+ * 鎸夋祦绋嬪疄渚媔d鍒犻櫎
+ *
+ * @param processInstanceId 娴佺▼瀹炰緥id
+ * @return 缁撴灉
+ */
+ boolean deleteByInstanceId(String processInstanceId);
+
+ /**
+ * 鎸夋祦绋嬪疄渚媔d鍒犻櫎
+ *
+ * @param processInstanceIds 娴佺▼瀹炰緥id
+ * @return 缁撴灉
+ */
+ boolean deleteByInstanceIds(List<String> processInstanceIds);
+}
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
index 3f8678a..f4e8df2 100644
--- 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
@@ -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();
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
index b623eab..d35e930 100644
--- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
+++ b/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;
}
}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java
new file mode 100644
index 0000000..b656429
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml
new file mode 100644
index 0000000..4a9179b
--- /dev/null
+++ b/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>
diff --git a/script/sql/flowable.sql b/script/sql/flowable.sql
index b7149e5..7eb8d6b 100644
--- a/script/sql/flowable.sql
+++ b/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, '');
--
Gitblit v1.9.3