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

Merge remote-tracking branch 'origin/dev' into 4.X

疯狂的狮子li 2 роки тому
батько
коміт
d2774d3706
84 змінених файлів з 686 додано та 615 видалено
  1. 1 1
      .editorconfig
  2. 12 0
      .run/ruoyi-admin.run.xml
  3. 12 0
      .run/ruoyi-monitor-admin.run.xml
  4. 12 0
      .run/ruoyi-xxl-job-admin.run.xml
  5. 1 1
      README.md
  6. 20 20
      pom.xml
  7. 1 20
      ruoyi-admin/pom.xml
  8. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
  9. 2 4
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
  10. 0 26
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  11. 2 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  12. 19 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  13. 13 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  14. 1 1
      ruoyi-admin/src/main/resources/application.yml
  15. 45 45
      ruoyi-admin/src/main/resources/i18n/messages.properties
  16. 13 13
      ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
  17. 45 45
      ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
  18. 1 1
      ruoyi-common/pom.xml
  19. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
  20. 7 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
  21. 1 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
  22. 8 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
  23. 38 80
      ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java
  24. 1 1
      ruoyi-demo/pom.xml
  25. 3 3
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java
  26. 7 1
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java
  27. 0 16
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemoComparator.java
  28. 4 11
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java
  29. 1 1
      ruoyi-extend/pom.xml
  30. 1 20
      ruoyi-extend/ruoyi-monitor-admin/pom.xml
  31. 1 22
      ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
  32. 1 1
      ruoyi-framework/pom.xml
  33. 15 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
  34. 16 1
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
  35. 8 11
      ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
  36. 1 1
      ruoyi-generator/pom.xml
  37. 1 0
      ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
  38. 1 0
      ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
  39. 1 0
      ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
  40. 1 0
      ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
  41. 1 1
      ruoyi-job/pom.xml
  42. 1 1
      ruoyi-oss/pom.xml
  43. 1 1
      ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
  44. 8 3
      ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
  45. 1 1
      ruoyi-sms/pom.xml
  46. 1 1
      ruoyi-system/pom.xml
  47. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
  48. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
  49. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
  50. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
  51. 13 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java
  52. 17 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
  53. 19 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
  54. 7 0
      ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
  55. 1 1
      ruoyi-ui/package.json
  56. 1 17
      ruoyi-ui/src/api/system/dept.js
  57. 1 1
      ruoyi-ui/src/api/system/ossConfig.js
  58. 8 0
      ruoyi-ui/src/api/system/role.js
  59. 8 0
      ruoyi-ui/src/api/system/user.js
  60. 5 0
      ruoyi-ui/src/assets/styles/transition.scss
  61. 17 10
      ruoyi-ui/src/components/FileUpload/index.vue
  62. 7 1
      ruoyi-ui/src/components/ImagePreview/index.vue
  63. 39 30
      ruoyi-ui/src/components/ImageUpload/index.vue
  64. 7 3
      ruoyi-ui/src/layout/components/AppMain.vue
  65. 24 0
      ruoyi-ui/src/layout/components/IframeToggle/index.vue
  66. 40 20
      ruoyi-ui/src/layout/components/InnerLink/index.vue
  67. 6 0
      ruoyi-ui/src/layout/components/TagsView/index.vue
  68. 33 12
      ruoyi-ui/src/store/modules/tagsView.js
  69. 1 1
      ruoyi-ui/src/views/index.vue
  70. 7 3
      ruoyi-ui/src/views/system/dept/index.vue
  71. 7 7
      ruoyi-ui/src/views/system/menu/index.vue
  72. 6 12
      ruoyi-ui/src/views/system/role/index.vue
  73. 4 7
      ruoyi-ui/src/views/system/user/index.vue
  74. 1 1
      ruoyi-ui/src/views/system/user/profile/index.vue
  75. 0 109
      script/docker/deploy.sh
  76. 6 5
      script/docker/docker-compose.yml
  77. 4 3
      script/sql/oracle/oracle_ry_vue_4.X.sql
  78. 10 3
      script/sql/postgres/postgres_ry_vue_4.X.sql
  79. 4 3
      script/sql/ry_vue_4.X.sql
  80. 5 3
      script/sql/sqlserver/sqlserver_ry_vue_4.X.sql
  81. 2 0
      script/sql/update/oracle/update-4.2-4.3.sql
  82. 10 0
      script/sql/update/postgres/update-4.2-4.3.sql
  83. 3 0
      script/sql/update/sqlserver/update-4.2-4.3.sql
  84. 2 0
      script/sql/update/update-4.2-4.3.sql

+ 1 - 1
.editorconfig

@@ -10,7 +10,7 @@ end_of_line = lf
 trim_trailing_whitespace = true
 insert_final_newline = true
 
-[*.{json,yml}]
+[*.{json,yml,yaml}]
 indent_size = 2
 
 [*.md]

+ 12 - 0
.run/ruoyi-admin.run.xml

@@ -0,0 +1,12 @@
+<component name="ProjectRunConfigurationManager">
+  <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:4.3.0" />
+        <option name="buildOnly" value="true" />
+        <option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
+      </settings>
+    </deployment>
+    <method v="2" />
+  </configuration>
+</component>

+ 12 - 0
.run/ruoyi-monitor-admin.run.xml

@@ -0,0 +1,12 @@
+<component name="ProjectRunConfigurationManager">
+  <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:4.3.0" />
+        <option name="buildOnly" value="true" />
+        <option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
+      </settings>
+    </deployment>
+    <method v="2" />
+  </configuration>
+</component>

+ 12 - 0
.run/ruoyi-xxl-job-admin.run.xml

@@ -0,0 +1,12 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="ruoyi-xxl-job-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
+    <deployment type="dockerfile">
+      <settings>
+        <option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.3.0" />
+        <option name="buildOnly" value="true" />
+        <option name="sourceFilePath" value="ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile" />
+      </settings>
+    </deployment>
+    <method v="2" />
+  </configuration>
+</component>

+ 1 - 1
README.md

@@ -4,7 +4,7 @@
 [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/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-4.3.0_beta2-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
+[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.3.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
 [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.7-blue.svg)]()
 [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]()
 [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]()

+ 20 - 20
pom.xml

@@ -6,34 +6,34 @@
 
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi-vue-plus</artifactId>
-    <version>4.3.0-beta2</version>
+    <version>4.3.0</version>
 
     <name>RuoYi-Vue-Plus</name>
     <url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
     <description>RuoYi-Vue-Plus后台管理系统</description>
 
     <properties>
-        <ruoyi-vue-plus.version>4.3.0-beta2</ruoyi-vue-plus.version>
-        <spring-boot.version>2.7.2</spring-boot.version>
+        <ruoyi-vue-plus.version>4.3.0</ruoyi-vue-plus.version>
+        <spring-boot.version>2.7.3</spring-boot.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
         <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
         <spring-boot.mybatis>2.2.2</spring-boot.mybatis>
-        <druid.version>1.2.11</druid.version>
-        <springdoc.version>1.6.9</springdoc.version>
+        <druid.version>1.2.12</druid.version>
+        <springdoc.version>1.6.11</springdoc.version>
         <poi.version>5.2.2</poi.version>
         <easyexcel.version>3.1.1</easyexcel.version>
         <velocity.version>2.3</velocity.version>
         <satoken.version>1.30.0</satoken.version>
         <mybatis-plus.version>3.5.2</mybatis-plus.version>
         <p6spy.version>3.9.1</p6spy.version>
-        <hutool.version>5.8.5</hutool.version>
+        <hutool.version>5.8.6</hutool.version>
         <okhttp.version>4.10.0</okhttp.version>
-        <spring-boot-admin.version>2.7.3</spring-boot-admin.version>
-        <redisson.version>3.17.5</redisson.version>
+        <spring-boot-admin.version>2.7.4</spring-boot-admin.version>
+        <redisson.version>3.17.6</redisson.version>
         <lock4j.version>2.2.2</lock4j.version>
-        <dynamic-ds.version>3.5.1</dynamic-ds.version>
+        <dynamic-ds.version>3.5.2</dynamic-ds.version>
         <tlog.version>1.4.3</tlog.version>
         <xxl-job.version>2.3.1</xxl-job.version>
         <lombok.version>1.18.24</lombok.version>
@@ -42,17 +42,10 @@
         <guava.version>31.1-jre</guava.version>
 
         <!-- OSS 配置 -->
-        <aws-java-sdk-s3.version>1.12.264</aws-java-sdk-s3.version>
+        <aws-java-sdk-s3.version>1.12.300</aws-java-sdk-s3.version>
         <!-- SMS 配置 -->
-        <aliyun.sms.version>2.0.16</aliyun.sms.version>
-        <tencent.sms.version>3.1.555</tencent.sms.version>
-
-        <!-- docker 配置 -->
-        <docker.registry.url>localhost</docker.registry.url>
-        <docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
-        <docker.namespace>ruoyi</docker.namespace>
-        <docker.plugin.version>1.2.2</docker.plugin.version>
-
+        <aliyun.sms.version>2.0.18</aliyun.sms.version>
+        <tencent.sms.version>3.1.591</tencent.sms.version>
     </properties>
 
     <!-- 依赖声明 -->
@@ -142,6 +135,12 @@
                 <groupId>cn.dev33</groupId>
                 <artifactId>sa-token-jwt</artifactId>
                 <version>${satoken.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>cn.hutool</groupId>
+                        <artifactId>hutool-all</artifactId>
+                    </exclusion>
+                </exclusions>
             </dependency>
 
             <!-- dynamic-datasource 多数据源-->
@@ -342,7 +341,7 @@
                         <path>
                             <groupId>com.github.therapi</groupId>
                             <artifactId>therapi-runtime-javadoc-scribe</artifactId>
-                            <version>0.13.0</version>
+                            <version>0.15.0</version>
                         </path>
                         <path>
                             <groupId>org.projectlombok</groupId>
@@ -434,3 +433,4 @@
     </profiles>
 
 </project>
+

+ 1 - 20
ruoyi-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>
@@ -107,25 +107,6 @@
                     <warName>${project.artifactId}</warName>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>docker-maven-plugin</artifactId>
-                <version>${docker.plugin.version}</version>
-                <configuration>
-                    <imageName>${docker.namespace}/ruoyi-server:${project.version}</imageName>
-                    <dockerDirectory>${project.basedir}</dockerDirectory>
-                    <dockerHost>${docker.registry.host}</dockerHost>
-                    <registryUrl>${docker.registry.url}</registryUrl>
-                    <serverId>${docker.registry.url}</serverId>
-                    <resources>
-                        <resource>
-                            <targetPath>/</targetPath>
-                            <directory>${project.build.directory}</directory>
-                            <include>${project.build.finalName}.jar</include>
-                        </resource>
-                    </resources>
-                </configuration>
-            </plugin>
         </plugins>
     </build>
 

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java

@@ -34,7 +34,7 @@ public class CacheController {
 
     static {
         CACHES.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
-        CACHES.add(new SysCache(CacheNames.ONLINE_TOKEN, "在线用户"));
+        CACHES.add(new SysCache(CacheConstants.ONLINE_TOKEN_KEY, "在线用户"));
         CACHES.add(new SysCache(CacheNames.SYS_CONFIG, "配置信息"));
         CACHES.add(new SysCache(CacheNames.SYS_DICT, "数据字典"));
         CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));

+ 2 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java

@@ -6,7 +6,6 @@ import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.CacheNames;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
@@ -14,7 +13,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.StreamUtils;
 import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
+import com.ruoyi.common.utils.redis.RedisUtils;
 import com.ruoyi.system.domain.SysUserOnline;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
@@ -51,8 +50,7 @@ public class SysUserOnlineController extends BaseController {
             if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < 0) {
                 continue;
             }
-            UserOnlineDTO dto = CacheUtils.get(CacheNames.ONLINE_TOKEN, token);
-            userOnlineDTOList.add(dto);
+            userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token));
         }
         if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
             userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->

