Explorar o código

!712 发布 5.4.1 小步迭代修复问题
Merge pull request !712 from 疯狂的狮子Li/dev

疯狂的狮子Li hai 1 ano
pai
achega
64100cf1ff
Modificáronse 86 ficheiros con 893 adicións e 477 borrados
  1. 1 1
      .run/ruoyi-monitor-admin.run.xml
  2. 1 1
      .run/ruoyi-server.run.xml
  3. 1 1
      .run/ruoyi-snailjob-server.run.xml
  4. 1 1
      README.md
  5. 11 12
      pom.xml
  6. 2 2
      ruoyi-admin/Dockerfile
  7. 1 1
      ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java
  8. 0 12
      ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java
  9. 1 1
      ruoyi-admin/src/main/resources/application.yml
  10. 1 1
      ruoyi-common/ruoyi-common-bom/pom.xml
  11. 5 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java
  12. 27 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java
  13. 40 13
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java
  14. 13 1
      ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java
  15. 1 5
      ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java
  16. 1 5
      ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java
  17. 23 35
      ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java
  18. 12 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java
  19. 2 0
      ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java
  20. 154 0
      ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java
  21. 2 2
      ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java
  22. 1 1
      ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java
  23. 16 0
      ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/ResourcesConfig.java
  24. 2 2
      ruoyi-extend/ruoyi-monitor-admin/Dockerfile
  25. 3 3
      ruoyi-extend/ruoyi-snailjob-server/Dockerfile
  26. 4 4
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/BoundedQueueController.java
  27. 2 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/DelayedQueueController.java
  28. 2 0
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java
  29. 2 0
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityQueueController.java
  30. 5 0
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/TestDemoBo.java
  31. 9 1
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java
  32. 7 10
      ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/controller/GenController.java
  33. 3 3
      ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java
  34. 8 4
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/CacheController.java
  35. 4 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysConfigController.java
  36. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java
  37. 8 7
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictDataController.java
  38. 4 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictTypeController.java
  39. 9 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java
  40. 10 4
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java
  41. 3 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java
  42. 2 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMenuMapper.java
  43. 13 5
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java
  44. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysConfigService.java
  45. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictDataService.java
  46. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictTypeService.java
  47. 4 16
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java
  48. 15 24
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java
  49. 11 17
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java
  50. 13 18
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java
  51. 14 14
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java
  52. 5 4
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java
  53. 5 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java
  54. 28 10
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java
  55. 0 26
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
  56. 0 11
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
  57. 0 31
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
  58. 5 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
  59. 2 1
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java
  60. 5 10
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java
  61. 0 2
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TestLeaveVo.java
  62. 3 1
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java
  63. 0 1
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java
  64. 1 7
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java
  65. 17 28
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java
  66. 247 0
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java
  67. 4 8
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java
  68. 4 4
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java
  69. 15 11
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java
  70. 6 3
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java
  71. 2 2
      ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java
  72. 0 4
      ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml
  73. 4 4
      script/docker/docker-compose.yml
  74. 1 1
      script/sql/oracle/oracle_ry_job.sql
  75. 4 4
      script/sql/oracle/oracle_ry_vue_5.X.sql
  76. 5 5
      script/sql/oracle/oracle_ry_workflow.sql
  77. 4 4
      script/sql/postgres/postgres_ry_vue_5.X.sql
  78. 6 7
      script/sql/postgres/postgres_ry_workflow.sql
  79. 4 4
      script/sql/ry_vue_5.X.sql
  80. 10 10
      script/sql/ry_workflow.sql
  81. 5 5
      script/sql/sqlserver/sqlserver_ry_vue_5.X.sql
  82. 5 4
      script/sql/sqlserver/sqlserver_ry_workflow.sql
  83. 4 4
      script/sql/update/oracle/update_5.3.1-5.4.0.sql
  84. 4 4
      script/sql/update/postgres/update_5.3.1-5.4.0.sql
  85. 4 4
      script/sql/update/sqlserver/update_5.3.1-5.4.0.sql
  86. 4 4
      script/sql/update/update_5.3.1-5.4.0.sql

+ 1 - 1
.run/ruoyi-monitor-admin.run.xml

@@ -2,7 +2,7 @@
   <configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
     <deployment type="dockerfile">
       <settings>
-        <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.4.0" />
+        <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.4.1" />
         <option name="buildOnly" value="true" />
         <option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
       </settings>

+ 1 - 1
.run/ruoyi-server.run.xml

@@ -2,7 +2,7 @@
   <configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
     <deployment type="dockerfile">
       <settings>
-        <option name="imageTag" value="ruoyi/ruoyi-server:5.4.0" />
+        <option name="imageTag" value="ruoyi/ruoyi-server:5.4.1" />
         <option name="buildOnly" value="true" />
         <option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
       </settings>

+ 1 - 1
.run/ruoyi-snailjob-server.run.xml

@@ -2,7 +2,7 @@
   <configuration default="false" name="ruoyi-snailjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
     <deployment type="dockerfile">
       <settings>
-        <option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.4.0" />
+        <option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.4.1" />
         <option name="buildOnly" value="true" />
         <option name="sourceFilePath" value="ruoyi-extend/ruoyi-snailjob-server/Dockerfile" />
       </settings>

+ 1 - 1
README.md

@@ -10,7 +10,7 @@
 [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/5.X/LICENSE)
 [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
 <br>
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.4.0-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus)
+[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.4.1-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus)
 [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4-blue.svg)]()
 [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]()
 [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]()

+ 11 - 12
pom.xml

@@ -13,8 +13,8 @@
     <description>Dromara RuoYi-Vue-Plus多租户管理系统</description>
 
     <properties>
-        <revision>5.4.0</revision>
-        <spring-boot.version>3.4.6</spring-boot.version>
+        <revision>5.4.1</revision>
+        <spring-boot.version>3.4.7</spring-boot.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>17</java.version>
@@ -23,12 +23,12 @@
         <therapi-javadoc.version>0.15.0</therapi-javadoc.version>
         <fastexcel.version>1.2.0</fastexcel.version>
         <velocity.version>2.3</velocity.version>
-        <satoken.version>1.42.0</satoken.version>
+        <satoken.version>1.44.0</satoken.version>
         <mybatis-plus.version>3.5.12</mybatis-plus.version>
         <p6spy.version>3.9.1</p6spy.version>
-        <hutool.version>5.8.35</hutool.version>
+        <hutool.version>5.8.38</hutool.version>
         <spring-boot-admin.version>3.4.7</spring-boot-admin.version>
-        <redisson.version>3.45.1</redisson.version>
+        <redisson.version>3.50.0</redisson.version>
         <lock4j.version>2.2.7</lock4j.version>
         <dynamic-ds.version>4.3.1</dynamic-ds.version>
         <snailjob.version>1.5.0</snailjob.version>
@@ -39,7 +39,6 @@
         <justauth.version>1.16.7</justauth.version>
         <!-- 离线IP地址定位库 -->
         <ip2region.version>2.7.0</ip2region.version>
-
         <!-- OSS 配置 -->
         <aws.sdk.version>2.28.22</aws.sdk.version>
         <!-- SMS 配置 -->
@@ -47,15 +46,15 @@
         <!-- 限制框架中的fastjson版本 -->
         <fastjson.version>1.2.83</fastjson.version>
         <!-- 面向运行时的D-ORM依赖 -->
-        <anyline.version>8.7.2-20250101</anyline.version>
+        <anyline.version>8.7.2-20250603</anyline.version>
         <!-- 工作流配置 -->
-        <warm-flow.version>1.7.3</warm-flow.version>
+        <warm-flow.version>1.7.4</warm-flow.version>
 
         <!-- 插件版本 -->
-        <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
-        <maven-war-plugin.version>3.2.2</maven-war-plugin.version>
-        <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
-        <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
+        <maven-jar-plugin.version>3.4.2</maven-jar-plugin.version>
+        <maven-war-plugin.version>3.4.0</maven-war-plugin.version>
+        <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
+        <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
         <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
         <!-- 打包默认跳过测试 -->
         <skipTests>true</skipTests>

+ 2 - 2
ruoyi-admin/Dockerfile

@@ -1,6 +1,6 @@
 # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
-FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
-#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
+FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
+#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
 #FROM findepi/graalvm:java17-native
 
 LABEL maintainer="Lion Li"

+ 1 - 1
ruoyi-admin/src/main/java/org/dromara/web/listener/UserActionListener.java

@@ -158,6 +158,6 @@ public class UserActionListener implements SaTokenListener {
      * 每次Token续期时触发
      */
     @Override
-    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
+    public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
     }
 }

+ 0 - 12
ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java

@@ -3,10 +3,7 @@ package org.dromara.web.service.impl;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.dev33.satoken.stp.parameter.SaLoginParameter;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.http.HttpUtil;
-import cn.hutool.http.Method;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.zhyd.oauth.model.AuthResponse;
@@ -68,15 +65,6 @@ public class SocialAuthStrategy implements IAuthStrategy {
             throw new ServiceException(response.getMsg());
         }
         AuthUser authUserData = response.getData();
-        if ("GITEE".equals(authUserData.getSource())) {
-            // 如用户使用 gitee 登录顺手 star 给作者一点支持 拒绝白嫖
-            HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Vue-Plus")
-                    .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
-                    .executeAsync();
-            HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Cloud-Plus")
-                    .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
-                    .executeAsync();
-        }
 
         List<SysSocialVo> list = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
         if (CollUtil.isEmpty(list)) {

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

@@ -183,7 +183,7 @@ springdoc:
     # 描述
     description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
     # 版本
-    version: '版本号: ${ruoyi.version}'
+    version: '版本号: ${project.version}'
     # 作者信息
     contact:
       name: Lion Li

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

@@ -14,7 +14,7 @@
     </description>
 
     <properties>
-        <revision>5.4.0</revision>
+        <revision>5.4.1</revision>
     </properties>
 
     <dependencyManagement>

+ 5 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java

@@ -77,4 +77,9 @@ public interface SystemConstants {
      */
     String ROOT_DEPT_ANCESTORS = "0";
 
+    /**
+     * 默认部门 ID
+     */
+    Long DEFAULT_DEPT_ID = 100L;
+
 }

+ 27 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java

@@ -10,6 +10,8 @@ import lombok.NoArgsConstructor;
 import org.dromara.common.core.utils.reflect.ReflectUtils;
 
 import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -60,6 +62,31 @@ public class TreeBuildUtils extends TreeUtil {
         return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser);
     }
 
+    /**
+     * 构建多根节点的树结构(支持多个顶级节点)
+     *
+     * @param list        原始数据列表
+     * @param getId       获取节点 ID 的方法引用,例如:node -> node.getId()
+     * @param getParentId 获取节点父级 ID 的方法引用,例如:node -> node.getParentId()
+     * @param parser      树节点属性映射器,用于将原始节点 T 转为 Tree 节点
+     * @param <T>         原始数据类型(如实体类、DTO 等)
+     * @param <K>         节点 ID 类型(如 Long、String)
+     * @return 构建完成的树形结构(可能包含多个顶级根节点)
+     */
+    public static <T, K> List<Tree<K>> buildMultiRoot(List<T> list, Function<T, K> getId, Function<T, K> getParentId, NodeParser<T, K> parser) {
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+
+        Set<K> rootParentIds = StreamUtils.toSet(list, getParentId);
+        rootParentIds.removeAll(StreamUtils.toSet(list, getId));
+
+        // 构建每一个根 parentId 下的树,并合并成最终结果列表
+        return rootParentIds.stream()
+            .flatMap(rootParentId -> TreeUtil.build(list, rootParentId, parser).stream())
+            .collect(Collectors.toList());
+    }
+
     /**
      * 获取节点列表中所有节点的叶子节点
      *

+ 40 - 13
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java

@@ -16,28 +16,55 @@ import org.dromara.common.core.utils.StringUtils;
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class AddressUtils {
 
+    // 未知IP
+    public static final String UNKNOWN_IP = "XX XX";
+    // 内网地址
+    public static final String LOCAL_ADDRESS = "内网IP";
     // 未知地址
-    public static final String UNKNOWN = "XX XX";
+    public static final String UNKNOWN_ADDRESS = "未知";
 
     public static String getRealAddressByIP(String ip) {
         // 处理空串并过滤HTML标签
         ip = HtmlUtil.cleanHtmlTag(StringUtils.blankToDefault(ip,""));
-        boolean isIPv6 = NetUtils.isIPv6(ip);
-        // 判断是否为IPv4或IPv6,如果不是则返回未知地址
-        if (!NetUtils.isIPv4(ip) && !isIPv6) {
-            return UNKNOWN;
+        // 判断是否为IPv4
+        if (NetUtils.isIPv4(ip)) {
+            return resolverIPv4Region(ip);
         }
-        // 内网不查询
-        if (NetUtils.isInnerIPv6(ip) || NetUtils.isInnerIP(ip)) {
-            return "内网IP";
+        // 判断是否为IPv6
+        if (NetUtils.isIPv6(ip)) {
+            return resolverIPv6Region(ip);
         }
-        // 不支持IPv6,不再进行没有必要的IP地址信息的解析,直接返回
-        if (isIPv6) {
-            log.warn("ip2region不支持IPV6地址解析:{}", ip);
-            // 如有需要,可自行实现IPv6地址信息解析逻辑,并在这里返回
-            return "未知";
+        // 如果不是IPv4或IPv6,则返回未知IP
+        return UNKNOWN_IP;
+    }
+
+    /**
+     * 根据IPv4地址查询IP归属行政区域
+     * @param ip ipv4地址
+     * @return 归属行政区域
+     */
+    private static String resolverIPv4Region(String ip){
+        // 内网不查询
+        if (NetUtils.isInnerIP(ip)) {
+            return LOCAL_ADDRESS;
         }
         return RegionUtils.getCityInfo(ip);
     }
 
+    /**
+     * 根据IPv6地址查询IP归属行政区域
+     * @param ip ipv6地址
+     * @return 归属行政区域
+     */
+    private static String resolverIPv6Region(String ip){
+        // 内网不查询
+        if (NetUtils.isInnerIPv6(ip)) {
+            return LOCAL_ADDRESS;
+        }
+        log.warn("ip2region不支持IPV6地址解析:{}", ip);
+        // 不支持IPv6,不再进行没有必要的IP地址信息的解析,直接返回
+        // 如有需要,可自行实现IPv6地址信息解析逻辑,并在这里返回
+        return UNKNOWN_ADDRESS;
+    }
+
 }

+ 13 - 1
ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java

@@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.ObjectUtil;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.executor.parameter.ParameterHandler;
 import org.apache.ibatis.executor.resultset.ResultSetHandler;
 import org.apache.ibatis.plugin.*;
 import org.dromara.common.core.utils.StringUtils;
