Explorar o código

增加初步驳回功能
dom4j增加失败

kemengkai %!s(int64=3) %!d(string=hai) anos
pai
achega
d43006dce8
Modificáronse 50 ficheiros con 1079 adicións e 169 borrados
  1. 1 0
      sql/ruoyi-vue-pro.sql
  2. 8 1
      yudao-dependencies/pom.xml
  3. 2 1
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
  4. 14 0
      yudao-module-bpm/yudao-module-bpm-biz/pom.xml
  5. 16 6
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
  6. 43 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java
  7. 0 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java
  8. 3 2
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java
  9. 92 44
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
  10. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java
  11. 2 2
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java
  12. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java
  13. 105 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java
  14. 2 2
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java
  15. 6 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java
  16. 50 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmActivityMapper.java
  17. 32 2
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java
  18. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmModelFormTypeEnum.java
  19. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskAssignRuleTypeEnum.java
  20. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskRuleScriptEnum.java
  21. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/message/BpmMessageEnum.java
  22. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceDeleteReasonEnum.java
  23. 3 2
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceResultEnum.java
  24. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceStatusEnum.java
  25. 34 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/vo/ApproveProcInstVO.java
  26. 28 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmSecurityConfiguration.java
  27. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceActivityBehavior.java
  28. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
  29. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
  30. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
  31. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
  32. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
  33. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
  34. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
  35. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
  36. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
  37. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
  38. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java
  39. 1 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java
  40. 11 19
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
  41. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
  42. 27 10
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
  43. 105 46
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
  44. 20 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/HistoricApproveTaskDTO.java
  45. 105 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/vo/HiTaskinstVO.java
  46. 263 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskinstService.java
  47. 48 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml
  48. 31 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml
  49. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/MultiInstancesTest.java
  50. 1 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java

+ 1 - 0
sql/ruoyi-vue-pro.sql

