diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml index 35b6b07f8..99818dcca 100644 --- a/.run/ruoyi-monitor-admin.run.xml +++ b/.run/ruoyi-monitor-admin.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-server.run.xml b/.run/ruoyi-server.run.xml index c0c575bee..6c3cd5e26 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-xxl-job-admin.run.xml b/.run/ruoyi-xxl-job-admin.run.xml index ae25907a8..98939edbd 100644 --- a/.run/ruoyi-xxl-job-admin.run.xml +++ b/.run/ruoyi-xxl-job-admin.run.xml @@ -2,7 +2,7 @@ - diff --git a/README.md b/README.md index 728871149..0a08820b3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.5.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.6.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.7-blue.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() diff --git a/pom.xml b/pom.xml index 5efd58c9a..d466abf71 100644 --- a/pom.xml +++ b/pom.xml @@ -6,45 +6,46 @@ com.ruoyi ruoyi-vue-plus - 4.5.0 + 4.6.0 RuoYi-Vue-Plus https://gitee.com/JavaLionLi/RuoYi-Vue-Plus RuoYi-Vue-Plus后台管理系统 - 4.5.0 - 2.7.7 + 4.6.0 + 2.7.9 UTF-8 UTF-8 1.8 3.2.2 2.2.2 - 1.6.14 + 1.6.15 5.2.3 - 3.1.5 + 3.2.1 2.3 1.34.0 3.5.3.1 3.9.1 - 5.8.11 + 5.8.15 4.10.0 2.7.10 - 3.19.1 + 3.20.0 2.2.3 3.5.2 2.14.2 2.3.1 - 1.18.24 + 1.18.26 + 1.72 1.33 - 1.12.373 + 1.12.400 2.0.23 - 3.1.660 + 3.1.687 @@ -264,6 +265,13 @@ ${snakeyaml.version} + + + org.bouncycastle + bcprov-jdk15to18 + ${bouncycastle.version} + + com.ruoyi diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 91baa5cfa..968969d2a 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 jar diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java index c1b3acd86..f5cb2a5ee 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -79,7 +79,7 @@ public R getConfigKey(@PathVariable String configKey) { @Log(title = "参数管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysConfig config) { - if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { + if (!configService.checkConfigKeyUnique(config)) { return R.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); } configService.insertConfig(config); @@ -93,7 +93,7 @@ public R add(@Validated @RequestBody SysConfig config) { @Log(title = "参数管理", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysConfig config) { - if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { + if (!configService.checkConfigKeyUnique(config)) { return R.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); } configService.updateConfig(config); 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 fa763df33..512c644c4 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 @@ -1,7 +1,7 @@ package com.ruoyi.web.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.convert.Convert; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; @@ -49,7 +49,7 @@ public R> list(SysDept dept) { public R> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) { List depts = deptService.selectDeptList(new SysDept()); depts.removeIf(d -> d.getDeptId().equals(deptId) - || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); + || StringUtils.splitList(d.getAncestors()).contains(Convert.toStr(deptId))); return R.ok(depts); } @@ -72,7 +72,7 @@ public R getInfo(@PathVariable Long deptId) { @Log(title = "部门管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysDept dept) { - if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { + if (!deptService.checkDeptNameUnique(dept)) { return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); } return toAjax(deptService.insertDept(dept)); @@ -87,7 +87,7 @@ public R add(@Validated @RequestBody SysDept dept) { public R edit(@Validated @RequestBody SysDept dept) { Long deptId = dept.getDeptId(); deptService.checkDeptDataScope(deptId); - if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { + if (!deptService.checkDeptNameUnique(dept)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); } else if (dept.getParentId().equals(deptId)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java index 86840b7a5..e6beb64ab 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java @@ -69,7 +69,7 @@ public R getInfo(@PathVariable Long dictId) { @Log(title = "字典类型", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysDictType dict) { - if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { + if (!dictTypeService.checkDictTypeUnique(dict)) { return R.fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); } dictTypeService.insertDictType(dict); @@ -83,7 +83,7 @@ public R add(@Validated @RequestBody SysDictType dict) { @Log(title = "字典类型", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysDictType dict) { - if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { + if (!dictTypeService.checkDictTypeUnique(dict)) { return R.fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); } dictTypeService.updateDictType(dict); 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 e80f0ee7c..1f1386156 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 @@ -82,7 +82,7 @@ public R> roleMenuTreeselect(@PathVariable("roleId") Long ro @Log(title = "菜单管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysMenu menu) { - if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { + if (!menuService.checkMenuNameUnique(menu)) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); @@ -97,7 +97,7 @@ public R add(@Validated @RequestBody SysMenu menu) { @Log(title = "菜单管理", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysMenu menu) { - if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { + if (!menuService.checkMenuNameUnique(menu)) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java index 656987776..4036364fa 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java @@ -69,9 +69,9 @@ public R getInfo(@PathVariable Long postId) { @Log(title = "岗位管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysPost post) { - if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) { + if (!postService.checkPostNameUnique(post)) { return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); - } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { + } else if (!postService.checkPostCodeUnique(post)) { return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); } return toAjax(postService.insertPost(post)); @@ -84,9 +84,9 @@ public R add(@Validated @RequestBody SysPost post) { @Log(title = "岗位管理", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysPost post) { - if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) { + if (!postService.checkPostNameUnique(post)) { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); - } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { + } else if (!postService.checkPostCodeUnique(post)) { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); } return toAjax(postService.updatePost(post)); 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 77a8767de..9e646ec2c 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 @@ -58,12 +58,10 @@ public R> profile() { @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping public R updateProfile(@RequestBody SysUser user) { - if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); } - if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { + if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setUserId(getUserId()); 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 5768806c2..47e157512 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 @@ -1,8 +1,11 @@ package com.ruoyi.web.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.util.ObjectUtil; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.PageQuery; @@ -84,9 +87,9 @@ public R getInfo(@PathVariable Long roleId) { @Log(title = "角色管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysRole role) { - if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { + if (!roleService.checkRoleNameUnique(role)) { return R.fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); - } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { + } else if (!roleService.checkRoleKeyUnique(role)) { return R.fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); } return toAjax(roleService.insertRole(role)); @@ -102,20 +105,32 @@ public R add(@Validated @RequestBody SysRole role) { public R edit(@Validated @RequestBody SysRole role) { roleService.checkRoleAllowed(role); roleService.checkRoleDataScope(role.getRoleId()); - if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { + if (!roleService.checkRoleNameUnique(role)) { return R.fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); - } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { + } else if (!roleService.checkRoleKeyUnique(role)) { return R.fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); } if (roleService.updateRole(role) > 0) { - // 更新缓存用户权限 - LoginUser loginUser = getLoginUser(); - SysUser sysUser = userService.selectUserById(loginUser.getUserId()); - if (ObjectUtil.isNotNull(sysUser) && !sysUser.isAdmin()) { - loginUser.setMenuPermission(permissionService.getMenuPermission(sysUser)); - LoginHelper.setLoginUser(loginUser); + List keys = StpUtil.searchTokenValue("", 0, -1, false); + if (CollUtil.isEmpty(keys)) { + return R.ok(); } + // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作 + keys.parallelStream().forEach(key -> { + String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, ""); + // 如果已经过期则跳过 + if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) { + return; + } + LoginUser loginUser = LoginHelper.getLoginUser(token); + if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(role.getRoleId()))) { + try { + StpUtil.logoutByTokenValue(token); + } catch (NotLoginException ignored) { + } + } + }); return R.ok(); } return R.fail("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); 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 7e358d511..0b91c50b9 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 @@ -136,13 +136,11 @@ public R> getInfo(@PathVariable(value = "userId", required = @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysUser user) { - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { + if (!userService.checkUserNameUnique(user)) { return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); - } else if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); - } else if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setPassword(BCrypt.hashpw(user.getPassword())); @@ -158,13 +156,11 @@ public R add(@Validated @RequestBody SysUser user) { public R edit(@Validated @RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { + if (!userService.checkUserNameUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); - } else if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } else if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } return toAjax(userService.updateUser(user)); diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 7b7380b8a..32123a764 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -86,15 +86,17 @@ spring: # 最小空闲线程数量 minIdle: 10 # 配置获取连接等待超时的时间 - connectionTimeout: 10000 + connectionTimeout: 30000 # 校验超时时间 validationTimeout: 5000 # 空闲连接存活最大时间,默认10分钟 - idleTimeout: 60000 + idleTimeout: 600000 # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 - maxLifetime: 900000 + maxLifetime: 1800000 # 连接测试query(配置检测连接是否有效) connectionTestQuery: SELECT 1 + # 多久检查一次连接的活性 + keepaliveTime: 30000 --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 970fe4c5a..85f6e935d 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -89,15 +89,17 @@ spring: # 最小空闲线程数量 minIdle: 10 # 配置获取连接等待超时的时间 - connectionTimeout: 10000 + connectionTimeout: 30000 # 校验超时时间 validationTimeout: 5000 # 空闲连接存活最大时间,默认10分钟 - idleTimeout: 60000 + idleTimeout: 600000 # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 - maxLifetime: 900000 + maxLifetime: 1800000 # 连接测试query(配置检测连接是否有效) connectionTestQuery: SELECT 1 + # 多久检查一次连接的活性 + keepaliveTime: 30000 --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 0468a33ac..d87088d1b 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -128,8 +128,10 @@ security: - /**/*.html - /**/*.css - /**/*.js - # swagger 文档配置 + # 公共路径 - /favicon.ico + - /error + # swagger 文档配置 - /*/api-docs - /*/api-docs/** # actuator 监控配置 @@ -180,10 +182,22 @@ mybatis-plus: # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件 where-strategy: NOT_NULL +# 数据加密 +mybatis-encryptor: + # 是否开启加密 + enable: false + # 默认加密算法 + algorithm: BASE64 + # 编码方式 BASE64/HEX。默认BASE64 + encode: BASE64 + # 安全秘钥 对称算法的秘钥 如:AES,SM4 + password: + # 公私钥 非对称算法的公私钥 如:SM2,RSA + publicKey: + privateKey: + # Swagger配置 swagger: - # 是否开启swagger - enabled: true info: # 标题 title: '标题:${ruoyi.name}后台管理系统_接口文档' @@ -205,6 +219,9 @@ swagger: name: ${sa-token.token-name} springdoc: + api-docs: + # 是否开启接口文档 + enabled: true swagger-ui: # 持久化认证数据 persistAuthorization: true diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index c438bf73c..e6e888eb8 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 @@ -146,7 +146,6 @@ org.redisson redisson-spring-data-27 - ${redisson.version} @@ -154,6 +153,12 @@ lock4j-redisson-spring-boot-starter + + + org.bouncycastle + bcprov-jdk15to18 + + 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 index 5c14a5520..564b2a4a1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java @@ -13,7 +13,9 @@ * 字典数据映射注解 * * @author itino + * @deprecated 建议使用通用翻译注解 */ +@Deprecated @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) @JacksonAnnotationsInside diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java new file mode 100644 index 000000000..2d6a321f1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java @@ -0,0 +1,44 @@ +package com.ruoyi.common.annotation; + +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; + +import java.lang.annotation.*; + +/** + * 字段加密注解 + * + * @author 老马 + */ +@Documented +@Inherited +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface EncryptField { + + /** + * 加密算法 + */ + AlgorithmType algorithm() default AlgorithmType.DEFAULT; + + /** + * 秘钥。AES、SM4需要 + */ + String password() default ""; + + /** + * 公钥。RSA、SM2需要 + */ + String publicKey() default ""; + + /** + * 公钥。RSA、SM2需要 + */ + String privateKey() default ""; + + /** + * 编码方式。对加密算法为BASE64的不起作用 + */ + EncodeType encode() default EncodeType.DEFAULT; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java index 400080ea7..4bb0cc868 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java @@ -1,5 +1,7 @@ package com.ruoyi.common.annotation; +import com.ruoyi.common.utils.StringUtils; + import java.lang.annotation.*; /** @@ -25,6 +27,6 @@ /** * 分隔符,读取字符串组内容 */ - String separator() default ","; + String separator() default StringUtils.SEPARATOR; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelEnumFormat.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelEnumFormat.java new file mode 100644 index 000000000..a8f550a4a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelEnumFormat.java @@ -0,0 +1,30 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.*; + +/** + * 枚举格式化 + * + * @author Liang + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ExcelEnumFormat { + + /** + * 字典枚举类型 + */ + Class> enumClass(); + + /** + * 字典枚举类中对应的code属性名称,默认为code + */ + String codeField() default "code"; + + /** + * 字典枚举类中对应的text属性名称,默认为text + */ + String textField() default "text"; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java index 32c39a3b0..f9ba00126 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java @@ -38,4 +38,10 @@ * 是否保存响应的参数 */ boolean isSaveResponseData() default true; + + /** + * 排除指定的请求参数 + */ + String[] excludeParamNames() default {}; + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java index 2e3ff7a82..6eeb2f2c4 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java @@ -1,6 +1,5 @@ package com.ruoyi.common.annotation; -import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.enums.LimitType; import java.lang.annotation.*; @@ -15,9 +14,10 @@ @Documented public @interface RateLimiter { /** - * 限流key + * 限流key,支持使用Spring el表达式来动态获取方法上的参数值 + * 格式类似于 #code.id #{#code} */ - String key() default CacheConstants.RATE_LIMIT_KEY; + String key() default ""; /** * 限流时间,单位秒 @@ -33,4 +33,9 @@ * 限流类型 */ LimitType limitType() default LimitType.DEFAULT; + + /** + * 提示消息 支持国际化 格式为 {code} + */ + String message() default "{rate.limiter.message}"; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Translation.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Translation.java new file mode 100644 index 000000000..ba8cd22ca --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Translation.java @@ -0,0 +1,39 @@ +package com.ruoyi.common.annotation; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.ruoyi.common.translation.handler.TranslationHandler; + +import java.lang.annotation.*; + +/** + * 通用翻译注解 + * + * @author Lion Li + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +@Documented +@JacksonAnnotationsInside +@JsonSerialize(using = TranslationHandler.class) +public @interface Translation { + + /** + * 类型 (需与实现类上的 {@link com.ruoyi.common.annotation.TranslationType} 注解type对应) + *