@@ -39,12 +40,23 @@ public class MybatisDecryptInterceptor implements Interceptor {
 
     @Override
     public Object intercept(Invocation invocation) throws Throwable {
+        // 开始进行参数解密
+        ResultSetHandler resultSetHandler = (ResultSetHandler) invocation.getTarget();
+        Field parameterHandlerField = resultSetHandler.getClass().getDeclaredField("parameterHandler");
+        parameterHandlerField.setAccessible(true);
+        Object target = parameterHandlerField.get(resultSetHandler);
+        if (target instanceof ParameterHandler parameterHandler) {
+            Object parameterObject = parameterHandler.getParameterObject();
+            if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) {
+                this.decryptHandler(parameterObject);
+            }
+        }
         // 获取执行mysql执行结果
         Object result = invocation.proceed();
         if (result == null) {
             return null;
         }
-        decryptHandler(result);
+        this.decryptHandler(result);
         return result;
     }
 

+ 1 - 5
ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java

@@ -6,17 +6,13 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * 批注
+ * 批注 此注解仅用于单表头 不支持多层级表头
  * @author guzhouyanyu
  */
 @Target({ElementType.FIELD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface ExcelNotation {
 
-    /**
-     * col index
-     */
-    int index() default -1;
     /**
      * 批注内容
      */

+ 1 - 5
ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java

@@ -8,17 +8,13 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * 是否必填
+ * 是否必填 此注解仅用于单表头 不支持多层级表头
  * @author guzhouyanyu
  */
 @Target({ElementType.FIELD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface ExcelRequired {
 
-    /**
-     * col index
-     */
-    int index() default -1;
     /**
      * 字体颜色
      */

+ 23 - 35
ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java

@@ -1,6 +1,7 @@
 package org.dromara.common.excel.handler;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.idev.excel.annotation.ExcelProperty;
 import cn.idev.excel.metadata.data.DataFormatData;
 import cn.idev.excel.metadata.data.WriteCellData;
 import cn.idev.excel.util.StyleUtil;
@@ -13,7 +14,6 @@ import cn.idev.excel.write.metadata.style.WriteFont;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
 import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.dromara.common.core.utils.reflect.ReflectUtils;
 import org.dromara.common.excel.annotation.ExcelNotation;
 import org.dromara.common.excel.annotation.ExcelRequired;
 
@@ -31,12 +31,12 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
     /**
      * 批注
      */
-    private final Map<Integer, String> notationMap;
+    private final Map<String, String> notationMap;
 
     /**
      * 头列字体颜色
      */
-    private final Map<Integer, Short> headColumnMap;
+    private final Map<String, Short> headColumnMap;
 
 
     public DataWriteHandler(Class<?> clazz) {
@@ -49,15 +49,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
         if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) {
             return;
         }
+        // 第一行
         WriteCellData<?> cellData = context.getFirstCellData();
+        // 第一个格子
         WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
 
-        DataFormatData dataFormatData = new DataFormatData();
-        // 单元格设置为文本格式
-        dataFormatData.setIndex((short) 49);
-        writeCellStyle.setDataFormatData(dataFormatData);
-
         if (context.getHead()) {
+            DataFormatData dataFormatData = new DataFormatData();
+            // 单元格设置为文本格式
+            dataFormatData.setIndex((short) 49);
+            writeCellStyle.setDataFormatData(dataFormatData);
             Cell cell = context.getCell();
             WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
             Sheet sheet = writeSheetHolder.getSheet();
@@ -67,17 +68,17 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
             WriteFont headWriteFont = new WriteFont();
             // 加粗
             headWriteFont.setBold(true);
-            if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getColumnIndex())) {
+            if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getStringCellValue())) {
                 // 设置字体颜色
-                headWriteFont.setColor(headColumnMap.get(cell.getColumnIndex()));
+                headWriteFont.setColor(headColumnMap.get(cell.getStringCellValue()));
             }
             writeCellStyle.setWriteFont(headWriteFont);
             CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle);
             cell.setCellStyle(cellStyle);
 
-            if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getColumnIndex())) {
+            if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getStringCellValue())) {
                 // 批注内容
-                String notationContext = notationMap.get(cell.getColumnIndex());
+                String notationContext = notationMap.get(cell.getStringCellValue());
                 // 创建绘图对象
                 Comment comment = drawing.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), 0, (short) 5, 5));
                 comment.setString(new XSSFRichTextString(notationContext));
@@ -89,23 +90,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
     /**
      * 获取必填列
      */
-    private static Map<Integer, Short> getRequiredMap(Class<?> clazz) {
-        Map<Integer, Short> requiredMap = new HashMap<>();
+    private static Map<String, Short> getRequiredMap(Class<?> clazz) {
+        Map<String, Short> requiredMap = new HashMap<>();
         Field[] fields = clazz.getDeclaredFields();
-        // 检查 fields 数组是否为空
-        if (fields.length == 0) {
-            return requiredMap;
-        }
-        Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName()));
-
-        for (int i = 0; i < filteredFields.length; i++) {
-            Field field = filteredFields[i];
+        for (Field field : fields) {
             if (!field.isAnnotationPresent(ExcelRequired.class)) {
                 continue;
             }
             ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class);
-            int columnIndex =  excelRequired.index() == -1 ? i : excelRequired.index();
-            requiredMap.put(columnIndex, excelRequired.fontColor().getIndex());
+            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+            requiredMap.put(excelProperty.value()[0], excelRequired.fontColor().getIndex());
         }
         return requiredMap;
     }
@@ -113,22 +107,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
     /**
      * 获取批注
      */
-    private static Map<Integer, String> getNotationMap(Class<?> clazz) {
-        Map<Integer, String> notationMap = new HashMap<>();
+    private static Map<String, String> getNotationMap(Class<?> clazz) {
+        Map<String, String> notationMap = new HashMap<>();
         Field[] fields = clazz.getDeclaredFields();
-        // 检查 fields 数组是否为空
-        if (fields.length == 0) {
-            return notationMap;
-        }
-        Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName()));
-        for (int i = 0; i < filteredFields.length; i++) {
-            Field field = filteredFields[i];
+        for (Field field : fields) {
             if (!field.isAnnotationPresent(ExcelNotation.class)) {
                 continue;
             }
             ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class);
-            int columnIndex =  excelNotation.index() == -1 ? i : excelNotation.index();
-            notationMap.put(columnIndex, excelNotation.value());
+            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+            notationMap.put(excelProperty.value()[0], excelNotation.value());
         }
         return notationMap;
     }

+ 12 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java

@@ -22,6 +22,11 @@ import java.util.Date;
 @Slf4j
 public class InjectionMetaObjectHandler implements MetaObjectHandler {
 
+    /**
+     * 如果用户不存在默认注入-1代表无用户
+     */
+    private static final Long DEFAULT_USER_ID = -1L;
+
     /**
      * 插入填充方法,用于在插入数据时自动填充实体对象中的创建时间、更新时间、创建人、更新人等信息
      *
@@ -45,6 +50,11 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
                         baseEntity.setCreateBy(userId);
                         baseEntity.setUpdateBy(userId);
                         baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), loginUser.getDeptId()));
+                    } else {
+                        // 填充创建人、更新人和创建部门信息
+                        baseEntity.setCreateBy(DEFAULT_USER_ID);
+                        baseEntity.setUpdateBy(DEFAULT_USER_ID);
+                        baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), DEFAULT_USER_ID));
                     }
                 }
             } else {
@@ -74,6 +84,8 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
                 Long userId = LoginHelper.getUserId();
                 if (ObjectUtil.isNotNull(userId)) {
                     baseEntity.setUpdateBy(userId);
+                } else {
+                    baseEntity.setUpdateBy(DEFAULT_USER_ID);
                 }
             } else {
                 this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
@@ -93,7 +105,6 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
         try {
             loginUser = LoginHelper.getLoginUser();
         } catch (Exception e) {
-            log.warn("自动注入警告 => 用户未登录");
             return null;
         }
         return loginUser;

+ 2 - 0
ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java

@@ -16,7 +16,9 @@ import java.util.function.Function;
  *
  * @author Lion Li
  * @version 3.6.0 新增
+ * @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
  */
+@Deprecated
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class QueueUtils {
 

+ 154 - 0
ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java

@@ -0,0 +1,154 @@
+package me.zhyd.oauth.request;
+
+import com.alibaba.fastjson.JSONObject;
+import me.zhyd.oauth.cache.AuthStateCache;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.config.AuthSource;
+import me.zhyd.oauth.enums.AuthResponseStatus;
+import me.zhyd.oauth.enums.AuthUserGender;
+import me.zhyd.oauth.exception.AuthException;
+import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.model.AuthToken;
+import me.zhyd.oauth.model.AuthUser;
+import me.zhyd.oauth.utils.HttpUtils;
+import me.zhyd.oauth.utils.StringUtils;
+import me.zhyd.oauth.utils.UrlBuilder;
+
+/**
+ * <p>
+ * 企业微信登录父类
+ * </p>
+ *
+ * @author liguanhua (347826496(a)qq.com)
+ * @since 1.15.9
+ */
+public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultRequest {
+
+    public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source) {
+        super(config,source);
+    }
+
+
+    public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) {
+        super(config, source, authStateCache);
+    }
+
+    @Override
+    public AuthToken getAccessToken(AuthCallback authCallback) {
+        String response = doGetAuthorizationCode(accessTokenUrl(null));
+
+        JSONObject object = this.checkResponse(response);
+
+        return AuthToken.builder()
+            .accessToken(object.getString("access_token"))
+            .expireIn(object.getIntValue("expires_in"))
+            .code(authCallback.getCode())
+            .build();
+    }
+
+    @Override
+    public AuthUser getUserInfo(AuthToken authToken) {
+        String response = doGetUserInfo(authToken);
+        JSONObject object = this.checkResponse(response);
+
+        // 返回 OpenId 或其他,均代表非当前企业用户,不支持
+        // https://github.com/justauth/JustAuth/issues/227 修复bug
+        if (!object.containsKey("userid")) {
+            throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source);
+        }
+        String userId = object.getString("userid");
+        String userTicket = object.getString("user_ticket");
+        JSONObject userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket);
+
+        return AuthUser.builder()
+            .rawUserInfo(userDetail)
+            .username(userDetail.getString("name"))
+            .nickname(userDetail.getString("alias"))
+            .avatar(userDetail.getString("avatar"))
+            .location(userDetail.getString("address"))
+            .email(userDetail.getString("email"))
+            .uuid(userId)
+            .gender(AuthUserGender.getWechatRealGender(userDetail.getString("gender")))
+            .token(authToken)
+            .source(source.toString())
+            .build();
+    }
+
+    /**
+     * 校验请求结果
+     *
+     * @param response 请求结果
+     * @return 如果请求结果正常,则返回JSONObject
+     */
+    private JSONObject checkResponse(String response) {
+        JSONObject object = JSONObject.parseObject(response);
+
+        if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
+            throw new AuthException(object.getString("errmsg"), source);
+        }
+
+        return object;
+    }
+
+
+    /**
+     * 返回获取accessToken的url
+     *
+     * @param code 授权码
+     * @return 返回获取accessToken的url
+     */
+    @Override
+    protected String accessTokenUrl(String code) {
+        return UrlBuilder.fromBaseUrl(source.accessToken())
+            .queryParam("corpid", config.getClientId())
+            .queryParam("corpsecret", config.getClientSecret())
+            .build();
+    }
+
+    /**
+     * 返回获取userInfo的url
+     *
+     * @param authToken 用户授权后的token
+     * @return 返回获取userInfo的url
+     */
+    @Override
+    protected String userInfoUrl(AuthToken authToken) {
+        return UrlBuilder.fromBaseUrl(source.userInfo())
+            .queryParam("access_token", authToken.getAccessToken())
+            .queryParam("code", authToken.getCode())
+            .build();
+    }
+
+    /**
+     * 用户详情
+     *
+     * @param accessToken accessToken
+     * @param userId      企业内用户id
+     * @param userTicket  成员票据,用于获取用户信息或敏感信息
+     * @return 用户详情
+     */
+    private JSONObject getUserDetail(String accessToken, String userId, String userTicket) {
+        // 用户基础信息
+        String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
+            .queryParam("access_token", accessToken)
+            .queryParam("userid", userId)
+            .build();
+        String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
+        JSONObject userInfo = checkResponse(userInfoResponse);
+
+        // 用户敏感信息
+        if (StringUtils.isNotEmpty(userTicket)) {
+            String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail")
+                .queryParam("access_token", accessToken)
+                .build();
+            JSONObject param = new JSONObject();
+            param.put("user_ticket", userTicket);
+            String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, param.toJSONString()).getBody();
+            JSONObject userDetail = checkResponse(userDetailResponse);
+
+            userInfo.putAll(userDetail);
+        }
+        return userInfo;
+    }
+
+}

+ 2 - 2
ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java

@@ -38,8 +38,8 @@ public class SseEmitterManager {
         // 每个用户可以有多个 SSE 连接,通过 token 进行区分
         Map<String, SseEmitter> emitters = USER_TOKEN_EMITTERS.computeIfAbsent(userId, k -> new ConcurrentHashMap<>());
 
-        // 创建一个新的 SseEmitter 实例,超时时间设置为 0 表示无限制
-        SseEmitter emitter = new SseEmitter(0L);
+        // 创建一个新的 SseEmitter 实例,超时时间设置为一天 避免连接之后直接关闭浏览器导致连接停滞
+        SseEmitter emitter = new SseEmitter(86400000L);
 
         emitters.put(token, emitter);
 

+ 1 - 1
ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java

@@ -48,7 +48,7 @@ public class PlusTenantLineHandler implements TenantLineHandler {
                 "gen_table_column"
             );
             tables.addAll(excludes);
-            return StringUtils.containsAnyIgnoreCase(tableName, tables.toArray(new String[0]));
+            return StringUtils.equalsAnyIgnoreCase(tableName, tables.toArray(new String[0]));
         }
         return true;
     }

+ 16 - 0
ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/ResourcesConfig.java

@@ -1,9 +1,12 @@
 package org.dromara.common.web.config;
 
+import cn.hutool.core.date.DateUtil;
+import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.web.handler.GlobalExceptionHandler;
 import org.dromara.common.web.interceptor.PlusWebInvokeTimeInterceptor;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.context.annotation.Bean;
