chen.cheng 4 місяців тому
батько
коміт
fe07d11e9e
26 змінених файлів з 1812 додано та 12 видалено
  1. 12 0
      bd-park/park-backend/park-application/pom.xml
  2. 15 2
      bd-park/park-backend/park-application/src/main/resources/application.yml
  3. 0 3
      bd-park/park-backend/park-core/src/main/java/com/huashe/park/core/service/impl/ConsUnitInfoServiceImpl.java
  4. 4 0
      bd-park/park-backend/park-core/src/main/java/com/huashe/park/core/service/impl/PileMachineInfoServiceImpl.java
  5. 16 0
      bd-park/park-backend/pom.xml
  6. 12 1
      common-application/pom.xml
  7. 19 6
      common-application/ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtils.java
  8. 39 0
      common-application/ruoyi-flow/pom.xml
  9. 40 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/AbstractWarmFlowAdapter.java
  10. 35 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/AddSignatureAdapter.java
  11. 35 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/DeputeAdapter.java
  12. 35 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/ReductionSignatureAdapter.java
  13. 35 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/TransferAdapter.java
  14. 9 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/WarmFlowAdapter.java
  15. 232 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/DefController.java
  16. 366 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/ExecuteController.java
  17. 209 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/FormController.java
  18. 68 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/mapper/WarmFlowMapper.java
  19. 64 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/ExecuteService.java
  20. 14 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/HhDefService.java
  21. 84 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/impl/ExecuteServiceImpl.java
  22. 59 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/impl/HhDefServiceImpl.java
  23. 81 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/vo/FlowTaskVo.java
  24. 75 0
      common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/vo/WarmFlowInteractiveTypeVo.java
  25. 253 0
      common-application/ruoyi-flow/src/main/resources/mapper/flow/WarmFLowMapper.xml
  26. 1 0
      common-application/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

+ 12 - 0
bd-park/park-backend/park-application/pom.xml

@@ -50,6 +50,10 @@
         </dependency>
         <dependency>
             <groupId>com.huashe.application</groupId>
+            <artifactId>ruoyi-flow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.huashe.application</groupId>
             <artifactId>ruoyi-common</artifactId>
         </dependency>
         <dependency>
