Merge remote-tracking branch 'origin/dev' into warm-flow-future
# Conflicts: # ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java # ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml
This commit is contained in:
commit
58ea6c899f
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.2.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.2.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
|
||||
</settings>
|
||||
|
@ -1,12 +1,12 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="演示机">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-server:5.2.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-server:5.2.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
</component>
|
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-snailjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.2.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.2.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-snailjob-server/Dockerfile" />
|
||||
</settings>
|
||||
|
@ -9,7 +9,7 @@
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
|
||||
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
||||
<br>
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
|
16
pom.xml
16
pom.xml
@ -13,7 +13,7 @@
|
||||
<description>RuoYi-Vue-Plus多租户管理系统</description>
|
||||
|
||||
<properties>
|
||||
<revision>5.2.1</revision>
|
||||
<revision>5.2.2</revision>
|
||||
<spring-boot.version>3.2.9</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
@ -23,7 +23,7 @@
|
||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||
<easyexcel.version>4.0.2</easyexcel.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<satoken.version>1.38.0</satoken.version>
|
||||
<satoken.version>1.39.0</satoken.version>
|
||||
<mybatis-plus.version>3.5.7</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<hutool.version>5.8.31</hutool.version>
|
||||
@ -69,6 +69,8 @@
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>local</profiles.active>
|
||||
<logging.level>info</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
@ -77,6 +79,8 @@
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>dev</profiles.active>
|
||||
<logging.level>info</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
<activation>
|
||||
<!-- 默认环境 -->
|
||||
@ -88,6 +92,8 @@
|
||||
<properties>
|
||||
<profiles.active>prod</profiles.active>
|
||||
<logging.level>warn</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
@ -328,9 +334,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<version>1.26.2</version>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.15.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -14,7 +14,7 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>5.2.1</revision>
|
||||
<revision>5.2.2</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -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 <T> 输入节点的类型
|
||||
* @param <K> 节点ID的类型
|
||||
* @param list 节点列表,其中包含了要构建树形结构的所有节点
|
||||
* @param nodeParser 解析器,用于将输入节点转换为树节点
|
||||
* @return 构建好的树形结构列表
|
||||
*/
|
||||
public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> 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 <K> 节点ID的类型
|
||||
* @param nodes 节点列表
|
||||
* @return 包含所有叶子节点的列表
|
||||
*/
|
||||
public static <K> List<Tree<K>> getLeafNodes(List<Tree<K>> nodes) {
|
||||
if (CollUtil.isEmpty(nodes)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return nodes.stream()
|
||||
.flatMap(TreeBuildUtils::extractLeafNodes)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定节点下的所有叶子节点
|
||||
*
|
||||
* @param <K> 节点ID的类型
|
||||
* @param node 要查找叶子节点的根节点
|
||||
* @return 包含所有叶子节点的列表
|
||||
*/
|
||||
private static <K> Stream<Tree<K>> extractLeafNodes(Tree<K> node) {
|
||||
if (!node.hasChild()) {
|
||||
return Stream.of(node);
|
||||
} else {
|
||||
// 递归调用,获取所有子节点的叶子节点
|
||||
return node.getChildren().stream()
|
||||
.flatMap(TreeBuildUtils::extractLeafNodes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()";
|
||||
|
||||
/**
|
||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||
|
@ -25,11 +25,6 @@
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<version>1.26.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<Void> 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*/
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -64,19 +64,19 @@
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.anyline</groupId>-->
|
||||
<!-- <artifactId>anyline-data-jdbc-oracle</artifactId>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.anyline</groupId>-->
|
||||
<!-- <artifactId>anyline-data-jdbc-postgresql</artifactId>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.anyline</groupId>-->
|
||||
<!-- <artifactId>anyline-data-jdbc-mssql</artifactId>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- <version>${anyline.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
|
@ -162,7 +162,7 @@ public class GenTable extends BaseEntity {
|
||||
* 上级菜单ID字段
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String parentMenuId;
|
||||
private Long parentMenuId;
|
||||
|
||||
/**
|
||||
* 上级菜单名称字段
|
||||
|
@ -137,7 +137,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
||||
}
|
||||
// 过滤并转换表格数据
|
||||
List<GenTable> 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);
|
||||
|
@ -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
|
||||
|
@ -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<Void> syncTenantDict() {
|
||||
if (!TenantHelper.isEnable()) {
|
||||
return R.fail("当前未开启租户模式");
|
||||
}
|
||||
tenantService.syncTenantDict();
|
||||
return R.ok("同步租户字典成功");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SysUserImportVo
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、账号 " + userVo.getUserName() + " 导入失败:";
|
||||
failureMsg.append(msg).append(e.getMessage());
|
||||
String message = e.getMessage();
|
||||
if (e instanceof ConstraintViolationException cvException) {
|
||||
message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
|
||||
}
|
||||
failureMsg.append(msg).append(message);
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
|
@ -79,4 +79,9 @@ public interface ISysTenantService {
|
||||
* 同步租户套餐
|
||||
*/
|
||||
Boolean syncTenantPackage(String tenantId, Long packageId);
|
||||
|
||||
/**
|
||||
* 同步租户字典
|
||||
*/
|
||||
void syncTenantDict();
|
||||
}
|
||||
|
@ -275,6 +275,8 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
|
||||
dept.setAncestors(newAncestors);
|
||||
updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
|
||||
}
|
||||
} else {
|
||||
dept.setAncestors(oldDept.getAncestors());
|
||||
}
|
||||
int result = baseMapper.updateById(dept);
|
||||
if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
|
||||
|
@ -3,18 +3,18 @@ package org.dromara.system.service.impl;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.ip.AddressUtils;
|
||||
import org.dromara.common.log.event.OperLogEvent;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.domain.SysOperLog;
|
||||
import org.dromara.system.domain.bo.SysOperLogBo;
|
||||
import org.dromara.system.domain.vo.SysOperLogVo;
|
||||
import org.dromara.system.mapper.SysOperLogMapper;
|
||||
import org.dromara.system.service.ISysOperLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -51,8 +51,18 @@ public class SysOperLogServiceImpl implements ISysOperLogService {
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysOperLogVo> selectPageOperLogList(SysOperLogBo operLog, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysOperLog> lqw = buildQueryWrapper(operLog);
|
||||
if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
|
||||
pageQuery.setOrderByColumn("oper_id");
|
||||
pageQuery.setIsAsc("desc");
|
||||
}
|
||||
Page<SysOperLogVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<SysOperLog> buildQueryWrapper(SysOperLogBo operLog) {
|
||||
Map<String, Object> params = operLog.getParams();
|
||||
LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>()
|
||||
return new LambdaQueryWrapper<SysOperLog>()
|
||||
.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<SysOperLogVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,23 +99,8 @@ public class SysOperLogServiceImpl implements ISysOperLogService {
|
||||
*/
|
||||
@Override
|
||||
public List<SysOperLogVo> selectOperLogList(SysOperLogBo operLog) {
|
||||
Map<String, Object> params = operLog.getParams();
|
||||
return baseMapper.selectVoList(new LambdaQueryWrapper<SysOperLog>()
|
||||
.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<SysOperLog> lqw = buildQueryWrapper(operLog);
|
||||
return baseMapper.selectVoList(lqw.orderByDesc(SysOperLog::getOperId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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<SysDictType> dictTypeList = new ArrayList<>();
|
||||
List<SysDictData> dictDataList = new ArrayList<>();
|
||||
TenantHelper.ignore(() -> {
|
||||
dictTypeList.addAll(dictTypeMapper.selectList());
|
||||
dictDataList.addAll(dictDataMapper.selectList());
|
||||
});
|
||||
Map<String, List<SysDictType>> typeMap = StreamUtils.groupByKey(dictTypeList, TenantEntity::getTenantId);
|
||||
Map<String, Map<String, List<SysDictData>>> typeDataMap = StreamUtils.groupBy2Key(
|
||||
dictDataList, TenantEntity::getTenantId, SysDictData::getDictType);
|
||||
// 管理租户字典数据
|
||||
List<SysDictType> defaultTypeMap = typeMap.get(TenantConstants.DEFAULT_TENANT_ID);
|
||||
Map<String, List<SysDictData>> defaultTypeDataMap = typeDataMap.get(TenantConstants.DEFAULT_TENANT_ID);
|
||||
|
||||
// 获取所有租户编号
|
||||
List<String> tenantIds = baseMapper.selectObjs(
|
||||
new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId)
|
||||
.eq(SysTenant::getStatus, TenantConstants.NORMAL), x -> {return Convert.toStr(x);});
|
||||
List<SysDictType> saveTypeList = new ArrayList<>();
|
||||
List<SysDictData> saveDataList = new ArrayList<>();
|
||||
Set<String> set = new HashSet<>();
|
||||
for (String tenantId : tenantIds) {
|
||||
if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
|
||||
continue;
|
||||
}
|
||||
for (SysDictType dictType : defaultTypeMap) {
|
||||
List<String> typeList = StreamUtils.toList(typeMap.get(tenantId), SysDictType::getDictType);
|
||||
List<SysDictData> dataList = defaultTypeDataMap.get(dictType.getDictType());
|
||||
if (typeList.contains(dictType.getDictType())) {
|
||||
List<SysDictData> dataListTenant = typeDataMap.get(tenantId).get(dictType.getDictType());
|
||||
Map<String, SysDictData> 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<UserDTO> selectListByIds(List<Long> userIds) {
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
@ -636,28 +643,54 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
||||
List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>()
|
||||
.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<Long> selectUserIdsByRoleIds(List<Long> roleIds) {
|
||||
List<SysUserRole> userRoles = userRoleMapper.selectList(
|
||||
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
|
||||
return StreamUtils.toList(userRoles, SysUserRole::getUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserDTO> selectUsersByRoleIds(List<Long> roleIds) {
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return List.of();
|
||||
}
|
||||
List<SysUserRole> userRoles = userRoleMapper.selectList(
|
||||
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
|
||||
List<Long> userIds = StreamUtils.toList(userRoles, SysUserRole::getUserId);
|
||||
return selectListByIds(userIds);
|
||||
return StreamUtils.toList(userRoles, SysUserRole::getUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过角色ID查询用户
|
||||
*
|
||||
* @param roleIds 角色ids
|
||||
* @return 用户
|
||||
*/
|
||||
@Override
|
||||
public List<UserDTO> selectUsersByRoleIds(List<Long> roleIds) {
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
// 通过角色ID获取用户角色信息
|
||||
List<SysUserRole> userRoles = userRoleMapper.selectList(
|
||||
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
|
||||
|
||||
// 获取用户ID列表
|
||||
Set<Long> userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId);
|
||||
|
||||
return selectListByIds(new ArrayList<>(userIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过部门ID查询用户
|
||||
*
|
||||
* @param deptIds 部门ids
|
||||
* @return 用户
|
||||
*/
|
||||
@Override
|
||||
public List<UserDTO> selectUsersByDeptIds(List<Long> deptIds) {
|
||||
if (CollUtil.isEmpty(deptIds)) {
|
||||
@ -666,7 +699,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
||||
List<SysUserVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<SysUser>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
# 时区上海
|
||||
|
@ -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
|
@ -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
|
@ -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`
|
||||
(
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user