+ * 默认取当前字段的值 如果设置了 @{@link Translation#mapper()} 则取映射字段的值 + */ + String type(); + + /** + * 映射字段 (如果不为空则取此字段的值) + */ + String mapper() default ""; + + /** + * 其他条件 例如: 字典type(sys_user_sex) + */ + String other() default ""; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/TranslationType.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/TranslationType.java new file mode 100644 index 000000000..f592f6d80 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/TranslationType.java @@ -0,0 +1,21 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.*; + +/** + * 翻译类型注解 (标注到{@link com.ruoyi.common.translation.TranslationInterface} 的实现类) + * + * @author Lion Li + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Documented +public @interface TranslationType { + + /** + * 类型 + */ + String type(); + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java index 591ca2546..1396b6d18 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java @@ -30,6 +30,16 @@ public interface CacheNames { */ String SYS_DICT = "sys_dict"; + /** + * 用户账户 + */ + String SYS_USER_NAME = "sys_user_name#30d"; + + /** + * 部门 + */ + String SYS_DEPT = "sys_dept#30d"; + /** * OSS内容 */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/TransConstant.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/TransConstant.java new file mode 100644 index 000000000..5c5e5f8e0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/TransConstant.java @@ -0,0 +1,30 @@ +package com.ruoyi.common.constant; + +/** + * 翻译常量 + * + * @author Lion Li + */ +public interface TransConstant { + + /** + * 用户id转账号 + */ + String USER_ID_TO_NAME = "user_id_to_name"; + + /** + * 部门id转名称 + */ + String DEPT_ID_TO_NAME = "dept_id_to_name"; + + /** + * 字典type转label + */ + String DICT_TYPE_TO_LABEL = "dict_type_to_label"; + + /** + * ossId转url + */ + String OSS_ID_TO_URL = "oss_id_to_url"; + +} 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 9f800be2f..4a095faad 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 @@ -112,12 +112,6 @@ public interface UserConstants { */ String INNER_LINK = "InnerLink"; - /** - * 校验返回结果码 - */ - String UNIQUE = "0"; - String NOT_UNIQUE = "1"; - /** * 用户名长度限制 */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelEnumConvert.java b/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelEnumConvert.java new file mode 100644 index 000000000..c69d90cfb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelEnumConvert.java @@ -0,0 +1,75 @@ +package com.ruoyi.common.convert; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.ruoyi.common.annotation.ExcelEnumFormat; +import com.ruoyi.common.utils.reflect.ReflectUtils; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * 枚举格式化转换处理 + * + * @author Liang + */ +@Slf4j +public class ExcelEnumConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Object.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + Object codeValue = cellData.getData(); + // 如果是空值 + if (ObjectUtil.isNull(codeValue)) { + return null; + } + Map enumValueMap = beforeConvert(contentProperty); + String textValue = enumValueMap.get(codeValue); + return Convert.convert(contentProperty.getField().getType(), textValue); + } + + @Override + public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (ObjectUtil.isNull(object)) { + return new WriteCellData<>(""); + } + Map enumValueMap = beforeConvert(contentProperty); + String value = Convert.toStr(enumValueMap.get(object), ""); + return new WriteCellData<>(value); + } + + private Map beforeConvert(ExcelContentProperty contentProperty) { + ExcelEnumFormat anno = getAnnotation(contentProperty.getField()); + Map enumValueMap = new HashMap<>(); + Enum[] enumConstants = anno.enumClass().getEnumConstants(); + for (Enum enumConstant : enumConstants) { + Object codeValue = ReflectUtils.invokeGetter(enumConstant, anno.codeField()); + String textValue = ReflectUtils.invokeGetter(enumConstant, anno.textField()); + enumValueMap.put(codeValue, textValue); + } + return enumValueMap; + } + + private ExcelEnumFormat getAnnotation(Field field) { + return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java index 60abde623..8a45905bb 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java @@ -87,8 +87,8 @@ private List buildOrderItem() { // 兼容前端排序类型 isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"}); - String[] orderByArr = orderBy.split(","); - String[] isAscArr = isAsc.split(","); + String[] orderByArr = orderBy.split(StringUtils.SEPARATOR); + String[] isAscArr = isAsc.split(StringUtils.SEPARATOR); if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) { throw new ServiceException("排序参数有误"); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java index 857f9b8db..ba4a382c7 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -34,7 +34,7 @@ public class SysDept extends TreeEntity { * 部门名称 */ @NotBlank(message = "部门名称不能为空") - @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") + @Size(min = 0, max = 30, message = "部门名称长度不能超过{max}个字符") private String deptName; /** @@ -51,14 +51,14 @@ public class SysDept extends TreeEntity { /** * 联系电话 */ - @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") + @Size(min = 0, max = 11, message = "联系电话长度不能超过{max}个字符") private String phone; /** * 邮箱 */ @Email(message = "邮箱格式不正确") - @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") private String email; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java index e20f96aa7..4ed2c5483 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -44,7 +44,7 @@ public class SysDictData extends BaseEntity { */ @ExcelProperty(value = "字典标签") @NotBlank(message = "字典标签不能为空") - @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") + @Size(min = 0, max = 100, message = "字典标签长度不能超过{max}个字符") private String dictLabel; /** @@ -52,7 +52,7 @@ public class SysDictData extends BaseEntity { */ @ExcelProperty(value = "字典键值") @NotBlank(message = "字典键值不能为空") - @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") + @Size(min = 0, max = 100, message = "字典键值长度不能超过{max}个字符") private String dictValue; /** @@ -60,13 +60,13 @@ public class SysDictData extends BaseEntity { */ @ExcelProperty(value = "字典类型") @NotBlank(message = "字典类型不能为空") - @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") + @Size(min = 0, max = 100, message = "字典类型长度不能超过{max}个字符") private String dictType; /** * 样式属性(其他样式扩展) */ - @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") + @Size(min = 0, max = 100, message = "样式属性长度不能超过{max}个字符") private String cssClass; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java index 36e38a971..76c20e102 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -38,7 +38,7 @@ public class SysDictType extends BaseEntity { */ @ExcelProperty(value = "字典名称") @NotBlank(message = "字典名称不能为空") - @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过{max}个字符") private String dictName; /** @@ -46,7 +46,7 @@ public class SysDictType extends BaseEntity { */ @ExcelProperty(value = "字典类型") @NotBlank(message = "字典类型不能为空") - @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符") @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)") private String dictType; 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 201605f96..38bd93659 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 @@ -32,7 +32,7 @@ public class SysMenu extends TreeEntity { * 菜单名称 */ @NotBlank(message = "菜单名称不能为空") - @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") + @Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符") private String menuName; /** @@ -44,13 +44,13 @@ public class SysMenu extends TreeEntity { /** * 路由地址 */ - @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") + @Size(min = 0, max = 200, message = "路由地址不能超过{max}个字符") private String path; /** * 组件路径 */ - @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") + @Size(min = 0, max = 200, message = "组件路径不能超过{max}个字符") private String component; /** @@ -88,7 +88,7 @@ public class SysMenu extends TreeEntity { * 权限字符串 */ @JsonInclude(JsonInclude.Include.NON_NULL) - @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") + @Size(min = 0, max = 100, message = "权限标识长度不能超过{max}个字符") private String perms; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java index 52682894a..594956998 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -17,7 +17,6 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -import java.util.Set; /** * 角色表 sys_role @@ -44,7 +43,7 @@ public class SysRole extends BaseEntity { */ @ExcelProperty(value = "角色名称") @NotBlank(message = "角色名称不能为空") - @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") + @Size(min = 0, max = 30, message = "角色名称长度不能超过{max}个字符") private String roleName; /** @@ -52,7 +51,7 @@ public class SysRole extends BaseEntity { */ @ExcelProperty(value = "角色权限") @NotBlank(message = "权限字符不能为空") - @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") + @Size(min = 0, max = 100, message = "权限字符长度不能超过{max}个字符") private String roleKey; /** @@ -115,12 +114,6 @@ public class SysRole extends BaseEntity { @TableField(exist = false) private Long[] deptIds; - /** - * 角色菜单权限 - */ - @TableField(exist = false) - private Set permissions; - public SysRole(Long roleId) { this.roleId = roleId; } 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 f2d961b7a..11fd056b8 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 @@ -1,6 +1,8 @@ package com.ruoyi.common.core.domain.entity; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.ruoyi.common.annotation.Sensitive; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.BaseEntity; @@ -44,14 +46,14 @@ public class SysUser extends BaseEntity { */ @Xss(message = "用户账号不能包含脚本字符") @NotBlank(message = "用户账号不能为空") - @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") + @Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符") private String userName; /** * 用户昵称 */ @Xss(message = "用户昵称不能包含脚本字符") - @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符") private String nickName; /** @@ -64,7 +66,7 @@ public class SysUser extends BaseEntity { */ @Sensitive(strategy = SensitiveStrategy.EMAIL) @Email(message = "邮箱格式不正确") - @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") private String email; /** @@ -91,6 +93,8 @@ public class SysUser extends BaseEntity { updateStrategy = FieldStrategy.NOT_EMPTY, whereStrategy = FieldStrategy.NOT_EMPTY ) + @JsonIgnore + @JsonProperty private String password; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java index c93b9efe1..83fcf9fe8 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -1,7 +1,6 @@ package com.ruoyi.common.core.domain.model; import com.ruoyi.common.core.domain.dto.RoleDTO; -import com.ruoyi.common.helper.LoginHelper; import lombok.Data; import lombok.NoArgsConstructor; @@ -111,7 +110,7 @@ public String getLoginId() { if (userId == null) { throw new IllegalArgumentException("用户ID不能为空"); } - return userType + LoginHelper.JOIN_CODE + userId; + return userType + ":" + userId; } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/DeptService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/DeptService.java new file mode 100644 index 000000000..c27f46182 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/DeptService.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.core.service; + +/** + * 通用 部门服务 + * + * @author Lion Li + */ +public interface DeptService { + + /** + * 通过部门ID查询部门名称 + * + * @param deptIds 部门ID串逗号分隔 + * @return 部门名称串逗号分隔 + */ + String selectDeptNameByIds(String deptIds); + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OssService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OssService.java new file mode 100644 index 000000000..65dda7c64 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/OssService.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.core.service; + +/** + * 通用 OSS服务 + * + * @author Lion Li + */ +public interface OssService { + + /** + * 通过ossId查询对应的url + * + * @param ossIds ossId串逗号分隔 + * @return url串逗号分隔 + */ + String selectUrlByIds(String ossIds); + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/UserService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/UserService.java new file mode 100644 index 000000000..d2206c8b0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/UserService.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.core.service; + +/** + * 通用 用户服务 + * + * @author Lion Li + */ +public interface UserService { + + /** + * 通过用户ID查询用户账户 + * + * @param userId 用户ID + * @return 用户账户 + */ + String selectUserNameById(Long userId); + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java new file mode 100644 index 000000000..1b82d51bd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java @@ -0,0 +1,41 @@ +package com.ruoyi.common.encrypt; + +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import lombok.Data; + +/** + * 加密上下文 用于encryptor传递必要的参数。 + * + * @author 老马 + * @version 4.6.0 + */ +@Data +public class EncryptContext { + + /** + * 默认算法 + */ + private AlgorithmType algorithm; + + /** + * 安全秘钥 + */ + private String password; + + /** + * 公钥 + */ + private String publicKey; + + /** + * 私钥 + */ + private String privateKey; + + /** + * 编码方式,base64/hex + */ + private EncodeType encode; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java new file mode 100644 index 000000000..7986a9b79 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.encrypt; + +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; + +/** + * 加解者 + * + * @author 老马 + * @version 4.6.0 + */ +public interface IEncryptor { + + /** + * 获得当前算法 + */ + AlgorithmType algorithm(); + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + * @return 加密后的字符串 + */ + String encrypt(String value, EncodeType encodeType); + + /** + * 解密 + * + * @param value 待加密字符串 + * @return 解密后的字符串 + */ + String decrypt(String value); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java new file mode 100644 index 000000000..860533612 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.encrypt.encryptor; + +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.encrypt.IEncryptor; + +/** + * 所有加密执行者的基类 + * + * @author 老马 + * @version 4.6.0 + */ +public abstract class AbstractEncryptor implements IEncryptor { + + public AbstractEncryptor(EncryptContext context) { + // 用户配置校验与配置注入 + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java new file mode 100644 index 000000000..ee4d82665 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java @@ -0,0 +1,69 @@ +package com.ruoyi.common.encrypt.encryptor; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.symmetric.AES; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; + +import java.nio.charset.StandardCharsets; + +/** + * AES算法实现 + * + * @author 老马 + * @version 4.6.0 + */ +public class AesEncryptor extends AbstractEncryptor { + + private final AES aes; + + public AesEncryptor(EncryptContext context) { + super(context); + String password = context.getPassword(); + if (StrUtil.isBlank(password)) { + throw new IllegalArgumentException("AES没有获得秘钥信息"); + } + // aes算法的秘钥要求是16位、24位、32位 + int[] array = {16, 24, 32}; + if (!ArrayUtil.contains(array, password.length())) { + throw new IllegalArgumentException("AES秘钥长度应该为16位、24位、32位,实际为" + password.length() + "位"); + } + aes = SecureUtil.aes(context.getPassword().getBytes(StandardCharsets.UTF_8)); + } + + /** + * 获得当前算法 + */ + @Override + public AlgorithmType algorithm() { + return AlgorithmType.AES; + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + */ + @Override + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return aes.encryptHex(value); + } else { + return aes.encryptBase64(value); + } + } + + /** + * 解密 + * + * @param value 待加密字符串 + */ + @Override + public String decrypt(String value) { + return this.aes.decryptStr(value); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java new file mode 100644 index 000000000..519158d00 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.encrypt.encryptor; + +import cn.hutool.core.codec.Base64; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; + +/** + * Base64算法实现 + * + * @author 老马 + * @version 4.6.0 + */ +public class Base64Encryptor extends AbstractEncryptor { + + public Base64Encryptor(EncryptContext context) { + super(context); + } + + /** + * 获得当前算法 + */ + @Override + public AlgorithmType algorithm() { + return AlgorithmType.BASE64; + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + */ + @Override + public String encrypt(String value, EncodeType encodeType) { + return Base64.encode(value); + } + + /** + * 解密 + * + * @param value 待加密字符串 + */ + @Override + public String decrypt(String value) { + return Base64.decodeStr(value); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java new file mode 100644 index 000000000..2563fc214 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java @@ -0,0 +1,65 @@ +package com.ruoyi.common.encrypt.encryptor; + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.RSA; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import com.ruoyi.common.utils.StringUtils; + + +/** + * RSA算法实现 + * + * @author 老马 + * @version 4.6.0 + */ +public class RsaEncryptor extends AbstractEncryptor { + + private final RSA rsa; + + public RsaEncryptor(EncryptContext context) { + super(context); + String privateKey = context.getPrivateKey(); + String publicKey = context.getPublicKey(); + if (StringUtils.isAnyEmpty(privateKey, publicKey)) { + throw new IllegalArgumentException("RSA公私钥均需要提供,公钥加密,私钥解密。"); + } + this.rsa = SecureUtil.rsa(Base64.decode(privateKey), Base64.decode(publicKey)); + } + + /** + * 获得当前算法 + */ + @Override + public AlgorithmType algorithm() { + return AlgorithmType.RSA; + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + */ + @Override + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return rsa.encryptHex(value, KeyType.PublicKey); + } else { + return rsa.encryptBase64(value, KeyType.PublicKey); + } + } + + /** + * 解密 + * + * @param value 待加密字符串 + */ + @Override + public String decrypt(String value) { + return this.rsa.decryptStr(value, KeyType.PrivateKey); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java new file mode 100644 index 000000000..a84f7f7ea --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java @@ -0,0 +1,65 @@ +package com.ruoyi.common.encrypt.encryptor; + + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.SM2; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import com.ruoyi.common.utils.StringUtils; + +/** + * sm2算法实现 + * + * @author 老马 + * @version 4.6.0 + */ +public class Sm2Encryptor extends AbstractEncryptor { + + private final SM2 sm2; + + public Sm2Encryptor(EncryptContext context) { + super(context); + String privateKey = context.getPrivateKey(); + String publicKey = context.getPublicKey(); + if (StringUtils.isAnyEmpty(privateKey, publicKey)) { + throw new IllegalArgumentException("SM2公私钥均需要提供,公钥加密,私钥解密。"); + } + this.sm2 = SmUtil.sm2(Base64.decode(privateKey), Base64.decode(publicKey)); + } + + /** + * 获得当前算法 + */ + @Override + public AlgorithmType algorithm() { + return AlgorithmType.SM2; + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + */ + @Override + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return sm2.encryptHex(value, KeyType.PublicKey); + } else { + return sm2.encryptBase64(value, KeyType.PublicKey); + } + } + + /** + * 解密 + * + * @param value 待加密字符串 + */ + @Override + public String decrypt(String value) { + return this.sm2.decryptStr(value, KeyType.PrivateKey); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java new file mode 100644 index 000000000..7d2e50974 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java @@ -0,0 +1,67 @@ +package com.ruoyi.common.encrypt.encryptor; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.symmetric.SM4; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; + +import java.nio.charset.StandardCharsets; + +/** + * sm4算法实现 + * + * @author 老马 + * @version 4.6.0 + */ +public class Sm4Encryptor extends AbstractEncryptor { + + private final SM4 sm4; + + public Sm4Encryptor(EncryptContext context) { + super(context); + String password = context.getPassword(); + if (StrUtil.isBlank(password)) { + throw new IllegalArgumentException("SM4没有获得秘钥信息"); + } + // sm4算法的秘钥要求是16位长度 + if (16 != password.length()) { + throw new IllegalArgumentException("SM4秘钥长度应该为16位,实际为" + password.length() + "位"); + } + this.sm4 = SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 获得当前算法 + */ + @Override + public AlgorithmType algorithm() { + return AlgorithmType.SM4; + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @param encodeType 加密后的编码格式 + */ + @Override + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return sm4.encryptHex(value); + } else { + return sm4.encryptBase64(value); + } + } + + /** + * 解密 + * + * @param value 待加密字符串 + */ + @Override + public String decrypt(String value) { + return this.sm4.decryptStr(value); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java new file mode 100644 index 000000000..124a139da --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.enums; + +import com.ruoyi.common.encrypt.encryptor.*; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 算法名称 + * + * @author 老马 + * @version 4.6.0 + */ +@Getter +@AllArgsConstructor +public enum AlgorithmType { + + /** + * 默认走yml配置 + */ + DEFAULT(null), + + /** + * base64 + */ + BASE64(Base64Encryptor.class), + + /** + * aes + */ + AES(AesEncryptor.class), + + /** + * rsa + */ + RSA(RsaEncryptor.class), + + /** + * sm2 + */ + SM2(Sm2Encryptor.class), + + /** + * sm4 + */ + SM4(Sm4Encryptor.class); + + private final Class clazz; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java new file mode 100644 index 000000000..4d469597c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.enums; + +/** + * 编码类型 + * + * @author 老马 + * @version 4.6.0 + */ +public enum EncodeType { + + /** + * 默认使用yml配置 + */ + DEFAULT, + + /** + * base64编码 + */ + BASE64, + + /** + * 16进制编码 + */ + HEX; + +} 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 5a0879472..72772c1b3 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 @@ -25,7 +25,7 @@ public class XssFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { String tempExcludes = filterConfig.getInitParameter("excludes"); if (StringUtils.isNotEmpty(tempExcludes)) { - String[] url = tempExcludes.split(","); + String[] url = tempExcludes.split(StringUtils.SEPARATOR); for (int i = 0; url != null && i < url.length; i++) { excludes.add(url[i]); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java index 0e60485ad..e2b1129f5 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java @@ -3,6 +3,8 @@ import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.context.model.SaStorage; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; +import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -44,4 +46,19 @@ public static Map getContext() { } throw new NullPointerException("data permission context type exception"); } + + /** + * 开启忽略数据权限(开启后需手动调用 {@link #disableIgnore()} 关闭) + */ + public static void enableIgnore() { + InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().dataPermission(true).build()); + } + + /** + * 关闭忽略数据权限 + */ + public static void disableIgnore() { + InterceptorIgnoreHelper.clearIgnoreStrategy(); + } + } 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 05e370b5d..3cbddb137 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 @@ -1,25 +1,25 @@ package com.ruoyi.common.helper; import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaStorage; +import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; -import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.DeviceType; import com.ruoyi.common.enums.UserType; -import com.ruoyi.common.exception.UtilException; -import com.ruoyi.common.utils.StringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; /** * 登录鉴权助手 - * + *

* user_type 为 用户类型 同一个用户表 可以有多种用户类型 例如 pc,app * deivce 为 设备类型 同一个用户类型 可以有 多种设备类型 例如 web,ios * 可以组成 用户类型与设备类型多对多的 权限灵活控制 - * + *

* 多用户体系 针对 多种用户类型 但权限控制不一致 * 可以组成 多用户类型表与多设备类型 分别控制权限 * @@ -28,8 +28,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class LoginHelper { - public static final String JOIN_CODE = ":"; public static final String LOGIN_USER_KEY = "loginUser"; + public static final String USER_KEY = "userId"; /** * 登录系统 @@ -37,9 +37,7 @@ public class LoginHelper { * @param loginUser 登录用户信息 */ public static void login(LoginUser loginUser) { - SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser); - StpUtil.login(loginUser.getLoginId()); - setLoginUser(loginUser); + loginByDevice(loginUser, null); } /** @@ -49,15 +47,14 @@ public static void login(LoginUser loginUser) { * @param loginUser 登录用户信息 */ public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) { - SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser); - StpUtil.login(loginUser.getLoginId(), deviceType.getDevice()); - setLoginUser(loginUser); - } - - /** - * 设置用户数据(多级缓存) - */ - public static void setLoginUser(LoginUser loginUser) { + SaStorage storage = SaHolder.getStorage(); + storage.set(LOGIN_USER_KEY, loginUser); + storage.set(USER_KEY, loginUser.getUserId()); + SaLoginModel model = new SaLoginModel(); + if (ObjectUtil.isNotNull(deviceType)) { + model.setDevice(deviceType.getDevice()); + } + StpUtil.login(loginUser.getLoginId(), model.setExtra(USER_KEY, loginUser.getUserId())); StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser); } @@ -74,27 +71,28 @@ public static LoginUser getLoginUser() { return loginUser; } + /** + * 获取用户基于token + */ + public static LoginUser getLoginUser(String token) { + return (LoginUser) StpUtil.getTokenSessionByToken(token).get(LOGIN_USER_KEY); + } + /** * 获取用户id */ public static Long getUserId() { - 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)) { - throw new UtilException("登录用户: LoginId异常 => " + loginId); + Long userId; + try { + userId = Convert.toLong(SaHolder.getStorage().get(USER_KEY)); + if (ObjectUtil.isNull(userId)) { + userId = Convert.toLong(StpUtil.getExtra(USER_KEY)); + SaHolder.getStorage().set(USER_KEY, userId); } - return Long.parseLong(userId); + } catch (Exception e) { + return null; } - return loginUser.getUserId(); + return userId; } /** 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 index caa059b92..5fbf0519c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java @@ -22,7 +22,9 @@ * 字典数据json序列化工具 * * @author itino + * @deprecated 建议使用通用翻译注解 */ +@Deprecated @Slf4j public class DictDataJsonSerializer extends JsonSerializer implements ContextualSerializer { diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/TranslationInterface.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/TranslationInterface.java new file mode 100644 index 000000000..91af97cae --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/TranslationInterface.java @@ -0,0 +1,17 @@ +package com.ruoyi.common.translation; + +/** + * 翻译接口 (实现类需标注 {@link com.ruoyi.common.annotation.TranslationType} 注解标明翻译类型) + * + * @author Lion Li + */ +public interface TranslationInterface { + + /** + * 翻译 + * + * @param key 需要被翻译的键(不为空) + * @return 返回键对应的值 + */ + T translation(Object key, String other); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationBeanSerializerModifier.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationBeanSerializerModifier.java new file mode 100644 index 000000000..0bcaf285e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationBeanSerializerModifier.java @@ -0,0 +1,29 @@ +package com.ruoyi.common.translation.handler; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; +import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; + +import java.util.List; + +/** + * Bean 序列化修改器 解决 Null 被单独处理问题 + * + * @author Lion Li + */ +public class TranslationBeanSerializerModifier extends BeanSerializerModifier { + + @Override + public List changeProperties(SerializationConfig config, BeanDescription beanDesc, + List beanProperties) { + for (BeanPropertyWriter writer : beanProperties) { + // 如果序列化器为 TranslationHandler 的话 将 Null 值也交给他处理 + if (writer.getSerializer() instanceof TranslationHandler) { + writer.assignNullSerializer(writer.getSerializer()); + } + } + return beanProperties; + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationHandler.java new file mode 100644 index 000000000..ede720675 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationHandler.java @@ -0,0 +1,65 @@ +package com.ruoyi.common.translation.handler; + +import cn.hutool.core.util.ObjectUtil; +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.Translation; +import com.ruoyi.common.translation.TranslationInterface; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 翻译处理器 + * + * @author Lion Li + */ +@Slf4j +public class TranslationHandler extends JsonSerializer implements ContextualSerializer { + + /** + * 全局翻译实现类映射器 + */ + public static final Map> TRANSLATION_MAPPER = new ConcurrentHashMap<>(); + + private Translation translation; + + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + TranslationInterface trans = TRANSLATION_MAPPER.get(translation.type()); + if (ObjectUtil.isNotNull(trans)) { + // 如果映射字段不为空 则取映射字段的值 + if (StringUtils.isNotBlank(translation.mapper())) { + value = ReflectUtils.invokeGetter(gen.getCurrentValue(), translation.mapper()); + } + // 如果为 null 直接写出 + if (ObjectUtil.isNull(value)) { + gen.writeNull(); + return; + } + Object result = trans.translation(value, translation.other()); + gen.writeObject(result); + } else { + gen.writeObject(value); + } + } + + @Override + public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { + Translation translation = property.getAnnotation(Translation.class); + if (Objects.nonNull(translation)) { + this.translation = translation; + return this; + } + return prov.findValueSerializer(property.getType(), property); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DeptNameTranslationImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DeptNameTranslationImpl.java new file mode 100644 index 000000000..69196171b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DeptNameTranslationImpl.java @@ -0,0 +1,25 @@ +package com.ruoyi.common.translation.impl; + +import com.ruoyi.common.annotation.TranslationType; +import com.ruoyi.common.constant.TransConstant; +import com.ruoyi.common.core.service.DeptService; +import com.ruoyi.common.translation.TranslationInterface; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 部门翻译实现 + * + * @author Lion Li + */ +@Component +@AllArgsConstructor +@TranslationType(type = TransConstant.DEPT_ID_TO_NAME) +public class DeptNameTranslationImpl implements TranslationInterface { + + private final DeptService deptService; + + public String translation(Object key, String other) { + return deptService.selectDeptNameByIds(key.toString()); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DictTypeTranslationImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DictTypeTranslationImpl.java new file mode 100644 index 000000000..210312c82 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DictTypeTranslationImpl.java @@ -0,0 +1,29 @@ +package com.ruoyi.common.translation.impl; + +import com.ruoyi.common.annotation.TranslationType; +import com.ruoyi.common.constant.TransConstant; +import com.ruoyi.common.core.service.DictService; +import com.ruoyi.common.translation.TranslationInterface; +import com.ruoyi.common.utils.StringUtils; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 字典翻译实现 + * + * @author Lion Li + */ +@Component +@AllArgsConstructor +@TranslationType(type = TransConstant.DICT_TYPE_TO_LABEL) +public class DictTypeTranslationImpl implements TranslationInterface { + + private final DictService dictService; + + public String translation(Object key, String other) { + if (key instanceof String && StringUtils.isNotBlank(other)) { + return dictService.getDictLabel(other, key.toString()); + } + return null; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/OssUrlTranslationImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/OssUrlTranslationImpl.java new file mode 100644 index 000000000..69ebd9afe --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/OssUrlTranslationImpl.java @@ -0,0 +1,25 @@ +package com.ruoyi.common.translation.impl; + +import com.ruoyi.common.annotation.TranslationType; +import com.ruoyi.common.constant.TransConstant; +import com.ruoyi.common.core.service.OssService; +import com.ruoyi.common.translation.TranslationInterface; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * OSS翻译实现 + * + * @author Lion Li + */ +@Component +@AllArgsConstructor +@TranslationType(type = TransConstant.OSS_ID_TO_URL) +public class OssUrlTranslationImpl implements TranslationInterface { + + private final OssService ossService; + + public String translation(Object key, String other) { + return ossService.selectUrlByIds(key.toString()); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/UserNameTranslationImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/UserNameTranslationImpl.java new file mode 100644 index 000000000..36fd6c399 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/UserNameTranslationImpl.java @@ -0,0 +1,28 @@ +package com.ruoyi.common.translation.impl; + +import com.ruoyi.common.annotation.TranslationType; +import com.ruoyi.common.constant.TransConstant; +import com.ruoyi.common.core.service.UserService; +import com.ruoyi.common.translation.TranslationInterface; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 用户名翻译实现 + * + * @author Lion Li + */ +@Component +@AllArgsConstructor +@TranslationType(type = TransConstant.USER_ID_TO_NAME) +public class UserNameTranslationImpl implements TranslationInterface { + + private final UserService userService; + + public String translation(Object key, String other) { + if (key instanceof Long) { + return userService.selectUserNameById((Long) key); + } + return null; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java index 88161daac..e1bafee22 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java @@ -12,6 +12,7 @@ import org.springframework.cglib.beans.BeanMap; import org.springframework.cglib.core.Converter; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -135,6 +136,25 @@ public static T mapToBean(Map map, T bean) { return bean; } + /** + * map拷贝到map + * + * @param map 数据来源 + * @param clazz 返回的对象类型 + * @return map对象 + */ + public static Map mapToMap(Map map, Class clazz) { + if (MapUtil.isEmpty(map)) { + return null; + } + if (ObjectUtil.isNull(clazz)) { + return null; + } + Map copyMap = new LinkedHashMap<>(map.size()); + map.forEach((k, v) -> copyMap.put(k, copy(v, clazz))); + return copyMap; + } + /** * BeanCopier属性缓存
* 缓存用于防止多次反射造成的性能问题 @@ -174,7 +194,7 @@ public BeanCopier get(Class srcClass, Class targetClass, Converter convert private String genKey(Class srcClass, Class targetClass, Converter converter) { final StringBuilder key = StrUtil.builder() .append(srcClass.getName()).append('#').append(targetClass.getName()); - if(null != converter){ + if (null != converter) { key.append('#').append(converter.getClass().getName()); } return key.toString(); 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 91ddd3f66..288a1a1a2 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 @@ -94,7 +94,7 @@ public static Map getParams(ServletRequest request) { 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(), ",")); + params.put(entry.getKey(), StringUtils.join(entry.getValue(), StringUtils.SEPARATOR)); } return params; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java index fccd9e3d1..a03e5bee4 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java @@ -41,7 +41,7 @@ public static List filter(Collection collection, Predicate function * @return 拼接后的list */ public static String join(Collection collection, Function function) { - return join(collection, function, ","); + return join(collection, function, StringUtils.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 16f8861c1..2a5bd488b 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 @@ -1,16 +1,16 @@ package com.ruoyi.common.utils; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.util.AntPathMatcher; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 字符串工具类 @@ -20,6 +20,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class StringUtils extends org.apache.commons.lang3.StringUtils { + public static final String SEPARATOR = ","; + /** * 获取参数不为空值 * @@ -224,7 +226,6 @@ public static boolean matches(String str, List strs) { * * @param pattern 匹配规则 * @param url 需要匹配的url - * @return */ public static boolean isMatch(String pattern, String url) { AntPathMatcher matcher = new AntPathMatcher(); @@ -234,23 +235,23 @@ public static boolean isMatch(String pattern, String url) { /** * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 * - * @param num 数字对象 + * @param num 数字对象 * @param size 字符串指定长度 * @return 返回数字的字符串格式,该字符串为指定长度。 */ - public static final String padl(final Number num, final int size) { + public static String padl(final Number num, final int size) { return padl(num.toString(), size, '0'); } /** * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 * - * @param s 原始字符串 + * @param s 原始字符串 * @param size 字符串指定长度 - * @param c 用于补齐的字符 + * @param c 用于补齐的字符 * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 */ - public static final String padl(final String s, final int size, final char c) { + public static String padl(final String s, final int size, final char c) { final StringBuilder sb = new StringBuilder(size); if (s != null) { final int len = s.length(); @@ -270,4 +271,55 @@ public static final String padl(final String s, final int size, final char c) { return sb.toString(); } + /** + * 切分字符串(分隔符默认逗号) + * + * @param str 被切分的字符串 + * @return 分割后的数据列表 + */ + public static List splitList(String str) { + return splitTo(str, Convert::toStr); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符 + * @return 分割后的数据列表 + */ + public static List splitList(String str, String separator) { + return splitTo(str, separator, Convert::toStr); + } + + /** + * 切分字符串自定义转换(分隔符默认逗号) + * + * @param str 被切分的字符串 + * @param mapper 自定义转换 + * @return 分割后的数据列表 + */ + public static List splitTo(String str, Function mapper) { + return splitTo(str, SEPARATOR, mapper); + } + + /** + * 切分字符串自定义转换 + * + * @param str 被切分的字符串 + * @param separator 分隔符 + * @param mapper 自定义转换 + * @return 分割后的数据列表 + */ + public static List splitTo(String str, String separator, Function mapper) { + if (isBlank(str)) { + return new ArrayList<>(0); + } + return StrUtil.split(str, separator) + .stream() + .filter(Objects::nonNull) + .map(mapper) + .collect(Collectors.toList()); + } + } 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 211c6214c..cf2ba885c 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 @@ -270,7 +270,7 @@ private static void resetResponse(String sheetName, HttpServletResponse response */ public static String convertByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); + String[] convertSource = converterExp.split(StringUtils.SEPARATOR); for (String item : convertSource) { String[] itemArray = item.split("="); if (StringUtils.containsAny(propertyValue, separator)) { @@ -299,7 +299,7 @@ public static String convertByExp(String propertyValue, String converterExp, Str */ public static String reverseByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); + String[] convertSource = converterExp.split(StringUtils.SEPARATOR); for (String item : convertSource) { String[] itemArray = item.split("="); if (StringUtils.containsAny(propertyValue, separator)) { diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index 31f712cbc..b64625d34 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java new file mode 100644 index 000000000..6abe4e184 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java @@ -0,0 +1,55 @@ +package com.ruoyi.demo.controller; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.demo.domain.TestDemoEncrypt; +import com.ruoyi.demo.mapper.TestDemoEncryptMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + + +/** + * 测试数据库加解密功能 + * + * @author Lion Li + */ +@Validated +@RestController +@RequestMapping("/demo/encrypt") +public class TestEncryptController { + + @Autowired + private TestDemoEncryptMapper mapper; + @Value("${mybatis-encryptor.enable}") + private Boolean encryptEnable; + + /** + * 测试数据库加解密 + * + * @param key 测试key + * @param value 测试value + */ + @GetMapping() + public R> test(String key, String value) { + if (!encryptEnable) { + throw new RuntimeException("加密功能未开启!"); + } + Map map = new HashMap<>(2); + TestDemoEncrypt demo = new TestDemoEncrypt(); + demo.setTestKey(key); + demo.setValue(value); + mapper.insert(demo); + map.put("加密", demo); + TestDemoEncrypt testDemo = mapper.selectById(demo.getId()); + map.put("解密", testDemo); + return R.ok(map); + } + + +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java new file mode 100644 index 000000000..4672185c7 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java @@ -0,0 +1,29 @@ +package com.ruoyi.demo.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.enums.AlgorithmType; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("test_demo") +public class TestDemoEncrypt extends TestDemo { + + /** + * key键 + */ + // @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==") + @EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB") + private String testKey; + + /** + * 值 + */ + // @EncryptField // 什么也不写走默认yml配置 + // @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5") + @EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5") + private String value; + +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java new file mode 100644 index 000000000..5c76097df --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java @@ -0,0 +1,13 @@ +package com.ruoyi.demo.mapper; + +import com.ruoyi.common.core.mapper.BaseMapperPlus; +import com.ruoyi.demo.domain.TestDemoEncrypt; + +/** + * 测试加密功能 + * + * @author Lion Li + */ +public interface TestDemoEncryptMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml index a55645806..512368cd9 100644 --- a/ruoyi-extend/pom.xml +++ b/ruoyi-extend/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 ruoyi-extend diff --git a/ruoyi-extend/ruoyi-monitor-admin/pom.xml b/ruoyi-extend/ruoyi-monitor-admin/pom.xml index 19fc04e20..8cb17a887 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/pom.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-extend com.ruoyi - 4.5.0 + 4.6.0 4.0.0 jar diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml index 7e65df583..8e4f135db 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml @@ -4,7 +4,7 @@ ruoyi-extend com.ruoyi - 4.5.0 + 4.6.0 ruoyi-xxl-job-admin jar diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 072b5b2f2..665a16e0c 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 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 64ab736a6..00918327b 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 @@ -112,7 +112,7 @@ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLog // 是否需要保存request,参数和值 if (log.isSaveRequestData()) { // 获取参数的信息,传入到数据库中。 - setRequestValue(joinPoint, operLog); + setRequestValue(joinPoint, operLog, log.excludeParamNames()); } // 是否需要保存response,参数和值 if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { @@ -126,14 +126,16 @@ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLog * @param operLog 操作日志 * @throws Exception 异常 */ - private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception { + private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog, String[] excludeParamNames) throws Exception { + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); String requestMethod = operLog.getRequestMethod(); - if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { - String params = argsArrayToString(joinPoint.getArgs()); + if (MapUtil.isEmpty(paramsMap) + && HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); operLog.setOperParam(StringUtils.substring(params, 0, 2000)); } else { - Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES); + MapUtil.removeAny(paramsMap, excludeParamNames); operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000)); } } @@ -141,7 +143,7 @@ private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws E /** * 参数拼装 */ - private String argsArrayToString(Object[] paramsArray) { + private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) { StringBuilder params = new StringBuilder(); if (paramsArray != null && paramsArray.length > 0) { for (Object o : paramsArray) { @@ -151,6 +153,7 @@ private String argsArrayToString(Object[] paramsArray) { Dict dict = JsonUtils.parseMap(str); if (MapUtil.isNotEmpty(dict)) { MapUtil.removeAny(dict, EXCLUDE_PROPERTIES); + MapUtil.removeAny(dict, excludeParamNames); str = JsonUtils.toJsonString(dict); } params.append(str).append(" "); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java index 542b16bfd..d558a4ce7 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -1,10 +1,13 @@ package com.ruoyi.framework.aspectj; +import cn.hutool.core.util.ArrayUtil; import com.ruoyi.common.annotation.RateLimiter; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.enums.LimitType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; @@ -12,6 +15,14 @@ import org.aspectj.lang.annotation.Before; import org.aspectj.lang.reflect.MethodSignature; import org.redisson.api.RateType; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParserContext; +import org.springframework.expression.common.TemplateParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @@ -26,6 +37,23 @@ @Component public class RateLimiterAspect { + /** + * 定义spel表达式解析器 + */ + private final ExpressionParser parser = new SpelExpressionParser(); + /** + * 定义spel解析模版 + */ + private final ParserContext parserContext = new TemplateParserContext(); + /** + * 定义spel上下文对象进行解析 + */ + private final EvaluationContext context = new StandardEvaluationContext(); + /** + * 方法参数解析器 + */ + private final ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer(); + @Before("@annotation(rateLimiter)") public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable { int time = rateLimiter.time(); @@ -38,29 +66,56 @@ public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable } long number = RedisUtils.rateLimiter(combineKey, rateType, count, time); if (number == -1) { - throw new ServiceException(MessageUtils.message("rate.limiter.message")); + String message = rateLimiter.message(); + if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { + message = MessageUtils.message(StringUtils.substring(message, 1, message.length() - 1)); + } + throw new ServiceException(message); } log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存key => '{}'", count, number, combineKey); - } catch (ServiceException e) { - throw e; } catch (Exception e) { - throw new RuntimeException("服务器限流异常,请稍候再试"); + if (e instanceof ServiceException) { + throw e; + } else { + throw new RuntimeException("服务器限流异常,请稍候再试"); + } } } public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) { - StringBuilder stringBuffer = new StringBuilder(rateLimiter.key()); + String key = rateLimiter.key(); + // 获取方法(通过方法签名来获取) + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + Class targetClass = method.getDeclaringClass(); + // 判断是否是spel格式 + if (StringUtils.containsAny(key, "#")) { + // 获取参数值 + Object[] args = point.getArgs(); + // 获取方法上参数的名称 + String[] parameterNames = pnd.getParameterNames(method); + if (ArrayUtil.isEmpty(parameterNames)) { + throw new ServiceException("限流key解析异常!请联系管理员!"); + } + for (int i = 0; i < parameterNames.length; i++) { + context.setVariable(parameterNames[i], args[i]); + } + // 解析返回给key + try { + key = parser.parseExpression(key, parserContext).getValue(context, String.class) + ":"; + } catch (Exception e) { + throw new ServiceException("限流key解析异常!请联系管理员!"); + } + } + StringBuilder stringBuffer = new StringBuilder(CacheConstants.RATE_LIMIT_KEY); + stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(":"); if (rateLimiter.limitType() == LimitType.IP) { // 获取请求ip - stringBuffer.append(ServletUtils.getClientIP()).append("-"); + stringBuffer.append(ServletUtils.getClientIP()).append(":"); } else if (rateLimiter.limitType() == LimitType.CLUSTER) { // 获取客户端实例id - stringBuffer.append(RedisUtils.getClient().getId()).append("-"); + stringBuffer.append(RedisUtils.getClient().getId()).append(":"); } - MethodSignature signature = (MethodSignature) point.getSignature(); - Method method = signature.getMethod(); - Class targetClass = method.getDeclaringClass(); - stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); - return stringBuffer.toString(); + return stringBuffer.append(key).toString(); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java new file mode 100644 index 000000000..ed90d2067 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java @@ -0,0 +1,39 @@ +package com.ruoyi.framework.config; + +import com.ruoyi.framework.config.properties.EncryptorProperties; +import com.ruoyi.framework.manager.EncryptorManager; +import com.ruoyi.framework.encrypt.MybatisDecryptInterceptor; +import com.ruoyi.framework.encrypt.MybatisEncryptInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 加解密配置 + * + * @author 老马 + * @version 4.6.0 + */ +@Configuration +@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true") +public class EncryptorConfig { + + @Autowired + private EncryptorProperties properties; + + @Bean + public EncryptorManager encryptorManager() { + return new EncryptorManager(); + } + + @Bean + public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) { + return new MybatisEncryptInterceptor(encryptorManager, properties); + } + + @Bean + public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) { + return new MybatisDecryptInterceptor(encryptorManager, properties); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java index 6f3b099ab..0770c2162 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java @@ -32,7 +32,7 @@ public FilterRegistrationBean xssFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new XssFilter()); - registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), ",")); + registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), StringUtils.SEPARATOR)); registration.setName("xssFilter"); registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); Map initParameters = new HashMap(); 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 291228667..b45eace4b 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 @@ -1,11 +1,17 @@ package com.ruoyi.framework.config; +import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.jwt.StpLogicJwtForSimple; import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.stp.StpInterface; 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.SecurityProperties; +import com.ruoyi.framework.handler.AllUrlHandler; +import com.ruoyi.framework.satoken.dao.PlusSaTokenDao; +import com.ruoyi.framework.satoken.service.SaPermissionImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; @@ -32,10 +38,11 @@ public class SaTokenConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { // 注册路由拦截器,自定义验证规则 registry.addInterceptor(new SaInterceptor(handler -> { + AllUrlHandler allUrlHandler = SpringUtils.getBean(AllUrlHandler.class); // 登录验证 -- 排除多个路径 SaRouter // 获取所有的 - .match("/**") + .match(allUrlHandler.getUrls()) // 对未排除的路径进行检查 .check(() -> { // 检查是否登录 是否有token @@ -59,4 +66,20 @@ public StpLogic getStpLogicJwt() { return new StpLogicJwtForSimple(); } + /** + * 权限接口实现(使用bean注入方便用户替换) + */ + @Bean + public StpInterface stpInterface() { + return new SaPermissionImpl(); + } + + /** + * 自定义dao层存储 + */ + @Bean + public SaTokenDao saTokenDao() { + return new PlusSaTokenDao(); + } + } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java index ab92cf591..88af7e725 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java @@ -33,7 +33,7 @@ @RequiredArgsConstructor @Configuration @AutoConfigureBefore(SpringDocConfiguration.class) -@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true) public class SwaggerConfig { private final SwaggerProperties swaggerProperties; diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TranslationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TranslationConfig.java new file mode 100644 index 000000000..c68bf6073 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TranslationConfig.java @@ -0,0 +1,50 @@ +package com.ruoyi.framework.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ruoyi.common.annotation.TranslationType; +import com.ruoyi.common.translation.TranslationInterface; +import com.ruoyi.common.translation.handler.TranslationBeanSerializerModifier; +import com.ruoyi.common.translation.handler.TranslationHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 翻译模块配置类 + * + * @author Lion Li + */ +@Slf4j +@Configuration +public class TranslationConfig { + + @Autowired + private List> list; + + @Autowired + private ObjectMapper objectMapper; + + @PostConstruct + public void init() { + Map> map = new HashMap<>(list.size()); + for (TranslationInterface trans : list) { + if (trans.getClass().isAnnotationPresent(TranslationType.class)) { + TranslationType annotation = trans.getClass().getAnnotation(TranslationType.class); + map.put(annotation.type(), trans); + } else { + log.warn(trans.getClass().getName() + " 翻译实现类未标注 TranslationType 注解!"); + } + } + TranslationHandler.TRANSLATION_MAPPER.putAll(map); + // 设置 Bean 序列化修改器 + objectMapper.setSerializerFactory( + objectMapper.getSerializerFactory() + .withSerializerModifier(new TranslationBeanSerializerModifier())); + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java new file mode 100644 index 000000000..8b2000d6a --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java @@ -0,0 +1,50 @@ +package com.ruoyi.framework.config.properties; + +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 加解密属性配置类 + * + * @author 老马 + * @version 4.6.0 + */ +@Data +@Component +@ConfigurationProperties(prefix = "mybatis-encryptor") +public class EncryptorProperties { + + /** + * 过滤开关 + */ + private Boolean enable; + + /** + * 默认算法 + */ + private AlgorithmType algorithm; + + /** + * 安全秘钥 + */ + private String password; + + /** + * 公钥 + */ + private String publicKey; + + /** + * 私钥 + */ + private String privateKey; + + /** + * 编码方式,base64/hex + */ + private EncodeType encode; + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java index 736d70a45..ac6fc4249 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java @@ -23,11 +23,6 @@ @ConfigurationProperties(prefix = "swagger") public class SwaggerProperties { - /** - * 是否开启 openApi 文档 - */ - private Boolean enabled = true; - /** * 文档基本信息 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java new file mode 100644 index 000000000..8755e7d46 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java @@ -0,0 +1,113 @@ +package com.ruoyi.framework.encrypt; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptorProperties; +import com.ruoyi.framework.manager.EncryptorManager; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.executor.resultset.ResultSetHandler; +import org.apache.ibatis.plugin.*; + +import java.lang.reflect.Field; +import java.sql.Statement; +import java.util.*; + +/** + * 出参解密拦截器 + * + * @author 老马 + * @version 4.6.0 + */ +@Slf4j +@Intercepts({@Signature( + type = ResultSetHandler.class, + method = "handleResultSets", + args = {Statement.class}) +}) +@AllArgsConstructor +public class MybatisDecryptInterceptor implements Interceptor { + + private final EncryptorManager encryptorManager; + private final EncryptorProperties defaultProperties; + + @Override + public Object intercept(Invocation invocation) throws Throwable { + // 获取执行mysql执行结果 + Object result = invocation.proceed(); + if (result == null) { + return null; + } + decryptHandler(result); + return result; + } + + /** + * 解密对象 + * + * @param sourceObject 待加密对象 + */ + private void decryptHandler(Object sourceObject) { + if (ObjectUtil.isNull(sourceObject)) { + return; + } + if (sourceObject instanceof Map) { + new HashSet<>(((Map) sourceObject).values()).forEach(this::decryptHandler); + return; + } + if (sourceObject instanceof List) { + List sourceList = (List) sourceObject; + if(CollectionUtil.isEmpty(sourceList)) { + return; + } + // 判断第一个元素是否含有注解。如果没有直接返回,提高效率 + Object firstItem = sourceList.get(0); + if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { + return; + } + ((List) sourceObject).forEach(this::decryptHandler); + return; + } + Set fields = encryptorManager.getFieldCache(sourceObject.getClass()); + try { + for (Field field : fields) { + field.set(sourceObject, this.decryptField(String.valueOf(field.get(sourceObject)), field)); + } + } catch (Exception e) { + log.error("处理解密字段时出错", e); + } + } + + /** + * 字段值进行加密。通过字段的批注注册新的加密算法 + * + * @param value 待加密的值 + * @param field 待加密字段 + * @return 加密后结果 + */ + private String decryptField(String value, Field field) { + EncryptField encryptField = field.getAnnotation(EncryptField.class); + EncryptContext encryptContext = new EncryptContext(); + encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); + encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); + encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); + encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); + encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); + return this.encryptorManager.decrypt(value, encryptContext); + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + @Override + public void setProperties(Properties properties) { + + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java new file mode 100644 index 000000000..e2ce1957b --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java @@ -0,0 +1,118 @@ +package com.ruoyi.framework.encrypt; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptorProperties; +import com.ruoyi.framework.manager.EncryptorManager; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.executor.parameter.ParameterHandler; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Signature; + +import java.lang.reflect.Field; +import java.sql.PreparedStatement; +import java.util.*; + +/** + * 入参加密拦截器 + * + * @author 老马 + * @version 4.6.0 + */ +@Slf4j +@Intercepts({@Signature( + type = ParameterHandler.class, + method = "setParameters", + args = {PreparedStatement.class}) +}) +@AllArgsConstructor +public class MybatisEncryptInterceptor implements Interceptor { + + private final EncryptorManager encryptorManager; + private final EncryptorProperties defaultProperties; + + @Override + public Object intercept(Invocation invocation) throws Throwable { + return invocation; + } + + @Override + public Object plugin(Object target) { + if (target instanceof ParameterHandler) { + // 进行加密操作 + ParameterHandler parameterHandler = (ParameterHandler) target; + Object parameterObject = parameterHandler.getParameterObject(); + if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) { + this.encryptHandler(parameterObject); + } + } + return target; + } + + /** + * 加密对象 + * + * @param sourceObject 待加密对象 + */ + private void encryptHandler(Object sourceObject) { + if (ObjectUtil.isNull(sourceObject)) { + return; + } + if (sourceObject instanceof Map) { + new HashSet<>(((Map) sourceObject).values()).forEach(this::encryptHandler); + return; + } + if (sourceObject instanceof List) { + List sourceList = (List) sourceObject; + if(CollectionUtil.isEmpty(sourceList)) { + return; + } + // 判断第一个元素是否含有注解。如果没有直接返回,提高效率 + Object firstItem = sourceList.get(0); + if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { + return; + } + ((List) sourceObject).forEach(this::encryptHandler); + return; + } + Set fields = encryptorManager.getFieldCache(sourceObject.getClass()); + try { + for (Field field : fields) { + field.set(sourceObject, this.encryptField(String.valueOf(field.get(sourceObject)), field)); + } + } catch (Exception e) { + log.error("处理加密字段时出错", e); + } + } + + /** + * 字段值进行加密。通过字段的批注注册新的加密算法 + * + * @param value 待加密的值 + * @param field 待加密字段 + * @return 加密后结果 + */ + private String encryptField(String value, Field field) { + EncryptField encryptField = field.getAnnotation(EncryptField.class); + EncryptContext encryptContext = new EncryptContext(); + encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); + encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); + encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); + encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); + encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); + return this.encryptorManager.encrypt(value, encryptContext); + } + + + @Override + public void setProperties(Properties properties) { + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/AllUrlHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/AllUrlHandler.java new file mode 100644 index 000000000..76e5ffdd4 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/AllUrlHandler.java @@ -0,0 +1,41 @@ +package com.ruoyi.framework.handler; + +import cn.hutool.core.util.ReUtil; +import com.ruoyi.common.utils.spring.SpringUtils; +import lombok.Data; +import org.springframework.beans.factory.InitializingBean; +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 java.util.*; +import java.util.regex.Pattern; + +/** + * 获取所有Url配置 + * + * @author Lion Li + */ +@Data +@Component +public class AllUrlHandler implements InitializingBean { + + private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); + + private List urls = new ArrayList<>(); + + @Override + public void afterPropertiesSet() { + Set set = new HashSet<>(); + RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); + Map map = mapping.getHandlerMethods(); + map.keySet().forEach(info -> { + // 获取注解上边的 path 替代 path variable 为 * + Objects.requireNonNull(info.getPathPatternsCondition().getPatterns()) + .forEach(url -> set.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, "*"))); + }); + urls.addAll(set); + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java new file mode 100644 index 000000000..94515aab4 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java @@ -0,0 +1,96 @@ +package com.ruoyi.framework.manager; + +import cn.hutool.core.util.ReflectUtil; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.encrypt.IEncryptor; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 加密管理类 + * + * @author 老马 + * @version 4.6.0 + */ +@Slf4j +public class EncryptorManager { + + /** + * 缓存加密器 + */ + Map encryptorMap = new ConcurrentHashMap<>(); + + /** + * 类加密字段缓存 + */ + Map, Set> fieldCache = new ConcurrentHashMap<>(); + + /** + * 获取类加密字段缓存 + */ + public Set getFieldCache(Class sourceClazz) { + return fieldCache.computeIfAbsent(sourceClazz, clazz -> { + Field[] declaredFields = clazz.getDeclaredFields(); + Set fieldSet = Arrays.stream(declaredFields).filter(field -> + field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class) + .collect(Collectors.toSet()); + for (Field field : fieldSet) { + field.setAccessible(true); + } + return fieldSet; + }); + } + + /** + * 注册加密执行者到缓存 + * + * @param encryptContext 加密执行者需要的相关配置参数 + */ + public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) { + if (encryptorMap.containsKey(encryptContext)) { + return encryptorMap.get(encryptContext); + } + IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext); + encryptorMap.put(encryptContext, encryptor); + return encryptor; + } + + /** + * 移除缓存中的加密执行者 + * + * @param encryptContext 加密执行者需要的相关配置参数 + */ + public void removeEncryptor(EncryptContext encryptContext) { + this.encryptorMap.remove(encryptContext); + } + + /** + * 根据配置进行加密。会进行本地缓存对应的算法和对应的秘钥信息。 + * + * @param value 待加密的值 + * @param encryptContext 加密相关的配置信息 + */ + public String encrypt(String value, EncryptContext encryptContext) { + IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); + return encryptor.encrypt(value, encryptContext.getEncode()); + } + + /** + * 根据配置进行解密 + * + * @param value 待解密的值 + * @param encryptContext 加密相关的配置信息 + */ + public String decrypt(String value, EncryptContext encryptContext) { + IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); + return encryptor.decrypt(value); + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java index 83c3d5455..2e4e89025 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java @@ -3,7 +3,6 @@ import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.util.SaFoxUtil; import com.ruoyi.common.utils.redis.RedisUtils; -import org.springframework.stereotype.Component; import java.time.Duration; import java.util.ArrayList; @@ -15,7 +14,6 @@ * * @author Lion Li */ -@Component public class PlusSaTokenDao implements SaTokenDao { /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java index 057d18336..632cc7168 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java @@ -4,7 +4,6 @@ import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.UserType; import com.ruoyi.common.helper.LoginHelper; -import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @@ -14,7 +13,6 @@ * * @author Lion Li */ -@Component public class SaPermissionImpl implements StpInterface { /** diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml index 529048eed..edbd25528 100644 --- a/ruoyi-generator/pom.xml +++ b/ruoyi-generator/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java index 280204b55..f6dbcaaf4 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -212,7 +212,7 @@ public String readConverterExp() { if (StringUtils.isNotEmpty(value)) { Object startStr = value.subSequence(0, 1); String endStr = value.substring(1); - sb.append("").append(startStr).append("=").append(endStr).append(","); + sb.append(StringUtils.EMPTY).append(startStr).append("=").append(endStr).append(StringUtils.SEPARATOR); } } return sb.deleteCharAt(sb.length() - 1).toString(); diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java index b6c2248e6..f04beb983 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -58,7 +58,7 @@ public static void initColumnField(GenTableColumn column, GenTable table) { column.setHtmlType(GenConstants.HTML_INPUT); // 如果是浮点型 统一用BigDecimal - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); + String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), StringUtils.SEPARATOR); if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { column.setJavaType(GenConstants.TYPE_BIGDECIMAL); } @@ -167,7 +167,7 @@ public static String convertClassName(String tableName) { boolean autoRemovePre = GenConfig.getAutoRemovePre(); String tablePrefix = GenConfig.getTablePrefix(); if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) { - String[] searchList = StringUtils.split(tablePrefix, ","); + String[] searchList = StringUtils.split(tablePrefix, StringUtils.SEPARATOR); tableName = replaceFirst(tableName, searchList); } return StringUtils.convertToCamelCase(tableName); @@ -184,7 +184,7 @@ public static String replaceFirst(String replacementm, String[] searchList) { String text = replacementm; for (String searchString : searchList) { if (replacementm.startsWith(searchString)) { - text = replacementm.replaceFirst(searchString, ""); + text = replacementm.replaceFirst(searchString, StringUtils.EMPTY); break; } } diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java index d8eeb6dd7..2277e2c38 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -232,7 +232,7 @@ public static String getPackagePrefix(String packageName) { public static HashSet getImportList(GenTable genTable) { List columns = genTable.getColumns(); GenTable subGenTable = genTable.getSubTable(); - HashSet importList = new HashSet(); + HashSet importList = new HashSet<>(); if (ObjectUtil.isNotNull(subGenTable)) { importList.add("java.util.List"); } diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml index fc44d8cbc..e81203ef9 100644 --- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml @@ -93,6 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ORDER BY c.relname, a.attnum ) temp WHERE table_name = (#{tableName}) + AND column_type ]]> '-' SELECT diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index 2bc699a20..fd07e4d72 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -51,11 +51,12 @@ #end diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index e645b6bb8..7e41538e7 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -51,11 +51,12 @@ #end 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 663893a2c..4f109531b 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 @@ -50,11 +50,12 @@ #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 a93922ef5..705394050 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 @@ -50,11 +50,11 @@ #end @@ -540,7 +540,7 @@ function submitForm() { /** 删除按钮操作 */ function handleDelete(row) { const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value; - proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { + proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() { loading.value = true; return del${BusinessName}(_${pkColumn.javaField}s); }).then(() => { diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml index 1146c9254..364dfa9f3 100644 --- a/ruoyi-job/pom.xml +++ b/ruoyi-job/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 jar diff --git a/ruoyi-oss/pom.xml b/ruoyi-oss/pom.xml index d25f2b8df..c2e1e996c 100644 --- a/ruoyi-oss/pom.xml +++ b/ruoyi-oss/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 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 fe409ce7d..a82853e9c 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 @@ -183,6 +183,12 @@ public String getConfigKey() { return configKey; } + /** + * 获取私有URL链接 + * + * @param objectKey 对象KEY + * @param second 授权时间 + */ public String getPrivateUrl(String objectKey, Integer second) { GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey) @@ -192,6 +198,13 @@ public String getPrivateUrl(String objectKey, Integer second) { return url.toString(); } + /** + * 检查配置是否相同 + */ + public boolean checkPropertiesSame(OssProperties properties) { + return this.properties.equals(properties); + } + /** * 获取当前桶权限类型 * diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java index c3312d730..78b53529f 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java @@ -24,21 +24,6 @@ public class OssFactory { private static final Map CLIENT_CACHE = new ConcurrentHashMap<>(); - /** - * 初始化工厂 - */ - public static void init() { - log.info("初始化OSS工厂"); - RedisUtils.subscribe(OssConstant.DEFAULT_CONFIG_KEY, String.class, configKey -> { - OssClient client = getClient(configKey); - // 未初始化不处理 - if (client != null) { - refresh(configKey); - log.info("订阅刷新OSS配置 => " + configKey); - } - }); - } - /** * 获取默认实例 */ @@ -55,25 +40,24 @@ public static OssClient instance() { * 根据类型获取实例 */ public static OssClient instance(String configKey) { - OssClient client = getClient(configKey); - if (client == null) { - refresh(configKey); - return getClient(configKey); - } - return client; - } - - private static void refresh(String configKey) { String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey); if (json == null) { throw new OssException("系统异常, '" + configKey + "'配置信息不存在!"); } OssProperties properties = JsonUtils.parseObject(json, OssProperties.class); - CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); - } - - private static OssClient getClient(String configKey) { - return CLIENT_CACHE.get(configKey); + OssClient client = CLIENT_CACHE.get(configKey); + if (client == null) { + CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); + log.info("创建OSS实例 key => {}", configKey); + return CLIENT_CACHE.get(configKey); + } + // 配置不相同则重新构建 + if (!client.checkPropertiesSame(properties)) { + CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); + log.info("重载OSS实例 key => {}", configKey); + return CLIENT_CACHE.get(configKey); + } + return client; } } diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml index 7180b058a..387139dff 100644 --- a/ruoyi-sms/pom.xml +++ b/ruoyi-sms/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java index 17f5b5b16..69ec7f1ec 100644 --- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java @@ -53,7 +53,7 @@ public SmsResult send(String phones, String templateId, Map para throw new SmsException("模板ID不能为空"); } SendSmsRequest req = new SendSmsRequest(); - Set set = Arrays.stream(phones.split(",")).map(p -> "+86" + p).collect(Collectors.toSet()); + Set set = Arrays.stream(phones.split(StringUtils.SEPARATOR)).map(p -> "+86" + p).collect(Collectors.toSet()); req.setPhoneNumberSet(ArrayUtil.toArray(set, String.class)); if (CollUtil.isNotEmpty(param)) { req.setTemplateParamSet(ArrayUtil.toArray(param.values(), String.class)); diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index c1c28d9f8..9c382a39e 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.5.0 + 4.6.0 4.0.0 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java index 40bc2821d..ca9a77ce3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java @@ -37,7 +37,7 @@ public class SysConfig extends BaseEntity { */ @ExcelProperty(value = "参数名称") @NotBlank(message = "参数名称不能为空") - @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") + @Size(min = 0, max = 100, message = "参数名称不能超过{max}个字符") private String configName; /** @@ -45,7 +45,7 @@ public class SysConfig extends BaseEntity { */ @ExcelProperty(value = "参数键名") @NotBlank(message = "参数键名长度不能为空") - @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") + @Size(min = 0, max = 100, message = "参数键名长度不能超过{max}个字符") private String configKey; /** @@ -53,7 +53,7 @@ public class SysConfig extends BaseEntity { */ @ExcelProperty(value = "参数键值") @NotBlank(message = "参数键值不能为空") - @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") + @Size(min = 0, max = 500, message = "参数键值长度不能超过{max}个字符") private String configValue; /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java index f9457406a..dec401e3e 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java @@ -32,7 +32,7 @@ public class SysNotice extends BaseEntity { */ @Xss(message = "公告标题不能包含脚本字符") @NotBlank(message = "公告标题不能为空") - @Size(min = 0, max = 50, message = "公告标题不能超过50个字符") + @Size(min = 0, max = 50, message = "公告标题不能超过{max}个字符") private String noticeTitle; /** 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 7f2b05f6a..ac5e5a3ac 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 @@ -68,7 +68,7 @@ public class SysOssConfig extends BaseEntity { private String region; /** - * 状态(0正常 1停用) + * 是否默认(0=是,1=否) */ private String status; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java index 1edabf509..ecb84f4b4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java @@ -39,7 +39,7 @@ public class SysPost extends BaseEntity { */ @ExcelProperty(value = "岗位编码") @NotBlank(message = "岗位编码不能为空") - @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") + @Size(min = 0, max = 64, message = "岗位编码长度不能超过{max}个字符") private String postCode; /** @@ -47,7 +47,7 @@ public class SysPost extends BaseEntity { */ @ExcelProperty(value = "岗位名称") @NotBlank(message = "岗位名称不能为空") - @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") + @Size(min = 0, max = 50, message = "岗位名称长度不能超过{max}个字符") private String postName; /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java index 3f5ab4a8d..f874b20e3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java @@ -13,22 +13,31 @@ @EqualsAndHashCode(callSuper = true) public class SysOssBo extends BaseEntity { + /** + * ossId + */ + private Long ossId; + /** * 文件名 */ private String fileName; + /** * 原名 */ private String originalName; + /** * 文件后缀名 */ private String fileSuffix; + /** * URL地址 */ private String url; + /** * 服务商 */ 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 af289376c..2e257e8ea 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 @@ -32,28 +32,28 @@ public class SysOssConfigBo extends BaseEntity { * 配置key */ @NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class}) - @Size(min = 2, max = 100, message = "configKey长度必须介于2和20 之间") + @Size(min = 2, max = 100, message = "configKey长度必须介于{min}和{max} 之间") private String configKey; /** * accessKey */ @NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class}) - @Size(min = 2, max = 100, message = "accessKey长度必须介于2和100 之间") + @Size(min = 2, max = 100, message = "accessKey长度必须介于{min}和{max} 之间") private String accessKey; /** * 秘钥 */ @NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class}) - @Size(min = 2, max = 100, message = "secretKey长度必须介于2和100 之间") + @Size(min = 2, max = 100, message = "secretKey长度必须介于{min}和{max} 之间") private String secretKey; /** * 桶名称 */ @NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class}) - @Size(min = 2, max = 100, message = "bucketName长度必须介于2和100之间") + @Size(min = 2, max = 100, message = "bucketName长度必须介于{min}和{max}之间") private String bucketName; /** @@ -65,7 +65,7 @@ public class SysOssConfigBo extends BaseEntity { * 访问站点 */ @NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class}) - @Size(min = 2, max = 100, message = "endpoint长度必须介于2和100之间") + @Size(min = 2, max = 100, message = "endpoint长度必须介于{min}和{max}之间") private String endpoint; /** @@ -79,7 +79,7 @@ public class SysOssConfigBo extends BaseEntity { private String isHttps; /** - * 状态(0=正常,1=停用) + * 是否默认(0=是,1=否) */ private String status; 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 616e4e82d..9edc60c2b 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 @@ -68,7 +68,7 @@ public class SysOssConfigVo { private String region; /** - * 状态(0=正常,1=停用) + * 是否默认(0=是,1=否) */ private String status; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java index adcb5d3f7..d6bd54f64 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java @@ -91,6 +91,6 @@ public interface ISysConfigService { * @param config 参数信息 * @return 结果 */ - String checkConfigKeyUnique(SysConfig config); + boolean checkConfigKeyUnique(SysConfig config); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java index d821a4ab3..4ae34ab20 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java @@ -81,7 +81,7 @@ public interface ISysDeptService { * @param dept 部门信息 * @return 结果 */ - String checkDeptNameUnique(SysDept dept); + boolean checkDeptNameUnique(SysDept dept); /** * 校验部门是否有数据权限 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java index 1bad68089..0e3d94dab 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java @@ -100,5 +100,5 @@ public interface ISysDictTypeService { * @param dictType 字典类型 * @return 结果 */ - String checkDictTypeUnique(SysDictType dictType); + boolean checkDictTypeUnique(SysDictType dictType); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java index 813b1e282..906cd88b4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -133,5 +133,5 @@ public interface ISysMenuService { * @param menu 菜单信息 * @return 结果 */ - String checkMenuNameUnique(SysMenu menu); + boolean checkMenuNameUnique(SysMenu menu); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java index 9c3b78cd7..42968e953 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java @@ -53,7 +53,7 @@ public interface ISysPostService { * @param post 岗位信息 * @return 结果 */ - String checkPostNameUnique(SysPost post); + boolean checkPostNameUnique(SysPost post); /** * 校验岗位编码 @@ -61,7 +61,7 @@ public interface ISysPostService { * @param post 岗位信息 * @return 结果 */ - String checkPostCodeUnique(SysPost post); + boolean checkPostCodeUnique(SysPost post); /** * 通过岗位ID查询岗位使用数量 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java index 5b726b2e0..107ccf262 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -71,7 +71,7 @@ public interface ISysRoleService { * @param role 角色信息 * @return 结果 */ - String checkRoleNameUnique(SysRole role); + boolean checkRoleNameUnique(SysRole role); /** * 校验角色权限是否唯一 @@ -79,7 +79,7 @@ public interface ISysRoleService { * @param role 角色信息 * @return 结果 */ - String checkRoleKeyUnique(SysRole role); + boolean checkRoleKeyUnique(SysRole role); /** * 校验角色是否允许操作 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 042efc2c9..cfa6e16f9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -86,7 +86,7 @@ public interface ISysUserService { * @param user 用户信息 * @return 结果 */ - String checkUserNameUnique(SysUser user); + boolean checkUserNameUnique(SysUser user); /** * 校验手机号码是否唯一 @@ -94,7 +94,7 @@ public interface ISysUserService { * @param user 用户信息 * @return 结果 */ - String checkPhoneUnique(SysUser user); + boolean checkPhoneUnique(SysUser user); /** * 校验email是否唯一 @@ -102,7 +102,7 @@ public interface ISysUserService { * @param user 用户信息 * @return 结果 */ - String checkEmailUnique(SysUser user); + boolean checkEmailUnique(SysUser user); /** * 校验用户是否允许操作 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java index 97ff4801a..5adc63225 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java @@ -1,12 +1,10 @@ package com.ruoyi.system.service; -import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.HashSet; -import java.util.List; import java.util.Set; /** @@ -28,7 +26,7 @@ public class SysPermissionService { * @return 角色权限信息 */ public Set getRolePermission(SysUser user) { - Set roles = new HashSet(); + Set roles = new HashSet<>(); // 管理员拥有所有权限 if (user.isAdmin()) { roles.add("admin"); @@ -45,22 +43,12 @@ public Set getRolePermission(SysUser user) { * @return 菜单权限信息 */ public Set getMenuPermission(SysUser user) { - Set perms = new HashSet(); + Set perms = new HashSet<>(); // 管理员拥有所有权限 if (user.isAdmin()) { perms.add("*:*:*"); } else { - List roles = user.getRoles(); - if (!roles.isEmpty() && roles.size() > 1) { - // 多角色设置permissions属性,以便数据权限匹配权限 - for (SysRole role : roles) { - Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); - role.setPermissions(rolePerms); - perms.addAll(rolePerms); - } - } else { - perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); - } + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); } return perms; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java index bf9d00d4d..886aec3b8 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java @@ -54,7 +54,7 @@ public void register(RegisterBody registerBody) { sysUser.setPassword(BCrypt.hashpw(password)); sysUser.setUserType(userType); - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) { + if (!userService.checkUserNameUnique(sysUser)) { throw new UserException("user.register.save.error", username); } boolean regFlag = userService.registerUser(sysUser); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index c39ec74df..932753b26 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -204,13 +204,13 @@ public void resetConfigCache() { * @return 结果 */ @Override - public String checkConfigKeyUnique(SysConfig config) { - Long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + public boolean checkConfigKeyUnique(SysConfig config) { + long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper().eq(SysConfig::getConfigKey, config.getConfigKey())); - if (ObjectUtil.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) { - return UserConstants.NOT_UNIQUE; + if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) { + return false; } - return UserConstants.UNIQUE; + return true; } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java index 00b402467..8af6cabdb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -6,20 +6,26 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.service.DeptService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.DataBaseHelper; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TreeBuildUtils; +import com.ruoyi.common.utils.redis.CacheUtils; +import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.service.ISysDeptService; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -33,7 +39,7 @@ */ @RequiredArgsConstructor @Service -public class SysDeptServiceImpl implements ISysDeptService { +public class SysDeptServiceImpl implements ISysDeptService, DeptService { private final SysDeptMapper baseMapper; private final SysRoleMapper roleMapper; @@ -106,15 +112,37 @@ public List selectDeptListByRoleId(Long roleId) { * @param deptId 部门ID * @return 部门信息 */ + @Cacheable(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") @Override public SysDept selectDeptById(Long deptId) { SysDept dept = baseMapper.selectById(deptId); + if (ObjectUtil.isNull(dept)) { + return null; + } SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId())); dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null); return dept; } + /** + * 通过部门ID查询部门名称 + * + * @param deptIds 部门ID串逗号分隔 + * @return 部门名称串逗号分隔 + */ + @Override + public String selectDeptNameByIds(String deptIds) { + List list = new ArrayList<>(); + for (Long id : StringUtils.splitTo(deptIds, Convert::toLong)) { + SysDept dept = SpringUtils.getAopProxy(this).selectDeptById(id); + if (ObjectUtil.isNotNull(dept)) { + list.add(dept.getDeptName()); + } + } + return String.join(StringUtils.SEPARATOR, list); + } + /** * 根据ID查询所有子部门数(正常状态) * @@ -159,15 +187,12 @@ public boolean checkDeptExistUser(Long deptId) { * @return 结果 */ @Override - public String checkDeptNameUnique(SysDept dept) { + public boolean checkDeptNameUnique(SysDept dept) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysDept::getDeptName, dept.getDeptName()) .eq(SysDept::getParentId, dept.getParentId()) .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -200,7 +225,7 @@ public int insertDept(SysDept dept) { if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) { throw new ServiceException("部门停用,不允许新增"); } - dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + dept.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + dept.getParentId()); return baseMapper.insert(dept); } @@ -210,12 +235,13 @@ public int insertDept(SysDept dept) { * @param dept 部门信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#dept.deptId") @Override public int updateDept(SysDept dept) { SysDept newParentDept = baseMapper.selectById(dept.getParentId()); SysDept oldDept = baseMapper.selectById(dept.getDeptId()); if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) { - String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String newAncestors = newParentDept.getAncestors() + StringUtils.SEPARATOR + newParentDept.getDeptId(); String oldAncestors = oldDept.getAncestors(); dept.setAncestors(newAncestors); updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); @@ -259,8 +285,10 @@ public void updateDeptChildren(Long deptId, String newAncestors, String oldAnces dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); list.add(dept); } - if (list.size() > 0) { - baseMapper.updateBatchById(list); + if (CollUtil.isNotEmpty(list)) { + if (baseMapper.updateBatchById(list)) { + list.forEach(dept -> CacheUtils.evict(CacheNames.SYS_DEPT, dept.getDeptId())); + } } } @@ -270,6 +298,7 @@ public void updateDeptChildren(Long deptId, String newAncestors, String oldAnces * @param deptId 部门ID * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") @Override public int deleteDeptById(Long deptId) { return baseMapper.deleteById(deptId); 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 d7244116a..0c897df61 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 @@ -216,14 +216,11 @@ public List updateDictType(SysDictType dict) { * @return 结果 */ @Override - public String checkDictTypeUnique(SysDictType dict) { + public boolean checkDictTypeUnique(SysDictType dict) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysDictType::getDictType, dict.getDictType()) .ne(ObjectUtil.isNotNull(dict.getDictId()), SysDictType::getDictId, dict.getDictId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** 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 4d3406757..8e3fad9f4 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 @@ -92,7 +92,7 @@ public Set selectMenuPermsByUserId(Long userId) { Set permsSet = new HashSet<>(); for (String perm : perms) { if (StringUtils.isNotEmpty(perm)) { - permsSet.addAll(Arrays.asList(perm.trim().split(","))); + permsSet.addAll(StringUtils.splitList(perm.trim())); } } return permsSet; @@ -110,7 +110,7 @@ public Set selectMenuPermsByRoleId(Long roleId) { Set permsSet = new HashSet<>(); for (String perm : perms) { if (StringUtils.isNotEmpty(perm)) { - permsSet.addAll(Arrays.asList(perm.trim().split(","))); + permsSet.addAll(StringUtils.splitList(perm.trim())); } } return permsSet; @@ -153,7 +153,7 @@ public List selectMenuListByRoleId(Long roleId) { */ @Override public List buildMenus(List menus) { - List routers = new LinkedList(); + List routers = new LinkedList<>(); for (SysMenu menu : menus) { RouterVo router = new RouterVo(); router.setHidden("1".equals(menu.getVisible())); @@ -163,13 +163,13 @@ public List buildMenus(List menus) { router.setQuery(menu.getQueryParam()); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); List cMenus = menu.getChildren(); - if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); } else if (isMenuFrame(menu)) { router.setMeta(null); - List childrenList = new ArrayList(); + List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponent()); @@ -181,7 +181,7 @@ public List buildMenus(List menus) { } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setPath("/"); - List childrenList = new ArrayList(); + List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); String routerPath = innerLinkReplaceEach(menu.getPath()); children.setPath(routerPath); @@ -287,15 +287,12 @@ public int deleteMenuById(Long menuId) { * @return 结果 */ @Override - public String checkMenuNameUnique(SysMenu menu) { + public boolean checkMenuNameUnique(SysMenu menu) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysMenu::getMenuName, menu.getMenuName()) .eq(SysMenu::getParentId, menu.getParentId()) .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -394,7 +391,7 @@ public boolean isParentView(SysMenu menu) { * @return String */ public List getChildPerms(List list, int parentId) { - List returnList = new ArrayList(); + List returnList = new ArrayList<>(); for (SysMenu t : list) { // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 if (t.getParentId() == parentId) { @@ -433,7 +430,7 @@ private List getChildList(List list, SysMenu t) { * 判断是否有子节点 */ private boolean hasChild(List list, SysMenu t) { - return getChildList(list, t).size() > 0; + return CollUtil.isNotEmpty(getChildList(list, t)); } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java index d6269242c..2e90e50f6 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java @@ -8,7 +8,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.CacheNames; -import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; @@ -16,9 +15,7 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; -import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.oss.constant.OssConstant; -import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOssConfig; import com.ruoyi.system.domain.bo.SysOssConfigBo; import com.ruoyi.system.domain.vo.SysOssConfigVo; @@ -26,7 +23,6 @@ import com.ruoyi.system.service.ISysOssConfigService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -59,10 +55,8 @@ public void init() { if ("0".equals(config.getStatus())) { RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey); } - SpringUtils.context().publishEvent(config); + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); } - // 初始化OSS工厂 - OssFactory.init(); } @Override @@ -92,7 +86,7 @@ public Boolean insertByBo(SysOssConfigBo bo) { validEntityBeforeSave(config); boolean flag = baseMapper.insert(config) > 0; if (flag) { - SpringUtils.context().publishEvent(config); + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); } return flag; } @@ -109,7 +103,7 @@ public Boolean updateByBo(SysOssConfigBo bo) { luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId()); boolean flag = baseMapper.update(config, luw) > 0; if (flag) { - SpringUtils.context().publishEvent(config); + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); } return flag; } @@ -118,8 +112,7 @@ public Boolean updateByBo(SysOssConfigBo bo) { * 保存前的数据校验 */ private void validEntityBeforeSave(SysOssConfig entity) { - if (StringUtils.isNotEmpty(entity.getConfigKey()) - && UserConstants.NOT_UNIQUE.equals(checkConfigKeyUnique(entity))) { + if (StringUtils.isNotEmpty(entity.getConfigKey()) && !checkConfigKeyUnique(entity)) { throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!"); } } @@ -147,15 +140,15 @@ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { /** * 判断configKey是否唯一 */ - private String checkConfigKeyUnique(SysOssConfig sysOssConfig) { + private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) { long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId(); SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey) .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey())); if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) { - return UserConstants.NOT_UNIQUE; + return false; } - return UserConstants.UNIQUE; + return true; } /** @@ -174,16 +167,4 @@ public int updateOssConfigStatus(SysOssConfigBo bo) { return row; } - /** - * 更新配置缓存 - * - * @param config 配置 - */ - @EventListener - public void updateConfigCache(SysOssConfig config) { - CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); - RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> { - log.info("发布刷新OSS配置 => " + msg); - }); - } } 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 cd9bffb14..c36bfa274 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.convert.Convert; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -8,6 +9,7 @@ import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.service.OssService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.BeanCopyUtils; import com.ruoyi.common.utils.StringUtils; @@ -31,10 +33,7 @@ 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.*; import java.util.stream.Collectors; /** @@ -44,7 +43,7 @@ */ @RequiredArgsConstructor @Service -public class SysOssServiceImpl implements ISysOssService { +public class SysOssServiceImpl implements ISysOssService, OssService { private final SysOssMapper baseMapper; @@ -69,6 +68,18 @@ public List listByIds(Collection ossIds) { return list; } + @Override + public String selectUrlByIds(String ossIds) { + List list = new ArrayList<>(); + for (Long id : StringUtils.splitTo(ossIds, Convert::toLong)) { + SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); + if (ObjectUtil.isNotNull(vo)) { + list.add(this.matchingUrl(vo).getUrl()); + } + } + return String.join(StringUtils.SEPARATOR, list); + } + private LambdaQueryWrapper buildQueryWrapper(SysOssBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java index 7e2a56c2b..79edef7f9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java @@ -3,7 +3,6 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; @@ -94,14 +93,11 @@ public List selectPostListByUserId(Long userId) { * @return 结果 */ @Override - public String checkPostNameUnique(SysPost post) { + public boolean checkPostNameUnique(SysPost post) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysPost::getPostName, post.getPostName()) .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -111,14 +107,11 @@ public String checkPostNameUnique(SysPost post) { * @return 结果 */ @Override - public String checkPostCodeUnique(SysPost post) { + public boolean checkPostCodeUnique(SysPost post) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysPost::getPostCode, post.getPostCode()) .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index e7e5b53c5..eb2a6df2a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.UserConstants; @@ -14,6 +13,8 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.StreamUtils; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysRoleDept; import com.ruoyi.system.domain.SysRoleMenu; import com.ruoyi.system.domain.SysUserRole; @@ -106,7 +107,7 @@ public Set selectRolePermissionByUserId(Long userId) { Set permsSet = new HashSet<>(); for (SysRole perm : perms) { if (ObjectUtil.isNotNull(perm)) { - permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + permsSet.addAll(StringUtils.splitList(perm.getRoleKey().trim())); } } return permsSet; @@ -151,14 +152,11 @@ public SysRole selectRoleById(Long roleId) { * @return 结果 */ @Override - public String checkRoleNameUnique(SysRole role) { + public boolean checkRoleNameUnique(SysRole role) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysRole::getRoleName, role.getRoleName()) .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -168,14 +166,11 @@ public String checkRoleNameUnique(SysRole role) { * @return 结果 */ @Override - public String checkRoleKeyUnique(SysRole role) { + public boolean checkRoleKeyUnique(SysRole role) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysRole::getRoleKey, role.getRoleKey()) .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -397,14 +392,13 @@ public int deleteAuthUsers(Long roleId, Long[] userIds) { public int insertAuthUsers(Long roleId, Long[] userIds) { // 新增用户与角色管理 int rows = 1; - List list = new ArrayList(); - for (Long userId : userIds) { + List list = StreamUtils.toList(Arrays.asList(userIds), userId -> { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); - list.add(ur); - } - if (list.size() > 0) { + return ur; + }); + if (CollUtil.isNotEmpty(list)) { rows = userRoleMapper.insertBatch(list) ? list.size() : 0; } return rows; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index 4e63f17ea..b4105870c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -9,12 +9,14 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.service.UserService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.DataBaseHelper; import com.ruoyi.common.helper.LoginHelper; @@ -27,10 +29,10 @@ import com.ruoyi.system.service.ISysUserService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -43,7 +45,7 @@ @Slf4j @RequiredArgsConstructor @Service -public class SysUserServiceImpl implements ISysUserService { +public class SysUserServiceImpl implements ISysUserService, UserService { private final SysUserMapper baseMapper; private final SysDeptMapper deptMapper; @@ -197,48 +199,37 @@ public String selectUserPostGroup(String userName) { * @return 结果 */ @Override - public String checkUserNameUnique(SysUser user) { + public boolean checkUserNameUnique(SysUser user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysUser::getUserName, user.getUserName()) .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** * 校验手机号码是否唯一 * * @param user 用户信息 - * @return */ @Override - public String checkPhoneUnique(SysUser user) { + public boolean checkPhoneUnique(SysUser user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysUser::getPhonenumber, user.getPhonenumber()) .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** * 校验email是否唯一 * * @param user 用户信息 - * @return */ @Override - public String checkEmailUnique(SysUser user) { + public boolean checkEmailUnique(SysUser user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysUser::getEmail, user.getEmail()) .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); - if (exist) { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; + return !exist; } /** @@ -417,13 +408,12 @@ public void insertUserPost(SysUser user) { Long[] posts = user.getPostIds(); if (ArrayUtil.isNotEmpty(posts)) { // 新增用户与岗位管理 - List list = new ArrayList<>(posts.length); - for (Long postId : posts) { + List list = StreamUtils.toList(Arrays.asList(posts), postId -> { SysUserPost up = new SysUserPost(); up.setUserId(user.getUserId()); up.setPostId(postId); - list.add(up); - } + return up; + }); userPostMapper.insertBatch(list); } } @@ -437,13 +427,12 @@ public void insertUserPost(SysUser user) { public void insertUserRole(Long userId, Long[] roleIds) { if (ArrayUtil.isNotEmpty(roleIds)) { // 新增用户与角色管理 - List list = new ArrayList<>(roleIds.length); - for (Long roleId : roleIds) { + List list = StreamUtils.toList(Arrays.asList(roleIds), roleId -> { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); - list.add(ur); - } + return ur; + }); userRoleMapper.insertBatch(list); } } @@ -485,4 +474,12 @@ public int deleteUserByIds(Long[] userIds) { return baseMapper.deleteBatchIds(ids); } + @Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId") + @Override + public String selectUserNameById(Long userId) { + SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() + .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); + return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); + } + } diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index dacdcd8a6..06a653efe 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -86,17 +86,17 @@ diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index c1975834f..11de952f8 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi-vue-plus", - "version": "4.5.0", + "version": "4.6.0", "description": "RuoYi-Vue-Plus后台管理系统", "author": "LionLi", "license": "MIT", @@ -40,7 +40,7 @@ "clipboard": "2.0.8", "core-js": "3.25.3", "echarts": "5.4.0", - "element-ui": "2.15.10", + "element-ui": "2.15.12", "file-saver": "2.0.5", "fuse.js": "6.4.3", "highlight.js": "9.18.5", diff --git a/ruoyi-ui/src/layout/components/TagsView/index.vue b/ruoyi-ui/src/layout/components/TagsView/index.vue index cc980717e..3c0644e1c 100644 --- a/ruoyi-ui/src/layout/components/TagsView/index.vue +++ b/ruoyi-ui/src/layout/components/TagsView/index.vue @@ -87,7 +87,7 @@ export default { }, isFirstView() { try { - return this.selectedTag.fullPath === this.visitedViews[1].fullPath || this.selectedTag.fullPath === '/index' + return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath } catch (err) { return false } diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js index 6bb0a1f83..609d21590 100644 --- a/ruoyi-ui/src/permission.js +++ b/ruoyi-ui/src/permission.js @@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request' NProgress.configure({ showSpinner: false }) -const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] +const whiteList = ['/login', '/register'] router.beforeEach((to, from, next) => { NProgress.start() diff --git a/ruoyi-ui/src/plugins/download.js b/ruoyi-ui/src/plugins/download.js index a1b21dad9..b27702f18 100644 --- a/ruoyi-ui/src/plugins/download.js +++ b/ruoyi-ui/src/plugins/download.js @@ -17,9 +17,9 @@ export default { url: url, responseType: 'blob', headers: { 'Authorization': 'Bearer ' + getToken() } - }).then(async (res) => { - const isLogin = await blobValidate(res.data); - if (isLogin) { + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { const blob = new Blob([res.data], { type: 'application/octet-stream' }) this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) } else { @@ -42,9 +42,9 @@ export default { 'Authorization': 'Bearer ' + getToken(), 'datasource': localStorage.getItem("dataName") } - }).then(async (res) => { - const isLogin = await blobValidate(res.data); - if (isLogin) { + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { const blob = new Blob([res.data], { type: 'application/zip' }) this.saveAs(blob, name) } else { diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index f94fa0e5e..850685cd6 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -74,7 +74,7 @@ service.interceptors.response.use(res => { // 获取错误信息 const msg = errorCode[code] || res.data.msg || errorCode['default'] // 二进制数据则直接返回 - if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){ + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { return res.data } if (code === 401) { @@ -127,8 +127,8 @@ export function download(url, params, filename, config) { responseType: 'blob', ...config }).then(async (data) => { - const isLogin = await blobValidate(data); - if (isLogin) { + const isBlob = blobValidate(data); + if (isBlob) { const blob = new Blob([data]) saveAs(blob, filename) } else { diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js index 243c4c7b1..44bf9c403 100644 --- a/ruoyi-ui/src/utils/ruoyi.js +++ b/ruoyi-ui/src/utils/ruoyi.js @@ -228,12 +228,6 @@ export function tansParams(params) { } // 验证是否为blob格式 -export async function blobValidate(data) { - try { - const text = await data.text(); - JSON.parse(text); - return false; - } catch (error) { - return true; - } +export function blobValidate(data) { + return data.type !== 'application/json' } diff --git a/ruoyi-ui/src/views/demo/demo/index.vue b/ruoyi-ui/src/views/demo/demo/index.vue index 65387c9a5..2bfefd47f 100644 --- a/ruoyi-ui/src/views/demo/demo/index.vue +++ b/ruoyi-ui/src/views/demo/demo/index.vue @@ -24,11 +24,12 @@ v-model="daterangeCreateTime" size="small" style="width: 240px" - value-format="yyyy-MM-dd" + value-format="yyyy-MM-dd HH:mm:ss" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" + :default-time="['00:00:00', '23:59:59']" > diff --git a/ruoyi-ui/src/views/demo/tree/index.vue b/ruoyi-ui/src/views/demo/tree/index.vue index 6cfa7f243..d66c6f96e 100644 --- a/ruoyi-ui/src/views/demo/tree/index.vue +++ b/ruoyi-ui/src/views/demo/tree/index.vue @@ -15,11 +15,12 @@ v-model="daterangeCreateTime" size="small" style="width: 240px" - value-format="yyyy-MM-dd" + value-format="yyyy-MM-dd HH:mm:ss" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" + :default-time="['00:00:00', '23:59:59']" > diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue index 7f7008e43..cbeab0f90 100644 --- a/ruoyi-ui/src/views/index.vue +++ b/ruoyi-ui/src/views/index.vue @@ -114,7 +114,7 @@ export default { data() { return { // 版本号 - version: "4.5.0", + version: "4.6.0", }; }, methods: { diff --git a/ruoyi-ui/src/views/login.vue b/ruoyi-ui/src/views/login.vue index ed8d971a2..0ddb13443 100644 --- a/ruoyi-ui/src/views/login.vue +++ b/ruoyi-ui/src/views/login.vue @@ -56,7 +56,7 @@ diff --git a/ruoyi-ui/src/views/monitor/cache/index.vue b/ruoyi-ui/src/views/monitor/cache/index.vue index 53f6eee51..e81da2e8f 100644 --- a/ruoyi-ui/src/views/monitor/cache/index.vue +++ b/ruoyi-ui/src/views/monitor/cache/index.vue @@ -3,7 +3,7 @@ -
基本信息
+
基本信息
@@ -45,7 +45,7 @@ -
命令统计
+
命令统计
@@ -54,9 +54,7 @@ -
- 内存信息 -
+
内存信息
diff --git a/ruoyi-ui/src/views/monitor/cache/list.vue b/ruoyi-ui/src/views/monitor/cache/list.vue index 94307ab6a..8073d56a7 100644 --- a/ruoyi-ui/src/views/monitor/cache/list.vue +++ b/ruoyi-ui/src/views/monitor/cache/list.vue @@ -4,7 +4,7 @@
- 缓存列表 + 缓存列表
- 键名列表 + 键名列表
- 缓存内容 + 缓存内容 diff --git a/ruoyi-ui/src/views/monitor/operlog/index.vue b/ruoyi-ui/src/views/monitor/operlog/index.vue index c1b537789..8e672f91f 100644 --- a/ruoyi-ui/src/views/monitor/operlog/index.vue +++ b/ruoyi-ui/src/views/monitor/operlog/index.vue @@ -53,11 +53,12 @@ diff --git a/ruoyi-ui/src/views/register.vue b/ruoyi-ui/src/views/register.vue index 649c4d8d1..b22fd447e 100644 --- a/ruoyi-ui/src/views/register.vue +++ b/ruoyi-ui/src/views/register.vue @@ -61,7 +61,7 @@
diff --git a/ruoyi-ui/src/views/system/config/index.vue b/ruoyi-ui/src/views/system/config/index.vue index f580b983e..984b7e29b 100644 --- a/ruoyi-ui/src/views/system/config/index.vue +++ b/ruoyi-ui/src/views/system/config/index.vue @@ -33,11 +33,12 @@ @@ -107,7 +108,7 @@ - + - +