+import org.springframework.format.FormatterRegistry;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.filter.CorsFilter;
@@ -11,6 +14,8 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
+import java.util.Date;
+
 /**
  * 通用配置
  *
@@ -25,6 +30,17 @@ public class ResourcesConfig implements WebMvcConfigurer {
         registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
     }
 
+    @Override
+    public void addFormatters(FormatterRegistry registry) {
+        // 全局日期格式转换配置
+        registry.addConverter(String.class, Date.class, source -> {
+            if (StringUtils.isBlank(source)) {
+                return null;
+            }
+            return DateUtil.parse(source);
+        });
+    }
+
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
     }

+ 2 - 2
ruoyi-extend/ruoyi-monitor-admin/Dockerfile

@@ -1,6 +1,6 @@
 # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
-FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
-#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
+FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
+#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
 #FROM findepi/graalvm:java17-native
 
 LABEL maintainer="Lion Li"

+ 3 - 3
ruoyi-extend/ruoyi-snailjob-server/Dockerfile

@@ -1,6 +1,6 @@
 # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
-FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
-#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
+FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
+#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
 #FROM findepi/graalvm:java17-native
 
 LABEL maintainer="Lion Li"
@@ -9,7 +9,7 @@ RUN mkdir -p /ruoyi/snailjob/logs
 
 WORKDIR /ruoyi/snailjob
 
-ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="-Xms512m -Xmx1024m"
+ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
 
 EXPOSE 8800
 EXPOSE 17888

+ 4 - 4
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/BoundedQueueController.java

@@ -1,11 +1,9 @@
 package org.dromara.demo.controller.queue;
 
-import cn.dev33.satoken.annotation.SaIgnore;
-import org.dromara.common.core.domain.R;
-import org.dromara.common.redis.utils.QueueUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RBoundedBlockingQueue;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.redis.utils.QueueUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -20,7 +18,9 @@ import org.springframework.web.bind.annotation.RestController;
  *
  * @author Lion Li
  * @version 3.6.0
+ * @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
  */
+@Deprecated
 @Slf4j
 @RequiredArgsConstructor
 @RestController

+ 2 - 2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/DelayedQueueController.java

@@ -1,6 +1,5 @@
 package org.dromara.demo.controller.queue;
 
-import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.domain.R;
@@ -23,8 +22,9 @@ import java.util.concurrent.TimeUnit;
  *
  * @author Lion Li
  * @version 3.6.0
+ * @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
  */
-@SaIgnore
+@Deprecated
 @Slf4j
 @RequiredArgsConstructor
 @RestController

+ 2 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java

@@ -8,7 +8,9 @@ import lombok.NoArgsConstructor;
  *
  * @author Lion Li
  * @version 3.6.0
+ * @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
  */
+@Deprecated
 @Data
 @NoArgsConstructor
 public class PriorityDemo implements Comparable<PriorityDemo> {

+ 2 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityQueueController.java

@@ -19,7 +19,9 @@ import org.springframework.web.bind.annotation.RestController;
  *
  * @author Lion Li
  * @version 3.6.0
+ * @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
  */
+@Deprecated
 @Slf4j
 @RequiredArgsConstructor
 @RestController

+ 5 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/TestDemoBo.java

@@ -59,4 +59,9 @@ public class TestDemoBo extends BaseEntity {
     @NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class})
     private String value;
 
+    /**
+     * 版本
+     */
+    private Long version;
+
 }

+ 9 - 1
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java

@@ -2,6 +2,7 @@ package org.dromara.demo.domain.vo;
 
 import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
 import cn.idev.excel.annotation.ExcelProperty;
+import cn.idev.excel.annotation.format.DateTimeFormat;
 import org.dromara.common.excel.annotation.ExcelNotation;
 import org.dromara.common.excel.annotation.ExcelRequired;
 import org.dromara.common.translation.annotation.Translation;
@@ -46,7 +47,7 @@ public class TestDemoVo implements Serializable {
      * 用户id
      */
     @ExcelRequired
-    @ExcelProperty(value = "用户id")
+    @ExcelProperty(value = "用户id", index = 5)
     private Long userId;
 
     /**
@@ -73,6 +74,8 @@ public class TestDemoVo implements Serializable {
     /**
      * 创建时间
      */
+    @ExcelRequired
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
     @ExcelProperty(value = "创建时间")
     private Date createTime;
 
@@ -108,4 +111,9 @@ public class TestDemoVo implements Serializable {
     @ExcelProperty(value = "更新人账号")
     private String updateByName;
 
+    /**
+     * 版本
+     */
+    private Long version;
+
 }

+ 7 - 10
ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/controller/GenController.java

@@ -3,21 +3,21 @@ package org.dromara.generator.controller;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.IoUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
-import org.dromara.common.mybatis.helper.DataBaseHelper;
-import org.dromara.common.web.core.BaseController;
-import org.dromara.common.mybatis.core.page.PageQuery;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.log.annotation.Log;
 import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.helper.DataBaseHelper;
+import org.dromara.common.web.core.BaseController;
 import org.dromara.generator.domain.GenTable;
 import org.dromara.generator.domain.GenTableColumn;
 import org.dromara.generator.service.IGenTableService;
-import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
@@ -80,11 +80,8 @@ public class GenController extends BaseController {
     @SaCheckPermission("tool:gen:list")
     @GetMapping(value = "/column/{tableId}")
     public TableDataInfo<GenTableColumn> columnList(@PathVariable("tableId") Long tableId) {
-        TableDataInfo<GenTableColumn> dataInfo = new TableDataInfo<>();
         List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
-        dataInfo.setRows(list);
-        dataInfo.setTotal(list.size());
-        return dataInfo;
+        return TableDataInfo.build(list);
     }
 
     /**

+ 3 - 3
ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java

@@ -297,13 +297,13 @@ public class GenTableServiceImpl implements IGenTableService {
         List<GenTableColumn> tableColumns = new ArrayList<>();
         columns.forEach((columnName, column) -> {
             GenTableColumn tableColumn = new GenTableColumn();
-            tableColumn.setIsPk(String.valueOf(column.isPrimaryKey()));
+            tableColumn.setIsPk(column.isPrimaryKey() ? "1" : "0");
             tableColumn.setColumnName(column.getName());
             tableColumn.setColumnComment(column.getComment());
             tableColumn.setColumnType(column.getOriginType().toLowerCase());
             tableColumn.setSort(column.getPosition());
-            tableColumn.setIsRequired(column.isNullable() == 0 ? "1" : "0");
-            tableColumn.setIsIncrement(column.isAutoIncrement() == -1 ? "0" : "1");
+            tableColumn.setIsRequired(column.isNullable() ? "1" : "0");
+            tableColumn.setIsIncrement(column.isAutoIncrement() ? "1" : "0");
             tableColumns.add(tableColumn);
         });
         return tableColumns;

+ 8 - 4
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/CacheController.java

@@ -6,6 +6,7 @@ import org.dromara.common.core.domain.R;
 import org.dromara.common.core.utils.StringUtils;
 import org.redisson.spring.data.connection.RedissonConnectionFactory;
 import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.core.RedisConnectionUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -31,9 +32,9 @@ public class CacheController {
     @GetMapping()
     public R<CacheListInfoVo> getInfo() throws Exception {
         RedisConnection connection = connectionFactory.getConnection();
-        Properties commandStats = connection.commands().info("commandstats");
-
-        List<Map<String, String>> pieList = new ArrayList<>();
+        try {
+            Properties commandStats = connection.commands().info("commandstats");
+            List<Map<String, String>> pieList = new ArrayList<>();
         if (commandStats != null) {
             commandStats.stringPropertyNames().forEach(key -> {
                 Map<String, String> data = new HashMap<>(2);
@@ -43,10 +44,13 @@ public class CacheController {
                 pieList.add(data);
             });
         }
-
         return R.ok(new CacheListInfoVo(
             connection.commands().info(),
             connection.commands().dbSize(), pieList));
+        } finally {
+            // 归还连接给连接池
+            RedisConnectionUtils.releaseConnection(connection, connectionFactory);
+        }
     }
 
     public record CacheListInfoVo(Properties info, Long dbSize, List<Map<String, String>> commandStats) {}

+ 4 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysConfigController.java

@@ -1,6 +1,8 @@
 package org.dromara.system.controller.system;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.excel.utils.ExcelUtil;
 import org.dromara.common.log.annotation.Log;
@@ -11,11 +13,10 @@ import org.dromara.common.web.core.BaseController;
 import org.dromara.system.domain.bo.SysConfigBo;
 import org.dromara.system.domain.vo.SysConfigVo;
 import org.dromara.system.service.ISysConfigService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -120,7 +121,7 @@ public class SysConfigController extends BaseController {
     @Log(title = "参数管理", businessType = BusinessType.DELETE)
     @DeleteMapping("/{configIds}")
     public R<Void> remove(@PathVariable Long[] configIds) {
-        configService.deleteConfigByIds(configIds);
+        configService.deleteConfigByIds(Arrays.asList(configIds));
         return R.ok();
     }
 

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java

@@ -113,6 +113,9 @@ public class SysDeptController extends BaseController {
     @Log(title = "部门管理", businessType = BusinessType.DELETE)
     @DeleteMapping("/{deptId}")
     public R<Void> remove(@PathVariable Long deptId) {
+        if (SystemConstants.DEFAULT_DEPT_ID.equals(deptId)) {
+            return R.warn("默认部门,不允许删除");
+        }
         if (deptService.hasChildByDeptId(deptId)) {
             return R.warn("存在下级部门,不允许删除");
         }

+ 8 - 7
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictDataController.java

@@ -2,23 +2,24 @@ package org.dromara.system.controller.system;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.ObjectUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
 import org.dromara.common.log.annotation.Log;
-import org.dromara.common.web.core.BaseController;
+import org.dromara.common.log.enums.BusinessType;
 import org.dromara.common.mybatis.core.page.PageQuery;
-import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.log.enums.BusinessType;
-import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.web.core.BaseController;
 import org.dromara.system.domain.bo.SysDictDataBo;
 import org.dromara.system.domain.vo.SysDictDataVo;
 import org.dromara.system.service.ISysDictDataService;
 import org.dromara.system.service.ISysDictTypeService;
-import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import jakarta.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -117,7 +118,7 @@ public class SysDictDataController extends BaseController {
     @Log(title = "字典类型", businessType = BusinessType.DELETE)
     @DeleteMapping("/{dictCodes}")
     public R<Void> remove(@PathVariable Long[] dictCodes) {
-        dictDataService.deleteDictDataByIds(dictCodes);
+        dictDataService.deleteDictDataByIds(Arrays.asList(dictCodes));
         return R.ok();
     }
 }

+ 4 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictTypeController.java

@@ -1,6 +1,8 @@
 package org.dromara.system.controller.system;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.excel.utils.ExcelUtil;
 import org.dromara.common.log.annotation.Log;
@@ -11,11 +13,10 @@ import org.dromara.common.web.core.BaseController;
 import org.dromara.system.domain.bo.SysDictTypeBo;
 import org.dromara.system.domain.vo.SysDictTypeVo;
 import org.dromara.system.service.ISysDictTypeService;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -99,7 +100,7 @@ public class SysDictTypeController extends BaseController {
     @Log(title = "字典类型", businessType = BusinessType.DELETE)
     @DeleteMapping("/{dictIds}")
     public R<Void> remove(@PathVariable Long[] dictIds) {
-        dictTypeService.deleteDictTypeByIds(dictIds);
+        dictTypeService.deleteDictTypeByIds(Arrays.asList(dictIds));
         return R.ok();
     }
 

+ 9 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java

@@ -21,6 +21,7 @@ import org.dromara.system.service.ISysMenuService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -111,9 +112,14 @@ public class SysMenuController extends BaseController {
     @GetMapping(value = "/tenantPackageMenuTreeselect/{packageId}")
     public R<MenuTreeSelectVo> tenantPackageMenuTreeselect(@PathVariable("packageId") Long packageId) {
         List<SysMenuVo> menus = menuService.selectMenuList(LoginHelper.getUserId());
-        MenuTreeSelectVo selectVo = new MenuTreeSelectVo(
-            menuService.selectMenuListByPackageId(packageId),
-            menuService.buildMenuTreeSelect(menus));
+        List<Tree<Long>> list = menuService.buildMenuTreeSelect(menus);
+        // 删除租户管理菜单
+        list.removeIf(menu -> menu.getId() == 6L);
+        List<Long> ids = new ArrayList<>();
+        if (packageId > 0L) {
+            ids = menuService.selectMenuListByPackageId(packageId);
+        }
+        MenuTreeSelectVo selectVo = new MenuTreeSelectVo(ids, list);
         return R.ok(selectVo);
     }
 

+ 10 - 4
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java

@@ -2,7 +2,6 @@ package org.dromara.system.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
 import org.dromara.common.mybatis.annotation.DataColumn;
@@ -30,18 +29,23 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
     @DataPermission({
         @DataColumn(key = "deptName", value = "dept_id")
     })
-    List<SysDeptVo> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
+    default List<SysDeptVo> selectDeptList(Wrapper<SysDept> queryWrapper) {
+        return this.selectVoList(queryWrapper);
+    }
 
     /**
      * 分页查询部门管理数据
      *
+     * @param page         分页信息
      * @param queryWrapper 查询条件
      * @return 部门信息集合
      */
     @DataPermission({
         @DataColumn(key = "deptName", value = "dept_id"),
     })
-    Page<SysDeptVo> selectPageDeptList(@Param("page") Page<SysDeptVo> page, @Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
+    default Page<SysDeptVo> selectPageDeptList(Page<SysDept> page, Wrapper<SysDept> queryWrapper) {
+        return this.selectVoPage(page, queryWrapper);
+    }
 
     /**
      * 统计指定部门ID的部门数量
@@ -52,7 +56,9 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
     @DataPermission({
         @DataColumn(key = "deptName", value = "dept_id")
     })
-    long countDeptById(Long deptId);
+    default long countDeptById(Long deptId) {
+        return this.selectCount(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptId, deptId));
+    }
 
     /**
      * 根据父部门ID查询其所有子部门的列表

+ 3 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java

@@ -1,9 +1,7 @@
 package org.dromara.system.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import org.apache.ibatis.annotations.Param;
 import org.dromara.common.mybatis.annotation.DataColumn;
 import org.dromara.common.mybatis.annotation.DataPermission;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@@ -30,7 +28,9 @@ public interface SysPostMapper extends BaseMapperPlus<SysPost, SysPostVo> {
         @DataColumn(key = "deptName", value = "dept_id"),
         @DataColumn(key = "userName", value = "create_by")
     })
-    Page<SysPostVo> selectPagePostList(@Param("page") Page<SysPostVo> page, @Param(Constants.WRAPPER) Wrapper<SysPost> queryWrapper);
+    default Page<SysPostVo> selectPagePostList(Page<SysPost> page, Wrapper<SysPost> queryWrapper) {
+        return this.selectVoPage(page, queryWrapper);
+    }
 
     /**
      * 查询用户所属岗位组

+ 2 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMenuMapper.java

@@ -16,12 +16,11 @@ public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenu, SysRoleMe
     /**
      * 根据菜单ID串删除关联关系
      *
+     * @param menuIds 菜单ID串
      * @return 结果
      */
     default int deleteByMenuIds(List<Long> menuIds) {
-        LambdaUpdateWrapper<SysRoleMenu> lqw = new LambdaUpdateWrapper<SysRoleMenu>()
-            .in(SysRoleMenu::getMenuId, menuIds);
-        return this.delete(lqw);
+        return this.delete(new LambdaUpdateWrapper<SysRoleMenu>().in(SysRoleMenu::getMenuId, menuIds));
     }
 
 }

+ 13 - 5
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java

@@ -1,6 +1,7 @@
 package org.dromara.system.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
@@ -28,10 +29,12 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
      * @return 分页的用户信息
      */
     @DataPermission({
-        @DataColumn(key = "deptName", value = "u.dept_id"),
-        @DataColumn(key = "userName", value = "u.user_id")
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
     })
-    Page<SysUserVo> selectPageUserList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+    default Page<SysUserVo> selectPageUserList(Page<SysUser> page, Wrapper<SysUser> queryWrapper) {
+        return this.selectVoPage(page, queryWrapper);
+    }
 
     /**
      * 查询用户列表,并进行数据权限控制
@@ -43,7 +46,9 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
         @DataColumn(key = "deptName", value = "dept_id"),
         @DataColumn(key = "userName", value = "user_id")
     })
-    List<SysUserVo> selectUserList(@Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+    default List<SysUserVo> selectUserList(Wrapper<SysUser> queryWrapper) {
+        return this.selectVoList(queryWrapper);
+    }
 
     /**
      * 根据条件分页查询用户列表
@@ -60,6 +65,7 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
     /**
      * 根据条件分页查询已配用户角色列表
      *
+     * @param page         分页信息
      * @param queryWrapper 查询条件
      * @return 用户信息集合信息
      */
@@ -91,7 +97,9 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
         @DataColumn(key = "deptName", value = "dept_id"),
         @DataColumn(key = "userName", value = "user_id")
     })