@@ -75,6 +79,14 @@
             <artifactId>park-core</artifactId>
             <version>${park.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.dromara.warm</groupId>
+            <artifactId>warm-flow-mybatis-sb-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.dromara.warm</groupId>
+            <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

+ 15 - 2
bd-park/park-backend/park-application/src/main/resources/application.yml

@@ -111,11 +111,11 @@ token:
 
 huashe:
   permit:
-    urlPatterns: /pkb/**,/pkbs/**
+    urlPatterns: /pkbs/**,/warm-flow-ui/**
 # MyBatis配置
 mybatis:
   # 搜索指定包别名
-  typeAliasesPackage: com.huashe.**.domain,com.ruoyi.**.domain
+  typeAliasesPackage: com.huashe.**.domain,com.ruoyi.**.domain,org.dromara.warm.flow.orm.entity
   # 配置mapper的扫描,找到所有的mapper.xml映射文件
   mapperLocations: classpath*:mapper/**/*Mapper.xml
   # 加载全局的配置文件
@@ -147,3 +147,16 @@ xss:
 evt-fusion:
   thread-pool-size: 2
 
+# warm-flow工作流配置
+warm-flow:
+  # 是否开启工作流,默认true
+  enabled: true
+  # 是否显示banner图,默认是
+  banner: true
+  # id生成器类型, 不填默认为orm扩展自带生成器或者warm-flow内置的19位雪花算法, SnowId14:14位,SnowId15:15位, SnowFlake19:19位
+  key_type:
+  # 是否开启设计器ui,默认true
+  ui: true
+  ## 如果需要工作流共享业务系统权限,默认Authorization,如果有多个token,用逗号分隔
+  token-name: Authorization
+

+ 0 - 3
bd-park/park-backend/park-core/src/main/java/com/huashe/park/core/service/impl/ConsUnitInfoServiceImpl.java

@@ -90,9 +90,6 @@ public class ConsUnitInfoServiceImpl implements IConsUnitInfoService {
     @Autowired
     private IConsPileHoleInfoService pileHoleInfoService;
 
-    @Autowired
-    private ExcelHandle excelHandle;
-
     private final static String PROFILE = "/profile";
 
     @Autowired

+ 4 - 0
bd-park/park-backend/park-core/src/main/java/com/huashe/park/core/service/impl/PileMachineInfoServiceImpl.java

@@ -10,6 +10,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 
 import com.huashe.common.utils.StringUtils;
 import com.huashe.park.common.EnhancedIDGenerator;
@@ -210,6 +211,9 @@ public class PileMachineInfoServiceImpl implements IPileMachineInfoService {
 
     @Override
     public List<PileMachineInfo> selectMachineByConsUnitId(Long consUnitId) {
+        if (ObjectUtils.isEmpty(consUnitId)) {
+            return pileMachineInfoMapper.selectPileMachineInfoList(new PileMachineInfo());
+        }
         return pileMachineInfoMapper.selectMachineByConsUnitId(consUnitId);
     }
 

+ 16 - 0
bd-park/park-backend/pom.xml

@@ -58,6 +58,7 @@
         <fastexcel.version>1.1.0</fastexcel.version>
         <paho.version>1.2.5</paho.version>
         <common.collect>4.4</common.collect>
+        <warm-flow>1.6.7</warm-flow>
     </properties>
 
     <!-- 依赖声明 -->
@@ -220,6 +221,11 @@
                 <artifactId>ruoyi-common</artifactId>
                 <version>${ruoyi.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.huashe.application</groupId>
+                <artifactId>ruoyi-flow</artifactId>
+                <version>${ruoyi.version}</version>
+            </dependency>
 
             <dependency>
                 <groupId>com.dtflys.forest</groupId>
@@ -372,6 +378,16 @@
                 <artifactId>commons-collections4</artifactId>
                 <version>${common.collect}</version>
             </dependency>
+            <dependency>
+                <groupId>org.dromara.warm</groupId>
+                <artifactId>warm-flow-mybatis-sb-starter</artifactId>
+                <version>${warm-flow}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.dromara.warm</groupId>
+                <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
+                <version>${warm-flow}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
     <repositories>

+ 12 - 1
common-application/pom.xml

@@ -36,6 +36,7 @@
         <spring-security.version>5.7.12</spring-security.version>
         <spring-framework.version>5.3.39</spring-framework.version>
         <prod.commons.version>1.0-SNAPSHOT</prod.commons.version>
+        <warm-flow>1.6.7</warm-flow>
     </properties>
 
     <!-- 依赖声明 -->
@@ -224,7 +225,16 @@
                 <artifactId>prod-commons</artifactId>
                 <version>${prod.commons.version}</version>
             </dependency>
-
+            <dependency>
+                <groupId>org.dromara.warm</groupId>
+                <artifactId>warm-flow-mybatis-sb-starter</artifactId>
+                <version>${warm-flow}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.dromara.warm</groupId>
+                <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
+                <version>${warm-flow}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -235,6 +245,7 @@
         <module>ruoyi-quartz</module>
         <module>ruoyi-generator</module>
         <module>ruoyi-common</module>
+        <module>ruoyi-flow</module>
     </modules>
     <packaging>pom</packaging>
 

+ 19 - 6
common-application/ruoyi-common/src/main/java/com/ruoyi/common/utils/SpringUtils.java

@@ -1,5 +1,6 @@
 package com.ruoyi.common.utils;
 
+
 import com.huashe.common.utils.StringUtils;
 import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.BeansException;
@@ -10,14 +11,15 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.stereotype.Component;
 
+import java.util.Map;
 
 /**
  * spring工具类 方便在非spring管理环境中获取bean
- * 
+ *
  * @author ruoyi
  */
 @Component
-public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
 {
     /** Spring应用上下文环境 */
     private static ConfigurableListableBeanFactory beanFactory;
@@ -25,13 +27,13 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
     private static ApplicationContext applicationContext;
 
     @Override
-    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
     {
         SpringUtils.beanFactory = beanFactory;
     }
 
     @Override
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
     {
         SpringUtils.applicationContext = applicationContext;
     }
@@ -114,7 +116,7 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
 
     /**
      * 获取aop代理对象
-     * 
+     *
      * @param invoker
      * @return
      */
@@ -156,4 +158,15 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
     {
         return applicationContext.getEnvironment().getRequiredProperty(key);
     }
-}
+
+    /**
+     * 获取clazz类型所有的实现类,key为类名
+     *
+     * @param clazz 类类型
+     * @param <T>   T
+     * @return 所有实现类
+     */
+    public static <T> Map<String, T> getBeanNamesForType(Class<T> clazz) {
+        return beanFactory.getBeansOfType(clazz);
+    }
+}

+ 39 - 0
common-application/ruoyi-flow/pom.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>common-application</artifactId>
+        <groupId>com.huashe.application</groupId>
+        <version>3.8.8</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-flow</artifactId>
+
+    <description>
+        flow工作流模块
+    </description>
+
+    <dependencies>
+        <!-- 通用工具-->
+        <dependency>
+            <groupId>com.huashe.application</groupId>
+            <artifactId>ruoyi-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.dromara.warm</groupId>
+            <artifactId>warm-flow-mybatis-sb-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.dromara.warm</groupId>
+            <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.huashe.application</groupId>
+            <artifactId>ruoyi-system</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 40 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/AbstractWarmFlowAdapter.java

@@ -0,0 +1,40 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.dromara.warm.flow.core.service.TaskService;
+import org.dromara.warm.flow.core.utils.StreamUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public abstract class AbstractWarmFlowAdapter {
+    @Resource
+    protected TaskService taskService;
+
+    /**
+     * 获取权限
+     *
+     * @return 权限列表
+     */
+    protected List<String> permissionList(SysUser sysUser, String userId) {
+        List<SysRole> roles = sysUser.getRoles();
+        List<String> permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId());
+        permissionList.add(userId);
+        permissionList.add("dept:" + sysUser.getDeptId());
+        return permissionList;
+    }
+
+    /**
+     * 根据类型获取描述
+     *
+     * @param type 流程类型
+     * @return value
+     */
+    protected String type(Integer type) {
+        return CooperateType.getValueByKey(type);
+    }
+}

+ 35 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/AddSignatureAdapter.java

@@ -0,0 +1,35 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import org.dromara.warm.flow.core.dto.FlowParams;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.springframework.stereotype.Component;
+
+import java.util.Objects;
+
+/**
+ * 加签适配器
+ */
+@Component
+public class AddSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter {
+    @Override
+    public boolean isAdapter(Integer warmFlowType) {
+        return Objects.equals(CooperateType.ADD_SIGNATURE.getKey(), warmFlowType);
+    }
+
+    @Override
+    public boolean adapter(WarmFlowInteractiveTypeVo obj) {
+        Long taskId = obj.getTaskId();
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        String userId = String.valueOf(sysUser.getUserId());
+        FlowParams flowParams = new FlowParams()
+                .handler(userId)
+                .permissionFlag(permissionList(sysUser, userId))
+                .addHandlers(obj.getAddHandlers())
+                .message(this.type(obj.getOperatorType()));
+
+        return super.taskService.addSignature(taskId, flowParams);
+    }
+}

+ 35 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/DeputeAdapter.java

@@ -0,0 +1,35 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import org.dromara.warm.flow.core.dto.FlowParams;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.springframework.stereotype.Component;
+
+import java.util.Objects;
+
+/**
+ * 委派适配器
+ */
+@Component
+public class DeputeAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter {
+    @Override
+    public boolean isAdapter(Integer warmFlowType) {
+        return Objects.equals(CooperateType.DEPUTE.getKey(), warmFlowType);
+    }
+
+    @Override
+    public boolean adapter(WarmFlowInteractiveTypeVo obj) {
+        Long taskId = obj.getTaskId();
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        String userId = String.valueOf(sysUser.getUserId());
+        FlowParams flowParams = new FlowParams()
+                .handler(userId)
+                .permissionFlag(permissionList(sysUser, userId))
+                .addHandlers(obj.getAddHandlers())
+                .message(this.type(obj.getOperatorType()));
+
+        return super.taskService.depute(taskId, flowParams);
+    }
+}

+ 35 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/ReductionSignatureAdapter.java

@@ -0,0 +1,35 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import org.dromara.warm.flow.core.dto.FlowParams;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.springframework.stereotype.Component;
+
+import java.util.Objects;
+
+/**
+ * 减签适配器
+ */
+@Component
+public class ReductionSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter {
+    @Override
+    public boolean isAdapter(Integer warmFlowType) {
+        return Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), warmFlowType);
+    }
+
+    @Override
+    public boolean adapter(WarmFlowInteractiveTypeVo obj) {
+        Long taskId = obj.getTaskId();
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        String userId = String.valueOf(sysUser.getUserId());
+        FlowParams flowParams = new FlowParams()
+                .handler(userId)
+                .permissionFlag(permissionList(sysUser, userId))
+                .reductionHandlers(obj.getAddHandlers())
+                .message(type(obj.getOperatorType()));
+
+        return super.taskService.reductionSignature(taskId, flowParams);
+    }
+}

+ 35 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/TransferAdapter.java

@@ -0,0 +1,35 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import org.dromara.warm.flow.core.dto.FlowParams;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.springframework.stereotype.Component;
+
+import java.util.Objects;
+
+/**
+ * 转办适配器
+ */
+@Component
+public class TransferAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter {
+    @Override
+    public boolean isAdapter(Integer warmFlowType) {
+        return Objects.equals(CooperateType.TRANSFER.getKey(), warmFlowType);
+    }
+
+    @Override
+    public boolean adapter(WarmFlowInteractiveTypeVo obj) {
+        Long taskId = obj.getTaskId();
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        String userId = String.valueOf(sysUser.getUserId());
+        FlowParams flowParams = new FlowParams()
+                .handler(userId)
+                .permissionFlag(permissionList(sysUser, userId))
+                .addHandlers(obj.getAddHandlers())
+                .message(this.type(obj.getOperatorType()));
+
+        return super.taskService.transfer(taskId, flowParams);
+    }
+}

+ 9 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/adapter/WarmFlowAdapter.java

@@ -0,0 +1,9 @@
+package com.ruoyi.flow.adapter;
+
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+
+public interface WarmFlowAdapter {
+    boolean isAdapter(Integer warmFlowType);
+
+    boolean adapter(WarmFlowInteractiveTypeVo obj);
+}

+ 232 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/DefController.java

