diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml index 5b32519c5..478b4f30d 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 9fefae69a..541800ddc 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -1,12 +1,12 @@ - + - - + \ No newline at end of file diff --git a/.run/ruoyi-snailjob-server.run.xml b/.run/ruoyi-snailjob-server.run.xml index 914809dbf..5221eef4f 100644 --- a/.run/ruoyi-snailjob-server.run.xml +++ b/.run/ruoyi-snailjob-server.run.xml @@ -2,7 +2,7 @@ - diff --git a/README.md b/README.md index 71895dc3f..eeb3f7b4b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/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-5.2.1-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.2-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg)]() [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]() [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]() diff --git a/pom.xml b/pom.xml index 8ebef3498..e8b9c2932 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ RuoYi-Vue-Plus多租户管理系统 - 5.2.1 + 5.2.2 3.2.9 UTF-8 UTF-8 @@ -23,7 +23,7 @@ 0.15.0 4.0.2 2.3 - 1.38.0 + 1.39.0 3.5.7 3.9.1 5.8.31 @@ -69,6 +69,8 @@ local info + ruoyi + 123456 @@ -77,6 +79,8 @@ dev info + ruoyi + 123456 @@ -88,6 +92,8 @@ prod warn + ruoyi + 123456 @@ -328,9 +334,9 @@ - commons-compress - org.apache.commons - 1.26.2 + commons-io + commons-io + 2.15.0 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 5e20daee7..f12202050 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -8,8 +8,8 @@ spring.boot.admin.client: metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: ruoyi - password: 123456 + username: @monitor.username@ + password: @monitor.password@ --- # snail-job 配置 snail-job: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 2823bba11..192eb7ed6 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -11,8 +11,8 @@ spring.boot.admin.client: metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: ruoyi - password: 123456 + username: @monitor.username@ + password: @monitor.password@ --- # snail-job 配置 snail-job: diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index 19ca420e3..455408d8c 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -14,7 +14,7 @@ - 5.2.1 + 5.2.2 diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java index d0163e643..8e501dfea 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java @@ -5,11 +5,13 @@ import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.TreeNodeConfig; import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.lang.tree.parser.NodeParser; -import org.dromara.common.core.utils.reflect.ReflectUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.dromara.common.core.utils.reflect.ReflectUtils; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 扩展 hutool TreeUtil 封装系统树构建 @@ -24,12 +26,54 @@ public class TreeBuildUtils extends TreeUtil { */ public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label"); + /** + * 构建树形结构 + * + * @param 输入节点的类型 + * @param 节点ID的类型 + * @param list 节点列表,其中包含了要构建树形结构的所有节点 + * @param nodeParser 解析器,用于将输入节点转换为树节点 + * @return 构建好的树形结构列表 + */ public static List> build(List list, NodeParser nodeParser) { if (CollUtil.isEmpty(list)) { - return null; + return CollUtil.newArrayList(); } K k = ReflectUtils.invokeGetter(list.get(0), "parentId"); return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser); } + /** + * 获取节点列表中所有节点的叶子节点 + * + * @param 节点ID的类型 + * @param nodes 节点列表 + * @return 包含所有叶子节点的列表 + */ + public static List> getLeafNodes(List> nodes) { + if (CollUtil.isEmpty(nodes)) { + return CollUtil.newArrayList(); + } + return nodes.stream() + .flatMap(TreeBuildUtils::extractLeafNodes) + .collect(Collectors.toList()); + } + + /** + * 获取指定节点下的所有叶子节点 + * + * @param 节点ID的类型 + * @param node 要查找叶子节点的根节点 + * @return 包含所有叶子节点的列表 + */ + private static Stream> extractLeafNodes(Tree node) { + if (!node.hasChild()) { + return Stream.of(node); + } else { + // 递归调用,获取所有子节点的叶子节点 + return node.getChildren().stream() + .flatMap(TreeBuildUtils::extractLeafNodes); + } + } + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java index b8b12d43c..6dde12998 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java @@ -21,7 +21,8 @@ public final class RegexUtils extends ReUtil { */ public static String extractFromString(String input, String regex, String defaultInput) { try { - return ReUtil.get(regex, input, 1); + String str = ReUtil.get(regex, input, 1); + return str == null ? defaultInput : str; } catch (Exception e) { return defaultInput; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java index 3e109b21a..fcf9fb4b6 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java @@ -15,7 +15,7 @@ public class SqlUtil { /** * 定义常用的 sql关键字 */ - public static final String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare "; + public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; /** * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) diff --git a/ruoyi-common/ruoyi-common-excel/pom.xml b/ruoyi-common/ruoyi-common-excel/pom.xml index 14b9410bb..dd4a5eebe 100644 --- a/ruoyi-common/ruoyi-common-excel/pom.xml +++ b/ruoyi-common/ruoyi-common-excel/pom.xml @@ -25,11 +25,6 @@ com.alibaba easyexcel - - commons-compress - org.apache.commons - 1.26.2 - diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index 5e300da22..bde26ae1c 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -340,8 +340,8 @@ public class OssClient { * @return UploadResult 包含上传后的文件信息 * @throws OssException 如果上传失败,抛出自定义异常 */ - public UploadResult uploadSuffix(byte[] data, String suffix) { - return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), FileUtils.getMimeType(suffix)); + public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { + return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), contentType); } /** @@ -353,8 +353,8 @@ public class OssClient { * @return UploadResult 包含上传后的文件信息 * @throws OssException 如果上传失败,抛出自定义异常 */ - public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), length, FileUtils.getMimeType(suffix)); + public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length, String contentType) { + return upload(inputStream, getPath(properties.getPrefix(), suffix), length, contentType); } /** diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java index 061d3aa45..bd801baed 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java @@ -2,6 +2,7 @@ package org.dromara.common.web.handler; import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpStatus; +import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; @@ -10,6 +11,7 @@ import org.dromara.common.core.domain.R; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.base.BaseException; import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; @@ -53,6 +55,22 @@ public class GlobalExceptionHandler { return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage()); } + /** + * servlet异常 + */ + @ExceptionHandler(ServletException.class) + public R handleServletException(ServletException e, HttpServletRequest request) { + if (StringUtils.contains(e.getMessage(), "NotLoginException")) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); + return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源"); + } else { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestURI, e); + return R.fail(e.getMessage()); + } + } + /** * 业务异常 */ diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml index beee58775..622c93d3c 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml @@ -13,8 +13,8 @@ logging: spring: security: user: - name: ruoyi - password: 123456 + name: @monitor.username@ + password: @monitor.password@ boot: admin: ui: @@ -44,5 +44,5 @@ spring.boot.admin.client: metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: ruoyi - password: 123456 + username: @monitor.username@ + password: @monitor.password@ diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml index cbe40be1e..3ed797cf6 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml @@ -46,5 +46,5 @@ spring.boot.admin.client: metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: ruoyi - password: 123456 + username: @monitor.username@ + password: @monitor.password@ diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml index 3ba983c2b..1d830dbe7 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml @@ -46,5 +46,5 @@ spring.boot.admin.client: metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: ruoyi - password: 123456 + username: @monitor.username@ + password: @monitor.password@ diff --git a/ruoyi-modules/ruoyi-generator/pom.xml b/ruoyi-modules/ruoyi-generator/pom.xml index b7fd94f59..49060292f 100644 --- a/ruoyi-modules/ruoyi-generator/pom.xml +++ b/ruoyi-modules/ruoyi-generator/pom.xml @@ -64,19 +64,19 @@ - + - + - + diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTable.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTable.java index f792cebc2..f2d725709 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTable.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTable.java @@ -162,7 +162,7 @@ public class GenTable extends BaseEntity { * 上级菜单ID字段 */ @TableField(exist = false) - private String parentMenuId; + private Long parentMenuId; /** * 上级菜单名称字段 diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index 99935f7fa..bb8b444fc 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -137,7 +137,7 @@ public class GenTableServiceImpl implements IGenTableService { } // 过滤并转换表格数据 List tables = tablesMap.values().stream() - .filter(x -> !StringUtils.containsAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> { if (CollUtil.isEmpty(tableNames)) { return true; @@ -174,6 +174,16 @@ public class GenTableServiceImpl implements IGenTableService { return TableDataInfo.build(page); } + public static boolean startWithAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) { + // 判断是否是以指定字符串开头 + for (CharSequence searchCharSequence : searchCharSequences) { + if (StringUtils.startsWithIgnoreCase(cs, searchCharSequence)) { + return true; + } + } + return false; + } + /** * 查询据库列表 * @@ -548,7 +558,7 @@ public class GenTableServiceImpl implements IGenTableService { String treeCode = paramsObj.getStr(GenConstants.TREE_CODE); String treeParentCode = paramsObj.getStr(GenConstants.TREE_PARENT_CODE); String treeName = paramsObj.getStr(GenConstants.TREE_NAME); - String parentMenuId = paramsObj.getStr(GenConstants.PARENT_MENU_ID); + Long parentMenuId = paramsObj.getLong(GenConstants.PARENT_MENU_ID); String parentMenuName = paramsObj.getStr(GenConstants.PARENT_MENU_NAME); genTable.setTreeCode(treeCode); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm index c896afbe8..5591f9778 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm @@ -58,7 +58,7 @@ public class ${ClassName}Vo implements Serializable { * ${column.columnComment}Url */ @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "${column.javaField}") - private String ${column.javaField}Url"; + private String ${column.javaField}Url; #end #end #end diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java index bad240c72..10c6777e7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java @@ -176,4 +176,18 @@ public class SysTenantController extends BaseController { return toAjax(TenantHelper.ignore(() -> tenantService.syncTenantPackage(tenantId, packageId))); } + /** + * 同步租户字典 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @Log(title = "同步租户字典", businessType = BusinessType.INSERT) + @GetMapping("/syncTenantDict") + public R syncTenantDict() { + if (!TenantHelper.isEnable()) { + return R.fail("当前未开启租户模式"); + } + tenantService.syncTenantDict(); + return R.ok("同步租户字典成功"); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java index c20a4eca5..1ea8f2dad 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java @@ -5,8 +5,11 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.digest.BCrypt; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.excel.core.ExcelListener; import org.dromara.common.excel.core.ExcelResult; @@ -80,7 +83,11 @@ public class SysUserImportListener extends AnalysisEventListener selectPageOperLogList(SysOperLogBo operLog, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(operLog); + if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { + pageQuery.setOrderByColumn("oper_id"); + pageQuery.setIsAsc("desc"); + } + Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(page); + } + + private LambdaQueryWrapper buildQueryWrapper(SysOperLogBo operLog) { Map params = operLog.getParams(); - LambdaQueryWrapper lqw = new LambdaQueryWrapper() + return new LambdaQueryWrapper() .like(StringUtils.isNotBlank(operLog.getOperIp()), SysOperLog::getOperIp, operLog.getOperIp()) .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle()) .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0, @@ -67,12 +77,6 @@ public class SysOperLogServiceImpl implements ISysOperLogService { .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName()) .between(params.get("beginTime") != null && params.get("endTime") != null, SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime")); - if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { - pageQuery.setOrderByColumn("oper_id"); - pageQuery.setIsAsc("desc"); - } - Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(page); } /** @@ -95,23 +99,8 @@ public class SysOperLogServiceImpl implements ISysOperLogService { */ @Override public List selectOperLogList(SysOperLogBo operLog) { - Map params = operLog.getParams(); - return baseMapper.selectVoList(new LambdaQueryWrapper() - .like(StringUtils.isNotBlank(operLog.getOperIp()), SysOperLog::getOperIp, operLog.getOperIp()) - .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle()) - .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0, - SysOperLog::getBusinessType, operLog.getBusinessType()) - .func(f -> { - if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) { - f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes())); - } - }) - .eq(operLog.getStatus() != null && operLog.getStatus() > 0, - SysOperLog::getStatus, operLog.getStatus()) - .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName()) - .between(params.get("beginTime") != null && params.get("endTime") != null, - SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime")) - .orderByDesc(SysOperLog::getOperId)); + LambdaQueryWrapper lqw = buildQueryWrapper(operLog); + return baseMapper.selectVoList(lqw.orderByDesc(SysOperLog::getOperId)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 186653182..ba7c179c0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -195,7 +195,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(); UploadResult uploadResult; try { - uploadResult = storage.uploadSuffix(file.getBytes(), suffix); + uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType()); } catch (IOException e) { throw new ServiceException(e.getMessage()); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index d30750db5..65380f221 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -1,6 +1,7 @@ package org.dromara.system.service.impl; import cn.dev33.satoken.secure.BCrypt; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; @@ -14,9 +15,13 @@ import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.redis.utils.CacheUtils; +import org.dromara.common.tenant.core.TenantEntity; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.*; import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.vo.SysTenantVo; @@ -27,10 +32,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; +import java.util.*; /** * 租户Service业务层处理 @@ -369,4 +371,86 @@ public class SysTenantServiceImpl implements ISysTenantService { } return true; } + + /** + * 同步租户字典 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public void syncTenantDict() { + // 查询超管 所有字典数据 + List dictTypeList = new ArrayList<>(); + List dictDataList = new ArrayList<>(); + TenantHelper.ignore(() -> { + dictTypeList.addAll(dictTypeMapper.selectList()); + dictDataList.addAll(dictDataMapper.selectList()); + }); + Map> typeMap = StreamUtils.groupByKey(dictTypeList, TenantEntity::getTenantId); + Map>> typeDataMap = StreamUtils.groupBy2Key( + dictDataList, TenantEntity::getTenantId, SysDictData::getDictType); + // 管理租户字典数据 + List defaultTypeMap = typeMap.get(TenantConstants.DEFAULT_TENANT_ID); + Map> defaultTypeDataMap = typeDataMap.get(TenantConstants.DEFAULT_TENANT_ID); + + // 获取所有租户编号 + List tenantIds = baseMapper.selectObjs( + new LambdaQueryWrapper().select(SysTenant::getTenantId) + .eq(SysTenant::getStatus, TenantConstants.NORMAL), x -> {return Convert.toStr(x);}); + List saveTypeList = new ArrayList<>(); + List saveDataList = new ArrayList<>(); + Set set = new HashSet<>(); + for (String tenantId : tenantIds) { + if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + continue; + } + for (SysDictType dictType : defaultTypeMap) { + List typeList = StreamUtils.toList(typeMap.get(tenantId), SysDictType::getDictType); + List dataList = defaultTypeDataMap.get(dictType.getDictType()); + if (typeList.contains(dictType.getDictType())) { + List dataListTenant = typeDataMap.get(tenantId).get(dictType.getDictType()); + Map map = StreamUtils.toIdentityMap(dataListTenant, SysDictData::getDictValue); + for (SysDictData dictData : dataList) { + if (!map.containsKey(dictData.getDictValue())) { + // 设置字典编码为 null + dictData.setDictCode(null); + dictData.setTenantId(tenantId); + dictData.setCreateTime(null); + dictData.setUpdateTime(null); + set.add(tenantId); + saveDataList.add(dictData); + } + } + } else { + dictType.setDictId(null); + dictType.setTenantId(tenantId); + dictType.setCreateTime(null); + dictType.setUpdateTime(null); + set.add(tenantId); + saveTypeList.add(dictType); + if (CollUtil.isNotEmpty(dataList)) { + // 筛选出 dictType 对应的 data + for (SysDictData dictData : dataList) { + // 设置字典编码为 null + dictData.setDictCode(null); + dictData.setTenantId(tenantId); + dictData.setCreateTime(null); + dictData.setUpdateTime(null); + set.add(tenantId); + } + saveDataList.addAll(dataList); + } + } + } + } + if (CollUtil.isNotEmpty(saveTypeList)) { + dictTypeMapper.insertBatch(saveTypeList); + } + if (CollUtil.isNotEmpty(saveDataList)) { + dictDataMapper.insertBatch(saveDataList); + } + for (String tenantId : set) { + TenantHelper.dynamic(tenantId, () -> CacheUtils.clear(CacheNames.SYS_DICT)); + } + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 254060688..8c6d1d5f5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -42,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; /** * 用户 业务层处理 @@ -628,6 +629,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return ObjectUtil.isNull(sysUser) ? null : sysUser.getEmail(); } + /** + * 通过用户ID查询用户列表 + * + * @param userIds 用户ids + * @return 用户列表 + */ @Override public List selectListByIds(List userIds) { if (CollUtil.isEmpty(userIds)) { @@ -636,28 +643,54 @@ public class SysUserServiceImpl implements ISysUserService, UserService { List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) .eq(SysUser::getStatus, UserConstants.USER_NORMAL) - .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); + .in(SysUser::getUserId, userIds)); return BeanUtil.copyToList(list, UserDTO.class); } + /** + * 通过角色ID查询用户ID + * + * @param roleIds 角色ids + * @return 用户ids + */ @Override public List selectUserIdsByRoleIds(List roleIds) { - List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); - return StreamUtils.toList(userRoles, SysUserRole::getUserId); - } - - @Override - public List selectUsersByRoleIds(List roleIds) { if (CollUtil.isEmpty(roleIds)) { return List.of(); } List userRoles = userRoleMapper.selectList( new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); - List userIds = StreamUtils.toList(userRoles, SysUserRole::getUserId); - return selectListByIds(userIds); + return StreamUtils.toList(userRoles, SysUserRole::getUserId); } + /** + * 通过角色ID查询用户 + * + * @param roleIds 角色ids + * @return 用户 + */ + @Override + public List selectUsersByRoleIds(List roleIds) { + if (CollUtil.isEmpty(roleIds)) { + return List.of(); + } + + // 通过角色ID获取用户角色信息 + List userRoles = userRoleMapper.selectList( + new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); + + // 获取用户ID列表 + Set userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId); + + return selectListByIds(new ArrayList<>(userIds)); + } + + /** + * 通过部门ID查询用户 + * + * @param deptIds 部门ids + * @return 用户 + */ @Override public List selectUsersByDeptIds(List deptIds) { if (CollUtil.isEmpty(deptIds)) { @@ -666,7 +699,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) .eq(SysUser::getStatus, UserConstants.USER_NORMAL) - .in(CollUtil.isNotEmpty(deptIds), SysUser::getDeptId, deptIds)); + .in(SysUser::getDeptId, deptIds)); return BeanUtil.copyToList(list, UserDTO.class); } } diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index b4f96aa44..91d97aeed 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -100,7 +100,7 @@ services: network_mode: "host" ruoyi-server1: - image: ruoyi/ruoyi-server:5.2.1 + image: ruoyi/ruoyi-server:5.2.2 container_name: ruoyi-server1 environment: # 时区上海 @@ -115,7 +115,7 @@ services: network_mode: "host" ruoyi-server2: - image: ruoyi/ruoyi-server:5.2.1 + image: ruoyi/ruoyi-server:5.2.2 container_name: ruoyi-server2 environment: # 时区上海 @@ -130,7 +130,7 @@ services: network_mode: "host" ruoyi-monitor-admin: - image: ruoyi/ruoyi-monitor-admin:5.2.1 + image: ruoyi/ruoyi-monitor-admin:5.2.2 container_name: ruoyi-monitor-admin environment: # 时区上海 @@ -142,7 +142,7 @@ services: network_mode: "host" ruoyi-snailjob-server: - image: ruoyi/ruoyi-snailjob-server:5.2.1 + image: ruoyi/ruoyi-snailjob-server:5.2.2 container_name: ruoyi-snailjob-server environment: # 时区上海 diff --git a/script/sql/oracle/snail_job_oracle.sql b/script/sql/oracle/oracle_ry_job.sql similarity index 99% rename from script/sql/oracle/snail_job_oracle.sql rename to script/sql/oracle/oracle_ry_job.sql index d2e17c1f0..da65dbbf6 100644 --- a/script/sql/oracle/snail_job_oracle.sql +++ b/script/sql/oracle/oracle_ry_job.sql @@ -74,6 +74,7 @@ COMMENT ON COLUMN sj_group_config.update_dt IS '修改时间'; COMMENT ON TABLE sj_group_config IS '组配置'; INSERT INTO sj_group_config (namespace_id, group_name, description, token, group_status, version, group_partition, id_generator_mode, init_scene, bucket_index, create_dt, update_dt) VALUES ('dev', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, sysdate, sysdate); +INSERT INTO sj_group_config (namespace_id, group_name, description, token, group_status, version, group_partition, id_generator_mode, init_scene, bucket_index, create_dt, update_dt) VALUES ('prod', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, sysdate, sysdate); -- sj_notify_config CREATE TABLE sj_notify_config diff --git a/script/sql/oracle/flowable.sql b/script/sql/oracle/oracle_ry_workflow.sql similarity index 100% rename from script/sql/oracle/flowable.sql rename to script/sql/oracle/oracle_ry_workflow.sql diff --git a/script/sql/postgres/snail_job_postgre.sql b/script/sql/postgres/postgres_ry_job.sql similarity index 99% rename from script/sql/postgres/snail_job_postgre.sql rename to script/sql/postgres/postgres_ry_job.sql index c8abc6816..546db3cc8 100644 --- a/script/sql/postgres/snail_job_postgre.sql +++ b/script/sql/postgres/postgres_ry_job.sql @@ -68,6 +68,7 @@ COMMENT ON COLUMN sj_group_config.update_dt IS '修改时间'; COMMENT ON TABLE sj_group_config IS '组配置'; INSERT INTO sj_group_config VALUES (1, 'dev', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, now(), now()); +INSERT INTO sj_group_config VALUES (2, 'prod', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, now(), now()); -- sj_notify_config CREATE TABLE sj_notify_config diff --git a/script/sql/postgres/flowable.sql b/script/sql/postgres/postgres_ry_workflow.sql similarity index 100% rename from script/sql/postgres/flowable.sql rename to script/sql/postgres/postgres_ry_workflow.sql diff --git a/script/sql/snail_job.sql b/script/sql/ry_job.sql similarity index 99% rename from script/sql/snail_job.sql rename to script/sql/ry_job.sql index c3aa7601b..396798ee0 100644 --- a/script/sql/snail_job.sql +++ b/script/sql/ry_job.sql @@ -40,6 +40,7 @@ CREATE TABLE `sj_group_config` DEFAULT CHARSET = utf8mb4 COMMENT ='组配置'; INSERT INTO `sj_group_config` VALUES (1, 'dev', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, now(), now()); +INSERT INTO `sj_group_config` VALUES (2, 'prod', 'ruoyi_group', '', 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', 1, 1, 0, 1, 1, 4, now(), now()); CREATE TABLE `sj_notify_config` ( diff --git a/script/sql/flowable.sql b/script/sql/ry_workflow.sql similarity index 100% rename from script/sql/flowable.sql rename to script/sql/ry_workflow.sql diff --git a/script/sql/sqlserver/snail_job_sqlserver.sql b/script/sql/sqlserver/sqlserver_ry_job.sql similarity index 99% rename from script/sql/sqlserver/snail_job_sqlserver.sql rename to script/sql/sqlserver/sqlserver_ry_job.sql index 249842b98..bcf87f668 100644 --- a/script/sql/sqlserver/snail_job_sqlserver.sql +++ b/script/sql/sqlserver/sqlserver_ry_job.sql @@ -203,6 +203,8 @@ GO INSERT INTO sj_group_config(namespace_id, group_name, description, token, group_status, version, group_partition, id_generator_mode, init_scene, bucket_index, create_dt, update_dt) VALUES (N'dev', N'ruoyi_group', N'', N'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', N'1', N'1', N'0', N'1', N'1', N'4', getdate(), getdate()) GO +INSERT INTO sj_group_config(namespace_id, group_name, description, token, group_status, version, group_partition, id_generator_mode, init_scene, bucket_index, create_dt, update_dt) VALUES (N'prod', N'ruoyi_group', N'', N'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT', N'1', N'1', N'0', N'1', N'1', N'4', getdate(), getdate()) +GO -- sj_notify_config CREATE TABLE sj_notify_config diff --git a/script/sql/sqlserver/flowable.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql similarity index 100% rename from script/sql/sqlserver/flowable.sql rename to script/sql/sqlserver/sqlserver_ry_workflow.sql