+ 0 - 26
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java

@@ -1,7 +1,6 @@
 package com.ruoyi.web.controller.system;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.lang.tree.Tree;
 import cn.hutool.core.util.ArrayUtil;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
@@ -15,9 +14,7 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * 部门信息
@@ -69,29 +66,6 @@ public class SysDeptController extends BaseController {
     }
 
     /**
-     * 获取部门下拉树列表
-     */
-    @GetMapping("/treeselect")
-    public R<List<Tree<Long>>> treeselect(SysDept dept) {
-        List<SysDept> depts = deptService.selectDeptList(dept);
-        return R.ok(deptService.buildDeptTreeSelect(depts));
-    }
-
-    /**
-     * 加载对应角色部门列表树
-     *
-     * @param roleId 角色ID
-     */
-    @GetMapping(value = "/roleDeptTreeselect/{roleId}")
-    public R<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
-        List<SysDept> depts = deptService.selectDeptList(new SysDept());
-        Map<String, Object> ajax = new HashMap<>();
-        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
-        ajax.put("depts", deptService.buildDeptTreeSelect(depts));
-        return R.ok(ajax);
-    }
-
-    /**
      * 新增部门
      */
     @SaCheckPermission("system:dept:add")

+ 2 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -68,6 +68,8 @@ public class SysProfileController extends BaseController {
         user.setUserId(getUserId());
         user.setUserName(null);
         user.setPassword(null);
+        user.setAvatar(null);
+        user.setDeptId(null);
         if (userService.updateUserProfile(user) > 0) {
             return R.ok();
         }

+ 19 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java

@@ -7,6 +7,7 @@ import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
@@ -15,6 +16,7 @@ import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.helper.LoginHelper;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
 import com.ruoyi.system.service.SysPermissionService;
@@ -23,7 +25,9 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 角色信息
@@ -38,6 +42,7 @@ public class SysRoleController extends BaseController {
 
     private final ISysRoleService roleService;
     private final ISysUserService userService;
+    private final ISysDeptService deptService;
     private final SysPermissionService permissionService;
 
     /**
@@ -215,4 +220,18 @@ public class SysRoleController extends BaseController {
         roleService.checkRoleDataScope(roleId);
         return toAjax(roleService.insertAuthUsers(roleId, userIds));
     }
+
+    /**
+     * 获取对应角色部门树列表
+     *
+     * @param roleId 角色ID
+     */
+    @SaCheckPermission("system:role:list")
+    @GetMapping(value = "/deptTree/{roleId}")
+    public R<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
+        Map<String, Object> ajax = new HashMap<>();
+        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
+        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
+        return R.ok(ajax);
+    }
 }

+ 13 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -3,6 +3,7 @@ package com.ruoyi.web.controller.system;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.secure.BCrypt;
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.tree.Tree;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.ruoyi.common.annotation.Log;
@@ -23,6 +24,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.system.domain.vo.SysUserExportVo;
 import com.ruoyi.system.domain.vo.SysUserImportVo;
 import com.ruoyi.system.listener.SysUserImportListener;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysPostService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
@@ -52,6 +54,7 @@ public class SysUserController extends BaseController {
     private final ISysUserService userService;
     private final ISysRoleService roleService;
     private final ISysPostService postService;
+    private final ISysDeptService deptService;
 
     /**
      * 获取用户列表
@@ -235,4 +238,14 @@ public class SysUserController extends BaseController {
         userService.insertUserAuth(userId, roleIds);
         return R.ok();
     }
+
+    /**
+     * 获取部门树列表
+     */
+    @SaCheckPermission("system:user:list")
+    @GetMapping("/deptTree")
+    public R<List<Tree<Long>>> deptTree(SysDept dept) {
+        return R.ok(deptService.selectDeptTreeList(dept));
+    }
+
 }

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

@@ -237,7 +237,7 @@ thread-pool:
 lock4j:
   # 获取分布式锁超时时间,默认为 3000 毫秒
   acquire-timeout: 3000
-  # 分布式锁的超时时间,默认为 30 
+  # 分布式锁的超时时间,默认为 30 秒
   expire: 30000
 
 --- # Actuator 监控端点的配置项

+ 45 - 45
ruoyi-admin/src/main/resources/i18n/messages.properties

@@ -1,45 +1,45 @@
-#\u9519\u8BEF\u6D88\u606F
-not.null=* \u5FC5\u987B\u586B\u5199
-user.jcaptcha.error=\u9A8C\u8BC1\u7801\u9519\u8BEF
-user.jcaptcha.expire=\u9A8C\u8BC1\u7801\u5DF2\u5931\u6548
-user.not.exists=\u5BF9\u4E0D\u8D77, \u60A8\u7684\u8D26\u53F7\uFF1A{0} \u4E0D\u5B58\u5728.
-user.password.not.match=\u7528\u6237\u4E0D\u5B58\u5728/\u5BC6\u7801\u9519\u8BEF
-user.password.retry.limit.count=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21
-user.password.retry.limit.exceed=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21\uFF0C\u5E10\u6237\u9501\u5B9A{1}\u5206\u949F
-user.password.delete=\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u7684\u8D26\u53F7\uFF1A{0} \u5DF2\u88AB\u5220\u9664
-user.blocked=\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u7684\u8D26\u53F7\uFF1A{0} \u5DF2\u7981\u7528\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
-role.blocked=\u89D2\u8272\u5DF2\u5C01\u7981\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
-user.logout.success=\u9000\u51FA\u6210\u529F
-length.not.valid=\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.username.not.blank=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
-user.username.not.valid=* 2\u523020\u4E2A\u6C49\u5B57\u3001\u5B57\u6BCD\u3001\u6570\u5B57\u6216\u4E0B\u5212\u7EBF\u7EC4\u6210\uFF0C\u4E14\u5FC5\u987B\u4EE5\u975E\u6570\u5B57\u5F00\u5934
-user.username.length.valid=\u8D26\u6237\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.password.not.blank=\u7528\u6237\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
-user.password.length.valid=\u7528\u6237\u5BC6\u7801\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.password.not.valid=* 5-50\u4E2A\u5B57\u7B26
-user.email.not.valid=\u90AE\u7BB1\u683C\u5F0F\u9519\u8BEF
-user.phonenumber.not.blank=\u7528\u6237\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
-user.mobile.phone.number.not.valid=\u624B\u673A\u53F7\u683C\u5F0F\u9519\u8BEF
-user.login.success=\u767B\u5F55\u6210\u529F
-user.register.success=\u6CE8\u518C\u6210\u529F
-user.register.save.error=\u4FDD\u5B58\u7528\u6237 {0} \u5931\u8D25\uFF0C\u6CE8\u518C\u8D26\u53F7\u5DF2\u5B58\u5728
-user.register.error=\u6CE8\u518C\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7CFB\u7EDF\u7BA1\u7406\u4EBA\u5458
-user.notfound=\u8BF7\u91CD\u65B0\u767B\u5F55
-user.forcelogout=\u7BA1\u7406\u5458\u5F3A\u5236\u9000\u51FA\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
-user.unknown.error=\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
-##\u6587\u4EF6\u4E0A\u4F20\u6D88\u606F
-upload.exceed.maxSize=\u4E0A\u4F20\u7684\u6587\u4EF6\u5927\u5C0F\u8D85\u51FA\u9650\u5236\u7684\u6587\u4EF6\u5927\u5C0F\uFF01<br/>\u5141\u8BB8\u7684\u6587\u4EF6\u6700\u5927\u5927\u5C0F\u662F\uFF1A{0}MB\uFF01
-upload.filename.exceed.length=\u4E0A\u4F20\u7684\u6587\u4EF6\u540D\u6700\u957F{0}\u4E2A\u5B57\u7B26
-##\u6743\u9650
-no.permission=\u60A8\u6CA1\u6709\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.create.permission=\u60A8\u6CA1\u6709\u521B\u5EFA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.update.permission=\u60A8\u6CA1\u6709\u4FEE\u6539\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.delete.permission=\u60A8\u6CA1\u6709\u5220\u9664\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.export.permission=\u60A8\u6CA1\u6709\u5BFC\u51FA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.view.permission=\u60A8\u6CA1\u6709\u67E5\u770B\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-repeat.submit.message=\u4E0D\u5141\u8BB8\u91CD\u590D\u63D0\u4EA4\uFF0C\u8BF7\u7A0D\u5019\u518D\u8BD5
-rate.limiter.message=\u8BBF\u95EE\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u5019\u518D\u8BD5
-sms.code.not.blank=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
-sms.code.retry.limit.count=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21
-sms.code.retry.limit.exceed=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21\uFF0C\u5E10\u6237\u9501\u5B9A{0}\u5206\u949F
-xcx.code.not.blank=\u5C0F\u7A0B\u5E8Fcode\u4E0D\u80FD\u4E3A\u7A7A
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=对不起, 您的账号:{0} 不存在.
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
+user.password.delete=对不起,您的账号:{0} 已被删除
+user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+length.not.valid=长度必须在{min}到{max}个字符之间
+user.username.not.blank=用户名不能为空
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.username.length.valid=账户长度必须在{min}到{max}个字符之间
+user.password.not.blank=用户密码不能为空
+user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
+user.password.not.valid=* 5-50个字符
+user.email.not.valid=邮箱格式错误
+user.phonenumber.not.blank=用户手机号不能为空
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.register.save.error=保存用户 {0} 失败,注册账号已存在
+user.register.error=注册失败,请联系系统管理人员
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
+repeat.submit.message=不允许重复提交,请稍候再试
+rate.limiter.message=访问过于频繁,请稍候再试
+sms.code.not.blank=短信验证码不能为空
+sms.code.retry.limit.count=短信验证码输入错误{0}次
+sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟
+xcx.code.not.blank=小程序code不能为空

+ 13 - 13
ruoyi-admin/src/main/resources/i18n/messages_en_US.properties

@@ -1,4 +1,4 @@
-#\u9519\u8BEF\u6D88\u606F
+#错误消息
 not.null=* Required fill in
 user.jcaptcha.error=Captcha error
 user.jcaptcha.expire=Captcha invalid
@@ -6,9 +6,9 @@ user.not.exists=Sorry, your account: {0} does not exist
 user.password.not.match=User does not exist/Password error
 user.password.retry.limit.count=Password input error {0} times
 user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
-user.password.delete=Sorry, your account\uFF1A{0} has been deleted
+user.password.delete=Sorry, your account{0} has been deleted
 user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
-role.blocked=Role disabled\uFF0Cplease contact administrators
+role.blocked=Role disabledplease contact administrators
 user.logout.success=Exit successful
 length.not.valid=The length must be between {min} and {max} characters
 user.username.not.blank=Username cannot be blank
@@ -25,18 +25,18 @@ user.register.success=Register successful
 user.register.save.error=Failed to save user {0}, The registered account already exists
 user.register.error=Register failed, please contact system administrator
 user.notfound=Please login again
-user.forcelogout=The administrator is forced to exit\uFF0Cplease login again
+user.forcelogout=The administrator is forced to exitplease login again
 user.unknown.error=Unknown error, please login again
-##\u6587\u4EF6\u4E0A\u4F20\u6D88\u606F
-upload.exceed.maxSize=The uploaded file size exceeds the limit file size\uFF01<br/>the maximum allowed file size is\uFF1A{0}MB\uFF01
+##文件上传消息
+upload.exceed.maxSize=The uploaded file size exceeds the limit file size!<br/>the maximum allowed file size is:{0}MB!
 upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters
-##\u6743\u9650
-no.permission=You do not have permission to the data\uFF0Cplease contact your administrator to add permissions [{0}]
-no.create.permission=You do not have permission to create data\uFF0Cplease contact your administrator to add permissions [{0}]
-no.update.permission=You do not have permission to modify data\uFF0Cplease contact your administrator to add permissions [{0}]
-no.delete.permission=You do not have permission to delete data\uFF0Cplease contact your administrator to add permissions [{0}]
-no.export.permission=You do not have permission to export data\uFF0Cplease contact your administrator to add permissions [{0}]
-no.view.permission=You do not have permission to view data\uFF0Cplease contact your administrator to add permissions [{0}]
+##权限
+no.permission=You do not have permission to the dataplease contact your administrator to add permissions [{0}]
+no.create.permission=You do not have permission to create dataplease contact your administrator to add permissions [{0}]
+no.update.permission=You do not have permission to modify dataplease contact your administrator to add permissions [{0}]
+no.delete.permission=You do not have permission to delete dataplease contact your administrator to add permissions [{0}]
+no.export.permission=You do not have permission to export dataplease contact your administrator to add permissions [{0}]
+no.view.permission=You do not have permission to view dataplease contact your administrator to add permissions [{0}]
 repeat.submit.message=Repeat submit is not allowed, please try again later
 rate.limiter.message=Visit too frequently, please try again later
 sms.code.not.blank=Sms code cannot be blank

+ 45 - 45
ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties

@@ -1,45 +1,45 @@
-#\u9519\u8BEF\u6D88\u606F
-not.null=* \u5FC5\u987B\u586B\u5199
-user.jcaptcha.error=\u9A8C\u8BC1\u7801\u9519\u8BEF
-user.jcaptcha.expire=\u9A8C\u8BC1\u7801\u5DF2\u5931\u6548
-user.not.exists=\u5BF9\u4E0D\u8D77, \u60A8\u7684\u8D26\u53F7\uFF1A{0} \u4E0D\u5B58\u5728.
-user.password.not.match=\u7528\u6237\u4E0D\u5B58\u5728/\u5BC6\u7801\u9519\u8BEF
-user.password.retry.limit.count=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21
-user.password.retry.limit.exceed=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21\uFF0C\u5E10\u6237\u9501\u5B9A{1}\u5206\u949F
-user.password.delete=\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u7684\u8D26\u53F7\uFF1A{0} \u5DF2\u88AB\u5220\u9664
-user.blocked=\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u7684\u8D26\u53F7\uFF1A{0} \u5DF2\u7981\u7528\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
-role.blocked=\u89D2\u8272\u5DF2\u5C01\u7981\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
-user.logout.success=\u9000\u51FA\u6210\u529F
-length.not.valid=\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.username.not.blank=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
-user.username.not.valid=* 2\u523020\u4E2A\u6C49\u5B57\u3001\u5B57\u6BCD\u3001\u6570\u5B57\u6216\u4E0B\u5212\u7EBF\u7EC4\u6210\uFF0C\u4E14\u5FC5\u987B\u4EE5\u975E\u6570\u5B57\u5F00\u5934
-user.username.length.valid=\u8D26\u6237\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.password.not.blank=\u7528\u6237\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
-user.password.length.valid=\u7528\u6237\u5BC6\u7801\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4
-user.password.not.valid=* 5-50\u4E2A\u5B57\u7B26
-user.email.not.valid=\u90AE\u7BB1\u683C\u5F0F\u9519\u8BEF
-user.phonenumber.not.blank=\u7528\u6237\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
-user.mobile.phone.number.not.valid=\u624B\u673A\u53F7\u683C\u5F0F\u9519\u8BEF
-user.login.success=\u767B\u5F55\u6210\u529F
-user.register.success=\u6CE8\u518C\u6210\u529F
-user.register.save.error=\u4FDD\u5B58\u7528\u6237 {0} \u5931\u8D25\uFF0C\u6CE8\u518C\u8D26\u53F7\u5DF2\u5B58\u5728
-user.register.error=\u6CE8\u518C\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7CFB\u7EDF\u7BA1\u7406\u4EBA\u5458
-user.notfound=\u8BF7\u91CD\u65B0\u767B\u5F55
-user.forcelogout=\u7BA1\u7406\u5458\u5F3A\u5236\u9000\u51FA\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
-user.unknown.error=\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
-##\u6587\u4EF6\u4E0A\u4F20\u6D88\u606F
-upload.exceed.maxSize=\u4E0A\u4F20\u7684\u6587\u4EF6\u5927\u5C0F\u8D85\u51FA\u9650\u5236\u7684\u6587\u4EF6\u5927\u5C0F\uFF01<br/>\u5141\u8BB8\u7684\u6587\u4EF6\u6700\u5927\u5927\u5C0F\u662F\uFF1A{0}MB\uFF01
-upload.filename.exceed.length=\u4E0A\u4F20\u7684\u6587\u4EF6\u540D\u6700\u957F{0}\u4E2A\u5B57\u7B26
-##\u6743\u9650
-no.permission=\u60A8\u6CA1\u6709\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.create.permission=\u60A8\u6CA1\u6709\u521B\u5EFA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.update.permission=\u60A8\u6CA1\u6709\u4FEE\u6539\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.delete.permission=\u60A8\u6CA1\u6709\u5220\u9664\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.export.permission=\u60A8\u6CA1\u6709\u5BFC\u51FA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-no.view.permission=\u60A8\u6CA1\u6709\u67E5\u770B\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}]
-repeat.submit.message=\u4E0D\u5141\u8BB8\u91CD\u590D\u63D0\u4EA4\uFF0C\u8BF7\u7A0D\u5019\u518D\u8BD5
-rate.limiter.message=\u8BBF\u95EE\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u5019\u518D\u8BD5
-sms.code.not.blank=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
-sms.code.retry.limit.count=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21
-sms.code.retry.limit.exceed=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21\uFF0C\u5E10\u6237\u9501\u5B9A{0}\u5206\u949F
-xcx.code.not.blank=\u5C0F\u7A0B\u5E8Fcode\u4E0D\u80FD\u4E3A\u7A7A
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=对不起, 您的账号:{0} 不存在.
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
+user.password.delete=对不起,您的账号:{0} 已被删除
+user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+user.logout.success=退出成功
+length.not.valid=长度必须在{min}到{max}个字符之间
+user.username.not.blank=用户名不能为空
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.username.length.valid=账户长度必须在{min}到{max}个字符之间
+user.password.not.blank=用户密码不能为空
+user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
+user.password.not.valid=* 5-50个字符
+user.email.not.valid=邮箱格式错误
+user.phonenumber.not.blank=用户手机号不能为空
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.register.save.error=保存用户 {0} 失败,注册账号已存在
+user.register.error=注册失败,请联系系统管理人员
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
+repeat.submit.message=不允许重复提交,请稍候再试
+rate.limiter.message=访问过于频繁,请稍候再试
+sms.code.not.blank=短信验证码不能为空
+sms.code.retry.limit.count=短信验证码输入错误{0}次
+sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟
+xcx.code.not.blank=小程序code不能为空

+ 1 - 1
ruoyi-common/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -18,6 +18,11 @@ public interface Constants {
     String GBK = "GBK";
 
     /**
+     * www主域
+     */
+    String WWW = "www.";
+
+    /**
      * http请求
      */
     String HTTP = "http://";

+ 7 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java

@@ -75,4 +75,11 @@ public class R<T> implements Serializable {
         return r;
     }
 
+    public Boolean isError() {
+        return !isSuccess();
+    }
+
+    public Boolean isSuccess() {
+        return R.SUCCESS == getCode();
+    }
 }

+ 1 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java