@@ -0,0 +1,232 @@
+package com.ruoyi.flow.controller;
+
+import com.huashe.common.constant.HttpStatus;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.enums.BusinessType;
+import org.dromara.warm.flow.core.chart.BetweenChart;
+import org.dromara.warm.flow.core.chart.FlowChart;
+import org.dromara.warm.flow.core.entity.Definition;
+import org.dromara.warm.flow.core.service.ChartService;
+import org.dromara.warm.flow.core.service.DefService;
+import org.dromara.warm.flow.core.utils.MapUtil;
+import org.dromara.warm.flow.core.utils.page.Page;
+import org.dromara.warm.flow.orm.entity.FlowDefinition;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.awt.*;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 流程定义Controller
+ *
+ * @author hh
+ * @date 2023-04-11
+ */
+@Validated
+@RestController
+@RequestMapping("/flow/definition")
+public class DefController extends BaseController {
+    @Resource
+    private DefService defService;
+
+    @Resource
+    private ChartService chartService;
+
+    /**
+     * 分页查询流程定义列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(FlowDefinition flowDefinition) {
+        // flow组件自带分页功能
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Page<Definition> page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize());
+        page = defService.orderByCreateTime().desc().page(flowDefinition, page);
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(page.getList());
+        rspData.setTotal(page.getTotal());
+        return rspData;
+    }
+
+
+    /**
+     * 获取流程定义详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
+    @GetMapping(value = "/{id}")
+    public R<Definition> getInfo(@PathVariable("id") Long id) {
+        return R.ok(defService.getById(id));
+    }
+
+    /**
+     * 新增流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:add')")
+    @Log(title = "流程定义", businessType = BusinessType.INSERT)
+    @PostMapping
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> add(@RequestBody FlowDefinition flowDefinition) {
+        return R.ok(defService.saveAndInitNode(flowDefinition));
+    }
+
+    /**
+     * 发布流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
+    @Log(title = "流程定义", businessType = BusinessType.INSERT)
+    @GetMapping("/publish/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> publish(@PathVariable("id") Long id) {
+        return R.ok(defService.publish(id));
+    }
+
+    /**
+     * 取消发布流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
+    @Log(title = "流程定义", businessType = BusinessType.INSERT)
+    @GetMapping("/unPublish/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Void> unPublish(@PathVariable("id") Long id) {
+        defService.unPublish(id);
+        return R.ok();
+    }
+
+    /**
+     * 修改流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:edit')")
+    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
+    @PutMapping
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> edit(@RequestBody FlowDefinition flowDefinition) {
+        return R.ok(defService.updateById(flowDefinition));
+    }
+
+    /**
+     * 删除流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:remove')")
+    @Log(title = "流程定义", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> remove(@PathVariable List<Long> ids) {
+        return R.ok(defService.removeDef(ids));
+    }
+
+    /**
+     * 复制流程定义
+     */
+    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
+    @Log(title = "流程定义", businessType = BusinessType.INSERT)
+    @GetMapping("/copyDef/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> copyDef(@PathVariable("id") Long id) {
+        return R.ok(defService.copyDef(id));
+    }
+
+    @Log(title = "流程定义", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('flow:definition:importDefinition')")
+    @PostMapping("/importDefinition")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Void> importDefinition(MultipartFile file) throws Exception {
+        defService.importIs(file.getInputStream());
+        return R.ok();
+    }
+
+    @Log(title = "流程定义", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('flow:definition:exportDefinition')")
+    @PostMapping("/exportDefinition/{id}")
+    public ResponseEntity<byte[]> exportDefinition(@PathVariable("id") Long id) {
+        // 要导出的字符串
+        String content = defService.exportJson(id);
+
+        // 设置响应头
+        HttpHeaders headers = new HttpHeaders();
+        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exported_string.txt");
+
+        // 返回响应
+        return ResponseEntity.ok()
+                .headers(headers)
+                .contentType(MediaType.TEXT_PLAIN)
+                .body(content.getBytes(StandardCharsets.UTF_8));
+    }
+
+    /**
+     * 查询流程图
+     *
+     * @param definitionId
+     *
+     * @return
+     */
+    @GetMapping("/chartDef/{definitionId}")
+    public R<String> chartDef(@PathVariable("definitionId") Long definitionId) {
+        return R.ok(chartService.chartDef(definitionId));
+    }
+
+    /**
+     * 查询流程图
+     *
+     * @param instanceId
+     * @return
+     */
+    @GetMapping("/flowChart/{instanceId}")
+    public R<String> flowChart(@PathVariable("instanceId") Long instanceId) {
+        return R.ok(chartService.chartIns(instanceId, (flowChartChain) -> {
+            List<FlowChart> flowChartList = flowChartChain.getFlowChartList();
+            flowChartList.forEach(flowChart -> {
+                if (flowChart instanceof BetweenChart) {
+                    BetweenChart betweenChart = (BetweenChart) flowChart;
+                    Map<String, Object> extMap = betweenChart.getNodeJson().getExtMap();
+                    // 给节点顶部增加文字说明
+//                    betweenChart.topText("办理时间: 2025-02-08 12:12:12", Color.red);
+                    if (MapUtil.isNotEmpty(extMap)) {
+                        for(Map.Entry<String, Object> entry : extMap.entrySet()){
+                            // 给节点中追加文字
+                            betweenChart.addText(entry.getKey() + ":", Color.red);
+                            betweenChart.addText((String) entry.getValue(), Color.red);
+                        }
+                    }
+                }
+            });
+        }));
+    }
+
+    /**
+     * 激活流程
+     *
+     * @param definitionId
+     * @return
+     */
+    @GetMapping("/active/{definitionId}")
+    public R<Boolean> active(@PathVariable("definitionId") Long definitionId) {
+        return R.ok(defService.active(definitionId));
+    }
+
+    /**
+     * 挂起流程
+     *
+     * @param definitionId
+     * @return
+     */
+    @GetMapping("/unActive/{definitionId}")
+    public R<Boolean> unActive(@PathVariable("definitionId") Long definitionId) {
+        return R.ok(defService.unActive(definitionId));
+    }
+}

+ 366 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/ExecuteController.java

@@ -0,0 +1,366 @@
+package com.ruoyi.flow.controller;
+
+import com.huashe.common.utils.StringUtils;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import com.ruoyi.flow.service.ExecuteService;
+import com.ruoyi.flow.service.HhDefService;
+import com.ruoyi.flow.vo.FlowTaskVo;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.dromara.warm.flow.core.FlowEngine;
+import org.dromara.warm.flow.core.entity.*;
+import org.dromara.warm.flow.core.enums.CooperateType;
+import org.dromara.warm.flow.core.enums.NodeType;
+import org.dromara.warm.flow.core.enums.UserType;
+import org.dromara.warm.flow.core.service.*;
+import org.dromara.warm.flow.core.utils.StreamUtils;
+import org.dromara.warm.flow.orm.entity.FlowHisTask;
+import org.dromara.warm.flow.orm.entity.FlowTask;
+import org.springframework.beans.BeanUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**load
+ * 流程实例Controller
+ *
+ * @author hh
+ * @date 2023-04-18
+ */
+@Validated
+@RestController
+@RequestMapping("/flow/execute")
+public class ExecuteController extends BaseController {
+    @Resource
+    private ISysUserService userService;
+
+    @Resource
+    private ISysDeptService deptService;
+
+    @Resource
+    private ISysRoleService roleService;
+
+    @Resource
+    private HisTaskService hisTaskService;
+
+    @Resource
+    private TaskService taskService;
+
+    @Resource
+    private NodeService nodeService;
+
+    @Resource
+    private InsService insService;
+
+    @Resource
+    private UserService flowUserservice;
+
+    @Resource
+    private ExecuteService executeService;
+
+    @Resource
+    private HhDefService hhDefService;
+
+    /**
+     * 分页待办任务列表
+     */
+    @PreAuthorize("@ss.hasPermi('flow:execute:toDoPage')")
+    @GetMapping("/toDoPage")
+    public TableDataInfo toDoPage(FlowTask flowTask) {
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        List<String> permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser);
+        flowTask.setPermissionList(permissionList);
+        startPage();
+        List<FlowTaskVo> list = executeService.toDoPage(flowTask);
+        List<Long> taskIds = StreamUtils.toList(list, FlowTaskVo::getId);
+        List<User> userList = flowUserservice.getByAssociateds(taskIds);
+        Map<Long, List<User>> map = StreamUtils.groupByKey(userList, User::getAssociated);
+        for (FlowTaskVo taskVo : list) {
+            if (StringUtils.isNotNull(taskVo)) {
+                List<User> users = map.get(taskVo.getId());
+                if (CollectionUtils.isNotEmpty(users)) {
+                    for (User user : users) {
+                        if (UserType.APPROVAL.getKey().equals(user.getType())) {
+                            if (StringUtils.isEmpty(taskVo.getApprover())) {
+                                taskVo.setApprover("");
+                            }
+                            String name = getName(user.getProcessedBy());
+                            if (StringUtils.isNotEmpty(name)) taskVo.setApprover(taskVo.getApprover().concat(name).concat(";"));
+                        } else if (UserType.TRANSFER.getKey().equals(user.getType())) {
+                            if (StringUtils.isEmpty(taskVo.getTransferredBy())) {
+                                taskVo.setTransferredBy("");
+                            }
+                            String name = getName(user.getProcessedBy());
+                            if (StringUtils.isNotEmpty(name)) taskVo.setTransferredBy(taskVo.getTransferredBy().concat(name).concat(";"));
+                        } else if (UserType.DEPUTE.getKey().equals(user.getType())) {
+                            if (StringUtils.isEmpty(taskVo.getDelegate())) {
+                                taskVo.setDelegate("");
+                            }
+                            String name = getName(user.getProcessedBy());
+                            if (StringUtils.isNotEmpty(name)) taskVo.setDelegate(taskVo.getDelegate().concat(name).concat(";"));
+                        }
+                    }
+                }
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 分页抄送任务列表
+     * author:暗影
+     */
+    @PreAuthorize("@ss.hasPermi('flow:execute:copyPage')")
+    @GetMapping("/copyPage")
+    public TableDataInfo copyPage(FlowTask flowTask) {
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        List<String> permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser);
+        flowTask.setPermissionList(permissionList);
+        startPage();
+        List<FlowHisTask> list = executeService.copyPage(flowTask);
+        return getDataTable(list);
+    }
+    /**
+     * 分页已办任务列表
+     */
+    @PreAuthorize("@ss.hasPermi('flow:execute:donePage')")
+    @GetMapping("/donePage")
+    public TableDataInfo donePage(FlowHisTask flowHisTask) {
+        startPage();
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        List<String> permissionList = permissionList(String.valueOf(sysUser.getUserId()), sysUser.getDeptId(), sysUser);
+        flowHisTask.setPermissionList(permissionList);
+        List<FlowHisTask> list = executeService.donePage(flowHisTask);
+        Map<Long, String> userMap = StreamUtils.toMap(userService.selectUserList(new SysUser())
+                , SysUser::getUserId, SysUser::getNickName);
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (FlowHisTask hisTask : list) {
+                if (StringUtils.isNotEmpty(hisTask.getApprover())) {
+                    String name = getName(hisTask.getApprover());
+                    hisTask.setApprover(name);
+                }
+                if (StringUtils.isNotEmpty(hisTask.getCollaborator())) {
+                    String[] split = hisTask.getCollaborator().split(",");
+                    if (split.length > 1) {
+                        List<String> names = new ArrayList<>();
+                        for (String s : split) {
+                            names.add(userMap.get(Long.valueOf(s)));
+                        }
+                        hisTask.setCollaborator(StringUtils.join(names, ","));
+                    }
+                }
+            }
+        }
+        return getDataTable(list);
+    }
+
+    private String getName(String id) {
+        Map<Long, String> userMap = StreamUtils.toMap(userService.selectUserList(new SysUser())
+                , SysUser::getUserId, SysUser::getNickName);
+        Map<Long, String> deptMap = StreamUtils.toMap(deptService.selectDeptList(new SysDept())
+                , SysDept::getDeptId, SysDept::getDeptName);
+        Map<Long, String> roleMap = StreamUtils.toMap(roleService.selectRoleAll()
+                , SysRole::getRoleId, SysRole::getRoleName);
+        if (StringUtils.isNotNull(id)) {
+            if (id.contains("user:")) {
+                String name = userMap.get(Long.valueOf(id.replace("user:", "")));
+                if (StringUtils.isNotEmpty(name)) {
+                    return "用户:" + name;
+                }
+            } else if (id.contains("dept:")) {
+                String name = deptMap.get(Long.valueOf(id.replace("dept:", "")));
+                if (StringUtils.isNotEmpty(name)) {
+                    return "部门:" + name;
+                }
+            } else if (id.contains("role")) {
+                String name = roleMap.get(Long.valueOf(id.replace("role:", "")));
+                if (StringUtils.isNotEmpty(name)) {
+                    return "角色:" + name;
+                }
+            } else {
+                try {
+                    long parseLong = Long.parseLong(id);
+                    String name = userMap.get(parseLong);
+                    if (StringUtils.isNotEmpty(name)) {
+                        return "用户:" + name;
+                    }
+                } catch (NumberFormatException e) {
+                    return id;
+                }
+
+            }
+        }
+        return "";
+    }
+
+
+    /**
+     * 查询已办任务历史记录
+     */
+    @PreAuthorize("@ss.hasPermi('flow:execute:doneList')")
+    @GetMapping("/doneList/{instanceId}")
+    public R<List<FlowHisTask>> doneList(@PathVariable("instanceId") Long instanceId) {
+        List<HisTask> flowHisTasks = hisTaskService.orderById().desc().list(new FlowHisTask().setInstanceId(instanceId));
+        Map<Long, String> userMap = StreamUtils.toMap(userService.selectUserList(new SysUser())
+                , SysUser::getUserId, SysUser::getNickName);
+        List<FlowHisTask> flowHisTaskList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(flowHisTasks)) {
+            for (HisTask hisTask : flowHisTasks) {
+                if (StringUtils.isNotEmpty(hisTask.getApprover())) {
+                    String name = getName(hisTask.getApprover());
+                    hisTask.setApprover(name);
+                }
+                if (StringUtils.isNotEmpty(hisTask.getCollaborator())) {
+                    String[] split = hisTask.getCollaborator().split(",");
+                    if (split.length > 1) {
+                        List<String> names = new ArrayList<>();
+                        for (String s : split) {
+                            names.add(userMap.get(Long.valueOf(s)));
+                        }
+                        hisTask.setCollaborator(StringUtils.join(names, ","));
+                    }
+                }
+                FlowHisTask flowHisTask = new FlowHisTask();
+                BeanUtils.copyProperties(hisTask, flowHisTask);
+                flowHisTaskList.add(flowHisTask);
+            }
+        }
+        return R.ok(flowHisTaskList);
+    }
+
+    /**
+     * 根据taskId查询代表任务
+     *
+     * @param taskId
+     * @return
+     */
+    @GetMapping("/getTaskById/{taskId}")
+    public R<Task> getTaskById(@PathVariable("taskId") Long taskId) {
+        return R.ok(taskService.getById(taskId));
+    }
+
+    /**
+     * 查询跳转任意节点列表
+     */
+    @PreAuthorize("@ss.hasPermi('flow:execute:doneList')")
+    @GetMapping("/anyNodeList/{instanceId}")
+    public R<List<Node>> anyNodeList(@PathVariable("instanceId") Long instanceId) {
+        Instance instance = insService.getById(instanceId);
+        List<Node> nodeList = nodeService.list(FlowEngine.newNode().setDefinitionId(instance.getDefinitionId()));
+        nodeList.removeIf(node -> NodeType.isGateWay(node.getNodeType()));
+        return R.ok(nodeList);
+    }
+
+    /**
+     * 处理非办理的流程交互类型
+     *
+     * @param warmFlowInteractiveTypeVo 要转办用户
+     * @return 是否成功
+     */
+    @PostMapping("/interactiveType")
+    public R<Boolean> interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
+        return R.ok(hhDefService.interactiveType(warmFlowInteractiveTypeVo));
+    }
+
+    /**
+     * 交互类型可以选择的用户
+     *
+     * @param warmFlowInteractiveTypeVo 交互类型请求类
+     * @return 是否成功
+     */
+    @GetMapping("/interactiveTypeSysUser")
+    public TableDataInfo interactiveTypeSysUser(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
+        startPage();
+        SysUser currentUser = SecurityUtils.getLoginUser().getUser();
+        Long userId = currentUser.getUserId();
+        Integer operatorType = warmFlowInteractiveTypeVo.getOperatorType();
+        List<SysUser> list;
+        Long taskId = warmFlowInteractiveTypeVo.getTaskId();
+        List<User> users = flowUserservice.listByAssociatedAndTypes(taskId);
+        if (!Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), operatorType)) {
+            List<String> userIds = StreamUtils.toList(users, User::getProcessedBy);
+            warmFlowInteractiveTypeVo.setUserIds(userIds);
+            list = executeService.selectNotUserList(warmFlowInteractiveTypeVo);
+        } else {
+            List<String> userIds = StreamUtils.toList(users, User::getProcessedBy);
+            warmFlowInteractiveTypeVo.setUserIds(userIds);
+            list = executeService.selectUserList(warmFlowInteractiveTypeVo);
+            list = StreamUtils.filter(list, sysUser -> !Objects.equals(userId, sysUser.getUserId()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 激活流程
+     *
+     * @param instanceId
+     * @return
+     */
+    @GetMapping("/active/{instanceId}")
+    public R<Boolean> active(@PathVariable("instanceId") Long instanceId) {
+        return R.ok(insService.active(instanceId));
+    }
+
+    /**
+     * 挂起流程
+     *
+     * @param instanceId
+     * @return
+     */
+    @GetMapping("/unActive/{instanceId}")
+    public R<Boolean> unActive(@PathVariable("instanceId") Long instanceId) {
+        return R.ok(insService.unActive(instanceId));
+    }
+
+    /**
+     * 获取权限
+     *
+     * @param userId  用户编号
+     * @param deptId  部门编号
+     * @param sysUser 登陆用户
+     * @return 权限列表
+     */
+    private List<String> permissionList(String userId, Long deptId, SysUser sysUser) {
+        List<SysRole> roles = sysUser.getRoles();
+        List<String> permissionList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(roles)) {
+            permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId());
+        }
+        permissionList.add(userId);
+        if (Objects.nonNull(deptId)) {
+            permissionList.add("dept:" + deptId);
+        }
+        logger.info("当前用户所有权限[{}]", permissionList);
+        return permissionList;
+    }
+
+    /**
+     * 根据ID反显姓名
+     *
+     * @param ids 需要反显姓名的用户ID
+     * @return {@link R< List<SysUser>>}
+     * @author liangli
+     * @date 2024/8/21 17:08
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
+    @GetMapping(value = "/idReverseDisplayName/{ids}")
+    public R<List<SysUser>> idReverseDisplayName(@PathVariable Long[] ids) {
+        return R.ok(executeService.idReverseDisplayName(ids));
+    }
+
+}

+ 209 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/controller/FormController.java

@@ -0,0 +1,209 @@
+package com.ruoyi.flow.controller;
+
+import com.huashe.common.constant.HttpStatus;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.enums.BusinessType;
+import org.dromara.warm.flow.core.FlowEngine;
+import org.dromara.warm.flow.core.entity.Form;
+import org.dromara.warm.flow.core.service.FormService;
+import org.dromara.warm.flow.core.utils.page.Page;
+import org.dromara.warm.flow.orm.entity.FlowForm;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 表单Controller
+ *
+ * @author liangli
+ * @date 2024-09-05
+ */
+@Validated
+@RestController
+@RequestMapping("/flow/form")
+public class FormController extends BaseController {
+
+    @Resource
+    private FormService formService;
+
+    /**
+     * 表单列表
+     *
+     * @param form 携带的查询参数
+     * @return {@link TableDataInfo}
+     * @author liangli
+     * @date 2024/9/5 15:07
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:list')")
+    @GetMapping(value = "/list")
+    public TableDataInfo list(FlowForm form) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Page<Form> page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize());
+        page = formService.orderByCreateTime().desc().page(form, page);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(page.getList());
+        rspData.setTotal(page.getTotal());
+        return rspData;
+    }
+
+    /**
+     * 已发布表单列表
+     *
+     * @param form 携带的查询参数
+     * @return {@link TableDataInfo}
+     * @author vanlin
+     * @date 2024/11/11 15:07
+     **/
+    @GetMapping(value = "/publishedList")
+    public TableDataInfo publishedList(FlowForm form) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Page<Form> page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize());
+        form.setIsPublish(1); //已发布
+        page = formService.orderByCreateTime().desc().page(form, page);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(page.getList());
+        rspData.setTotal(page.getTotal());
+        return rspData;
+    }
+
+    /**
+     * 查询表单详情
+     *
+     * @param id 表单ID
+     * @return {@link R< Form>}
+     * @author liangli
+     * @date 2024/9/5 15:41
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:query')")
+    @GetMapping(value = "/{id}")
+    public R<Form> getForm(@PathVariable("id") Long id) {
+        return R.ok(formService.getById(id));
+    }
+
+    /**
+     * 提交表单
+     *
+     * @param form 表单ID对应的表单内容
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 15:07
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:add')")
+    @Log(title = "提交表单", businessType = BusinessType.INSERT)
+    @PostMapping("/saveFormContent")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> saveFormContent(@RequestBody FlowForm form) {
+        return R.ok(formService.updateById(FlowEngine.newForm().setFormContent(form.getFormContent()).setId(form.getId())));
+    }
+
+    /**
+     * 提交表单
+     *
+     * @param form 携带的查询参数
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 15:07
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:add')")
+    @Log(title = "提交表单", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> add(@RequestBody FlowForm form) {
+        return R.ok(formService.save(form));
+    }
+
+    /**
+     * 发布表单
+     *
+     * @param id 表单ID
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 15:26
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:publish')")
+    @Log(title = "发布表单", businessType = BusinessType.INSERT)
+    @GetMapping("/publish/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> publish(@PathVariable("id") Long id) {
+        return R.ok(formService.publish(id));
+    }
+
+    /**
+     * 取消表单
+     *
+     * @param id 表单ID
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 15:26
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:unPublish')")
+    @Log(title = "取消发布表单", businessType = BusinessType.INSERT)
+    @GetMapping("/unPublish/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> unPublish(@PathVariable("id") Long id) {
+        return R.ok(formService.unPublish(id));
+    }
+
+    /**
+     * 修改表单
+     *
+     * @param form 表单
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 15:26
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:edit')")
+    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
+    @PutMapping("/edit")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> edit(@RequestBody FlowForm form) {
+        return R.ok(formService.updateById(form));
+    }
+
+    /**
+     * 删除表单
+     *
+     * @param ids 表单ID
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 16:19
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:remove')")
+    @Log(title = "流程定义", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> remove(@PathVariable List<Long> ids) {
+        return R.ok(formService.removeByIds(ids));
+    }
+
+    /**
+     * 复制表单
+     *
+     * @param id 表单ID
+     * @return {@link R<Boolean>}
+     * @author liangli
+     * @date 2024/9/5 16:19
+     **/
+    @PreAuthorize("@ss.hasPermi('flow:form:add')")
+    @Log(title = "流程定义", businessType = BusinessType.INSERT)
+    @PostMapping("/copyForm/{id}")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Boolean> copyForm(@PathVariable("id") Long id) {
+        return R.ok(formService.copyForm(id));
+    }
+}