@@ -546,6 +546,7 @@ COMMIT;
 DROP TABLE IF EXISTS `bpm_task_ext`;
 CREATE TABLE `bpm_task_ext` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+  `task_def_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '流程任务key',
   `assignee_user_id` bigint DEFAULT NULL COMMENT '任务的审批人',
   `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '任务的名字',
   `task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务的编号',

+ 8 - 1
yudao-dependencies/pom.xml

@@ -65,6 +65,7 @@
         <tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version>
         <yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
         <justauth.version>1.4.0</justauth.version>
+        <dom4j.version>2.1.3</dom4j.version>
     </properties>
 
     <dependencyManagement>
@@ -578,7 +579,13 @@
                 <artifactId>justauth-spring-boot-starter</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
                 <version>${justauth.version}</version>
             </dependency>
-
+            <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
+            <!-- XML读写框架 -->
+            <dependency>
+                <groupId>org.dom4j</groupId>
+                <artifactId>dom4j</artifactId>
+                <version>${dom4j.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

+ 2 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java

@@ -58,7 +58,8 @@ public class YudaoSwaggerAutoConfiguration {
                 .build()
                 .securitySchemes(securitySchemes())
                 .globalRequestParameters(globalRequestParameters())
-                .securityContexts(securityContexts());
+                .securityContexts(securityContexts())
+                .host("http://localhost:48080");
     }
 
     // ========== apiInfo ==========

+ 14 - 0
yudao-module-bpm/yudao-module-bpm-biz/pom.xml

@@ -10,6 +10,10 @@
     <modelVersion>4.0.0</modelVersion>
     <artifactId>yudao-module-bpm-biz</artifactId>
 
+    <properties>
+        <dom4j.version>2.1.3</dom4j.version>
+    </properties>
+
     <name>${project.artifactId}</name>
     <description>
         bpm-base 模块,实现公用的工作流的逻辑,提供给 bpm-activiti 和 bpm-flowable 复用
@@ -36,6 +40,10 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
+        </dependency>
 
         <!-- Web 相关 -->
         <dependency>
@@ -77,5 +85,11 @@
             <version>1.4.196</version>
             <scope>test</scope>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
+        <!-- XML读写框架 -->
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 16 - 6
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.apache.ibatis.annotations.Param;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.engine.TaskService;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -17,6 +18,7 @@ import javax.annotation.Resource;
 import javax.validation.Valid;
 
 import java.util.List;
+import java.util.Objects;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
@@ -49,10 +51,17 @@ public class BpmTaskController {
     @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
     @PreAuthorize("@ss.hasPermission('bpm:task:query')")
     public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
-            @RequestParam("processInstanceId") String processInstanceId) {
+        @RequestParam("processInstanceId") String processInstanceId) {
         return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
     }
 
+    @GetMapping("/get")
+    @ApiOperation(value = "获取审批单详情", notes = "包括完成的、未完成的")
+    @ApiImplicitParam(name = "taskId", value = "任务Id", required = true, dataTypeClass = String.class)
+    public CommonResult<Object> getTask(@Param("taskId") String processInstanceId) {
+        return success(taskService.getTaskInfo(processInstanceId));
+    }
+
     @PutMapping("/approve")
     @ApiOperation("通过任务")
     @PreAuthorize("@ss.hasPermission('bpm:task:update')")
@@ -76,13 +85,14 @@ public class BpmTaskController {
         taskService.updateTaskAssignee(getLoginUserId(), reqVO);
         return success(true);
     }
+
     @PutMapping("/back")
     @ApiOperation(value = "回退")
-//    @PreAuthorize("@ss.hasPermission('bpm:task:back')")
-    public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) {
+    //    @PreAuthorize("@ss.hasPermission('bpm:task:back')")
+    public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskBackReqVO reqVO) {
         //先硬编码到 回退到第一个审批节点
-        String destinationTaskDefKey = "task01";
-        taskService.backTask(reqVO.getId(),destinationTaskDefKey);
-        return success(true);
+        //        String destinationTaskDefKey = "task01";
+        return taskService.backTask(reqVO);
+
     }
 }

+ 43 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author kemengkai
+ * @create 2022-05-07 08:05
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BpmTaskBackReqVO {
+
+    @ApiModelProperty(value = "用户id", required = true, example = "1")
+    @NotEmpty(message = "用户id不能为空")
+    private String userId;
+
+    @ApiModelProperty(value = "流程编号id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0")
+    @NotEmpty(message = "流程编号id不能为空")
+    private String procInstId;
+
+    @ApiModelProperty(value = "当前任务id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0")
+    @NotEmpty(message = "当前任务id不能为空")
+    private String taskId;
+
+    @ApiModelProperty(value = "当前流程任务id", required = true, example = "Activity_1jlembv")
+    @NotNull(message = "当前流程任务id不能为空")
+    private String oldTaskDefKey;
+
+    @ApiModelProperty(value = "准备回退的流程任务id", required = true, example = "task01")
+    @NotNull(message = "准备回退流程任务id不能为空")
+    private String newTaskDefKey;
+
+    @ApiModelProperty(value = "审批结果", required = true, example = "任务驳回")
+    @NotNull(message = "审批结果")
+    private String comment;
+}

+ 0 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java

@@ -35,5 +35,4 @@ public class BpmTaskRespVO extends BpmTaskDonePageItemRespVO {
         private String deptName;
 
     }
-
 }

+ 3 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.bpm.convert.task;
 
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
 import org.flowable.engine.history.HistoricActivityInstance;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -19,11 +20,11 @@ public interface BpmActivityConvert {
 
     BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
 
-    List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
+    List<BpmActivityRespVO> convertList(List<BpmActivityDO> list);
 
     @Mappings({
             @Mapping(source = "activityId", target = "key"),
             @Mapping(source = "activityType", target = "type")
     })
-    BpmActivityRespVO convert(HistoricActivityInstance bean);
+    BpmActivityRespVO convert(BpmActivityDO bean);
 }

+ 92 - 44
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java

@@ -1,11 +1,13 @@
 package cn.iocoder.yudao.module.bpm.convert.task;
 
+import cn.hutool.core.util.BooleanUtil;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -17,9 +19,10 @@ import org.flowable.task.api.Task;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.mapstruct.*;
 import org.mapstruct.factory.Mappers;
+import org.springframework.beans.BeanUtils;
 
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * Bpm 任务 Convert
@@ -31,8 +34,37 @@ public interface BpmTaskConvert {
 
     BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
 
-    default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks, Map<String, ProcessInstance> processInstanceMap,
-                                                         Map<Long, AdminUserRespDTO> userMap) {
+    /**
+     * 复制对象
+     *
+     * @param source 源 要复制的对象
+     * @param target 目标 复制到此对象
+     * @param <T>
+     *
+     * @return
+     */
+    public static <T> T copy(Object source, Class<T> target) {
+        if (source == null || target == null) {
+            return null;
+        }
+        try {
+            T newInstance = target.newInstance();
+            BeanUtils.copyProperties(source, newInstance);
+            return newInstance;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    default <T, K> List<K> copyList(List<T> source, Class<K> target) {
+        if (null == source || source.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());
+    }
+
+    default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks,
+        Map<String, ProcessInstance> processInstanceMap, Map<Long, AdminUserRespDTO> userMap) {
         return CollectionUtils.convertList(tasks, task -> {
             BpmTaskTodoPageItemRespVO respVO = convert1(task);
             ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
@@ -49,13 +81,12 @@ public interface BpmTaskConvert {
 
     @Named("convertSuspendedToSuspensionState")
     default Integer convertSuspendedToSuspensionState(boolean suspended) {
-        return suspended ? SuspensionState.SUSPENDED.getStateCode() :
-                SuspensionState.ACTIVE.getStateCode();
+        return suspended ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode();
     }
 
-    default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
-                                                         Map<String, HistoricProcessInstance> historicProcessInstanceMap,
-                                                         Map<Long, AdminUserRespDTO> userMap) {
+    default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
+        Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
+        Map<Long, AdminUserRespDTO> userMap) {
         return CollectionUtils.convertList(tasks, task -> {
             BpmTaskDonePageItemRespVO respVO = convert2(task);
             BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@@ -71,18 +102,16 @@ public interface BpmTaskConvert {
 
     BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean);
 
-    @Mappings({
-            @Mapping(source = "processInstance.id", target = "id"),
-            @Mapping(source = "processInstance.name", target = "name"),
-            @Mapping(source = "processInstance.startUserId", target = "startUserId"),
-            @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
-            @Mapping(source = "startUser.nickname", target = "startUserNickname")
-    })
+    @Mappings({@Mapping(source = "processInstance.id", target = "id"),
+        @Mapping(source = "processInstance.name", target = "name"),
+        @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+        @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+        @Mapping(source = "startUser.nickname", target = "startUserNickname")})
     BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
 
-    default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
-                                             HistoricProcessInstance processInstance, Map<Long, AdminUserRespDTO> userMap,
-                                             Map<Long, DeptRespDTO> deptMap) {
+    default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
+        Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
+        Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
         return CollectionUtils.convertList(tasks, task -> {
             BpmTaskRespVO respVO = convert3(task);
             BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@@ -111,37 +140,56 @@ public interface BpmTaskConvert {
     @Mapping(target = "id", ignore = true)
     void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
 
-    @Mappings({
-            @Mapping(source = "processInstance.id", target = "id"),
-            @Mapping(source = "processInstance.name", target = "name"),
-            @Mapping(source = "processInstance.startUserId", target = "startUserId"),
-            @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
-            @Mapping(source = "startUser.nickname", target = "startUserNickname")
-    })
-    BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, AdminUserRespDTO startUser);
-
-    default BpmTaskExtDO convert2TaskExt(Task task){
-        BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
-                .setTaskId(task.getId())
-                .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
-                .setName(task.getName())
-                .setProcessDefinitionId(task.getProcessDefinitionId())
-                .setProcessInstanceId(task.getProcessInstanceId());
+    @Mappings({@Mapping(source = "processInstance.id", target = "id"),
+        @Mapping(source = "processInstance.name", target = "name"),
+        @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+        @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+        @Mapping(source = "startUser.nickname", target = "startUserNickname")})
+    BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
+        AdminUserRespDTO startUser);
+
+    default BpmTaskExtDO convert2TaskExt(Task task) {
+        BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())
+            .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
+            .setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
         taskExtDO.setCreateTime(task.getCreateTime());
         return taskExtDO;
     }
 
-    default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, Task task) {
+    default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
+        Task task) {
         BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
         reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
-                .setProcessInstanceName(processInstance.getName())
-                .setStartUserId(startUser.getId())
-                .setStartUserNickname(startUser.getNickname())
-                .setTaskId(task.getId())
-                .setTaskName(task.getName())
-                .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
+            .setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())
+            .setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())
+            .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
         return reqDTO;
     }
-}
-
 
+    /**
+     * bpmTaskExtDo 类数据去重
+     *
+     * @param bpmTaskExtDOList bpmTaskExtDo 类列表
+     *
+     * @return 返回新的list
+     */
+    default List<BpmTaskExtDO> distinct(List<BpmTaskExtDO> bpmTaskExtDOList) {
+        HashMap<String, BpmTaskExtDO> tmpMap = new HashMap<>(50);
+        List<BpmTaskExtDO> result = new ArrayList<>();
+        for (BpmTaskExtDO bpmTaskExtDO : bpmTaskExtDOList) {
+            boolean containsResult = tmpMap.containsKey(bpmTaskExtDO.getTaskDefKey());
+            if (BooleanUtil.isFalse(containsResult)) {
+                tmpMap.put(bpmTaskExtDO.getTaskDefKey(), bpmTaskExtDO);
+            }
+            BpmTaskExtDO tmpBpmTaskExtDO = tmpMap.get(bpmTaskExtDO.getTaskDefKey());
+            if (bpmTaskExtDO.getTaskDefKey().equals(tmpBpmTaskExtDO.getTaskDefKey())) {
+                if (!bpmTaskExtDO.getResult().equals(BpmProcessInstanceResultEnum.PROCESS.getResult())) {
+                    tmpMap.remove(bpmTaskExtDO.getTaskDefKey());
+                    tmpMap.put(bpmTaskExtDO.getTaskDefKey(), bpmTaskExtDO);
+                }
+            }
+        }
+        tmpMap.forEach((key, var) -> result.add(var));
+        return result;
+    }
+}

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;

+ 2 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java

@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
 
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
 import lombok.*;
 import java.util.*;
 import com.baomidou.mybatisplus.annotation.*;

+ 105 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java

@@ -0,0 +1,105 @@
+package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.*;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
+
+/**
+ * 任务流程关联表
+ *
+ * @author kemengkai
+ * @create 2022-05-09 10:33
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BpmActivityDO {
+
+    /**
+     * 任务流程关联id
+     */
+    private String id;
+
+    /**
+     * 审批结果
+     */
+    private Integer rev;
+
+    /**
+     * 任务流程部署id
+     */
+    private String procDefId;
+
+    /**
+     * 任务流程id
+     */
+    private String processInstanceId;
+
+    /**
+     * 任务执行id
+     */
+    private String executionId;
+
+    /**
+     * 任务key
+     */
+    private String activityId;
+
+    /**
+     * 任务id
+     */
+    private String taskId;
+
+    /**
+     * 调用流程id
+     */
+    private String callProcInstId;
+
+    /**
+     * 任务名称
+     */
+    private String activityName;
+
+    /**
+     * 任务类型
+     */
+    private String activityType;
+
+    /**
+     * 任务审批人id
+     */
+    private String assignee;
+
+    /**
+     * 任务开始时间
+     */
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
+    private Date startTime;
+
+    /**
+     * 任务结束时间
+     */
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
+    private Date endTime;
+
+    private Integer transactionOrder;
+
+    private Long duration;
+
+    /**
+     * 删除结果
+     */
+    private String deleteReason;
+
+    /**
+     * 租户id
+     */
+    private String tenantId;
+}

+ 2 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;

+ 6 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -27,6 +27,11 @@ public class BpmTaskExtDO extends BaseDO {
      */
     @TableId
     private Long id;
+
+    /**
+     * 流程任务key
+     */
+    private String taskDefKey;
     /**
      * 任务的审批人
      *

+ 50 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmActivityMapper.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.bpm.dal.mysql.task;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author kemengkai
+ * @create 2022-05-09 09:26
+ */
+@Mapper
+public interface BpmActivityMapper extends BaseMapperX<BpmActivityDO> {
+
+    /**
+     * 获取所有历史任务
+     *
+     * @return 返回历史任务
+     */
+    List<BpmActivityDO> listAll();
+
+    /**
+     * 获取指定流程的历史任务
+     *
+     * @param procInstId 流程id
+     *
+     * @return 返回历史任务
+     */
+    List<BpmActivityDO> listAllByProcInstIdAndDelete(@Param("procInstId") String procInstId);
+
+    /**
+     * 逻辑删除hiActInst表任务
+     *
+     * @param taskIdList 任务列表
+     *
+     * @return 返回是否成功
+     */
+    Boolean delHiActInstByTaskId(@Param("taskIdList") List<String> taskIdList);
+
+    /**
+     * 逻辑删除hiTaskInst任务
+     *
+     * @param taskIdList 任务列表
+     *
+     * @return 返回是否成功
+     */
+    Boolean delHiTaskInstByTaskId(@Param("taskIdList") List<String> taskIdList);
+}

+ 32 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.bpm.dal.mysql.task;
 
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -20,14 +21,43 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
         return selectList(BpmTaskExtDO::getTaskId, taskIds);
     }
 
+    /**
+     * 查询任务
+     *
+     * @param procInstId 流程id
+     *
+     * @return 返回任务列表
+     */
+    @TenantIgnore
+    List<BpmTaskExtDO> listByProcInstId(@Param("procInstId") String procInstId);
+
     default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
         return selectList("process_instance_id", processInstanceId);
     }
 
     /**
-     * 修改或签任务信息
+     * 删除非当前相同taskDefKey非进行中的任务
      *
      * @param entity 任务信息
      */
-    void updateUserOrSignTask(@Param("entity") BpmTaskExtDO entity);
+    void delTaskByProcInstIdAndTaskIdAndTaskDefKey(@Param("entity") BpmTaskExtDO entity);
+
+    /**
+     * 任务驳回
+     *
+     * @param taskId  任务列表
+     * @param comment 驳回理由
+     *
+     * @return 返回驳回结果,是否成功
+     */
+    Boolean backByTaskId(@Param("taskId") String taskId, @Param("comment") String comment);
+
+    /**
+     * 逻辑删除任务
+     *
+     * @param taskIdList 任务id列表
+     *
+     * @return 返回是否成功
+     */
+    Boolean delByTaskIds(@Param("taskIdList") List<String> taskIdList);
 }

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmModelFormTypeEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.definition;
+package cn.iocoder.yudao.module.bpm.domain.enums.definition;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskAssignRuleTypeEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.definition;
+package cn.iocoder.yudao.module.bpm.domain.enums.definition;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskRuleScriptEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.definition;
+package cn.iocoder.yudao.module.bpm.domain.enums.definition;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/message/BpmMessageEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.message;
+package cn.iocoder.yudao.module.bpm.domain.enums.message;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceDeleteReasonEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.task;
+package cn.iocoder.yudao.module.bpm.domain.enums.task;
 
 import cn.hutool.core.util.StrUtil;
 import lombok.AllArgsConstructor;

+ 3 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceResultEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.task;
+package cn.iocoder.yudao.module.bpm.domain.enums.task;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -15,7 +15,8 @@ public enum BpmProcessInstanceResultEnum {
     PROCESS(1, "处理中"),
     APPROVE(2, "通过"),
     REJECT(3, "不通过"),
-    CANCEL(4, "已取消");
+    CANCEL(4, "已取消"),
+    BACK(5, "退回/驳回");
 
     /**
      * 结果

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java → yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceStatusEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.enums.task;
+package cn.iocoder.yudao.module.bpm.domain.enums.task;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;

+ 34 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/vo/ApproveProcInstVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.bpm.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+
+/**
+ * 审批流程VO
+ *
+ * @author kemengkai
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ApproveProcInstVO {
+
+    @ApiModelProperty("任务id")
+    private String id;
+    @ApiModelProperty("任务部署key")
+    private String taskDefKey;
+    @ApiModelProperty("任务名称")
+    private String name;
+    @ApiModelProperty("审批人登录名")
+    private String assignee;
+    @ApiModelProperty("审批人姓名")
+    private String assigneeName;
+    @ApiModelProperty("审批回复")
+    private String taskComment;
+    @ApiModelProperty("审批完成时间")
+    private LocalDate endTime;
+}

+ 28 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmSecurityConfiguration.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.bpm.framework.bpm.config;
+
+import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
+
+/**
+ * @author kemengkai
+ * @create 2022-05-07 08:15
+ */
+@Configuration("bpmSecurityConfiguration")
+public class BpmSecurityConfiguration {
+
+    @Bean("bpmAuthorizeRequestsCustomizer")
+    public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
+        return new AuthorizeRequestsCustomizer() {
+
+            @Override
+            public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
+                // 任务回退接口
+                registry.antMatchers(buildAdminApi("/bpm/task/back")).permitAll();
+            }
+
+        };
+    }
+}

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceActivityBehavior.java

@@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java

@@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
 
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 
 import java.util.Set;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
 
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 import org.springframework.stereotype.Component;
 

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
 
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 import org.springframework.stereotype.Component;
 

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl
 
 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
 
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java

@@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
 import lombok.extern.slf4j.Slf4j;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java

@@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.PostApi;
 import cn.iocoder.yudao.module.system.api.dict.DictDataApi;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.bpm.service.definition.dto;
 
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
 import lombok.Data;
 
 /**

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.definition.dto;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
 import lombok.Data;
 
 import javax.validation.constraints.AssertTrue;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.message;
 
 import cn.iocoder.yudao.framework.web.config.WebProperties;
 import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
-import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.message.BpmMessageEnum;
 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
 import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;

+ 11 - 19
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java

@@ -1,28 +1,19 @@
 package cn.iocoder.yudao.module.bpm.service.task;
 
-import cn.hutool.core.io.IoUtil;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
 import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
 import lombok.extern.slf4j.Slf4j;
 
-import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.engine.HistoryService;
-import org.flowable.engine.history.HistoricActivityInstance;
-import org.flowable.engine.history.HistoricProcessInstance;
-import org.flowable.image.ProcessDiagramGenerator;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.io.InputStream;
-import java.util.Collections;
 import java.util.List;
 
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS;
-import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
 
 /**
  * BPM 活动实例 Service 实现类
@@ -36,14 +27,15 @@ public class BpmActivityServiceImpl implements BpmActivityService {
 
     @Resource
     private HistoryService historyService;
+    @Resource
+    private BpmActivityMapper bpmActivityMapper;
 
     @Override
-    public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) {
-        List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
-                .processInstanceId(processInstanceId).list();
-        return BpmActivityConvert.INSTANCE.convertList(activityList);
+    @TenantIgnore
+    public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String procInstId) {
+//                List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
+//                        .processInstanceId(procInstId).list();
+        List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(procInstId);
+        return BpmActivityConvert.INSTANCE.convertList(bpmActivityDOList);
     }
-
-
-
 }

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java

@@ -11,9 +11,9 @@ import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceDeleteReasonEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum;
 import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;

+ 27 - 10
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java

@@ -1,11 +1,11 @@
 package cn.iocoder.yudao.module.bpm.service.task;
 
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
 import org.flowable.task.api.Task;
 
-
 import javax.validation.Valid;
 import java.util.List;
 import java.util.Map;
@@ -20,16 +20,19 @@ public interface BpmTaskService {
     /**
      * 获得待办的流程任务分页
      *
-     * @param userId 用户编号
+     * @param userId    用户编号
      * @param pageReqVO 分页请求
+     *
      * @return 流程任务分页
      */
     PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
+
     /**
      * 获得已办的流程任务分页
      *
-     * @param userId 用户编号
+     * @param userId    用户编号
      * @param pageReqVO 分页请求
+     *
      * @return 流程任务分页
      */
     PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
@@ -38,17 +41,19 @@ public interface BpmTaskService {
      * 获得流程任务 Map
      *
      * @param processInstanceIds 流程实例的编号数组
+     *
      * @return 流程任务 Map
      */
     default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
         return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
-                Task::getProcessInstanceId);
+            Task::getProcessInstanceId);
     }
 
     /**
      * 获得流程任务列表
      *
      * @param processInstanceIds 流程实例的编号数组
+     *
      * @return 流程任务列表
      */
     List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
@@ -57,15 +62,25 @@ public interface BpmTaskService {
      * 获得指令流程实例的流程任务列表,包括所有状态的
      *
      * @param processInstanceId 流程实例的编号
+     *
      * @return 流程任务列表
      */
     List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
 
+    /**
+     * 获取任务详情
+     *
+     * @param processInstanceId 流程实例的编号
+     *
+     * @return 流程任务列表
+     */
+    List<BpmTaskRespVO> getTaskInfo(String processInstanceId);
+
     /**
      * 通过任务
      *
      * @param userId 用户编号
-     * @param reqVO 通过请求
+     * @param reqVO  通过请求
      */
     void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO);
 
@@ -73,28 +88,30 @@ public interface BpmTaskService {
      * 不通过任务
      *
      * @param userId 用户编号
-     * @param reqVO 不通过请求
+     * @param reqVO  不通过请求
      */
     void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
+
     /**
      * 回退任务
      *
-     * @param taskId 任务编号
+     * @param userId 用户id
+     * @param reqVO  回退任务信息
      */
-    void backTask(String taskId,String destinationTaskDefKey);
+    CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO);
 
     /**
      * 将流程任务分配给指定用户
      *
      * @param userId 用户编号
-     * @param reqVO 分配请求
+     * @param reqVO  分配请求
      */
     void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO);
 
     /**
      * 将流程任务分配给指定用户
      *
-     * @param id 流程任务编号
+     * @param id     流程任务编号
      * @param userId 用户编号
      */
     void updateTaskAssignee(String id, Long userId);

+ 105 - 46
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

@@ -2,17 +2,21 @@ package cn.iocoder.yudao.module.bpm.service.task;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
+import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -36,10 +40,12 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
 
 /**
@@ -50,7 +56,7 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  */
 @Slf4j
 @Service
-public class BpmTaskServiceImpl implements BpmTaskService{
+public class BpmTaskServiceImpl implements BpmTaskService {
 
     @Resource
     private TaskService taskService;
@@ -71,13 +77,14 @@ public class BpmTaskServiceImpl implements BpmTaskService{
     private BpmMessageService messageService;
     @Resource
     private BpmTaskAssignRuleMapper taskAssignRuleMapper;
+    @Resource
+    private BpmActivityMapper bpmActivityMapper;
 
     @Override
     public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
         // 查询待办任务
-        TaskQuery taskQuery = taskService.createTaskQuery()
-                .taskAssignee(String.valueOf(userId)) // 分配给自己
-                .orderByTaskCreateTime().desc(); // 创建时间倒序
+        TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己
+            .orderByTaskCreateTime().desc(); // 创建时间倒序
         if (StrUtil.isNotBlank(pageVO.getName())) {
             taskQuery.taskNameLike("%" + pageVO.getName() + "%");
         }
@@ -94,23 +101,22 @@ public class BpmTaskServiceImpl implements BpmTaskService{
         }
 
         // 获得 ProcessInstance Map
-        Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
-                convertSet(tasks, Task::getProcessInstanceId));
+        Map<String, ProcessInstance> processInstanceMap =
+            processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
         // 获得 User Map
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+            convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
         // 拼接结果
         return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
-                taskQuery.count());
+            taskQuery.count());
     }
 
     @Override
     public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
         // 查询已办任务
-        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
-                .finished() // 已完成
-                .taskAssignee(String.valueOf(userId)) // 分配给自己
-                .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
+        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
+            .taskAssignee(String.valueOf(userId)) // 分配给自己
+            .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
         if (StrUtil.isNotBlank(pageVO.getName())) {
             taskQuery.taskNameLike("%" + pageVO.getName() + "%");
         }
@@ -127,17 +133,20 @@ public class BpmTaskServiceImpl implements BpmTaskService{
         }
 
         // 获得 TaskExtDO Map
-        List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
+        List<BpmTaskExtDO> bpmTaskExtDOs =
+            taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
         Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
         // 获得 ProcessInstance Map
-        Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
+        Map<String, HistoricProcessInstance> historicProcessInstanceMap =
+            processInstanceService.getHistoricProcessInstanceMap(
                 convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
         // 获得 User Map
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+            convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
         // 拼接结果
-        return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
-                taskQuery.count());
+        return new PageResult<>(
+            BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
+            taskQuery.count());
     }
 
     @Override
@@ -151,17 +160,22 @@ public class BpmTaskServiceImpl implements BpmTaskService{
     @Override
     public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) {
         // 获得任务列表
-        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
-                .processInstanceId(processInstanceId)
+        List<HistoricTaskInstance> tasks =
+            historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId)
                 .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
                 .list();
         if (CollUtil.isEmpty(tasks)) {
             return Collections.emptyList();
         }
-
         // 获得 TaskExtDO Map
-        List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
-        Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
+        //        List<BpmTaskExtDO> bpmTaskExtDOList =
+        //            taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
+
+        List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
+        //        List<BpmTaskExtDO> bpmTaskExtDOList = BpmTaskConvert.INSTANCE.distinct(tmpBpmTaskExtDOList);
+        //        bpmTaskExtDOList.forEach(var -> log.info("var = " + var));
+
+        Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
         // 获得 ProcessInstance Map
         HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
         // 获得 User Map
@@ -172,7 +186,25 @@ public class BpmTaskServiceImpl implements BpmTaskService{
         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
 
         // 拼接数据
-        return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
+        return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDoMap, processInstance, userMap, deptMap);
+    }
+
+    @Override
+    public List<BpmTaskRespVO> getTaskInfo(String processInstanceId) {
+
+        List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
+
+        Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
+        // 获得 ProcessInstance Map
+        HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
+        // 获得 User Map
+        Set<Long> userIds = bpmTaskExtDOList.stream().map(BpmTaskExtDO::getAssigneeUserId).collect(Collectors.toSet());
+        userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
+
+
+        // 拼接数据
+        return new ArrayList<>();
     }
 
     @Override
@@ -199,9 +231,9 @@ public class BpmTaskServiceImpl implements BpmTaskService{
                 task.getTaskDefinitionKey());
         if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) {
             if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) {
-                taskExtMapper.updateUserOrSignTask(
-                    (BpmTaskExtDO)new BpmTaskExtDO().setTaskId(task.getId()).setName(task.getName())
-                        .setProcessInstanceId(task.getProcessInstanceId()).setDeleted(true));
+                taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey(
+                    new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())
+                        .setProcessInstanceId(task.getProcessInstanceId()));
             }
         }
     }
@@ -220,18 +252,45 @@ public class BpmTaskServiceImpl implements BpmTaskService{
         processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
 
         // 更新任务拓展表为不通过
-        taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
-                .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
+        taskExtMapper.updateByTaskId(
+            new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
+                .setComment(reqVO.getComment()));
     }
 
     @Override
-    public void backTask(String taskId,String destinationTaskDefKey) {
-        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
+    @Transactional(rollbackFor = Exception.class)
+    @TenantIgnore
+    public CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO) {
+        Long userId = Long.valueOf(reqVO.getUserId());
+        // 校验任务存在
+        Task task = checkTask(userId, reqVO.getTaskId());
+        ArrayList<String> oldTaskDefKeyList = CollUtil.newArrayList(reqVO.getOldTaskDefKey());
+
+        //        List<HistoricActivityInstance> hisActInstList =
+        //            historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list();
+        List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(reqVO.getProcInstId());
+        //        List<BpmActivityDO> bpmActivityDOList = BpmTaskConvert.INSTANCE.copyList(hisActInstList, BpmActivityDO.class);
+        //        bpmActivityDOList.forEach(bpmActivityDO -> log.info("bpmActivityDO = " + bpmActivityDO));
+        List<String> taskIdList = bpmActivityDOList.stream().filter(
+                bpmActivityDO -> bpmActivityDO.getActivityId().equals(reqVO.getOldTaskDefKey())
+                    && !bpmActivityDO.getTaskId().equals(reqVO.getTaskId())).map(BpmActivityDO::getTaskId)
+            .collect(Collectors.toList());
 
-        runtimeService.createChangeActivityStateBuilder()
-                .processInstanceId(currentTask.getProcessInstanceId())
-                .moveActivityIdTo(currentTask.getTaskDefinitionKey(), destinationTaskDefKey)
-                .changeState();
+        // 使用flowable更改任务节点
+        runtimeService.createChangeActivityStateBuilder().processInstanceId(reqVO.getProcInstId())
+            .moveActivityIdsToSingleActivityId(oldTaskDefKeyList, reqVO.getNewTaskDefKey()).changeState();
+
+        // 逻辑删除hiActInst表任务
+        Boolean delHiActInstResult = bpmActivityMapper.delHiActInstByTaskId(taskIdList);
+        // 逻辑删除hiTaskInst表任务
+        Boolean delHiTaskInstResult = bpmActivityMapper.delHiTaskInstByTaskId(taskIdList);
+        // 更新任务拓展表
+        Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getComment());
+        Boolean delTaskResult = taskExtMapper.delByTaskIds(taskIdList);
+        if (!delHiActInstResult && !delHiTaskInstResult && !backResult && !delTaskResult) {
+            throw new RuntimeException("任务驳回失败!!!");
+        }
+        return CommonResult.success(true);
     }
 
     @Override
@@ -247,40 +306,40 @@ public class BpmTaskServiceImpl implements BpmTaskService{
         taskService.setAssignee(id, String.valueOf(userId));
     }
 
-
     @Override
     public void createTaskExt(Task task) {
-        BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
-                .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
+        BpmTaskExtDO taskExtDO =
+            BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
         taskExtMapper.insert(taskExtDO);
     }
 
     @Override
     public void updateTaskExtComplete(Task task) {
-        BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
-                .setEndTime(new Date());
+        BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task).setEndTime(new Date());
         taskExtMapper.updateByTaskId(taskExtDO);
     }
 
     @Override
     public void updateTaskExtAssign(Task task) {
-        BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
-                .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
-                .setTaskId(task.getId());
+        BpmTaskExtDO taskExtDO =
+            new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
         taskExtMapper.updateByTaskId(taskExtDO);
         // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
         TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
             @Override
             public void afterCommit() {
-                ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+                ProcessInstance processInstance =
+                    processInstanceService.getProcessInstance(task.getProcessInstanceId());
                 AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
-                messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
+                messageService.sendMessageWhenTaskAssigned(
+                    BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
             }
         });
     }
 
     /**
      * 校验任务是否存在, 并且是否是分配给自己的任务
+     *
      * @param userId 用户 id
      * @param taskId task id
      */

+ 20 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/HistoricApproveTaskDTO.java

@@ -0,0 +1,20 @@
+package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author kemengkai
+ * @create 2022-01-11 15:09
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class HistoricApproveTaskDTO {
+
+    private String procInstId;
+    private String name;
+    private String assignee;
+
+}

+ 105 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/domain/vo/HiTaskinstVO.java

@@ -0,0 +1,105 @@
+package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain.vo;
+
+import lombok.Data;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ *  [  ]
+ *
+ * @author 孟凯
+ * @version 1.0
+ * @company 1024创新实验室( www.1024lab.net )
+ * @copyright (c) 1024创新实验室( www.1024lab.net )Inc. All rights reserved.
+ * @date  2022-01-17 15:14:27
+ * @since JDK1.8
+ */
+@Data
+public class HiTaskinstVO {
+    @ApiModelProperty("ID_")
+    private String id;
+
+    @ApiModelProperty("TASK_DEF_KEY_")
+    private String taskDefKey;
+
+    @ApiModelProperty("PROC_DEF_KEY_")
+    private String procDefKey;
+
+    @ApiModelProperty("PROC_DEF_ID_")
+    private String procDefId;
+
+    @ApiModelProperty("ROOT_PROC_INST_ID_")
+    private String rootProcInstId;
+
+    @ApiModelProperty("PROC_INST_ID_")
+    private String procInstId;
+
+    @ApiModelProperty("EXECUTION_ID_")
+    private String executionId;
+
+    @ApiModelProperty("CASE_DEF_KEY_")
+    private String caseDefKey;
+
+    @ApiModelProperty("CASE_DEF_ID_")
+    private String caseDefId;
+
+    @ApiModelProperty("CASE_INST_ID_")
+    private String caseInstId;
+
+    @ApiModelProperty("CASE_EXECUTION_ID_")
+    private String caseExecutionId;
+
+    @ApiModelProperty("ACT_INST_ID_")
+    private String actInstId;
+
+    @ApiModelProperty("NAME_")
+    private String name;
+
+    @ApiModelProperty("PARENT_TASK_ID_")
+    private String parentTaskId;
+
+    @ApiModelProperty("DESCRIPTION_")
+    private String description;
+
+    @ApiModelProperty("OWNER_")
+    private String owner;
+
+    @ApiModelProperty("ASSIGNEE_")
+    private String assignee;
+
+    @ApiModelProperty("START_TIME_")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date startTime;
+
+    @ApiModelProperty("END_TIME_")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date endTime;
+
+    @ApiModelProperty("DURATION_")
+    private Long duration;
+
+    @ApiModelProperty("DELETE_REASON_")
+    private String deleteReason;
+
+    @ApiModelProperty("PRIORITY_")
+    private Integer priority;
+
+    @ApiModelProperty("DUE_DATE_")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date dueDate;
+
+    @ApiModelProperty("FOLLOW_UP_DATE_")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date followUpDate;
+
+    @ApiModelProperty("TENANT_ID_")
+    private String tenantId;
+
+    @ApiModelProperty("REMOVAL_TIME_")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date removalTime;
+
+
+
+}

+ 263 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskinstService.java

@@ -0,0 +1,263 @@
+package cn.iocoder.yudao.module.business.hi.task.inst.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.module.bpm.domain.vo.ApproveProcInstVO;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.RepositoryService;
+import org.flowable.engine.TaskService;
+import org.flowable.variable.api.history.HistoricVariableInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * [  ]
+ *
+ * @author 孟凯
+ * @version 1.0
+ * @company 1024创新实验室(www.1024lab.net)
+ * @copyright (c)  1024创新实验室( www.1024lab.net )Inc. All rights reserved.
+ * @date 2022-01-17 15:14:27
+ * @since JDK1.8
+ */
+@Slf4j
+@Service
+public class HiTaskinstService {
+
+
+    @Autowired
+    private TaskService taskService;
+    @Autowired
+    private HistoryService historyService;
+    @Autowired
+    private RepositoryService repositoryService;
+
+    /**
+     * 获取任务具体流程信息
+     *
+     * @param procInstId 流程id
+     * @param procDefId  流程部署id
+     *
+     * @return 返回流程信息
+     */
+    public List<ApproveProcInstVO> taskGetComment(String procInstId, String procDefId) {
+        Map<String, Object> variableMap = new HashMap<>(50);
+        List<HistoricVariableInstance> hisVarInstList =
+            historyService.createHistoricVariableInstanceQuery().processInstanceId(procInstId).list();
+        hisVarInstList.forEach(hisVarInst -> {
+            variableMap.put(hisVarInst.getName(), hisVarInst.getValue());
+        });
+
+        List<ApproveProcInstVO> procInstVOList = hiTaskinstDao.listByProcInstIdAndNotDelete(procInstId);
+
+        BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModel(procDefId);
+        DomElement document1 = bpmnModelInstance.getDocument().getElementById(procDefId.split(":")[0]);
+        LinkedHashMap<String, DomElement> domElementMap = new LinkedHashMap<>(50);
+        getChildElementToMap(document1, domElementMap);
+        getChildNode(procInstVOList, domElementMap, variableMap);
+        return procInstVOList;
+    }
+
+    /**
+     * 获取子节点信息,存储到map中
+     *
+     * @param domElement    父节点
+     * @param domElementMap 节点map
+     */
+    private void getChildElementToMap(DomElement domElement, LinkedHashMap<String, DomElement> domElementMap) {
+        List<DomElement> childElements = domElement.getChildElements();
+        for (DomElement childElement : childElements) {
+            if ("BPMNDiagram".equals(childElement.getLocalName())) {
+                break;
+            }
+            if ("extensionElements".equals(childElement.getLocalName())) {
+                break;
+            }
+            if (!"outgoing".equals(childElement.getLocalName()) && !"incoming".equals(childElement.getLocalName())) {
+                domElementMap.put(childElement.getAttribute("id"), childElement);
+            }
+            getChildElementToMap(childElement, domElementMap);
+        }
+    }
+
+    /**
+     * 获取子节点信息
+     *
+     * @param procInstVOList 流程VO列表
+     * @param domElementMap  节点map
+     * @param variableMap    流程所有的变量
+     */
+    private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
+        Map<String, Object> variableMap) {
+        DomElement domElement = domElementMap.get(procInstVOList.get(procInstVOList.size() - 1).getTaskDefKey());
+        for (DomElement childElement : domElement.getChildElements()) {
+            if ("outgoing".equals(childElement.getLocalName())) {
+                DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
+                getChildNode(procInstVOList, domElementMap, variableMap, tmpDomElement);
+            }
+        }
+    }
+
+    /**
+     * 获取子节点信息
+     *
+     * @param procInstVOList 流程VO列表
+     * @param domElementMap  节点map
+     * @param variableMap    流程所有的变量
+     * @param domElement     父节点信息
+     */
+    private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
+        Map<String, Object> variableMap, DomElement domElement) {
+        if ("exclusiveGateway".equals(domElement.getLocalName())) {
+            DomElement domElementChild = getNodeExclusiveGateway(domElementMap, variableMap, domElement);
+            getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
+        } else if ("userTask".equals(domElement.getLocalName())) {
+            getProcInstVO(procInstVOList, domElement, variableMap);
+            for (DomElement childElement : domElement.getChildElements()) {
+                if ("outgoing".equals(childElement.getLocalName())) {
+                    DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
+                    DomElement domElementChild = getNodeBySequenceFlow(domElementMap, tmpDomElement);
+                    if ("endEvent".equals(domElementChild.getLocalName())) {
+                        return;
+                    }
+                    getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
+                }
+            }
+        } else {
+            DomElement domElementChild = getNodeBySequenceFlow(domElementMap, domElement);
+            if (BeanUtil.isEmpty(domElementChild)) {
+                throw new RuntimeException("无流程可执行!!!");
+            }
+            if ("endEvent".equals(domElementChild.getLocalName())) {
+                return;
+            }
+            getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
+        }
+    }
+
+    /**
+     * 获取网关节点的子节点
+     *
+     * @param domElementMap 流程所有的节点
+     * @param variableMap   流程所有的变量
+     * @param domElement    父节点信息
+     *
+     * @return 返回子节点信息
+     */
+    private DomElement getNodeExclusiveGateway(LinkedHashMap<String, DomElement> domElementMap,
+        Map<String, Object> variableMap, DomElement domElement) {
+        Boolean elExpressionFlag = Boolean.FALSE;
+        ArrayList<DomElement> nullChildSequenceFlowList = new ArrayList<>();
+        for (DomElement exclusiveGatewayChild : domElement.getChildElements()) {
+            if ("outgoing".equals(exclusiveGatewayChild.getLocalName()) && BooleanUtil.isFalse(elExpressionFlag)) {
+                DomElement sequenceFlowDomElement = domElementMap.get(exclusiveGatewayChild.getTextContent());
+                if (CollUtil.isNotEmpty(sequenceFlowDomElement.getChildElements())
+                    && sequenceFlowDomElement.getChildElements().size() > 0) {
+                    for (DomElement conditionExpression : sequenceFlowDomElement.getChildElements()) {
+                        if ("conditionExpression".equals(conditionExpression.getLocalName())) {
+                            elExpressionFlag = elExpression(conditionExpression.getTextContent(), variableMap);
+                            if (BooleanUtil.isTrue(elExpressionFlag)) {
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    nullChildSequenceFlowList.add(sequenceFlowDomElement);
+                }
+                if (elExpressionFlag) {
+                    return getNodeBySequenceFlow(domElementMap, sequenceFlowDomElement);
+                }
+            }
+        }
+        if (CollUtil.isEmpty(nullChildSequenceFlowList) && nullChildSequenceFlowList.size() < 1) {
+            throw new RuntimeException("网关缺少无条件流程可执行!!!");
+        }
+        if (nullChildSequenceFlowList.size() > 1) {
+            throw new RuntimeException("无条件流程大于1条!!!");
+        }
+        return getNodeBySequenceFlow(domElementMap, nullChildSequenceFlowList.get(0));
+    }
+
+    /**
+     * 获取流程序列流的子节点
+     *
+     * @param domElementMap 流程所有节点
+     * @param domElement    父节点信息
+     *
+     * @return 返回子节点
+     */
+    private DomElement getNodeBySequenceFlow(LinkedHashMap<String, DomElement> domElementMap, DomElement domElement) {
+        String targetRef = domElement.getAttribute("targetRef");
+        return domElementMap.get(targetRef);
+    }
+
+    /**
+     * 设置节点信息进ApproveProcInstVO
+     *
+     * @param procInstVOList ApproveProcInstVOList
+     * @param domElement     节点信息
+     * @param variableMap    流程所有变量
+     */
+    private void getProcInstVO(List<ApproveProcInstVO> procInstVOList, DomElement domElement,
+        Map<String, Object> variableMap) {
+        String camundaNameSpaceUri = "http://camunda.org/schema/1.0/bpmn";
+        boolean userListFlag = false;
+        List<Object> approveProcInstVOList = new ArrayList<>();
+        for (DomElement childElement : domElement.getChildElements()) {
+            if ("multiInstanceLoopCharacteristics".equals(childElement.getLocalName())) {
+                userListFlag = true;
+                String collectionVar = childElement.getAttribute(camundaNameSpaceUri, "collection");
+                Object taskUserList = variableMap.get(collectionVar);
+                approveProcInstVOList = JSONUtil.parseArray(taskUserList);
+            }
+        }
+
+        if (userListFlag) {
+            approveProcInstVOList.forEach(tmpAssignee -> {
+                String assignee = String.valueOf(tmpAssignee);
+                ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
+                approveProcInstVO.setName(domElement.getAttribute("name"));
+                approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
+                approveProcInstVO.setAssignee(assignee);
+                approveProcInstVO.setAssigneeName(employeeDao.getByLoginName(assignee, 0).getActualName());
+                procInstVOList.add(approveProcInstVO);
+            });
+        } else {
+            ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
+            approveProcInstVO.setName(domElement.getAttribute("name"));
+            approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
+            approveProcInstVO.setAssignee(domElement.getAttribute(camundaNameSpaceUri, "assignee"));
+            approveProcInstVO.setAssigneeName(
+                employeeDao.getByLoginName(approveProcInstVO.getAssignee(), 0).getActualName());
+            procInstVOList.add(approveProcInstVO);
+        }
+    }
+
+    /**
+     * 网关分叉条件判断,网关分叉,必须要有默认出口
+     *
+     * @param elExpression el表达式
+     * @param variableMap  流程所有变量
+     *
+     * @return 返回true或false
+     */
+    private Boolean elExpression(String elExpression, Map<String, Object> variableMap) {
+        ExpressionFactory factory = new ExpressionFactoryImpl();
+        SimpleContext context = new SimpleContext();
+        for (String k : variableMap.keySet()) {
+            if (variableMap.get(k) != null) {
+                context.setVariable(k,
+                    factory.createValueExpression(variableMap.get(k), variableMap.get(k).getClass()));
+            }
+        }
+        ValueExpression e = factory.createValueExpression(context, elExpression, Boolean.class);
+        //el表达式和variables得到的结果
+        return (Boolean)e.getValue(context);
+    }
+}

+ 48 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml

@@ -0,0 +1,48 @@
+<?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="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper">
+
+    <update id="delHiActInstByTaskId">
+        UPDATE act_hi_actinst
+        SET delete_reason_ = 'delete task' WHERE task_id_ IN
+        <foreach collection="taskIdList" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </update>
+    <delete id="delHiTaskInstByTaskId">
+        UPDATE act_hi_taskinst
+        SET delete_reason_ = 'delete task' WHERE id_ IN
+        <foreach collection="taskIdList" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </delete>
+
+    <select id="listAll" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO">
+        SELECT *
+        FROM act_hi_taskinst;
+    </select>
+    <select id="listAllByProcInstIdAndDelete"
+            resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO">
+        SELECT id_                AS `id`,
+               rev_               AS `rev`,
+               proc_def_id_       AS `proc_def_id`,
+               proc_inst_id_      AS `process_instance_id`,
+               execution_id_      AS `execution_id`,
+               act_id_            AS `activity_id`,
+               task_id_           AS `task_id`,
+               call_proc_inst_id_ AS `call_proc_inst_id`,
+               act_name_          AS `activity_name`,
+               act_type_          AS `activity_type`,
+               assignee_          AS `assignee`,
+               start_time_        AS `start_time`,
+               end_time_          AS `end_time`,
+               transaction_order_ AS `transaction_order`,
+               duration_          AS `duration`,
+               delete_reason_     AS `delete_reason`,
+               tenant_id_         AS `tenant_id`
+        FROM act_hi_actinst aha
+        WHERE aha.proc_inst_id_ = #{procInstId}
+          AND aha.act_type_ != 'sequenceFlow'
+        LIMIT 500;
+    </select>
+</mapper>

+ 31 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml

@@ -2,8 +2,36 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper">
 
-    
-    <update id="updateUserOrSignTask">
-        UPDATE bpm_task_ext SET deleted=1 WHERE process_instance_id = #{entity.processInstanceId} AND name = #{entity.name} AND task_id != #{entity.taskId}
+
+    <update id="delTaskByProcInstIdAndTaskIdAndTaskDefKey">
+        UPDATE bpm_task_ext
+        SET deleted=1
+        WHERE process_instance_id = #{entity.processInstanceId}
+          AND task_def_key = #{entity.taskDefKey}
+          AND task_id != #{entity.taskId}
+    </update>
+    <update id="backByTaskId">
+        UPDATE bpm_task_ext
+        SET result=2,
+            `comment`=#{comment}
+        WHERE task_id = #{taskId}
     </update>
+    <update id="delByTaskIds">
+        UPDATE bpm_task_ext
+        SET result=1,
+        `deleted`= true
+        WHERE `task_id` IN
+        <foreach collection="taskIdList" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </update>
+
+    <select id="listByProcInstId" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO">
+        SELECT *
+        FROM bpm_task_ext
+        WHERE `process_instance_id` = #{procInstId}
+          AND `deleted` = FALSE
+        ORDER BY create_time
+        LIMIT 500
+    </select>
 </mapper>

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/MultiInstancesTest.java

@@ -8,13 +8,13 @@ import org.flowable.engine.repository.ProcessDefinition;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.engine.test.Deployment;
 import org.flowable.task.api.Task;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.text.SimpleDateFormat;
 import java.util.*;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 /**
  * @author henryyan

+ 1 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java

@@ -8,6 +8,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression
 
 /**
  * System 模块的 Security 配置
+ * @author kemengkai
  */
 @Configuration("systemSecurityConfiguration")
 public class SecurityConfiguration {