-    long countUserById(Long userId);
+    default long countUserById(Long userId) {
+        return this.selectCount(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId, userId));
+    }
 
     /**
      * 根据条件更新用户数据

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysConfigService.java

@@ -69,7 +69,7 @@ public interface ISysConfigService {
      *
      * @param configIds 需要删除的参数ID
      */
-    void deleteConfigByIds(Long[] configIds);
+    void deleteConfigByIds(List<Long> configIds);
 
     /**
      * 重置参数缓存数据

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictDataService.java

@@ -47,7 +47,7 @@ public interface ISysDictDataService {
      *
      * @param dictCodes 需要删除的字典数据ID
      */
-    void deleteDictDataByIds(Long[] dictCodes);
+    void deleteDictDataByIds(List<Long> dictCodes);
 
     /**
      * 新增保存字典数据信息

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictTypeService.java

@@ -62,7 +62,7 @@ public interface ISysDictTypeService {
      *
      * @param dictIds 需要删除的字典ID
      */
-    void deleteDictTypeByIds(Long[] dictIds);
+    void deleteDictTypeByIds(List<Long> dictIds);
 
     /**
      * 重置字典缓存数据

+ 4 - 16
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.system.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.crypto.SecureUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -43,11 +44,10 @@ public class SysClientServiceImpl implements ISysClientService {
     @Override
     public SysClientVo queryById(Long id) {
         SysClientVo vo = baseMapper.selectVoById(id);
-        vo.setGrantTypeList(List.of(vo.getGrantType().split(",")));
+        vo.setGrantTypeList(StringUtils.splitList(vo.getGrantType()));
         return vo;
     }
 
-
     /**
      * 查询客户端管理
      */
@@ -64,7 +64,7 @@ public class SysClientServiceImpl implements ISysClientService {
     public TableDataInfo<SysClientVo> queryPageList(SysClientBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<SysClient> lqw = buildQueryWrapper(bo);
         Page<SysClientVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        result.getRecords().forEach(r -> r.setGrantTypeList(List.of(r.getGrantType().split(","))));
+        result.getRecords().forEach(r -> r.setGrantTypeList(StringUtils.splitList(r.getGrantType())));
         return TableDataInfo.build(result);
     }
 
@@ -93,8 +93,7 @@ public class SysClientServiceImpl implements ISysClientService {
     @Override
     public Boolean insertByBo(SysClientBo bo) {
         SysClient add = MapstructUtils.convert(bo, SysClient.class);
-        validEntityBeforeSave(add);
-        add.setGrantType(String.join(",", bo.getGrantTypeList()));
+        add.setGrantType(CollUtil.join(bo.getGrantTypeList(), StringUtils.SEPARATOR));
         // 生成clientid
         String clientKey = bo.getClientKey();
         String clientSecret = bo.getClientSecret();
@@ -113,7 +112,6 @@ public class SysClientServiceImpl implements ISysClientService {
     @Override
     public Boolean updateByBo(SysClientBo bo) {
         SysClient update = MapstructUtils.convert(bo, SysClient.class);
-        validEntityBeforeSave(update);
         update.setGrantType(String.join(",", bo.getGrantTypeList()));
         return baseMapper.updateById(update) > 0;
     }
@@ -130,22 +128,12 @@ public class SysClientServiceImpl implements ISysClientService {
                 .eq(SysClient::getClientId, clientId));
     }
 
-    /**
-     * 保存前的数据校验
-     */
-    private void validEntityBeforeSave(SysClient entity) {
-        //TODO 做一些数据校验,如唯一约束
-    }
-
     /**
      * 批量删除客户端管理
      */
     @CacheEvict(cacheNames = CacheNames.SYS_CLIENT, allEntries = true)
     @Override
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            //TODO 做一些业务上的校验,判断是否需要校验
-        }
         return baseMapper.deleteByIds(ids) > 0;
     }
 }

+ 15 - 24
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java

@@ -2,10 +2,10 @@ package org.dromara.system.service.impl;
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.dynamic.datasource.annotation.DS;
 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 org.dromara.common.core.constant.CacheNames;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.exception.ServiceException;
@@ -23,12 +23,10 @@ import org.dromara.system.domain.bo.SysConfigBo;
 import org.dromara.system.domain.vo.SysConfigVo;
 import org.dromara.system.mapper.SysConfigMapper;
 import org.dromara.system.service.ISysConfigService;
-import lombok.RequiredArgsConstructor;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -57,7 +55,6 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
      * @return 参数配置信息
      */
     @Override
-    @DS("master")
     public SysConfigVo selectConfigById(Long configId) {
         return baseMapper.selectVoById(configId);
     }
@@ -83,14 +80,10 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
      */
     @Override
     public boolean selectRegisterEnabled(String tenantId) {
-        SysConfig retConfig = TenantHelper.dynamic(tenantId, () -> {
-            return baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
-                .eq(SysConfig::getConfigKey, "sys.account.registerUser"));
-        });
-        if (ObjectUtil.isNull(retConfig)) {
-            return false;
-        }
-        return Convert.toBool(retConfig.getConfigValue());
+        String configValue = TenantHelper.dynamic(tenantId, () ->
+            this.selectConfigByKey("sys.account.registerUser")
+        );
+        return Convert.toBool(configValue);
     }
 
     /**
@@ -168,15 +161,15 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
      * @param configIds 需要删除的参数ID
      */
     @Override
-    public void deleteConfigByIds(Long[] configIds) {
-        for (Long configId : configIds) {
-            SysConfig config = baseMapper.selectById(configId);
+    public void deleteConfigByIds(List<Long> configIds) {
+        List<SysConfig> list = baseMapper.selectByIds(configIds);
+        list.forEach(config -> {
             if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) {
-                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
+                throw new ServiceException(String.format("内置参数【%s】不能删除", config.getConfigKey()));
             }
             CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
-        }
-        baseMapper.deleteByIds(Arrays.asList(configIds));
+        });
+        baseMapper.deleteByIds(configIds);
     }
 
     /**
@@ -195,12 +188,10 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
      */
     @Override
     public boolean checkConfigKeyUnique(SysConfigBo config) {
-        long configId = ObjectUtils.notNull(config.getConfigId(), -1L);
-        SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
-        if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) {
-            return false;
-        }
-        return true;
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysConfig>()
+            .eq(SysConfig::getConfigKey, config.getConfigKey())
+            .ne(ObjectUtil.isNotNull(config.getConfigId()), SysConfig::getConfigId, config.getConfigId()));
+        return !exist;
     }
 
     /**

+ 11 - 17
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java

@@ -131,23 +131,17 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
         if (CollUtil.isEmpty(depts)) {
             return CollUtil.newArrayList();
         }
-        // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点
-        List<Tree<Long>> treeList = CollUtil.newArrayList();
-        for (SysDeptVo d : depts) {
-            Long parentId = d.getParentId();
-            SysDeptVo sysDeptVo = StreamUtils.findFirst(depts, it -> it.getDeptId().longValue() == parentId);
-            if (ObjectUtil.isNull(sysDeptVo)) {
-                List<Tree<Long>> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) ->
-                    tree.setId(dept.getDeptId())
-                        .setParentId(dept.getParentId())
-                        .setName(dept.getDeptName())
-                        .setWeight(dept.getOrderNum())
-                        .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus())));
-                Tree<Long> tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getDeptId());
-                treeList.add(tree);
-            }
-        }
-        return treeList;
+        return TreeBuildUtils.buildMultiRoot(
+            depts,
+            SysDeptVo::getDeptId,
+            SysDeptVo::getParentId,
+            (node, treeNode) -> treeNode
+                .setId(node.getDeptId())
+                .setParentId(node.getParentId())
+                .setName(node.getDeptName())
+                .setWeight(node.getOrderNum())
+                .putExtra("disabled", SystemConstants.DISABLE.equals(node.getStatus()))
+        );
     }
 
     /**

+ 13 - 18
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java

@@ -4,20 +4,19 @@ import cn.hutool.core.util.ObjectUtil;
 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 org.dromara.common.core.constant.CacheNames;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.MapstructUtils;
-import org.dromara.common.core.utils.ObjectUtils;
+import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
-import org.dromara.system.domain.SysDictData;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.core.exception.ServiceException;
-import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.redis.utils.CacheUtils;
+import org.dromara.system.domain.SysDictData;
 import org.dromara.system.domain.bo.SysDictDataBo;
 import org.dromara.system.domain.vo.SysDictDataVo;
 import org.dromara.system.mapper.SysDictDataMapper;
 import org.dromara.system.service.ISysDictDataService;
-import lombok.RequiredArgsConstructor;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.stereotype.Service;
 
@@ -95,12 +94,10 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
      * @param dictCodes 需要删除的字典数据ID
      */
     @Override
-    public void deleteDictDataByIds(Long[] dictCodes) {
-        for (Long dictCode : dictCodes) {
-            SysDictData data = baseMapper.selectById(dictCode);
-            baseMapper.deleteById(dictCode);
-            CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType());
-        }
+    public void deleteDictDataByIds(List<Long> dictCodes) {
+        List<SysDictData> list = baseMapper.selectByIds(dictCodes);
+        baseMapper.deleteByIds(dictCodes);
+        list.forEach(x -> CacheUtils.evict(CacheNames.SYS_DICT, x.getDictType()));
     }
 
     /**
@@ -145,13 +142,11 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
      */
     @Override
     public boolean checkDictDataUnique(SysDictDataBo dict) {
-        Long dictCode = ObjectUtils.notNull(dict.getDictCode(), -1L);
-        SysDictData entity = baseMapper.selectOne(new LambdaQueryWrapper<SysDictData>()
-            .eq(SysDictData::getDictType, dict.getDictType()).eq(SysDictData::getDictValue, dict.getDictValue()));
-        if (ObjectUtil.isNotNull(entity) && !dictCode.equals(entity.getDictCode())) {
-            return false;
-        }
-        return true;
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictData>()
+            .eq(SysDictData::getDictType, dict.getDictType())
+            .eq(SysDictData::getDictValue, dict.getDictValue())
+            .ne(ObjectUtil.isNotNull(dict.getDictCode()), SysDictData::getDictCode, dict.getDictCode()));
+        return !exist;
     }
 
 }

+ 14 - 14
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java

@@ -98,10 +98,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
     @Override
     public List<SysDictDataVo> selectDictDataByType(String dictType) {
         List<SysDictDataVo> dictDatas = dictDataMapper.selectDictDataByType(dictType);
-        if (CollUtil.isNotEmpty(dictDatas)) {
-            return dictDatas;
-        }
-        return null;
+        return CollUtil.isNotEmpty(dictDatas) ? dictDatas : null;
     }
 
     /**
@@ -133,17 +130,20 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
      * @param dictIds 需要删除的字典ID
      */
     @Override
-    public void deleteDictTypeByIds(Long[] dictIds) {
-        for (Long dictId : dictIds) {
-            SysDictType dictType = baseMapper.selectById(dictId);
-            if (dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
-                .eq(SysDictData::getDictType, dictType.getDictType()))) {
-                throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
+    public void deleteDictTypeByIds(List<Long> dictIds) {
+        List<SysDictType> list = baseMapper.selectByIds(dictIds);
+        list.forEach(x -> {
+            boolean assigned = dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
+                .eq(SysDictData::getDictType, x.getDictType()));
+            if (assigned) {
+                throw new ServiceException(String.format("%1$s已分配,不能删除", x.getDictName()));
             }
-            CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType());
-            CacheUtils.evict(CacheNames.SYS_DICT_TYPE, dictType.getDictType());
-        }
-        baseMapper.deleteByIds(Arrays.asList(dictIds));
+        });
+        baseMapper.deleteByIds(dictIds);
+        list.forEach(x -> {
+            CacheUtils.evict(CacheNames.SYS_DICT, x.getDictType());
+            CacheUtils.evict(CacheNames.SYS_DICT_TYPE, x.getDictType());
+        });
     }
 
     /**

+ 5 - 4
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.Constants;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StreamUtils;
@@ -142,7 +143,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
         } else {
             menus = baseMapper.selectMenuTreeByUserId(userId);
         }
-        return getChildPerms(menus, 0);
+        return getChildPerms(menus, Constants.TOP_PARENT_ID);
     }
 
     /**
@@ -221,7 +222,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
                 children.setQuery(menu.getQueryParam());
                 childrenList.add(children);
                 router.setChildren(childrenList);
-            } else if (menu.getParentId().intValue() == 0 && menu.isInnerLink()) {
+            } else if (menu.getParentId().equals(Constants.TOP_PARENT_ID) && menu.isInnerLink()) {
                 router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
                 router.setPath("/");
                 List<RouterVo> childrenList = new ArrayList<>();
@@ -375,11 +376,11 @@ public class SysMenuServiceImpl implements ISysMenuService {
      * @param parentId 传入的父节点ID
      * @return String
      */
