Переглянути джерело

!549 ♥️发布 5.2.0-BETA2 公测版本
Merge pull request !549 from 疯狂的狮子Li/dev

疯狂的狮子Li 5 місяців тому
батько
коміт
456620b638
70 змінених файлів з 860 додано та 673 видалено
  1. 5 6
      pom.xml
  2. 0 15
      ruoyi-admin/pom.xml
  3. 2 2
      ruoyi-admin/src/main/resources/application-dev.yml
  4. 2 1
      ruoyi-admin/src/main/resources/application-prod.yml
  5. 1 1
      ruoyi-common/ruoyi-common-bom/pom.xml
  6. 41 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java
  7. 35 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java
  8. 1 1
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java
  9. 76 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java
  10. 1 1
      ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java
  11. 12 8
      ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java
  12. 4 1
      ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java
  13. 1 1
      ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java
  14. 4 5
      ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java
  15. 9 0
      ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java
  16. 30 0
      ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java
  17. 1 1
      ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java
  18. 13 8
      ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java
  19. 5 2
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java
  20. 1 0
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java
  21. 28 19
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java
  22. 28 0
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java
  23. 14 13
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java
  24. 8 1
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java
  25. 26 9
      ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java
  26. 8 5
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java
  27. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java
  28. 7 9
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java
  29. 7 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java
  30. 3 0
      ruoyi-modules/ruoyi-workflow/README.md
  31. 4 1
      ruoyi-modules/ruoyi-workflow/pom.xml
  32. 0 27
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/annotation/FlowListenerAnnotation.java
  33. 2 2
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
  34. 26 26
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java
  35. 2 2
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java
  36. 7 7
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java
  37. 5 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/TestLeave.java
  38. 3 3
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java
  39. 5 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java
  40. 4 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java
  41. 3 3
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TestLeaveVo.java
  42. 48 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java
  43. 0 1
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java
  44. 0 73
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowEventStrategy.java
  45. 0 20
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowProcessEventHandler.java
  46. 0 19
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowTaskEventHandler.java
  47. 0 31
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestCustomProcessHandler.java
  48. 0 23
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestCustomTaskHandler.java
  49. 0 28
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestLeaveExecutionListener.java
  50. 0 21
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestLeaveTaskListener.java
  51. 12 20
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java
  52. 79 78
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
  53. 25 40
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
  54. 47 21
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java
  55. 119 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
  56. 16 1
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java
  57. 31 77
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
  58. BIN
      script/bpmn/模型.zip
  59. 8 7
      script/sql/flowable.sql
  60. 9 7
      script/sql/oracle/flowable.sql
  61. 0 1
      script/sql/oracle/oracle_ry_vue_5.X.sql
  62. 10 7
      script/sql/postgres/flowable.sql
  63. 0 1
      script/sql/postgres/postgres_ry_vue_5.X.sql
  64. 0 1
      script/sql/ry_vue_5.X.sql
  65. 16 7
      script/sql/sqlserver/flowable.sql
  66. 0 2
      script/sql/sqlserver/sqlserver_ry_vue_5.X.sql
  67. 1 1
      script/sql/update/oracle/update_5.1.2-5.2.0.sql
  68. 1 1
      script/sql/update/postgres/update_5.1.2-5.2.0.sql
  69. 2 2
      script/sql/update/sqlserver/update_5.1.2-5.2.0.sql
  70. 1 1
      script/sql/update/update_5.1.2-5.2.0.sql

+ 5 - 6
pom.xml

@@ -13,8 +13,8 @@
     <description>RuoYi-Vue-Plus多租户管理系统</description>
 
     <properties>
-        <revision>5.2.0-BETA</revision>
-        <spring-boot.version>3.2.5</spring-boot.version>
+        <revision>5.2.0-BETA2</revision>
+        <spring-boot.version>3.2.6</spring-boot.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>17</java.version>
@@ -34,7 +34,7 @@
         <lock4j.version>2.2.7</lock4j.version>
         <dynamic-ds.version>4.3.0</dynamic-ds.version>
         <alibaba-ttl.version>2.14.4</alibaba-ttl.version>
-        <snailjob.version>1.0.0-beta1</snailjob.version>
+        <snailjob.version>1.0.0-beta3</snailjob.version>
         <mapstruct-plus.version>1.3.6</mapstruct-plus.version>
         <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
         <lombok.version>1.18.32</lombok.version>
@@ -50,6 +50,8 @@
         <sms4j.version>3.2.1</sms4j.version>
         <!-- 限制框架中的fastjson版本 -->
         <fastjson.version>1.2.83</fastjson.version>
+        <!--工作流配置-->
+        <flowable.version>7.0.0</flowable.version>
 
         <!-- 插件版本 -->
         <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
@@ -57,9 +59,6 @@
         <maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
         <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
         <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
-
-        <!--工作流配置-->
-        <flowable.version>7.0.0</flowable.version>
     </properties>
 
     <profiles>

+ 0 - 15
ruoyi-admin/pom.xml

@@ -97,21 +97,6 @@
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>me.zhyd.oauth</groupId>
-            <artifactId>JustAuth</artifactId>
-        </dependency>
-
-        <!-- SnailJob client -->
-        <dependency>
-            <groupId>com.aizuda</groupId>
-            <artifactId>snail-job-client-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.aizuda</groupId>
-            <artifactId>snail-job-client-job-core</artifactId>
-        </dependency>
-
         <!-- skywalking 整合 logback -->
 <!--        <dependency>-->
 <!--            <groupId>org.apache.skywalking</groupId>-->

+ 2 - 2
ruoyi-admin/src/main/resources/application-dev.yml

@@ -12,7 +12,7 @@ spring.boot.admin.client:
 snail-job:
   enabled: true
   # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
-  group-name: "ruoyi_group"
+  group: "ruoyi_group"
   # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表
   token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
   server:
@@ -21,7 +21,6 @@ snail-job:
   # 详见 script/sql/snail_job.sql `sj_namespace` 表
   namespace: ${spring.profiles.active}
 
-
 --- # 数据源配置
 spring:
   datasource:
@@ -102,6 +101,7 @@ spring.data:
     # 是否开启ssl
     ssl.enabled: false
 
+# redisson 配置
 redisson:
   # redis key前缀
   keyPrefix:

+ 2 - 1
ruoyi-admin/src/main/resources/application-prod.yml

@@ -15,7 +15,7 @@ spring.boot.admin.client:
 snail-job:
   enabled: false
   # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
-  group-name: "ruoyi_group"
+  group: "ruoyi_group"
   # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表
   token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
   server:
@@ -104,6 +104,7 @@ spring.data:
     # 是否开启ssl
     ssl.enabled: false
 
+# redisson 配置
 redisson:
   # redis key前缀
   keyPrefix:

+ 1 - 1
ruoyi-common/ruoyi-common-bom/pom.xml

@@ -14,7 +14,7 @@
     </description>
 
     <properties>
-        <revision>5.2.0-BETA</revision>
+        <revision>5.2.0-BETA2</revision>
     </properties>
 
     <dependencyManagement>

+ 41 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java

@@ -0,0 +1,41 @@
+package org.dromara.common.core.domain.event;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 总体流程监听
+ *
+ * @author may
+ */
+
+@Data
+public class ProcessEvent implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 流程定义key
+     */
+    private String key;
+
+    /**
+     * 业务id
+     */
+    private String businessKey;
+
+    /**
+     * 状态
+     */
+    private String status;
+
+    /**
+     * 当为true时为申请人节点办理
+     */
+    private boolean submit;
+
+
+}

+ 35 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java

@@ -0,0 +1,35 @@
+package org.dromara.common.core.domain.event;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 流程办理监听
+ *
+ * @author may
+ */
+
+@Data
+public class ProcessTaskEvent implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 流程定义key与流程节点标识(拼接方式:流程定义key_流程节点)
+     */
+    private String keyNode;
+
+    /**
+     * 任务id
+     */
+    private String taskId;
+
+    /**
+     * 业务id
+     */
+    private String businessKey;
+
+}

+ 1 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/BusinessStatusEnum.java → ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java

@@ -1,4 +1,4 @@
-package org.dromara.workflow.common.enums;
+package org.dromara.common.core.enums;
 
 import cn.hutool.core.util.StrUtil;
 import lombok.AllArgsConstructor;

+ 76 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java

@@ -0,0 +1,76 @@
+package org.dromara.common.core.service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 通用 工作流服务
+ *
+ * @author may
+ */
+public interface WorkflowService {
+
+    /**
+     * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
+     *
+     * @param businessKeys 业务id
+     * @return 结果
+     */
+    boolean deleteRunAndHisInstance(List<String> businessKeys);
+
+    /**
+     * 获取当前流程状态
+     *
+     * @param taskId 任务id
+     */
+    String getBusinessStatusByTaskId(String taskId);
+
+    /**
+     * 获取当前流程状态
+     *
+     * @param businessKey 业务id
+     */
+    String getBusinessStatus(String businessKey);
+
+    /**
+     * 设置流程变量(全局变量)
+     *
+     * @param taskId       任务id
+     * @param variableName 变量名称
+     * @param value        变量值
+     */
+    void setVariable(String taskId, String variableName, Object value);
+
+    /**
+     * 设置流程变量(全局变量)
+     *
+     * @param taskId    任务id
+     * @param variables 流程变量
+     */
+    void setVariables(String taskId, Map<String, Object> variables);
+
+    /**
+     * 设置流程变量(本地变量,非全局变量)
+     *
+     * @param taskId       任务id
+     * @param variableName 变量名称
+     * @param value        变量值
+     */
+    void setVariableLocal(String taskId, String variableName, Object value);
+
+    /**
+     * 设置流程变量(本地变量,非全局变量)
+     *
+     * @param taskId    任务id
+     * @param variables 流程变量
+     */
+    void setVariablesLocal(String taskId, Map<String, Object> variables);
+
+    /**
+     * 按照业务id查询流程实例id
+     *
+     * @param businessKey 业务id
+     * @return 结果
+     */
+    String getInstanceIdByBusinessKey(String businessKey);
+}

+ 1 - 1
ruoyi-common/ruoyi-common-job/src/main/java/org/dromara/common/job/config/SnailJobConfig.java

@@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 @AutoConfiguration
 @ConditionalOnProperty(prefix = "snail-job", name = "enabled", havingValue = "true")
 @EnableScheduling
-@EnableSnailJob(group = "${snail-job.group-name}")
+@EnableSnailJob
 public class SnailJobConfig {
 
     @EventListener(SnailClientStartingEvent.class)

+ 12 - 8
ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java

@@ -162,13 +162,14 @@ public class OssClient {
     /**
      * 上传文件到 Amazon S3,并返回上传结果
      *
-     * @param filePath  本地文件路径
-     * @param key       在 Amazon S3 中的对象键
-     * @param md5Digest 本地文件的 MD5 哈希值(可选)
+     * @param filePath    本地文件路径
+     * @param key         在 Amazon S3 中的对象键
+     * @param md5Digest   本地文件的 MD5 哈希值(可选)
+     * @param contentType 文件内容类型
      * @return UploadResult 包含上传后的文件信息
      * @throws OssException 如果上传失败,抛出自定义异常
      */
-    public UploadResult upload(Path filePath, String key, String md5Digest) {
+    public UploadResult upload(Path filePath, String key, String md5Digest, String contentType) {
         try {
             // 构建上传请求对象
             FileUpload fileUpload = transferManager.uploadFile(
@@ -176,6 +177,7 @@ public class OssClient {
                         y -> y.bucket(properties.getBucketName())
                             .key(key)
                             .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null)
+                            .contentType(contentType)
                             .build())
                     .addTransferListener(LoggingTransferListener.create())
                     .source(filePath).build());
@@ -201,10 +203,11 @@ public class OssClient {
      * @param inputStream 要上传的输入流
      * @param key         在 Amazon S3 中的对象键
      * @param length      输入流的长度
+     * @param contentType 文件内容类型
      * @return UploadResult 包含上传后的文件信息
      * @throws OssException 如果上传失败,抛出自定义异常
      */
-    public UploadResult upload(InputStream inputStream, String key, Long length) {
+    public UploadResult upload(InputStream inputStream, String key, Long length, String contentType) {
         // 如果输入流不是 ByteArrayInputStream,则将其读取为字节数组再创建 ByteArrayInputStream
         if (!(inputStream instanceof ByteArrayInputStream)) {
             inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
@@ -219,6 +222,7 @@ public class OssClient {
                     .putObjectRequest(
                         y -> y.bucket(properties.getBucketName())
                             .key(key)
+                            .contentType(contentType)
                             .build())
                     .build());
 
@@ -335,7 +339,7 @@ public class OssClient {
      * @throws OssException 如果上传失败,抛出自定义异常
      */
     public UploadResult uploadSuffix(byte[] data, String suffix) {
-        return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length));
+        return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), FileUtils.getMimeType(suffix));
     }
 
     /**
@@ -348,7 +352,7 @@ public class OssClient {
      * @throws OssException 如果上传失败,抛出自定义异常
      */
     public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length) {
-        return upload(inputStream, getPath(properties.getPrefix(), suffix), length);
+        return upload(inputStream, getPath(properties.getPrefix(), suffix), length, FileUtils.getMimeType(suffix));
     }
 
     /**
@@ -360,7 +364,7 @@ public class OssClient {
      * @throws OssException 如果上传失败,抛出自定义异常
      */
     public UploadResult uploadSuffix(File file, String suffix) {
-        return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null);
+        return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null, FileUtils.getMimeType(suffix));
     }
 
     /**

+ 4 - 1
ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java

@@ -48,7 +48,10 @@ public class OssFactory {
         }
         OssProperties properties = JsonUtils.parseObject(json, OssProperties.class);
         // 使用租户标识避免多个租户相同key实例覆盖
-        String key = properties.getTenantId() + ":" + configKey;
+        String key = configKey;
+        if (StringUtils.isNotBlank(properties.getTenantId())) {
+            key = properties.getTenantId() + ":" + configKey;
+        }
         OssClient client = CLIENT_CACHE.get(key);
         // 客户端不存在或配置不相同则重新构建
         if (client == null || !client.checkPropertiesSame(properties)) {

+ 1 - 1
ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java

@@ -23,7 +23,7 @@ public class RedisExceptionHandler {
     @ExceptionHandler(LockFailureException.class)
     public R<Void> handleLockFailureException(LockFailureException e, HttpServletRequest request) {
         String requestURI = request.getRequestURI();
-        log.error("获取锁失败了'{}',发生Lock4j异常." + requestURI, e.getMessage());
+        log.error("获取锁失败了'{}',发生Lock4j异常.", requestURI, e);
         return R.fail(HttpStatus.HTTP_UNAVAILABLE, "业务处理中,请稍后再试...");
     }
 

+ 4 - 5
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java

@@ -2,7 +2,6 @@ package org.dromara.common.satoken.core.dao;
 
 import cn.dev33.satoken.dao.SaTokenDao;
 import cn.dev33.satoken.util.SaFoxUtil;
-import cn.hutool.core.lang.Console;
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import org.dromara.common.redis.utils.RedisUtils;
@@ -54,7 +53,7 @@ public class PlusSaTokenDao implements SaTokenDao {
         } else {
             RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout));
         }
-        CAFFEINE.put(key, value);
+        CAFFEINE.invalidate(key);
     }
 
     /**
@@ -64,7 +63,7 @@ public class PlusSaTokenDao implements SaTokenDao {
     public void update(String key, String value) {
         if (RedisUtils.hasKey(key)) {
             RedisUtils.setCacheObject(key, value, true);
-            CAFFEINE.put(key, value);
+            CAFFEINE.invalidate(key);
         }
     }
 
@@ -117,7 +116,7 @@ public class PlusSaTokenDao implements SaTokenDao {
         } else {
             RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout));
         }
-        CAFFEINE.put(key, object);
+        CAFFEINE.invalidate(key);
     }
 
     /**
@@ -127,7 +126,7 @@ public class PlusSaTokenDao implements SaTokenDao {
     public void updateObject(String key, Object object) {
         if (RedisUtils.hasKey(key)) {
             RedisUtils.setCacheObject(key, object, true);
-            CAFFEINE.put(key, object);
+            CAFFEINE.invalidate(key);
         }
     }
 

+ 9 - 0
ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java

@@ -1,6 +1,7 @@
 package org.dromara.common.sms.config;
 
 import org.dromara.common.sms.core.dao.PlusSmsDao;
+import org.dromara.common.sms.handler.SmsExceptionHandler;
 import org.dromara.sms4j.api.dao.SmsDao;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
@@ -21,4 +22,12 @@ public class SmsAutoConfiguration {
         return new PlusSmsDao();
     }
 
+    /**
+     * 异常处理器
+     */
+    @Bean
+    public SmsExceptionHandler smsExceptionHandler() {
+        return new SmsExceptionHandler();
+    }
+
 }

+ 30 - 0
ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java

@@ -0,0 +1,30 @@
+package org.dromara.common.sms.handler;
+
+import cn.hutool.http.HttpStatus;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.sms4j.comm.exception.SmsBlendException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * SMS异常处理器
+ *
+ * @author AprilWind
+ */
+@Slf4j
+@RestControllerAdvice
+public class SmsExceptionHandler {
+
+    /**
+     * sms异常
+     */
+    @ExceptionHandler(SmsBlendException.class)
+    public R<Void> handleSmsBlendException(SmsBlendException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("请求地址'{}',发生sms短信异常.", requestURI, e);
+        return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "短信发送失败,请稍后再试...");
+    }
+
+}