+ 68 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/mapper/WarmFlowMapper.java

@@ -0,0 +1,68 @@
+package com.ruoyi.flow.mapper;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import com.ruoyi.flow.vo.FlowTaskVo;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.warm.flow.core.entity.HisTask;
+import org.dromara.warm.flow.core.entity.Task;
+import org.dromara.warm.flow.orm.entity.FlowHisTask;
+import org.dromara.warm.flow.orm.entity.FlowTask;
+
+import java.util.List;
+
+/**
+ * warm-flow工作流Mapper接口
+ *
+ * @author ruoyi
+ * @date 2024-03-07
+ */
+public interface WarmFlowMapper {
+    /**
+     * 分页查询待办任务
+     *
+     * @param task 条件实体
+     */
+    List<FlowTaskVo> toDoPage(@Param("task") Task task);
+
+    /**
+     * 获取最新的已办任务
+     *
+     * @param hisTask
+     * @return
+     */
+    List<FlowHisTask> donePage(@Param("hisTask") HisTask hisTask);
+
+    /**
+     * 分页获取抄送任务
+     * @param flowTask
+     * @return
+     */
+    List<FlowHisTask> copyPage(@Param("task") FlowTask flowTask);
+
+    /**
+     * 根据ID反显姓名
+     *
+     * @param ids 需要反显姓名的用户ID
+     * @return {@link List<SysUser>}
+     * @author liangli
+     * @date 2024/8/21 17:11
+     **/
+    List<SysUser> idReverseDisplayName(@Param("ids") Long[] ids);
+
+    /**
+     * 查询不为输入的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 输入用户编号集合
+     * @return 用户列表
+     */
+    List<SysUser> selectNotUserIds(@Param("warmFlowInteractiveTypeVo") WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo);
+
+    /**
+     * 查询包含输入的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 输入用户编号集合
+     * @return 用户列表
+     */
+    List<SysUser> selectUserIds(@Param("warmFlowInteractiveTypeVo")WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo);
+}