-    private List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
+    private List<SysMenu> getChildPerms(List<SysMenu> list, Long parentId) {
         List<SysMenu> returnList = new ArrayList<>();
         for (SysMenu t : list) {
             // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
-            if (t.getParentId() == parentId) {
+            if (t.getParentId().equals(parentId)) {
                 recursionFn(list, t);
                 returnList.add(t);
             }

+ 5 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.system.service.impl;
 
 import cn.hutool.core.convert.Convert;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.domain.dto.TaskAssigneeDTO;
 import org.dromara.common.core.domain.model.TaskAssigneeBody;
 import org.dromara.common.core.service.TaskAssigneeService;
@@ -51,6 +52,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
         SysRoleBo bo = new SysRoleBo();
         bo.setRoleKey(taskQuery.getHandlerCode());
         bo.setRoleName(taskQuery.getHandlerName());
+        bo.setStatus(SystemConstants.NORMAL);
         Map<String, Object> params = bo.getParams();
         params.put("beginTime", taskQuery.getBeginTime());
         params.put("endTime", taskQuery.getEndTime());
@@ -73,6 +75,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
         SysPostBo bo = new SysPostBo();
         bo.setPostCategory(taskQuery.getHandlerCode());
         bo.setPostName(taskQuery.getHandlerName());
+        bo.setStatus(SystemConstants.NORMAL);
         Map<String, Object> params = bo.getParams();
         params.put("beginTime", taskQuery.getBeginTime());
         params.put("endTime", taskQuery.getEndTime());
@@ -96,6 +99,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
         SysDeptBo bo = new SysDeptBo();
         bo.setDeptCategory(taskQuery.getHandlerCode());
         bo.setDeptName(taskQuery.getHandlerName());
+        bo.setStatus(SystemConstants.NORMAL);
         Map<String, Object> params = bo.getParams();
         params.put("beginTime", taskQuery.getBeginTime());
         params.put("endTime", taskQuery.getEndTime());
@@ -107,7 +111,6 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
         return new TaskAssigneeDTO(page.getTotal(), handlers);
     }
 
-
     /**
      * 查询用户并返回任务指派的列表,支持分页
      *
@@ -120,6 +123,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
         SysUserBo bo = new SysUserBo();
         bo.setUserName(taskQuery.getHandlerCode());
         bo.setNickName(taskQuery.getHandlerName());
+        bo.setStatus(SystemConstants.NORMAL);
         Map<String, Object> params = bo.getParams();
         params.put("beginTime", taskQuery.getBeginTime());
         params.put("endTime", taskQuery.getEndTime());

+ 28 - 10
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

@@ -69,15 +69,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
      */
     @Override
     public List<SysUserExportVo> selectUserExportList(SysUserBo user) {
-        return baseMapper.selectUserExportList(this.buildQueryWrapper(user));
-    }
-
-    private Wrapper<SysUser> buildQueryWrapper(SysUserBo user) {
         Map<String, Object> params = user.getParams();
         QueryWrapper<SysUser> wrapper = Wrappers.query();
         wrapper.eq("u.del_flag", SystemConstants.NORMAL)
-            .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
-            .in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong))
             .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
             .like(StringUtils.isNotBlank(user.getNickName()), "u.nick_name", user.getNickName())
             .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
@@ -90,8 +84,29 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
                 ids.add(user.getDeptId());
                 w.in("u.dept_id", ids);
             }).orderByAsc("u.user_id");
+        return baseMapper.selectUserExportList(wrapper);
+    }
+
+    private Wrapper<SysUser> buildQueryWrapper(SysUserBo user) {
+        Map<String, Object> params = user.getParams();
+        LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(SysUser::getDelFlag, SystemConstants.NORMAL)
+            .eq(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())
+            .in(StringUtils.isNotBlank(user.getUserIds()), SysUser::getUserId, StringUtils.splitTo(user.getUserIds(), Convert::toLong))
+            .like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName())
+            .like(StringUtils.isNotBlank(user.getNickName()), SysUser::getNickName, user.getNickName())
+            .eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus())
+            .like(StringUtils.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysUser::getCreateTime, params.get("beginTime"), params.get("endTime"))
+            .and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
+                List<SysDept> deptList = deptMapper.selectListByParentId(user.getDeptId());
+                List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
+                ids.add(user.getDeptId());
+                w.in(SysUser::getDeptId, ids);
+            }).orderByAsc(SysUser::getUserId);
         if (StringUtils.isNotBlank(user.getExcludeUserIds())) {
-            wrapper.notIn("u.user_id", StringUtils.splitTo(user.getExcludeUserIds(), Convert::toLong));
+            wrapper.notIn(SysUser::getUserId, StringUtils.splitList(user.getExcludeUserIds()));
         }
         return wrapper;
     }
@@ -635,7 +650,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
             return List.of();
         }
         List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>()
-            .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber)
+            .select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUserName,
+                SysUser::getNickName, SysUser::getUserType, SysUser::getEmail,
+                SysUser::getPhonenumber, SysUser::getSex, SysUser::getStatus,
+                SysUser::getCreateTime)
             .eq(SysUser::getStatus, SystemConstants.NORMAL)
             .in(SysUser::getUserId, userIds));
         return BeanUtil.copyToList(list, UserDTO.class);
@@ -676,7 +694,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
         // 获取用户ID列表
         Set<Long> userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId);
 
-        return selectListByIds(new ArrayList<>(userIds));
+        return this.selectListByIds(new ArrayList<>(userIds));
     }
 
     /**
@@ -716,7 +734,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
         // 获取用户ID列表
         Set<Long> userIds = StreamUtils.toSet(userPosts, SysUserPost::getUserId);
 
-        return selectListByIds(new ArrayList<>(userIds));
+        return this.selectListByIds(new ArrayList<>(userIds));
     }
 
     /**

+ 0 - 26
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml

@@ -7,32 +7,6 @@
     <resultMap type="org.dromara.system.domain.vo.SysDeptVo" id="SysDeptResult">
     </resultMap>
 
-    <select id="selectDeptList" resultMap="SysDeptResult">
-        select
-        <if test="ew.getSqlSelect != null">
-            ${ew.getSqlSelect}
-        </if>
-        <if test="ew.getSqlSelect == null">
-            *
-        </if>
-        from sys_dept ${ew.getCustomSqlSegment}
-    </select>
-
-    <select id="selectPageDeptList" resultMap="SysDeptResult">
-        select
-        <if test="ew.getSqlSelect != null">
-            ${ew.getSqlSelect}
-        </if>
-        <if test="ew.getSqlSelect == null">
-            *
-        </if>
-        from sys_dept ${ew.getCustomSqlSegment}
-    </select>
-
-    <select id="countDeptById" resultType="Long">
-        select count(*) from sys_dept where del_flag = '0' and dept_id = #{deptId}
-    </select>
-
     <select id="selectDeptListByRoleId" resultType="Long">
         select d.dept_id
         from sys_dept d

+ 0 - 11
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml

@@ -7,17 +7,6 @@
     <resultMap type="org.dromara.system.domain.vo.SysPostVo" id="SysPostResult">
     </resultMap>
 
-    <select id="selectPagePostList" resultMap="SysPostResult">
-        select
-        <if test="ew.getSqlSelect != null">
-            ${ew.getSqlSelect}
-        </if>
-        <if test="ew.getSqlSelect == null">
-            *
-        </if>
-        from sys_post ${ew.getCustomSqlSegment}
-    </select>
-
     <select id="selectPostsByUserId" parameterType="Long" resultMap="SysPostResult">
         select p.post_id, p.dept_id, p.post_name, p.post_code, p.post_category
         from sys_post p

+ 0 - 31
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -11,32 +11,6 @@
         <id property="userId" column="user_id"/>
     </resultMap>
 
-    <select id="selectPageUserList" resultMap="SysUserResult">
-        select
-        <if test="ew.getSqlSelect != null">
-            ${ew.getSqlSelect}
-        </if>
-        <if test="ew.getSqlSelect == null">
-            u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
-            u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark
-        </if>
-        from sys_user u
-        ${ew.getCustomSqlSegment}
-    </select>
-
-    <select id="selectUserList" resultMap="SysUserResult">
-        select
-        <if test="ew.getSqlSelect != null">
-            ${ew.getSqlSelect}
-        </if>
-        <if test="ew.getSqlSelect == null">
-            u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
-            u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark
-        </if>
-        from sys_user u
-        ${ew.getCustomSqlSegment}
-    </select>
-
     <select id="selectUserExportList" resultMap="SysUserExportResult">
         select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
             u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
@@ -65,9 +39,4 @@
         ${ew.getCustomSqlSegment}
     </select>
 
-    <select id="countUserById" resultType="Long">
-        select count(*) from sys_user where del_flag = '0' and user_id = #{userId}
-    </select>
-
-
 </mapper>

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

@@ -73,4 +73,9 @@ public interface FlowConstant {
      */
     String MESSAGE_NOTICE = "messageNotice";
 
+    /**
+     * 任务状态
+     */
+    String WF_TASK_STATUS = "wf_task_status";
+
 }

+ 2 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java

@@ -70,7 +70,8 @@ public class CompleteTaskBo implements Serializable {
 
     public Map<String, Object> getVariables() {
         if (variables == null) {
-            return new HashMap<>(16);
+            variables = new HashMap<>(16);
+            return variables;
         }
         variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
         return variables;

+ 5 - 10
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java

@@ -4,14 +4,13 @@ import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
 import cn.idev.excel.annotation.ExcelProperty;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.workflow.common.constant.FlowConstant;
 import org.dromara.workflow.domain.FlowCategory;
 
 import java.io.Serial;
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
-
 
 /**
  * 流程分类视图对象 wf_category
@@ -34,13 +33,14 @@ public class FlowCategoryVo implements Serializable {
     private Long categoryId;
 
     /**
-     * 父级id
+     * 父级分类id
      */
     private Long parentId;
 
     /**
-     * 父类名称
+     * 父级分类名称
      */
+    @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "parentId")
     private String parentName;
 
     /**
@@ -66,9 +66,4 @@ public class FlowCategoryVo implements Serializable {
     @ExcelProperty(value = "创建时间")
     private Date createTime;
 
-    /**
-     * 子菜单
-     */
-    private List<FlowCategoryVo> children = new ArrayList<>();
-
 }

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

@@ -42,14 +42,12 @@ public class TestLeaveVo implements Serializable {
      * 开始时间
      */
     @ExcelProperty(value = "开始时间")
-    @JsonFormat(pattern = "yyyy-MM-dd")
     private Date startDate;
 
     /**
      * 结束时间
      */
     @ExcelProperty(value = "结束时间")
-    @JsonFormat(pattern = "yyyy-MM-dd")
     private Date endDate;
 
     /**

+ 3 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java

@@ -29,7 +29,9 @@ public interface FlwCategoryMapper extends BaseMapperPlus<FlowCategory, FlowCate
     @DataPermission({
         @DataColumn(key = "deptName", value = "createDept")
     })
-    long countCategoryById(Long categoryId);
+    default long countCategoryById(Long categoryId) {
+        return this.selectCount(new LambdaQueryWrapper<FlowCategory>().eq(FlowCategory::getCategoryId, categoryId));
+    }
 
     /**
      * 根据父流程分类ID查询其所有子流程分类的列表

+ 0 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java

@@ -35,7 +35,6 @@ public interface IFlwDefinitionService {
      */
     TableDataInfo<FlowDefinitionVo> unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery);
 