+ 1 - 1
ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java

@@ -35,7 +35,7 @@ public class TenantConfig {
 
     @ConditionalOnBean(MybatisPlusConfig.class)
     @AutoConfiguration(after = {MybatisPlusConfig.class})
-    static class MybatisPlusConfigation {
+    static class MybatisPlusConfiguration {
 
         /**
          * 多租户插件

+ 13 - 8
ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java

@@ -1,6 +1,5 @@
 package org.dromara.common.tenant.helper;
 
-import cn.dev33.satoken.context.SaHolder;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.convert.Convert;
 import com.alibaba.ttl.TransmittableThreadLocal;
@@ -79,22 +78,28 @@ public class TenantHelper {
         }
     }
 
+    public static void setDynamic(String tenantId) {
+        setDynamic(tenantId, false);
+    }
+
     /**
      * 设置动态租户(一直有效 需要手动清理)
      * <p>
      * 如果为未登录状态下 那么只在当前线程内生效
+     *
+     * @param tenantId 租户id
+     * @param global   是否全局生效
      */
-    public static void setDynamic(String tenantId) {
+    public static void setDynamic(String tenantId, boolean global) {
         if (!isEnable()) {
             return;
         }
-        if (!isLogin()) {
+        if (!isLogin() || !global) {
             TEMP_DYNAMIC_TENANT.set(tenantId);
             return;
         }
         String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
         RedisUtils.setCacheObject(cacheKey, tenantId);
-        SaHolder.getStorage().set(cacheKey, tenantId);
     }
 
     /**
@@ -109,13 +114,13 @@ public class TenantHelper {
         if (!isLogin()) {
             return TEMP_DYNAMIC_TENANT.get();
         }
-        String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
-        String tenantId = (String) SaHolder.getStorage().get(cacheKey);
+        // 如果线程内有值 优先返回
+        String tenantId = TEMP_DYNAMIC_TENANT.get();
         if (StringUtils.isNotBlank(tenantId)) {
             return tenantId;
         }
+        String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
         tenantId = RedisUtils.getCacheObject(cacheKey);
-        SaHolder.getStorage().set(cacheKey, tenantId);
         return tenantId;
     }
 
@@ -130,9 +135,9 @@ public class TenantHelper {
             TEMP_DYNAMIC_TENANT.remove();
             return;
         }
+        TEMP_DYNAMIC_TENANT.remove();
         String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
         RedisUtils.deleteObject(cacheKey);
-        SaHolder.getStorage().delete(cacheKey);
     }
 
     /**

+ 5 - 2
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java

@@ -27,17 +27,20 @@ public class WebSocketConfig {
 
     @Bean
     public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor,
-                                                   WebSocketHandler webSocketHandler,
-                                                   WebSocketProperties webSocketProperties) {
+                                                   WebSocketHandler webSocketHandler, WebSocketProperties webSocketProperties) {
+        // 如果WebSocket的路径为空,则设置默认路径为 "/websocket"
         if (StrUtil.isBlank(webSocketProperties.getPath())) {
             webSocketProperties.setPath("/websocket");
         }
 
+        // 如果允许跨域访问的地址为空,则设置为 "*",表示允许所有来源的跨域请求
         if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) {
             webSocketProperties.setAllowedOrigins("*");
         }
 
+        // 返回一个WebSocketConfigurer对象,用于配置WebSocket
         return registry -> registry
+            // 添加WebSocket处理程序和拦截器到指定路径,设置允许的跨域来源
             .addHandler(webSocketHandler, webSocketProperties.getPath())
             .addInterceptors(handshakeInterceptor)
             .setAllowedOrigins(webSocketProperties.getAllowedOrigins());

+ 1 - 0
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java

@@ -6,6 +6,7 @@ package org.dromara.common.websocket.constant;
  * @author zendwang
  */
 public interface WebSocketConstants {
+
     /**
      * websocketSession中的参数的key
      */

+ 28 - 19
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java

@@ -31,33 +31,42 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
     }
 
     /**
-     * 处理发送来的文本消息
+     * 处理接收到的文本消息
      *
-     * @param session
-     * @param message
-     * @throws Exception
+     * @param session WebSocket会话
+     * @param message 接收到的文本消息
+     * @throws Exception 处理消息过程中可能抛出的异常
      */
     @Override
     protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
+        // 从WebSocket会话中获取登录用户信息
         LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
-        List<Long> userIds = List.of(loginUser.getUserId());
+
+        // 创建WebSocket消息DTO对象
         WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto();
-        webSocketMessageDto.setSessionKeys(userIds);
+        webSocketMessageDto.setSessionKeys(List.of(loginUser.getUserId()));
         webSocketMessageDto.setMessage(message.getPayload());
         WebSocketUtils.publishMessage(webSocketMessageDto);
     }
 
+    /**
+     * 处理接收到的二进制消息
+     *
+     * @param session WebSocket会话
+     * @param message 接收到的二进制消息
+     * @throws Exception 处理消息过程中可能抛出的异常
+     */
     @Override
     protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
         super.handleBinaryMessage(session, message);
     }
 
     /**
-     * 心跳监测的回复
+     * 处理接收到的Pong消息(心跳监测)
      *
-     * @param session
-     * @param message
-     * @throws Exception
+     * @param session WebSocket会话
+     * @param message 接收到的Pong消息
+     * @throws Exception 处理消息过程中可能抛出的异常
      */
     @Override
     protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
@@ -65,11 +74,11 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
     }
 
     /**
-     * 连接出错时
+     * 处理WebSocket传输错误
      *
-     * @param session
-     * @param exception
-     * @throws Exception
+     * @param session   WebSocket会话
+     * @param exception 发生的异常
+     * @throws Exception 处理过程中可能抛出的异常
      */
     @Override
     public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
@@ -77,10 +86,10 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
     }
 
     /**
-     * 连接关闭后
+     * 在WebSocket连接关闭后执行清理操作
      *
-     * @param session
-     * @param status
+     * @param session WebSocket会话
+     * @param status  关闭状态信息
      */
     @Override
     public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
@@ -90,9 +99,9 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
     }
 
     /**
-     * 是否支持分消息
+     * 指示处理程序是否支持接收部分消息
      *
-     * @return
+     * @return 如果支持接收部分消息,则返回true;否则返回false
      */
     @Override
     public boolean supportsPartialMessages() {

+ 28 - 0
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java

@@ -18,24 +18,52 @@ public class WebSocketSessionHolder {
 
     private static final Map<Long, WebSocketSession> USER_SESSION_MAP = new ConcurrentHashMap<>();
 
+    /**
+     * 将WebSocket会话添加到用户会话Map中
+     *
+     * @param sessionKey 会话键,用于检索会话
+     * @param session    要添加的WebSocket会话
+     */
     public static void addSession(Long sessionKey, WebSocketSession session) {
         USER_SESSION_MAP.put(sessionKey, session);
     }
 
+    /**
+     * 从用户会话Map中移除指定会话键对应的WebSocket会话
+     *
+     * @param sessionKey 要移除的会话键
+     */
     public static void removeSession(Long sessionKey) {
         if (USER_SESSION_MAP.containsKey(sessionKey)) {
             USER_SESSION_MAP.remove(sessionKey);
         }
     }
 
+    /**
+     * 根据会话键从用户会话Map中获取WebSocket会话
+     *
+     * @param sessionKey 要获取的会话键
+     * @return 与给定会话键对应的WebSocket会话,如果不存在则返回null
+     */
     public static WebSocketSession getSessions(Long sessionKey) {
         return USER_SESSION_MAP.get(sessionKey);
     }
 
+    /**
+     * 获取存储在用户会话Map中所有WebSocket会话的会话键集合
+     *
+     * @return 所有WebSocket会话的会话键集合
+     */
     public static Set<Long> getSessionsAll() {
         return USER_SESSION_MAP.keySet();
     }
 
+    /**
+     * 检查给定的会话键是否存在于用户会话Map中
+     *
+     * @param sessionKey 要检查的会话键
+     * @return 如果存在对应的会话键,则返回true;否则返回false
+     */
     public static Boolean existSession(Long sessionKey) {
         return USER_SESSION_MAP.containsKey(sessionKey);
     }

+ 14 - 13
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java

@@ -1,8 +1,8 @@
 package org.dromara.common.websocket.interceptor;
 
+import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.domain.model.LoginUser;
 import org.dromara.common.satoken.utils.LoginHelper;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.server.ServerHttpRequest;
 import org.springframework.http.server.ServerHttpResponse;
 import org.springframework.web.socket.WebSocketHandler;
@@ -21,13 +21,13 @@ import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USE
 public class PlusWebSocketInterceptor implements HandshakeInterceptor {
 
     /**
-     * 握手前
+     * WebSocket握手执行的前置处理方法
      *
-     * @param request    request
-     * @param response   response
-     * @param wsHandler  wsHandler
-     * @param attributes attributes
-     * @return 是否握手成功
+     * @param request    WebSocket握手请求
+     * @param response   WebSocket握手响应
+     * @param wsHandler  WebSocket处理程序
+     * @param attributes 与WebSocket会话关联的属性
+     * @return 如果允许握手继续进行,则返回true;否则返回false
      */
     @Override
     public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
@@ -37,15 +37,16 @@ public class PlusWebSocketInterceptor implements HandshakeInterceptor {
     }
 
     /**
-     * 握手后
+     * WebSocket握手成功执行的后置处理方法
      *
-     * @param request   request
-     * @param response  response
-     * @param wsHandler wsHandler
-     * @param exception 异常
+     * @param request   WebSocket握手请求
+     * @param response  WebSocket握手响应
+     * @param wsHandler WebSocket处理程序
+     * @param exception 握手过程中可能出现的异常
      */
     @Override
     public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
-
+        // 在这个方法中可以执行一些握手成功后的后续处理逻辑,比如记录日志或者其他操作
     }
+
 }

+ 8 - 1
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java

@@ -1,9 +1,9 @@
 package org.dromara.common.websocket.listener;
 
 import cn.hutool.core.collection.CollUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.websocket.holder.WebSocketSessionHolder;
 import org.dromara.common.websocket.utils.WebSocketUtils;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.core.Ordered;
@@ -16,8 +16,15 @@ import org.springframework.core.Ordered;
 @Slf4j
 public class WebSocketTopicListener implements ApplicationRunner, Ordered {
 
+    /**
+     * 在Spring Boot应用程序启动时初始化WebSocket主题订阅监听器
+     *
+     * @param args 应用程序参数
+     * @throws Exception 初始化过程中可能抛出的异常
+     */
     @Override
     public void run(ApplicationArguments args) throws Exception {
+        // 订阅WebSocket消息
         WebSocketUtils.subscribeMessage((message) -> {
             log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage());
             // 如果key不为空就按照key发消息 如果为空就群发

+ 26 - 9
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java

@@ -29,10 +29,10 @@ import static org.dromara.common.websocket.constant.WebSocketConstants.WEB_SOCKE
 public class WebSocketUtils {
 
     /**
-     * 发送消息
+     * 向指定的WebSocket会话发送消息
      *
-     * @param sessionKey session主键 一般为用户id
-     * @param message    消息文本
+     * @param sessionKey 要发送消息的用户id
+     * @param message    要发送的消息内容
      */
     public static void sendMessage(Long sessionKey, String message) {
         WebSocketSession session = WebSocketSessionHolder.getSessions(sessionKey);
@@ -40,18 +40,18 @@ public class WebSocketUtils {
     }
 
     /**
-     * 订阅消息
+     * 订阅WebSocket消息主题,并提供一个消费者函数来处理接收到的消息
      *
-     * @param consumer 自定义处理
+     * @param consumer 处理WebSocket消息的消费者函数
      */
     public static void subscribeMessage(Consumer<WebSocketMessageDto> consumer) {
         RedisUtils.subscribe(WEB_SOCKET_TOPIC, WebSocketMessageDto.class, consumer);
     }
 
     /**
-     * 发布订阅消息
+     * 发布WebSocket订阅消息
      *
-     * @param webSocketMessage 消息对象
+     * @param webSocketMessage 要发布的WebSocket消息对象
      */
     public static void publishMessage(WebSocketMessageDto webSocketMessage) {
         List<Long> unsentSessionKeys = new ArrayList<>();
@@ -76,9 +76,9 @@ public class WebSocketUtils {
     }
 
     /**
-     * 发布订阅的消息(群发)
+     * 向所有的WebSocket会话发布订阅的消息(群发)
      *
-     * @param message 消息内容
+     * @param message 要发布的消息内容
      */
     public static void publishAll(String message) {
         WebSocketMessageDto broadcastMessage = new WebSocketMessageDto();
@@ -88,14 +88,31 @@ public class WebSocketUtils {
         });
     }
 
+    /**
+     * 向指定的WebSocket会话发送Pong消息
+     *
+     * @param session 要发送Pong消息的WebSocket会话
+     */
     public static void sendPongMessage(WebSocketSession session) {
         sendMessage(session, new PongMessage());
     }
 
+    /**
+     * 向指定的WebSocket会话发送文本消息
+     *
+     * @param session WebSocket会话
+     * @param message 要发送的文本消息内容
+     */
     public static void sendMessage(WebSocketSession session, String message) {
         sendMessage(session, new TextMessage(message));
     }
 
+    /**
+     * 向指定的WebSocket会话发送WebSocket消息对象
+     *
+     * @param session WebSocket会话
+     * @param message 要发送的WebSocket消息对象
+     */
     private static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) {
         if (session == null || !session.isOpen()) {
             log.warn("[send] session会话已经关闭");

+ 8 - 5
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java

@@ -3,10 +3,12 @@ package org.dromara.system.controller.system;
 import cn.dev33.satoken.secure.BCrypt;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.io.FileUtil;
+import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.core.utils.file.MimeTypeUtils;
 import org.dromara.common.encrypt.annotation.ApiEncrypt;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
 import org.dromara.common.log.annotation.Log;
 import org.dromara.common.log.enums.BusinessType;
 import org.dromara.common.satoken.utils.LoginHelper;
@@ -19,9 +21,7 @@ import org.dromara.system.domain.vo.ProfileVo;
 import org.dromara.system.domain.vo.SysOssVo;
 import org.dromara.system.domain.vo.SysUserVo;
 import org.dromara.system.service.ISysOssService;
-import org.dromara.system.service.ISysRoleService;
 import org.dromara.system.service.ISysUserService;
-import lombok.RequiredArgsConstructor;
 import org.springframework.http.MediaType;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -57,12 +57,14 @@ public class SysProfileController extends BaseController {
     }
 
     /**
-     * 修改用户
+     * 修改用户信息
      */
+    @RepeatSubmit
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PutMapping
-    public R<Void> updateProfile(@RequestBody SysUserProfileBo profile) {
+    public R<Void> updateProfile(@Validated @RequestBody SysUserProfileBo profile) {
         SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class);
+        user.setUserId(LoginHelper.getUserId());
         String username = LoginHelper.getUsername();
         if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
             return R.fail("修改用户'" + username + "'失败,手机号码已存在");
@@ -70,7 +72,6 @@ public class SysProfileController extends BaseController {
         if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
             return R.fail("修改用户'" + username + "'失败,邮箱账号已存在");
         }
-        user.setUserId(LoginHelper.getUserId());
         if (userService.updateUserProfile(user) > 0) {
             return R.ok();
         }
@@ -82,6 +83,7 @@ public class SysProfileController extends BaseController {
      *
      * @param bo 新旧密码
      */
+    @RepeatSubmit
     @ApiEncrypt
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PutMapping("/updatePwd")
@@ -106,6 +108,7 @@ public class SysProfileController extends BaseController {
      *
      * @param avatarfile 用户头像
      */
+    @RepeatSubmit
     @Log(title = "用户头像", businessType = BusinessType.UPDATE)
     @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     public R<AvatarVo> avatar(@RequestPart("avatarfile") MultipartFile avatarfile) {

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java

@@ -144,7 +144,7 @@ public class SysTenantController extends BaseController {
     @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
     @GetMapping("/dynamic/{tenantId}")
     public R<Void> dynamicTenant(@NotBlank(message = "租户ID不能为空") @PathVariable String tenantId) {
-        TenantHelper.setDynamic(tenantId);
+        TenantHelper.setDynamic(tenantId, true);
         return R.ok();
     }
 

+ 7 - 9
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java

@@ -1,14 +1,16 @@
 package org.dromara.system.domain.bo;
 
-import org.dromara.common.core.xss.Xss;
-import org.dromara.common.mybatis.core.domain.BaseEntity;
-import org.dromara.common.sensitive.annotation.Sensitive;
-import org.dromara.common.sensitive.core.SensitiveStrategy;
 import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Pattern;
 import jakarta.validation.constraints.Size;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
+import org.dromara.common.core.constant.RegexConstants;
+import org.dromara.common.core.xss.Xss;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.sensitive.annotation.Sensitive;
+import org.dromara.common.sensitive.core.SensitiveStrategy;
 
 /**
  * 个人信息业务处理
@@ -21,11 +23,6 @@ import lombok.NoArgsConstructor;
 @EqualsAndHashCode(callSuper = true)
 public class SysUserProfileBo extends BaseEntity {
 
-    /**
-     * 用户ID
-     */
-    private Long userId;
-
     /**
      * 用户昵称
      */
@@ -44,6 +41,7 @@ public class SysUserProfileBo extends BaseEntity {
     /**
      * 手机号码
      */
+    @Pattern(regexp = RegexConstants.MOBILE, message = "手机号格式不正确")
     @Sensitive(strategy = SensitiveStrategy.PHONE)
     private String phonenumber;
 

+ 7 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

@@ -37,6 +37,7 @@ import org.dromara.system.domain.vo.SysUserExportVo;
 import org.dromara.system.domain.vo.SysUserVo;
 import org.dromara.system.mapper.*;
 import org.dromara.system.service.ISysUserService;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -338,6 +339,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
      * @return 结果
      */
     @Override
+    @CacheEvict(cacheNames = CacheNames.SYS_NICKNAME, key = "#user.userId")
     @Transactional(rollbackFor = Exception.class)
     public int updateUser(SysUserBo user) {
         // 新增用户与角色管理
@@ -386,6 +388,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
      * @param user 用户信息
      * @return 结果
      */
+    @CacheEvict(cacheNames = CacheNames.SYS_NICKNAME, key = "#user.userId")
     @Override
     public int updateUserProfile(SysUserBo user) {
         return baseMapper.update(null,
@@ -636,7 +639,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
         if (CollUtil.isEmpty(userIds)) {
             return List.of();
         }
-        List<SysUserVo> list = this.selectUserByIds(userIds, null);
+        List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>()
+            .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName)
+            .eq(SysUser::getStatus, UserConstants.USER_NORMAL)
+            .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds));
         return BeanUtil.copyToList(list, UserDTO.class);
     }
 

+ 3 - 0
ruoyi-modules/ruoyi-workflow/README.md

@@ -0,0 +1,3 @@
+# 工作流说明
+
+工作流目前在未成熟阶段 后续仍会经历重构 甚至重写(生产使用前请慎重考虑后续是否要更新维护)

+ 4 - 1
ruoyi-modules/ruoyi-workflow/pom.xml

@@ -109,7 +109,10 @@
             <groupId>org.dromara</groupId>
             <artifactId>ruoyi-common-tenant</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-common-security</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 0 - 27
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/annotation/FlowListenerAnnotation.java

@@ -1,27 +0,0 @@
-package org.dromara.workflow.annotation;
-
-
-import java.lang.annotation.*;
-
-/**
- * 流程任务监听注解
- *
- * @author may
- * @date 2023-12-27
- */
-@Target({ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Inherited
-public @interface FlowListenerAnnotation {
-
-    /**
-     * 流程定义key
-     */
-    String processDefinitionKey();
-
-    /**
-     * 节点id
-     */
-    String taskDefId() default "";
-}

+ 2 - 2
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java

@@ -71,9 +71,9 @@ public interface FlowConstant {
     String ZIP = "ZIP";
 
     /**
-     * 流程实例对象
+     * 业务与流程实例关联对象
      */
-    String PROCESS_INSTANCE_VO = "processInstanceVo";
+    String BUSINESS_INSTANCE_DTO = "businessInstanceDTO";
 
     /**
      * 流程定义配置

+ 26 - 26
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java

@@ -58,33 +58,33 @@ public class ActProcessInstanceController extends BaseController {
     }
 
     /**
-     * 通过流程实例id获取历史流程图
+     * 通过业务id获取历史流程图
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
-    @GetMapping("/getHistoryImage/{processInstanceId}")
-    public R<String> getHistoryImage(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
-        return R.ok("操作成功", actProcessInstanceService.getHistoryImage(processInstanceId));
+    @GetMapping("/getHistoryImage/{businessKey}")
+    public R<String> getHistoryImage(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
+        return R.ok("操作成功", actProcessInstanceService.getHistoryImage(businessKey));
     }
 
     /**
-     * 通过流程实例id获取历史流程图运行中,历史等节点
+     * 通过业务id获取历史流程图运行中,历史等节点
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
-    @GetMapping("/getHistoryList/{processInstanceId}")
-    public R<Map<String, Object>> getHistoryList(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
-        return R.ok("操作成功", actProcessInstanceService.getHistoryList(processInstanceId));
+    @GetMapping("/getHistoryList/{businessKey}")
+    public R<Map<String, Object>> getHistoryList(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
+        return R.ok("操作成功", actProcessInstanceService.getHistoryList(businessKey));
     }
 
     /**
      * 获取审批记录
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
-    @GetMapping("/getHistoryRecord/{processInstanceId}")
-    public R<List<ActHistoryInfoVo>> getHistoryRecord(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
-        return R.ok(actProcessInstanceService.getHistoryRecord(processInstanceId));
+    @GetMapping("/getHistoryRecord/{businessKey}")
+    public R<List<ActHistoryInfoVo>> getHistoryRecord(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
+        return R.ok(actProcessInstanceService.getHistoryRecord(businessKey));
     }
 
     /**
@@ -102,37 +102,37 @@ public class ActProcessInstanceController extends BaseController {
     /**
      * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
+     * @param businessKeys 业务id
      */
     @Log(title = "流程实例管理", businessType = BusinessType.DELETE)
     @RepeatSubmit()
-    @DeleteMapping("/deleteRunAndHisInstance/{processInstanceIds}")
-    public R<Void> deleteRunAndHisInstance(@NotNull(message = "流程实例id不能为空") @PathVariable String[] processInstanceIds) {
-        return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(processInstanceIds)));
+    @DeleteMapping("/deleteRunAndHisInstance/{businessKeys}")
+    public R<Void> deleteRunAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
+        return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(businessKeys)));
     }
 
     /**
      * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
+     * @param businessKeys 业务id
      */
     @Log(title = "流程实例管理", businessType = BusinessType.DELETE)
     @RepeatSubmit()
-    @DeleteMapping("/deleteFinishAndHisInstance/{processInstanceIds}")
-    public R<Void> deleteFinishAndHisInstance(@NotNull(message = "流程实例id不能为空") @PathVariable String[] processInstanceIds) {
-        return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(processInstanceIds)));
+    @DeleteMapping("/deleteFinishAndHisInstance/{businessKeys}")
+    public R<Void> deleteFinishAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
+        return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(businessKeys)));
     }
 
     /**
      * 撤销流程申请
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
     @Log(title = "流程实例管理", businessType = BusinessType.INSERT)
     @RepeatSubmit()
-    @PostMapping("/cancelProcessApply/{processInstanceId}")
-    public R<Void> cancelProcessApply(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
-        return toAjax(actProcessInstanceService.cancelProcessApply(processInstanceId));
+    @PostMapping("/cancelProcessApply/{businessKey}")
+    public R<Void> cancelProcessApply(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
+        return toAjax(actProcessInstanceService.cancelProcessApply(businessKey));
     }
 
     /**

+ 2 - 2
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java

@@ -225,7 +225,7 @@ public class ActTaskController extends BaseController {
     @RepeatSubmit()
     @PostMapping("/backProcess")
     public R<String> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) {
-        return R.ok(actTaskService.backProcess(backProcessBo));
+        return R.ok("操作成功", actTaskService.backProcess(backProcessBo));
     }
 
     /**
@@ -279,7 +279,7 @@ public class ActTaskController extends BaseController {
      */
     @GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}")
     public R<String> getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) {
-        return R.ok(actTaskService.getTaskUserIdsByAddMultiInstance(taskId));
+        return R.ok("操作成功", actTaskService.getTaskUserIdsByAddMultiInstance(taskId));
     }
 
     /**

+ 7 - 7
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java

@@ -32,7 +32,7 @@ import java.util.List;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/demo/leave")
+@RequestMapping("/workflow/leave")
 public class TestLeaveController extends BaseController {
 
     private final ITestLeaveService testLeaveService;
@@ -40,7 +40,7 @@ public class TestLeaveController extends BaseController {
     /**
      * 查询请假列表
      */
-    @SaCheckPermission("demo:leave:list")
+    @SaCheckPermission("workflow:leave:list")
     @GetMapping("/list")
     public TableDataInfo<TestLeaveVo> list(TestLeaveBo bo, PageQuery pageQuery) {
         return testLeaveService.queryPageList(bo, pageQuery);
@@ -49,7 +49,7 @@ public class TestLeaveController extends BaseController {
     /**
      * 导出请假列表
      */
-    @SaCheckPermission("demo:leave:export")
+    @SaCheckPermission("workflow:leave:export")
     @Log(title = "请假", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(TestLeaveBo bo, HttpServletResponse response) {
@@ -62,7 +62,7 @@ public class TestLeaveController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("demo:leave:query")
+    @SaCheckPermission("workflow:leave:query")
     @GetMapping("/{id}")
     public R<TestLeaveVo> getInfo(@NotNull(message = "主键不能为空")
                                   @PathVariable Long id) {
@@ -72,7 +72,7 @@ public class TestLeaveController extends BaseController {
     /**
      * 新增请假
      */
-    @SaCheckPermission("demo:leave:add")
+    @SaCheckPermission("workflow:leave:add")
     @Log(title = "请假", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
@@ -83,7 +83,7 @@ public class TestLeaveController extends BaseController {
     /**
      * 修改请假
      */
-    @SaCheckPermission("demo:leave:edit")
+    @SaCheckPermission("workflow:leave:edit")
     @Log(title = "请假", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()
@@ -96,7 +96,7 @@ public class TestLeaveController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("demo:leave:remove")
+    @SaCheckPermission("workflow:leave:remove")
     @Log(title = "请假", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空")

+ 5 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/TestLeave.java

@@ -54,5 +54,10 @@ public class TestLeave extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 状态
+     */
+    private String status;
+
 
 }

+ 3 - 3
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java

@@ -19,10 +19,10 @@ public class ProcessInvalidBo implements Serializable {
     private static final long serialVersionUID = 1L;
 
     /**
-     * 流程实例id
+     * 业务id
      */
-    @NotBlank(message = "流程实例id不能为空", groups = {AddGroup.class})
-    private String processInstanceId;
+    @NotBlank(message = "业务id不能为空", groups = {AddGroup.class})
+    private String businessKey;
 
     /**
      * 作废原因

+ 5 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java

@@ -71,5 +71,10 @@ public class TestLeaveBo extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 状态
+     */
+    private String status;
+
 
 }

+ 4 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java

@@ -36,6 +36,10 @@ public class ActHistoryInfoVo implements Serializable {
      * 流程实例id
      */
     private String processInstanceId;
+    /**
+     * 版本
+     */
+    private Integer version;
     /**
      * 开始时间
      */

+ 3 - 3
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TestLeaveVo.java

@@ -62,9 +62,9 @@ public class TestLeaveVo implements Serializable {
     private String remark;
 
     /**
-     * 流程实例对象
+     * 状态
      */
-    private ProcessInstanceVo processInstanceVo;
-
+    @ExcelProperty(value = "状态")
+    private String status;
 
 }

+ 48 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java

@@ -0,0 +1,48 @@
+package org.dromara.workflow.flowable.handler;
+
+import org.dromara.common.core.domain.event.ProcessEvent;
+import org.dromara.common.core.domain.event.ProcessTaskEvent;
+import org.dromara.common.core.utils.SpringUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * 流程监听服务
+ *
+ * @author may
+ * @date 2024-06-02
+ */
+@Component
+public class FlowProcessEventHandler {
+
+    /**
+     * 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
+     *
+     * @param key         流程key
+     * @param businessKey 业务id
+     * @param status      状态
+     * @param submit      当为true时为申请人节点办理
+     */
+    public void processHandler(String key, String businessKey, String status, boolean submit) {
+        ProcessEvent processEvent = new ProcessEvent();
+        processEvent.setKey(key);
+        processEvent.setBusinessKey(businessKey);
+        processEvent.setStatus(status);
+        processEvent.setSubmit(submit);
+        SpringUtils.context().publishEvent(processEvent);
+    }
+
+    /**
+     * 执行办理任务监听
+     *
+     * @param keyNode     流程定义key与流程节点标识(拼接方式:流程定义key_流程节点)
+     * @param taskId      任务id
+     * @param businessKey 业务id
+     */
+    public void processTaskHandler(String keyNode, String taskId, String businessKey) {
+        ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
+        processTaskEvent.setKeyNode(keyNode);
+        processTaskEvent.setTaskId(taskId);
+        processTaskEvent.setBusinessKey(businessKey);
+        SpringUtils.context().publishEvent(processTaskEvent);
+    }
+}

+ 0 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java

@@ -8,7 +8,6 @@ import org.flowable.engine.impl.util.CommandContextUtil;
 import org.flowable.job.service.JobHandler;
 import org.flowable.job.service.impl.persistence.entity.JobEntity;
 import org.flowable.task.api.Task;
-import org.flowable.task.api.TaskQuery;
 import org.flowable.variable.api.delegate.VariableScope;
 
 /**

+ 0 - 73
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowEventStrategy.java

@@ -1,73 +0,0 @@
-package org.dromara.workflow.flowable.strategy;
-
-import org.dromara.common.core.utils.StringUtils;
-import org.dromara.workflow.annotation.FlowListenerAnnotation;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 流程任务监听策略
- *
- * @author may
- * @date 2023-12-27
- */
-@Component
-public class FlowEventStrategy implements BeanPostProcessor {
-
-    private final Map<String, FlowTaskEventHandler> flowTaskEventHandlers = new HashMap<>();
-    private final Map<String, FlowProcessEventHandler> flowProcessEventHandlers = new HashMap<>();
-
-    @Override
-    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-        if (bean instanceof FlowTaskEventHandler) {
-            FlowListenerAnnotation annotation = bean.getClass().getAnnotation(FlowListenerAnnotation.class);
-            if (null != annotation) {
-                if (StringUtils.isNotBlank(annotation.processDefinitionKey()) && StringUtils.isNotBlank(annotation.taskDefId())) {
-                    String id = annotation.processDefinitionKey() + "_" + annotation.taskDefId();
-                    if (!flowTaskEventHandlers.containsKey(id)) {
-                        flowTaskEventHandlers.put(id, (FlowTaskEventHandler) bean);
-                    }
-                }
-            }
-        }
-        if (bean instanceof FlowProcessEventHandler) {
-            FlowListenerAnnotation annotation = bean.getClass().getAnnotation(FlowListenerAnnotation.class);
-            if (null != annotation) {
-                if (StringUtils.isNotBlank(annotation.processDefinitionKey()) && StringUtils.isBlank(annotation.taskDefId())) {
-                    if (!flowProcessEventHandlers.containsKey(annotation.processDefinitionKey())) {
-                        flowProcessEventHandlers.put(annotation.processDefinitionKey(), (FlowProcessEventHandler) bean);
-                    }
-                }
-            }
-        }
-        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
-    }
-
-    /**
-     * 获取可执行bean
-     *
-     * @param key key
-     */
-    public FlowTaskEventHandler getTaskHandler(String key) {
-        if (!flowTaskEventHandlers.containsKey(key)) {
-            return null;
-        }
-        return flowTaskEventHandlers.get(key);
-    }
-
-    /**
-     * 获取可执行bean
-     *
-     * @param key key
-     */
-    public FlowProcessEventHandler getProcessHandler(String key) {
-        if (!flowProcessEventHandlers.containsKey(key)) {
-            return null;
-        }
-        return flowProcessEventHandlers.get(key);
-    }
-}

+ 0 - 20
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowProcessEventHandler.java

@@ -1,20 +0,0 @@
-package org.dromara.workflow.flowable.strategy;
-
-
-/**
- * 流程监听
- *
- * @author may
- * @date 2023-12-27
- */
-public interface FlowProcessEventHandler {
-
-    /**
-     * 执行办理任务监听
-     *
-     * @param businessKey 业务id
-     * @param status      状态
-     * @param submit      当为true时为申请人节点办理
-     */
-    void handleProcess(String businessKey, String status, boolean submit);
-}

+ 0 - 19
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/strategy/FlowTaskEventHandler.java

@@ -1,19 +0,0 @@
-package org.dromara.workflow.flowable.strategy;
-
-
-/**
- * 流程任务监听
- *
- * @author may
- * @date 2023-12-27
- */
-public interface FlowTaskEventHandler {
-
-    /**
-     * 执行办理任务监听
-     *
-     * @param taskId      任务ID
-     * @param businessKey 业务id
-     */
-    void handleTask(String taskId, String businessKey);
-}

+ 0 - 31
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestCustomProcessHandler.java

@@ -1,31 +0,0 @@
-package org.dromara.workflow.listener;
-
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.workflow.annotation.FlowListenerAnnotation;
-import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
-import org.springframework.stereotype.Component;
-
-/**
- * 自定义监听测试
- *
- * @author may
- * @date 2023-12-27
- */
-@Slf4j
-@Component
-@FlowListenerAnnotation(processDefinitionKey = "leave1")
-public class TestCustomProcessHandler implements FlowProcessEventHandler {
-
-
-    /**
-     * 执行办理任务监听
-     *
-     * @param businessKey 业务id
-     * @param status      状态
-     * @param submit      当为true时为申请人节点办理
-     */
-    @Override
-    public void handleProcess(String businessKey, String status, boolean submit) {
-        log.info("业务ID:" + businessKey + ",状态:" + status);
-    }
-}

+ 0 - 23
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestCustomTaskHandler.java

@@ -1,23 +0,0 @@
-package org.dromara.workflow.listener;
-
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.workflow.annotation.FlowListenerAnnotation;
-import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler;
-import org.springframework.stereotype.Component;
-
-/**
- * 自定义监听测试
- *
- * @author may
- * @date 2023-12-27
- */
-@Slf4j
-@Component
-@FlowListenerAnnotation(processDefinitionKey = "leave1", taskDefId = "Activity_14633hx")
-public class TestCustomTaskHandler implements FlowTaskEventHandler {
-
-    @Override
-    public void handleTask(String taskId, String businessKey) {
-        log.info("任务ID:" + taskId + ",业务ID:" + businessKey);
-    }
-}

+ 0 - 28
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestLeaveExecutionListener.java

@@ -1,28 +0,0 @@
-package org.dromara.workflow.listener;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.workflow.utils.QueryUtils;
-import org.flowable.engine.TaskService;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.flowable.engine.delegate.ExecutionListener;
-import org.flowable.task.api.Task;
-import org.springframework.stereotype.Component;
-
-/**
- * 流程实例监听测试
- *
- * @author may
- * @date 2023-12-12
- */
-@Slf4j
-@RequiredArgsConstructor
-@Component("testLeaveExecutionListener")
-public class TestLeaveExecutionListener implements ExecutionListener {
-
-    @Override
-    public void notify(DelegateExecution execution) {
-        Task task = QueryUtils.taskQuery().executionId(execution.getId()).singleResult();
-        log.info("执行监听【" + task.getName() + "】");
-    }
-}

+ 0 - 21
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/TestLeaveTaskListener.java

@@ -1,21 +0,0 @@
-package org.dromara.workflow.listener;
-
-import lombok.extern.slf4j.Slf4j;
-import org.flowable.task.service.delegate.DelegateTask;
-import org.flowable.task.service.delegate.TaskListener;
-import org.springframework.stereotype.Component;
-
-/**
- * 流程任务监听测试
- *
- * @author may
- * @date 2023-12-12
- */
-@Slf4j
-@Component("testLeaveTaskListener")
-public class TestLeaveTaskListener implements TaskListener {
-    @Override
-    public void notify(DelegateTask delegateTask) {
-        log.info("执行监听【" + delegateTask.getName() + "】");
-    }
-}

+ 12 - 20
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java

@@ -20,18 +20,18 @@ public interface IActProcessInstanceService {
     /**
      * 通过流程实例id获取历史流程图
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 流程实例id
      * @return 结果
      */
-    String getHistoryImage(String processInstanceId);
+    String getHistoryImage(String businessKey);
 
     /**
-     * 通过流程实例id获取历史流程图运行中,历史等节点
+     * 通过业务id获取历史流程图运行中,历史等节点
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      * @return 结果
      */
-    Map<String, Object> getHistoryList(String processInstanceId);
+    Map<String, Object> getHistoryList(String businessKey);
 
     /**
      * 分页查询正在运行的流程实例
@@ -54,10 +54,10 @@ public interface IActProcessInstanceService {
     /**
      * 获取审批记录
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      * @return 结果
      */
-    List<ActHistoryInfoVo> getHistoryRecord(String processInstanceId);
+    List<ActHistoryInfoVo> getHistoryRecord(String businessKey);
 
     /**
      * 作废流程实例,不会删除历史记录(删除运行中的实例)
@@ -70,34 +70,26 @@ public interface IActProcessInstanceService {
     /**
      * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
-     * @return 结果
-     */
-    boolean deleteRunAndHisInstance(List<String> processInstanceIds);
-
-    /**
-     * 按照业务id删除 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
-     *
      * @param businessKeys 业务id
      * @return 结果
      */
-    boolean deleteRunAndHisInstanceByBusinessKeys(List<String> businessKeys);
+    boolean deleteRunAndHisInstance(List<String> businessKeys);
 
     /**
      * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
+     * @param businessKeys 业务id
      * @return 结果
      */
-    boolean deleteFinishAndHisInstance(List<String> processInstanceIds);
+    boolean deleteFinishAndHisInstance(List<String> businessKeys);
 
     /**
      * 撤销流程申请
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      * @return 结果
      */
-    boolean cancelProcessApply(String processInstanceId);
+    boolean cancelProcessApply(String businessKey);
 
     /**
      * 分页查询当前登录人单据

+ 79 - 78
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java

@@ -16,7 +16,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.workflow.common.constant.FlowConstant;
-import org.dromara.workflow.common.enums.BusinessStatusEnum;
+import org.dromara.common.core.enums.BusinessStatusEnum;
 import org.dromara.workflow.common.enums.TaskStatusEnum;
 import org.dromara.workflow.domain.ActHiProcinst;
 import org.dromara.workflow.domain.bo.ProcessInstanceBo;
@@ -26,8 +26,7 @@ import org.dromara.workflow.domain.vo.*;
 import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator;
 import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd;
 import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd;
-import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
-import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
+import org.dromara.workflow.flowable.handler.FlowProcessEventHandler;
 import org.dromara.workflow.service.IActHiProcinstService;
 import org.dromara.workflow.service.IActProcessInstanceService;
 import org.dromara.workflow.service.IWfNodeConfigService;
@@ -75,9 +74,9 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     private final TaskService taskService;
     private final IActHiProcinstService actHiProcinstService;
     private final ManagementService managementService;
-    private final FlowEventStrategy flowEventStrategy;
     private final IWfTaskBackNodeService wfTaskBackNodeService;
     private final IWfNodeConfigService wfNodeConfigService;
+    private final FlowProcessEventHandler flowProcessEventHandler;
 
     @Value("${flowable.activity-font-name}")
     private String activityFontName;
@@ -184,28 +183,28 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     }
 
     /**
-     * 通过流程实例id获取历史流程图
+     * 通过业务id获取历史流程图
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
     @SneakyThrows
     @Override
-    public String getHistoryImage(String processInstanceId) {
+    public String getHistoryImage(String businessKey) {
         String processDefinitionId;
         // 获取当前的流程实例
-        ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult();
+        ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey).singleResult();
         // 如果流程已经结束,则得到结束节点
         if (Objects.isNull(processInstance)) {
-            HistoricProcessInstance pi = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
+            HistoricProcessInstance pi = QueryUtils.hisInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
             processDefinitionId = pi.getProcessDefinitionId();
         } else {
             // 根据流程实例ID获得当前处于活动状态的ActivityId合集
-            ProcessInstance pi = QueryUtils.instanceQuery(processInstanceId).singleResult();
+            ProcessInstance pi = QueryUtils.instanceQuery(processInstance.getProcessInstanceId()).singleResult();
             processDefinitionId = pi.getProcessDefinitionId();
         }
 
         // 获得活动的节点
-        List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
+        List<HistoricActivityInstance> highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstance.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list();
 
         List<String> highLightedFlows = new ArrayList<>();
         List<String> highLightedNodes = new ArrayList<>();
@@ -240,15 +239,16 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     }
 
     /**
-     * 通过流程实例id获取历史流程图运行中,历史等节点
+     * 通过业务id获取历史流程图运行中,历史等节点
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
     @Override
-    public Map<String, Object> getHistoryList(String processInstanceId) {
+    public Map<String, Object> getHistoryList(String businessKey) {
         Map<String, Object> map = new HashMap<>();
         List<Map<String, Object>> taskList = new ArrayList<>();
-        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
+        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
+        String processInstanceId = historicProcessInstance.getId();
         StringBuilder xml = new StringBuilder();
         ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
         // 获取节点
@@ -280,7 +280,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
             }
         }
         map.put("taskList", taskList);
-        List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId);
+        List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId, processDefinition.getVersion());
         map.put("historyList", historyTaskList);
         InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
         xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
@@ -292,8 +292,9 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
      * 获取历史任务节点信息
      *
      * @param processInstanceId 流程实例id
+     * @param version           版本
      */
-    private List<ActHistoryInfoVo> getHistoryTaskList(String processInstanceId) {
+    private List<ActHistoryInfoVo> getHistoryTaskList(String processInstanceId, Integer version) {
         //查询任务办理记录
         List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
         list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
@@ -305,27 +306,48 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
             if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
                 actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
             }
+            actHistoryInfoVo.setVersion(version);
             actHistoryInfoVoList.add(actHistoryInfoVo);
         }
         List<ActHistoryInfoVo> historyInfoVoList = new ArrayList<>();
         Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
         for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
             ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo();
-            BeanUtils.copyProperties(entry.getValue().get(0), historyInfoVo);
-            actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst()
-                .ifPresent(e -> {
-                    historyInfoVo.setStatus("待处理");
-                    historyInfoVo.setStartTime(e.getStartTime());
-                    historyInfoVo.setEndTime(null);
-                    historyInfoVo.setRunDuration(null);
-                    if (ObjectUtil.isEmpty(e.getAssignee())) {
-                        ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId());
+            if (entry.getValue().size() > 1) {
+                List<ActHistoryInfoVo> historyInfoVos = StreamUtils.filter(entry.getValue(), e -> StringUtils.isNotBlank(e.getAssignee()));
+                if (CollUtil.isNotEmpty(historyInfoVos)) {
+                    ActHistoryInfoVo infoVo = historyInfoVos.get(0);
+                    BeanUtils.copyProperties(infoVo, historyInfoVo);
+                    historyInfoVo.setStatus(infoVo.getEndTime() == null ? "待处理" : "已处理");
+                    historyInfoVo.setStartTime(infoVo.getStartTime());
+                    historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime());
+                    historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration());
+                    if (ObjectUtil.isEmpty(infoVo.getAssignee())) {
+                        ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId());
                         if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                             historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                         }
                     }
-                });
+                }
+            } else {
+                actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey())).findFirst()
+                    .ifPresent(e -> {
+                        BeanUtils.copyProperties(e, historyInfoVo);
+                        historyInfoVo.setStatus(e.getEndTime() == null ? "待处理" : "已处理");
+                        historyInfoVo.setStartTime(e.getStartTime());
+                        historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime());
+                        historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration());
+                        if (ObjectUtil.isEmpty(e.getAssignee())) {
+                            ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId());
+                            if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
+                                historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
+                            }
+                        }
+                    });
+
+            }
             historyInfoVoList.add(historyInfoVo);
+
         }
         return historyInfoVoList;
     }
@@ -333,13 +355,15 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     /**
      * 获取审批记录
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
     @Override
-    public List<ActHistoryInfoVo> getHistoryRecord(String processInstanceId) {
+    public List<ActHistoryInfoVo> getHistoryRecord(String businessKey) {
         // 查询任务办理记录
-        List<HistoricTaskInstance> list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
+        List<HistoricTaskInstance> list = QueryUtils.hisTaskBusinessKeyQuery(businessKey).orderByHistoricTaskInstanceEndTime().desc().list();
         list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
+        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
+        String processInstanceId = historicProcessInstance.getId();
         List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>();
         List<Comment> processInstanceComments = taskService.getProcessInstanceComments(processInstanceId);
         //附件
@@ -440,7 +464,8 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     @Transactional(rollbackFor = Exception.class)
     public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) {
         try {
-            List<Task> list = QueryUtils.taskQuery(processInvalidBo.getProcessInstanceId()).list();
+            List<Task> list = QueryUtils.taskQuery().processInstanceBusinessKey(processInvalidBo.getBusinessKey()).list();
+            String processInstanceId = list.get(0).getProcessInstanceId();
             List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
             if (CollUtil.isNotEmpty(subTasks)) {
                 subTasks.forEach(e -> taskService.deleteTask(e.getId()));
@@ -452,14 +477,13 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
             for (Task task : StreamUtils.filter(list, e -> StringUtils.isBlank(e.getParentTaskId()))) {
                 taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.INVALID.getStatus(), deleteReason);
             }
-            HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInvalidBo.getProcessInstanceId()).singleResult();
+            HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
             BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
-            runtimeService.updateBusinessStatus(processInvalidBo.getProcessInstanceId(), BusinessStatusEnum.INVALID.getStatus());
-            runtimeService.deleteProcessInstance(processInvalidBo.getProcessInstanceId(), deleteReason);
-            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
-            if (processHandler != null) {
-                processHandler.handleProcess(historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
-            }
+            runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.INVALID.getStatus());
+            runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
+            //流程作废监听
+            flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(),
+                historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
             return true;
         } catch (Exception e) {
             e.printStackTrace();
@@ -470,40 +494,11 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     /**
      * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean deleteRunAndHisInstance(List<String> processInstanceIds) {
-        try {
-            // 1.删除运行中流程实例
-            List<Task> list = QueryUtils.taskQuery(processInstanceIds).list();
-            List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
-            if (CollUtil.isNotEmpty(subTasks)) {
-                subTasks.forEach(e -> taskService.deleteTask(e.getId()));
-            }
-            runtimeService.bulkDeleteProcessInstances(processInstanceIds, LoginHelper.getUserId() + "删除了当前流程申请");
-            // 2.删除历史记录
-            List<HistoricProcessInstance> historicProcessInstanceList = QueryUtils.hisInstanceQuery(new HashSet<>(processInstanceIds)).list();
-            if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
-                historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
-            }
-            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
-            return true;
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new ServiceException(e.getMessage());
-        }
-    }
-
-    /**
-     * 按照业务id删除 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
-     *
      * @param businessKeys 业务id
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean deleteRunAndHisInstanceByBusinessKeys(List<String> businessKeys) {
+    public boolean deleteRunAndHisInstance(List<String> businessKeys) {
         try {
             // 1.删除运行中流程实例
             List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
@@ -534,12 +529,18 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     /**
      * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
      *
-     * @param processInstanceIds 流程实例id
+     * @param businessKeys 业务id
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) {
+    public boolean deleteFinishAndHisInstance(List<String> businessKeys) {
         try {
+            List<ActHiProcinst> actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
+            if (CollUtil.isEmpty(actHiProcinsts)) {
+                log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys);
+                return false;
+            }
+            List<String> processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId);
             historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
             wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
             return true;
@@ -552,13 +553,13 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
     /**
      * 撤销流程申请
      *
-     * @param processInstanceId 流程实例id
+     * @param businessKey 业务id
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean cancelProcessApply(String processInstanceId) {
+    public boolean cancelProcessApply(String businessKey) {
         try {
-            ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId)
+            ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey)
                 .startedBy(String.valueOf(LoginHelper.getUserId())).singleResult();
             if (ObjectUtil.isNull(processInstance)) {
                 throw new ServiceException("您不是流程发起人,撤销失败!");
@@ -566,13 +567,14 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
             if (processInstance.isSuspended()) {
                 throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
             }
+            String processInstanceId = processInstance.getId();
             BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus());
             List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
             for (Task task : taskList) {
                 taskService.setAssignee(task.getId(), null);
                 taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.CANCEL.getStatus(), LoginHelper.getLoginUser().getNickname() + ":撤销申请");
             }
-            HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
+            HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
             List<String> nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey);
             runtimeService.createChangeActivityStateBuilder()
                 .processInstanceId(processInstanceId)
@@ -588,10 +590,9 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
                 managementService.executeCommand(deleteExecutionCmd);
             }
             runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus());
-            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
-            if (processHandler != null) {
-                processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
-            }
+            //流程作废监听
+            flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(),
+                processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
             return true;
         } catch (Exception e) {
             e.printStackTrace();

+ 25 - 40
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java

@@ -18,16 +18,14 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.tenant.helper.TenantHelper;
 import org.dromara.workflow.common.constant.FlowConstant;
-import org.dromara.workflow.common.enums.BusinessStatusEnum;
+import org.dromara.common.core.enums.BusinessStatusEnum;
 import org.dromara.workflow.common.enums.TaskStatusEnum;
 import org.dromara.workflow.domain.ActHiTaskinst;
 import org.dromara.workflow.domain.WfTaskBackNode;
 import org.dromara.workflow.domain.bo.*;
 import org.dromara.workflow.domain.vo.*;
 import org.dromara.workflow.flowable.cmd.*;
-import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
-import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
-import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler;
+import org.dromara.workflow.flowable.handler.FlowProcessEventHandler;
 import org.dromara.workflow.mapper.ActHiTaskinstMapper;
 import org.dromara.workflow.mapper.ActTaskMapper;
 import org.dromara.workflow.service.IActTaskService;
@@ -75,13 +73,13 @@ public class ActTaskServiceImpl implements IActTaskService {
     private final HistoryService historyService;
     private final IdentityService identityService;
     private final ManagementService managementService;
-    private final FlowEventStrategy flowEventStrategy;
     private final ActTaskMapper actTaskMapper;
     private final IWfTaskBackNodeService wfTaskBackNodeService;
     private final ActHiTaskinstMapper actHiTaskinstMapper;
     private final IWfNodeConfigService wfNodeConfigService;
     private final IWfDefinitionConfigService wfDefinitionConfigService;
     private final UserService userService;
+    private final FlowProcessEventHandler flowProcessEventHandler;
 
     /**
      * 启动任务
@@ -159,15 +157,8 @@ public class ActTaskServiceImpl implements IActTaskService {
     @Transactional(rollbackFor = Exception.class)
     public boolean completeTask(CompleteTaskBo completeTaskBo) {
         try {
-            List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
             String userId = String.valueOf(LoginHelper.getUserId());
-            TaskQuery taskQuery = QueryUtils.taskQuery();
-            taskQuery.taskId(completeTaskBo.getTaskId()).taskCandidateOrAssigned(userId);
-            if (CollUtil.isNotEmpty(roles)) {
-                List<String> groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
-                taskQuery.taskCandidateGroupIn(groupIds);
-            }
-            Task task = taskQuery.singleResult();
+            Task task = WorkflowUtils.getTaskByCurrentUser(completeTaskBo.getTaskId());
             if (task == null) {
                 throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
             }
@@ -186,19 +177,15 @@ public class ActTaskServiceImpl implements IActTaskService {
             //附件上传
             AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId());
             managementService.executeCommand(attachmentCmd);
-            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
-            String businessStatus = WorkflowUtils.getBusinessStatus(task.getProcessInstanceId());
+            String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey());
+            //流程提交监听
             if (BusinessStatusEnum.DRAFT.getStatus().equals(businessStatus) || BusinessStatusEnum.BACK.getStatus().equals(businessStatus) || BusinessStatusEnum.CANCEL.getStatus().equals(businessStatus)) {
-                if (processHandler != null) {
-                    processHandler.handleProcess(processInstance.getBusinessKey(), businessStatus, true);
-                }
+                flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), businessStatus, true);
             }
             runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus());
-            String key = processInstance.getProcessDefinitionKey() + "_" + task.getTaskDefinitionKey();
-            FlowTaskEventHandler taskHandler = flowEventStrategy.getTaskHandler(key);
-            if (taskHandler != null) {
-                taskHandler.handleTask(task.getId(), processInstance.getBusinessKey());
-            }
+            //办理监听
+            String keyNode = processInstance.getProcessDefinitionKey() + "_" + task.getTaskDefinitionKey();
+            flowProcessEventHandler.processTaskHandler(keyNode, task.getId(), processInstance.getBusinessKey());
             //办理意见
             taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage());
             //办理任务
@@ -214,9 +201,8 @@ public class ActTaskServiceImpl implements IActTaskService {
             if (pi == null) {
                 UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
                 managementService.executeCommand(updateBusinessStatusCmd);
-                if (processHandler != null) {
-                    processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.FINISH.getStatus(), false);
-                }
+                flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(),
+                    BusinessStatusEnum.FINISH.getStatus(), false);
             } else {
                 List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
                 for (Task t : list) {
@@ -470,8 +456,8 @@ public class ActTaskServiceImpl implements IActTaskService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean delegateTask(DelegateBo delegateBo) {
-        TaskQuery query = QueryUtils.taskQuery();
-        TaskEntity task = (TaskEntity) query.taskId(delegateBo.getTaskId()).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult();
+        Task task = WorkflowUtils.getTaskByCurrentUser(delegateBo.getTaskId());
+
         if (ObjectUtil.isEmpty(task)) {
             throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
         }
@@ -527,10 +513,9 @@ public class ActTaskServiceImpl implements IActTaskService {
                 runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus());
                 runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY);
             }
-            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
-            if (processHandler != null) {
-                processHandler.handleProcess(historicProcessInstance.getBusinessKey(), BusinessStatusEnum.TERMINATION.getStatus(), false);
-            }
+            //流程终止监听
+            flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(),
+                historicProcessInstance.getBusinessKey(), BusinessStatusEnum.TERMINATION.getStatus(), false);
             return true;
         } catch (Exception e) {
             throw new ServiceException(e.getMessage());
@@ -544,7 +529,7 @@ public class ActTaskServiceImpl implements IActTaskService {
      */
     @Override
     public boolean transferTask(TransmitBo transmitBo) {
-        Task task = QueryUtils.taskQuery().taskId(transmitBo.getTaskId()).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult();
+        Task task = WorkflowUtils.getTaskByCurrentUser(transmitBo.getTaskId());
         if (ObjectUtil.isEmpty(task)) {
             throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
         }
@@ -669,9 +654,9 @@ public class ActTaskServiceImpl implements IActTaskService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public String backProcess(BackProcessBo backProcessBo) {
-        TaskQuery query = QueryUtils.taskQuery();
         String userId = String.valueOf(LoginHelper.getUserId());
-        Task task = query.taskId(backProcessBo.getTaskId()).taskCandidateOrAssigned(userId).singleResult();
+        Task task = WorkflowUtils.getTaskByCurrentUser(backProcessBo.getTaskId());
+
         if (ObjectUtil.isEmpty(task)) {
             throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
         }
@@ -705,7 +690,9 @@ public class ActTaskServiceImpl implements IActTaskService {
             MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
             if (multiInstance == null && taskList.size() > 1) {
                 List<Task> tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
-                actHiTaskinstMapper.deleteBatchIds(StreamUtils.toList(tasks, Task::getId));
+                if (CollUtil.isNotEmpty(tasks)) {
+                    actHiTaskinstMapper.deleteBatchIds(StreamUtils.toList(tasks, Task::getId));
+                }
             }
 
 
@@ -728,10 +715,8 @@ public class ActTaskServiceImpl implements IActTaskService {
             WfTaskBackNode wfTaskBackNode = wfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId());
             if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) {
                 runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
-                FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
-                if (processHandler != null) {
-                    processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false);
-                }
+                flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(),
+                    processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false);
             }
             //删除驳回后的流程节点
             wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());

+ 47 - 21
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java

@@ -1,10 +1,14 @@
 package org.dromara.workflow.service.impl;
 
-import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.event.ProcessEvent;
+import org.dromara.common.core.domain.event.ProcessTaskEvent;
+import org.dromara.common.core.enums.BusinessStatusEnum;
+import org.dromara.common.core.service.WorkflowService;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StreamUtils;
 import org.dromara.common.core.utils.StringUtils;
@@ -15,9 +19,8 @@ import org.dromara.workflow.domain.TestLeave;
 import org.dromara.workflow.domain.bo.TestLeaveBo;
 import org.dromara.workflow.domain.vo.TestLeaveVo;
 import org.dromara.workflow.mapper.TestLeaveMapper;
-import org.dromara.workflow.service.IActProcessInstanceService;
 import org.dromara.workflow.service.ITestLeaveService;
-import org.dromara.workflow.utils.WorkflowUtils;
+import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -32,19 +35,18 @@ import java.util.List;
  */
 @RequiredArgsConstructor
 @Service
+@Slf4j
 public class TestLeaveServiceImpl implements ITestLeaveService {
 
     private final TestLeaveMapper baseMapper;
-    private final IActProcessInstanceService actProcessInstanceService;
+    private final WorkflowService workflowService;
 
     /**
      * 查询请假
      */
     @Override
     public TestLeaveVo queryById(Long id) {
-        TestLeaveVo testLeaveVo = baseMapper.selectVoById(id);
-        WorkflowUtils.setProcessInstanceVo(testLeaveVo, String.valueOf(id));
-        return testLeaveVo;
+        return baseMapper.selectVoById(id);
     }
 
     /**
@@ -54,13 +56,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     public TableDataInfo<TestLeaveVo> queryPageList(TestLeaveBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<TestLeave> lqw = buildQueryWrapper(bo);
         Page<TestLeaveVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        TableDataInfo<TestLeaveVo> build = TableDataInfo.build(result);
-        List<TestLeaveVo> rows = build.getRows();
-        if (CollUtil.isNotEmpty(rows)) {
-            List<String> ids = StreamUtils.toList(rows, e -> String.valueOf(e.getId()));
-            WorkflowUtils.setProcessInstanceListVo(rows, ids, "id");
-        }
-        return build;
+        return TableDataInfo.build(result);
     }
 
     /**
@@ -87,13 +83,14 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     @Override
     public TestLeaveVo insertByBo(TestLeaveBo bo) {
         TestLeave add = MapstructUtils.convert(bo, TestLeave.class);
+        if (StringUtils.isBlank(add.getStatus())) {
+            add.setStatus(BusinessStatusEnum.DRAFT.getStatus());
+        }
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
             bo.setId(add.getId());
         }
-        TestLeaveVo testLeaveVo = MapstructUtils.convert(add, TestLeaveVo.class);
-        WorkflowUtils.setProcessInstanceVo(testLeaveVo, String.valueOf(add.getId()));
-        return testLeaveVo;
+        return MapstructUtils.convert(add, TestLeaveVo.class);
     }
 
     /**
@@ -103,9 +100,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     public TestLeaveVo updateByBo(TestLeaveBo bo) {
         TestLeave update = MapstructUtils.convert(bo, TestLeave.class);
         baseMapper.updateById(update);
-        TestLeaveVo testLeaveVo = MapstructUtils.convert(update, TestLeaveVo.class);
-        WorkflowUtils.setProcessInstanceVo(testLeaveVo, String.valueOf(update.getId()));
-        return testLeaveVo;
+        return MapstructUtils.convert(update, TestLeaveVo.class);
     }
 
     /**
@@ -115,7 +110,38 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     @Transactional(rollbackFor = Exception.class)
     public Boolean deleteWithValidByIds(Collection<Long> ids) {
         List<String> idList = StreamUtils.toList(ids, String::valueOf);
-        actProcessInstanceService.deleteRunAndHisInstanceByBusinessKeys(idList);
+        workflowService.deleteRunAndHisInstance(idList);
         return baseMapper.deleteBatchIds(ids) > 0;
     }
+
+    /**
+     * 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
+     *
+     * @param processEvent 参数
+     */
+    @EventListener(condition = "#processEvent.key=='leave1'")
+    public void processHandler(ProcessEvent processEvent) {
+        log.info("当前任务执行了{}", processEvent.toString());
+        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey()));
+        testLeave.setStatus(processEvent.getStatus());
+        if (processEvent.isSubmit()) {
+            testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
+        }
+        baseMapper.updateById(testLeave);
+    }
+
+    /**
+     * 执行办理任务监听
+     *
+     * @param processTaskEvent 参数
+     */
+    @EventListener(condition = "#processTaskEvent.keyNode=='leave1_Activity_14633hx'")
+    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
+        log.info("当前任务执行了{}", processTaskEvent.toString());
+        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
+        testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
+        baseMapper.updateById(testLeave);
+    }
+
+
 }