@@ -80,7 +80,7 @@ public class SysMenu extends TreeEntity<SysMenu> {
     private String visible;
 
     /**
-     * 菜单状态(0显示 1隐藏
+     * 菜单状态(0正常 1停用
      */
     private String status;
 

+ 8 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java

@@ -17,6 +17,7 @@ import lombok.NoArgsConstructor;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
+import java.util.Set;
 
 /**
  * 角色表 sys_role
@@ -82,7 +83,7 @@ public class SysRole extends BaseEntity {
      * 角色状态(0正常 1停用)
      */
     @ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_common_status")
+    @ExcelDictFormat(dictType = "sys_normal_disable")
     private String status;
 
     /**
@@ -114,6 +115,12 @@ public class SysRole extends BaseEntity {
     @TableField(exist = false)
     private Long[] deptIds;
 
+    /**
+     * 角色菜单权限
+     */
+    @TableField(exist = false)
+    private Set<String> permissions;
+
     public SysRole(Long roleId) {
         this.roleId = roleId;
     }

+ 38 - 80
ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java

@@ -5,7 +5,6 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.redisson.api.*;
 
-import java.util.Comparator;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
@@ -31,6 +30,43 @@ public class QueueUtils {
     }
 
     /**
+     * 添加普通队列数据
+     *
+     * @param queueName 队列名
+     * @param data      数据
+     */
+    public static <T> boolean addQueueObject(String queueName, T data) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.offer(data);
+    }
+
+    /**
+     * 通用获取一个队列数据 没有数据返回 null(不支持延迟队列)
+     *
+     * @param queueName 队列名
+     */
+    public static <T> T getQueueObject(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.poll();
+    }
+
+    /**
+     * 通用删除队列数据(不支持延迟队列)
+     */
+    public static <T> boolean removeQueueObject(String queueName, T data) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.remove(data);
+    }
+
+    /**
+     * 通用销毁队列 所有阻塞监听 报错(不支持延迟队列)
+     */
+    public static <T> boolean destroyQueue(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.delete();
+    }
+
+    /**
      * 添加延迟队列数据 默认毫秒
      *
      * @param queueName 队列名
@@ -85,32 +121,6 @@ public class QueueUtils {
     }
 
     /**
-     * 尝试设置 优先队列比较器 用于排序优先级
-     *
-     * @param queueName  队列名
-     * @param comparator 比较器
-     */
-    public static <T> boolean trySetPriorityQueueComparator(String queueName, Comparator<T> comparator) {
-        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        return priorityBlockingQueue.trySetComparator(comparator);
-    }
-
-    /**
-     * 尝试设置 优先队列比较器 用于排序优先级
-     *
-     * @param queueName  队列名
-     * @param comparator 比较器
-     * @param destroy    已存在是否销毁
-     */
-    public static <T> boolean trySetPriorityQueueComparator(String queueName, Comparator<T> comparator, boolean destroy) {
-        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        if (priorityBlockingQueue.isExists() && destroy) {
-            destroyPriorityQueueObject(queueName);
-        }
-        return priorityBlockingQueue.trySetComparator(comparator);
-    }
-
-    /**
      * 添加优先队列数据
      *
      * @param queueName 队列名
@@ -122,32 +132,6 @@ public class QueueUtils {
     }
 
     /**
-     * 获取一个优先队列数据 没有数据返回 null
-     *
-     * @param queueName 队列名
-     */
-    public static <T> T getPriorityQueueObject(String queueName) {
-        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        return priorityBlockingQueue.poll();
-    }
-
-    /**
-     * 删除优先队列数据
-     */
-    public static <T> boolean removePriorityQueueObject(String queueName, T data) {
-        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        return priorityBlockingQueue.remove(data);
-    }
-
-    /**
-     * 销毁优先队列
-     */
-    public static boolean destroyPriorityQueueObject(String queueName) {
-        RPriorityBlockingQueue<?> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        return priorityBlockingQueue.delete();
-    }
-
-    /**
      * 尝试设置 有界队列 容量 用于限制数量
      *
      * @param queueName 队列名
@@ -168,7 +152,7 @@ public class QueueUtils {
     public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) {
         RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
         if (boundedBlockingQueue.isExists() && destroy) {
-            destroyBoundedQueueObject(queueName);
+            destroyQueue(queueName);
         }
         return boundedBlockingQueue.trySetCapacity(capacity);
     }
@@ -186,32 +170,6 @@ public class QueueUtils {
     }
 
     /**
-     * 获取一个有界队列数据 没有数据返回 null
-     *
-     * @param queueName 队列名
-     */
-    public static <T> T getBoundedQueueObject(String queueName) {
-        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        return boundedBlockingQueue.poll();
-    }
-
-    /**
-     * 删除有界队列数据
-     */
-    public static <T> boolean removeBoundedQueueObject(String queueName, T data) {
-        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        return boundedBlockingQueue.remove(data);
-    }
-
-    /**
-     * 销毁有界队列
-     */
-    public static boolean destroyBoundedQueueObject(String queueName) {
-        RBoundedBlockingQueue<?> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        return boundedBlockingQueue.delete();
-    }
-
-    /**
      * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等)
      */
     public static <T> void subscribeBlockingQueue(String queueName, Consumer<T> consumer) {

+ 1 - 1
ruoyi-demo/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 3 - 3
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java

@@ -35,7 +35,7 @@ public class BoundedQueueController {
     @GetMapping("/add")
     public R<Void> add(String queueName, int capacity) {
         // 用完了一定要销毁 否则会一直存在
-        boolean b = QueueUtils.destroyBoundedQueueObject(queueName);
+        boolean b = QueueUtils.destroyQueue(queueName);
         log.info("通道: {} , 删除: {}", queueName, b);
         // 初始化设置一次即可
         if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
@@ -64,7 +64,7 @@ public class BoundedQueueController {
     @GetMapping("/remove")
     public R<Void> remove(String queueName) {
         String data = "data-" + 5;
-        if (QueueUtils.removeBoundedQueueObject(queueName, data)) {
+        if (QueueUtils.removeQueueObject(queueName, data)) {
             log.info("通道: {} , 删除数据: {}", queueName, data);
         } else {
             return R.fail("操作失败");
@@ -81,7 +81,7 @@ public class BoundedQueueController {
     public R<Void> get(String queueName) {
         String data;
         do {
-            data = QueueUtils.getBoundedQueueObject(queueName);
+            data = QueueUtils.getQueueObject(queueName);
             log.info("通道: {} , 获取数据: {}", queueName, data);
         } while (data != null);
         return R.ok("操作成功");

+ 7 - 1
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java

@@ -2,6 +2,7 @@ package com.ruoyi.demo.controller.queue;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * 实体类 注意不允许使用内部类 否则会找不到类
@@ -11,7 +12,12 @@ import lombok.NoArgsConstructor;
  */
 @Data
 @NoArgsConstructor
-public class PriorityDemo {
+public class PriorityDemo implements Comparable<PriorityDemo> {
     private String name;
     private Integer orderNum;
+
+    @Override
+    public int compareTo(@NotNull PriorityDemo other) {
+        return Integer.compare(getOrderNum(), other.getOrderNum());
+    }
 }

+ 0 - 16
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemoComparator.java

@@ -1,16 +0,0 @@
-package com.ruoyi.demo.controller.queue;
-
-import java.util.Comparator;
-
-/**
- * 比较器 注意不允许使用 内部类或匿名类或lambda表达式 会找不到类
- *
- * @author Lion Li
- * @version 3.6.0
- */
-public class PriorityDemoComparator implements Comparator<PriorityDemo> {
-    @Override
-    public int compare(PriorityDemo pd1, PriorityDemo pd2) {
-        return Integer.compare(pd1.getOrderNum(), pd2.getOrderNum());
-    }
-}

+ 4 - 11
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java

@@ -34,16 +34,9 @@ public class PriorityQueueController {
     @GetMapping("/add")
     public R<Void> add(String queueName) {
         // 用完了一定要销毁 否则会一直存在
-        boolean b = QueueUtils.destroyPriorityQueueObject(queueName);
+        boolean b = QueueUtils.destroyQueue(queueName);
         log.info("通道: {} , 删除: {}", queueName, b);
-        // 初始化设置一次即可 此处注意 不允许用内部类或匿名类
-        boolean flag = QueueUtils.trySetPriorityQueueComparator(queueName, new PriorityDemoComparator());
-        if (flag) {
-            log.info("通道: {} , 设置比较器成功", queueName);
-        } else {
-            log.info("通道: {} , 设置比较器失败", queueName);
-            return R.fail("操作失败");
-        }
+
         for (int i = 0; i < 10; i++) {
             int randomNum = RandomUtil.randomInt(10);
             PriorityDemo data = new PriorityDemo();
@@ -70,7 +63,7 @@ public class PriorityQueueController {
         PriorityDemo data = new PriorityDemo();
         data.setName(name);
         data.setOrderNum(orderNum);
-        if (QueueUtils.removePriorityQueueObject(queueName, data)) {
+        if (QueueUtils.removeQueueObject(queueName, data)) {
             log.info("通道: {} , 删除数据: {}", queueName, data);
         } else {
             return R.fail("操作失败");
@@ -87,7 +80,7 @@ public class PriorityQueueController {
     public R<Void> get(String queueName) {
         PriorityDemo data;
         do {
-            data = QueueUtils.getPriorityQueueObject(queueName);
+            data = QueueUtils.getQueueObject(queueName);
             log.info("通道: {} , 获取数据: {}", queueName, data);
         } while (data != null);
         return R.ok("操作成功");

+ 1 - 1
ruoyi-extend/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>ruoyi-extend</artifactId>

+ 1 - 20
ruoyi-extend/ruoyi-monitor-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-extend</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>
@@ -59,25 +59,6 @@
                     </execution>
                 </executions>
             </plugin>
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>docker-maven-plugin</artifactId>
-                <version>${docker.plugin.version}</version>
-                <configuration>
-                    <imageName>${docker.namespace}/${project.artifactId}:${project.version}</imageName>
-                    <dockerDirectory>${project.basedir}</dockerDirectory>
-                    <dockerHost>${docker.registry.host}</dockerHost>
-                    <registryUrl>${docker.registry.url}</registryUrl>
-                    <serverId>${docker.registry.url}</serverId>
-                    <resources>
-                        <resource>
-                            <targetPath>/</targetPath>
-                            <directory>${project.build.directory}</directory>
-                            <include>${project.build.finalName}.jar</include>
-                        </resource>
-                    </resources>
-                </configuration>
-            </plugin>
         </plugins>
     </build>
 

+ 1 - 22
ruoyi-extend/ruoyi-xxl-job-admin/pom.xml

@@ -4,7 +4,7 @@
     <parent>
         <artifactId>ruoyi-extend</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <artifactId>ruoyi-xxl-job-admin</artifactId>
     <packaging>jar</packaging>
@@ -96,27 +96,6 @@
                     </execution>
                 </executions>
             </plugin>
-            <!-- docker -->
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>docker-maven-plugin</artifactId>
-                <version>${docker.plugin.version}</version>
-                <configuration>
-                    <!-- made of '[a-z0-9-_.]' -->
-                    <imageName>${docker.namespace}/${project.artifactId}:${project.version}</imageName>
-                    <dockerDirectory>${project.basedir}</dockerDirectory>
-                    <dockerHost>${docker.registry.host}</dockerHost>
-                    <registryUrl>${docker.registry.url}</registryUrl>
-                    <serverId>${docker.registry.url}</serverId>
-                    <resources>
-                        <resource>
-                            <targetPath>/</targetPath>
-                            <directory>${project.build.directory}</directory>
-                            <include>${project.build.finalName}.jar</include>
-                        </resource>
-                    </resources>
-                </configuration>
-            </plugin>
         </plugins>
     </build>
 

+ 1 - 1
ruoyi-framework/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 15 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java

@@ -1,5 +1,7 @@
 package com.ruoyi.framework.aspectj;
 
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.domain.dto.OperLogDTO;
@@ -37,6 +39,11 @@ import java.util.Map;
 public class LogAspect {
 
     /**
+     * 排除敏感属性字段
+     */
+    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
+
+    /**
      * 处理完请求后执行
      *
      * @param joinPoint 切点
@@ -66,7 +73,7 @@ public class LogAspect {
             // 请求的地址
             String ip = ServletUtils.getClientIP();
             operLog.setOperIp(ip);
-            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
             operLog.setOperName(LoginHelper.getUsername());
 
             if (e != null) {
@@ -142,7 +149,13 @@ public class LogAspect {
             for (Object o : paramsArray) {
                 if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
                     try {
-                        params.append(JsonUtils.toJsonString(o)).append(" ");
+                        String str = JsonUtils.toJsonString(o);
+                        Dict dict = JsonUtils.parseMap(str);
+                        if (MapUtil.isNotEmpty(dict)) {
+                            MapUtil.removeAny(dict, EXCLUDE_PROPERTIES);
+                            str = JsonUtils.toJsonString(dict);
+                        }
+                        params.append(str).append(" ");
                     } catch (Exception e) {
                         e.printStackTrace();
                     }

+ 16 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java

@@ -95,10 +95,25 @@ public class SwaggerConfig {
         // 对所有路径增加前置上下文路径
         return openApi -> {
             Paths oldPaths = openApi.getPaths();
-            Paths newPaths = new Paths();
+            if (oldPaths instanceof PlusPaths) {
+                return;
+            }
+            PlusPaths newPaths = new PlusPaths();
             oldPaths.forEach((k,v) -> newPaths.addPathItem(finalContextPath + k, v));
             openApi.setPaths(newPaths);
         };
     }
 
+    /**
+     * 单独使用一个类便于判断 解决springdoc路径拼接重复问题
+     *
+     * @author Lion Li
+     */
+    static class PlusPaths extends Paths {
+
+        public PlusPaths() {
+            super();
+        }
+    }
+
 }

+ 8 - 11
ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java

@@ -5,18 +5,20 @@ import cn.dev33.satoken.listener.SaTokenListener;
 import cn.dev33.satoken.stp.SaLoginModel;
 import cn.hutool.http.useragent.UserAgent;
 import cn.hutool.http.useragent.UserAgentUtil;
-import com.ruoyi.common.constant.CacheNames;
+import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.enums.UserType;
 import com.ruoyi.common.helper.LoginHelper;
 import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
 import com.ruoyi.common.utils.ip.AddressUtils;
+import com.ruoyi.common.utils.redis.RedisUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
+import java.time.Duration;
+
 /**
  * 用户行为 侦听器的实现
  *
@@ -48,12 +50,7 @@ public class UserActionListener implements SaTokenListener {
             dto.setTokenId(tokenValue);
             dto.setUserName(user.getUsername());
             dto.setDeptName(user.getDeptName());
-            String cacheNames = CacheNames.ONLINE_TOKEN;
-            if (tokenConfig.getTimeout() > 0) {
-                // 增加 ttl 过期时间 单位秒
-                cacheNames = CacheNames.ONLINE_TOKEN + "#" + tokenConfig.getTimeout() + "s";
-            }
-            CacheUtils.put(cacheNames, tokenValue, dto);
+            RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
             log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
         } else if (userType == UserType.APP_USER) {
             // app端 自行根据业务编写
@@ -65,7 +62,7 @@ public class UserActionListener implements SaTokenListener {
      */
     @Override
     public void doLogout(String loginType, Object loginId, String tokenValue) {
-        CacheUtils.evict(CacheNames.ONLINE_TOKEN, tokenValue);
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
         log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue);
     }
 
@@ -74,7 +71,7 @@ public class UserActionListener implements SaTokenListener {
      */
     @Override
     public void doKickout(String loginType, Object loginId, String tokenValue) {
-        CacheUtils.evict(CacheNames.ONLINE_TOKEN, tokenValue);
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
         log.info("user doLogoutByLoginId, userId:{}, token:{}", loginId, tokenValue);
     }
 
@@ -83,7 +80,7 @@ public class UserActionListener implements SaTokenListener {
      */
     @Override
     public void doReplaced(String loginType, Object loginId, String tokenValue) {
-        CacheUtils.evict(CacheNames.ONLINE_TOKEN, tokenValue);
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
         log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue);
     }
 

+ 1 - 1
ruoyi-generator/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 0
ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm

@@ -504,6 +504,7 @@ export default {
         this.loading = false;
         this.getList();
         this.#[[$modal]]#.msgSuccess("删除成功");
+      }).catch(() => {
       }).finally(() => {
         this.loading = false;
       });

+ 1 - 0
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm

@@ -561,6 +561,7 @@ export default {
         this.loading = false;
         this.getList();
         this.#[[$modal]]#.msgSuccess("删除成功");
+      }).catch(() => {
       }).finally(() => {
         this.loading = false;
       });

+ 1 - 0
ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm

@@ -487,6 +487,7 @@ function handleDelete(row) {
     loading.value = false;
     getList();
     proxy.#[[$modal]]#.msgSuccess("删除成功");
+  }).catch(() => {
   }).finally(() => {
     loading.value = false;
   });

+ 1 - 0
ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm

@@ -553,6 +553,7 @@ function handleDelete(row) {
     loading.value = true;
     getList();
     proxy.#[[$modal]]#.msgSuccess("删除成功");
+  }).catch(() => {
   }).finally(() => {
     loading.value = false;
   });

+ 1 - 1
ruoyi-job/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>

+ 1 - 1
ruoyi-oss/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java

@@ -23,7 +23,7 @@ public interface OssConstant {
     /**
      * 系统数据ids
      */
-    List<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
+    List<Long> SYSTEM_DATA_IDS = Arrays.asList(1L, 2L, 3L, 4L);
 
     /**
      * 云服务商

+ 8 - 3
ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java

@@ -10,6 +10,7 @@ import com.amazonaws.auth.BasicAWSCredentials;
 import com.amazonaws.client.builder.AwsClientBuilder;
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import com.amazonaws.services.s3.model.*;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -51,12 +52,16 @@ public class OssClient {
             } else {
                 clientConfig.setProtocol(Protocol.HTTP);
             }
-            this.client = AmazonS3Client.builder()
+            AmazonS3ClientBuilder build = AmazonS3Client.builder()
                 .withEndpointConfiguration(endpointConfig)
                 .withClientConfiguration(clientConfig)
                 .withCredentials(credentialsProvider)
-                .disableChunkedEncoding()
-                .build();
+                .disableChunkedEncoding();
+            if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)){
+                // minio 使用https限制使用域名访问 需要此配置 站点填域名
+                build.enablePathStyleAccess();
+            }
+            this.client = build.build();
 
             createBucket();
         } catch (Exception e) {

+ 1 - 1
ruoyi-sms/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>4.3.0-beta2</version>
+        <version>4.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java

@@ -61,7 +61,7 @@ public class SysPost extends BaseEntity {
      * 状态(0正常 1停用)
      */
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_common_status")
+    @ExcelDictFormat(dictType = "sys_normal_disable")
     private String status;
 
     /**

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java

@@ -41,6 +41,14 @@ public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, Sy
     List<String> selectMenuPermsByUserId(Long userId);
 
     /**
+     * 根据角色ID查询权限
+     *
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    List<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
      * 根据用户ID查询菜单
      *
      * @return 菜单列表

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java

@@ -20,6 +20,14 @@ public interface ISysDeptService {
     List<SysDept> selectDeptList(SysDept dept);
 
     /**
+     * 查询部门树结构信息
+     *
+     * @param dept 部门信息
+     * @return 部门树信息集合
+     */
+    List<Tree<Long>> selectDeptTreeList(SysDept dept);
+
+    /**
      * 构建前端所需要下拉树结构
      *
      * @param depts 部门列表

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java

@@ -40,6 +40,14 @@ public interface ISysMenuService {
     Set<String> selectMenuPermsByUserId(Long userId);
 
     /**
+     * 根据角色ID查询权限
+     *
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    Set<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
      * 根据用户ID查询菜单树信息
      *
      * @param userId 用户ID

+ 13 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java

@@ -1,10 +1,12 @@
 package com.ruoyi.system.service;
 
+import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -48,7 +50,17 @@ public class SysPermissionService {
         if (user.isAdmin()) {
             perms.add("*:*:*");
         } else {
-            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+            List<SysRole> roles = user.getRoles();
+            if (!roles.isEmpty() && roles.size() > 1) {
+                // 多角色设置permissions属性,以便数据权限匹配权限
+                for (SysRole role : roles) {
+                    Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
+                    role.setPermissions(rolePerms);
+                    perms.addAll(rolePerms);
+                }
+            } else {
+                perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+            }
         }
         return perms;
     }

+ 17 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java

@@ -59,6 +59,18 @@ public class SysDeptServiceImpl implements ISysDeptService {
     }
 
     /**
+     * 查询部门树结构信息
+     *
+     * @param dept 部门信息
+     * @return 部门树信息集合
+     */
+    @Override
+    public List<Tree<Long>> selectDeptTreeList(SysDept dept) {
+        List<SysDept> depts = this.selectDeptList(dept);
+        return buildDeptTreeSelect(depts);
+    }
+
+    /**
      * 构建前端所需要下拉树结构
      *
      * @param depts 部门列表
@@ -96,7 +108,11 @@ public class SysDeptServiceImpl implements ISysDeptService {
      */
     @Override
     public SysDept selectDeptById(Long deptId) {
-        return baseMapper.selectById(deptId);
+        SysDept dept = baseMapper.selectById(deptId);
+        SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper<SysDept>()
+            .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId()));
+        dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null);
+        return dept;
     }
 
     /**

+ 19 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java

@@ -98,6 +98,24 @@ public class SysMenuServiceImpl implements ISysMenuService {
     }
 
     /**
+     * 根据角色ID查询权限
+     *
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    @Override
+    public Set<String> selectMenuPermsByRoleId(Long roleId) {
+        List<String> perms = baseMapper.selectMenuPermsByRoleId(roleId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
      * 根据用户ID查询菜单
      *
      * @param userId 用户名称
@@ -429,7 +447,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
      * @return
      */
     public String innerLinkReplaceEach(String path) {
-        return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS},
+        return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "." },
             new String[]{"", ""});
     }
 }

+ 7 - 0
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml

@@ -95,4 +95,11 @@
           and sur.user_id = #{userId}
     </select>
 
+    <select id="selectMenuPermsByRoleId" parameterType="Long" resultType="String">
+        select distinct m.perms
+        from sys_menu m
+                 left join sys_role_menu rm on m.menu_id = rm.menu_id
+        where m.status = '0' and rm.role_id = #{roleId}
+    </select>
+
 </mapper>

+ 1 - 1
ruoyi-ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "ruoyi-vue-plus",
-  "version": "4.3.0-beta2",
+  "version": "4.3.0",
   "description": "RuoYi-Vue-Plus后台管理系统",
   "author": "LionLi",
   "license": "MIT",

+ 1 - 17
ruoyi-ui/src/api/system/dept.js

@@ -25,22 +25,6 @@ export function getDept(deptId) {
   })
 }
 
-// 查询部门下拉树结构
-export function treeselect() {
-  return request({
-    url: '/system/dept/treeselect',
-    method: 'get'
-  })
-}
-
-// 根据角色ID查询部门树结构
-export function roleDeptTreeselect(roleId) {
-  return request({
-    url: '/system/dept/roleDeptTreeselect/' + roleId,
-    method: 'get'
-  })
-}
-
 // 新增部门
 export function addDept(data) {
   return request({
@@ -65,4 +49,4 @@ export function delDept(deptId) {
     url: '/system/dept/' + deptId,
     method: 'delete'
   })
-}
+}

+ 1 - 1
ruoyi-ui/src/api/system/ossConfig.js

@@ -43,7 +43,7 @@ export function delOssConfig(ossConfigId) {
   })
 }
 
-// 用户状态修改
+// 对象存储状态修改
 export function changeOssConfigStatus(ossConfigId, status, configKey) {
   const data = {
     ossConfigId,

+ 8 - 0
ruoyi-ui/src/api/system/role.js

@@ -109,3 +109,11 @@ export function authUserSelectAll(data) {
     params: data
   })
 }
+
+// 根据角色ID查询部门树结构
+export function deptTreeSelect(roleId) {
+  return request({
+    url: '/system/role/deptTree/' + roleId,
+    method: 'get'
+  })
+}

+ 8 - 0
ruoyi-ui/src/api/system/user.js

@@ -125,3 +125,11 @@ export function updateAuthRole(data) {
     params: data
   })
 }
+
+// 查询部门下拉树结构
+export function deptTreeSelect() {
+  return request({
+    url: '/system/user/deptTree',
+    method: 'get'
+  })
+}

+ 5 - 0
ruoyi-ui/src/assets/styles/transition.scss

@@ -12,11 +12,16 @@
 }
 
 /* fade-transform */
+.fade-transform--move,
 .fade-transform-leave-active,
 .fade-transform-enter-active {
   transition: all .5s;
 }
 
+.fade-transform-leave-active {
+  position: absolute;
+}
+
 .fade-transform-enter {
   opacity: 0;
   transform: translateX(-30px);

+ 17 - 10
ruoyi-ui/src/components/FileUpload/index.vue

@@ -12,7 +12,7 @@
       :show-file-list="false"
       :headers="headers"
       class="upload-file-uploader"
-      ref="upload"
+      ref="fileUpload"
     >
       <!-- 上传按钮 -->
       <el-button size="mini" type="primary">选取文件</el-button>
@@ -157,22 +157,19 @@ export default {
     // 上传失败
     handleUploadError(err) {
       this.$modal.msgError("上传图片失败,请重试");
-      this.$modal.closeLoading()
+      this.$modal.closeLoading();
     },
     // 上传成功回调
     handleUploadSuccess(res, file) {
       if (res.code === 200) {
         this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
-        if (this.uploadList.length === this.number) {
-          this.fileList = this.fileList.concat(this.uploadList);
-          this.uploadList = [];
-          this.number = 0;
-          this.$emit("input", this.listToString(this.fileList));
-          this.$modal.closeLoading();
-        }
+        this.uploadedSuccessfully();
       } else {
-        this.$modal.msgError(res.msg);
+        this.number--;
         this.$modal.closeLoading();
+        this.$modal.msgError(res.msg);
+        this.$refs.fileUpload.handleRemove(file);
+        this.uploadedSuccessfully();
       }
     },
     // 删除文件
@@ -182,6 +179,16 @@ export default {
       this.fileList.splice(index, 1);
       this.$emit("input", this.listToString(this.fileList));
     },
+    // 上传结束处理
+    uploadedSuccessfully() {
+      if (this.number > 0 && this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList);
+        this.uploadList = [];
+        this.number = 0;
+        this.$emit("input", this.listToString(this.fileList));
+        this.$modal.closeLoading();
+      }
+    },
     // 获取文件名称
     getFileName(name) {
       // 如果是url那么取最后的名字 如果不是直接返回

+ 7 - 1
ruoyi-ui/src/components/ImagePreview/index.vue

@@ -18,7 +18,7 @@ export default {
   props: {
     src: {
       type: String,
-      required: true
+      default: ""
     },
     width: {
       type: [Number, String],
@@ -31,10 +31,16 @@ export default {
   },
   computed: {
     realSrc() {
+      if (!this.src) {
+        return;
+      }
       let real_src = this.src.split(",")[0];
       return real_src;
     },
     realSrcList() {
+      if (!this.src) {
+        return;
+      }
       let real_src_list = this.src.split(",");
       let srcList = [];
       real_src_list.forEach(item => {

+ 39 - 30
ruoyi-ui/src/components/ImageUpload/index.vue

@@ -9,8 +9,8 @@
       :limit="limit"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
-      name="file"
-      :on-remove="handleRemove"
+      ref="imageUpload"
+      :on-remove="handleDelete"
       :show-file-list="true"
       :headers="headers"
       :file-list="fileList"
@@ -120,32 +120,6 @@ export default {
     },
   },
   methods: {
-    // 删除图片
-    handleRemove(file, fileList) {
-      const findex = this.fileList.map(f => f.name).indexOf(file.name);
-      if(findex > -1) {
-        let ossId = this.fileList[findex].ossId;
-        delOss(ossId);
-        this.fileList.splice(findex, 1);
-        this.$emit("input", this.listToString(this.fileList));
-      }
-    },
-    // 上传成功回调
-    handleUploadSuccess(res) {
-      if (res.code == 200) {
-        this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
-        if (this.uploadList.length === this.number) {
-          this.fileList = this.fileList.concat(this.uploadList);
-          this.uploadList = [];
-          this.number = 0;
-          this.$emit("input", this.listToString(this.fileList));
-          this.$modal.closeLoading();
-        }
-      } else {
-        this.$modal.msgError(res.msg);
-        this.$modal.closeLoading();
-      }
-    },
     // 上传前loading加载
     handleBeforeUpload(file) {
       let isImg = false;
@@ -181,11 +155,44 @@ export default {
     handleExceed() {
       this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
     },
+    // 上传成功回调
+    handleUploadSuccess(res, file) {
+      if (res.code === 200) {
+        this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
+        this.uploadedSuccessfully();
+      } else {
+        this.number--;
+        this.$modal.closeLoading();
+        this.$modal.msgError(res.msg);
+        this.$refs.imageUpload.handleRemove(file);
+        this.uploadedSuccessfully();
+      }
+    },
+    // 删除图片
+    handleDelete(file) {
+      const findex = this.fileList.map(f => f.name).indexOf(file.name);
+      if(findex > -1) {
+        let ossId = this.fileList[findex].ossId;
+        delOss(ossId);
+        this.fileList.splice(findex, 1);
+        this.$emit("input", this.listToString(this.fileList));
+      }
+    },
     // 上传失败
     handleUploadError(res) {
       this.$modal.msgError("上传图片失败,请重试");
       this.$modal.closeLoading();
     },
+    // 上传结束处理
+    uploadedSuccessfully() {
+      if (this.number > 0 && this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList);
+        this.uploadList = [];
+        this.number = 0;
+        this.$emit("input", this.listToString(this.fileList));
+        this.$modal.closeLoading();
+      }
+    },
     // 预览
     handlePictureCardPreview(file) {
       this.dialogImageUrl = file.url;
@@ -196,10 +203,12 @@ export default {
       let strs = "";
       separator = separator || ",";
       for (let i in list) {
-        strs += list[i].ossId + separator;
+        if (list[i].ossId) {
+          strs += list[i].ossId + separator;
+        }
       }
       return strs != "" ? strs.substr(0, strs.length - 1) : "";
-    },
+    }
   }
 };
 </script>

+ 7 - 3
ruoyi-ui/src/layout/components/AppMain.vue

@@ -2,15 +2,19 @@
   <section class="app-main">
     <transition name="fade-transform" mode="out-in">
       <keep-alive :include="cachedViews">
-        <router-view :key="key" />
+        <router-view v-if="!$route.meta.link" :key="key" />
       </keep-alive>
     </transition>
+    <iframe-toggle />
   </section>
 </template>
 
 <script>
+import iframeToggle from "./IframeToggle/index"
+
 export default {
   name: 'AppMain',
+  components: { iframeToggle },
   computed: {
     cachedViews() {
       return this.$store.state.tagsView.cachedViews
@@ -31,7 +35,7 @@ export default {
   overflow: hidden;
 }
 
-.fixed-header+.app-main {
+.fixed-header + .app-main {
   padding-top: 50px;
 }
 
@@ -41,7 +45,7 @@ export default {
     min-height: calc(100vh - 84px);
   }
 
-  .fixed-header+.app-main {
+  .fixed-header + .app-main {
     padding-top: 84px;
   }
 }

+ 24 - 0
ruoyi-ui/src/layout/components/IframeToggle/index.vue

@@ -0,0 +1,24 @@
+<template>
+  <transition-group name="fade-transform" mode="out-in">
+    <inner-link
+      v-for="(item, index) in iframeViews"
+      :key="item.path"
+      :iframeId="'iframe' + index"
+      v-show="$route.path === item.path"
+      :src="item.meta.link"
+    ></inner-link>
+  </transition-group>
+</template>
+
+<script>
+import InnerLink from "../InnerLink/index"
+
+export default {
+  components: { InnerLink },
+  computed: {
+    iframeViews() {
+      return this.$store.state.tagsView.iframeViews
+    }
+  }
+}
+</script>

+ 40 - 20
ruoyi-ui/src/layout/components/InnerLink/index.vue

@@ -1,27 +1,47 @@
+<template>
+  <div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!">
+    <iframe
+      :id="iframeId"
+      style="width: 100%; height: 100%"
+      :src="src"
+      frameborder="no"
+    ></iframe>
+  </div>
+</template>
+
 <script>
 export default {
+  props: {
+    src: {
+      type: String,
+      default: "/"
+    },
+    iframeId: {
+      type: String
+    }
+  },
   data() {
-    return {};
+    return {
+      loading: false,
+      height: document.documentElement.clientHeight - 94.5 + "px;"
+    };
   },
-  render() {
-    const { $route: { meta: { link } }, } = this;
-    if ({ link }.link === "") {
-      return "404";
+  mounted() {
+    var _this = this;
+    const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
+    const iframe = document.querySelector(iframeId);
+    // iframe页面loading控制
+    if (iframe.attachEvent) {
+      this.loading = true;
+      iframe.attachEvent("onload", function () {
+        _this.loading = false;
+      });
+    } else {
+      this.loading = true;
+      iframe.onload = function () {
+        _this.loading = false;
+      };
     }
-    let url = { link }.link;
-    const height = document.documentElement.clientHeight - 94.5 + "px";
-    const style = { height: height };
-
-    return (
-      <div style={style}>
-        <iframe
-          src={url}
-          frameborder="no"
-          style="width: 100%; height: 100%"
-          scrolling="auto"
-        ></iframe>
-      </div>
-    );
-  },
+  }
 };
 </script>

+ 6 - 0
ruoyi-ui/src/layout/components/TagsView/index.vue

@@ -133,6 +133,9 @@ export default {
       const { name } = this.$route
       if (name) {
         this.$store.dispatch('tagsView/addView', this.$route)
+        if (this.$route.meta.link) {
+          this.$store.dispatch('tagsView/addIframeView', this.$route)
+        }
       }
       return false
     },
@@ -153,6 +156,9 @@ export default {
     },
     refreshSelectedTag(view) {
       this.$tab.refreshPage(view);
+      if (this.$route.meta.link) {
+        this.$store.dispatch('tagsView/delIframeView', this.$route)
+      }
     },
     closeSelectedTag(view) {
       this.$tab.closePage(view).then(({ visitedViews }) => {

+ 33 - 12
ruoyi-ui/src/store/modules/tagsView.js

@@ -1,9 +1,18 @@
 const state = {
   visitedViews: [],
-  cachedViews: []
+  cachedViews: [],
+  iframeViews: []
 }
 
 const mutations = {
+  ADD_IFRAME_VIEW: (state, view) => {
+    if (state.iframeViews.some(v => v.path === view.path)) return
+    state.iframeViews.push(
+      Object.assign({}, view, {
+        title: view.meta.title || 'no-name'
+      })
+    )
+  },
   ADD_VISITED_VIEW: (state, view) => {
     if (state.visitedViews.some(v => v.path === view.path)) return
     state.visitedViews.push(
@@ -18,7 +27,6 @@ const mutations = {
       state.cachedViews.push(view.name)
     }
   },
-
   DEL_VISITED_VIEW: (state, view) => {
     for (const [i, v] of state.visitedViews.entries()) {
       if (v.path === view.path) {
@@ -26,6 +34,10 @@ const mutations = {
         break
       }
     }
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
+  },
+  DEL_IFRAME_VIEW: (state, view) => {
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
   },
   DEL_CACHED_VIEW: (state, view) => {
     const index = state.cachedViews.indexOf(view.name)
@@ -36,6 +48,7 @@ const mutations = {
     state.visitedViews = state.visitedViews.filter(v => {
       return v.meta.affix || v.path === view.path
     })
+    state.iframeViews = state.iframeViews.filter(item => item.path === view.path)
   },
   DEL_OTHERS_CACHED_VIEWS: (state, view) => {
     const index = state.cachedViews.indexOf(view.name)
@@ -45,16 +58,15 @@ const mutations = {
       state.cachedViews = []
     }
   },
-
   DEL_ALL_VISITED_VIEWS: state => {
     // keep affix tags
     const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
     state.visitedViews = affixTags
+    state.iframeViews = []
   },
   DEL_ALL_CACHED_VIEWS: state => {
     state.cachedViews = []
   },
-
   UPDATE_VISITED_VIEW: (state, view) => {
     for (let v of state.visitedViews) {
       if (v.path === view.path) {
@@ -63,7 +75,6 @@ const mutations = {
       }
     }
   },
-
   DEL_RIGHT_VIEWS: (state, view) => {
     const index = state.visitedViews.findIndex(v => v.path === view.path)
     if (index === -1) {
@@ -77,10 +88,13 @@ const mutations = {
       if (i > -1) {
         state.cachedViews.splice(i, 1)
       }
+      if(item.meta.link) {
+        const fi = state.iframeViews.findIndex(v => v.path === item.path)
+        state.iframeViews.splice(fi, 1)
+      }
       return false
     })
   },
-
   DEL_LEFT_VIEWS: (state, view) => {
     const index = state.visitedViews.findIndex(v => v.path === view.path)
     if (index === -1) {
@@ -94,6 +108,10 @@ const mutations = {
       if (i > -1) {
         state.cachedViews.splice(i, 1)
       }
+      if(item.meta.link) {
+        const fi = state.iframeViews.findIndex(v => v.path === item.path)
+        state.iframeViews.splice(fi, 1)
+      }
       return false
     })
   }
@@ -104,13 +122,15 @@ const actions = {
     dispatch('addVisitedView', view)
     dispatch('addCachedView', view)
   },
+  addIframeView({ commit }, view) {
+    commit('ADD_IFRAME_VIEW', view)
+  },
   addVisitedView({ commit }, view) {
     commit('ADD_VISITED_VIEW', view)
   },
   addCachedView({ commit }, view) {
     commit('ADD_CACHED_VIEW', view)
   },
-
   delView({ dispatch, state }, view) {
     return new Promise(resolve => {
       dispatch('delVisitedView', view)
@@ -127,13 +147,18 @@ const actions = {
       resolve([...state.visitedViews])
     })
   },
+  delIframeView({ commit, state }, view) {
+    return new Promise(resolve => {
+      commit('DEL_IFRAME_VIEW', view)
+      resolve([...state.iframeViews])
+    })
+  },
   delCachedView({ commit, state }, view) {
     return new Promise(resolve => {
       commit('DEL_CACHED_VIEW', view)
       resolve([...state.cachedViews])
     })
   },
-
   delOthersViews({ dispatch, state }, view) {
     return new Promise(resolve => {
       dispatch('delOthersVisitedViews', view)
@@ -156,7 +181,6 @@ const actions = {
       resolve([...state.cachedViews])
     })
   },
-
   delAllViews({ dispatch, state }, view) {
     return new Promise(resolve => {
       dispatch('delAllVisitedViews', view)
@@ -179,18 +203,15 @@ const actions = {
       resolve([...state.cachedViews])
     })
   },
-
   updateVisitedView({ commit }, view) {
     commit('UPDATE_VISITED_VIEW', view)
   },
-
   delRightTags({ commit }, view) {
     return new Promise(resolve => {
       commit('DEL_RIGHT_VIEWS', view)
       resolve([...state.visitedViews])
     })
   },
-
   delLeftTags({ commit }, view) {
     return new Promise(resolve => {
       commit('DEL_LEFT_VIEWS', view)

+ 1 - 1
ruoyi-ui/src/views/index.vue

@@ -114,7 +114,7 @@ export default {
   data() {
     return {
       // 版本号
-      version: "4.3.0-beta2",
+      version: "4.3.0",
     };
   },
   methods: {

+ 7 - 3
ruoyi-ui/src/views/system/dept/index.vue

@@ -297,9 +297,13 @@ export default {
         this.form = response.data;
         this.open = true;
         this.title = "修改部门";
-      });
-      listDeptExcludeChild(row.deptId).then(response => {
-        this.deptOptions = this.handleTree(response.data, "deptId");
+        listDeptExcludeChild(row.deptId).then(response => {
+          this.deptOptions = this.handleTree(response.data, "deptId");
+          if (this.deptOptions.length == 0) {
+            const noResultsOptions = { deptId: this.form.parentId, deptName: this.form.parentName, children: [] };
+            this.deptOptions.push(noResultsOptions);
+          }
+        });
       });
     },
     /** 提交按钮 */

+ 7 - 7
ruoyi-ui/src/views/system/menu/index.vue

@@ -107,7 +107,7 @@
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
         <el-row>
           <el-col :span="24">
-            <el-form-item label="上级菜单">
+            <el-form-item label="上级菜单" prop="parentId">
               <treeselect
                 v-model="form.parentId"
                 :options="menuOptions"
@@ -159,7 +159,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType != 'F'">
-            <el-form-item>
+            <el-form-item prop="isFrame">
               <span slot="label">
                 <el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
                 <i class="el-icon-question"></i>
@@ -195,7 +195,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType != 'M'">
-            <el-form-item>
+            <el-form-item prop="perms">
               <el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
               <span slot="label">
                 <el-tooltip content="控制器中定义的权限字符,如:@SaCheckPermission('system:user:list')" placement="top">
@@ -206,7 +206,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType == 'C'">
-            <el-form-item>
+            <el-form-item prop="queryParam">
               <el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
               <span slot="label">
                 <el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
@@ -217,7 +217,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType == 'C'">
-            <el-form-item>
+            <el-form-item prop="isCache">
               <span slot="label">
                 <el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
                 <i class="el-icon-question"></i>
@@ -231,7 +231,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType != 'F'">
-            <el-form-item>
+            <el-form-item prop="visible">
               <span slot="label">
                 <el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
                 <i class="el-icon-question"></i>
@@ -248,7 +248,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12" v-if="form.menuType != 'F'">
-            <el-form-item>
+            <el-form-item prop="status">
               <span slot="label">
                 <el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
                 <i class="el-icon-question"></i>

+ 6 - 12
ruoyi-ui/src/views/system/role/index.vue

@@ -254,9 +254,8 @@
 </template>
 
 <script>
-import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus } from "@/api/system/role";
+import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role";
 import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
-import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept";
 
 export default {
   name: "Role",
@@ -364,12 +363,6 @@ export default {
         this.menuOptions = response.data;
       });
     },
-    /** 查询部门树结构 */
-    getDeptTreeselect() {
-      deptTreeselect().then(response => {
-        this.deptOptions = response.data;
-      });
-    },
     // 所有菜单节点数据
     getMenuAllCheckedKeys() {
       // 目前被选中的菜单节点
@@ -396,8 +389,8 @@ export default {
       });
     },
     /** 根据角色ID查询部门树结构 */
-    getRoleDeptTreeselect(roleId) {
-      return roleDeptTreeselect(roleId).then(response => {
+    getDeptTree(roleId) {
+      return deptTreeSelect(roleId).then(response => {
         this.deptOptions = response.data.depts;
         return response;
       });
@@ -543,12 +536,12 @@ export default {
     /** 分配数据权限操作 */
     handleDataScope(row) {
       this.reset();
-      const roleDeptTreeselect = this.getRoleDeptTreeselect(row.roleId);
+      const deptTreeSelect = this.getDeptTree(row.roleId);
       getRole(row.roleId).then(response => {
         this.form = response.data;
         this.openDataScope = true;
         this.$nextTick(() => {
-          roleDeptTreeselect.then(res => {
+          deptTreeSelect.then(res => {
             this.$refs.dept.setCheckedKeys(res.data.checkedKeys);
           });
         });
@@ -612,3 +605,4 @@ export default {
   }
 };
 </script>
+

+ 4 - 7
ruoyi-ui/src/views/system/user/index.vue

@@ -342,9 +342,8 @@
 </template>
 
 <script>
-import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
+import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user";
 import { getToken } from "@/utils/auth";
-import { treeselect } from "@/api/system/dept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 
@@ -462,7 +461,7 @@ export default {
   },
   created() {
     this.getList();
-    this.getTreeselect();
+    this.getDeptTree();
     this.getConfigKey("sys.user.initPassword").then(response => {
       this.initPassword = response.msg;
     });
@@ -479,8 +478,8 @@ export default {
       );
     },
     /** 查询部门下拉树结构 */
-    getTreeselect() {
-      treeselect().then(response => {
+    getDeptTree() {
+      deptTreeSelect().then(response => {
         this.deptOptions = response.data;
       });
     },
@@ -561,7 +560,6 @@ export default {
     /** 新增按钮操作 */
     handleAdd() {
       this.reset();
-      this.getTreeselect();
       getUser().then(response => {
         this.postOptions = response.data.posts;
         this.roleOptions = response.data.roles;
@@ -573,7 +571,6 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      this.getTreeselect();
       const userId = row.userId || this.ids;
       getUser(userId).then(response => {
         this.form = response.data.user;

+ 1 - 1
ruoyi-ui/src/views/system/user/profile/index.vue

@@ -49,7 +49,7 @@
               <userInfo :user="user" />
             </el-tab-pane>
             <el-tab-pane label="修改密码" name="resetPwd">
-              <resetPwd :user="user" />
+              <resetPwd />
             </el-tab-pane>
           </el-tabs>
         </el-card>

+ 0 - 109
script/docker/deploy.sh

@@ -1,109 +0,0 @@
-#!/bin/bash
-
-#使用说明,用来提示输入参数
-usage() {
-    echo "Usage: sh 执行脚本.sh [port|mount|monitor|base|start|stop|stopall|rm|rmiNoneTag]"
-    exit 1
-}
-
-#开启所需端口(生产环境不推荐开启)
-port(){
-    # mysql 端口
-    firewall-cmd --add-port=3306/tcp --permanent
-    # redis 端口
-    firewall-cmd --add-port=6379/tcp --permanent
-    # minio api 端口
-    firewall-cmd --add-port=9000/tcp --permanent
-    # minio 控制台端口
-    firewall-cmd --add-port=9001/tcp --permanent
-    # 监控中心端口
-    firewall-cmd --add-port=9090/tcp --permanent
-    # 任务调度中心端口
-    firewall-cmd --add-port=9100/tcp --permanent
-    # 重启防火墙
-    service firewalld restart
-}
-
-##放置挂载文件
-mount(){
-    #挂载 nginx 配置文件
-    if test ! -f "/docker/nginx/" ;then
-        mkdir -p /docker/nginx/
-        cp -r nginx/* /docker/nginx/
-    fi
-    #挂载 redis 配置文件
-    if test ! -f "/docker/redis/" ;then
-        mkdir -p /docker/redis/
-        cp -r redis/* /docker/redis/
-    fi
-    chmod -R 777 /docker
-}
-
-#启动基础模块
-base(){
-    docker-compose up -d mysql nginx-web redis minio
-}
-
-#启动监控模块
-monitor(){
-    docker-compose up -d ruoyi-monitor-admin
-}
-
-#启动程序模块
-start(){
-    docker-compose up -d ruoyi-xxl-job-admin ruoyi-server1 ruoyi-server2
-}
-
-#停止程序模块
-stop(){
-    docker-compose stop ruoyi-xxl-job-admin ruoyi-server1 ruoyi-server2
-}
-
-#关闭所有模块
-stopall(){
-    docker-compose stop
-}
-
-#删除所有模块
-rm(){
-    docker-compose rm
-}
-
-#删除Tag为空的镜像
-rmiNoneTag(){
-    docker images|grep none|awk '{print $3}'|xargs docker rmi -f
-}
-
-#根据输入参数,选择执行对应方法,不输入则执行使用说明
-case "$1" in
-"port")
-    port
-;;
-"mount")
-    mount
-;;
-"base")
-    base
-;;
-"monitor")
-    monitor
-;;
-"start")
-    start
-;;
-"stop")
-    stop
-;;
-"stopall")
-    stopall
-;;
-"rm")
-    rm
-;;
-"rmiNoneTag")
-    rmiNoneTag
-;;
-*)
-    usage
-;;
-esac

+ 6 - 5
script/docker/docker-compose.yml

@@ -82,7 +82,8 @@ services:
       # 管理后台密码,最小8个字符
       MINIO_SECRET_KEY: ruoyi123
       # https需要指定域名
-      MINIO_SERVER_URL: ""
+      #MINIO_SERVER_URL: "https://xxx.com:9000"
+      #MINIO_BROWSER_REDIRECT_URL: "https://xxx.com:9001"
       # 开启压缩 on 开启 off 关闭
       MINIO_COMPRESS: "off"
       # 扩展名 .pdf,.doc 为空 所有类型均压缩
@@ -99,7 +100,7 @@ services:
     network_mode: "host"
 
   ruoyi-server1:
-    image: ruoyi/ruoyi-server:4.3.0-beta2
+    image: ruoyi/ruoyi-server:4.3.0
     container_name: ruoyi-server1
     environment:
       # 时区上海
@@ -112,7 +113,7 @@ services:
     network_mode: "host"
 
   ruoyi-server2:
-    image: "ruoyi/ruoyi-server:4.3.0-beta2"
+    image: "ruoyi/ruoyi-server:4.3.0"
     container_name: ruoyi-server2
     environment:
       # 时区上海
@@ -125,7 +126,7 @@ services:
     network_mode: "host"
 
   ruoyi-monitor-admin:
-    image: ruoyi/ruoyi-monitor-admin:4.3.0-beta2
+    image: ruoyi/ruoyi-monitor-admin:4.3.0
     container_name: ruoyi-monitor-admin
     environment:
       # 时区上海
@@ -137,7 +138,7 @@ services:
     network_mode: "host"
 
   ruoyi-xxl-job-admin:
-    image: ruoyi/ruoyi-xxl-job-admin:4.3.0-beta2
+    image: ruoyi/ruoyi-xxl-job-admin:4.3.0
     container_name: ruoyi-xxl-job-admin
     environment:
       # 时区上海

+ 4 - 3
script/sql/oracle/oracle_ry_vue_4.X.sql

@@ -228,7 +228,7 @@ comment on column sys_menu.query_param  is '路由参数';
 comment on column sys_menu.is_frame     is '是否为外链(0是 1否)';
 comment on column sys_menu.is_cache     is '是否缓存(0缓存 1不缓存)';
 comment on column sys_menu.menu_type    is '菜单类型(M目录 C菜单 F按钮)';
-comment on column sys_menu.visible      is '菜单状态(0显示 1隐藏)';
+comment on column sys_menu.visible      is '显示状态(0显示 1隐藏)';
 comment on column sys_menu.status       is '菜单状态(0正常 1停用)';
 comment on column sys_menu.perms        is '权限标识';
 comment on column sys_menu.icon         is '菜单图标';
@@ -642,6 +642,7 @@ insert into sys_dict_data values(14, 1,  '通知',     '1',       'sys_notice_ty
 insert into sys_dict_data values(15, 2,  '公告',     '2',       'sys_notice_type',     '',   'success', 'N', '0', 'admin', sysdate, '', null, '公告');
 insert into sys_dict_data values(16, 1,  '正常',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', sysdate, '', null, '正常状态');
 insert into sys_dict_data values(17, 2,  '关闭',     '1',       'sys_notice_status',   '',   'danger',  'N', '0', 'admin', sysdate, '', null, '关闭状态');
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate, '', null, '其他操作');
 insert into sys_dict_data values(18, 1,  '新增',     '1',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate, '', null, '新增操作');
 insert into sys_dict_data values(19, 2,  '修改',     '2',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate, '', null, '修改操作');
 insert into sys_dict_data values(20, 3,  '删除',     '3',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate, '', null, '删除操作');
@@ -873,7 +874,7 @@ create table sys_oss (
   original_name   varchar(255)  not null,
   file_suffix     varchar(10)  not null,
   url             varchar(500) not null,
-  service         varchar(10)  default 'minio' not null,
+  service         varchar(20)  default 'minio' not null,
   create_by       varchar(64)  default '',
   create_time     date,
   update_by       varchar(64)  default '',
@@ -900,7 +901,7 @@ comment on column sys_oss.update_by is '更新者';
 -- ----------------------------
 create table sys_oss_config (
   oss_config_id   number(20)    not null,
-  config_key      varchar(255)  not null,
+  config_key      varchar(20)   not null,
   access_key      varchar(255)  default '',
   secret_key      varchar(255)  default '',
   bucket_name     varchar(255)  default '',

+ 10 - 3
script/sql/postgres/postgres_ry_vue_4.X.sql

@@ -231,7 +231,7 @@ comment on column sys_menu.query_param is '路由参数';
 comment on column sys_menu.is_frame is '是否为外链(0是 1否)';
 comment on column sys_menu.is_cache is '是否缓存(0缓存 1不缓存)';
 comment on column sys_menu.menu_type is '菜单类型(M目录 C菜单 F按钮)';
-comment on column sys_menu.visible is '菜单状态(0显示 1隐藏)';
+comment on column sys_menu.visible is '显示状态(0显示 1隐藏)';
 comment on column sys_menu.status is '菜单状态(0正常 1停用)';
 comment on column sys_menu.perms is '权限标识';
 comment on column sys_menu.icon is '菜单图标';
@@ -650,6 +650,7 @@ insert into sys_dict_data values(14, 1,  '通知',     '1',       'sys_notice_ty
 insert into sys_dict_data values(15, 2,  '公告',     '2',       'sys_notice_type',     '',   'success', 'N', '0', 'admin', now(), '', null, '公告');
 insert into sys_dict_data values(16, 1,  '正常',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', now(), '', null, '正常状态');
 insert into sys_dict_data values(17, 2,  '关闭',     '1',       'sys_notice_status',   '',   'danger',  'N', '0', 'admin', now(), '', null, '关闭状态');
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', now(), '', null, '其他操作');
 insert into sys_dict_data values(18, 1,  '新增',     '1',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', now(), '', null, '新增操作');
 insert into sys_dict_data values(19, 2,  '修改',     '2',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', now(), '', null, '修改操作');
 insert into sys_dict_data values(20, 3,  '删除',     '3',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', now(), '', null, '删除操作');
@@ -890,7 +891,7 @@ create table if not exists sys_oss
     create_time   timestamp,
     update_by     varchar(64)  default ''::varchar,
     update_time   timestamp,
-    service       varchar(10)  default 'minio'::varchar,
+    service       varchar(20)  default 'minio'::varchar,
     constraint sys_oss_pk primary key (oss_id)
 );
 
@@ -913,7 +914,7 @@ drop table if exists sys_oss_config;
 create table if not exists sys_oss_config
 (
     oss_config_id int8,
-    config_key    varchar(255) default ''::varchar not null,
+    config_key    varchar(20)  default ''::varchar not null,
     access_key    varchar(255) default ''::varchar,
     secret_key    varchar(255) default ''::varchar,
     bucket_name   varchar(255) default ''::varchar,
@@ -957,3 +958,9 @@ insert into sys_oss_config values (3, 'aliyun', 'XXXXXXXXXXXXXXX',  'XXXXXXXXXXX
 insert into sys_oss_config values (4, 'qcloud', 'XXXXXXXXXXXXXXX',  'XXXXXXXXXXXXXXX', 'ruoyi-1250000000',  '', 'cos.ap-beijing.myqcloud.com',         '','N', 'ap-beijing',  '1', '', 'admin', now(), 'admin', now(), null);
 insert into sys_oss_config values (5, 'image',  'ruoyi',            'ruoyi123',        'ruoyi',             'image', '127.0.0.1:9000',                 '','N', '',            '1', '', 'admin', now(), 'admin', now(), NULL);
 
+-- 字符串自动转时间 避免框架时间查询报错问题
+create or replace function cast_varchar_to_timestamp(varchar) returns timestamptz as $$
+select to_timestamp($1, 'yyyy-mm-dd hh24:mi:ss');
+$$ language sql strict ;
+
+create cast (varchar as timestamptz) with function cast_varchar_to_timestamp as IMPLICIT;

+ 4 - 3
script/sql/ry_vue_4.X.sql

@@ -141,7 +141,7 @@ create table sys_menu (
   is_frame          int(1)          default 1                  comment '是否为外链(0是 1否)',
   is_cache          int(1)          default 0                  comment '是否缓存(0缓存 1不缓存)',
   menu_type         char(1)         default ''                 comment '菜单类型(M目录 C菜单 F按钮)',
-  visible           char(1)         default 0                  comment '菜单状态(0显示 1隐藏)',
+  visible           char(1)         default 0                  comment '显示状态(0显示 1隐藏)',
   status            char(1)         default 0                  comment '菜单状态(0正常 1停用)',
   perms             varchar(100)    default null               comment '权限标识',
   icon              varchar(100)    default '#'                comment '菜单图标',
@@ -499,6 +499,7 @@ insert into sys_dict_data values(14, 1,  '通知',     '1',       'sys_notice_ty
 insert into sys_dict_data values(15, 2,  '公告',     '2',       'sys_notice_type',     '',   'success', 'N', '0', 'admin', sysdate(), '', null, '公告');
 insert into sys_dict_data values(16, 1,  '正常',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
 insert into sys_dict_data values(17, 2,  '关闭',     '1',       'sys_notice_status',   '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '关闭状态');
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '其他操作');
 insert into sys_dict_data values(18, 1,  '新增',     '1',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '新增操作');
 insert into sys_dict_data values(19, 2,  '修改',     '2',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '修改操作');
 insert into sys_dict_data values(20, 3,  '删除',     '3',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '删除操作');
@@ -654,7 +655,7 @@ create table sys_oss (
   create_by       varchar(64)           default ''        comment '上传人',
   update_time     datetime              default null      comment '更新时间',
   update_by       varchar(64)           default ''        comment '更新人',
-  service         varchar(10)  not null default 'minio'   comment '服务商',
+  service         varchar(20)  not null default 'minio'   comment '服务商',
   primary key (oss_id)
 ) engine=innodb comment ='OSS对象存储表';
 
@@ -664,7 +665,7 @@ create table sys_oss (
 drop table if exists sys_oss_config;
 create table sys_oss_config (
   oss_config_id   bigint(20)   not null                   comment '主建',
-  config_key      varchar(255)  not null default ''       comment '配置key',
+  config_key      varchar(20)  not null   default ''      comment '配置key',
   access_key      varchar(255)            default ''      comment 'accessKey',
   secret_key      varchar(255)            default ''      comment '秘钥',
   bucket_name     varchar(255)            default ''      comment '桶名称',

+ 5 - 3
script/sql/sqlserver/sqlserver_ry_vue_4.X.sql

@@ -702,6 +702,8 @@ INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [d
 GO
 INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [dict_type], [css_class], [list_class], [is_default], [status], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (17, 2, N'关闭', N'1', N'sys_notice_status', N'', N'danger', N'N', N'0', N'admin', getdate(), N'', NULL, N'关闭状态')
 GO
+INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [dict_type], [css_class], [list_class], [is_default], [status], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (29, 99, N'其他', N'0', N'sys_oper_type', N'', N'info', N'N', N'0', N'admin', getdate(), N'', NULL, N'其他操作');
+GO
 INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [dict_type], [css_class], [list_class], [is_default], [status], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (18, 1, N'新增', N'1', N'sys_oper_type', N'', N'info', N'N', N'0', N'admin', getdate(), N'', NULL, N'新增操作')
 GO
 INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [dict_type], [css_class], [list_class], [is_default], [status], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (19, 2, N'修改', N'2', N'sys_oper_type', N'', N'info', N'N', N'0', N'admin', getdate(), N'', NULL, N'修改操作')
@@ -991,7 +993,7 @@ EXEC sys.sp_addextendedproperty
     'COLUMN', N'menu_type'
 GO
 EXEC sys.sp_addextendedproperty
-    'MS_Description', N'菜单状态(0显示 1隐藏)' ,
+    'MS_Description', N'显示状态(0显示 1隐藏)' ,
     'SCHEMA', N'dbo',
     'TABLE', N'sys_menu',
     'COLUMN', N'visible'
@@ -2114,7 +2116,7 @@ CREATE TABLE [sys_oss]
     [create_by]     nvarchar(64)  DEFAULT ''        NULL,
     [update_time]   datetime2(7)                    NULL,
     [update_by]     nvarchar(64)  DEFAULT ''        NULL,
-    [service]       nvarchar(10)  DEFAULT ('minio') NOT NULL,
+    [service]       nvarchar(20)  DEFAULT ('minio') NOT NULL,
     CONSTRAINT [PK__sys_oss__91241EA442389F0D] PRIMARY KEY CLUSTERED ([oss_id])
         WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
         ON [PRIMARY]
@@ -2191,7 +2193,7 @@ GO
 CREATE TABLE [sys_oss_config]
 (
     [oss_config_id] bigint                      NOT NULL,
-    [config_key]    nvarchar(255) DEFAULT ''    NOT NULL,
+    [config_key]    nvarchar(20)  DEFAULT ''    NOT NULL,
     [access_key]    nvarchar(255) DEFAULT ''    NULL,
     [secret_key]    nvarchar(255) DEFAULT ''    NULL,
     [bucket_name]   nvarchar(255) DEFAULT ''    NULL,

+ 2 - 0
script/sql/update/oracle/update-4.2-4.3.sql

@@ -7,3 +7,5 @@ update sys_config set config_key = 'sys.account.captchaEnabled' where config_id
 insert into sys_menu values('1050', '账户解锁', '501', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock',  '#', 'admin', sysdate, '', null, '');
 
 insert into sys_role_menu values ('2', '1050');
+
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate, '', null, '其他操作');

+ 10 - 0
script/sql/update/postgres/update-4.2-4.3.sql

@@ -7,3 +7,13 @@ update sys_config set config_key = 'sys.account.captchaEnabled' where config_id
 insert into sys_menu values('1050', '账户解锁', '501', '4', '#', '', '', '1', '0', 'F', '0', '0', 'monitor:logininfor:unlock',  '#', 'admin', now(), '', null, '');
 
 insert into sys_role_menu values ('2', '1050');
+
+-- 字符串自动转时间 避免框架时间查询报错问题
+create or replace function cast_varchar_to_timestamp(varchar) returns timestamptz as $$
+select to_timestamp($1, 'yyyy-mm-dd hh24:mi:ss');
+$$ language sql strict ;
+
+create cast (varchar as timestamptz) with function cast_varchar_to_timestamp as IMPLICIT;
+
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', now(), '', null, '其他操作');
+

+ 3 - 0
script/sql/update/sqlserver/update-4.2-4.3.sql

@@ -12,3 +12,6 @@ GO
 
 INSERT [sys_role_menu] ([role_id], [menu_id]) VALUES (2, 1050)
 GO
+
+INSERT [sys_dict_data] ([dict_code], [dict_sort], [dict_label], [dict_value], [dict_type], [css_class], [list_class], [is_default], [status], [create_by], [create_time], [update_by], [update_time], [remark]) VALUES (29, 99, N'其他', N'0', N'sys_oper_type', N'', N'info', N'N', N'0', N'admin', getdate(), N'', NULL, N'其他操作');
+GO

+ 2 - 0
script/sql/update/update-4.2-4.3.sql

@@ -7,3 +7,5 @@ update sys_config set config_key = 'sys.account.captchaEnabled' where config_id
 insert into sys_menu values('1050', '账户解锁', '501', '4', '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock',  '#', 'admin', sysdate(), '', null, '');
 
 insert into sys_role_menu values ('2', '1050');
+
+insert into sys_dict_data values(29, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '其他操作');