-
     /**
      * 发布流程定义
      *

+ 1 - 7
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java

@@ -26,12 +26,6 @@ public class CategoryNameTranslationImpl implements TranslationInterface<String>
 
     @Override
     public String translation(Object key, String other) {
-        Long id = null;
-        if (key instanceof String categoryId) {
-            id = Convert.toLong(categoryId);
-        } else if (key instanceof Long categoryId) {
-            id = categoryId;
-        }
-        return flwCategoryService.selectCategoryNameById(id);
+        return flwCategoryService.selectCategoryNameById(Convert.toLong(key));
     }
 }

+ 17 - 28
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java

@@ -8,7 +8,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.exception.ServiceException;
-import org.dromara.common.core.utils.*;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.ObjectUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.core.utils.TreeBuildUtils;
 import org.dromara.common.mybatis.helper.DataBaseHelper;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.warm.flow.core.service.DefService;
@@ -48,14 +51,7 @@ public class FlwCategoryServiceImpl implements IFlwCategoryService {
      */
     @Override
     public FlowCategoryVo queryById(Long categoryId) {
-        FlowCategoryVo category = baseMapper.selectVoById(categoryId);
-        if (ObjectUtil.isNull(category)) {
-            return null;
-        }
-        FlowCategoryVo parentCategory = baseMapper.selectVoOne(new LambdaQueryWrapper<FlowCategory>()
-            .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, category.getParentId()));
-        category.setParentName(ObjectUtils.notNullGetter(parentCategory, FlowCategoryVo::getCategoryName));
-        return category;
+        return baseMapper.selectVoById(categoryId);
     }
 
     /**
@@ -95,27 +91,20 @@ public class FlwCategoryServiceImpl implements IFlwCategoryService {
      */
     @Override
     public List<Tree<String>> selectCategoryTreeList(FlowCategoryBo category) {
-        LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(category);
-        List<FlowCategoryVo> categorys = baseMapper.selectVoList(lqw);
-        if (CollUtil.isEmpty(categorys)) {
+        List<FlowCategoryVo> categoryList = this.queryList(category);
+        if (CollUtil.isEmpty(categoryList)) {
             return CollUtil.newArrayList();
         }
-        // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点
-        List<Tree<String>> treeList = CollUtil.newArrayList();
-        for (FlowCategoryVo d : categorys) {
-            String parentId = d.getParentId().toString();
-            FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().toString().equals(parentId));
-            if (ObjectUtil.isNull(categoryVo)) {
-                List<Tree<String>> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) ->
-                    tree.setId(dept.getCategoryId().toString())
-                        .setParentId(dept.getParentId().toString())
-                        .setName(dept.getCategoryName())
-                        .setWeight(dept.getOrderNum()));
-                Tree<String> tree = StreamUtils.findFirst(trees, it -> it.getId().equals(d.getCategoryId().toString()));
-                treeList.add(tree);
-            }
-        }
-        return treeList;
+        return TreeBuildUtils.buildMultiRoot(
+            categoryList,
+            node -> String.valueOf(node.getCategoryId()),
+            node -> String.valueOf(node.getParentId()),
+            (node, treeNode) -> treeNode
+                .setId(String.valueOf(node.getCategoryId()))
+                .setParentId(String.valueOf(node.getParentId()))
+                .setName(node.getCategoryName())
+                .setWeight(node.getOrderNum())
+        );
     }
 
     /**

+ 247 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java

@@ -0,0 +1,247 @@
+package org.dromara.workflow.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.dto.UserDTO;
+import org.dromara.common.core.service.DeptService;
+import org.dromara.common.core.service.DictService;
+import org.dromara.common.core.service.UserService;
+import org.dromara.common.core.utils.DateUtils;
+import org.dromara.common.core.utils.ServletUtils;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.warm.flow.core.dto.DefJson;
+import org.dromara.warm.flow.core.dto.NodeJson;
+import org.dromara.warm.flow.core.dto.PromptContent;
+import org.dromara.warm.flow.core.enums.NodeType;
+import org.dromara.warm.flow.core.utils.MapUtil;
+import org.dromara.warm.flow.orm.entity.FlowHisTask;
+import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper;
+import org.dromara.warm.flow.ui.service.ChartExtService;
+import org.dromara.workflow.common.ConditionalOnEnable;
+import org.dromara.workflow.common.constant.FlowConstant;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 流程图提示信息
+ *
+ * @author AprilWind
+ */
+@ConditionalOnEnable
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class FlwChartExtServiceImpl implements ChartExtService {
+
+    private final UserService userService;
+    private final DeptService deptService;
+    private final FlowHisTaskMapper flowHisTaskMapper;
+    private final DictService dictService;
+
+    /**
+     * 设置流程图提示信息
+     *
+     * @param defJson 流程定义json对象
+     */
+    @Override
+    public void execute(DefJson defJson) {
+        // 临时修复 后续版本将通过defjson获取流程实例ID
+        String[] parts = ServletUtils.getRequest().getRequestURI().split("/");
+        Long instanceId = Convert.toLong(parts[parts.length - 1]);
+
+        // 根据流程实例ID查询所有相关的历史任务列表
+        List<FlowHisTask> flowHisTasks = this.getHisTaskGroupedByNode(instanceId);
+        if (CollUtil.isEmpty(flowHisTasks)) {
+            return;
+        }
+
+        // 按节点编号(nodeCode)对历史任务进行分组
+        Map<String, List<FlowHisTask>> groupedByNode = StreamUtils.groupByKey(flowHisTasks, FlowHisTask::getNodeCode);
+
+        // 批量查询所有审批人的用户信息
+        List<UserDTO> userDTOList = userService.selectListByIds(StreamUtils.toList(flowHisTasks, e -> Convert.toLong(e.getApprover())));
+
+        // 将查询到的用户列表转换为以用户ID为key的映射
+        Map<Long, UserDTO> userMap = StreamUtils.toIdentityMap(userDTOList, UserDTO::getUserId);
+
+        Map<String, String> dictType = dictService.getAllDictByDictType(FlowConstant.WF_TASK_STATUS);
+
+        // 遍历流程定义中的每个节点,调用处理方法,将对应节点的任务列表及用户信息传入,生成扩展提示内容
+        for (NodeJson nodeJson : defJson.getNodeList()) {
+            // 获取当前节点对应的历史任务列表,如果没有则返回空列表避免空指针
+            List<FlowHisTask> taskList = groupedByNode.get(nodeJson.getNodeCode());
+            if (CollUtil.isEmpty(taskList)) {
+                continue;
+            }
+            // 处理当前节点的扩展信息,包括构建审批人提示内容等
+            this.processNodeExtInfo(nodeJson, taskList, userMap, dictType);
+        }
+    }
+
+    /**
+     * 初始化流程图提示信息
+     *
+     * @param defJson 流程定义json对象
+     */
+    @Override
+    public void initPromptContent(DefJson defJson) {
+        defJson.setTopText("流程名称: " + defJson.getFlowName());
+        defJson.getNodeList().forEach(nodeJson -> {
+            nodeJson.setPromptContent(
+                new PromptContent()
+                    // 提示信息
+                    .setInfo(
+                        CollUtil.newArrayList(
+                            new PromptContent.InfoItem()
+                                .setPrefix("任务名称: ")
+                                .setContent(nodeJson.getNodeName())
+                                .setContentStyle(Map.of(
+                                    "border", "1px solid #d1e9ff",
+                                    "backgroundColor", "#e8f4ff",
+                                    "padding", "4px 8px",
+                                    "borderRadius", "4px"
+                                ))
+                                .setRowStyle(Map.of(
+                                    "fontWeight", "bold",
+                                    "margin", "0 0 6px 0",
+                                    "padding", "0 0 8px 0",
+                                    "borderBottom", "1px solid #ccc"
+                                ))
+                        )
+                    )
+                    // 弹窗样式
+                    .setDialogStyle(MapUtil.mergeAll(
+                        "position", "absolute",
+                        "backgroundColor", "#fff",
+                        "border", "1px solid #ccc",
+                        "borderRadius", "4px",
+                        "boxShadow", "0 2px 8px rgba(0, 0, 0, 0.15)",
+                        "padding", "8px 12px",
+                        "fontSize", "14px",
+                        "zIndex", "1000",
+                        "maxWidth", "500px",
+                        "overflowY", "visible",
+                        "overflowX", "hidden",
+                        "color", "#333",
+                        "pointerEvents", "auto",
+                        "scrollbarWidth", "thin"
+                    ))
+            );
+        });
+    }
+
+    /**
+     * 处理节点的扩展信息,构建用于流程图悬浮提示的内容
+     *
+     * @param nodeJson 当前节点对象
+     * @param taskList 当前节点对应的历史审批任务列表
+     */
+    private void processNodeExtInfo(NodeJson nodeJson, List<FlowHisTask> taskList, Map<Long, UserDTO> userMap, Map<String, String> dictType) {
+
+        // 获取节点提示内容对象中的 info 列表,用于追加提示项
+        List<PromptContent.InfoItem> info = nodeJson.getPromptContent().getInfo();
+
+        // 遍历所有任务记录,构建提示内容
+        for (FlowHisTask task : taskList) {
+            UserDTO userDTO = userMap.get(Convert.toLong(task.getApprover()));
+            if (ObjectUtil.isEmpty(userDTO)) {
+                continue;
+            }
+
+            // 查询用户所属部门名称
+            String deptName = deptService.selectDeptNameByIds(Convert.toStr(userDTO.getDeptId()));
+
+            // 添加标题项,如:👤 张三(市场部)
+            info.add(new PromptContent.InfoItem()
+                .setPrefix(StringUtils.format("👥 {}({})", userDTO.getNickName(), deptName))
+                .setPrefixStyle(Map.of(
+                    "fontWeight", "bold",
+                    "fontSize", "15px",
+                    "color", "#333"
+                ))
+                .setRowStyle(Map.of(
+                    "margin", "8px 0",
+                    "borderBottom", "1px dashed #ccc"
+                ))
+            );
+
+            // 添加具体信息项:账号、耗时、时间
+            info.add(buildInfoItem("用户账号", userDTO.getUserName()));
+            info.add(buildInfoItem("审批状态", dictType.get(task.getFlowStatus())));
+            info.add(buildInfoItem("审批耗时", DateUtils.getTimeDifference(task.getUpdateTime(), task.getCreateTime())));
+            info.add(buildInfoItem("办理时间", DateUtils.formatDateTime(task.getUpdateTime())));
+        }
+    }
+
+    /**
+     * 构建单条提示内容对象 InfoItem,用于悬浮窗显示(key: value)
+     *
+     * @param key   字段名(作为前缀)
+     * @param value 字段值
+     * @return 提示项对象
+     */
+    private PromptContent.InfoItem buildInfoItem(String key, String value) {
+        return new PromptContent.InfoItem()
+            // 前缀
+            .setPrefix(key + ": ")
+            // 前缀样式
+            .setPrefixStyle(Map.of(
+                "textAlign", "right",
+                "color", "#444",
+                "userSelect", "none",
+                "display", "inline-block",
+                "width", "100px",
+                "paddingRight", "8px",
+                "fontWeight", "500",
+                "fontSize", "14px",
+                "lineHeight", "24px",
+                "verticalAlign", "middle"
+            ))
+            // 内容
+            .setContent(value)
+            // 内容样式
+            .setContentStyle(Map.of(
+                "backgroundColor", "#f7faff",
+                "color", "#005cbf",
+                "padding", "4px 8px",
+                "fontSize", "14px",
+                "borderRadius", "4px",
+                "whiteSpace", "normal",
+                "border", "1px solid #d0e5ff",
+                "userSelect", "text",
+                "lineHeight", "20px"
+            ))
+            // 行样式
+            .setRowStyle(Map.of(
+                "color", "#222",
+                "alignItems", "center",
+                "display", "flex",
+                "marginBottom", "6px",
+                "fontWeight", "400",
+                "fontSize", "14px"
+            ));
+    }
+
+    /**
+     * 根据流程实例ID获取历史任务列表
+     *
+     * @param instanceId 流程实例ID
+     * @return 历史任务列表
+     */
+    public List<FlowHisTask> getHisTaskGroupedByNode(Long instanceId) {
+        LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(FlowHisTask::getInstanceId, instanceId)
+            .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
+            .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
+        return flowHisTaskMapper.selectList(wrapper);
+    }
+
+}

+ 4 - 8
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java

@@ -78,10 +78,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
         LambdaQueryWrapper<FlowDefinition> wrapper = buildQueryWrapper(flowDefinition);
         wrapper.eq(FlowDefinition::getIsPublish, PublishStatus.PUBLISHED.getKey());
         Page<FlowDefinition> page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper);
-        TableDataInfo<FlowDefinitionVo> build = TableDataInfo.build();
-        build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class));
-        build.setTotal(page.getTotal());
-        return build;
+        List<FlowDefinitionVo> list = BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class);
+        return new TableDataInfo<>(list, page.getTotal());
     }
 
     /**
@@ -96,10 +94,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
         LambdaQueryWrapper<FlowDefinition> wrapper = buildQueryWrapper(flowDefinition);
         wrapper.in(FlowDefinition::getIsPublish, Arrays.asList(PublishStatus.UNPUBLISHED.getKey(), PublishStatus.EXPIRED.getKey()));
         Page<FlowDefinition> page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper);
-        TableDataInfo<FlowDefinitionVo> build = TableDataInfo.build();
-        build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class));
-        build.setTotal(page.getTotal());
-        return build;
+        List<FlowDefinitionVo> list = BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class);
+        return new TableDataInfo<>(list, page.getTotal());
     }
 
     private LambdaQueryWrapper<FlowDefinition> buildQueryWrapper(FlowDefinition flowDefinition) {

+ 4 - 4
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java

@@ -304,14 +304,14 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
         }
         //历史任务
         LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
-        wrapper.eq(FlowHisTask::getInstanceId, instanceId);
-        wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey());
-        wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime);
+        wrapper.eq(FlowHisTask::getInstanceId, instanceId)
+            .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
+            .orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
         List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper);
         if (CollUtil.isNotEmpty(flowHisTasks)) {
             list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class));
         }
-        return Map.of("list", list,"instanceId",instanceId);
+        return Map.of("list", list, "instanceId", instanceId);
     }
 
     /**

+ 15 - 11
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.workflow.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
 import cn.hutool.core.lang.Pair;
 import cn.hutool.core.util.StrUtil;
 import lombok.RequiredArgsConstructor;
@@ -106,15 +107,10 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
             .map(entry -> {
                 String storageId = entry.getKey();
                 Pair<TaskAssigneeEnum, Long> parsed = entry.getValue();
-                String handlerName = "格式错误";
-                if (parsed != null) {
-                    Map<Long, String> nameMapping = nameMap.getOrDefault(parsed.getKey(), Collections.emptyMap());
-                    handlerName = nameMapping.getOrDefault(parsed.getValue(), "未知名称");
-                }
-                HandlerFeedBackVo backVo = new HandlerFeedBackVo();
-                backVo.setStorageId(storageId);
-                backVo.setHandlerName(handlerName);
-                return backVo;
+                String handlerName = (parsed == null) ? null
+                    : nameMap.getOrDefault(parsed.getKey(), Collections.emptyMap())
+                    .get(parsed.getValue());
+                return new HandlerFeedBackVo(storageId, handlerName);
             }).toList();
     }
 
@@ -233,13 +229,21 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
      * @return Pair(TaskAssigneeEnum, Long),如果格式非法返回 null
      */
     private Pair<TaskAssigneeEnum, Long> parseStorageId(String storageId) {
+        if (StringUtils.isBlank(storageId)) {
+            return null;
+        }
+        // 跳过以 $ 或 # 开头的字符串
+        if (StringUtils.startsWith(storageId, "$") || StringUtils.startsWith(storageId, "#")) {
+            log.debug("跳过 storageId 解析,检测到内置变量表达式:{}", storageId);
+            return null;
+        }
         try {
             String[] parts = storageId.split(StrUtil.COLON, 2);
             if (parts.length < 2) {
-                return Pair.of(TaskAssigneeEnum.USER, Long.valueOf(parts[0]));
+                return Pair.of(TaskAssigneeEnum.USER, Convert.toLong(parts[0]));
             } else {
                 TaskAssigneeEnum type = TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON);
-                return Pair.of(type, Long.valueOf(parts[1]));
+                return Pair.of(type, Convert.toLong(parts[1]));
             }
         } catch (Exception e) {
             log.warn("解析 storageId 失败,格式非法:{},错误信息:{}", storageId, e.getMessage());

+ 6 - 3
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java

@@ -530,7 +530,10 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
             // 构建以下节点数据
             List<Task> buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance, definition, FlowParams.build()));
             // 办理人变量替换
