diff --git a/README.md b/README.md
index 364d6c00bf54b6b7893f2e803ac45e5200fd2e36..e5a47b8c968eb18a95db8d340d4d92274c6c8c66 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-RuoYi v3.8.7
+RuoYi v3.8.8
基于SpringBoot+Vue前后端分离的Java快速开发框架
-
+
@@ -93,4 +93,4 @@
## 若依前后端分离交流群
-QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) 点击按钮入群。
\ No newline at end of file
+QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) 点击按钮入群。
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a7215ac1317bdfdc9a176f9c3215a9e3367b0f6d..5994ea8906e1032f52321e3ea8450726f8d911e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,27 +6,28 @@
com.ruoyi
ruoyi
- 3.8.7
+ 3.8.8
ruoyi
http://www.ruoyi.vip
若依管理系统
- 3.8.7
+ 3.8.8
UTF-8
UTF-8
1.8
3.1.1
- 1.2.20
+ 5.3.33
+ 5.7.12
+ 1.2.23
1.21
3.0.0
2.3.3
1.4.7
- 2.0.43
- 6.4.11
+ 2.0.53
+ 6.6.3
2.13.0
- 3.2.2
4.1.2
2.3
0.9.1
@@ -36,6 +37,24 @@
+
+
+ org.springframework
+ spring-framework-bom
+ ${spring-framework.version}
+ pom
+ import
+
+
+
+
+ org.springframework.security
+ spring-security-bom
+ ${spring-security.version}
+ pom
+ import
+
+
org.springframework.boot
@@ -107,13 +126,6 @@
${velocity.version}
-
-
- commons-collections
- commons-collections
- ${commons.collections.version}
-
-
com.alibaba.fastjson2
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index e6c67123146abe02f993241d51cb7fbb3e1f21a9..ce384b469721113c79968329c3a15ca96b225d17 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.7
+ 3.8.8
4.0.0
jar
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
index 41029fd918e39802ad614e2ecea65761be92d3da..504c0fde6b5c0301c56a3ac5b1086aa0f1a804ed 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.TreeSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
@@ -80,7 +81,7 @@ public class CacheController
public AjaxResult getCacheKeys(@PathVariable String cacheName)
{
Set cacheKeys = redisTemplate.keys(cacheName + "*");
- return AjaxResult.success(cacheKeys);
+ return AjaxResult.success(new TreeSet<>(cacheKeys));
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index dab2bf8792394a2aff3a9f7df74ba20a947719f2..e575d287cf047bf90b5077e70c7d9d07daa60cbb 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -12,9 +12,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
+import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
/**
@@ -34,6 +36,9 @@ public class SysLoginController
@Autowired
private SysPermissionService permissionService;
+ @Autowired
+ private TokenService tokenService;
+
/**
* 登录方法
*
@@ -59,11 +64,17 @@ public class SysLoginController
@GetMapping("getInfo")
public AjaxResult getInfo()
{
- SysUser user = SecurityUtils.getLoginUser().getUser();
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ SysUser user = loginUser.getUser();
// 角色集合
Set roles = permissionService.getRolePermission(user);
// 权限集合
Set permissions = permissionService.getMenuPermission(user);
+ if (!loginUser.getPermissions().equals(permissions))
+ {
+ loginUser.setPermissions(permissions);
+ tokenService.refreshToken(loginUser);
+ }
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
ajax.put("roles", roles);
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
index ebe7460e19d1fc2bf33ad56b2ce0782a0abce13c..dfbf256b19d583d0fbfc5eaee5552eafdaa02d40 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -132,8 +132,8 @@ public class SysRoleController extends BaseController
LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
- loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
+ loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
tokenService.setLoginUser(loginUser);
}
return success();
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 dc29d4982c478cb284282cfd59a6d5a324dc0723..24aafae73faf33e7af79996d3c999f9688bf86e1 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
@@ -124,6 +124,8 @@ public class SysUserController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysUser user)
{
+ deptService.checkDeptDataScope(user.getDeptId());
+ roleService.checkRoleDataScope(user.getRoleIds());
if (!userService.checkUserNameUnique(user))
{
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
@@ -151,6 +153,8 @@ public class SysUserController extends BaseController
{
userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
+ deptService.checkDeptDataScope(user.getDeptId());
+ roleService.checkRoleDataScope(user.getRoleIds());
if (!userService.checkUserNameUnique(user))
{
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
@@ -235,6 +239,7 @@ public class SysUserController extends BaseController
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
userService.checkUserDataScope(userId);
+ roleService.checkRoleDataScope(roleIds);
userService.insertUserAuth(userId, roleIds);
return success();
}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index f7125af6d578038a9211b7f479cb3fe20687da03..c777ac14d323d14a6f9cf3cc992069ed05473d17 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -3,9 +3,9 @@ ruoyi:
# 名称
name: RuoYi
# 版本
- version: 3.8.7
+ version: 3.8.8
# 版权年份
- copyrightYear: 2023
+ copyrightYear: 2024
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 38326a1fafdf61b075d51054d1f4c88ada76001e..56c3f8191cf86a34f82a4928268e17b4684ee123 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.7
+ 3.8.8
4.0.0
@@ -59,13 +59,6 @@
jackson-databind
-
-
- com.baomidou
- dynamic-datasource-spring-boot-starter
- 3.5.2
-
-
com.alibaba.fastjson2
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
index d534a3ebcccbe17fcf7906bc4ef1c1c22a8edf3e..0d69d3940d5c5f2016d462b97c702394bab9bd0b 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
@@ -88,6 +88,11 @@ public @interface Excel
*/
public String[] combo() default {};
+ /**
+ * 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
+ */
+ public boolean comboReadDict() default false;
+
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
@@ -171,7 +176,7 @@ public @interface Excel
public enum ColumnType
{
- NUMERIC(0), STRING(1), IMAGE(2);
+ NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
private final int value;
ColumnType(int value)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0621e9e8f6d2d54d5356f3a7105a4deb7da1de6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
+import com.ruoyi.common.enums.DesensitizedType;
+
+/**
+ * 数据脱敏注解
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = SensitiveJsonSerializer.class)
+public @interface Sensitive
+{
+ DesensitizedType desensitizedType();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e819a1d7b64f76d587e2e25bbcbf1e09164c88c8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.config.serializer;
+
+import java.io.IOException;
+import java.util.Objects;
+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.Sensitive;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.DesensitizedType;
+import com.ruoyi.common.utils.SecurityUtils;
+
+/**
+ * 数据脱敏序列化过滤
+ *
+ * @author ruoyi
+ */
+public class SensitiveJsonSerializer extends JsonSerializer implements ContextualSerializer
+{
+ private DesensitizedType desensitizedType;
+
+ @Override
+ public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
+ {
+ if (desensitization())
+ {
+ gen.writeString(desensitizedType.desensitizer().apply(value));
+ }
+ else
+ {
+ gen.writeString(value);
+ }
+ }
+
+ @Override
+ public JsonSerializer> createContextual(SerializerProvider prov, BeanProperty property)
+ throws JsonMappingException
+ {
+ Sensitive annotation = property.getAnnotation(Sensitive.class);
+ if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
+ {
+ this.desensitizedType = annotation.desensitizedType();
+ return this;
+ }
+ return prov.findValueSerializer(property.getType(), property);
+ }
+
+ /**
+ * 是否需要脱敏处理
+ */
+ private boolean desensitization()
+ {
+ try
+ {
+ LoginUser securityUser = SecurityUtils.getLoginUser();
+ // 管理员不脱敏
+ return !securityUser.getUser().isAdmin();
+ }
+ catch (Exception e)
+ {
+ return true;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
index 5fbfc73933ef4a35ef46f0ee0b7aa3baf8c9364f..a94c3fa35e7fc60555c30a734d7091b474ff7d5e 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -1,5 +1,6 @@
package com.ruoyi.common.constant;
+import java.util.Locale;
import io.jsonwebtoken.Claims;
/**
@@ -19,6 +20,11 @@ public class Constants
*/
public static final String GBK = "GBK";
+ /**
+ * 系统语言
+ */
+ public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
+
/**
* www主域
*/
@@ -157,11 +163,11 @@ public class Constants
/**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
*/
- public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
+ public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
- "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
+ "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
index b09b6f3d5c321ad6d57658b1bcf87f0f54b7ff89..f2b5ab58841752d2744b02542188949e00660743 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -21,6 +21,9 @@ public class UserConstants
/** 用户封禁状态 */
public static final String USER_DISABLE = "1";
+ /** 角色正常状态 */
+ public static final String ROLE_NORMAL = "0";
+
/** 角色封禁状态 */
public static final String ROLE_DISABLE = "1";
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
index 9f3a6f6593065e8f9f76adf8f78dca93d1bbc09c..f062120292d59cbeb4d83cbb62d70f842bd003ca 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
@@ -42,6 +42,9 @@ public class SysMenu extends BaseEntity
/** 路由参数 */
private String query;
+ /** 路由名称,默认和路由地址相同的驼峰格式(注意:因为vue3版本的router会删除名称相同路由,为避免名字的冲突,特殊情况可以自定义) */
+ private String routeName;
+
/** 是否为外链(0是 1否) */
private String isFrame;
@@ -53,7 +56,7 @@ public class SysMenu extends BaseEntity
/** 显示状态(0显示 1隐藏) */
private String visible;
-
+
/** 菜单状态(0正常 1停用) */
private String status;
@@ -151,6 +154,16 @@ public class SysMenu extends BaseEntity
this.query = query;
}
+ public String getRouteName()
+ {
+ return routeName;
+ }
+
+ public void setRouteName(String routeName)
+ {
+ this.routeName = routeName;
+ }
+
public String getIsFrame()
{
return isFrame;
@@ -232,7 +245,7 @@ public class SysMenu extends BaseEntity
{
this.children = children;
}
-
+
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -242,6 +255,8 @@ public class SysMenu extends BaseEntity
.append("orderNum", getOrderNum())
.append("path", getPath())
.append("component", getComponent())
+ .append("query", getQuery())
+ .append("routeName", getRouteName())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
index 8d4d4c566f1fb4fc68394eb5bd1642ef7f3565a4..c33d91246247813ea0f95e742bedb29aff991d2a 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -22,7 +22,7 @@ public class SysUser extends BaseEntity
private static final long serialVersionUID = 1L;
/** 用户ID */
- @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
+ @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId;
/** 部门ID */
@@ -42,7 +42,7 @@ public class SysUser extends BaseEntity
private String email;
/** 手机号码 */
- @Excel(name = "手机号码")
+ @Excel(name = "手机号码", cellType = ColumnType.TEXT)
private String phonenumber;
/** 用户性别 */
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
index 8a2ad80a2ac78d6ca595a0946bf37ffecbafc216..938d0c9f22134f4536de73fba99c6901ee81d450 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -365,6 +365,10 @@ public class Convert
*/
public static String[] toStrArray(String str)
{
+ if (StringUtils.isEmpty(str))
+ {
+ return new String[] {};
+ }
return toStrArray(",", str);
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
new file mode 100644
index 0000000000000000000000000000000000000000..450812293b9fcb2dd522ee94b82aab871fc77b64
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+import java.util.function.Function;
+import com.ruoyi.common.utils.DesensitizedUtil;
+
+/**
+ * 脱敏类型
+ *
+ * @author ruoyi
+ */
+public enum DesensitizedType
+{
+ /**
+ * 姓名,第2位星号替换
+ */
+ USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
+
+ /**
+ * 密码,全部字符都用*代替
+ */
+ PASSWORD(DesensitizedUtil::password),
+
+ /**
+ * 身份证,中间10位星号替换
+ */
+ ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
+
+ /**
+ * 手机号,中间4位星号替换
+ */
+ PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
+
+ /**
+ * 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
+ */
+ EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
+
+ /**
+ * 银行卡号,保留最后4位,其他星号替换
+ */
+ BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
+
+ /**
+ * 车牌号码,包含普通车辆、新能源车辆
+ */
+ CAR_LICENSE(DesensitizedUtil::carLicense);
+
+ private final Function desensitizer;
+
+ DesensitizedType(Function desensitizer)
+ {
+ this.desensitizer = desensitizer;
+ }
+
+ public Function desensitizer()
+ {
+ return desensitizer;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
index 23a76fe1d8cb2ce3828a4d31160286a213cb3920..b4eaabcb6d53c1d015d9173aae678d61bed30c03 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
@@ -32,10 +32,10 @@ public class XssFilter implements Filter
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes))
{
- String[] url = tempExcludes.split(",");
- for (int i = 0; url != null && i < url.length; i++)
+ String[] urls = tempExcludes.split(",");
+ for (String url : urls)
{
- excludes.add(url[i]);
+ excludes.add(url);
}
}
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..f8a4c022eec81f288689d52f4220565d13cfee0b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.utils;
+
+/**
+ * 脱敏工具类
+ *
+ * @author ruoyi
+ */
+public class DesensitizedUtil
+{
+ /**
+ * 密码的全部字符都用*代替,比如:******
+ *
+ * @param password 密码
+ * @return 脱敏后的密码
+ */
+ public static String password(String password)
+ {
+ if (StringUtils.isBlank(password))
+ {
+ return StringUtils.EMPTY;
+ }
+ return StringUtils.repeat('*', password.length());
+ }
+
+ /**
+ * 车牌中间用*代替,如果是错误的车牌,不处理
+ *
+ * @param carLicense 完整的车牌号
+ * @return 脱敏后的车牌
+ */
+ public static String carLicense(String carLicense)
+ {
+ if (StringUtils.isBlank(carLicense))
+ {
+ return StringUtils.EMPTY;
+ }
+ // 普通车牌
+ if (carLicense.length() == 7)
+ {
+ carLicense = StringUtils.hide(carLicense, 3, 6);
+ }
+ else if (carLicense.length() == 8)
+ {
+ // 新能源车牌
+ carLicense = StringUtils.hide(carLicense, 3, 7);
+ }
+ return carLicense;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
index 39ad84a6bb2a3f09bf61c46a14acddbfd0f1cf1e..8204f1338436983ee35db4c8d14f3f6c856edf76 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
@@ -56,6 +56,10 @@ public class DictUtils
*/
public static String getDictLabel(String dictType, String dictValue)
{
+ if (StringUtils.isEmpty(dictValue))
+ {
+ return StringUtils.EMPTY;
+ }
return getDictLabel(dictType, dictValue, SEPARATOR);
}
@@ -68,6 +72,10 @@ public class DictUtils
*/
public static String getDictValue(String dictType, String dictLabel)
{
+ if (StringUtils.isEmpty(dictLabel))
+ {
+ return StringUtils.EMPTY;
+ }
return getDictValue(dictType, dictLabel, SEPARATOR);
}
@@ -83,31 +91,31 @@ public class DictUtils
{
StringBuilder propertyString = new StringBuilder();
List datas = getDictCache(dictType);
-
- if (StringUtils.isNotNull(datas))
+ if (StringUtils.isNull(datas))
{
- if (StringUtils.containsAny(separator, dictValue))
+ return StringUtils.EMPTY;
+ }
+ if (StringUtils.containsAny(separator, dictValue))
+ {
+ for (SysDictData dict : datas)
{
- for (SysDictData dict : datas)
+ for (String value : dictValue.split(separator))
{
- for (String value : dictValue.split(separator))
+ if (value.equals(dict.getDictValue()))
{
- if (value.equals(dict.getDictValue()))
- {
- propertyString.append(dict.getDictLabel()).append(separator);
- break;
- }
+ propertyString.append(dict.getDictLabel()).append(separator);
+ break;
}
}
}
- else
+ }
+ else
+ {
+ for (SysDictData dict : datas)
{
- for (SysDictData dict : datas)
+ if (dictValue.equals(dict.getDictValue()))
{
- if (dictValue.equals(dict.getDictValue()))
- {
- return dict.getDictLabel();
- }
+ return dict.getDictLabel();
}
}
}
@@ -126,8 +134,11 @@ public class DictUtils
{
StringBuilder propertyString = new StringBuilder();
List datas = getDictCache(dictType);
-
- if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ if (StringUtils.containsAny(separator, dictLabel))
{
for (SysDictData dict : datas)
{
@@ -154,6 +165,48 @@ public class DictUtils
return StringUtils.stripEnd(propertyString.toString(), separator);
}
+ /**
+ * 根据字典类型获取字典所有值
+ *
+ * @param dictType 字典类型
+ * @return 字典值
+ */
+ public static String getDictValues(String dictType)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ for (SysDictData dict : datas)
+ {
+ propertyString.append(dict.getDictValue()).append(SEPARATOR);
+ }
+ return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+ }
+
+ /**
+ * 根据字典类型获取字典所有标签
+ *
+ * @param dictType 字典类型
+ * @return 字典值
+ */
+ public static String getDictLabels(String dictType)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ for (SysDictData dict : datas)
+ {
+ propertyString.append(dict.getDictLabel()).append(SEPARATOR);
+ }
+ return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+ }
+
/**
* 删除指定字典缓存
*
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
index 215d1153c5083e53693e8fe0d4ca485ab555b535..fc6c6b5e086527700cbd568e43a02fa7b1da983c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -23,6 +23,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/** 下划线 */
private static final char SEPARATOR = '_';
+ /** 星号 */
+ private static final char ASTERISK = '*';
+
/**
* 获取参数不为空值
*
@@ -163,6 +166,49 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return (str == null ? "" : str.trim());
}
+ /**
+ * 替换指定字符串的指定区间内字符为"*"
+ *
+ * @param str 字符串
+ * @param startInclude 开始位置(包含)
+ * @param endExclude 结束位置(不包含)
+ * @return 替换后的字符串
+ */
+ public static String hide(CharSequence str, int startInclude, int endExclude)
+ {
+ if (isEmpty(str))
+ {
+ return NULLSTR;
+ }
+ final int strLength = str.length();
+ if (startInclude > strLength)
+ {
+ return NULLSTR;
+ }
+ if (endExclude > strLength)
+ {
+ endExclude = strLength;
+ }
+ if (startInclude > endExclude)
+ {
+ // 如果起始位置大于结束位置,不替换
+ return NULLSTR;
+ }
+ final char[] chars = new char[strLength];
+ for (int i = 0; i < strLength; i++)
+ {
+ if (i >= startInclude && i < endExclude)
+ {
+ chars[i] = ASTERISK;
+ }
+ else
+ {
+ chars[i] = str.charAt(i);
+ }
+ }
+ return new String(chars);
+ }
+
/**
* 截取字符串
*
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
index 4652a2985b454ec65856dfa966c4c64aa8ad912c..5a0ef64004382e0f2c99dbbf0993d61e37bafbc9 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
@@ -25,7 +25,7 @@ public class FileUploadUtils
/**
* 默认大小 50M
*/
- public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+ public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 默认的文件名最大长度 100
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index 68ccbf11c0586f3786cb5c9ef35ff57c5e336604..64f97baa36eb3d945ccfef43ee8095fab9a56d0b 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -39,6 +39,7 @@ import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
@@ -470,7 +471,12 @@ public class ExcelUtil
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
- val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+ if (!sysDictMap.containsKey(attr.dictType() + val))
+ {
+ String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+ sysDictMap.put(attr.dictType() + val, dictValue);
+ }
+ val = sysDictMap.get(attr.dictType() + val);
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
@@ -783,6 +789,8 @@ public class ExcelUtil
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true);
style.setFont(titleFont);
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
styles.put("title", style);
style = wb.createCellStyle();
@@ -845,6 +853,9 @@ public class ExcelUtil
headerFont.setBold(true);
headerFont.setColor(excel.headerColor().index);
style.setFont(headerFont);
+ // 设置表格头单元格文本形式
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
headerStyles.put(key, style);
}
}
@@ -862,34 +873,66 @@ public class ExcelUtil
Map styles = new HashMap();
for (Object[] os : fields)
{
+ Field field = (Field) os[0];
Excel excel = (Excel) os[1];
- String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor());
- if (!styles.containsKey(key))
+ if (Collection.class.isAssignableFrom(field.getType()))
{
- CellStyle style = wb.createCellStyle();
- style.setAlignment(excel.align());
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.THIN);
- style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFillForegroundColor(excel.backgroundColor().getIndex());
- Font dataFont = wb.createFont();
- dataFont.setFontName("Arial");
- dataFont.setFontHeightInPoints((short) 10);
- dataFont.setColor(excel.color().index);
- style.setFont(dataFont);
- styles.put(key, style);
+ ParameterizedType pt = (ParameterizedType) field.getGenericType();
+ Class> subClass = (Class>) pt.getActualTypeArguments()[0];
+ List subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ annotationDataStyles(styles, subField, subExcel);
+ }
+ }
+ else
+ {
+ annotationDataStyles(styles, field, excel);
}
}
return styles;
}
+ /**
+ * 根据Excel注解创建表格列样式
+ *
+ * @param styles 自定义样式列表
+ * @param field 属性列信息
+ * @param excel 注解信息
+ */
+ public void annotationDataStyles(Map styles, Field field, Excel excel)
+ {
+ String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
+ if (!styles.containsKey(key))
+ {
+ CellStyle style = wb.createCellStyle();
+ style.setAlignment(excel.align());
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.THIN);
+ style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFillForegroundColor(excel.backgroundColor().getIndex());
+ Font dataFont = wb.createFont();
+ dataFont.setFontName("Arial");
+ dataFont.setFontHeightInPoints((short) 10);
+ dataFont.setColor(excel.color().index);
+ style.setFont(dataFont);
+ if (ColumnType.TEXT == excel.cellType())
+ {
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
+ }
+ styles.put(key, style);
+ }
+ }
+
/**
* 创建单元格
*/
@@ -904,7 +947,7 @@ public class ExcelUtil
if (isSubList())
{
// 填充默认样式,防止合并单元格样式失效
- sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+ sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
if (attr.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -922,7 +965,7 @@ public class ExcelUtil
*/
public void setCellVo(Object value, Excel attr, Cell cell)
{
- if (ColumnType.STRING == attr.cellType())
+ if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
{
String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
@@ -999,17 +1042,28 @@ public class ExcelUtil
// 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
}
- if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
+ if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
{
- if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
+ String[] comboArray = attr.combo();
+ if (attr.comboReadDict())
+ {
+ if (!sysDictMap.containsKey("combo_" + attr.dictType()))
+ {
+ String labels = DictUtils.getDictLabels(attr.dictType());
+ sysDictMap.put("combo_" + attr.dictType(), labels);
+ }
+ String val = sysDictMap.get("combo_" + attr.dictType());
+ comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
+ }
+ if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
{
// 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
- setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+ setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
}
else
{
// 提示信息或只能选择不能输入的列内容.
- setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+ setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
}
}
}
@@ -1034,7 +1088,7 @@ public class ExcelUtil
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress);
}
- cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor())));
+ cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
index 9f40118c7b50be503a9a9f4d3c74c87921ce76b7..e345cb45b0f718f7dfc1a6abc3a65bee53bce0bb 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
@@ -13,7 +13,7 @@ public class SqlUtil
/**
* 定义常用的 sql关键字
*/
- public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
+ public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
index 0bcd7d0733c4cfc9c38634eb39e856dcd2cf7e2e..de50de35da7ffb32bb9aafa9a8cf8580ce063096 100644
--- a/ruoyi-framework/pom.xml
+++ b/ruoyi-framework/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.7
+ 3.8.8
4.0.0
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
index 35a6b50d064e8ec44d71baa8b7b105893c20cc3c..719c3711fc71fd3901618803fa20ed811c2c6532 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -7,6 +7,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
@@ -73,8 +74,7 @@ public class DataScopeAspect
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
- dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
- controllerDataScope.userAlias(), permission);
+ dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
}
}
}
@@ -92,16 +92,22 @@ public class DataScopeAspect
{
StringBuilder sqlString = new StringBuilder();
List conditions = new ArrayList();
+ List scopeCustomIds = new ArrayList();
+ user.getRoles().forEach(role -> {
+ if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+ {
+ scopeCustomIds.add(Convert.toStr(role.getRoleId()));
+ }
+ });
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
- if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
+ if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
{
continue;
}
- if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
- && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+ if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
@@ -113,9 +119,15 @@ public class DataScopeAspect
}
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
- sqlString.append(StringUtils.format(
- " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
- role.getRoleId()));
+ if (scopeCustomIds.size() > 1)
+ {
+ // 多个自定数据权限使用in查询,避免多次拼接。
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
+ }
+ else
+ {
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
+ }
}
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
@@ -123,9 +135,7 @@ public class DataScopeAspect
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
- sqlString.append(StringUtils.format(
- " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
- deptAlias, user.getDeptId(), user.getDeptId()));
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
@@ -142,7 +152,7 @@ public class DataScopeAspect
conditions.add(dataScope);
}
- // 多角色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
+ // 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
if (StringUtils.isEmpty(conditions))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
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 bd22052571c2b0b5d5deb1ca5bcb790c29576772..ca9a10f7079407b1b8f6cb3555f54a3fbd37b16e 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
@@ -172,8 +172,7 @@ public class LogAspect
{
Map, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
String requestMethod = operLog.getRequestMethod();
- if (StringUtils.isEmpty(paramsMap)
- && (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
+ if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
{
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..163fd01c6943eac36b394e99e0a8e34db629ef09
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
@@ -0,0 +1,43 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 资源文件配置加载
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class I18nConfig implements WebMvcConfigurer
+{
+ @Bean
+ public LocaleResolver localeResolver()
+ {
+ SessionLocaleResolver slr = new SessionLocaleResolver();
+ // 默认语言
+ slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
+ return slr;
+ }
+
+ @Bean
+ public LocaleChangeInterceptor localeChangeInterceptor()
+ {
+ LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
+ // 参数名
+ lci.setParamName("lang");
+ return lci;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry)
+ {
+ registry.addInterceptor(localeChangeInterceptor());
+ }
+}
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 4e067a7b16f217ad8ac159c070f443c9db4d5787..b6afb5db1c1ba746c6f35d1944f149a3046dec16 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
@@ -36,7 +36,7 @@ public class ResourcesConfig implements WebMvcConfigurer
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
- .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
+ .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
}
/**
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
index bdb7199fe9c9335c901b00a77eb89681fa1ab6cc..b04beffb4821142895dca2159fd334a2e3011ab2 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -2,16 +2,17 @@ package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
@@ -25,8 +26,9 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
*
* @author ruoyi
*/
-@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
-public class SecurityConfig extends WebSecurityConfigurerAdapter
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
+@Configuration
+public class SecurityConfig
{
/**
* 自定义用户认证逻辑
@@ -65,16 +67,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
private PermitAllUrlProperties permitAllUrl;
/**
- * 解决 无法直接注入 AuthenticationManager
- *
- * @return
- * @throws Exception
+ * 身份验证实现
*/
@Bean
- @Override
- public AuthenticationManager authenticationManagerBean() throws Exception
+ public AuthenticationManager authenticationManager()
{
- return super.authenticationManagerBean();
+ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
+ daoAuthenticationProvider.setUserDetailsService(userDetailsService);
+ daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
+ return new ProviderManager(daoAuthenticationProvider);
}
/**
@@ -92,40 +93,39 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
- @Override
- protected void configure(HttpSecurity httpSecurity) throws Exception
+ @Bean
+ protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
{
- // 注解标记允许匿名访问的url
- ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
- permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
-
- httpSecurity
- // CSRF禁用,因为不使用session
- .csrf().disable()
- // 禁用HTTP响应标头
- .headers().cacheControl().disable().and()
- // 认证失败处理类
- .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
- // 基于token,所以不需要session
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
- // 过滤请求
- .authorizeRequests()
+ return httpSecurity
+ // CSRF禁用,因为不使用session
+ .csrf(csrf -> csrf.disable())
+ // 禁用HTTP响应标头
+ .headers((headersCustomizer) -> {
+ headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
+ })
+ // 认证失败处理类
+ .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
+ // 基于token,所以不需要session
+ .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ // 注解标记允许匿名访问的url
+ .authorizeHttpRequests((requests) -> {
+ permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
- .antMatchers("/login", "/register", "/captchaImage").permitAll()
- // 静态资源,可匿名访问
- .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
- .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
- // 除上面外的所有请求全部需要鉴权认证
- .anyRequest().authenticated()
- .and()
- .headers().frameOptions().disable();
- // 添加Logout filter
- httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
- // 添加JWT filter
- httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
- // 添加CORS filter
- httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
- httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
+ requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
+ // 静态资源,可匿名访问
+ .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
+ .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
+ // 除上面外的所有请求全部需要鉴权认证
+ .anyRequest().authenticated();
+ })
+ // 添加Logout filter
+ .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
+ // 添加JWT filter
+ .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
+ // 添加CORS filter
+ .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
+ .addFilterBefore(corsFilter, LogoutFilter.class)
+ .build();
}
/**
@@ -136,13 +136,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
{
return new BCryptPasswordEncoder();
}
-
- /**
- * 身份认证接口
- */
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception
- {
- auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
- }
}
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 d4d6421255d85dc4afd98a38a9b3e73ddf43ba4a..e118fb53143b6e379eff0e58d61d4c548d45e7f7 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
@@ -13,9 +13,11 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
/**
* 全局异常处理器
@@ -79,8 +81,13 @@ public class GlobalExceptionHandler
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
+ String value = Convert.toStr(e.getValue());
+ if (StringUtils.isNotEmpty(value))
+ {
+ value = EscapeUtil.clean(value);
+ }
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
- return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
+ return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
}
/**
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
index 4831849d2ea88bad15eb85f6f210eedb7c17339d..97abcead1b54da1d31ade31e39cfb259639b4c0c 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -115,12 +115,12 @@ public class SysLoginService
{
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
String captcha = redisCache.getCacheObject(verifyKey);
- redisCache.deleteObject(verifyKey);
if (captcha == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
+ redisCache.deleteObject(verifyKey);
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
index 64007506532f9ab4d5bbd8dc94e9af6f2df27bcc..dbfccde27bf49d5723b3449d7cdade8070449020 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
@@ -6,8 +6,10 @@ import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
+import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRoleService;
@@ -68,9 +70,12 @@ public class SysPermissionService
// 多角色设置permissions属性,以便数据权限匹配权限
for (SysRole role : roles)
{
- Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
- role.setPermissions(rolePerms);
- perms.addAll(rolePerms);
+ if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL))
+ {
+ Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
+ role.setPermissions(rolePerms);
+ perms.addAll(rolePerms);
+ }
}
}
else
diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml
index 83fde2f535f63985d8e2f4c1f872cc200dd83bce..27d31cc6f1ab0935152d2dbda08bf5fffc4b9d4b 100644
--- a/ruoyi-generator/pom.xml
+++ b/ruoyi-generator/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.7
+ 3.8.8
4.0.0
@@ -17,24 +17,24 @@
-
+
org.apache.velocity
velocity-engine-core
-
-
- commons-collections
- commons-collections
-
-
com.ruoyi
ruoyi-common
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
index af9f4ee38525a2243cf1a084ce691942e490cda1..75f7fbe1782f15c64bd0c5dff75f0ea26ad2a097 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
@@ -1,6 +1,7 @@
package com.ruoyi.generator.controller;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -17,12 +18,18 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import com.alibaba.druid.DbType;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.service.IGenTableColumnService;
@@ -109,10 +116,47 @@ public class GenController extends BaseController
String[] tableNames = Convert.toStrArray(tables);
// 查询表信息
List tableList = genTableService.selectDbTableListByNames(tableNames);
- genTableService.importGenTable(tableList);
+ genTableService.importGenTable(tableList, SecurityUtils.getUsername());
return success();
}
+ /**
+ * 创建表结构(保存)
+ */
+ @PreAuthorize("@ss.hasRole('admin')")
+ @Log(title = "创建表", businessType = BusinessType.OTHER)
+ @PostMapping("/createTable")
+ public AjaxResult createTableSave(String sql)
+ {
+ try
+ {
+ SqlUtil.filterKeyword(sql);
+ List sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
+ List tableNames = new ArrayList<>();
+ for (SQLStatement sqlStatement : sqlStatements)
+ {
+ if (sqlStatement instanceof MySqlCreateTableStatement)
+ {
+ MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
+ if (genTableService.createTable(createTableStatement.toString()))
+ {
+ String tableName = createTableStatement.getTableName().replaceAll("`", "");
+ tableNames.add(tableName);
+ }
+ }
+ }
+ List tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
+ String operName = SecurityUtils.getUsername();
+ genTableService.importGenTable(tableList, operName);
+ return AjaxResult.success();
+ }
+ catch (Exception e)
+ {
+ logger.error(e.getMessage(), e);
+ return AjaxResult.error("创建表结构异常");
+ }
+ }
+
/**
* 修改保存代码生成业务
*/
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
index c3af38f096b8fb411daf80981405758068363fad..2777d419e6b2c5b582f993cc20229c9505285b26 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
@@ -93,7 +93,7 @@ public class GenTable extends BaseEntity
private String treeName;
/** 上级菜单ID字段 */
- private String parentMenuId;
+ private Long parentMenuId;
/** 上级菜单名称字段 */
private String parentMenuName;
@@ -318,12 +318,12 @@ public class GenTable extends BaseEntity
this.treeName = treeName;
}
- public String getParentMenuId()
+ public Long getParentMenuId()
{
return parentMenuId;
}
- public void setParentMenuId(String parentMenuId)
+ public void setParentMenuId(Long parentMenuId)
{
this.parentMenuId = parentMenuId;
}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
index c2fdf71fdf4673a769d26c90e91023d019145d12..a5ce3c6072c865147ded8722653143c75994288a 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
@@ -80,4 +80,12 @@ public interface GenTableMapper
* @return 结果
*/
public int deleteGenTableByIds(Long[] ids);
+
+ /**
+ * 创建表
+ *
+ * @param sql 表结构
+ * @return 结果
+ */
+ public int createTable(String sql);
}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
index ff6291db3540e34ada7338ebdf685760a23edf12..99a837aa34aedff8b6ba31c8122c6ed787a6676f 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
@@ -27,7 +27,6 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.text.CharsetKit;
import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
@@ -150,6 +149,18 @@ public class GenTableServiceImpl implements IGenTableService
genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
}
+ /**
+ * 创建表
+ *
+ * @param sql 创建表语句
+ * @return 结果
+ */
+ @Override
+ public boolean createTable(String sql)
+ {
+ return genTableMapper.createTable(sql) == 0;
+ }
+
/**
* 导入表结构
*
@@ -157,9 +168,8 @@ public class GenTableServiceImpl implements IGenTableService
*/
@Override
@Transactional
- public void importGenTable(List tableList)
+ public void importGenTable(List tableList, String operName)
{
- String operName = SecurityUtils.getUsername();
try
{
for (GenTable table : tableList)
@@ -491,7 +501,7 @@ public class GenTableServiceImpl implements IGenTableService
String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
String treeName = paramsObj.getString(GenConstants.TREE_NAME);
- String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
+ Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID);
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
genTable.setTreeCode(treeCode);
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
index 955b326bd95cd86284135208750a52ab3f9389b7..526038d591ca32f1c1444e180f3617485be4afb5 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
@@ -66,12 +66,21 @@ public interface IGenTableService
*/
public void deleteGenTableByIds(Long[] tableIds);
+ /**
+ * 创建表
+ *
+ * @param sql 创建表语句
+ * @return 结果
+ */
+ public boolean createTable(String sql);
+
/**
* 导入表结构
- *
+ *
* @param tableList 导入表列表
+ * @param operName 操作人员
*/
- public void importGenTable(List tableList);
+ public void importGenTable(List tableList, String operName);
/**
* 预览代码
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
index 9c65e4ca6fedc0066b0e88efa2136d1a5ce4d0f5..8d7dd8bf6eb958c2dc16726674735afa42f74777 100644
--- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -26,7 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-
+
@@ -68,10 +68,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
- AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
+ AND date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
- AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
+ AND date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
@@ -79,7 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-
+#if($table.sub)
+
+
+#end
+
insert into ${tableName}
@@ -127,7 +132,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values
-
+
(#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end)
diff --git a/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml
index 80279a821e7dea2db5f91bc693521444278766b7..acfd4d442eff4185ee7f5679c35ca6b5322f16e1 100644
--- a/ruoyi-quartz/pom.xml
+++ b/ruoyi-quartz/pom.xml
@@ -5,7 +5,7 @@
ruoyi
com.ruoyi
- 3.8.7
+ 3.8.8
4.0.0
diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
index 588d17705b6f0faa603c70d8dcd51aeb5756426e..5ed72647b3e4f58585ebc1ed16f4d9a05eebdea1 100644
--- a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
+++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
@@ -36,12 +36,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND invoke_target like concat('%', #{invokeTarget}, '%')
- and date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
+ and date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
- and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
+ and date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ order by create_time desc
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
index 75d80a157f38ba36f1341e3ce42a4aad91bb394d..c5e1da9d073481c8502baa0fb8daa52e6eeb37dc 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
@@ -41,7 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by dict_sort asc
-
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
index e90f6baf0bbc6aa7d0617179a4d356e02a2dc99c..e6be3aefd4dfecf9dba8b7352bcc6b7a6752d4d2 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -13,6 +13,7 @@
+
@@ -28,7 +29,7 @@
@@ -49,13 +50,13 @@