+ 64 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/ExecuteService.java

@@ -0,0 +1,64 @@
+package com.ruoyi.flow.service;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import com.ruoyi.flow.vo.FlowTaskVo;
+import org.dromara.warm.flow.core.entity.HisTask;
+import org.dromara.warm.flow.core.entity.Task;
+import org.dromara.warm.flow.orm.entity.FlowHisTask;
+import org.dromara.warm.flow.orm.entity.FlowTask;
+
+import java.util.List;
+
+/**
+ * 流程执行service
+ *
+ * @author warm
+ * @since 2023/5/29 13:09
+ */
+public interface ExecuteService {
+
+    /**
+     * 分页查询待办任务
+     *
+     * @param task 条件实体
+     * @return
+     */
+    List<FlowTaskVo> toDoPage(Task task);
+
+    /**
+     * 获取已办任务
+     *
+     * @param hisTask
+     * @return
+     */
+    List<FlowHisTask> donePage(HisTask hisTask);
+
+    List<FlowHisTask> copyPage(FlowTask flowTask);
+
+    /**
+     * 根据ID反显姓名
+     *
+     * @param ids 需要反显姓名的用户ID
+     * @return {@link List<SysUser>}
+     * @author liangli
+     * @date 2024/8/21 17:11
+     **/
+    List<SysUser> idReverseDisplayName(Long[] ids);
+
+    /**
+     * 根据条件分页查询不等于用户列表的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 用户编号集合
+     * @return 用户信息集合信息
+     */
+    public List<SysUser> selectNotUserList(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo);
+
+    /**
+     * 根据条件分页查询不等于用户列表的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 用户编号集合
+     * @return 用户信息集合信息
+     */
+    public List<SysUser> selectUserList(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo);
+}