-            ExpressionUtil.evalVariable(buildNextTaskList, mergeVariable);
+            ExpressionUtil.evalVariable(buildNextTaskList,
+                FlowParams.build()
+                    .variable(mergeVariable)
+            );
             for (FlowNode flowNode : nextFlowNodes) {
                 buildNextTaskList.stream().filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())).findFirst().ifPresent(t -> {
                     if (CollUtil.isNotEmpty(t.getPermissionList())) {
@@ -714,7 +717,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
         for (Map.Entry<Long, List<User>> entry : listMap.entrySet()) {
             List<User> value = entry.getValue();
             if (CollUtil.isNotEmpty(value)) {
-                List<UserDTO> userDtoList = userService.selectListByIds(StreamUtils.toList(value, e -> Long.valueOf(e.getProcessedBy())));
+                List<UserDTO> userDtoList = userService.selectListByIds(StreamUtils.toList(value, e -> Convert.toLong(e.getProcessedBy())));
                 map.put(entry.getKey(), userDtoList);
             }
         }
@@ -733,7 +736,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
         if (CollUtil.isEmpty(userList)) {
             return Collections.emptyList();
         }
-        return userService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy())));
+        return userService.selectListByIds(StreamUtils.toList(userList, e -> Convert.toLong(e.getProcessedBy())));
     }
 
     /**

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

@@ -145,7 +145,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     @EventListener(condition = "#processEvent.flowCode.startsWith('leave')")
     public void processHandler(ProcessEvent processEvent) {
         log.info("当前任务执行了{}", processEvent.toString());
-        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId()));
+        TestLeave testLeave = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
         testLeave.setStatus(processEvent.getStatus());
         // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
         Map<String, Object> params = processEvent.getParams();
@@ -188,7 +188,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
     @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('leave')")
     public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) {
         log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString());
-        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId()));
+        TestLeave testLeave = baseMapper.selectById(Convert.toLong(processDeleteEvent.getBusinessId()));
         if (ObjectUtil.isNull(testLeave)) {
             return;
         }

+ 0 - 4
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml

@@ -4,8 +4,4 @@
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.dromara.workflow.mapper.FlwCategoryMapper">
 
-    <select id="countCategoryById" resultType="Long">
-        select count(*) from flow_category where del_flag = '0' and category_id = #{categoryId}
-    </select>
-
 </mapper>

+ 4 - 4
script/docker/docker-compose.yml

@@ -99,7 +99,7 @@ services:
     network_mode: "host"
 
   ruoyi-server1:
-    image: ruoyi/ruoyi-server:5.4.0
+    image: ruoyi/ruoyi-server:5.4.1
     container_name: ruoyi-server1
     environment:
       # 时区上海
@@ -115,7 +115,7 @@ services:
     network_mode: "host"
 
   ruoyi-server2:
-    image: ruoyi/ruoyi-server:5.4.0
+    image: ruoyi/ruoyi-server:5.4.1
     container_name: ruoyi-server2
     environment:
       # 时区上海
@@ -131,7 +131,7 @@ services:
     network_mode: "host"
 
   ruoyi-monitor-admin:
-    image: ruoyi/ruoyi-monitor-admin:5.4.0
+    image: ruoyi/ruoyi-monitor-admin:5.4.1
     container_name: ruoyi-monitor-admin
     environment:
       # 时区上海
@@ -143,7 +143,7 @@ services:
     network_mode: "host"
 
   ruoyi-snailjob-server:
-    image: ruoyi/ruoyi-snailjob-server:5.4.0
+    image: ruoyi/ruoyi-snailjob-server:5.4.1
     container_name: ruoyi-snailjob-server
     environment:
       # 时区上海

+ 1 - 1
script/sql/oracle/oracle_ry_job.sql

@@ -411,7 +411,7 @@ CREATE TABLE sj_distributed_lock
 );
 
 ALTER TABLE sj_distributed_lock
-    ADD CONSTRAINT pk_sj_distributed_lock PRIMARY KEY (id);
+    ADD CONSTRAINT pk_sj_distributed_lock PRIMARY KEY (name);
 
 COMMENT ON COLUMN sj_distributed_lock.name IS '锁名称';
 COMMENT ON COLUMN sj_distributed_lock.lock_until IS '锁定时长';

+ 4 - 4
script/sql/oracle/oracle_ry_vue_5.X.sql

@@ -447,10 +447,10 @@ insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',
 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, '租户套餐管理菜单');
 insert into sys_menu values('123',  '客户端管理',   '1',   '11', 'client',           'system/client/index',          '', 1, 0, 'C', '0', '0', 'system:client:list',          'international', 103, 1, sysdate, null, null, '客户端管理菜单');
-insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate, null, null, '');
-insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate, null, null, '');
-insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate, null, null, '');
-insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate, null, null, '');
+insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate, null, null, '');
+insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate, null, null, '');
+insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate, null, null, '');
+insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate, null, null, '');
 insert into sys_menu values('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', 1, 1, 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, sysdate, null, null, '');
 
 -- springboot-admin监控

+ 5 - 5
script/sql/oracle/oracle_ry_workflow.sql

@@ -61,7 +61,7 @@ create table FLOW_NODE
     VERSION         VARCHAR2(20),
     CREATE_TIME     DATE,
     UPDATE_TIME     DATE,
-    EXT             VARCHAR2(500),
+    EXT             CLOB,
     DEL_FLAG        VARCHAR2(1)   default '0',
     TENANT_ID       VARCHAR2(40),
     PERMISSION_FLAG VARCHAR2(200)
@@ -88,10 +88,10 @@ comment on column FLOW_NODE.FORM_PATH is '审批表单路径';
 comment on column FLOW_NODE.VERSION is '版本';
 comment on column FLOW_NODE.CREATE_TIME is '创建时间';
 comment on column FLOW_NODE.UPDATE_TIME is '更新时间';
-comment on column FLOW_NODE.EXT is '扩展属性';
+comment on column FLOW_NODE.EXT is '节点扩展属性';
 comment on column FLOW_NODE.DEL_FLAG is '删除标志';
 comment on column FLOW_NODE.TENANT_ID is '租户id';
-comment on column FLOW_NODE.PERMISSION_FLAG is '权限标识(权限类型:权限标识,可以多个,用逗号隔开)';
+comment on column FLOW_NODE.PERMISSION_FLAG is '权限标识(权限类型:权限标识,可以多个,用@@隔开)';
 
 create table FLOW_SKIP
 (
@@ -179,7 +179,7 @@ create table FLOW_TASK
     NODE_CODE     VARCHAR2(100),
     NODE_NAME     VARCHAR2(100),
     NODE_TYPE     NUMBER(1),
-    FLOW_STATUS      VARCHAR2(20),
+    FLOW_STATUS   VARCHAR2(20),
     FORM_CUSTOM   VARCHAR2(1) default 'N',
     FORM_PATH     VARCHAR2(100),
     CREATE_TIME   DATE,
@@ -226,7 +226,7 @@ create table FLOW_HIS_TASK
     FORM_PATH        VARCHAR2(100),
     MESSAGE          VARCHAR2(500),
     VARIABLE         CLOB,
-    EXT              VARCHAR2(500),
+    EXT              CLOB,
     CREATE_TIME      DATE,
     UPDATE_TIME      DATE,
     DEL_FLAG         VARCHAR2(1) default '0',

+ 4 - 4
script/sql/postgres/postgres_ry_vue_5.X.sql

@@ -448,10 +448,10 @@ insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',
 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, '租户套餐管理菜单');
 insert into sys_menu values('123',  '客户端管理',   '1',   '11', 'client',           'system/client/index',          '', '1', '0', 'C', '0', '0', 'system:client:list',          'international', 103, 1, now(), null, null, '客户端管理菜单');
-insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', '1', '1', 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, now(), null, null, '');
-insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', '1', '1', 'C', '1', '0', 'system:role:edit',      '#',               103, 1, now(), null, null, '');
-insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', '1', '1', 'C', '1', '0', 'system:user:edit',      '#',               103, 1, now(), null, null, '');
-insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', '1', '1', 'C', '1', '0', 'system:dict:list',         '#',               103, 1, now(), null, null, '');
+insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', '1', '1', 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, now(), null, null, '');
+insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', '1', '1', 'C', '1', '0', 'system:role:edit',      '#',               103, 1, now(), null, null, '');
+insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', '1', '1', 'C', '1', '0', 'system:user:edit',      '#',               103, 1, now(), null, null, '');
+insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', '1', '1', 'C', '1', '0', 'system:dict:list',         '#',               103, 1, now(), null, null, '');
 insert into sys_menu values('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', '1', '1', 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, now(), null, null, '');
 
 -- springboot-admin监控

+ 6 - 7
script/sql/postgres/postgres_ry_workflow.sql

@@ -47,7 +47,7 @@ CREATE TABLE flow_node
     definition_id   int8          NOT NULL,                             -- 流程定义id
     node_code       varchar(100)  NOT NULL,                             -- 流程节点编码
     node_name       varchar(100)  NULL,                                 -- 流程节点名称
-    permission_flag varchar(200)  NULL,                                 -- 权限标识(权限类型:权限标识,可以多个,用逗号隔开)
+    permission_flag varchar(200)  NULL,                                 -- 权限标识(权限类型:权限标识,可以多个,用@@隔开)
     node_ratio      numeric(6, 3) NULL,                                 -- 流程签署比例值
     coordinate      varchar(100)  NULL,                                 -- 坐标
     any_node_skip   varchar(100)  NULL,                                 -- 任意结点跳转
@@ -60,7 +60,7 @@ CREATE TABLE flow_node
     "version"       varchar(20)   NOT NULL,                             -- 版本
     create_time     timestamp     NULL,                                 -- 创建时间
     update_time     timestamp     NULL,                                 -- 更新时间
-    ext             varchar(500)  NULL,                                 -- 扩展属性
+    ext             text         NULL,                                  -- 扩展属性
     del_flag        bpchar(1)     NULL DEFAULT '0':: character varying, -- 删除标志
     tenant_id       varchar(40)   NULL,                                 -- 租户id
     CONSTRAINT flow_node_pkey PRIMARY KEY (id)
@@ -72,7 +72,7 @@ COMMENT ON COLUMN flow_node.node_type IS '节点类型(0开始节点 1中间
 COMMENT ON COLUMN flow_node.definition_id IS '流程定义id';
 COMMENT ON COLUMN flow_node.node_code IS '流程节点编码';
 COMMENT ON COLUMN flow_node.node_name IS '流程节点名称';
-COMMENT ON COLUMN flow_node.permission_flag IS '权限标识(权限类型:权限标识,可以多个,用逗号隔开)';
+COMMENT ON COLUMN flow_node.permission_flag IS '权限标识(权限类型:权限标识,可以多个,用@@隔开)';
 COMMENT ON COLUMN flow_node.node_ratio IS '流程签署比例值';
 COMMENT ON COLUMN flow_node.coordinate IS '坐标';
 COMMENT ON COLUMN flow_node.any_node_skip IS '任意结点跳转';
@@ -85,7 +85,7 @@ COMMENT ON COLUMN flow_node.form_path IS '审批表单路径';
 COMMENT ON COLUMN flow_node."version" IS '版本';
 COMMENT ON COLUMN flow_node.create_time IS '创建时间';
 COMMENT ON COLUMN flow_node.update_time IS '更新时间';
-COMMENT ON COLUMN flow_node.ext IS '扩展属性';
+COMMENT ON COLUMN flow_node.ext IS '节点扩展属性';
 COMMENT ON COLUMN flow_node.del_flag IS '删除标志';
 COMMENT ON COLUMN flow_node.tenant_id IS '租户id';
 
@@ -172,7 +172,7 @@ CREATE TABLE flow_task
     node_code     varchar(100) NOT NULL,                             -- 节点编码
     node_name     varchar(100) NULL,                                 -- 节点名称
     node_type     int2         NOT NULL,                             -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
-    flow_status      varchar(20)  NOT NULL,                                 -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效)
+    flow_status   varchar(20)  NOT NULL,                             -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效)
     form_custom   bpchar(1)    NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否)
     form_path     varchar(100) NULL,                                 -- 审批表单路径
     create_time   timestamp    NULL,                                 -- 创建时间
@@ -215,7 +215,7 @@ CREATE TABLE flow_his_task
     flow_status      varchar(20)  NOT NULL,                                 -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效)
     form_custom      bpchar(1)    NULL     DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否)
     form_path        varchar(100) NULL,                                     -- 审批表单路径
-    ext              varchar(500) NULL,                                     -- 扩展字段,预留给业务系统使用
+    ext              text         NULL,                                     -- 扩展字段,预留给业务系统使用
     message          varchar(500) NULL,                                     -- 审批意见
     variable         text         NULL,                                     -- 任务变量
     create_time      timestamp    NULL,                                     -- 创建时间
@@ -265,7 +265,6 @@ CREATE TABLE flow_user
 );
 CREATE INDEX user_processed_type ON flow_user USING btree (processed_by, type);
 CREATE INDEX user_associated_idx ON FLOW_USER USING btree (associated);
-
 COMMENT ON TABLE flow_user IS '流程用户表';
 
 COMMENT ON COLUMN flow_user.id IS '主键id';

+ 4 - 4
script/sql/ry_vue_5.X.sql

@@ -282,10 +282,10 @@ insert into sys_menu values('115',  '代码生成',     '3',   '2', 'gen',
 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, '租户套餐管理菜单');
 insert into sys_menu values('123',  '客户端管理',   '1',   '11', 'client',           'system/client/index',          '', 1, 0, 'C', '0', '0', 'system:client:list',          'international', 103, 1, sysdate(), null, null, '客户端管理菜单');
-insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate(), null, null, '');
 insert into sys_menu values('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', 1, 1, 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, sysdate(), null, null, '');
 
 -- springboot-admin监控

+ 10 - 10
script/sql/ry_workflow.sql

@@ -29,7 +29,7 @@ CREATE TABLE `flow_node`
     `definition_id`   bigint          NOT NULL COMMENT '流程定义id',
     `node_code`       varchar(100)    NOT NULL COMMENT '流程节点编码',
     `node_name`       varchar(100)  DEFAULT NULL COMMENT '流程节点名称',
-    `permission_flag` varchar(200)  DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用逗号隔开)',
+    `permission_flag` varchar(200)  DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用@@隔开)',
     `node_ratio`      decimal(6, 3) DEFAULT NULL COMMENT '流程签署比例值',
     `coordinate`      varchar(100)  DEFAULT NULL COMMENT '坐标',
     `any_node_skip`   varchar(100)  DEFAULT NULL COMMENT '任意结点跳转',
@@ -42,7 +42,7 @@ CREATE TABLE `flow_node`
     `version`         varchar(20)     NOT NULL COMMENT '版本',
     `create_time`     datetime      DEFAULT NULL COMMENT '创建时间',
     `update_time`     datetime      DEFAULT NULL COMMENT '更新时间',
-    `ext`             text          COMMENT '扩展属性',
+    `ext`             text          COMMENT '节点扩展属性',
     `del_flag`        char(1)       DEFAULT '0' COMMENT '删除标志',
     `tenant_id`       varchar(40)   DEFAULT NULL COMMENT '租户id',
     PRIMARY KEY (`id`) USING BTREE
@@ -108,25 +108,25 @@ CREATE TABLE `flow_task`
 
 CREATE TABLE `flow_his_task`
 (
-    `id`               bigint(20)          NOT NULL COMMENT '主键id',
-    `definition_id`    bigint(20)          NOT NULL COMMENT '对应flow_definition表的id',
-    `instance_id`      bigint(20)          NOT NULL COMMENT '对应flow_instance表的id',
-    `task_id`          bigint(20)          NOT NULL COMMENT '对应flow_task表的id',
+    `id`               bigint(20)                   NOT NULL COMMENT '主键id',
+    `definition_id`    bigint(20)                   NOT NULL COMMENT '对应flow_definition表的id',
+    `instance_id`      bigint(20)                   NOT NULL COMMENT '对应flow_instance表的id',
+    `task_id`          bigint(20)                   NOT NULL COMMENT '对应flow_task表的id',
     `node_code`        varchar(100)                 DEFAULT NULL COMMENT '开始节点编码',
     `node_name`        varchar(100)                 DEFAULT NULL COMMENT '开始节点名称',
     `node_type`        tinyint(1)                   DEFAULT NULL COMMENT '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
     `target_node_code` varchar(200)                 DEFAULT NULL COMMENT '目标节点编码',
     `target_node_name` varchar(200)                 DEFAULT NULL COMMENT '结束节点名称',
     `approver`         varchar(40)                  DEFAULT NULL COMMENT '审批者',
-    `cooperate_type`   tinyint(1)          NOT NULL DEFAULT '0' COMMENT '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)',
+    `cooperate_type`   tinyint(1)                   NOT NULL DEFAULT '0' COMMENT '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)',
     `collaborator`     varchar(40)                  DEFAULT NULL COMMENT '协作人',
-    `skip_type`        varchar(10)         NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)',
-    `flow_status`      varchar(20)         NOT NULL COMMENT '流程状态(0待提交 1审批中 2审批通过 4终止 5作废 6撤销 8已完成 9已退回 10失效 11拿回)',
+    `skip_type`        varchar(10)                  NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)',
+    `flow_status`      varchar(20)                  NOT NULL COMMENT '流程状态(0待提交 1审批中 2审批通过 4终止 5作废 6撤销 8已完成 9已退回 10失效 11拿回)',
     `form_custom`      char(1)                      DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)',
     `form_path`        varchar(100)                 DEFAULT NULL COMMENT '审批表单路径',
     `message`          varchar(500)                 DEFAULT NULL COMMENT '审批意见',
     `variable`         TEXT                         DEFAULT NULL COMMENT '任务变量',
-    `ext`              varchar(500)                 DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串',
+    `ext`              TEXT                         DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串',
     `create_time`      datetime                     DEFAULT NULL COMMENT '任务开始时间',
     `update_time`      datetime                     DEFAULT NULL COMMENT '审批完成时间',
     `del_flag`         char(1)                      DEFAULT '0' COMMENT '删除标志',

+ 5 - 5
script/sql/sqlserver/sqlserver_ry_vue_5.X.sql

@@ -379,7 +379,7 @@ CREATE TABLE sys_tenant_package
 (
     package_id            bigint                          NOT NULL,
     package_name          nvarchar(20)                    NOT NULL,
-    menu_ids              nvarchar(20)                    NULL,
+    menu_ids              nvarchar(3000)                  NULL,
     remark                nvarchar(200)                   NULL,
     menu_check_strictly   tinyint         DEFAULT ((1))   NULL,
     status                nchar(1)        DEFAULT ('0')   NULL,
@@ -1690,13 +1690,13 @@ INSERT sys_menu VALUES (122, N'租户套餐管理', 6, 2, N'tenantPackage', N'sy
 GO
 INSERT sys_menu VALUES (123, N'客户端管理', 1, 11, N'client', N'system/client/index', N'', 1, 0, N'C', N'0', N'0', N'system:client:list', N'international', 103, 1, getdate(), NULL, NULL, N'客户端管理菜单')
 GO
-INSERT sys_menu VALUES (116, N'修改生成配置',  3,   2, N'gen-edit/index/:tableId(\\d+)', N'tool/gen/editTable', N'', 1, 1, N'C', N'1', N'0', N'tool:gen:edit',           N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (116, N'修改生成配置',  3,   2, N'gen-edit/index/:tableId', N'tool/gen/editTable', N'', 1, 1, N'C', N'1', N'0', N'tool:gen:edit',           N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (130, N'分配用户',     1,   2, N'role-auth/user/:roleId(\\d+)', N'system/role/authUser', N'', 1, 1, N'C', N'1', N'0', N'system:role:edit',      N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (130, N'分配用户',     1,   2, N'role-auth/user/:roleId', N'system/role/authUser', N'', 1, 1, N'C', N'1', N'0', N'system:role:edit',      N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (131, N'分配角色',     1,   1, N'user-auth/role/:userId(\\d+)', N'system/user/authRole', N'', 1, 1, N'C', N'1', N'0', N'system:user:edit',      N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (131, N'分配角色',     1,   1, N'user-auth/role/:userId', N'system/user/authRole', N'', 1, 1, N'C', N'1', N'0', N'system:user:edit',      N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (132, N'字典数据',     1,   6, N'dict-data/index/:dictId(\\d+)', N'system/dict/data', N'', 1, 1, N'C', N'1', N'0', N'system:dict:list',         N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (132, N'字典数据',     1,   6, N'dict-data/index/:dictId', N'system/dict/data', N'', 1, 1, N'C', N'1', N'0', N'system:dict:list',         N'#',               103, 1, getdate(), null, null, N'');
 GO
 INSERT sys_menu VALUES (133, N'文件配置管理',  1,   10, N'oss-config/index',              N'system/oss/config', N'', 1, 1, N'C', N'1', N'0', N'system:ossConfig:list',  N'#',                103, 1, getdate(), null, null, N'');
 GO

+ 5 - 4
script/sql/sqlserver/sqlserver_ry_workflow.sql

@@ -162,7 +162,7 @@ CREATE TABLE flow_node (
     version nvarchar(20) NOT NULL,
     create_time datetime2(7)  NULL,
     update_time datetime2(7)  NULL,
-    ext nvarchar(500) NULL,
+    ext nvarchar(max) NULL,
     del_flag nchar(1) DEFAULT('0') NULL,
     tenant_id nvarchar(40) NULL,
     CONSTRAINT PK__flow_nod__3213E83F372470DE PRIMARY KEY CLUSTERED (id)
@@ -208,7 +208,7 @@ EXEC sp_addextendedproperty
 GO
 
 EXEC sp_addextendedproperty
-'MS_Description', N'权限标识(权限类型:权限标识,可以多个,用逗号隔开)',
+'MS_Description', N'权限标识(权限类型:权限标识,可以多个,用@@隔开)',
 'SCHEMA', N'dbo',
 'TABLE', N'flow_node',
 'COLUMN', N'permission_flag'
@@ -299,12 +299,13 @@ EXEC sp_addextendedproperty
 GO
 
 EXEC sp_addextendedproperty
-'MS_Description', N'扩展属性',
+'MS_Description', N'节点扩展属性',
 'SCHEMA', N'dbo',
 'TABLE', N'flow_node',
 'COLUMN', N'ext'
 GO
 
+
 EXEC sp_addextendedproperty
 'MS_Description', N'删除标志',
 'SCHEMA', N'dbo',
@@ -731,7 +732,7 @@ CREATE TABLE flow_his_task (
     form_path nvarchar(100) NULL,
     message nvarchar(500) NULL,
     variable nvarchar(max) NULL,
-    ext nvarchar(500) NULL,
+    ext nvarchar(max) NULL,
     create_time datetime2(7)  NULL,
     update_time datetime2(7)  NULL,
     del_flag nchar(1) DEFAULT('0') NULL,

+ 4 - 4
script/sql/update/oracle/update_5.3.1-5.4.0.sql

@@ -9,10 +9,10 @@ ALTER TABLE sys_social
     MODIFY (access_token VARCHAR2(2000 BYTE))
     MODIFY (refresh_token VARCHAR2(2000 BYTE));
 
-INSERT INTO sys_menu VALUES ('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate, null, null, '');
-INSERT INTO sys_menu VALUES ('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate, null, null, '');
-INSERT INTO sys_menu VALUES ('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate, null, null, '');
-INSERT INTO sys_menu VALUES ('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate, null, null, '');
+INSERT INTO sys_menu VALUES ('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate, null, null, '');
+INSERT INTO sys_menu VALUES ('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate, null, null, '');
+INSERT INTO sys_menu VALUES ('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate, null, null, '');
+INSERT INTO sys_menu VALUES ('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate, null, null, '');
 INSERT INTO sys_menu VALUES ('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', 1, 1, 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, sysdate, null, null, '');
 INSERT INTO sys_menu VALUES ('11700', '流程设计', '11616', '5', 'design/index',   'workflow/processDefinition/design', '', '1', '1', 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, SYSDATE, NULL, NULL, '');
 INSERT INTO sys_menu VALUES ('11701', '请假申请', '11616', '6', 'leaveEdit/index', 'workflow/leave/leaveEdit', '', '1', '1', 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, SYSDATE, NULL, NULL, '');

+ 4 - 4
script/sql/update/postgres/update_5.3.1-5.4.0.sql

@@ -9,10 +9,10 @@ ALTER TABLE sys_social
 ALTER COLUMN access_token TYPE varchar(2000),
 ALTER COLUMN refresh_token TYPE varchar(2000);
 
-INSERT INTO sys_menu VALUES ('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', '1', '1', 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, now(), null, null, '');
-INSERT INTO sys_menu VALUES ('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', '1', '1', 'C', '1', '0', 'system:role:edit',      '#',               103, 1, now(), null, null, '');
-INSERT INTO sys_menu VALUES ('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', '1', '1', 'C', '1', '0', 'system:user:edit',      '#',               103, 1, now(), null, null, '');
-INSERT INTO sys_menu VALUES ('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', '1', '1', 'C', '1', '0', 'system:dict:list',         '#',               103, 1, now(), null, null, '');
+INSERT INTO sys_menu VALUES ('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', '1', '1', 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, now(), null, null, '');
+INSERT INTO sys_menu VALUES ('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', '1', '1', 'C', '1', '0', 'system:role:edit',      '#',               103, 1, now(), null, null, '');
+INSERT INTO sys_menu VALUES ('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', '1', '1', 'C', '1', '0', 'system:user:edit',      '#',               103, 1, now(), null, null, '');
+INSERT INTO sys_menu VALUES ('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', '1', '1', 'C', '1', '0', 'system:dict:list',         '#',               103, 1, now(), null, null, '');
 INSERT INTO sys_menu VALUES ('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', '1', '1', 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, now(), null, null, '');
 INSERT INTO sys_menu VALUES ('11700', '流程设计', '11616', '5', 'design/index',   'workflow/processDefinition/design', '', '1', '1', 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, '');
 INSERT INTO sys_menu VALUES ('11701', '请假申请', '11616', '6', 'leaveEdit/index', 'workflow/leave/leaveEdit', '', '1', '1', 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, '');

+ 4 - 4
script/sql/update/sqlserver/update_5.3.1-5.4.0.sql

@@ -47,13 +47,13 @@ GO
 ALTER TABLE sys_social ALTER COLUMN refresh_token VARCHAR(2000) NULL
 GO
 
-INSERT sys_menu VALUES (116, N'修改生成配置',  3,   2, N'gen-edit/index/:tableId(\\d+)', N'tool/gen/editTable', N'', 1, 1, N'C', N'1', N'0', N'tool:gen:edit',           N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (116, N'修改生成配置',  3,   2, N'gen-edit/index/:tableId', N'tool/gen/editTable', N'', 1, 1, N'C', N'1', N'0', N'tool:gen:edit',           N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (130, N'分配用户',     1,   2, N'role-auth/user/:roleId(\\d+)', N'system/role/authUser', N'', 1, 1, N'C', N'1', N'0', N'system:role:edit',      N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (130, N'分配用户',     1,   2, N'role-auth/user/:roleId', N'system/role/authUser', N'', 1, 1, N'C', N'1', N'0', N'system:role:edit',      N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (131, N'分配角色',     1,   1, N'user-auth/role/:userId(\\d+)', N'system/user/authRole', N'', 1, 1, N'C', N'1', N'0', N'system:user:edit',      N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (131, N'分配角色',     1,   1, N'user-auth/role/:userId', N'system/user/authRole', N'', 1, 1, N'C', N'1', N'0', N'system:user:edit',      N'#',               103, 1, getdate(), null, null, N'');
 GO
-INSERT sys_menu VALUES (132, N'字典数据',     1,   6, N'dict-data/index/:dictId(\\d+)', N'system/dict/data', N'', 1, 1, N'C', N'1', N'0', N'system:dict:list',         N'#',               103, 1, getdate(), null, null, N'');
+INSERT sys_menu VALUES (132, N'字典数据',     1,   6, N'dict-data/index/:dictId', N'system/dict/data', N'', 1, 1, N'C', N'1', N'0', N'system:dict:list',         N'#',               103, 1, getdate(), null, null, N'');
 GO
 INSERT sys_menu VALUES (133, N'文件配置管理',  1,   10, N'oss-config/index',              N'system/oss/config', N'', 1, 1, N'C', N'1', N'0', N'system:ossConfig:list',  N'#',                103, 1, getdate(), null, null, N'');
 GO

+ 4 - 4
script/sql/update/update_5.3.1-5.4.0.sql

@@ -12,10 +12,10 @@ ALTER TABLE `sys_social`
 ALTER TABLE `sys_social`
     MODIFY COLUMN `refresh_token` varchar(2000) DEFAULT NULL COMMENT '刷新令牌,部分平台可能没有' AFTER `expire_in`;
 
-insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId(\\d+)', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId(\\d+)', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId(\\d+)', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate(), null, null, '');
-insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId(\\d+)', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('116', '修改生成配置',  '3',   '2', 'gen-edit/index/:tableId', 'tool/gen/editTable', '', 1, 1, 'C', '1', '0', 'tool:gen:edit',           '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('130', '分配用户',     '1',   '2', 'role-auth/user/:roleId', 'system/role/authUser', '', 1, 1, 'C', '1', '0', 'system:role:edit',      '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('131', '分配角色',     '1',   '1', 'user-auth/role/:userId', 'system/user/authRole', '', 1, 1, 'C', '1', '0', 'system:user:edit',      '#',               103, 1, sysdate(), null, null, '');
+insert into sys_menu values('132', '字典数据',     '1',   '6', 'dict-data/index/:dictId', 'system/dict/data', '', 1, 1, 'C', '1', '0', 'system:dict:list',         '#',               103, 1, sysdate(), null, null, '');
 insert into sys_menu values('133', '文件配置管理',  '1',   '10', 'oss-config/index',              'system/oss/config', '', 1, 1, 'C', '1', '0', 'system:ossConfig:list',  '#',                103, 1, sysdate(), null, null, '');
 insert into sys_menu values('11700', '流程设计', '11616', '5', 'design/index',   'workflow/processDefinition/design', '', 1, 1, 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), null, null, '');
 insert into sys_menu values('11701', '请假申请', '11616', '6', 'leaveEdit/index', 'workflow/leave/leaveEdit', '', 1, 1, 'C', '1', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), null, null, '');