+ 119 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java

@@ -0,0 +1,119 @@
+package org.dromara.workflow.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.service.WorkflowService;
+import org.dromara.workflow.domain.ActHiProcinst;
+import org.dromara.workflow.service.IActHiProcinstService;
+import org.dromara.workflow.service.IActProcessInstanceService;
+import org.dromara.workflow.utils.WorkflowUtils;
+import org.flowable.engine.RuntimeService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 通用 工作流服务实现
+ *
+ * @author may
+ */
+@RequiredArgsConstructor
+@Service
+public class WorkflowServiceImpl implements WorkflowService {
+
+    private final IActProcessInstanceService iActProcessInstanceService;
+    private final RuntimeService runtimeService;
+    private final IActHiProcinstService iActHiProcinstService;
+    /**
+     * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
+     *
+     * @param businessKeys 业务id
+     * @return 结果
+     */
+    @Override
+    public boolean deleteRunAndHisInstance(List<String> businessKeys) {
+        return iActProcessInstanceService.deleteRunAndHisInstance(businessKeys);
+    }
+
+    /**
+     * 获取当前流程状态
+     *
+     * @param taskId 任务id
+     */
+    @Override
+    public String getBusinessStatusByTaskId(String taskId) {
+        return WorkflowUtils.getBusinessStatusByTaskId(taskId);
+    }
+
+    /**
+     * 获取当前流程状态
+     *
+     * @param businessKey 业务id
+     */
+    @Override
+    public String getBusinessStatus(String businessKey) {
+        return WorkflowUtils.getBusinessStatus(businessKey);
+    }
+
+    /**
+     * 设置流程变量(全局变量)
+     *
+     * @param taskId       任务id
+     * @param variableName 变量名称
+     * @param value        变量值
+     */
+    @Override
+    public void setVariable(String taskId, String variableName, Object value) {
+        runtimeService.setVariable(taskId, variableName, value);
+    }
+
+    /**
+     * 设置流程变量(全局变量)
+     *
+     * @param taskId    任务id
+     * @param variables 流程变量
+     */
+    @Override
+    public void setVariables(String taskId, Map<String, Object> variables) {
+        runtimeService.setVariables(taskId, variables);
+    }
+
+    /**
+     * 设置流程变量(本地变量,非全局变量)
+     *
+     * @param taskId       任务id
+     * @param variableName 变量名称
+     * @param value        变量值
+     */
+    @Override
+    public void setVariableLocal(String taskId, String variableName, Object value) {
+        runtimeService.setVariableLocal(taskId, variableName, value);
+    }
+
+    /**
+     * 设置流程变量(本地变量,非全局变量)
+     *
+     * @param taskId    任务id
+     * @param variables 流程变量
+     */
+    @Override
+    public void setVariablesLocal(String taskId, Map<String, Object> variables) {
+        runtimeService.setVariablesLocal(taskId, variables);
+    }
+
+    /**
+     * 按照业务id查询流程实例id
+     *
+     * @param businessKey 业务id
+     * @return 结果
+     */
+    @Override
+    public String getInstanceIdByBusinessKey(String businessKey) {
+        ActHiProcinst actHiProcinst = iActHiProcinstService.selectByBusinessKey(businessKey);
+        if (actHiProcinst == null) {
+            return StrUtil.EMPTY;
+        }
+        return actHiProcinst.getId();
+    }
+}