+ 14 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/HhDefService.java

@@ -0,0 +1,14 @@
+package com.ruoyi.flow.service;
+
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+
+/**
+ * 流程定义service
+ *
+ * @author warm
+ * @since 2023/5/29 13:09
+ */
+public interface HhDefService {
+
+    Boolean interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo);
+}

+ 84 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/impl/ExecuteServiceImpl.java

@@ -0,0 +1,84 @@
+package com.ruoyi.flow.service.impl;
+
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import com.ruoyi.flow.mapper.WarmFlowMapper;
+import com.ruoyi.flow.service.ExecuteService;
+import com.ruoyi.flow.vo.FlowTaskVo;
+import org.dromara.warm.flow.core.entity.HisTask;
+import org.dromara.warm.flow.core.entity.Task;
+import org.dromara.warm.flow.orm.entity.FlowHisTask;
+import org.dromara.warm.flow.orm.entity.FlowTask;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 流程执行SERVICEIMPL
+ *
+ * @author WARM
+ * @since 2023/5/29 13:09
+ */
+@Service
+public class ExecuteServiceImpl implements ExecuteService {
+
+    @Resource
+    private WarmFlowMapper flowMapper;
+
+    @Override
+    public List<FlowTaskVo> toDoPage(Task task) {
+        return flowMapper.toDoPage(task);
+    }
+
+    @Override
+    public List<FlowHisTask> donePage(HisTask hisTask) {
+        return flowMapper.donePage(hisTask);
+    }
+
+    @Override
+    public List<FlowHisTask> copyPage(FlowTask flowTask) {
+        return flowMapper.copyPage(flowTask);
+    }
+
+    /**
+     * 根据ID反显姓名
+     *
+     * @param ids 需要反显姓名的用户ID
+     * @return {@link List<SysUser>}
+     * @author liangli
+     * @date 2024/8/21 17:11
+     **/
+    @Override
+    public List<SysUser> idReverseDisplayName(Long[] ids) {
+        if (Objects.isNull(ids) || ids.length == 0) {
+            return null;
+        }
+        return flowMapper.idReverseDisplayName(ids);
+    }
+
+    /**
+     * 查询不包含输入的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 输入用户编号集合
+     * @return 用户列表
+     */
+    @DataScope(deptAlias = "d", userAlias = "u")
+    @Override
+    public List<SysUser> selectNotUserList(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
+        return flowMapper.selectNotUserIds(warmFlowInteractiveTypeVo);
+    }
+
+    /**
+     * 查询包含输入的所有用户
+     *
+     * @param warmFlowInteractiveTypeVo 输入用户编号集合
+     * @return 用户列表
+     */
+    @Override
+    public List<SysUser> selectUserList(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
+        return flowMapper.selectUserIds(warmFlowInteractiveTypeVo);
+    }
+}

+ 59 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/service/impl/HhDefServiceImpl.java

