diff --git a/pom.xml b/pom.xml
index eb11dd3d..4b39a3d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,27 +14,26 @@
0.7.2
- 2.7.5
+ 2.7.6
UTF-8
UTF-8
1.8
3.2.2
2.2.2
- 1.2.12
- 1.6.12
+ 1.6.13
5.2.3
- 3.1.1
+ 3.1.3
2.3
- 1.31.0
+ 1.33.0
3.5.2
3.9.1
- 5.8.8
+ 5.8.10
4.10.0
- 2.7.6
- 3.17.7
- 2.2.2
+ 2.7.7
+ 3.18.0
+ 2.2.3
3.5.2
- 1.5.0
+ 2.14.2
2.3.1
1.18.24
6.7.2
@@ -45,10 +44,10 @@
1.32
- 1.12.324
+ 1.12.349
2.0.22
- 3.1.611
+ 3.1.635
@@ -73,13 +72,6 @@
import
-
-
- com.alibaba
- druid-spring-boot-starter
- ${druid.version}
-
-
org.springdoc
springdoc-openapi-webmvc-core
@@ -190,7 +182,7 @@
com.tencentcloudapi
- tencentcloud-sdk-java
+ tencentcloud-sdk-java-sms
${tencent.sms.version}
@@ -225,29 +217,9 @@
- com.yomahub
- tlog-web-spring-boot-starter
- ${tlog.version}
-
-
- log4j
- log4j
-
-
- dom4j
- dom4j
-
-
- commons-beanutils
- commons-beanutils
-
-
-
-
-
- com.yomahub
- tlog-xxljob-spring-boot-starter
- ${tlog.version}
+ com.alibaba
+ transmittable-thread-local
+ ${alibaba-ttl.version}
@@ -381,6 +353,19 @@
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+ -Dfile.encoding=UTF-8
+
+ ${profiles.active}
+
+ exclude
+
+
@@ -405,8 +390,8 @@
public
- aliyun nexus
- https://maven.aliyun.com/repository/public/
+ huawei nexus
+ https://mirrors.huaweicloud.com/repository/maven/
true
@@ -416,8 +401,8 @@
public
- aliyun nexus
- https://maven.aliyun.com/repository/public/
+ huawei nexus
+ https://mirrors.huaweicloud.com/repository/maven/
true
diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile
index 7bb2b0d0..6033f7e8 100644
--- a/ruoyi-admin/Dockerfile
+++ b/ruoyi-admin/Dockerfile
@@ -2,9 +2,9 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
-RUN mkdir -p /ruoyi/server
-RUN mkdir -p /ruoyi/server/logs
-RUN mkdir -p /ruoyi/server/temp
+RUN mkdir -p /ruoyi/server/logs \
+ /ruoyi/server/temp \
+ /ruoyi/skywalking/agent
WORKDIR /ruoyi/server
@@ -14,4 +14,10 @@ EXPOSE ${SERVER_PORT}
ADD ./target/ruoyi-admin.jar ./app.jar
-ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dserver.port=${SERVER_PORT}","-jar", "app.jar"]
+ENTRYPOINT ["java", \
+ "-Djava.security.egd=file:/dev/./urandom", \
+ "-Dserver.port=${SERVER_PORT}", \
+ # 应用名称 如果想区分集群节点监控 改成不同的名称即可
+# "-Dskywalking.agent.service_name=ruoyi-server", \
+# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \
+ "-jar", "app.jar"]
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index ec98c454..77447e20 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -26,8 +26,8 @@
- mysql
- mysql-connector-java
+ com.mysql
+ mysql-connector-j
@@ -84,6 +84,24 @@
ruoyi-flowable
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
index 01a4a82c..b0b574c3 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
@@ -42,7 +42,7 @@ public class SysUserOnlineController extends BaseController {
@GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName) {
// 获取所有未过期的 token
- List keys = StpUtil.searchTokenValue("", -1, 0, false);
+ List keys = StpUtil.searchTokenValue("", 0, -1, false);
List userOnlineDTOList = new ArrayList<>();
for (String key : keys) {
String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, "");
@@ -83,7 +83,7 @@ public class SysUserOnlineController extends BaseController {
public R forceLogout(@PathVariable String tokenId) {
try {
StpUtil.kickoutByTokenValue(tokenId);
- } catch (NotLoginException e) {
+ } catch (NotLoginException ignored) {
}
return R.ok();
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
index 411eee9e..fa763df3 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
@@ -108,10 +108,10 @@ public class SysDeptController extends BaseController {
@DeleteMapping("/{deptId}")
public R remove(@PathVariable Long deptId) {
if (deptService.hasChildByDeptId(deptId)) {
- return R.fail("存在下级部门,不允许删除");
+ return R.warn("存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId)) {
- return R.fail("部门存在用户,不允许删除");
+ return R.warn("部门存在用户,不允许删除");
}
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId));
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
index 2000fd03..e80f0ee7 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
@@ -117,10 +117,10 @@ public class SysMenuController extends BaseController {
@DeleteMapping("/{menuId}")
public R remove(@PathVariable("menuId") Long menuId) {
if (menuService.hasChildByMenuId(menuId)) {
- return R.fail("存在子菜单,不允许删除");
+ return R.warn("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId)) {
- return R.fail("菜单已分配,不允许删除");
+ return R.warn("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
index cdba39cc..8dc4876e 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
@@ -66,7 +66,7 @@ public class SysOssConfigController extends BaseController {
@RepeatSubmit()
@PostMapping()
public R add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
- return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0);
+ return toAjax(iSysOssConfigService.insertByBo(bo));
}
/**
@@ -77,7 +77,7 @@ public class SysOssConfigController extends BaseController {
@RepeatSubmit()
@PutMapping()
public R edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
- return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0);
+ return toAjax(iSysOssConfigService.updateByBo(bo));
}
/**
@@ -90,7 +90,7 @@ public class SysOssConfigController extends BaseController {
@DeleteMapping("/{ossConfigIds}")
public R remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ossConfigIds) {
- return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0);
+ return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
}
/**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
index fac5ddef..606895a7 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
@@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.oss.core.OssClient;
+import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
@@ -80,7 +82,7 @@ public class SysOssController extends BaseController {
if (ObjectUtil.isNull(file)) {
throw new ServiceException("上传文件不能为空");
}
- SysOss oss = iSysOssService.upload(file);
+ SysOssVo oss = iSysOssService.upload(file);
Map map = new HashMap<>(2);
map.put("url", oss.getUrl());
map.put("fileName", oss.getOriginalName());
@@ -96,23 +98,7 @@ public class SysOssController extends BaseController {
@SaCheckPermission("system:oss:download")
@GetMapping("/download/{ossId}")
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
- SysOssVo sysOss = iSysOssService.getById(ossId);
- if (ObjectUtil.isNull(sysOss)) {
- throw new ServiceException("文件数据不存在!");
- }
- FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
- response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
- long data;
- try {
- data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
- } catch (HttpException e) {
- if (e.getMessage().contains("403")) {
- throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
- } else {
- throw new ServiceException(e.getMessage());
- }
- }
- response.setContentLength(Convert.toInt(data));
+ iSysOssService.download(ossId,response);
}
/**
@@ -125,7 +111,7 @@ public class SysOssController extends BaseController {
@DeleteMapping("/{ossIds}")
public R remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ossIds) {
- return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0);
+ return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
}
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
index 5c331681..77a8767d 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -12,6 +12,7 @@ import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.system.domain.SysOss;
+import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysOssService;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
@@ -115,7 +116,7 @@ public class SysProfileController extends BaseController {
if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
}
- SysOss oss = iSysOssService.upload(avatarfile);
+ SysOssVo oss = iSysOssService.upload(avatarfile);
String avatar = oss.getUrl();
if (userService.updateUserAvatar(getUsername(), avatar)) {
ajax.put("imgUrl", avatar);
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index 215b53c9..7e358d51 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -1,6 +1,5 @@
package com.ruoyi.web.controller.system;
-import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
@@ -66,15 +65,6 @@ public class SysUserController extends BaseController {
return userService.selectPageUserList(user, pageQuery);
}
- /**
- * 查询用户列表,用于用户选择场景
- */
- @SaCheckLogin
- @GetMapping("/selectUser")
- public TableDataInfo selectUser(SysUser user, PageQuery pageQuery) {
- return userService.selectPageUserList(user, pageQuery);
- }
-
/**
* 导出用户列表
*/
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 5844a242..98041c09 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -33,7 +33,7 @@ xxl.job:
--- # 数据源配置
spring:
datasource:
- type: com.alibaba.druid.pool.DruidDataSource
+ type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
@@ -45,6 +45,7 @@ spring:
datasource:
# 主库数据源
master:
+ type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
@@ -54,72 +55,46 @@ spring:
# 从库数据源
slave:
lazy: true
+ type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
- url:
+ url: jdbc:mysql://localhost:3306/ry-flowable-plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
username:
password:
# oracle:
+# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
-# druid:
-# validationQuery: SELECT 1 FROM DUAL
+# hikari:
+# connectionTestQuery: SELECT 1 FROM DUAL
# postgres:
+# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
+# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
-# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true
+# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
- druid:
- # 初始连接数
- initialSize: 5
- # 最小连接池数量
- minIdle: 10
+ hikari:
# 最大连接池数量
- maxActive: 20
+ maxPoolSize: 20
+ # 最小空闲线程数量
+ minIdle: 10
# 配置获取连接等待超时的时间
- maxWait: 60000
- # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
- timeBetweenEvictionRunsMillis: 60000
- # 配置一个连接在池中最小生存的时间,单位是毫秒
- minEvictableIdleTimeMillis: 300000
- # 配置一个连接在池中最大生存的时间,单位是毫秒
- maxEvictableIdleTimeMillis: 900000
- # 配置检测连接是否有效
- validationQuery: SELECT 1
- testWhileIdle: true
- testOnBorrow: false
- testOnReturn: false
- # 注意这个值和druid原生不一致,默认启动了stat
- filters: stat
-
---- # druid 配置
-spring.datasource.druid:
- webStatFilter:
- enabled: true
- statViewServlet:
- enabled: true
- # 设置白名单,不填则允许所有访问
- allow:
- url-pattern: /druid/*
- # 控制台管理用户名和密码
- login-username: ruoyi
- login-password: 123456
- filter:
- stat:
- enabled: true
- # 慢SQL记录
- log-slow-sql: true
- slow-sql-millis: 1000
- merge-sql: true
- wall:
- config:
- multi-statement-allow: true
+ connectionTimeout: 10000
+ # 校验超时时间
+ validationTimeout: 5000
+ # 空闲连接存活最大时间,默认10分钟
+ idleTimeout: 60000
+ # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
+ maxLifetime: 900000
+ # 连接测试query(配置检测连接是否有效)
+ connectionTestQuery: SELECT 1
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring:
diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml
index 0987874f..970fe4c5 100644
--- a/ruoyi-admin/src/main/resources/application-prod.yml
+++ b/ruoyi-admin/src/main/resources/application-prod.yml
@@ -36,7 +36,7 @@ xxl.job:
--- # 数据源配置
spring:
datasource:
- type: com.alibaba.druid.pool.DruidDataSource
+ type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
@@ -48,6 +48,7 @@ spring:
datasource:
# 主库数据源
master:
+ type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
@@ -57,72 +58,46 @@ spring:
# 从库数据源
slave:
lazy: true
+ type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
- url:
+ url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username:
password:
# oracle:
+# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
-# druid:
-# validationQuery: SELECT 1 FROM DUAL
+# hikari:
+# connectionTestQuery: SELECT 1 FROM DUAL
# postgres:
+# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
+# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
-# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true
+# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
- druid:
- # 初始连接数
- initialSize: 5
- # 最小连接池数量
- minIdle: 10
+ hikari:
# 最大连接池数量
- maxActive: 20
+ maxPoolSize: 20
+ # 最小空闲线程数量
+ minIdle: 10
# 配置获取连接等待超时的时间
- maxWait: 60000
- # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
- timeBetweenEvictionRunsMillis: 60000
- # 配置一个连接在池中最小生存的时间,单位是毫秒
- minEvictableIdleTimeMillis: 300000
- # 配置一个连接在池中最大生存的时间,单位是毫秒
- maxEvictableIdleTimeMillis: 900000
- # 配置检测连接是否有效
- validationQuery: SELECT 1
- testWhileIdle: true
- testOnBorrow: false
- testOnReturn: false
- # 注意这个值和druid原生不一致,默认启动了stat
- filters: stat
-
---- # druid 配置
-spring.datasource.druid:
- webStatFilter:
- enabled: true
- statViewServlet:
- enabled: true
- # 设置白名单,不填则允许所有访问
- allow:
- url-pattern: /druid/*
- # 控制台管理用户名和密码
- login-username: ruoyi
- login-password: 123456
- filter:
- stat:
- enabled: true
- # 慢SQL记录
- log-slow-sql: true
- slow-sql-millis: 1000
- merge-sql: true
- wall:
- config:
- multi-statement-allow: true
+ connectionTimeout: 10000
+ # 校验超时时间
+ validationTimeout: 5000
+ # 空闲连接存活最大时间,默认10分钟
+ idleTimeout: 60000
+ # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
+ maxLifetime: 900000
+ # 连接测试query(配置检测连接是否有效)
+ connectionTestQuery: SELECT 1
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring:
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index ab78e332..176cb938 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -115,8 +115,6 @@ sa-token:
token-prefix: "Bearer"
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
- # 是否输出操作日志
- is-log: true
# security配置
security:
@@ -131,8 +129,6 @@ security:
- /favicon.ico
- /*/api-docs
- /*/api-docs/**
- # druid 监控配置
- - /druid/**
# actuator 监控配置
- /actuator
- /actuator/**
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
index b78044b3..40fa33b7 100644
--- a/ruoyi-admin/src/main/resources/logback.xml
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -7,7 +7,7 @@
-
+
${console.log.pattern}
utf-8
@@ -22,7 +22,7 @@
1
-
+
${log.pattern}
utf-8
@@ -42,7 +42,7 @@
60
-
+
${log.pattern}
@@ -64,7 +64,7 @@
60
-
+
${log.pattern}
@@ -78,7 +78,7 @@
-
+
0
@@ -88,7 +88,7 @@
-
+
0
@@ -97,12 +97,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-admin/src/main/resources/spy.properties b/ruoyi-admin/src/main/resources/spy.properties
index bee2392d..abbd8931 100644
--- a/ruoyi-admin/src/main/resources/spy.properties
+++ b/ruoyi-admin/src/main/resources/spy.properties
@@ -24,3 +24,5 @@ outagedetection=true
outagedetectioninterval=2
# 是否过滤 Log
filter=true
+# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
+exclude=SELECT 1
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
new file mode 100644
index 00000000..5b9c9f84
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
@@ -0,0 +1,45 @@
+package com.ruoyi.test;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * 断言单元测试案例
+ *
+ * @author Lion Li
+ */
+@DisplayName("断言单元测试案例")
+public class AssertUnitTest {
+
+ @DisplayName("测试 assertEquals 方法")
+ @Test
+ public void testAssertEquals() {
+ Assertions.assertEquals("666", new String("666"));
+ Assertions.assertNotEquals("666", new String("666"));
+ }
+
+ @DisplayName("测试 assertSame 方法")
+ @Test
+ public void testAssertSame() {
+ Object obj = new Object();
+ Object obj1 = obj;
+ Assertions.assertSame(obj, obj1);
+ Assertions.assertNotSame(obj, obj1);
+ }
+
+ @DisplayName("测试 assertTrue 方法")
+ @Test
+ public void testAssertTrue() {
+ Assertions.assertTrue(true);
+ Assertions.assertFalse(true);
+ }
+
+ @DisplayName("测试 assertNull 方法")
+ @Test
+ public void testAssertNull() {
+ Assertions.assertNull(null);
+ Assertions.assertNotNull(null);
+ }
+
+}
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
new file mode 100644
index 00000000..a40fd827
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
@@ -0,0 +1,70 @@
+package com.ruoyi.test;
+
+import com.ruoyi.common.config.RuoYiConfig;
+import org.junit.jupiter.api.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 单元测试案例
+ *
+ * @author Lion Li
+ */
+@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
+@DisplayName("单元测试案例")
+public class DemoUnitTest {
+
+ @Autowired
+ private RuoYiConfig ruoYiConfig;
+
+ @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
+ @Test
+ public void testTest() {
+ System.out.println(ruoYiConfig);
+ }
+
+ @Disabled
+ @DisplayName("测试 @Disabled 注解")
+ @Test
+ public void testDisabled() {
+ System.out.println(ruoYiConfig);
+ }
+
+ @Timeout(value = 2L, unit = TimeUnit.SECONDS)
+ @DisplayName("测试 @Timeout 注解")
+ @Test
+ public void testTimeout() throws InterruptedException {
+ Thread.sleep(3000);
+ System.out.println(ruoYiConfig);
+ }
+
+
+ @DisplayName("测试 @RepeatedTest 注解")
+ @RepeatedTest(3)
+ public void testRepeatedTest() {
+ System.out.println(666);
+ }
+
+ @BeforeAll
+ public static void testBeforeAll() {
+ System.out.println("@BeforeAll ==================");
+ }
+
+ @BeforeEach
+ public void testBeforeEach() {
+ System.out.println("@BeforeEach ==================");
+ }
+
+ @AfterEach
+ public void testAfterEach() {
+ System.out.println("@AfterEach ==================");
+ }
+
+ @AfterAll
+ public static void testAfterAll() {
+ System.out.println("@AfterAll ==================");
+ }
+
+}
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
new file mode 100644
index 00000000..04bf1b5c
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
@@ -0,0 +1,72 @@
+package com.ruoyi.test;
+
+import com.ruoyi.common.enums.UserType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+/**
+ * 带参数单元测试案例
+ *
+ * @author Lion Li
+ */
+@DisplayName("带参数单元测试案例")
+public class ParamUnitTest {
+
+ @DisplayName("测试 @ValueSource 注解")
+ @ParameterizedTest
+ @ValueSource(strings = {"t1", "t2", "t3"})
+ public void testValueSource(String str) {
+ System.out.println(str);
+ }
+
+ @DisplayName("测试 @NullSource 注解")
+ @ParameterizedTest
+ @NullSource
+ public void testNullSource(String str) {
+ System.out.println(str);
+ }
+
+ @DisplayName("测试 @EnumSource 注解")
+ @ParameterizedTest
+ @EnumSource(UserType.class)
+ public void testEnumSource(UserType type) {
+ System.out.println(type.getUserType());
+ }
+
+ @DisplayName("测试 @MethodSource 注解")
+ @ParameterizedTest
+ @MethodSource("getParam")
+ public void testMethodSource(String str) {
+ System.out.println(str);
+ }
+
+ public static Stream getParam() {
+ List list = new ArrayList<>();
+ list.add("t1");
+ list.add("t2");
+ list.add("t3");
+ return list.stream();
+ }
+
+ @BeforeEach
+ public void testBeforeEach() {
+ System.out.println("@BeforeEach ==================");
+ }
+
+ @AfterEach
+ public void testAfterEach() {
+ System.out.println("@AfterEach ==================");
+ }
+
+
+}
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
new file mode 100644
index 00000000..04240a07
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
@@ -0,0 +1,54 @@
+package com.ruoyi.test;
+
+import org.junit.jupiter.api.*;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * 标签单元测试案例
+ *
+ * @author Lion Li
+ */
+@SpringBootTest
+@DisplayName("标签单元测试案例")
+public class TagUnitTest {
+
+ @Tag("dev")
+ @DisplayName("测试 @Tag dev")
+ @Test
+ public void testTagDev() {
+ System.out.println("dev");
+ }
+
+ @Tag("prod")
+ @DisplayName("测试 @Tag prod")
+ @Test
+ public void testTagProd() {
+ System.out.println("prod");
+ }
+
+ @Tag("local")
+ @DisplayName("测试 @Tag local")
+ @Test
+ public void testTagLocal() {
+ System.out.println("local");
+ }
+
+ @Tag("exclude")
+ @DisplayName("测试 @Tag exclude")
+ @Test
+ public void testTagExclude() {
+ System.out.println("exclude");
+ }
+
+ @BeforeEach
+ public void testBeforeEach() {
+ System.out.println("@BeforeEach ==================");
+ }
+
+ @AfterEach
+ public void testAfterEach() {
+ System.out.println("@AfterEach ==================");
+ }
+
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
deleted file mode 100644
index 51eaf082..00000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 匿名访问不鉴权注解
- *
- * @author ruoyi
- * @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替
- */
-@Deprecated
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface Anonymous {
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java
new file mode 100644
index 00000000..5c14a552
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.annotation;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.jackson.DictDataJsonSerializer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 字典数据映射注解
+ *
+ * @author itino
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+@JacksonAnnotationsInside
+@JsonSerialize(using = DictDataJsonSerializer.class)
+public @interface DictDataMapper {
+
+ /**
+ * 设置字典的type值 (如: sys_user_sex)
+ */
+ String dictType() default "";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
new file mode 100644
index 00000000..f007b8c8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
@@ -0,0 +1,93 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author Lion Li
+ */
+public interface HttpStatus {
+ /**
+ * 操作成功
+ */
+ int SUCCESS = 200;
+
+ /**
+ * 对象创建成功
+ */
+ int CREATED = 201;
+
+ /**
+ * 请求已经被接受
+ */
+ int ACCEPTED = 202;
+
+ /**
+ * 操作已经执行成功,但是没有返回数据
+ */
+ int NO_CONTENT = 204;
+
+ /**
+ * 资源已被移除
+ */
+ int MOVED_PERM = 301;
+
+ /**
+ * 重定向
+ */
+ int SEE_OTHER = 303;
+
+ /**
+ * 资源没有被修改
+ */
+ int NOT_MODIFIED = 304;
+
+ /**
+ * 参数列表错误(缺少,格式不匹配)
+ */
+ int BAD_REQUEST = 400;
+
+ /**
+ * 未授权
+ */
+ int UNAUTHORIZED = 401;
+
+ /**
+ * 访问受限,授权过期
+ */
+ int FORBIDDEN = 403;
+
+ /**
+ * 资源,服务未找到
+ */
+ int NOT_FOUND = 404;
+
+ /**
+ * 不允许的http方法
+ */
+ int BAD_METHOD = 405;
+
+ /**
+ * 资源冲突,或者资源被锁
+ */
+ int CONFLICT = 409;
+
+ /**
+ * 不支持的数据,媒体类型
+ */
+ int UNSUPPORTED_TYPE = 415;
+
+ /**
+ * 系统内部错误
+ */
+ int ERROR = 500;
+
+ /**
+ * 接口未实现
+ */
+ int NOT_IMPLEMENTED = 501;
+
+ /**
+ * 系统警告消息
+ */
+ int WARN = 601;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
index 5a20f9d0..bd316079 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -2,6 +2,8 @@ package com.ruoyi.common.core.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serializable;
@@ -23,6 +25,7 @@ public class BaseEntity implements Serializable {
/**
* 搜索值
*/
+ @JsonIgnore
@TableField(exist = false)
private String searchValue;
@@ -53,6 +56,7 @@ public class BaseEntity implements Serializable {
/**
* 请求参数
*/
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private Map params = new HashMap<>();
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
index 1c7b1d86..381a6f60 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
@@ -1,5 +1,6 @@
package com.ruoyi.common.core.domain;
+import com.ruoyi.common.constant.HttpStatus;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -67,6 +68,27 @@ public class R implements Serializable {
return restResult(null, code, msg);
}
+ /**
+ * 返回警告消息
+ *
+ * @param msg 返回内容
+ * @return 警告消息
+ */
+ public static R warn(String msg) {
+ return restResult(null, HttpStatus.WARN, msg);
+ }
+
+ /**
+ * 返回警告消息
+ *
+ * @param msg 返回内容
+ * @param data 数据对象
+ * @return 警告消息
+ */
+ public static R warn(String msg, T data) {
+ return restResult(data, HttpStatus.WARN, msg);
+ }
+
private static R restResult(T data, int code, String msg) {
R r = new R<>();
r.setCode(code);
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
index ca76e76c..c1cbe3f2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
@@ -12,7 +12,6 @@ import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
/**
* 构建可重复读取inputStream的request
@@ -27,7 +26,7 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
request.setCharacterEncoding(Constants.UTF8);
response.setCharacterEncoding(Constants.UTF8);
- body = IoUtil.readUtf8(request.getInputStream()).getBytes(StandardCharsets.UTF_8);
+ body = IoUtil.readBytes(request.getInputStream(), false);
}
@Override
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
index f1b51315..3646f1fe 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
@@ -1,6 +1,7 @@
package com.ruoyi.common.filter;
import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.http.HttpHeaders;
@@ -50,7 +51,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
}
// 为空,直接返回
- String json = IoUtil.read(super.getInputStream(), StandardCharsets.UTF_8);
+ String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8);
if (StringUtils.isEmpty(json)) {
return super.getInputStream();
}
@@ -88,7 +89,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* 是否是Json请求
- *
*/
public boolean isJsonRequest() {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
index f1216662..a82f4195 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
@@ -2,6 +2,7 @@ package com.ruoyi.common.helper;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.model.LoginUser;
@@ -80,18 +81,12 @@ public class LoginHelper {
LoginUser loginUser = getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
String loginId = StpUtil.getLoginIdAsString();
- String userId = null;
- for (UserType value : UserType.values()) {
- if (StringUtils.contains(loginId, value.getUserType())) {
- String[] strs = StringUtils.split(loginId, JOIN_CODE);
- // 用户id在总是在最后
- userId = strs[strs.length - 1];
- }
- }
- if (StringUtils.isBlank(userId)) {
+ String[] strs = StringUtils.split(loginId, JOIN_CODE);
+ if (!ArrayUtil.containsAny(strs, UserType.values())) {
throw new UtilException("登录用户: LoginId异常 => " + loginId);
}
- return Long.parseLong(userId);
+ // 用户id在总是在最后
+ return Long.parseLong(strs[strs.length - 1]);
}
return loginUser.getUserId();
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java
new file mode 100644
index 00000000..caa059b9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.jackson;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.annotation.DictDataMapper;
+import com.ruoyi.common.core.service.DictService;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * 字典数据json序列化工具
+ *
+ * @author itino
+ */
+@Slf4j
+public class DictDataJsonSerializer extends JsonSerializer implements ContextualSerializer {
+
+ private String dictType;
+
+ @Override
+ public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ try {
+ DictService dictService = SpringUtils.getBean(DictService.class);
+ if (ObjectUtil.isNotNull(dictService)) {
+ String label = dictService.getDictLabel(dictType, value);
+ gen.writeString(StringUtils.isNotBlank(label) ? label : value);
+ } else {
+ gen.writeString(value);
+ }
+ } catch (BeansException e) {
+ log.error("字典数据未查到, 采用默认处理 => {}", e.getMessage());
+ gen.writeString(value);
+ }
+ }
+
+ @Override
+ public JsonSerializer> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
+ DictDataMapper anno = property.getAnnotation(DictDataMapper.class);
+ if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) {
+ this.dictType = anno.dictType();
+ return this;
+ }
+ return prov.findValueSerializer(property.getType(), property);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
index 7012a01f..91ddd3f6 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
@@ -11,6 +11,7 @@ import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
+import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -19,6 +20,9 @@ import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
/**
* 客户端工具类
@@ -70,6 +74,31 @@ public class ServletUtils extends ServletUtil {
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
+ /**
+ * 获得所有请求参数
+ *
+ * @param request 请求对象{@link ServletRequest}
+ * @return Map
+ */
+ public static Map getParams(ServletRequest request) {
+ final Map map = request.getParameterMap();
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * 获得所有请求参数
+ *
+ * @param request 请求对象{@link ServletRequest}
+ * @return Map
+ */
+ public static Map getParamMap(ServletRequest request) {
+ Map params = new HashMap<>();
+ for (Map.Entry entry : getParams(request).entrySet()) {
+ params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+ }
+ return params;
+ }
+
/**
* 获取request
*/
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java
index c14b3938..80f5f528 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java
@@ -327,6 +327,17 @@ public class RedisUtils {
return rMap.getAll(rMap.keySet());
}
+ /**
+ * 获得缓存Map的key列表
+ *
+ * @param key 缓存的键值
+ * @return key列表
+ */
+ public static Set getCacheMapKeySet(final String key) {
+ RMap rMap = CLIENT.getMap(key);
+ return rMap.keySet();
+ }
+
/**
* 往Hash中存入数据
*
diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml
index 2a0335cd..1331fc62 100644
--- a/ruoyi-demo/pom.xml
+++ b/ruoyi-demo/pom.xml
@@ -36,7 +36,7 @@
-
+
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
index caed9756..3bd2867e 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
@@ -46,7 +46,7 @@ public class TestBatchController extends BaseController {
testDemo.setValue("测试新增");
list.add(testDemo);
}
- return toAjax(testDemoMapper.insertBatch(list) ? 1 : 0);
+ return toAjax(testDemoMapper.insertBatch(list));
}
/**
@@ -74,7 +74,7 @@ public class TestBatchController extends BaseController {
testDemo.setId(null);
}
}
- return toAjax(testDemoMapper.insertOrUpdateBatch(list) ? 1 : 0);
+ return toAjax(testDemoMapper.insertOrUpdateBatch(list));
}
/**
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
index 33b34128..873facc3 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
@@ -119,7 +119,7 @@ public class TestDemoController extends BaseController {
// 使用校验工具对标 @Validated(AddGroup.class) 注解
// 用于在非 Controller 的地方校验对象
ValidatorUtils.validate(bo, AddGroup.class);
- return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);
+ return toAjax(iTestDemoService.insertByBo(bo));
}
/**
@@ -130,7 +130,7 @@ public class TestDemoController extends BaseController {
@RepeatSubmit
@PutMapping()
public R edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
- return toAjax(iTestDemoService.updateByBo(bo) ? 1 : 0);
+ return toAjax(iTestDemoService.updateByBo(bo));
}
/**
@@ -143,6 +143,6 @@ public class TestDemoController extends BaseController {
@DeleteMapping("/{ids}")
public R remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
- return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
+ return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
index 52d881ed..db54230c 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
@@ -78,7 +78,7 @@ public class TestTreeController extends BaseController {
@RepeatSubmit
@PostMapping()
public R add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
- return toAjax(iTestTreeService.insertByBo(bo) ? 1 : 0);
+ return toAjax(iTestTreeService.insertByBo(bo));
}
/**
@@ -89,7 +89,7 @@ public class TestTreeController extends BaseController {
@RepeatSubmit
@PutMapping()
public R edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
- return toAjax(iTestTreeService.updateByBo(bo) ? 1 : 0);
+ return toAjax(iTestTreeService.updateByBo(bo));
}
/**
@@ -102,6 +102,6 @@ public class TestTreeController extends BaseController {
@DeleteMapping("/{ids}")
public R remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
- return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
+ return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}
diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
index b506a2dd..02b741f4 100644
--- a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
+++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
@@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
-RUN mkdir -p /ruoyi/monitor
RUN mkdir -p /ruoyi/monitor/logs
WORKDIR /ruoyi/monitor
diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile b/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile
index f7221bdf..bd61580a 100644
--- a/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile
+++ b/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile
@@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
-RUN mkdir -p /ruoyi/xxljob
RUN mkdir -p /ruoyi/xxljob/logs
WORKDIR /ruoyi/xxljob
@@ -14,4 +13,4 @@ EXPOSE 9100
ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar
-ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
\ No newline at end of file
+ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
index d68066da..936a1ab0 100644
--- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
+++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
@@ -64,8 +64,8 @@
- mysql
- mysql-connector-java
+ com.mysql
+ mysql-connector-j
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
index f139717e..274fa0c4 100644
--- a/ruoyi-framework/pom.xml
+++ b/ruoyi-framework/pom.xml
@@ -40,12 +40,6 @@
spring-boot-starter-aop
-
-
- com.alibaba
- druid-spring-boot-starter
-
-
p6spy
@@ -62,17 +56,17 @@
spring-boot-admin-starter-client
+
+ com.alibaba
+ transmittable-thread-local
+
+
com.ruoyi
ruoyi-common
-
- com.yomahub
- tlog-web-spring-boot-starter
-
-
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
index 0159bc3c..3b6a858a 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
@@ -21,7 +21,6 @@ import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -92,7 +91,6 @@ public class LogAspect {
SpringUtils.getBean(OperLogService.class).recordOper(operLog);
} catch (Exception exp) {
// 记录本地异常日志
- log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
@@ -135,8 +133,9 @@ public class LogAspect {
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
} else {
- Map, ?> paramsMap = (Map, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
- operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
+ Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
+ MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES);
+ operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000));
}
}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
deleted file mode 100644
index 6f7a82ec..00000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
-import com.alibaba.druid.util.Utils;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.servlet.*;
-import java.io.IOException;
-
-/**
- * druid 配置多数据源
- *
- * @author ruoyi
- */
-@Configuration
-public class DruidConfig {
-
- /**
- * 去除监控页面底部的广告
- */
- @SuppressWarnings({"rawtypes", "unchecked"})
- @Bean
- @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
- public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
- // 获取web监控页面的参数
- DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
- // 提取common.js的配置路径
- String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
- String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
- final String filePath = "support/http/resources/js/common.js";
- // 创建filter进行过滤
- Filter filter = new Filter() {
- @Override
- public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- chain.doFilter(request, response);
- // 重置缓冲区,响应头不会被重置
-// response.resetBuffer();
- // 获取common.js
- String text = Utils.readFromResource(filePath);
- // 正则替换banner, 除去底部的广告信息
- text = text.replaceAll("
", "");
- text = text.replaceAll("powered.*?shrek.wang", "");
- response.getWriter().write(text);
- }
-
- @Override
- public void destroy() {
- }
- };
- FilterRegistrationBean registrationBean = new FilterRegistrationBean();
- registrationBean.setFilter(filter);
- registrationBean.addUrlPatterns(commonJsPattern);
- return registrationBean;
- }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
index f43ecab7..ea83338b 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -1,7 +1,6 @@
package com.ruoyi.framework.config;
import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
-import com.yomahub.tlog.web.interceptor.TLogWebInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
@@ -21,8 +20,6 @@ public class ResourcesConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
- // 全局链路跟踪拦截器
- registry.addInterceptor(new TLogWebInterceptor());
// 全局访问性能拦截
registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java
index a7c51fa6..29122866 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java
@@ -5,8 +5,6 @@ import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.config.properties.ExcludeUrlProperties;
import com.ruoyi.framework.config.properties.SecurityProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -34,14 +32,10 @@ public class SaTokenConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
// 注册路由拦截器,自定义验证规则
registry.addInterceptor(new SaInterceptor(handler -> {
- // 自定义注解 @Anonymous 匿名访问配置,后续版本将删除
- ExcludeUrlProperties excludeUrlProperties = SpringUtils.getBean(ExcludeUrlProperties.class);
// 登录验证 -- 排除多个路径
SaRouter
// 获取所有的
.match("/**")
- // 排除下不需要拦截的(每次匹配)
- .notMatch(excludeUrlProperties.getExcludes())
// 对未排除的路径进行检查
.check(() -> {
// 检查是否登录 是否有token
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
deleted file mode 100644
index 5ae55add..00000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.yomahub.tlog.springboot.TLogWebAutoConfiguration;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 整合 TLog 框架配置
- *
- * @author Lion Li
- * @since 3.3.0
- */
-@Configuration
-// 排除 web 自动配置 自定义实现
-@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class)
-public class TLogConfig {
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java
deleted file mode 100644
index 99d2eae8..00000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import cn.dev33.satoken.interceptor.SaInterceptor;
-import cn.hutool.core.util.ReUtil;
-import com.ruoyi.common.annotation.Anonymous;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.Getter;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.stereotype.Component;
-import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-import org.springframework.web.util.pattern.PathPattern;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.*;
-import java.util.regex.Pattern;
-
-/**
- * 设置注解允许匿名访问的url
- *
- * @author Lion Li
- * @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替,
- * 底层过滤方法详见 {@link SaInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object)}
- */
-@Deprecated
-@Lazy
-@Component
-public class ExcludeUrlProperties implements InitializingBean {
-
- private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
-
- @Getter
- private final List excludes = new ArrayList<>();
-
- @Override
- public void afterPropertiesSet() {
- String asterisk = "*";
- RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
- Map map = mapping.getHandlerMethods();
-
- map.keySet().forEach(info -> {
- HandlerMethod handlerMethod = map.get(info);
-
- // 获取方法上边的注解 替代path variable 为 *
- Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
- Optional.ofNullable(method).ifPresent(anonymous -> {
- Set patterns = info.getPathPatternsCondition().getPatterns();
- patterns.forEach(url -> {
- excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
- });
- });
-
- // 获取类上边的注解, 替代path variable 为 *
- Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
- Optional.ofNullable(controller).ifPresent(anonymous -> {
- Set patterns = info.getPathPatternsCondition().getPatterns();
- patterns.forEach(url -> {
- excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
- });
- });
- });
- }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
index 9c48c135..a9de17e6 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
@@ -102,6 +102,20 @@ public class UserActionListener implements SaTokenListener {
public void doUntieDisable(String loginType, Object loginId, String service) {
}
+ /**
+ * 每次打开二级认证时触发
+ */
+ @Override
+ public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
+ }
+
+ /**
+ * 每次创建Session时触发
+ */
+ @Override
+ public void doCloseSafe(String loginType, String tokenValue, String service) {
+ }
+
/**
* 每次创建Session时触发
*/
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
index e04d528a..40f2d27c 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -105,7 +105,7 @@ public class GlobalExceptionHandler {
public R handleServiceException(ServiceException e, HttpServletRequest request) {
log.error(e.getMessage(), e);
Integer code = e.getCode();
- return ObjectUtil.isNotNull(code) ? R.fail(code.intValue(), e.getMessage()) : R.fail(e.getMessage());
+ return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
}
/**
diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
index 1b2bc136..3edbc338 100644
--- a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
+++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
@@ -89,7 +89,7 @@ public class ${ClassName}Controller extends BaseController {
@RepeatSubmit()
@PostMapping()
public R add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
- return toAjax(i${ClassName}Service.insertByBo(bo) ? 1 : 0);
+ return toAjax(i${ClassName}Service.insertByBo(bo));
}
/**
@@ -100,7 +100,7 @@ public class ${ClassName}Controller extends BaseController {
@RepeatSubmit()
@PutMapping()
public R edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
- return toAjax(i${ClassName}Service.updateByBo(bo) ? 1 : 0);
+ return toAjax(i${ClassName}Service.updateByBo(bo));
}
/**
@@ -113,6 +113,6 @@ public class ${ClassName}Controller extends BaseController {
@DeleteMapping("/{${pkColumn.javaField}s}")
public R remove(@NotEmpty(message = "主键不能为空")
@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
- return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true) ? 1 : 0);
+ return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true));
}
}
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
index d44e082f..01a7367f 100644
--- a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
@@ -136,24 +136,9 @@
#end
- 修改
- 新增
- 删除
+ 修改
+ 新增
+ 删除
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
index f7c1bd02..d0f4f8bc 100644
--- a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
@@ -148,18 +148,8 @@
#end
- 修改
- 删除
+ 修改
+ 删除
diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml
index 632faf96..a53b53bb 100644
--- a/ruoyi-job/pom.xml
+++ b/ruoyi-job/pom.xml
@@ -29,11 +29,6 @@
xxl-job-core
-
- com.yomahub
- tlog-xxljob-spring-boot-starter
-
-
diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java b/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
index 20afa2e6..4ca170be 100644
--- a/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
+++ b/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
@@ -12,7 +12,6 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
/**
* XxlJob开发示例(Bean模式)
@@ -39,7 +38,6 @@ public class SampleService {
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
- TimeUnit.SECONDS.sleep(2);
}
// default success
}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
index ff88c117..06202d0f 100644
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
+++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
@@ -28,7 +28,7 @@ public interface OssConstant {
/**
* 云服务商
*/
- String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu"};
+ String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"};
/**
* https 状态
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
index 15833d3c..fe409ce7 100644
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
+++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
@@ -1,7 +1,9 @@
package com.ruoyi.oss.core;
+import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.amazonaws.ClientConfiguration;
+import com.amazonaws.HttpMethod;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
@@ -16,12 +18,15 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.constant.OssConstant;
import com.ruoyi.oss.entity.UploadResult;
+import com.ruoyi.oss.enumd.AccessPolicyType;
import com.ruoyi.oss.enumd.PolicyType;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.OssProperties;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.net.URL;
+import java.util.Date;
/**
* S3 存储协议 所有兼容S3协议的云厂商均支持
@@ -57,7 +62,7 @@ public class OssClient {
.withClientConfiguration(clientConfig)
.withCredentials(credentialsProvider)
.disableChunkedEncoding();
- if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)){
+ if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) {
// minio 使用https限制使用域名访问 需要此配置 站点填域名
build.enablePathStyleAccess();
}
@@ -79,9 +84,10 @@ public class OssClient {
return;
}
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
- createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
+ AccessPolicyType accessPolicy = getAccessPolicy();
+ createBucketRequest.setCannedAcl(accessPolicy.getAcl());
client.createBucket(createBucketRequest);
- client.setBucketPolicy(bucketName, getPolicy(bucketName, PolicyType.READ));
+ client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType()));
} catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]");
}
@@ -92,13 +98,16 @@ public class OssClient {
}
public UploadResult upload(InputStream inputStream, String path, String contentType) {
+ if (!(inputStream instanceof ByteArrayInputStream)) {
+ inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
+ }
try {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
metadata.setContentLength(inputStream.available());
PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata);
// 设置上传对象的 Acl 为公共读
- putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
+ putObjectRequest.setCannedAcl(getAccessPolicy().getAcl());
client.putObject(putObjectRequest);
} catch (Exception e) {
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
@@ -111,7 +120,7 @@ public class OssClient {
try {
client.deleteObject(properties.getBucketName(), path);
} catch (Exception e) {
- throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
+ throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]");
}
}
@@ -129,16 +138,23 @@ public class OssClient {
* @param path 完整文件路径
*/
public ObjectMetadata getObjectMetadata(String path) {
+ path = path.replace(getUrl() + "/", "");
S3Object object = client.getObject(properties.getBucketName(), path);
return object.getObjectMetadata();
}
+ public InputStream getObjectContent(String path) {
+ path = path.replace(getUrl() + "/", "");
+ S3Object object = client.getObject(properties.getBucketName(), path);
+ return object.getObjectContent();
+ }
+
public String getUrl() {
String domain = properties.getDomain();
String endpoint = properties.getEndpoint();
String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://";
// 云服务商直接返回
- if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)){
+ if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) {
if (StringUtils.isNotBlank(domain)) {
return header + domain;
}
@@ -167,6 +183,24 @@ public class OssClient {
return configKey;
}
+ public String getPrivateUrl(String objectKey, Integer second) {
+ GeneratePresignedUrlRequest generatePresignedUrlRequest =
+ new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
+ .withMethod(HttpMethod.GET)
+ .withExpiration(new Date(System.currentTimeMillis() + 1000L * second));
+ URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
+ return url.toString();
+ }
+
+ /**
+ * 获取当前桶权限类型
+ *
+ * @return 当前桶权限类型code
+ */
+ public AccessPolicyType getAccessPolicy() {
+ return AccessPolicyType.getByType(properties.getAccessPolicy());
+ }
+
private static String getPolicy(String bucketName, PolicyType policyType) {
StringBuilder builder = new StringBuilder();
builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n");
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java
new file mode 100644
index 00000000..1cae6709
--- /dev/null
+++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java
@@ -0,0 +1,55 @@
+package com.ruoyi.oss.enumd;
+
+import com.amazonaws.services.s3.model.CannedAccessControlList;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 桶访问策略配置
+ *
+ * @author 陈賝
+ */
+@Getter
+@AllArgsConstructor
+public enum AccessPolicyType {
+
+ /**
+ * private
+ */
+ PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE),
+
+ /**
+ * public
+ */
+ PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ),
+
+ /**
+ * custom
+ */
+ CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ);
+
+ /**
+ * 桶 权限类型
+ */
+ private final String type;
+
+ /**
+ * 文件对象 权限类型
+ */
+ private final CannedAccessControlList acl;
+
+ /**
+ * 桶策略类型
+ */
+ private final PolicyType policyType;
+
+ public static AccessPolicyType getByType(String type) {
+ for (AccessPolicyType value : values()) {
+ if (value.getType().equals(type)) {
+ return value;
+ }
+ }
+ throw new RuntimeException("'type' not found By " + type);
+ }
+
+}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java
index a0177790..781a1700 100644
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java
+++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java
@@ -50,4 +50,9 @@ public class OssProperties {
*/
private String isHttps;
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ private String accessPolicy;
+
}
diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml
index 342a8c5f..ba7703e9 100644
--- a/ruoyi-sms/pom.xml
+++ b/ruoyi-sms/pom.xml
@@ -31,7 +31,7 @@
com.tencentcloudapi
- tencentcloud-sdk-java
+ tencentcloud-sdk-java-sms
true
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
index 577f17fb..7f2b05f6 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
@@ -82,4 +82,8 @@ public class SysOssConfig extends BaseEntity {
*/
private String remark;
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ private String accessPolicy;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
index e9f481d5..af289376 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
@@ -98,4 +98,10 @@ public class SysOssConfigBo extends BaseEntity {
*/
private String remark;
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ @NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class})
+ private String accessPolicy;
+
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
index f8b31d6b..616e4e82 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
@@ -82,4 +82,9 @@ public class SysOssConfigVo {
*/
private String remark;
+ /**
+ * 桶权限类型(0private 1public 2custom)
+ */
+ private String accessPolicy;
+
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
index f02ea3d9..7f5c090e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
@@ -2,11 +2,12 @@ package com.ruoyi.system.service;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
import java.util.Collection;
import java.util.List;
@@ -23,7 +24,9 @@ public interface ISysOssService {
SysOssVo getById(Long ossId);
- SysOss upload(MultipartFile file);
+ SysOssVo upload(MultipartFile file);
+
+ void download(Long ossId, HttpServletResponse response) throws IOException;
Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
index d18ceac5..6ea4a883 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
@@ -128,7 +128,7 @@ public class SysLoginService {
LoginUser loginUser = LoginHelper.getLoginUser();
StpUtil.logout();
asyncService.recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest());
- } catch (NotLoginException e) {
+ } catch (NotLoginException ignored) {
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
index c7dc8d62..d7244116 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -1,10 +1,12 @@
package com.ruoyi.system.service.impl;
+import cn.dev33.satoken.context.SaHolder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.CacheNames;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery;
@@ -27,6 +29,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
+import java.util.stream.Collectors;
/**
* 字典 业务层处理
@@ -231,28 +234,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
* @param separator 分隔符
* @return 字典标签
*/
+ @SuppressWarnings("unchecked cast")
@Override
public String getDictLabel(String dictType, String dictValue, String separator) {
- StringBuilder propertyString = new StringBuilder();
- List datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
-
- if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) {
- for (SysDictData dict : datas) {
- for (String value : dictValue.split(separator)) {
- if (value.equals(dict.getDictValue())) {
- propertyString.append(dict.getDictLabel() + separator);
- break;
- }
- }
- }
- } else {
- for (SysDictData dict : datas) {
- if (dictValue.equals(dict.getDictValue())) {
- return dict.getDictLabel();
- }
- }
+ // 优先从本地缓存获取
+ List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
+ if (ObjectUtil.isNull(datas)) {
+ datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
+ SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
+ }
+
+ Map map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel);
+ if (StringUtils.containsAny(dictValue, separator)) {
+ return Arrays.stream(dictValue.split(separator))
+ .map(v -> map.getOrDefault(v, StringUtils.EMPTY))
+ .collect(Collectors.joining(separator));
+ } else {
+ return map.getOrDefault(dictValue, StringUtils.EMPTY);
}
- return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
@@ -263,28 +262,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
* @param separator 分隔符
* @return 字典值
*/
+ @SuppressWarnings("unchecked cast")
@Override
public String getDictValue(String dictType, String dictLabel, String separator) {
- StringBuilder propertyString = new StringBuilder();
- List datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
-
- if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) {
- for (SysDictData dict : datas) {
- for (String label : dictLabel.split(separator)) {
- if (label.equals(dict.getDictLabel())) {
- propertyString.append(dict.getDictValue() + separator);
- break;
- }
- }
- }
- } else {
- for (SysDictData dict : datas) {
- if (dictLabel.equals(dict.getDictLabel())) {
- return dict.getDictValue();
- }
- }
+ // 优先从本地缓存获取
+ List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
+ if (ObjectUtil.isNull(datas)) {
+ datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
+ SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
+ }
+
+ Map map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue);
+ if (StringUtils.containsAny(dictLabel, separator)) {
+ return Arrays.stream(dictLabel.split(separator))
+ .map(l -> map.getOrDefault(l, StringUtils.EMPTY))
+ .collect(Collectors.joining(separator));
+ } else {
+ return map.getOrDefault(dictLabel, StringUtils.EMPTY);
}
- return StringUtils.stripEnd(propertyString.toString(), separator);
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
index ea6c604a..4d340675 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
@@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.helper.LoginHelper;
+import com.ruoyi.common.utils.StreamUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeBuildUtils;
import com.ruoyi.system.domain.SysRoleMenu;
@@ -425,13 +426,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
* 得到子节点列表
*/
private List getChildList(List list, SysMenu t) {
- List tlist = new ArrayList();
- for (SysMenu n : list) {
- if (n.getParentId().longValue() == t.getMenuId().longValue()) {
- tlist.add(n);
- }
- }
- return tlist;
+ return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
}
/**
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
index 6c63821f..cd9bffb1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.service.impl;
+import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -8,10 +9,13 @@ import com.ruoyi.common.constant.CacheNames;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.oss.core.OssClient;
import com.ruoyi.oss.entity.UploadResult;
+import com.ruoyi.oss.enumd.AccessPolicyType;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
@@ -20,14 +24,18 @@ import com.ruoyi.system.mapper.SysOssMapper;
import com.ruoyi.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
+import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* 文件上传 服务层实现
@@ -44,6 +52,8 @@ public class SysOssServiceImpl implements ISysOssService {
public TableDataInfo queryPageList(SysOssBo bo, PageQuery pageQuery) {
LambdaQueryWrapper lqw = buildQueryWrapper(bo);
Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ List filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
+ result.setRecords(filterResult);
return TableDataInfo.build(result);
}
@@ -53,7 +63,7 @@ public class SysOssServiceImpl implements ISysOssService {
for (Long id : ossIds) {
SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
if (ObjectUtil.isNotNull(vo)) {
- list.add(vo);
+ list.add(this.matchingUrl(vo));
}
}
return list;
@@ -80,7 +90,25 @@ public class SysOssServiceImpl implements ISysOssService {
}
@Override
- public SysOss upload(MultipartFile file) {
+ public void download(Long ossId, HttpServletResponse response) throws IOException {
+ SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
+ if (ObjectUtil.isNull(sysOss)) {
+ throw new ServiceException("文件数据不存在!");
+ }
+ FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
+ OssClient storage = OssFactory.instance();
+ try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
+ int available = inputStream.available();
+ IoUtil.copy(inputStream, response.getOutputStream(), available);
+ response.setContentLength(available);
+ } catch (Exception e) {
+ throw new ServiceException(e.getMessage());
+ }
+ }
+
+ @Override
+ public SysOssVo upload(MultipartFile file) {
String originalfileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
OssClient storage = OssFactory.instance();
@@ -98,7 +126,9 @@ public class SysOssServiceImpl implements ISysOssService {
oss.setOriginalName(originalfileName);
oss.setService(storage.getConfigKey());
baseMapper.insert(oss);
- return oss;
+ SysOssVo sysOssVo = new SysOssVo();
+ BeanCopyUtils.copy(oss, sysOssVo);
+ return this.matchingUrl(sysOssVo);
}
@Override
@@ -114,4 +144,18 @@ public class SysOssServiceImpl implements ISysOssService {
return baseMapper.deleteBatchIds(ids) > 0;
}
+ /**
+ * 匹配Url
+ *
+ * @param oss OSS对象
+ * @return oss 匹配Url的OSS对象
+ */
+ private SysOssVo matchingUrl(SysOssVo oss) {
+ OssClient storage = OssFactory.instance(oss.getService());
+ // 仅修改桶类型为 private 的URL,临时URL时长为120s
+ if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
+ oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120));
+ }
+ return oss;
+ }
}
diff --git a/ruoyi-ui/bin/package.bat b/ruoyi-ui/bin/package.bat
index 9f6e5f4d..2f22a4ad 100644
--- a/ruoyi-ui/bin/package.bat
+++ b/ruoyi-ui/bin/package.bat
@@ -1,6 +1,6 @@
@echo off
echo.
-echo [��Ϣ] ��װWeb���̣�����node_modules�ļ���
+echo [信息] 安装Web工程,生成node_modules文件。
echo.
%~d0
diff --git a/ruoyi-ui/bin/run-web.bat b/ruoyi-ui/bin/run-web.bat
index 3e209d77..0318c525 100644
--- a/ruoyi-ui/bin/run-web.bat
+++ b/ruoyi-ui/bin/run-web.bat
@@ -1,6 +1,6 @@
@echo off
echo.
-echo [��Ϣ] ʹ�� Vue CLI �������� Web ���̡�
+echo [信息] 使用 Vue CLI 命令运行 Web 工程。
echo.
%~d0
@@ -9,4 +9,4 @@ cd %~dp0
cd ..
npm run dev
-pause
+pause
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/icons/svg/code.svg b/ruoyi-ui/src/assets/icons/svg/code.svg
index ed4d23cf..5f9c5abd 100644
--- a/ruoyi-ui/src/assets/icons/svg/code.svg
+++ b/ruoyi-ui/src/assets/icons/svg/code.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/icons/svg/server.svg b/ruoyi-ui/src/assets/icons/svg/server.svg
index ca37b001..eb287e36 100644
--- a/ruoyi-ui/src/assets/icons/svg/server.svg
+++ b/ruoyi-ui/src/assets/icons/svg/server.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/icons/svg/system.svg b/ruoyi-ui/src/assets/icons/svg/system.svg
index dba28cf6..5992593e 100644
--- a/ruoyi-ui/src/assets/icons/svg/system.svg
+++ b/ruoyi-ui/src/assets/icons/svg/system.svg
@@ -1,2 +1,2 @@
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/icons/svg/tool.svg b/ruoyi-ui/src/assets/icons/svg/tool.svg
index c813067e..48e0e357 100644
--- a/ruoyi-ui/src/assets/icons/svg/tool.svg
+++ b/ruoyi-ui/src/assets/icons/svg/tool.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss
index ca7c6f96..16a4740f 100644
--- a/ruoyi-ui/src/assets/styles/ruoyi.scss
+++ b/ruoyi-ui/src/assets/styles/ruoyi.scss
@@ -149,10 +149,9 @@
}
/** 表格更多操作下拉样式 */
-.el-table .el-dropdown-link {
- cursor: pointer;
- color: #409EFF;
- margin-left: 5px;
+.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
+ cursor: pointer;
+ margin-left: 5px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
diff --git a/ruoyi-ui/src/components/Crontab/hour.vue b/ruoyi-ui/src/components/Crontab/hour.vue
index abee0bfe..4b1f1fcd 100644
--- a/ruoyi-ui/src/components/Crontab/hour.vue
+++ b/ruoyi-ui/src/components/Crontab/hour.vue
@@ -1,114 +1,114 @@
-
-
-
- 小时,允许的通配符[, - * /]
-
-
+
+
+
+ 小时,允许的通配符[, - * /]
+
+
-
-
- 周期从
- -
- 小时
-
-
+
+
+ 周期从
+ -
+ 小时
+
+
-
-
- 从
- 小时开始,每
- 小时执行一次
-
-
+
+
+ 从
+ 小时开始,每
+ 小时执行一次
+
+
-
-
- 指定
-
- {{item-1}}
-
-
-
-
+
+
+ 指定
+
+ {{item-1}}
+
+
+
+
diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue
index 0cc24dba..5f0edbef 100644
--- a/ruoyi-ui/src/components/TopNav/index.vue
+++ b/ruoyi-ui/src/components/TopNav/index.vue
@@ -92,7 +92,9 @@ export default {
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
const tmpPath = path.substring(1, path.length);
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
- this.$store.dispatch('app/toggleSideBarHide', false);
+ if (!this.$route.meta.link) {
+ this.$store.dispatch('app/toggleSideBarHide', false);
+ }
} else if(!this.$route.children) {
activePath = path;
this.$store.dispatch('app/toggleSideBarHide', true);
@@ -145,6 +147,8 @@ export default {
}
if(routes.length > 0) {
this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
+ } else {
+ this.$store.dispatch('app/toggleSideBarHide', true);
}
},
ishttp(url) {
diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js
index 2473bc13..f94fa0e5 100644
--- a/ruoyi-ui/src/utils/request.js
+++ b/ruoyi-ui/src/utils/request.js
@@ -80,31 +80,24 @@ service.interceptors.response.use(res => {
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
- MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
- confirmButtonText: '重新登录',
- cancelButtonText: '取消',
- type: 'warning'
- }
- ).then(() => {
- isRelogin.show = false;
- store.dispatch('LogOut').then(() => {
- location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
- })
+ MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ isRelogin.show = false;
+ store.dispatch('LogOut').then(() => {
+ location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
+ })
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
- Message({
- message: msg,
- type: 'error'
- })
+ Message({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
+ } else if (code === 601) {
+ Message({ message: msg, type: 'warning' })
+ return Promise.reject('error')
} else if (code !== 200) {
- Notification.error({
- title: msg
- })
+ Notification.error({ title: msg })
return Promise.reject('error')
} else {
return res.data
@@ -115,18 +108,12 @@ service.interceptors.response.use(res => {
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
- }
- else if (message.includes("timeout")) {
+ } else if (message.includes("timeout")) {
message = "系统接口请求超时";
- }
- else if (message.includes("Request failed with status code")) {
+ } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
- Message({
- message: message,
- type: 'error',
- duration: 5 * 1000
- })
+ Message({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
)
diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js
index d2cd2a06..243c4c7b 100644
--- a/ruoyi-ui/src/utils/ruoyi.js
+++ b/ruoyi-ui/src/utils/ruoyi.js
@@ -86,11 +86,14 @@ export function selectDictLabel(datas, value) {
return actions.join('');
}
-// 回显数据字典(字符串数组)
+// 回显数据字典(字符串、数组)
export function selectDictLabels(datas, value, separator) {
- if (value === undefined) {
+ if (value === undefined || value.length ===0) {
return "";
}
+ if (Array.isArray(value)) {
+ value = value.join(",");
+ }
var actions = [];
var currentSeparator = undefined === separator ? "," : separator;
var temp = value.split(currentSeparator);
diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue
index d59814cc..6207f3bf 100644
--- a/ruoyi-ui/src/views/index.vue
+++ b/ruoyi-ui/src/views/index.vue
@@ -23,7 +23,7 @@
* 分布式限流 Redisson 全局、请求IP、集群ID 多种限流
* 分布式锁 Lock4j 注解锁、工具锁 多种多样
* 分布式幂等 Redisson 拦截重复提交
- * 分布式日志 TLog 支持跟踪链路日志记录、性能分析、链路排查
+ * 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化
* 分布式任务调度 Xxl-Job 高性能 高可靠 易扩展
* 分布式文件存储 Minio 本地存储
* 分布式云存储 七牛、阿里、腾讯 云存储
@@ -32,7 +32,7 @@
* Excel框架 Alibaba EasyExcel 性能优异 扩展性强
* 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释
* 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性
- * 代码生成器 适配MP、Knife4j规范化代码 一键生成前后端代码
+ * 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码
* 部署方式 Docker 容器编排 一键部署业务集群
* 国际化 SpringMessage Spring标准国际化方案
diff --git a/ruoyi-ui/src/views/monitor/druid/index.vue b/ruoyi-ui/src/views/monitor/druid/index.vue
deleted file mode 100644
index c6ad585c..00000000
--- a/ruoyi-ui/src/views/monitor/druid/index.vue
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
diff --git a/ruoyi-ui/src/views/system/oss/config.vue b/ruoyi-ui/src/views/system/oss/config.vue
index 54ad98cb..0120641d 100644
--- a/ruoyi-ui/src/views/system/oss/config.vue
+++ b/ruoyi-ui/src/views/system/oss/config.vue
@@ -80,6 +80,13 @@
+
+
+ private
+ public
+ custom
+
+
{{dict.label}}
+
+
+ private
+ public
+ custom
+
+
@@ -259,6 +273,9 @@ export default {
trigger: "blur",
},
],
+ accessPolicy:[
+ { required: true, message: "accessPolicy不能为空", trigger: "blur" }
+ ]
},
};
},
@@ -292,6 +309,7 @@ export default {
endpoint: undefined,
domain: undefined,
isHttps: "N",
+ accessPolicy: "1",
region: undefined,
status: "1",
remark: undefined,
diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue
index 77d1d6a1..ca02f3ab 100644
--- a/ruoyi-ui/src/views/system/role/index.vue
+++ b/ruoyi-ui/src/views/system/role/index.vue
@@ -135,9 +135,7 @@
v-hasPermi="['system:role:remove']"
>删除
handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']">
-
- 更多
-
+ 更多
数据权限
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 3edf44ac..b2120e6d 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -20,6 +20,7 @@
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree"
+ node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
@@ -179,9 +180,7 @@
v-hasPermi="['system:user:remove']"
>删除
handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
-
- 更多
-
+ 更多
重置密码
@@ -536,6 +535,8 @@ export default {
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
+ this.queryParams.deptId = undefined;
+ this.$refs.tree.setCurrentKey(null);
this.handleQuery();
},
// 多选框选中数据
diff --git a/ruoyi-ui/src/views/system/user/profile/userAvatar.vue b/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
index bd1d23b6..18b23a4b 100644
--- a/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
+++ b/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
@@ -12,6 +12,7 @@
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
+ :outputType="options.outputType"
@realTime="realTime"
v-if="visible"
/>
@@ -79,6 +80,7 @@ export default {
autoCropWidth: 200, // 默认生成截图框宽度
autoCropHeight: 200, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
+ outputType:"png", // 默认生成截图为PNG格式
filename: ''
},
previews: {},
diff --git a/ruoyi-ui/src/views/tool/gen/index.vue b/ruoyi-ui/src/views/tool/gen/index.vue
index 45e91171..b7128e3f 100644
--- a/ruoyi-ui/src/views/tool/gen/index.vue
+++ b/ruoyi-ui/src/views/tool/gen/index.vue
@@ -279,7 +279,7 @@ export default {
this.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath);
});
} else {
- this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "ruoyi");
+ this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "ruoyi.zip");
}
},
/** 同步数据库操作 */
diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml
index af8edcc8..46bd7172 100644
--- a/script/docker/docker-compose.yml
+++ b/script/docker/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3'
services:
mysql:
- image: mysql:8.0.29
+ image: mysql:8.0.31
container_name: mysql
environment:
# 时区上海
@@ -109,6 +109,8 @@ services:
volumes:
# 配置文件
- /docker/server1/logs/:/ruoyi/server/logs/
+ # skywalking 探针
+# - /docker/skywalking/agent/:/ruoyi/skywalking/agent
privileged: true
network_mode: "host"
@@ -122,6 +124,8 @@ services:
volumes:
# 配置文件
- /docker/server2/logs/:/ruoyi/server/logs/
+ # skywalking 探针
+# - /docker/skywalking/agent/:/ruoyi/skywalking/agent
privileged: true
network_mode: "host"
diff --git a/script/sql/tables_xxl_job.sql b/script/sql/tables_xxl_job.sql
new file mode 100644
index 00000000..236c557e
--- /dev/null
+++ b/script/sql/tables_xxl_job.sql
@@ -0,0 +1,119 @@
+#
+# XXL-JOB v2.3.0
+# Copyright (c) 2015-present, xuxueli.
+
+SET NAMES utf8mb4;
+
+CREATE TABLE `xxl_job_info` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
+ `job_desc` varchar(255) NOT NULL,
+ `add_time` datetime DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL,
+ `author` varchar(64) DEFAULT NULL COMMENT '作者',
+ `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
+ `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
+ `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
+ `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
+ `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
+ `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
+ `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
+ `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
+ `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
+ `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
+ `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
+ `glue_source` mediumtext COMMENT 'GLUE源代码',
+ `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
+ `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
+ `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
+ `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
+ `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
+ `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_log` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
+ `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
+ `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
+ `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
+ `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
+ `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
+ `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
+ `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
+ `trigger_code` int(11) NOT NULL COMMENT '调度-结果',
+ `trigger_msg` text COMMENT '调度-日志',
+ `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
+ `handle_code` int(11) NOT NULL COMMENT '执行-状态',
+ `handle_msg` text COMMENT '执行-日志',
+ `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
+ PRIMARY KEY (`id`),
+ KEY `I_trigger_time` (`trigger_time`),
+ KEY `I_handle_code` (`handle_code`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_log_report` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
+ `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
+ `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
+ `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
+ `update_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_logglue` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
+ `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
+ `glue_source` mediumtext COMMENT 'GLUE源代码',
+ `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
+ `add_time` datetime DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_registry` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `registry_group` varchar(50) NOT NULL,
+ `registry_key` varchar(255) NOT NULL,
+ `registry_value` varchar(255) NOT NULL,
+ `update_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_group` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
+ `title` varchar(12) NOT NULL COMMENT '执行器名称',
+ `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
+ `address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
+ `update_time` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_user` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `username` varchar(50) NOT NULL COMMENT '账号',
+ `password` varchar(50) NOT NULL COMMENT '密码',
+ `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
+ `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `i_username` (`username`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `xxl_job_lock` (
+ `lock_name` varchar(50) NOT NULL COMMENT '锁名称',
+ PRIMARY KEY (`lock_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
+INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
+INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
+INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
+
+commit;
+
diff --git a/script/sql/test.sql b/script/sql/test.sql
new file mode 100644
index 00000000..6232bab6
--- /dev/null
+++ b/script/sql/test.sql
@@ -0,0 +1,171 @@
+DROP TABLE if EXISTS test_demo;
+CREATE TABLE test_demo
+(
+ id bigint(0) NOT NULL COMMENT '主键',
+ dept_id bigint(0) NULL DEFAULT NULL COMMENT '部门id',
+ user_id bigint(0) NULL DEFAULT NULL COMMENT '用户id',
+ order_num int(0) NULL DEFAULT 0 COMMENT '排序号',
+ test_key varchar(255) NULL DEFAULT NULL COMMENT 'key键',
+ value varchar(255) NULL DEFAULT NULL COMMENT '值',
+ version int(0) NULL DEFAULT 0 COMMENT '版本',
+ create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ create_by varchar(64) NULL DEFAULT NULL COMMENT '创建人',
+ update_time datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ update_by varchar(64) NULL DEFAULT NULL COMMENT '更新人',
+ del_flag int(0) NULL DEFAULT 0 COMMENT '删除标志',
+ PRIMARY KEY (id) USING BTREE
+) ENGINE = InnoDB COMMENT = '测试单表';
+
+DROP TABLE if EXISTS test_tree;
+CREATE TABLE test_tree
+(
+ id bigint(0) NOT NULL COMMENT '主键',
+ parent_id bigint(0) NULL DEFAULT 0 COMMENT '父id',
+ dept_id bigint(0) NULL DEFAULT NULL COMMENT '部门id',
+ user_id bigint(0) NULL DEFAULT NULL COMMENT '用户id',
+ tree_name varchar(255) NULL DEFAULT NULL COMMENT '值',
+ version int(0) NULL DEFAULT 0 COMMENT '版本',
+ create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ create_by varchar(64) NULL DEFAULT NULL COMMENT '创建人',
+ update_time datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ update_by varchar(64) NULL DEFAULT NULL COMMENT '更新人',
+ del_flag int(0) NULL DEFAULT 0 COMMENT '删除标志',
+ PRIMARY KEY (id) USING BTREE
+) ENGINE = InnoDB COMMENT = '测试树表';
+
+INSERT INTO sys_user(user_id, dept_id, user_name, nick_name, user_type, email, phonenumber, sex, avatar, password, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark) VALUES (3, 108, 'test', '本部门及以下 密码666666', 'sys_user', '', '', '0', '', '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), 'test', sysdate(), NULL);
+INSERT INTO sys_user(user_id, dept_id, user_name, nick_name, user_type, email, phonenumber, sex, avatar, password, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark) VALUES (4, 102, 'test1', '仅本人 密码666666', 'sys_user', '', '', '0', '', '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), 'test1', sysdate(), NULL);
+
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (5, '测试菜单', 0, 5, 'demo', NULL, 1, 0, 'M', '0', '0', NULL, 'star', 'admin', sysdate(), NULL, NULL, '');
+
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1500, '测试单表', 5, 1, 'demo', 'demo/demo/index', 1, 0, 'C', '0', '0', 'demo:demo:list', '#', 'admin', sysdate(), '', NULL, '测试单表菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1501, '测试单表查询', 1500, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:query', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1502, '测试单表新增', 1500, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:add', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1503, '测试单表修改', 1500, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:edit', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1504, '测试单表删除', 1500, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:remove', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1505, '测试单表导出', 1500, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:demo:export', '#', 'admin', sysdate(), '', NULL, '');
+
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1506, '测试树表', 5, 1, 'tree', 'demo/tree/index', 1, 0, 'C', '0', '0', 'demo:tree:list', '#', 'admin', sysdate(), '', NULL, '测试树表菜单');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1507, '测试树表查询', 1506, 1, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:query', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1508, '测试树表新增', 1506, 2, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:add', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1509, '测试树表修改', 1506, 3, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:edit', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1510, '测试树表删除', 1506, 4, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:remove', '#', 'admin', sysdate(), '', NULL, '');
+INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES (1511, '测试树表导出', 1506, 5, '#', '', 1, 0, 'F', '0', '0', 'demo:tree:export', '#', 'admin', sysdate(), '', NULL, '');
+
+INSERT INTO sys_role(role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, update_by, update_time, remark) VALUES (3, '本部门及以下', 'test1', 3, '4', 1, 1, '0', '0', 'admin', sysdate(), 'admin', NULL, NULL);
+INSERT INTO sys_role(role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, update_by, update_time, remark) VALUES (4, '仅本人', 'test2', 4, '5', 1, 1, '0', '0', 'admin', sysdate(), 'admin', NULL, NULL);
+
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 5);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 100);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 101);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 102);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 103);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 104);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 105);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 106);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 107);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 108);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 500);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 501);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1001);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1002);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1003);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1004);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1005);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1006);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1007);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1008);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1009);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1010);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1011);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1012);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1013);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1014);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1015);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1016);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1017);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1018);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1019);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1020);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1021);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1022);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1023);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1024);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1025);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1026);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1027);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1028);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1029);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1030);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1031);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1032);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1033);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1034);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1035);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1036);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1037);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1038);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1039);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1040);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1041);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1042);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1043);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1044);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1045);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1500);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1501);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1502);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1503);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1504);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1505);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1506);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1507);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1508);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1509);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1510);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (3, 1511);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 5);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1500);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1501);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1502);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1503);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1504);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1505);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1506);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1507);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1508);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1509);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1510);
+INSERT INTO sys_role_menu(role_id, menu_id) VALUES (4, 1511);
+
+INSERT INTO sys_user_role(user_id, role_id) VALUES (3, 3);
+INSERT INTO sys_user_role(user_id, role_id) VALUES (4, 4);
+
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (1, 102, 4, 1, '测试数据权限', '测试', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (2, 102, 3, 2, '子节点1', '111', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (3, 102, 3, 3, '子节点2', '222', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (4, 108, 4, 4, '测试数据', 'demo', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (5, 108, 3, 13, '子节点11', '1111', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (6, 108, 3, 12, '子节点22', '2222', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (7, 108, 3, 11, '子节点33', '3333', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (8, 108, 3, 10, '子节点44', '4444', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (9, 108, 3, 9, '子节点55', '5555', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (10, 108, 3, 8, '子节点66', '6666', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (11, 108, 3, 7, '子节点77', '7777', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (12, 108, 3, 6, '子节点88', '8888', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_demo(id, dept_id, user_id, order_num, test_key, value, version, create_time, create_by, update_time, update_by, del_flag) VALUES (13, 108, 3, 5, '子节点99', '9999', 0, sysdate(), 'admin', NULL, NULL, 0);
+
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (1, 0, 102, 4, '测试数据权限', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (2, 1, 102, 3, '子节点1', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (3, 2, 102, 3, '子节点2', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (4, 0, 108, 4, '测试树1', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (5, 4, 108, 3, '子节点11', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (6, 4, 108, 3, '子节点22', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (7, 4, 108, 3, '子节点33', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (8, 5, 108, 3, '子节点44', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (9, 6, 108, 3, '子节点55', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (10, 7, 108, 3, '子节点66', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (11, 7, 108, 3, '子节点77', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (12, 10, 108, 3, '子节点88', 0, sysdate(), 'admin', NULL, NULL, 0);
+INSERT INTO test_tree(id, parent_id, dept_id, user_id, tree_name, version, create_time, create_by, update_time, update_by, del_flag) VALUES (13, 10, 108, 3, '子节点99', 0, sysdate(), 'admin', NULL, NULL, 0);