+ 16 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java

@@ -12,6 +12,7 @@ import org.flowable.engine.history.HistoricProcessInstanceQuery;
 import org.flowable.engine.repository.DeploymentQuery;
 import org.flowable.engine.repository.ModelQuery;
 import org.flowable.engine.repository.ProcessDefinitionQuery;
+import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.engine.runtime.ProcessInstanceQuery;
 import org.flowable.task.api.Task;
 import org.flowable.task.api.TaskQuery;
@@ -75,6 +76,10 @@ public class QueryUtils {
         return hisTaskInstanceQuery().processInstanceId(processInstanceId);
     }
 
+    public static HistoricTaskInstanceQuery hisTaskBusinessKeyQuery(String businessKey) {
+        return hisTaskInstanceQuery().processInstanceBusinessKey(businessKey);
+    }
+
     public static ProcessInstanceQuery instanceQuery() {
         ProcessInstanceQuery query = PROCESS_ENGINE.getRuntimeService().createProcessInstanceQuery();
         if (TenantHelper.isEnable()) {
@@ -87,6 +92,10 @@ public class QueryUtils {
         return instanceQuery().processInstanceId(processInstanceId);
     }
 
+    public static ProcessInstanceQuery businessKeyQuery(String businessKey) {
+        return instanceQuery().processInstanceBusinessKey(businessKey);
+    }
+
     public static ProcessInstanceQuery instanceQuery(Set<String> processInstanceIds) {
         return instanceQuery().processInstanceIds(processInstanceIds);
     }
@@ -103,6 +112,10 @@ public class QueryUtils {
         return hisInstanceQuery().processInstanceId(processInstanceId);
     }
 
+    public static HistoricProcessInstanceQuery hisBusinessKeyQuery(String businessKey) {
+        return hisInstanceQuery().processInstanceBusinessKey(businessKey);
+    }
+
     public static HistoricProcessInstanceQuery hisInstanceQuery(Set<String> processInstanceIds) {
         return hisInstanceQuery().processInstanceIds(processInstanceIds);
     }
@@ -145,9 +158,11 @@ public class QueryUtils {
         if (task == null) {
             return null;
         }
+        ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
         TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
+        taskVo.setBusinessKey(processInstance.getBusinessKey());
         taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
-        String businessStatus = WorkflowUtils.getBusinessStatus(taskVo.getProcessInstanceId());
+        String businessStatus = WorkflowUtils.getBusinessStatus(taskVo.getBusinessKey());
         taskVo.setBusinessStatus(businessStatus);
         return taskVo;
     }

+ 31 - 77
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java

@@ -1,34 +1,30 @@
 package org.dromara.workflow.utils;
 
-import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.dromara.common.core.domain.dto.RoleDTO;
 import org.dromara.common.core.domain.dto.UserDTO;
 import org.dromara.common.core.service.UserService;
 import org.dromara.common.core.utils.SpringUtils;
 import org.dromara.common.core.utils.StreamUtils;
 import org.dromara.common.core.utils.StringUtils;
-import org.dromara.common.core.utils.reflect.ReflectUtils;
 import org.dromara.common.mail.utils.MailUtils;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.tenant.helper.TenantHelper;
 import org.dromara.common.websocket.dto.WebSocketMessageDto;
 import org.dromara.common.websocket.utils.WebSocketUtils;
 import org.dromara.workflow.common.constant.FlowConstant;
-import org.dromara.workflow.common.enums.BusinessStatusEnum;
 import org.dromara.workflow.common.enums.MessageTypeEnum;
 import org.dromara.workflow.common.enums.TaskStatusEnum;
-import org.dromara.workflow.domain.ActHiProcinst;
 import org.dromara.workflow.domain.ActHiTaskinst;
 import org.dromara.workflow.domain.vo.MultiInstanceVo;
 import org.dromara.workflow.domain.vo.ParticipantVo;
-import org.dromara.workflow.domain.vo.ProcessInstanceVo;
 import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd;
 import org.dromara.workflow.mapper.ActHiTaskinstMapper;
-import org.dromara.workflow.service.IActHiProcinstService;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.bpmn.model.FlowNode;
 import org.flowable.common.engine.api.delegate.Expression;
@@ -38,13 +34,12 @@ import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
 import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
 import org.flowable.identitylink.api.history.HistoricIdentityLink;
 import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskQuery;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 
 import java.util.*;
 
-import static org.dromara.workflow.common.constant.FlowConstant.PROCESS_INSTANCE_VO;
-
 /**
  * 工作流工具
  *
@@ -54,8 +49,6 @@ import static org.dromara.workflow.common.constant.FlowConstant.PROCESS_INSTANCE
 public class WorkflowUtils {
 
     private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class);
-    private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class);
-    private static final IActHiProcinstService ACT_HI_PROCINST_SERVICE = SpringUtils.getBean(IActHiProcinstService.class);
     private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class);
 
     /**
@@ -133,6 +126,7 @@ public class WorkflowUtils {
      * @param taskId 任务id
      */
     public static ParticipantVo getCurrentTaskParticipant(String taskId) {
+        UserService userService = SpringUtils.getBean(UserService.class);
         ParticipantVo participantVo = new ParticipantVo();
         List<HistoricIdentityLink> linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId);
         Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
@@ -140,10 +134,10 @@ public class WorkflowUtils {
             List<HistoricIdentityLink> groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId()));
             if (CollUtil.isNotEmpty(groupList)) {
                 List<Long> groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId()));