@@ -0,0 +1,59 @@
+package com.ruoyi.flow.service.impl;
+
+import com.ruoyi.common.utils.SpringUtils;
+import com.ruoyi.flow.adapter.WarmFlowAdapter;
+import com.ruoyi.flow.service.HhDefService;
+import com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo;
+import org.dromara.warm.flow.core.service.DefService;
+import org.dromara.warm.flow.core.service.NodeService;
+import org.dromara.warm.flow.core.service.SkipService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 流程定义serviceImpl
+ *
+ * @author warm
+ * @since 2023/5/29 13:09
+ */
+@Service
+public class HhDefServiceImpl implements HhDefService {
+
+    @Resource
+    private DefService defService;
+
+    @Resource
+    private NodeService nodeService;
+
+    @Resource
+    private SkipService skipService;
+
+    private static final List<WarmFlowAdapter> WARM_FLOW_ADAPTERS = new ArrayList<>();
+
+    /**
+     * 初始化方法
+     */
+    @PostConstruct
+    public void initMethod() {
+        Map<String, WarmFlowAdapter> beanNamesForType = SpringUtils.getBeanNamesForType(WarmFlowAdapter.class);
+        WARM_FLOW_ADAPTERS.addAll(beanNamesForType.values());
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Boolean interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
+        Integer operatorType = warmFlowInteractiveTypeVo.getOperatorType();
+        for (WarmFlowAdapter warmFlowAdapter : WARM_FLOW_ADAPTERS) {
+            if (warmFlowAdapter.isAdapter(operatorType)) {
+                return warmFlowAdapter.adapter(warmFlowInteractiveTypeVo);
+            }
+        }
+        return false;
+    }
+}

+ 81 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/vo/FlowTaskVo.java

@@ -0,0 +1,81 @@
+package com.ruoyi.flow.vo;
+
+import org.dromara.warm.flow.orm.entity.FlowTask;
+
+/**
+ * 待办任务vo
+ *
+ * @author warm
+ */
+public class FlowTaskVo extends FlowTask {
+
+    /**
+     * 计划审批人
+     */
+    private String approver;
+
+    /**
+     * 转办人
+     */
+    private String transferredBy;
+
+    /**
+     * 委派人
+     */
+    private String delegate;
+
+    /**
+     * 委派人
+     */
+    private String flowStatus;
+
+    /**
+     * 激活状态
+     */
+    private Integer activityStatus;
+
+    public String getApprover() {
+        return approver;
+    }
+
+    public FlowTaskVo setApprover(String approver) {
+        this.approver = approver;
+        return this;
+    }
+
+    public String getTransferredBy() {
+        return transferredBy;
+    }
+
+    public FlowTaskVo setTransferredBy(String transferredBy) {
+        this.transferredBy = transferredBy;
+        return this;
+    }
+
+    public String getDelegate() {
+        return delegate;
+    }
+
+    public FlowTaskVo setDelegate(String delegate) {
+        this.delegate = delegate;
+        return this;
+    }
+
+    public String getFlowStatus() {
+        return flowStatus;
+    }
+
+    public FlowTaskVo setFlowStatus(String flowStatus) {
+        this.flowStatus = flowStatus;
+        return this;
+    }
+
+    public Integer getActivityStatus() {
+        return activityStatus;
+    }
+
+    public FlowTaskVo setActivityStatus(Integer activityStatus) {
+        this.activityStatus = activityStatus;
+        return this;
+    }
+}

+ 75 - 0
common-application/ruoyi-flow/src/main/java/com/ruoyi/flow/vo/WarmFlowInteractiveTypeVo.java

@@ -0,0 +1,75 @@
+package com.ruoyi.flow.vo;
+
+
+import com.huashe.common.domain.BaseEntity;
+
+import java.util.List;
+
+public class WarmFlowInteractiveTypeVo extends BaseEntity {
+    /**
+     * 任务id
+     */
+    private Long taskId;
+
+    /**
+     * 增加办理人
+     */
+    private List<String> addHandlers;
+
+    /**
+     * 操作类型[2:转办,6:加签,3:委派,7:减签]
+     */
+    private Integer operatorType;
+
+    /**
+     * 部门ID
+     */
+    private Long deptId;
+
+    private List<String> userIds;
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public WarmFlowInteractiveTypeVo setTaskId(Long taskId) {
+        this.taskId = taskId;
+        return this;
+    }
+
+    public List<String> getAddHandlers() {
+        return addHandlers;
+    }
+
+    public WarmFlowInteractiveTypeVo setAddHandlers(List<String> addHandlers) {
+        this.addHandlers = addHandlers;
+        return this;
+    }
+
+    public Integer getOperatorType() {
+        return operatorType;
+    }
+
+    public WarmFlowInteractiveTypeVo setOperatorType(Integer operatorType) {
+        this.operatorType = operatorType;
+        return this;
+    }
+
+    public Long getDeptId() {
+        return deptId;
+    }
+
+    public WarmFlowInteractiveTypeVo setDeptId(Long deptId) {
+        this.deptId = deptId;
+        return this;
+    }
+
+    public List<String> getUserIds() {
+        return userIds;
+    }
+
+    public WarmFlowInteractiveTypeVo setUserIds(List<String> userIds) {
+        this.userIds = userIds;
+        return this;
+    }
+}

+ 253 - 0
common-application/ruoyi-flow/src/main/resources/mapper/flow/WarmFLowMapper.xml