-                List<Long> userIds = USER_SERVICE.selectUserIdsByRoleIds(groupIds);
+                List<Long> userIds = userService.selectUserIdsByRoleIds(groupIds);
                 if (CollUtil.isNotEmpty(userIds)) {
                     participantVo.setGroupIds(groupIds);
-                    List<UserDTO> userList = USER_SERVICE.selectListByIds(userIds);
+                    List<UserDTO> userList = userService.selectListByIds(userIds);
                     if (CollUtil.isNotEmpty(userList)) {
                         List<Long> userIdList = StreamUtils.toList(userList, UserDTO::getUserId);
                         List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
@@ -162,7 +156,7 @@ public class WorkflowUtils {
 
                     }
                 }
-                List<UserDTO> userList = USER_SERVICE.selectListByIds(userIdList);
+                List<UserDTO> userList = userService.selectListByIds(userIdList);
                 if (CollUtil.isNotEmpty(userList)) {
                     List<Long> userIds = StreamUtils.toList(userList, UserDTO::getUserId);
                     List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
@@ -225,70 +219,11 @@ public class WorkflowUtils {
     /**
      * 获取当前流程状态
      *
-     * @param processInstanceId 流程实例id
-     */
-    public static String getBusinessStatus(String processInstanceId) {
-        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult();
-        return historicProcessInstance.getBusinessStatus();
-    }
-
-    /**
-     * 设置流程实例对象
-     *
-     * @param obj         业务对象
      * @param businessKey 业务id
      */
-    public static void setProcessInstanceVo(Object obj, String businessKey) {
-        if (StringUtils.isBlank(businessKey) || obj == null) {
-            return;
-        }
-        ActHiProcinst actHiProcinst = ACT_HI_PROCINST_SERVICE.selectByBusinessKey(businessKey);
-        if (actHiProcinst == null) {
-            ProcessInstanceVo processInstanceVo = new ProcessInstanceVo();
-            processInstanceVo.setBusinessStatus(BusinessStatusEnum.DRAFT.getStatus());
-            ReflectUtils.invokeSetter(obj, PROCESS_INSTANCE_VO, processInstanceVo);
-            return;
-        }
-        ProcessInstanceVo processInstanceVo = BeanUtil.toBean(actHiProcinst, ProcessInstanceVo.class);
-        processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstanceVo.getBusinessStatus()));
-        ReflectUtils.invokeSetter(obj, PROCESS_INSTANCE_VO, processInstanceVo);
-    }
-
-    /**
-     * 设置流程实例对象
-     *
-     * @param obj       业务对象
-     * @param idList    业务id
-     * @param fieldName 主键属性名称
-     */
-    public static void setProcessInstanceListVo(Object obj, List<String> idList, String fieldName) {
-        if (CollUtil.isEmpty(idList) || obj == null) {
-            return;
-        }
-        List<ActHiProcinst> actHiProcinstList = ACT_HI_PROCINST_SERVICE.selectByBusinessKeyIn(idList);
-        if (obj instanceof Collection<?> collection) {
-            for (Object o : collection) {
-                String fieldValue = ReflectUtils.invokeGetter(o, fieldName).toString();
-                if (CollUtil.isEmpty(actHiProcinstList)) {
-                    ProcessInstanceVo processInstanceVo = new ProcessInstanceVo();
-                    processInstanceVo.setBusinessStatus(BusinessStatusEnum.DRAFT.getStatus());
-                    processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstanceVo.getBusinessStatus()));
-                    ReflectUtils.invokeSetter(o, PROCESS_INSTANCE_VO, processInstanceVo);
-                } else {
-                    ActHiProcinst actHiProcinst = actHiProcinstList.stream().filter(e -> e.getBusinessKey().equals(fieldValue)).findFirst().orElse(null);
-                    if (ObjectUtil.isNotEmpty(actHiProcinst)) {
-                        ProcessInstanceVo processInstanceVo = BeanUtil.toBean(actHiProcinst, ProcessInstanceVo.class);
-                        processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstanceVo.getBusinessStatus()));
-                        ReflectUtils.invokeSetter(o, PROCESS_INSTANCE_VO, processInstanceVo);
-                    } else {
-                        ProcessInstanceVo processInstanceVo = new ProcessInstanceVo();
-                        processInstanceVo.setBusinessStatus(BusinessStatusEnum.DRAFT.getStatus());
-                        processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstanceVo.getBusinessStatus()));
-                        ReflectUtils.invokeSetter(o, PROCESS_INSTANCE_VO, processInstanceVo);
-                    }
-                }
-            }
-        }
+    public static String getBusinessStatus(String businessKey) {
+        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
+        return historicProcessInstance.getBusinessStatus();
     }
 
     /**
@@ -300,6 +235,7 @@ public class WorkflowUtils {
      * @param message     消息内容,为空则发送默认配置的消息内容
      */
     public static void sendMessage(List<Task> list, String name, List<String> messageType, String message) {
+        UserService userService = SpringUtils.getBean(UserService.class);
         Set<Long> userIds = new HashSet<>();
         if (StringUtils.isBlank(message)) {
             message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。";
@@ -307,7 +243,7 @@ public class WorkflowUtils {
         for (Task t : list) {
             ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId());
             if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
-                List<Long> userIdList = USER_SERVICE.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
+                List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
                 if (CollUtil.isNotEmpty(userIdList)) {
                     userIds.addAll(userIdList);
                 }
@@ -318,7 +254,7 @@ public class WorkflowUtils {
             }
         }
         if (CollUtil.isNotEmpty(userIds)) {
-            List<UserDTO> userList = USER_SERVICE.selectListByIds(new ArrayList<>(userIds));
+            List<UserDTO> userList = userService.selectListByIds(new ArrayList<>(userIds));
             for (String code : messageType) {
                 MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
                 if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
@@ -340,4 +276,22 @@ public class WorkflowUtils {
             }
         }
     }
+
+    /**
+     * 根据任务id查询 当前用户的任务,检查 当前人员 是否是该 taskId 的办理人
+     *
+     * @param taskId 任务id
+     * @return 结果
+     */
+    public static Task getTaskByCurrentUser(String taskId) {
+        TaskQuery taskQuery = QueryUtils.taskQuery();
+        taskQuery.taskId(taskId).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId()));
+
+        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
+        if (CollUtil.isNotEmpty(roles)) {
+            List<String> groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
+            taskQuery.taskCandidateGroupIn(groupIds);
+        }
+        return taskQuery.singleResult();
+    }
 }

BIN
script/bpmn/模型.zip


+ 8 - 7
script/sql/flowable.sql

@@ -27,6 +27,7 @@ create table test_leave
     end_date     datetime                     not null comment '结束时间',
     leave_days  int(10)                      not null comment '请假天数',
     remark      varchar(255)                 null comment '请假原因',
+    status      varchar(255)                 null comment '状态',
     create_dept bigint                       null comment '创建部门',
     create_by   bigint                       null comment '创建者',
     create_time datetime                     null comment '创建时间',
@@ -112,7 +113,7 @@ create table wf_form_manage
 )
     comment '表单管理';
 
-insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/demo/leaveEdit/index', NULL, '000000', 103, 1, sysdate(), 1, sysdate());
+insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate(), 1, sysdate());
 
 create table wf_node_config
 (
@@ -134,12 +135,12 @@ create table wf_node_config
     comment '节点配置';
 
 
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'demo:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:query', '#', 103, 1, sysdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:add', '#', 103, 1, sysdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:export', '#', 103, 1, sysdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate(), NULL, NULL, '');
 
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate(), NULL, NULL, '业务状态列表');
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate(), NULL, NULL, '表单类型列表');

+ 9 - 7
script/sql/oracle/flowable.sql

@@ -30,6 +30,7 @@ create table TEST_LEAVE
     END_DATE    DATE,
     LEAVE_DAYS  NUMBER(10),
     REMARK      VARCHAR2(255),