@@ -0,0 +1,253 @@
+<?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="com.ruoyi.flow.mapper.WarmFlowMapper">
+
+    <resultMap type="com.ruoyi.flow.vo.FlowTaskVo" id="FlowTaskResult">
+        <result property="id" column="id"/>
+        <result property="nodeCode" column="node_code"/>
+        <result property="nodeName" column="node_name"/>
+        <result property="nodeType" column="node_type"/>
+        <result property="definitionId" column="definition_id"/>
+        <result property="instanceId" column="instance_id"/>
+        <result property="flowStatus" column="flow_status"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="tenantId" column="tenant_id"/>
+        <result property="businessId" column="business_id"/>
+        <result property="flowName" column="flow_name"/>
+        <result property="formCustom" column="form_custom"/>
+        <result property="formPath" column="form_path"/>
+        <result property="activityStatus" column="activity_status"/>
+        <result property="delFlag" column="del_flag"/>
+    </resultMap>
+
+    <resultMap type="org.dromara.warm.flow.orm.entity.FlowUser" id="FlowUserResult">
+        <result property="id" column="user_id"/>
+        <result property="type" column="type"/>
+        <result property="processedBy" column="processed_by"/>
+        <result property="associated" column="associated"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="tenantId" column="tenant_id"/>
+        <result property="delFlag" column="del_flag"/>
+    </resultMap>
+
+    <resultMap type="org.dromara.warm.flow.orm.entity.FlowHisTask" id="FlowHisTaskResult">
+        <result property="id" column="id"/>
+        <result property="nodeCode" column="node_code"/>
+        <result property="nodeName" column="node_name"/>
+        <result property="nodeType" column="node_type"/>
+        <result property="targetNodeCode" column="target_node_code"/>
+        <result property="targetNodeName" column="target_node_name"/>
+        <result property="approver" column="approver"/>
+        <result property="collaborator" column="collaborator"/>
+        <result property="definitionId" column="definition_id"/>
+        <result property="instanceId" column="instance_id"/>
+        <result property="taskId" column="task_id"/>
+        <result property="cooperateType" column="cooperate_type"/>
+        <result property="flowStatus" column="flow_status"/>
+        <result property="message" column="message"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="businessId" column="business_id"/>
+        <result property="tenantId" column="tenant_id"/>
+        <result property="formPath" column="form_path"/>
+        <result property="flowName" column="flow_name"/>
+        <result property="delFlag" column="del_flag"/>
+    </resultMap>
+
+    <select id="toDoPage" resultMap="FlowTaskResult">
+        SELECT
+        distinct t.id,
+            t.node_code,
+            t.node_name,
+            t.node_type,
+            t.definition_id,
+            t.instance_id,
+            t.create_time,
+            t.update_time,
+            t.tenant_id,
+            i.business_id,
+            i.flow_status,
+            i.activity_status,
+            d.flow_name,
+            t.form_custom,
+            t.form_path
+        FROM flow_task AS t
+        LEFT JOIN flow_user uu ON uu.associated = t.id
+        LEFT JOIN flow_definition d on t.definition_id = d.id
+        LEFT JOIN flow_instance i on t.instance_id = i.id
+        <where>
+            t.node_type = 1
+            <if test="task.permissionList != null and task.permissionList.size > 0">
+                AND  uu.processed_by in
+                <foreach item="permission" collection="task.permissionList" open="(" separator="," close=")">
+                    #{permission}
+                </foreach>
+            </if>
+            <if test="task.nodeCode != null and task.nodeCode != ''">and t.node_code = #{task.nodeCode}</if>
+            <if test="task.nodeName != null and task.nodeName != ''">and t.node_name like concat('%',
+                #{task.nodeName}, '%')
+            </if>
+            <if test="task.instanceId != null ">and t.instance_id = #{task.instanceId}</if>
+        </where>
+        order by t.create_time desc
+    </select>
+
+    <select id="donePage" resultMap="FlowHisTaskResult">
+        select
+            t.id,
+            t.node_code,
+            t.node_name,
+            t.cooperate_type,
+            t.approver,
+            t.collaborator,
+            t.node_type,
+            t.target_node_code,
+            t.target_node_name,
+            t.definition_id,
+            t.instance_id,
+            i.flow_status,
+            t.message,
+            t.ext,
+            t.create_time,
+            t.update_time,
+            t.tenant_id,
+            i.business_id,
+            t.form_path,
+            d.flow_name
+        from ( SELECT MAX(id) as id
+               FROM flow_his_task
+               <where>
+                   <if test="hisTask.permissionList != null and hisTask.permissionList.size > 0">
+                       AND approver in
+                       <foreach item="permission" collection="hisTask.permissionList" open="(" separator="," close=")">
+                           #{permission}
+                       </foreach>
+                   </if>
+                   <if test="hisTask.nodeCode != null  and hisTask.nodeCode != ''">and node_code =
+                       #{hisTask.nodeCode}
+                   </if>
+                   <if test="hisTask.nodeName != null  and hisTask.nodeName != ''">and node_name like concat('%',
+                       #{hisTask.nodeName}, '%')
+                   </if>
+                   <if test="hisTask.instanceId != null ">and instance_id = #{hisTask.instanceId}</if>
+               </where>
+              GROUP BY instance_id ) tmp
+        LEFT JOIN flow_his_task t ON t.id = tmp.id
+        LEFT JOIN flow_definition d on t.definition_id = d.id
+        LEFT JOIN flow_instance i on t.instance_id = i.id
+        order by t.create_time desc
+    </select>
+    <select id="copyPage" resultMap="FlowTaskResult">
+        SELECT
+            c.nick_name AS approver,
+            b.flow_status,
+            b.business_id,
+            a.create_time,
+            b.node_name,
+            b.id ,
+            d.flow_name
+        FROM
+            `flow_user` a
+                LEFT JOIN flow_instance b ON a.associated = b.id
+                LEFT JOIN sys_user c ON b.create_by = c.user_id
+                LEFT JOIN flow_definition d on b.definition_id=d.id
+        WHERE
+            a.type = 4
+        <if test="task.flowName != null and task.flowName != ''">and c.nick_name like concat('%',
+            #{task.flowName}, '%')
+          </if>
+        <if test="task.nodeName != null and task.nodeName != ''">and b.node_name like concat('%',
+            #{task.nodeName}, '%')
+        </if>
+        <if test="task.nodeType != null">and b.node_type = #{task.nodeType}</if>
+        ORDER BY create_time DESC
+    </select>
+
+    <select id="idReverseDisplayName" parameterType="long" resultType="com.ruoyi.common.core.domain.entity.SysUser">
+        select user_id as userId,user_name as userName,nick_name as nickName
+        from sys_user where user_id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
+    <resultMap type="SysUser" id="SysUserResult">
+        <id     property="userId"       column="user_id"      />
+        <result property="deptId"       column="dept_id"      />
+        <result property="userName"     column="user_name"    />
+        <result property="nickName"     column="nick_name"    />
+        <result property="email"        column="email"        />
+        <result property="phonenumber"  column="phonenumber"  />
+        <result property="sex"          column="sex"          />
+        <result property="avatar"       column="avatar"       />
+        <result property="password"     column="password"     />
+        <result property="status"       column="status"       />
+        <result property="delFlag"      column="del_flag"     />
+        <result property="loginIp"      column="login_ip"     />
+        <result property="loginDate"    column="login_date"   />
+        <result property="createBy"     column="create_by"    />
+        <result property="createTime"   column="create_time"  />
+        <result property="updateBy"     column="update_by"    />
+        <result property="updateTime"   column="update_time"  />
+        <result property="remark"       column="remark"       />
+        <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
+        <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
+    </resultMap>
+
+    <resultMap id="deptResult" type="SysDept">
+        <id     property="deptId"    column="dept_id"     />
+        <result property="parentId"  column="parent_id"   />
+        <result property="deptName"  column="dept_name"   />
+        <result property="ancestors" column="ancestors"   />
+        <result property="orderNum"  column="order_num"   />
+        <result property="leader"    column="leader"      />
+        <result property="status"    column="dept_status" />
+    </resultMap>
+
+    <resultMap id="RoleResult" type="SysRole">
+        <id     property="roleId"       column="role_id"        />
+        <result property="roleName"     column="role_name"      />
+        <result property="roleKey"      column="role_key"       />
+        <result property="roleSort"     column="role_sort"      />
+        <result property="dataScope"    column="data_scope"     />
+        <result property="status"       column="role_status"    />
+    </resultMap>
+
+    <select id="selectNotUserIds" parameterType="com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo" resultMap="SysUserResult">
+        select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
+        left join sys_dept d on u.dept_id = d.dept_id
+        where u.del_flag = '0'
+        <if test="warmFlowInteractiveTypeVo.userIds != null and warmFlowInteractiveTypeVo.userIds.size() > 0">
+            AND u.user_id not in
+            <foreach collection="warmFlowInteractiveTypeVo.userIds" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        <if test="warmFlowInteractiveTypeVo.deptId != null and warmFlowInteractiveTypeVo.deptId != 0">
+            AND (u.dept_id = #{warmFlowInteractiveTypeVo.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{warmFlowInteractiveTypeVo.deptId}, ancestors) ))
+        </if>
+        <!-- 数据范围过滤 -->
+        ${warmFlowInteractiveTypeVo.params.dataScope}
+    </select>
+
+    <select id="selectUserIds" parameterType="com.ruoyi.flow.vo.WarmFlowInteractiveTypeVo" resultMap="SysUserResult">
+        select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u
+        left join sys_dept d on u.dept_id = d.dept_id
+        where u.del_flag = '0'
+        <if test="warmFlowInteractiveTypeVo.userIds != null and warmFlowInteractiveTypeVo.userIds.size() > 0">
+            AND u.user_id in
+            <foreach collection="warmFlowInteractiveTypeVo.userIds" item="userId" open="(" separator="," close=")">
+                #{userId}
+            </foreach>
+        </if>
+        <if test="warmFlowInteractiveTypeVo.deptId != null and warmFlowInteractiveTypeVo.deptId != 0">
+            AND (u.dept_id = #{warmFlowInteractiveTypeVo.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{warmFlowInteractiveTypeVo.deptId}, ancestors) ))
+        </if>
+        <!-- 数据范围过滤 -->
+        ${warmFlowInteractiveTypeVo.params.dataScope}
+    </select>
+</mapper>

+ 1 - 0
common-application/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -125,6 +125,7 @@ public class SecurityConfig {
                             // 静态资源,可匿名访问
                             .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                             .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
+                            .antMatchers("/warm-flow-ui/**").permitAll()
                             // 除上面外的所有请求全部需要鉴权认证
                             .anyRequest().authenticated();
                 })