+    STATUS      VARCHAR2(255),
     CREATE_DEPT NUMBER(20),
     CREATE_BY   NUMBER(20),
     CREATE_TIME DATE,
@@ -45,6 +46,7 @@ comment on column TEST_LEAVE.START_DATE is '开始时间';
 comment on column TEST_LEAVE.END_DATE is '结束时间';
 comment on column TEST_LEAVE.LEAVE_DAYS is '请假天数';
 comment on column TEST_LEAVE.REMARK is '请假原因';
+comment on column TEST_LEAVE.STATUS is '状态';
 comment on column TEST_LEAVE.CREATE_DEPT is '创建部门';
 comment on column TEST_LEAVE.CREATE_BY is '创建者';
 comment on column TEST_LEAVE.CREATE_TIME is '创建时间';
@@ -182,7 +184,7 @@ comment on column WF_FORM_MANAGE.CREATE_TIME is '创建时间';
 comment on column WF_FORM_MANAGE.UPDATE_BY is '更新者';
 comment on column WF_FORM_MANAGE.UPDATE_TIME is '更新时间';
 
-insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/demo/leaveEdit/index', NULL, '000000', 103, 1, sysdate, 1, sysdate);
+insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate, 1, sysdate);
 
 create table WF_NODE_CONFIG
 (
@@ -218,12 +220,12 @@ comment on column WF_NODE_CONFIG.CREATE_TIME is '创建时间';
 comment on column WF_NODE_CONFIG.UPDATE_BY is '更新者';
 comment on column WF_NODE_CONFIG.UPDATE_TIME is '更新时间';
 
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'demo:leave:list', '#', 103, 1, sysdate, NULL, NULL, '请假申请菜单');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:query', '#', 103, 1, sysdate, NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:add', '#', 103, 1, sysdate, NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:edit', '#', 103, 1, sysdate, NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:remove', '#', 103, 1, sysdate, NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:export', '#', 103, 1, sysdate, NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate, NULL, NULL, '请假申请菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate, NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate, NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate, NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate, NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate, NULL, NULL, '');
 
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate, NULL, NULL, '业务状态列表');
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate, NULL, NULL, '表单类型列表');

+ 0 - 1
script/sql/oracle/oracle_ry_vue_5.X.sql

@@ -443,7 +443,6 @@ insert into sys_menu values('107',  '通知公告',     '1',   '8', 'notice',
 insert into sys_menu values('108',  '日志管理',     '1',   '9', 'log',              '',                             '', 1, 0, 'M', '0', '0', '',                            'log',           103, 1, sysdate, null, null, '日志管理菜单');
 insert into sys_menu values('109',  '在线用户',     '2',   '1', 'online',           'monitor/online/index',         '', 1, 0, 'C', '0', '0', 'monitor:online:list',         'online',        103, 1, sysdate, null, null, '在线用户菜单');
 insert into sys_menu values('113',  '缓存监控',     '2',   '5', 'cache',            'monitor/cache/index',          '', 1, 0, 'C', '0', '0', 'monitor:cache:list',          'redis',         103, 1, sysdate, null, null, '缓存监控菜单');
-insert into sys_menu values('114',  '表单构建',     '3',   '1', 'build',            'tool/build/index',             '', 1, 0, 'C', '0', '0', 'tool:build:list',             'build',         103, 1, sysdate, null, null, '表单构建菜单');
 insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',              'tool/gen/index',               '', 1, 0, 'C', '0', '0', 'tool:gen:list',               'code',          103, 1, sysdate, null, null, '代码生成菜单');
 insert into sys_menu values('121',  '租户管理',     '6',   '1', 'tenant',           'system/tenant/index',          '', 1, 0, 'C', '0', '0', 'system:tenant:list',          'list',          103, 1, sysdate, null, null, '租户管理菜单');
 insert into sys_menu values('122',  '租户套餐管理', '6',   '2', 'tenantPackage',    'system/tenantPackage/index',   '', 1, 0, 'C', '0', '0', 'system:tenantPackage:list',   'form',          103, 1, sysdate, null, null, '租户套餐管理菜单');

+ 10 - 7
script/sql/postgres/flowable.sql

@@ -29,6 +29,7 @@ create table test_leave
     end_date    timestamp,
     leave_days  bigint,
     remark      varchar(255),
+    status      varchar(255),
     create_dept bigint,
     create_by   bigint,
     create_time timestamp,
@@ -49,6 +50,8 @@ comment on column test_leave.end_date is '结束时间';
 
 comment on column test_leave.remark is '请假原因';
 
+comment on column test_leave.status is '状态';
+
 comment on column test_leave.create_dept is '创建部门';
 
 comment on column test_leave.create_by is '创建者';
@@ -251,7 +254,7 @@ comment on column wf_form_manage.update_by is '修改者';
 
 comment on column wf_form_manage.update_time is '修改时间';
 
-insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/demo/leaveEdit/index', NULL, '000000', 103, 1, now(), 1, now());
+insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, now(), 1, now());
 
 create table wf_node_config
 (
@@ -300,12 +303,12 @@ comment on column wf_node_config.update_by is '修改者';
 
 comment on column wf_node_config.update_time is '修改时间';
 
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'demo:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:query', '#', 103, 1, now(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:add', '#', 103, 1, now(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:edit', '#', 103, 1, now(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:remove', '#', 103, 1, now(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:export', '#', 103, 1, now(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, now(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, now(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, now(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, now(), NULL, NULL, '');
 
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, now(), NULL, NULL, '业务状态列表');
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, now(), NULL, NULL, '表单类型列表');

+ 0 - 1
script/sql/postgres/postgres_ry_vue_5.X.sql

@@ -444,7 +444,6 @@ insert into sys_menu values('107',  '通知公告',     '1',   '8', 'notice',
 insert into sys_menu values('108',  '日志管理',     '1',   '9', 'log',              '',                             '', '1', '0', 'M', '0', '0', '',                            'log',           103, 1, now(), null, null, '日志管理菜单');
 insert into sys_menu values('109',  '在线用户',     '2',   '1', 'online',           'monitor/online/index',         '', '1', '0', 'C', '0', '0', 'monitor:online:list',         'online',        103, 1, now(), null, null, '在线用户菜单');
 insert into sys_menu values('113',  '缓存监控',     '2',   '5', 'cache',            'monitor/cache/index',          '', '1', '0', 'C', '0', '0', 'monitor:cache:list',          'redis',         103, 1, now(), null, null, '缓存监控菜单');
-insert into sys_menu values('114',  '表单构建',     '3',   '1', 'build',            'tool/build/index',             '', '1', '0', 'C', '0', '0', 'tool:build:list',             'build',         103, 1, now(), null, null, '表单构建菜单');
 insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',              'tool/gen/index',               '', '1', '0', 'C', '0', '0', 'tool:gen:list',               'code',          103, 1, now(), null, null, '代码生成菜单');
 insert into sys_menu values('121',  '租户管理',     '6',   '1', 'tenant',           'system/tenant/index',          '', '1', '0', 'C', '0', '0', 'system:tenant:list',          'list',          103, 1, now(), null, null, '租户管理菜单');
 insert into sys_menu values('122',  '租户套餐管理', '6',   '2', 'tenantPackage',    'system/tenantPackage/index',   '', '1', '0', 'C', '0', '0', 'system:tenantPackage:list',   'form',          103, 1, now(), null, null, '租户套餐管理菜单');

+ 0 - 1
script/sql/ry_vue_5.X.sql

@@ -278,7 +278,6 @@ insert into sys_menu values('107',  '通知公告',     '1',   '8', 'notice',
 insert into sys_menu values('108',  '日志管理',     '1',   '9', 'log',              '',                             '', 1, 0, 'M', '0', '0', '',                            'log',           103, 1, sysdate(), null, null, '日志管理菜单');
 insert into sys_menu values('109',  '在线用户',     '2',   '1', 'online',           'monitor/online/index',         '', 1, 0, 'C', '0', '0', 'monitor:online:list',         'online',        103, 1, sysdate(), null, null, '在线用户菜单');
 insert into sys_menu values('113',  '缓存监控',     '2',   '5', 'cache',            'monitor/cache/index',          '', 1, 0, 'C', '0', '0', 'monitor:cache:list',          'redis',         103, 1, sysdate(), null, null, '缓存监控菜单');
-insert into sys_menu values('114',  '表单构建',     '3',   '1', 'build',            'tool/build/index',             '', 1, 0, 'C', '0', '0', 'tool:build:list',             'build',         103, 1, sysdate(), null, null, '表单构建菜单');
 insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',              'tool/gen/index',               '', 1, 0, 'C', '0', '0', 'tool:gen:list',               'code',          103, 1, sysdate(), null, null, '代码生成菜单');
 insert into sys_menu values('121',  '租户管理',     '6',   '1', 'tenant',           'system/tenant/index',          '', 1, 0, 'C', '0', '0', 'system:tenant:list',          'list',          103, 1, sysdate(), null, null, '租户管理菜单');
 insert into sys_menu values('122',  '租户套餐管理',  '6',   '2', 'tenantPackage',    'system/tenantPackage/index',   '', 1, 0, 'C', '0', '0', 'system:tenantPackage:list',   'form',          103, 1, sysdate(), null, null, '租户套餐管理菜单');

+ 16 - 7
script/sql/sqlserver/flowable.sql

@@ -28,6 +28,7 @@ create table test_leave
     end_date    datetime2     not null,
     leave_days  int           not null,
     remark      nvarchar(255),
+    status      nvarchar(255),
     create_dept bigint,
     create_by   bigint,
     create_time datetime2,
@@ -61,6 +62,9 @@ go
 exec sp_addextendedproperty 'MS_Description', N'请假原因', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'remark'
 go
 
+exec sp_addextendedproperty 'MS_Description', N'状态', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'status'
+go
+
 exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
      'create_dept'
 go
@@ -221,6 +225,7 @@ create table wf_definition_config
         unique,
     process_key   nvarchar(255)  not null,
     version       bigint         not null,
+    remark        nvarchar(500) DEFAULT ('') null,
     tenant_id     nvarchar(20),
     create_dept   bigint,
     create_by     bigint,
@@ -252,6 +257,10 @@ exec sp_addextendedproperty 'MS_Description', N'流程版本', 'SCHEMA', 'dbo',
      'version'
 go
 
+exec sp_addextendedproperty 'MS_Description', N'备注', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
+     'remark'
+go
+
 exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
      'tenant_id'
 go
@@ -334,7 +343,7 @@ exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo',
      'update_time'
 go
 
-insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/demo/leaveEdit/index', NULL, '000000', 103, 1, getdate(), 1, getdate());
+insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, getdate(), 1, getdate());
 
 create table wf_node_config
 (
@@ -406,12 +415,12 @@ exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo',
      'update_time'
 go
 
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'demo:leave:list', '#', 103, 1, getdate(), NULL, NULL, '请假申请菜单');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:query', '#', 103, 1, getdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:add', '#', 103, 1, getdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:edit', '#', 103, 1, getdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:remove', '#', 103, 1, getdate(), NULL, NULL, '');
-INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:leave:export', '#', 103, 1, getdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, getdate(), NULL, NULL, '请假申请菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, getdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, getdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, getdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, getdate(), NULL, NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, getdate(), NULL, NULL, '');
 
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, getdate(), NULL, NULL, '业务状态列表');
 INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, getdate(), NULL, NULL, '表单类型列表');

+ 0 - 2
script/sql/sqlserver/sqlserver_ry_vue_5.X.sql

@@ -1678,8 +1678,6 @@ INSERT sys_menu VALUES (109, N'在线用户', 2, 1, N'online', N'monitor/online/
 GO
 INSERT sys_menu VALUES (113, N'缓存监控', 2, 5, N'cache', N'monitor/cache/index', N'', 1, 0, N'C', N'0', N'0', N'monitor:cache:list', N'redis', 103, 1, getdate(), NULL, NULL, N'缓存监控菜单')
 GO
-INSERT sys_menu VALUES (114, N'表单构建', 3, 1, N'build', N'tool/build/index', N'', 1, 0, N'C', N'0', N'0', N'tool:build:list', N'build', 103, 1, getdate(), NULL, NULL, N'表单构建菜单')
-GO
 INSERT sys_menu VALUES (115, N'代码生成', 3, 2, N'gen', N'tool/gen/index', N'', 1, 0, N'C', N'0', N'0', N'tool:gen:list', N'code', 103, 1, getdate(), NULL, NULL, N'代码生成菜单')
 GO
 INSERT sys_menu VALUES (121, N'租户管理', 6, 1, N'tenant', N'system/tenant/index', N'', 1, 0, N'C', N'0', N'0', N'system:tenant:list', N'code', 103, 1, getdate(), NULL, NULL, N'租户管理菜单')

+ 1 - 1
script/sql/update/oracle/update_5.1.2-5.2.0.sql

@@ -6,4 +6,4 @@ ALTER TABLE sys_post ADD (post_category VARCHAR2(100) DEFAULT NULL) COMMENT '岗
 COMMENT ON COLUMN sys_post.post_category IS '岗位类别编码';
 UPDATE sys_post SET dept_id = 100;
 UPDATE sys_post SET dept_id = 103 where post_id = 1;
-UPDATE sys_menu SET path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;
+UPDATE sys_menu SET menu_name = 'SnailJob控制台', path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;

+ 1 - 1
script/sql/update/postgres/update_5.1.2-5.2.0.sql

@@ -6,4 +6,4 @@ ALTER TABLE sys_post ADD COLUMN post_category varchar(100) default null::varchar
 COMMENT ON COLUMN sys_post.post_category IS '岗位类别编码';
 UPDATE sys_post SET dept_id = 100;
 UPDATE sys_post SET dept_id = 103 where post_id = 1;
-UPDATE sys_menu SET path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;
+UPDATE sys_menu SET menu_name = 'SnailJob控制台', path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;

+ 2 - 2
script/sql/update/sqlserver/update_5.1.2-5.2.0.sql

@@ -25,5 +25,5 @@ UPDATE sys_post SET dept_id = 100
 GO
 UPDATE sys_post SET dept_id = 103 where post_id = 1
 GO
-UPDATE sys_menu SET path = N'snailjob', component = N'monitor/snailjob/index', perms = N'monitor:snailjob:list', remark = N'SnailJob控制台菜单' WHERE menu_id = 120
-GO
+UPDATE sys_menu SET menu_name = N'SnailJob控制台', path = N'snailjob', component = N'monitor/snailjob/index', perms = N'monitor:snailjob:list', remark = N'SnailJob控制台菜单' WHERE menu_id = 120
+GO

+ 1 - 1
script/sql/update/update_5.1.2-5.2.0.sql

@@ -2,4 +2,4 @@ ALTER TABLE sys_dept ADD dept_category VARCHAR(100) DEFAULT NULL COMMENT '部门
 ALTER TABLE sys_post ADD dept_id BIGINT(20) NOT NULL COMMENT '部门id', ADD post_category VARCHAR(100) DEFAULT NULL COMMENT '岗位类别编码';
 UPDATE sys_post SET dept_id = 100;
 UPDATE sys_post SET dept_id = 103 where post_id = 1;
-UPDATE sys_menu SET path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;
+UPDATE sys_menu SET menu_name = 'SnailJob控制台', path = 'snailjob', component = 'monitor/snailjob/index', perms = 'monitor:snailjob:list', remark = 'SnailJob控制台菜单' WHERE menu_id = 120;