mirror of
https://gitee.com/dromara/RuoYi-Cloud-Plus.git
synced 2025-09-02 18:46:13 +00:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8ed00aed21 | ||
![]() |
c519815fd4 | ||
![]() |
cd3a831213 | ||
![]() |
3b58e0952a | ||
![]() |
61ea1b3354 | ||
![]() |
c39a816689 | ||
![]() |
4ad0969f0a | ||
![]() |
c64410d0ae | ||
![]() |
d37a00497d | ||
![]() |
1ab8750cd5 | ||
![]() |
77dcf4b0d4 | ||
![]() |
af04bc74ed | ||
![]() |
ee7450c0e8 | ||
![]() |
6e7ecc96cb | ||
![]() |
72001f721e | ||
![]() |
d830a7d5cf | ||
![]() |
f50d7e85c0 | ||
![]() |
0aabd18e1c | ||
![]() |
249d7bdcde | ||
![]() |
1c126dc5d3 | ||
![]() |
84f0bc1832 | ||
![]() |
d2f43e7f95 | ||
![]() |
4263ccef62 | ||
![]() |
cf64f2139f | ||
![]() |
17c94cdc1a | ||
![]() |
679c83e837 | ||
![]() |
a9f10e4fa4 | ||
![]() |
a6ab750508 | ||
![]() |
1efe1ac78a | ||
![]() |
cb545862f4 | ||
![]() |
d26147fb61 | ||
![]() |
f26ef3515a | ||
![]() |
ef013bd653 | ||
![]() |
751e86298f | ||
![]() |
6738d68fa4 | ||
![]() |
d97146de98 | ||
![]() |
ca7c0c94f3 | ||
![]() |
6d319b13ad | ||
![]() |
1321a1ec38 | ||
![]() |
6d7fb33ae0 | ||
![]() |
faa9be7e4e | ||
![]() |
36ab89d582 | ||
![]() |
66bda00007 | ||
![]() |
f0ec0811fd | ||
![]() |
a28f05c145 | ||
![]() |
6d7e8e3822 | ||
![]() |
3f0d0ad82b | ||
![]() |
b7835ec5bd | ||
![]() |
1842103a18 | ||
![]() |
66e1767979 |
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-auth" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-auth:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-auth:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-auth/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-gateway" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gateway:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gateway:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-gateway/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-gen" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gen:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gen:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-gen/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-job" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-job:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-job:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-job/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-monitor" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-monitor/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-nacos" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-nacos:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-nacos:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-nacos/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-resource" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-resource:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-resource:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-resource/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-seata-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-seata-server:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-seata-server:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-seata-server/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-sentinel-dashboard" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-sentinel-dashboard:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-sentinel-dashboard:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-sentinel-dashboard/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -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:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-snailjob-server:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-snailjob-server/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-system" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-system:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-system:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-system/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-workflow" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-workflow:2.4.0" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-workflow:2.4.1" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-workflow/Dockerfile" />
|
||||
</settings>
|
||||
|
@@ -10,7 +10,7 @@
|
||||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus/blob/2.X/LICENSE)
|
||||
[](https://www.jetbrains.com/?from=RuoYi-Cloud-Plus)
|
||||
<br>
|
||||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
|
22
pom.xml
22
pom.xml
@@ -13,11 +13,11 @@
|
||||
<description>Dromara RuoYi-Cloud-Plus微服务系统</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.4.0</revision>
|
||||
<revision>2.4.1</revision>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<spring-boot.version>3.4.6</spring-boot.version>
|
||||
<spring-boot.version>3.4.7</spring-boot.version>
|
||||
<spring-cloud.version>2024.0.0</spring-cloud.version>
|
||||
<spring-boot-admin.version>3.4.7</spring-boot-admin.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
@@ -29,14 +29,14 @@
|
||||
<springdoc.version>2.8.8</springdoc.version>
|
||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||
<fastexcel.version>1.2.0</fastexcel.version>
|
||||
<hutool.version>5.8.35</hutool.version>
|
||||
<redisson.version>3.45.1</redisson.version>
|
||||
<hutool.version>5.8.38</hutool.version>
|
||||
<redisson.version>3.50.0</redisson.version>
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<snailjob.version>1.5.0</snailjob.version>
|
||||
<satoken.version>1.42.0</satoken.version>
|
||||
<satoken.version>1.44.0</satoken.version>
|
||||
<lombok.version>1.18.36</lombok.version>
|
||||
<logstash.version>7.4</logstash.version>
|
||||
<easy-es.version>2.1.0</easy-es.version>
|
||||
<easy-es.version>3.0.0</easy-es.version>
|
||||
<skywalking-toolkit.version>9.3.0</skywalking-toolkit.version>
|
||||
<bouncycastle.version>1.80</bouncycastle.version>
|
||||
<mapstruct-plus.version>1.4.8</mapstruct-plus.version>
|
||||
@@ -46,22 +46,20 @@
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<!-- 临时修复 fastjson 漏洞 -->
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
|
||||
<!-- OSS 配置 -->
|
||||
<aws.sdk.version>2.28.22</aws.sdk.version>
|
||||
|
||||
<!-- SMS 配置 -->
|
||||
<sms4j.version>3.3.4</sms4j.version>
|
||||
<!-- 面向运行时的D-ORM依赖 -->
|
||||
<anyline.version>8.7.2-20250101</anyline.version>
|
||||
<anyline.version>8.7.2-20250603</anyline.version>
|
||||
<!-- 工作流配置 -->
|
||||
<warm-flow.version>1.7.3</warm-flow.version>
|
||||
<warm-flow.version>1.7.4</warm-flow.version>
|
||||
<!-- mq配置 -->
|
||||
<rocketmq.version>2.3.0</rocketmq.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
|
||||
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
||||
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
|
||||
<!-- 打包默认跳过测试 -->
|
||||
<skipTests>true</skipTests>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.4.0</revision>
|
||||
<revision>2.4.1</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@@ -22,9 +22,12 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 非必需模块 如果需要跟工作流同步数据 则需要在对应服务内引入bus模块 如果只是调用工作流api则不需要 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-bus</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -103,7 +103,7 @@ public class TokenController {
|
||||
Long userId = LoginHelper.getUserId();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
remoteMessageService.publishMessage(List.of(userId), "欢迎登录RuoYi-Cloud-Plus微服务管理系统");
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
|
@@ -162,7 +162,7 @@ public class UserActionListener implements SaTokenListener {
|
||||
* 每次Token续期时触发
|
||||
*/
|
||||
@Override
|
||||
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||
public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,9 +3,6 @@ package org.dromara.auth.service.impl;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.http.Method;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
@@ -66,15 +63,6 @@ public class SocialAuthStrategy implements IAuthStrategy {
|
||||
throw new ServiceException(response.getMsg());
|
||||
}
|
||||
AuthUser authUserData = response.getData();
|
||||
if ("GITEE".equals(authUserData.getSource())) {
|
||||
// 如用户使用 gitee 登录顺手 star 给作者一点支持 拒绝白嫖
|
||||
HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Vue-Plus")
|
||||
.formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
|
||||
.executeAsync();
|
||||
HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Cloud-Plus")
|
||||
.formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken()))
|
||||
.executeAsync();
|
||||
}
|
||||
|
||||
List<RemoteSocialVo> list = remoteSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
|
@@ -14,14 +14,13 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.4.0</revision>
|
||||
<spring-cloud-alibaba.version>2023.0.1.2</spring-cloud-alibaba.version>
|
||||
<revision>2.4.1</revision>
|
||||
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
|
||||
<sentinel.version>1.8.8</sentinel.version>
|
||||
<seata.version>2.3.0</seata.version>
|
||||
<seata.version>2.4.0</seata.version>
|
||||
<nacos.client.version>2.5.1</nacos.client.version>
|
||||
<dubbo.version>3.3.4</dubbo.version>
|
||||
<dubbo.version>3.3.5</dubbo.version>
|
||||
<dubbo-extensions.version>3.3.1</dubbo-extensions.version>
|
||||
<spring.context.support.version>1.0.11</spring.context.support.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -177,12 +176,6 @@
|
||||
<artifactId>dubbo-metadata-report-redis</artifactId>
|
||||
<version>${dubbo-extensions.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.spring</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${spring.context.support.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
@@ -14,7 +14,7 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.4.0</revision>
|
||||
<revision>2.4.1</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@@ -0,0 +1,84 @@
|
||||
package org.dromara.common.core.utils;
|
||||
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.regex.RegexUtils;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* 增强网络相关工具类
|
||||
*
|
||||
* @author 秋辞未寒
|
||||
*/
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class NetUtils extends NetUtil {
|
||||
|
||||
/**
|
||||
* 判断是否为IPv6地址
|
||||
*
|
||||
* @param ip IP地址
|
||||
* @return 是否为IPv6地址
|
||||
*/
|
||||
public static boolean isIPv6(String ip) {
|
||||
try {
|
||||
// 判断是否为IPv6地址
|
||||
return InetAddress.getByName(ip) instanceof Inet6Address;
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断IPv6地址是否为内网地址
|
||||
* <br><br>
|
||||
* 以下地址将归类为本地地址,如有业务场景有需要,请根据需求自行处理:
|
||||
* <pre>
|
||||
* 通配符地址 0:0:0:0:0:0:0:0
|
||||
* 链路本地地址 fe80::/10
|
||||
* 唯一本地地址 fec0::/10
|
||||
* 环回地址 ::1
|
||||
* </pre>
|
||||
*
|
||||
* @param ip IP地址
|
||||
* @return 是否为内网地址
|
||||
*/
|
||||
public static boolean isInnerIPv6(String ip) {
|
||||
try {
|
||||
// 判断是否为IPv6地址
|
||||
if (InetAddress.getByName(ip) instanceof Inet6Address inet6Address) {
|
||||
// isAnyLocalAddress 判断是否为通配符地址,通常不会将其视为内网地址,根据业务场景自行处理判断
|
||||
// isLinkLocalAddress 判断是否为链路本地地址,通常不算内网地址,是否划分归属于内网需要根据业务场景自行处理判断
|
||||
// isLoopbackAddress 判断是否为环回地址,与IPv4的 127.0.0.1 同理,用于表示本机
|
||||
// isSiteLocalAddress 判断是否为本地站点地址,IPv6唯一本地地址(Unique Local Addresses,简称ULA)
|
||||
if (inet6Address.isAnyLocalAddress()
|
||||
|| inet6Address.isLinkLocalAddress()
|
||||
|| inet6Address.isLoopbackAddress()
|
||||
|| inet6Address.isSiteLocalAddress()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
// 注意,isInnerIPv6方法和isIPv6方法的适用范围不同,所以此处不能忽略其异常信息。
|
||||
throw new IllegalArgumentException("Invalid IPv6 address!", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为IPv4地址
|
||||
*
|
||||
* @param ip IP地址
|
||||
* @return 是否为IPv4地址
|
||||
*/
|
||||
public static boolean isIPv4(String ip) {
|
||||
return RegexUtils.isMatch(PatternPool.IPV4, ip);
|
||||
}
|
||||
|
||||
}
|
@@ -10,6 +10,9 @@ import lombok.NoArgsConstructor;
|
||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -60,6 +63,38 @@ public class TreeBuildUtils extends TreeUtil {
|
||||
return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建多根节点的树结构(支持多个顶级节点)
|
||||
*
|
||||
* @param list 原始数据列表
|
||||
* @param getId 获取节点 ID 的方法引用,例如:node -> node.getId()
|
||||
* @param getParentId 获取节点父级 ID 的方法引用,例如:node -> node.getParentId()
|
||||
* @param parser 树节点属性映射器,用于将原始节点 T 转为 Tree 节点
|
||||
* @param <T> 原始数据类型(如实体类、DTO 等)
|
||||
* @param <K> 节点 ID 类型(如 Long、String)
|
||||
* @return 构建完成的树形结构(可能包含多个顶级根节点)
|
||||
*/
|
||||
public static <T, K> List<Tree<K>> buildMultiRoot(List<T> list, Function<T, K> getId, Function<T, K> getParentId, NodeParser<T, K> parser) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
|
||||
// 提取所有节点 ID,用于后续判断哪些节点为根节点(即 parentId 不在其中)
|
||||
Set<K> allIds = StreamUtils.toSet(list, getId);
|
||||
|
||||
// 筛选出所有 parentId 不在 allIds 中的节点,这些节点的 parentId 可认为是根节点
|
||||
Set<K> rootParentIds = list.stream()
|
||||
.map(getParentId)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(pid -> !allIds.contains(pid))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 使用流处理,遍历每个顶级 parentId,构建对应树,并合并为一个列表返回
|
||||
return rootParentIds.stream()
|
||||
.flatMap(rootParentId -> TreeUtil.build(list, rootParentId, parser).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点列表中所有节点的叶子节点
|
||||
*
|
||||
|
@@ -1,11 +1,11 @@
|
||||
package org.dromara.common.core.utils.ip;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.NetUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 获取地址类
|
||||
@@ -16,18 +16,55 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class AddressUtils {
|
||||
|
||||
// 未知IP
|
||||
public static final String UNKNOWN_IP = "XX XX";
|
||||
// 内网地址
|
||||
public static final String LOCAL_ADDRESS = "内网IP";
|
||||
// 未知地址
|
||||
public static final String UNKNOWN = "XX XX";
|
||||
public static final String UNKNOWN_ADDRESS = "未知";
|
||||
|
||||
public static String getRealAddressByIP(String ip) {
|
||||
if (StringUtils.isBlank(ip)) {
|
||||
return UNKNOWN;
|
||||
// 处理空串并过滤HTML标签
|
||||
ip = HtmlUtil.cleanHtmlTag(StringUtils.blankToDefault(ip,""));
|
||||
// 判断是否为IPv4
|
||||
if (NetUtils.isIPv4(ip)) {
|
||||
return resolverIPv4Region(ip);
|
||||
}
|
||||
// 判断是否为IPv6
|
||||
if (NetUtils.isIPv6(ip)) {
|
||||
return resolverIPv6Region(ip);
|
||||
}
|
||||
// 如果不是IPv4或IPv6,则返回未知IP
|
||||
return UNKNOWN_IP;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IPv4地址查询IP归属行政区域
|
||||
* @param ip ipv4地址
|
||||
* @return 归属行政区域
|
||||
*/
|
||||
private static String resolverIPv4Region(String ip){
|
||||
// 内网不查询
|
||||
ip = StringUtils.contains(ip, "0:0:0:0:0:0:0:1") ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
||||
if (NetUtil.isInnerIP(ip)) {
|
||||
return "内网IP";
|
||||
if (NetUtils.isInnerIP(ip)) {
|
||||
return LOCAL_ADDRESS;
|
||||
}
|
||||
return RegionUtils.getCityInfo(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IPv6地址查询IP归属行政区域
|
||||
* @param ip ipv6地址
|
||||
* @return 归属行政区域
|
||||
*/
|
||||
private static String resolverIPv6Region(String ip){
|
||||
// 内网不查询
|
||||
if (NetUtils.isInnerIPv6(ip)) {
|
||||
return LOCAL_ADDRESS;
|
||||
}
|
||||
log.warn("ip2region不支持IPV6地址解析:{}", ip);
|
||||
// 不支持IPv6,不再进行没有必要的IP地址信息的解析,直接返回
|
||||
// 如有需要,可自行实现IPv6地址信息解析逻辑,并在这里返回
|
||||
return UNKNOWN_ADDRESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.context.dubbo3.filter;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.context.dubbo3.util.SaTokenContextDubbo3Util;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.rpc.*;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 Dubbo3 上下文初始化过滤器
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.42.0
|
||||
*/
|
||||
@Activate(group = {CommonConstants.PROVIDER}, order = SaTokenConsts.RPC_CONTEXT_FILTER_ORDER)
|
||||
public class SaTokenDubbo3ContextFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public Result invoke(Invoker<?> invoker, Invocation invocation) {
|
||||
if(SaHolder.getContext().isValid()) {
|
||||
return invoker.invoke(invocation);
|
||||
} else {
|
||||
try {
|
||||
SaTokenContextDubbo3Util.setContext(RpcContext.getServiceContext());
|
||||
return invoker.invoke(invocation);
|
||||
} finally {
|
||||
SaManager.getSaTokenContext().clearContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
package org.dromara.easyes.spring.config;
|
||||
|
||||
import lombok.Setter;
|
||||
import org.dromara.easyes.common.property.EasyEsDynamicProperties;
|
||||
import org.dromara.easyes.common.property.EasyEsProperties;
|
||||
import org.dromara.easyes.common.strategy.AutoProcessIndexStrategy;
|
||||
import org.dromara.easyes.common.utils.RestHighLevelClientUtils;
|
||||
import org.dromara.easyes.core.index.AutoProcessIndexNotSmoothlyStrategy;
|
||||
import org.dromara.easyes.core.index.AutoProcessIndexSmoothlyStrategy;
|
||||
import org.dromara.easyes.spring.factory.IndexStrategyFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
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;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author MoJie
|
||||
* @since 2.0
|
||||
*/
|
||||
@Setter
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "easy-es.enable", havingValue = "true")
|
||||
public class EasyEsConfiguration implements InitializingBean {
|
||||
|
||||
private EasyEsProperties easyEsProperties;
|
||||
|
||||
private EasyEsDynamicProperties easyEsDynamicProperties;
|
||||
|
||||
@Autowired
|
||||
public EasyEsConfiguration(EasyEsProperties easyEsProperties, EasyEsDynamicProperties easyEsDynamicProperties) {
|
||||
this.easyEsProperties = easyEsProperties;
|
||||
this.easyEsDynamicProperties = easyEsDynamicProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.easyEsProperties, "easyEsProperties must is A bean. easy-es配置类必须给配置一个bean");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IndexStrategyFactory indexStrategyFactory() {
|
||||
return new IndexStrategyFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestHighLevelClientUtils restHighLevelClientUtils() {
|
||||
RestHighLevelClientUtils restHighLevelClientUtils = new RestHighLevelClientUtils();
|
||||
if (this.easyEsDynamicProperties == null) {
|
||||
this.easyEsDynamicProperties = new EasyEsDynamicProperties();
|
||||
}
|
||||
Map<String, EasyEsProperties> datasourceMap = this.easyEsDynamicProperties.getDatasource();
|
||||
if (datasourceMap.isEmpty()) {
|
||||
// 设置默认数据源,兼容不使用多数据源配置场景的老用户使用习惯
|
||||
datasourceMap.put(RestHighLevelClientUtils.DEFAULT_DS, this.easyEsProperties);
|
||||
}
|
||||
for (String key : datasourceMap.keySet()) {
|
||||
EasyEsProperties easyEsConfigProperties = datasourceMap.get(key);
|
||||
RestHighLevelClientUtils.registerRestHighLevelClient(key, RestHighLevelClientUtils
|
||||
.restHighLevelClient(easyEsConfigProperties));
|
||||
}
|
||||
return restHighLevelClientUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* 索引策略注册
|
||||
*
|
||||
* @return {@link AutoProcessIndexStrategy}
|
||||
* @author MoJie
|
||||
*/
|
||||
@Bean
|
||||
public AutoProcessIndexStrategy autoProcessIndexSmoothlyStrategy() {
|
||||
return new AutoProcessIndexSmoothlyStrategy();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AutoProcessIndexStrategy autoProcessIndexNotSmoothlyStrategy() {
|
||||
return new AutoProcessIndexNotSmoothlyStrategy();
|
||||
}
|
||||
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
package org.dromara.easyes.starter.config;
|
||||
|
||||
import org.dromara.easyes.core.config.GeneratorConfig;
|
||||
import org.dromara.easyes.core.toolkit.Generator;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 代码生成注册
|
||||
* @author MoJie
|
||||
* @since 2.0
|
||||
*/
|
||||
@Component
|
||||
@ConditionalOnProperty(value = "easy-es.enable", havingValue = "true")
|
||||
public class GeneratorConfiguration extends Generator {
|
||||
|
||||
@Autowired
|
||||
private RestHighLevelClient client;
|
||||
|
||||
@Override
|
||||
public Boolean generate(GeneratorConfig config) {
|
||||
super.generateEntity(config, this.client);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
||||
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
@@ -39,12 +40,23 @@ public class MybatisDecryptInterceptor implements Interceptor {
|
||||
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
// 开始进行参数解密
|
||||
ResultSetHandler resultSetHandler = (ResultSetHandler) invocation.getTarget();
|
||||
Field parameterHandlerField = resultSetHandler.getClass().getDeclaredField("parameterHandler");
|
||||
parameterHandlerField.setAccessible(true);
|
||||
Object target = parameterHandlerField.get(resultSetHandler);
|
||||
if (target instanceof ParameterHandler parameterHandler) {
|
||||
Object parameterObject = parameterHandler.getParameterObject();
|
||||
if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) {
|
||||
this.decryptHandler(parameterObject);
|
||||
}
|
||||
}
|
||||
// 获取执行mysql执行结果
|
||||
Object result = invocation.proceed();
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
decryptHandler(result);
|
||||
this.decryptHandler(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -13,10 +13,6 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ExcelNotation {
|
||||
|
||||
/**
|
||||
* col index
|
||||
*/
|
||||
int index() default -1;
|
||||
/**
|
||||
* 批注内容
|
||||
*/
|
||||
|
@@ -15,10 +15,6 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ExcelRequired {
|
||||
|
||||
/**
|
||||
* col index
|
||||
*/
|
||||
int index() default -1;
|
||||
/**
|
||||
* 字体颜色
|
||||
*/
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package org.dromara.common.excel.handler;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import cn.idev.excel.metadata.data.DataFormatData;
|
||||
import cn.idev.excel.metadata.data.WriteCellData;
|
||||
import cn.idev.excel.util.StyleUtil;
|
||||
@@ -13,7 +14,6 @@ import cn.idev.excel.write.metadata.style.WriteFont;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||
import org.dromara.common.excel.annotation.ExcelNotation;
|
||||
import org.dromara.common.excel.annotation.ExcelRequired;
|
||||
|
||||
@@ -31,12 +31,12 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
|
||||
/**
|
||||
* 批注
|
||||
*/
|
||||
private final Map<Integer, String> notationMap;
|
||||
private final Map<String, String> notationMap;
|
||||
|
||||
/**
|
||||
* 头列字体颜色
|
||||
*/
|
||||
private final Map<Integer, Short> headColumnMap;
|
||||
private final Map<String, Short> headColumnMap;
|
||||
|
||||
|
||||
public DataWriteHandler(Class<?> clazz) {
|
||||
@@ -49,15 +49,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
|
||||
if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) {
|
||||
return;
|
||||
}
|
||||
// 第一行
|
||||
WriteCellData<?> cellData = context.getFirstCellData();
|
||||
// 第一个格子
|
||||
WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
|
||||
|
||||
DataFormatData dataFormatData = new DataFormatData();
|
||||
// 单元格设置为文本格式
|
||||
dataFormatData.setIndex((short) 49);
|
||||
writeCellStyle.setDataFormatData(dataFormatData);
|
||||
|
||||
if (context.getHead()) {
|
||||
DataFormatData dataFormatData = new DataFormatData();
|
||||
// 单元格设置为文本格式
|
||||
dataFormatData.setIndex((short) 49);
|
||||
writeCellStyle.setDataFormatData(dataFormatData);
|
||||
Cell cell = context.getCell();
|
||||
WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
@@ -67,17 +68,17 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
|
||||
WriteFont headWriteFont = new WriteFont();
|
||||
// 加粗
|
||||
headWriteFont.setBold(true);
|
||||
if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getColumnIndex())) {
|
||||
if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getStringCellValue())) {
|
||||
// 设置字体颜色
|
||||
headWriteFont.setColor(headColumnMap.get(cell.getColumnIndex()));
|
||||
headWriteFont.setColor(headColumnMap.get(cell.getStringCellValue()));
|
||||
}
|
||||
writeCellStyle.setWriteFont(headWriteFont);
|
||||
CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle);
|
||||
cell.setCellStyle(cellStyle);
|
||||
|
||||
if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getColumnIndex())) {
|
||||
if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getStringCellValue())) {
|
||||
// 批注内容
|
||||
String notationContext = notationMap.get(cell.getColumnIndex());
|
||||
String notationContext = notationMap.get(cell.getStringCellValue());
|
||||
// 创建绘图对象
|
||||
Comment comment = drawing.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), 0, (short) 5, 5));
|
||||
comment.setString(new XSSFRichTextString(notationContext));
|
||||
@@ -89,23 +90,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
|
||||
/**
|
||||
* 获取必填列
|
||||
*/
|
||||
private static Map<Integer, Short> getRequiredMap(Class<?> clazz) {
|
||||
Map<Integer, Short> requiredMap = new HashMap<>();
|
||||
private static Map<String, Short> getRequiredMap(Class<?> clazz) {
|
||||
Map<String, Short> requiredMap = new HashMap<>();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
// 检查 fields 数组是否为空
|
||||
if (fields.length == 0) {
|
||||
return requiredMap;
|
||||
}
|
||||
Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName()));
|
||||
|
||||
for (int i = 0; i < filteredFields.length; i++) {
|
||||
Field field = filteredFields[i];
|
||||
for (Field field : fields) {
|
||||
if (!field.isAnnotationPresent(ExcelRequired.class)) {
|
||||
continue;
|
||||
}
|
||||
ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class);
|
||||
int columnIndex = excelRequired.index() == -1 ? i : excelRequired.index();
|
||||
requiredMap.put(columnIndex, excelRequired.fontColor().getIndex());
|
||||
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||
requiredMap.put(excelProperty.value()[0], excelRequired.fontColor().getIndex());
|
||||
}
|
||||
return requiredMap;
|
||||
}
|
||||
@@ -113,22 +107,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler {
|
||||
/**
|
||||
* 获取批注
|
||||
*/
|
||||
private static Map<Integer, String> getNotationMap(Class<?> clazz) {
|
||||
Map<Integer, String> notationMap = new HashMap<>();
|
||||
private static Map<String, String> getNotationMap(Class<?> clazz) {
|
||||
Map<String, String> notationMap = new HashMap<>();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
// 检查 fields 数组是否为空
|
||||
if (fields.length == 0) {
|
||||
return notationMap;
|
||||
}
|
||||
Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName()));
|
||||
for (int i = 0; i < filteredFields.length; i++) {
|
||||
Field field = filteredFields[i];
|
||||
for (Field field : fields) {
|
||||
if (!field.isAnnotationPresent(ExcelNotation.class)) {
|
||||
continue;
|
||||
}
|
||||
ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class);
|
||||
int columnIndex = excelNotation.index() == -1 ? i : excelNotation.index();
|
||||
notationMap.put(columnIndex, excelNotation.value());
|
||||
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||
notationMap.put(excelProperty.value()[0], excelNotation.value());
|
||||
}
|
||||
return notationMap;
|
||||
}
|
||||
|
@@ -21,6 +21,11 @@ import java.util.Date;
|
||||
@Slf4j
|
||||
public class InjectionMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
/**
|
||||
* 如果用户不存在默认注入-1代表无用户
|
||||
*/
|
||||
private static final Long DEFAULT_USER_ID = -1L;
|
||||
|
||||
/**
|
||||
* 插入填充方法,用于在插入数据时自动填充实体对象中的创建时间、更新时间、创建人、更新人等信息
|
||||
*
|
||||
@@ -44,6 +49,11 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
|
||||
baseEntity.setCreateBy(userId);
|
||||
baseEntity.setUpdateBy(userId);
|
||||
baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), loginUser.getDeptId()));
|
||||
} else {
|
||||
// 填充创建人、更新人和创建部门信息
|
||||
baseEntity.setCreateBy(DEFAULT_USER_ID);
|
||||
baseEntity.setUpdateBy(DEFAULT_USER_ID);
|
||||
baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), DEFAULT_USER_ID));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -73,6 +83,8 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
|
||||
Long userId = LoginHelper.getUserId();
|
||||
if (ObjectUtil.isNotNull(userId)) {
|
||||
baseEntity.setUpdateBy(userId);
|
||||
} else {
|
||||
baseEntity.setUpdateBy(DEFAULT_USER_ID);
|
||||
}
|
||||
} else {
|
||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
||||
@@ -92,7 +104,6 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
|
||||
try {
|
||||
loginUser = LoginHelper.getLoginUser();
|
||||
} catch (Exception e) {
|
||||
log.warn("自动注入警告 => 用户未登录");
|
||||
return null;
|
||||
}
|
||||
return loginUser;
|
||||
|
@@ -87,11 +87,14 @@ public class DataPermissionHelper {
|
||||
* @throws NullPointerException 如果数据权限上下文类型异常,则抛出NullPointerException
|
||||
*/
|
||||
public static Map<String, Object> getContext() {
|
||||
SaStorage saStorage = SaHolder.getStorage();
|
||||
Object attribute = saStorage.get(DATA_PERMISSION_KEY);
|
||||
if (ObjectUtil.isNull(attribute)) {
|
||||
saStorage.set(DATA_PERMISSION_KEY, new HashMap<>());
|
||||
Object attribute = new HashMap<>();
|
||||
if (SaHolder.getContext().isValid()) {
|
||||
SaStorage saStorage = SaHolder.getStorage();
|
||||
attribute = saStorage.get(DATA_PERMISSION_KEY);
|
||||
if (ObjectUtil.isNull(attribute)) {
|
||||
saStorage.set(DATA_PERMISSION_KEY, new HashMap<>());
|
||||
attribute = saStorage.get(DATA_PERMISSION_KEY);
|
||||
}
|
||||
}
|
||||
if (attribute instanceof Map map) {
|
||||
return map;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package org.dromara.common.seata.config;
|
||||
|
||||
import org.dromara.common.core.factory.YmlPropertySourceFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
/**
|
||||
* seata 配置
|
||||
@@ -10,7 +8,6 @@ import org.springframework.context.annotation.PropertySource;
|
||||
* @author Lion Li
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@PropertySource(value = "classpath:common-seata.yml", factory = YmlPropertySourceFactory.class)
|
||||
public class SeataConfiguration {
|
||||
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
# 内置配置 不允许修改 如需修改请在 nacos 上写相同配置覆盖
|
||||
# seata配置
|
||||
seata:
|
||||
config:
|
||||
type: nacos
|
||||
nacos:
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
group: ${spring.cloud.nacos.config.group}
|
||||
namespace: ${spring.profiles.active}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
data-id: seata-server.properties
|
||||
registry:
|
||||
type: nacos
|
||||
nacos:
|
||||
application: ruoyi-seata-server
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
group: ${spring.cloud.nacos.discovery.group}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
namespace: ${spring.profiles.active}
|
||||
# 关闭自动代理
|
||||
enable-auto-data-source-proxy: false
|
@@ -0,0 +1,153 @@
|
||||
package me.zhyd.oauth.request;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import me.zhyd.oauth.config.AuthConfig;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.enums.AuthResponseStatus;
|
||||
import me.zhyd.oauth.enums.AuthUserGender;
|
||||
import me.zhyd.oauth.exception.AuthException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.utils.HttpUtils;
|
||||
import me.zhyd.oauth.utils.StringUtils;
|
||||
import me.zhyd.oauth.utils.UrlBuilder;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 企业微信登录父类
|
||||
* </p>
|
||||
*
|
||||
* @author liguanhua (347826496(a)qq.com)
|
||||
* @since 1.15.9
|
||||
*/
|
||||
public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultRequest {
|
||||
|
||||
public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source) {
|
||||
super(config,source);
|
||||
}
|
||||
|
||||
|
||||
public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) {
|
||||
super(config, source, authStateCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthToken getAccessToken(AuthCallback authCallback) {
|
||||
String response = doGetAuthorizationCode(accessTokenUrl(null));
|
||||
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
return AuthToken.builder()
|
||||
.accessToken(object.getString("access_token"))
|
||||
.expireIn(object.getIntValue("expires_in"))
|
||||
.code(authCallback.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthUser getUserInfo(AuthToken authToken) {
|
||||
String response = doGetUserInfo(authToken);
|
||||
JSONObject object = this.checkResponse(response);
|
||||
|
||||
// 返回 OpenId 或其他,均代表非当前企业用户,不支持
|
||||
if (!object.containsKey("UserId")) {
|
||||
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source);
|
||||
}
|
||||
String userId = object.getString("UserId");
|
||||
String userTicket = object.getString("user_ticket");
|
||||
JSONObject userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket);
|
||||
|
||||
return AuthUser.builder()
|
||||
.rawUserInfo(userDetail)
|
||||
.username(userDetail.getString("name"))
|
||||
.nickname(userDetail.getString("alias"))
|
||||
.avatar(userDetail.getString("avatar"))
|
||||
.location(userDetail.getString("address"))
|
||||
.email(userDetail.getString("email"))
|
||||
.uuid(userId)
|
||||
.gender(AuthUserGender.getWechatRealGender(userDetail.getString("gender")))
|
||||
.token(authToken)
|
||||
.source(source.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验请求结果
|
||||
*
|
||||
* @param response 请求结果
|
||||
* @return 如果请求结果正常,则返回JSONObject
|
||||
*/
|
||||
private JSONObject checkResponse(String response) {
|
||||
JSONObject object = JSONObject.parseObject(response);
|
||||
|
||||
if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
|
||||
throw new AuthException(object.getString("errmsg"), source);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回获取accessToken的url
|
||||
*
|
||||
* @param code 授权码
|
||||
* @return 返回获取accessToken的url
|
||||
*/
|
||||
@Override
|
||||
protected String accessTokenUrl(String code) {
|
||||
return UrlBuilder.fromBaseUrl(source.accessToken())
|
||||
.queryParam("corpid", config.getClientId())
|
||||
.queryParam("corpsecret", config.getClientSecret())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回获取userInfo的url
|
||||
*
|
||||
* @param authToken 用户授权后的token
|
||||
* @return 返回获取userInfo的url
|
||||
*/
|
||||
@Override
|
||||
protected String userInfoUrl(AuthToken authToken) {
|
||||
return UrlBuilder.fromBaseUrl(source.userInfo())
|
||||
.queryParam("access_token", authToken.getAccessToken())
|
||||
.queryParam("code", authToken.getCode())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户详情
|
||||
*
|
||||
* @param accessToken accessToken
|
||||
* @param userId 企业内用户id
|
||||
* @param userTicket 成员票据,用于获取用户信息或敏感信息
|
||||
* @return 用户详情
|
||||
*/
|
||||
private JSONObject getUserDetail(String accessToken, String userId, String userTicket) {
|
||||
// 用户基础信息
|
||||
String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
|
||||
.queryParam("access_token", accessToken)
|
||||
.queryParam("userid", userId)
|
||||
.build();
|
||||
String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
|
||||
JSONObject userInfo = checkResponse(userInfoResponse);
|
||||
|
||||
// 用户敏感信息
|
||||
if (StringUtils.isNotEmpty(userTicket)) {
|
||||
String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail")
|
||||
.queryParam("access_token", accessToken)
|
||||
.build();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("user_ticket", userTicket);
|
||||
String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, param.toJSONString()).getBody();
|
||||
JSONObject userDetail = checkResponse(userDetailResponse);
|
||||
|
||||
userInfo.putAll(userDetail);
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -38,8 +38,8 @@ public class SseEmitterManager {
|
||||
// 每个用户可以有多个 SSE 连接,通过 token 进行区分
|
||||
Map<String, SseEmitter> emitters = USER_TOKEN_EMITTERS.computeIfAbsent(userId, k -> new ConcurrentHashMap<>());
|
||||
|
||||
// 创建一个新的 SseEmitter 实例,超时时间设置为 0 表示无限制
|
||||
SseEmitter emitter = new SseEmitter(0L);
|
||||
// 创建一个新的 SseEmitter 实例,超时时间设置为一天 避免连接之后直接关闭浏览器导致连接停滞
|
||||
SseEmitter emitter = new SseEmitter(86400000L);
|
||||
|
||||
emitters.put(token, emitter);
|
||||
|
||||
|
@@ -48,7 +48,7 @@ public class PlusTenantLineHandler implements TenantLineHandler {
|
||||
"gen_table_column"
|
||||
);
|
||||
tables.addAll(excludes);
|
||||
return StringUtils.containsAnyIgnoreCase(tableName, tables.toArray(new String[0]));
|
||||
return StringUtils.equalsAnyIgnoreCase(tableName, tables.toArray(new String[0]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,12 +1,17 @@
|
||||
package org.dromara.common.web.config;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.web.handler.GlobalExceptionHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 通用配置
|
||||
*
|
||||
@@ -20,6 +25,17 @@ public class ResourcesConfig implements WebMvcConfigurer {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
// 全局日期格式转换配置
|
||||
registry.addConverter(String.class, Date.class, source -> {
|
||||
if (StringUtils.isBlank(source)) {
|
||||
return null;
|
||||
}
|
||||
return DateUtil.parse(source);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
}
|
||||
|
@@ -58,4 +58,9 @@ public class TestDemoBo extends BaseEntity {
|
||||
@NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private Long version;
|
||||
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package org.dromara.demo.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import cn.idev.excel.annotation.format.DateTimeFormat;
|
||||
import org.dromara.common.excel.annotation.ExcelNotation;
|
||||
import org.dromara.common.excel.annotation.ExcelRequired;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
@@ -46,7 +47,7 @@ public class TestDemoVo implements Serializable {
|
||||
* 用户id
|
||||
*/
|
||||
@ExcelRequired
|
||||
@ExcelProperty(value = "用户id")
|
||||
@ExcelProperty(value = "用户id", index = 5)
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
@@ -73,6 +74,8 @@ public class TestDemoVo implements Serializable {
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelRequired
|
||||
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@@ -108,4 +111,9 @@ public class TestDemoVo implements Serializable {
|
||||
@ExcelProperty(value = "更新人账号")
|
||||
private String updateByName;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private Long version;
|
||||
|
||||
}
|
||||
|
@@ -77,6 +77,8 @@ spring:
|
||||
easy-es:
|
||||
# 是否开启EE自动配置
|
||||
enable: false
|
||||
# 兼容模式
|
||||
compatible: true
|
||||
# es连接地址+端口 格式必须为ip:port,如果是集群则可用逗号隔开
|
||||
address : localhost:9200
|
||||
# 默认为http
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -80,11 +80,8 @@ public class GenController extends BaseController {
|
||||
@SaCheckPermission("tool:gen:list")
|
||||
@GetMapping(value = "/column/{tableId}")
|
||||
public TableDataInfo<GenTableColumn> columnList(@PathVariable("tableId") Long tableId) {
|
||||
TableDataInfo<GenTableColumn> dataInfo = new TableDataInfo<>();
|
||||
List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
|
||||
dataInfo.setRows(list);
|
||||
dataInfo.setTotal(list.size());
|
||||
return dataInfo;
|
||||
return TableDataInfo.build(list);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -297,13 +297,13 @@ public class GenTableServiceImpl implements IGenTableService {
|
||||
List<GenTableColumn> tableColumns = new ArrayList<>();
|
||||
columns.forEach((columnName, column) -> {
|
||||
GenTableColumn tableColumn = new GenTableColumn();
|
||||
tableColumn.setIsPk(String.valueOf(column.isPrimaryKey()));
|
||||
tableColumn.setIsPk(column.isPrimaryKey() ? "1" : "0");
|
||||
tableColumn.setColumnName(column.getName());
|
||||
tableColumn.setColumnComment(column.getComment());
|
||||
tableColumn.setColumnType(column.getOriginType().toLowerCase());
|
||||
tableColumn.setSort(column.getPosition());
|
||||
tableColumn.setIsRequired(column.isNullable() == 0 ? "1" : "0");
|
||||
tableColumn.setIsIncrement(column.isAutoIncrement() == -1 ? "0" : "1");
|
||||
tableColumn.setIsRequired(column.isNullable() ? "1" : "0");
|
||||
tableColumn.setIsIncrement(column.isAutoIncrement() ? "1" : "0");
|
||||
tableColumns.add(tableColumn);
|
||||
});
|
||||
return tableColumns;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -6,6 +6,7 @@ import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.redisson.spring.data.connection.RedissonConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.core.RedisConnectionUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -31,21 +32,25 @@ public class CacheController {
|
||||
@GetMapping()
|
||||
public R<CacheListInfoVo> getInfo() throws Exception {
|
||||
RedisConnection connection = connectionFactory.getConnection();
|
||||
Properties commandStats = connection.commands().info("commandstats");
|
||||
|
||||
List<Map<String, String>> pieList = new ArrayList<>();
|
||||
if (commandStats != null) {
|
||||
commandStats.stringPropertyNames().forEach(key -> {
|
||||
Map<String, String> data = new HashMap<>(2);
|
||||
String property = commandStats.getProperty(key);
|
||||
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
|
||||
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
|
||||
pieList.add(data);
|
||||
});
|
||||
try {
|
||||
Properties commandStats = connection.commands().info("commandstats");
|
||||
List<Map<String, String>> pieList = new ArrayList<>();
|
||||
if (commandStats != null) {
|
||||
commandStats.stringPropertyNames().forEach(key -> {
|
||||
Map<String, String> data = new HashMap<>(2);
|
||||
String property = commandStats.getProperty(key);
|
||||
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
|
||||
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
|
||||
pieList.add(data);
|
||||
});
|
||||
}
|
||||
return R.ok(new CacheListInfoVo(
|
||||
connection.commands().info(),
|
||||
connection.commands().dbSize(), pieList));
|
||||
} finally {
|
||||
// 归还连接给连接池
|
||||
RedisConnectionUtils.releaseConnection(connection, connectionFactory);
|
||||
}
|
||||
return R.ok(new CacheListInfoVo(
|
||||
connection.commands().info(),
|
||||
connection.commands().dbSize(), pieList));
|
||||
}
|
||||
|
||||
public record CacheListInfoVo(Properties info, Long dbSize, List<Map<String, String>> commandStats) {}
|
||||
|
@@ -16,6 +16,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -120,7 +122,7 @@ public class SysConfigController extends BaseController {
|
||||
@Log(title = "参数管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{configIds}")
|
||||
public R<Void> remove(@PathVariable Long[] configIds) {
|
||||
configService.deleteConfigByIds(configIds);
|
||||
configService.deleteConfigByIds(Arrays.asList(configIds));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -117,7 +118,7 @@ public class SysDictDataController extends BaseController {
|
||||
@Log(title = "字典类型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{dictCodes}")
|
||||
public R<Void> remove(@PathVariable Long[] dictCodes) {
|
||||
dictDataService.deleteDictDataByIds(dictCodes);
|
||||
dictDataService.deleteDictDataByIds(Arrays.asList(dictCodes));
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -99,7 +101,7 @@ public class SysDictTypeController extends BaseController {
|
||||
@Log(title = "字典类型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{dictIds}")
|
||||
public R<Void> remove(@PathVariable Long[] dictIds) {
|
||||
dictTypeService.deleteDictTypeByIds(dictIds);
|
||||
dictTypeService.deleteDictTypeByIds(Arrays.asList(dictIds));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@ import org.dromara.system.service.ISysMenuService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -111,9 +112,14 @@ public class SysMenuController extends BaseController {
|
||||
@GetMapping(value = "/tenantPackageMenuTreeselect/{packageId}")
|
||||
public R<MenuTreeSelectVo> tenantPackageMenuTreeselect(@PathVariable("packageId") Long packageId) {
|
||||
List<SysMenuVo> menus = menuService.selectMenuList(LoginHelper.getUserId());
|
||||
MenuTreeSelectVo selectVo = new MenuTreeSelectVo(
|
||||
menuService.selectMenuListByPackageId(packageId),
|
||||
menuService.buildMenuTreeSelect(menus));
|
||||
List<Tree<Long>> list = menuService.buildMenuTreeSelect(menus);
|
||||
// 删除租户管理菜单
|
||||
list.removeIf(menu -> menu.getId() == 6L);
|
||||
List<Long> ids = new ArrayList<>();
|
||||
if (packageId > 0L) {
|
||||
ids = menuService.selectMenuListByPackageId(packageId);
|
||||
}
|
||||
MenuTreeSelectVo selectVo = new MenuTreeSelectVo(ids, list);
|
||||
return R.ok(selectVo);
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ package org.dromara.system.dubbo;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.dromara.common.core.constant.SystemConstants;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.api.RemoteTaskAssigneeService;
|
||||
@@ -53,6 +54,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
|
||||
SysRoleBo bo = new SysRoleBo();
|
||||
bo.setRoleKey(taskQuery.getHandlerCode());
|
||||
bo.setRoleName(taskQuery.getHandlerName());
|
||||
bo.setStatus(SystemConstants.NORMAL);
|
||||
Map<String, Object> params = bo.getParams();
|
||||
params.put("beginTime", taskQuery.getBeginTime());
|
||||
params.put("endTime", taskQuery.getEndTime());
|
||||
@@ -75,6 +77,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
|
||||
SysPostBo bo = new SysPostBo();
|
||||
bo.setPostCategory(taskQuery.getHandlerCode());
|
||||
bo.setPostName(taskQuery.getHandlerName());
|
||||
bo.setStatus(SystemConstants.NORMAL);
|
||||
Map<String, Object> params = bo.getParams();
|
||||
params.put("beginTime", taskQuery.getBeginTime());
|
||||
params.put("endTime", taskQuery.getEndTime());
|
||||
@@ -98,6 +101,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
|
||||
SysDeptBo bo = new SysDeptBo();
|
||||
bo.setDeptCategory(taskQuery.getHandlerCode());
|
||||
bo.setDeptName(taskQuery.getHandlerName());
|
||||
bo.setStatus(SystemConstants.NORMAL);
|
||||
Map<String, Object> params = bo.getParams();
|
||||
params.put("beginTime", taskQuery.getBeginTime());
|
||||
params.put("endTime", taskQuery.getEndTime());
|
||||
@@ -109,7 +113,6 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
|
||||
return new RemoteTaskAssigneeVo(page.getTotal(), handlers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询用户并返回任务指派的列表,支持分页
|
||||
*
|
||||
@@ -122,6 +125,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
|
||||
SysUserBo bo = new SysUserBo();
|
||||
bo.setUserName(taskQuery.getHandlerCode());
|
||||
bo.setNickName(taskQuery.getHandlerName());
|
||||
bo.setStatus(SystemConstants.NORMAL);
|
||||
Map<String, Object> params = bo.getParams();
|
||||
params.put("beginTime", taskQuery.getBeginTime());
|
||||
params.put("endTime", taskQuery.getEndTime());
|
||||
|
@@ -312,7 +312,10 @@ public class RemoteUserServiceImpl implements RemoteUserService {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<SysUserVo> list = userMapper.selectVoList(new LambdaQueryWrapper<SysUser>()
|
||||
.select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber)
|
||||
.select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUserName,
|
||||
SysUser::getNickName, SysUser::getUserType, SysUser::getEmail,
|
||||
SysUser::getPhonenumber, SysUser::getSex, SysUser::getStatus,
|
||||
SysUser::getCreateTime)
|
||||
.eq(SysUser::getStatus, SystemConstants.NORMAL)
|
||||
.in(SysUser::getUserId, userIds));
|
||||
return MapstructUtils.convert(list, RemoteUserVo.class);
|
||||
|
@@ -2,7 +2,6 @@ package org.dromara.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.common.mybatis.annotation.DataColumn;
|
||||
@@ -30,19 +29,22 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "dept_id")
|
||||
})
|
||||
List<SysDeptVo> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
|
||||
|
||||
default List<SysDeptVo> selectDeptList(Wrapper<SysDept> queryWrapper) {
|
||||
return this.selectVoList(queryWrapper);
|
||||
}
|
||||
/**
|
||||
* 分页查询部门管理数据
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 部门信息集合
|
||||
*/
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
})
|
||||
Page<SysDeptVo> selectPageDeptList(@Param("page") Page<SysDeptVo> page, @Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
|
||||
|
||||
default Page<SysDeptVo> selectPageDeptList(Page<SysDept> page, Wrapper<SysDept> queryWrapper) {
|
||||
return this.selectVoPage(page, queryWrapper);
|
||||
}
|
||||
/**
|
||||
* 统计指定部门ID的部门数量
|
||||
*
|
||||
@@ -52,8 +54,9 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "dept_id")
|
||||
})
|
||||
long countDeptById(Long deptId);
|
||||
|
||||
default long countDeptById(Long deptId) {
|
||||
return this.selectCount(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptId, deptId));
|
||||
}
|
||||
/**
|
||||
* 根据父部门ID查询其所有子部门的列表
|
||||
*
|
||||
|
@@ -1,9 +1,7 @@
|
||||
package org.dromara.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.common.mybatis.annotation.DataColumn;
|
||||
import org.dromara.common.mybatis.annotation.DataPermission;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
@@ -23,7 +21,9 @@ public interface SysPostMapper extends BaseMapperPlus<SysPost, SysPostVo> {
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
@DataColumn(key = "userName", value = "create_by")
|
||||
})
|
||||
Page<SysPostVo> selectPagePostList(@Param("page") Page<SysPostVo> page, @Param(Constants.WRAPPER) Wrapper<SysPost> queryWrapper);
|
||||
default Page<SysPostVo> selectPagePostList(Page<SysPost> page, Wrapper<SysPost> queryWrapper) {
|
||||
return this.selectVoPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户所属岗位组
|
||||
|
@@ -16,12 +16,11 @@ public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenu, SysRoleMe
|
||||
/**
|
||||
* 根据菜单ID串删除关联关系
|
||||
*
|
||||
* @param menuIds 菜单ID串
|
||||
* @return 结果
|
||||
*/
|
||||
default int deleteByMenuIds(List<Long> menuIds) {
|
||||
LambdaUpdateWrapper<SysRoleMenu> lqw = new LambdaUpdateWrapper<SysRoleMenu>()
|
||||
.in(SysRoleMenu::getMenuId, menuIds);
|
||||
return this.delete(lqw);
|
||||
return this.delete(new LambdaUpdateWrapper<SysRoleMenu>().in(SysRoleMenu::getMenuId, menuIds));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package org.dromara.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -21,16 +22,20 @@ import java.util.List;
|
||||
public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
|
||||
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "u.dept_id"),
|
||||
@DataColumn(key = "userName", value = "u.user_id")
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
@DataColumn(key = "userName", value = "user_id")
|
||||
})
|
||||
Page<SysUserVo> selectPageUserList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
|
||||
default Page<SysUserVo> selectPageUserList(Page<SysUser> page, Wrapper<SysUser> queryWrapper) {
|
||||
return this.selectVoPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
@DataColumn(key = "userName", value = "user_id")
|
||||
})
|
||||
List<SysUserVo> selectUserList(@Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
|
||||
default List<SysUserVo> selectUserList(Wrapper<SysUser> queryWrapper) {
|
||||
return this.selectVoList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件分页查询用户列表
|
||||
@@ -47,6 +52,7 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
|
||||
/**
|
||||
* 根据条件分页查询已配用户角色列表
|
||||
*
|
||||
* @param page 分页信息
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
@@ -72,7 +78,9 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
@DataColumn(key = "userName", value = "user_id")
|
||||
})
|
||||
long countUserById(Long userId);
|
||||
default long countUserById(Long userId) {
|
||||
return this.selectCount(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId, userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataPermission({
|
||||
|
@@ -69,7 +69,7 @@ public interface ISysConfigService {
|
||||
*
|
||||
* @param configIds 需要删除的参数ID
|
||||
*/
|
||||
void deleteConfigByIds(Long[] configIds);
|
||||
void deleteConfigByIds(List<Long> configIds);
|
||||
|
||||
/**
|
||||
* 重置参数缓存数据
|
||||
|
@@ -47,7 +47,7 @@ public interface ISysDictDataService {
|
||||
*
|
||||
* @param dictCodes 需要删除的字典数据ID
|
||||
*/
|
||||
void deleteDictDataByIds(Long[] dictCodes);
|
||||
void deleteDictDataByIds(List<Long> dictCodes);
|
||||
|
||||
/**
|
||||
* 新增保存字典数据信息
|
||||
|
@@ -62,7 +62,7 @@ public interface ISysDictTypeService {
|
||||
*
|
||||
* @param dictIds 需要删除的字典ID
|
||||
*/
|
||||
void deleteDictTypeByIds(Long[] dictIds);
|
||||
void deleteDictTypeByIds(List<Long> dictIds);
|
||||
|
||||
/**
|
||||
* 重置字典缓存数据
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package org.dromara.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
@@ -42,11 +43,10 @@ public class SysClientServiceImpl implements ISysClientService {
|
||||
@Override
|
||||
public SysClientVo queryById(Long id) {
|
||||
SysClientVo vo = baseMapper.selectVoById(id);
|
||||
vo.setGrantTypeList(List.of(vo.getGrantType().split(",")));
|
||||
vo.setGrantTypeList(StringUtils.splitList(vo.getGrantType()));
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询客户端管理
|
||||
*/
|
||||
@@ -63,7 +63,7 @@ public class SysClientServiceImpl implements ISysClientService {
|
||||
public TableDataInfo<SysClientVo> queryPageList(SysClientBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysClient> lqw = buildQueryWrapper(bo);
|
||||
Page<SysClientVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
result.getRecords().forEach(r -> r.setGrantTypeList(List.of(r.getGrantType().split(","))));
|
||||
result.getRecords().forEach(r -> r.setGrantTypeList(StringUtils.splitList(r.getGrantType())));
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
@@ -92,8 +92,7 @@ public class SysClientServiceImpl implements ISysClientService {
|
||||
@Override
|
||||
public Boolean insertByBo(SysClientBo bo) {
|
||||
SysClient add = MapstructUtils.convert(bo, SysClient.class);
|
||||
validEntityBeforeSave(add);
|
||||
add.setGrantType(String.join(",", bo.getGrantTypeList()));
|
||||
add.setGrantType(CollUtil.join(bo.getGrantTypeList(), StringUtils.SEPARATOR));
|
||||
// 生成clientId
|
||||
String clientKey = bo.getClientKey();
|
||||
String clientSecret = bo.getClientSecret();
|
||||
@@ -112,7 +111,6 @@ public class SysClientServiceImpl implements ISysClientService {
|
||||
@Override
|
||||
public Boolean updateByBo(SysClientBo bo) {
|
||||
SysClient update = MapstructUtils.convert(bo, SysClient.class);
|
||||
validEntityBeforeSave(update);
|
||||
update.setGrantType(String.join(",", bo.getGrantTypeList()));
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
@@ -129,22 +127,12 @@ public class SysClientServiceImpl implements ISysClientService {
|
||||
.eq(SysClient::getClientId, clientId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(SysClient entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除客户端管理
|
||||
*/
|
||||
@CacheEvict(cacheNames = CacheNames.SYS_CLIENT, allEntries = true)
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ package org.dromara.system.service.impl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -26,7 +25,6 @@ import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -55,7 +53,6 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||
* @return 参数配置信息
|
||||
*/
|
||||
@Override
|
||||
@DS("master")
|
||||
public SysConfigVo selectConfigById(Long configId) {
|
||||
return baseMapper.selectVoById(configId);
|
||||
}
|
||||
@@ -81,14 +78,10 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||
*/
|
||||
@Override
|
||||
public boolean selectRegisterEnabled(String tenantId) {
|
||||
SysConfig retConfig = TenantHelper.dynamic(tenantId, () -> {
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
|
||||
.eq(SysConfig::getConfigKey, "sys.account.registerUser"));
|
||||
});
|
||||
if (ObjectUtil.isNull(retConfig)) {
|
||||
return false;
|
||||
}
|
||||
return Convert.toBool(retConfig.getConfigValue());
|
||||
String configValue = TenantHelper.dynamic(tenantId, () ->
|
||||
this.selectConfigByKey("sys.account.registerUser")
|
||||
);
|
||||
return Convert.toBool(configValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,15 +159,15 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||
* @param configIds 需要删除的参数ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteConfigByIds(Long[] configIds) {
|
||||
for (Long configId : configIds) {
|
||||
SysConfig config = baseMapper.selectById(configId);
|
||||
public void deleteConfigByIds(List<Long> configIds) {
|
||||
List<SysConfig> list = baseMapper.selectByIds(configIds);
|
||||
list.forEach(config -> {
|
||||
if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) {
|
||||
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
|
||||
throw new ServiceException(String.format("内置参数【%s】不能删除", config.getConfigKey()));
|
||||
}
|
||||
CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
|
||||
}
|
||||
baseMapper.deleteByIds(Arrays.asList(configIds));
|
||||
});
|
||||
baseMapper.deleteByIds(configIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,12 +186,10 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
||||
*/
|
||||
@Override
|
||||
public boolean checkConfigKeyUnique(SysConfigBo config) {
|
||||
long configId = ObjectUtils.notNull(config.getConfigId(), -1L);
|
||||
SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
|
||||
if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysConfig>()
|
||||
.eq(SysConfig::getConfigKey, config.getConfigKey())
|
||||
.ne(ObjectUtil.isNotNull(config.getConfigId()), SysConfig::getConfigId, config.getConfigId()));
|
||||
return !exist;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -128,23 +128,17 @@ public class SysDeptServiceImpl implements ISysDeptService {
|
||||
if (CollUtil.isEmpty(depts)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
// 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点
|
||||
List<Tree<Long>> treeList = CollUtil.newArrayList();
|
||||
for (SysDeptVo d : depts) {
|
||||
Long parentId = d.getParentId();
|
||||
SysDeptVo sysDeptVo = depts.stream().filter(it -> it.getDeptId().longValue() == parentId).findFirst().orElse(null);
|
||||
if (sysDeptVo == null) {
|
||||
List<Tree<Long>> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) ->
|
||||
tree.setId(dept.getDeptId())
|
||||
.setParentId(dept.getParentId())
|
||||
.setName(dept.getDeptName())
|
||||
.setWeight(dept.getOrderNum())
|
||||
.putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus())));
|
||||
Tree<Long> tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getDeptId());
|
||||
treeList.add(tree);
|
||||
}
|
||||
}
|
||||
return treeList;
|
||||
return TreeBuildUtils.buildMultiRoot(
|
||||
depts,
|
||||
SysDeptVo::getDeptId,
|
||||
SysDeptVo::getParentId,
|
||||
(node, treeNode) -> treeNode
|
||||
.setId(node.getDeptId())
|
||||
.setParentId(node.getParentId())
|
||||
.setName(node.getDeptName())
|
||||
.setWeight(node.getOrderNum())
|
||||
.putExtra("disabled", SystemConstants.DISABLE.equals(node.getStatus()))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -8,7 +8,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.constant.CacheNames;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.ObjectUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
@@ -58,7 +57,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
|
||||
lqw.eq(bo.getDictSort() != null, SysDictData::getDictSort, bo.getDictSort());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getDictLabel()), SysDictData::getDictLabel, bo.getDictLabel());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getDictType()), SysDictData::getDictType, bo.getDictType());
|
||||
lqw.orderByAsc(SysDictData::getDictSort);
|
||||
lqw.orderByAsc(SysDictData::getDictSort, SysDictData::getDictCode);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@@ -95,12 +94,10 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
|
||||
* @param dictCodes 需要删除的字典数据ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteDictDataByIds(Long[] dictCodes) {
|
||||
for (Long dictCode : dictCodes) {
|
||||
SysDictData data = baseMapper.selectById(dictCode);
|
||||
baseMapper.deleteById(dictCode);
|
||||
CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType());
|
||||
}
|
||||
public void deleteDictDataByIds(List<Long> dictCodes) {
|
||||
List<SysDictData> list = baseMapper.selectByIds(dictCodes);
|
||||
baseMapper.deleteByIds(dictCodes);
|
||||
list.forEach(x -> CacheUtils.evict(CacheNames.SYS_DICT, x.getDictType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,13 +142,11 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
|
||||
*/
|
||||
@Override
|
||||
public boolean checkDictDataUnique(SysDictDataBo dict) {
|
||||
Long dictCode = ObjectUtils.notNull(dict.getDictCode(), -1L);
|
||||
SysDictData entity = baseMapper.selectOne(new LambdaQueryWrapper<SysDictData>()
|
||||
.eq(SysDictData::getDictType, dict.getDictType()).eq(SysDictData::getDictValue, dict.getDictValue()));
|
||||
if (ObjectUtil.isNotNull(entity) && !dictCode.equals(entity.getDictCode())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictData>()
|
||||
.eq(SysDictData::getDictType, dict.getDictType())
|
||||
.eq(SysDictData::getDictValue, dict.getDictValue())
|
||||
.ne(ObjectUtil.isNotNull(dict.getDictCode()), SysDictData::getDictCode, dict.getDictCode()));
|
||||
return !exist;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ 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;
|
||||
|
||||
@@ -94,10 +93,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService {
|
||||
@Override
|
||||
public List<SysDictDataVo> selectDictDataByType(String dictType) {
|
||||
List<SysDictDataVo> dictDatas = dictDataMapper.selectDictDataByType(dictType);
|
||||
if (CollUtil.isNotEmpty(dictDatas)) {
|
||||
return dictDatas;
|
||||
}
|
||||
return null;
|
||||
return CollUtil.isNotEmpty(dictDatas) ? dictDatas : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,17 +125,20 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService {
|
||||
* @param dictIds 需要删除的字典ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteDictTypeByIds(Long[] dictIds) {
|
||||
for (Long dictId : dictIds) {
|
||||
SysDictType dictType = baseMapper.selectById(dictId);
|
||||
if (dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
|
||||
.eq(SysDictData::getDictType, dictType.getDictType()))) {
|
||||
throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
|
||||
public void deleteDictTypeByIds(List<Long> dictIds) {
|
||||
List<SysDictType> list = baseMapper.selectByIds(dictIds);
|
||||
list.forEach(x -> {
|
||||
boolean assigned = dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
|
||||
.eq(SysDictData::getDictType, x.getDictType()));
|
||||
if (assigned) {
|
||||
throw new ServiceException(String.format("%1$s已分配,不能删除", x.getDictName()));
|
||||
}
|
||||
CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType());
|
||||
CacheUtils.evict(CacheNames.SYS_DICT_TYPE, dictType.getDictType());
|
||||
}
|
||||
baseMapper.deleteByIds(Arrays.asList(dictIds));
|
||||
});
|
||||
baseMapper.deleteByIds(dictIds);
|
||||
list.forEach(x -> {
|
||||
CacheUtils.evict(CacheNames.SYS_DICT, x.getDictType());
|
||||
CacheUtils.evict(CacheNames.SYS_DICT_TYPE, x.getDictType());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.constant.SystemConstants;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
@@ -142,7 +143,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
} else {
|
||||
menus = baseMapper.selectMenuTreeByUserId(userId);
|
||||
}
|
||||
return getChildPerms(menus, 0);
|
||||
return getChildPerms(menus, Constants.TOP_PARENT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +222,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
children.setQuery(menu.getQueryParam());
|
||||
childrenList.add(children);
|
||||
router.setChildren(childrenList);
|
||||
} else if (menu.getParentId().intValue() == 0 && menu.isInnerLink()) {
|
||||
} else if (menu.getParentId().equals(Constants.TOP_PARENT_ID) && menu.isInnerLink()) {
|
||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
|
||||
router.setPath("/");
|
||||
List<RouterVo> childrenList = new ArrayList<>();
|
||||
@@ -375,11 +376,11 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
* @param parentId 传入的父节点ID
|
||||
* @return String
|
||||
*/
|
||||
private List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
|
||||
private List<SysMenu> getChildPerms(List<SysMenu> list, Long parentId) {
|
||||
List<SysMenu> returnList = new ArrayList<>();
|
||||
for (SysMenu t : list) {
|
||||
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
|
||||
if (t.getParentId() == parentId) {
|
||||
if (t.getParentId().equals(parentId)) {
|
||||
recursionFn(list, t);
|
||||
returnList.add(t);
|
||||
}
|
||||
|
@@ -67,15 +67,9 @@ public class SysUserServiceImpl implements ISysUserService {
|
||||
*/
|
||||
@Override
|
||||
public List<SysUserExportVo> selectUserExportList(SysUserBo user) {
|
||||
return baseMapper.selectUserExportList(this.buildQueryWrapper(user));
|
||||
}
|
||||
|
||||
private Wrapper<SysUser> buildQueryWrapper(SysUserBo user) {
|
||||
Map<String, Object> params = user.getParams();
|
||||
QueryWrapper<SysUser> wrapper = Wrappers.query();
|
||||
wrapper.eq("u.del_flag", SystemConstants.NORMAL)
|
||||
.eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
|
||||
.in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong))
|
||||
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
|
||||
.like(StringUtils.isNotBlank(user.getNickName()), "u.nick_name", user.getNickName())
|
||||
.eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
|
||||
@@ -88,8 +82,29 @@ public class SysUserServiceImpl implements ISysUserService {
|
||||
ids.add(user.getDeptId());
|
||||
w.in("u.dept_id", ids);
|
||||
}).orderByAsc("u.user_id");
|
||||
return baseMapper.selectUserExportList(wrapper);
|
||||
}
|
||||
|
||||
private Wrapper<SysUser> buildQueryWrapper(SysUserBo user) {
|
||||
Map<String, Object> params = user.getParams();
|
||||
LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(SysUser::getDelFlag, SystemConstants.NORMAL)
|
||||
.eq(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())
|
||||
.in(StringUtils.isNotBlank(user.getUserIds()), SysUser::getUserId, StringUtils.splitTo(user.getUserIds(), Convert::toLong))
|
||||
.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName())
|
||||
.like(StringUtils.isNotBlank(user.getNickName()), SysUser::getNickName, user.getNickName())
|
||||
.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus())
|
||||
.like(StringUtils.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
|
||||
.between(params.get("beginTime") != null && params.get("endTime") != null,
|
||||
SysUser::getCreateTime, params.get("beginTime"), params.get("endTime"))
|
||||
.and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
|
||||
List<SysDept> deptList = deptMapper.selectListByParentId(user.getDeptId());
|
||||
List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
|
||||
ids.add(user.getDeptId());
|
||||
w.in(SysUser::getDeptId, ids);
|
||||
}).orderByAsc(SysUser::getUserId);
|
||||
if (StringUtils.isNotBlank(user.getExcludeUserIds())) {
|
||||
wrapper.notIn("u.user_id", StringUtils.splitList(user.getExcludeUserIds()));
|
||||
wrapper.notIn(SysUser::getUserId, StringUtils.splitList(user.getExcludeUserIds()));
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
@@ -7,32 +7,6 @@
|
||||
<resultMap type="org.dromara.system.domain.vo.SysDeptVo" id="SysDeptResult">
|
||||
</resultMap>
|
||||
|
||||
<select id="selectDeptList" resultMap="SysDeptResult">
|
||||
select
|
||||
<if test="ew.getSqlSelect != null">
|
||||
${ew.getSqlSelect}
|
||||
</if>
|
||||
<if test="ew.getSqlSelect == null">
|
||||
*
|
||||
</if>
|
||||
from sys_dept ${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectPageDeptList" resultMap="SysDeptResult">
|
||||
select
|
||||
<if test="ew.getSqlSelect != null">
|
||||
${ew.getSqlSelect}
|
||||
</if>
|
||||
<if test="ew.getSqlSelect == null">
|
||||
*
|
||||
</if>
|
||||
from sys_dept ${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="countDeptById" resultType="Long">
|
||||
select count(*) from sys_dept where del_flag = '0' and dept_id = #{deptId}
|
||||
</select>
|
||||
|
||||
<select id="selectDeptListByRoleId" resultType="Long">
|
||||
select d.dept_id
|
||||
from sys_dept d
|
||||
|
@@ -7,17 +7,6 @@
|
||||
<resultMap type="org.dromara.system.domain.vo.SysPostVo" id="SysPostResult">
|
||||
</resultMap>
|
||||
|
||||
<select id="selectPagePostList" resultMap="SysPostResult">
|
||||
select
|
||||
<if test="ew.getSqlSelect != null">
|
||||
${ew.getSqlSelect}
|
||||
</if>
|
||||
<if test="ew.getSqlSelect == null">
|
||||
*
|
||||
</if>
|
||||
from sys_post ${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectPostsByUserId" parameterType="Long" resultMap="SysPostResult">
|
||||
select p.post_id, p.dept_id, p.post_name, p.post_code, p.post_category
|
||||
from sys_post p
|
||||
|
@@ -11,32 +11,6 @@
|
||||
<id property="userId" column="user_id"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectPageUserList" resultMap="SysUserResult">
|
||||
select
|
||||
<if test="ew.getSqlSelect != null">
|
||||
${ew.getSqlSelect}
|
||||
</if>
|
||||
<if test="ew.getSqlSelect == null">
|
||||
u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
|
||||
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark
|
||||
</if>
|
||||
from sys_user u
|
||||
${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectUserList" resultMap="SysUserResult">
|
||||
select
|
||||
<if test="ew.getSqlSelect != null">
|
||||
${ew.getSqlSelect}
|
||||
</if>
|
||||
<if test="ew.getSqlSelect == null">
|
||||
u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
|
||||
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark
|
||||
</if>
|
||||
from sys_user u
|
||||
${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectUserExportList" resultMap="SysUserExportResult">
|
||||
select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
|
||||
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
|
||||
@@ -65,9 +39,4 @@
|
||||
${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="countUserById" resultType="Long">
|
||||
select count(*) from sys_user where del_flag = '0' and user_id = #{userId}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -87,6 +87,12 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-api-workflow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-bus</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@@ -73,4 +73,9 @@ public interface FlowConstant {
|
||||
*/
|
||||
String MESSAGE_NOTICE = "messageNotice";
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
String WF_TASK_STATUS = "wf_task_status";
|
||||
|
||||
}
|
||||
|
@@ -65,13 +65,13 @@ public class CompleteTaskBo implements Serializable {
|
||||
|
||||
/**
|
||||
* 扩展变量(此处为逗号分隔的ossId)
|
||||
* @return
|
||||
*/
|
||||
private String ext;
|
||||
|
||||
public Map<String, Object> getVariables() {
|
||||
if (variables == null) {
|
||||
return new HashMap<>(16);
|
||||
variables = new HashMap<>(16);
|
||||
return variables;
|
||||
}
|
||||
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
|
||||
return variables;
|
||||
|
@@ -42,14 +42,12 @@ public class TestLeaveVo implements Serializable {
|
||||
* 开始时间
|
||||
*/
|
||||
@ExcelProperty(value = "开始时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@ExcelProperty(value = "结束时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
|
@@ -15,6 +15,7 @@ import org.dromara.warm.flow.core.entity.Task;
|
||||
import org.dromara.warm.flow.core.listener.GlobalListener;
|
||||
import org.dromara.warm.flow.core.listener.ListenerVariable;
|
||||
import org.dromara.warm.flow.core.service.InsService;
|
||||
import org.dromara.warm.flow.orm.entity.FlowInstance;
|
||||
import org.dromara.warm.flow.orm.entity.FlowTask;
|
||||
import org.dromara.workflow.common.ConditionalOnEnable;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
@@ -151,13 +152,15 @@ public class WorkflowGlobalListener implements GlobalListener {
|
||||
flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
|
||||
}
|
||||
}
|
||||
FlowInstance ins = new FlowInstance();
|
||||
Map<String, Object> variableMap = instance.getVariableMap();
|
||||
variableMap.remove(FlowConstant.FLOW_COPY_LIST);
|
||||
variableMap.remove(FlowConstant.MESSAGE_TYPE);
|
||||
variableMap.remove(FlowConstant.MESSAGE_NOTICE);
|
||||
variableMap.remove(FlowConstant.SUBMIT);
|
||||
instance.setVariable(FlowEngine.jsonConvert.objToStr(variableMap));
|
||||
insService.updateById(instance);
|
||||
ins.setId(instance.getId());
|
||||
ins.setVariable(FlowEngine.jsonConvert.objToStr(variableMap));
|
||||
insService.updateById(ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,9 @@ public interface FlwCategoryMapper extends BaseMapperPlus<FlowCategory, FlowCate
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "createDept")
|
||||
})
|
||||
long countCategoryById(Long categoryId);
|
||||
default long countCategoryById(Long categoryId) {
|
||||
return this.selectCount(new LambdaQueryWrapper<FlowCategory>().eq(FlowCategory::getCategoryId, categoryId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据父流程分类ID查询其所有子流程分类的列表
|
||||
|
@@ -26,12 +26,6 @@ public class CategoryNameTranslationImpl implements TranslationInterface<String>
|
||||
|
||||
@Override
|
||||
public String translation(Object key, String other) {
|
||||
Long id = null;
|
||||
if (key instanceof String categoryId) {
|
||||
id = Convert.toLong(categoryId);
|
||||
} else if (key instanceof Long categoryId) {
|
||||
id = categoryId;
|
||||
}
|
||||
return flwCategoryService.selectCategoryNameById(id);
|
||||
return flwCategoryService.selectCategoryNameById(Convert.toLong(key));
|
||||
}
|
||||
}
|
||||
|
@@ -95,27 +95,20 @@ public class FlwCategoryServiceImpl implements IFlwCategoryService {
|
||||
*/
|
||||
@Override
|
||||
public List<Tree<String>> selectCategoryTreeList(FlowCategoryBo category) {
|
||||
LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(category);
|
||||
List<FlowCategoryVo> categorys = baseMapper.selectVoList(lqw);
|
||||
if (CollUtil.isEmpty(categorys)) {
|
||||
List<FlowCategoryVo> categoryList = this.queryList(category);
|
||||
if (CollUtil.isEmpty(categoryList)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
// 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点
|
||||
List<Tree<String>> treeList = CollUtil.newArrayList();
|
||||
for (FlowCategoryVo d : categorys) {
|
||||
String parentId = d.getParentId().toString();
|
||||
FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().toString().equals(parentId));
|
||||
if (ObjectUtil.isNull(categoryVo)) {
|
||||
List<Tree<String>> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) ->
|
||||
tree.setId(dept.getCategoryId().toString())
|
||||
.setParentId(dept.getParentId().toString())
|
||||
.setName(dept.getCategoryName())
|
||||
.setWeight(dept.getOrderNum()));
|
||||
Tree<String> tree = StreamUtils.findFirst(trees, it -> it.getId().equals(d.getCategoryId().toString()));
|
||||
treeList.add(tree);
|
||||
}
|
||||
}
|
||||
return treeList;
|
||||
return TreeBuildUtils.buildMultiRoot(
|
||||
categoryList,
|
||||
node -> String.valueOf(node.getCategoryId()),
|
||||
node -> String.valueOf(node.getParentId()),
|
||||
(node, treeNode) -> treeNode
|
||||
.setId(String.valueOf(node.getCategoryId()))
|
||||
.setParentId(String.valueOf(node.getParentId()))
|
||||
.setName(node.getCategoryName())
|
||||
.setWeight(node.getOrderNum())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,251 @@
|
||||
package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.dromara.common.core.service.DictService;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.core.utils.ServletUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.system.api.RemoteDeptService;
|
||||
import org.dromara.system.api.RemoteUserService;
|
||||
import org.dromara.system.api.domain.vo.RemoteUserVo;
|
||||
import org.dromara.warm.flow.core.dto.DefJson;
|
||||
import org.dromara.warm.flow.core.dto.NodeJson;
|
||||
import org.dromara.warm.flow.core.dto.PromptContent;
|
||||
import org.dromara.warm.flow.core.enums.NodeType;
|
||||
import org.dromara.warm.flow.core.utils.MapUtil;
|
||||
import org.dromara.warm.flow.orm.entity.FlowHisTask;
|
||||
import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper;
|
||||
import org.dromara.warm.flow.ui.service.ChartExtService;
|
||||
import org.dromara.workflow.common.ConditionalOnEnable;
|
||||
import org.dromara.workflow.common.constant.FlowConstant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程图提示信息
|
||||
*
|
||||
* @author AprilWind
|
||||
*/
|
||||
@ConditionalOnEnable
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class FlwChartExtServiceImpl implements ChartExtService {
|
||||
|
||||
private final FlowHisTaskMapper flowHisTaskMapper;
|
||||
private final DictService dictService;
|
||||
|
||||
@DubboReference
|
||||
private RemoteUserService remoteUserService;
|
||||
@DubboReference
|
||||
private RemoteDeptService remoteDeptService;
|
||||
|
||||
/**
|
||||
* 设置流程图提示信息
|
||||
*
|
||||
* @param defJson 流程定义json对象
|
||||
*/
|
||||
@Override
|
||||
public void execute(DefJson defJson) {
|
||||
// 临时修复 后续版本将通过defjson获取流程实例ID
|
||||
String[] parts = ServletUtils.getRequest().getRequestURI().split("/");
|
||||
Long instanceId = Convert.toLong(parts[parts.length - 1]);
|
||||
|
||||
// 根据流程实例ID查询所有相关的历史任务列表
|
||||
List<FlowHisTask> flowHisTasks = this.getHisTaskGroupedByNode(instanceId);
|
||||
if (CollUtil.isEmpty(flowHisTasks)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 按节点编号(nodeCode)对历史任务进行分组
|
||||
Map<String, List<FlowHisTask>> groupedByNode = StreamUtils.groupByKey(flowHisTasks, FlowHisTask::getNodeCode);
|
||||
|
||||
// 批量查询所有审批人的用户信息
|
||||
List<RemoteUserVo> userDTOList = remoteUserService.selectListByIds(StreamUtils.toList(flowHisTasks, e -> Convert.toLong(e.getApprover())));
|
||||
|
||||
// 将查询到的用户列表转换为以用户ID为key的映射
|
||||
Map<Long, RemoteUserVo> userMap = StreamUtils.toIdentityMap(userDTOList, RemoteUserVo::getUserId);
|
||||
|
||||
Map<String, String> dictType = dictService.getAllDictByDictType(FlowConstant.WF_TASK_STATUS);
|
||||
|
||||
// 遍历流程定义中的每个节点,调用处理方法,将对应节点的任务列表及用户信息传入,生成扩展提示内容
|
||||
for (NodeJson nodeJson : defJson.getNodeList()) {
|
||||
// 获取当前节点对应的历史任务列表,如果没有则返回空列表避免空指针
|
||||
List<FlowHisTask> taskList = groupedByNode.get(nodeJson.getNodeCode());
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
continue;
|
||||
}
|
||||
// 处理当前节点的扩展信息,包括构建审批人提示内容等
|
||||
this.processNodeExtInfo(nodeJson, taskList, userMap, dictType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化流程图提示信息
|
||||
*
|
||||
* @param defJson 流程定义json对象
|
||||
*/
|
||||
@Override
|
||||
public void initPromptContent(DefJson defJson) {
|
||||
defJson.setTopText("流程名称: " + defJson.getFlowName());
|
||||
defJson.getNodeList().forEach(nodeJson -> {
|
||||
nodeJson.setPromptContent(
|
||||
new PromptContent()
|
||||
// 提示信息
|
||||
.setInfo(
|
||||
CollUtil.newArrayList(
|
||||
new PromptContent.InfoItem()
|
||||
.setPrefix("任务名称: ")
|
||||
.setContent(nodeJson.getNodeName())
|
||||
.setContentStyle(Map.of(
|
||||
"border", "1px solid #d1e9ff",
|
||||
"backgroundColor", "#e8f4ff",
|
||||
"padding", "4px 8px",
|
||||
"borderRadius", "4px"
|
||||
))
|
||||
.setRowStyle(Map.of(
|
||||
"fontWeight", "bold",
|
||||
"margin", "0 0 6px 0",
|
||||
"padding", "0 0 8px 0",
|
||||
"borderBottom", "1px solid #ccc"
|
||||
))
|
||||
)
|
||||
)
|
||||
// 弹窗样式
|
||||
.setDialogStyle(MapUtil.mergeAll(
|
||||
"position", "absolute",
|
||||
"backgroundColor", "#fff",
|
||||
"border", "1px solid #ccc",
|
||||
"borderRadius", "4px",
|
||||
"boxShadow", "0 2px 8px rgba(0, 0, 0, 0.15)",
|
||||
"padding", "8px 12px",
|
||||
"fontSize", "14px",
|
||||
"zIndex", "1000",
|
||||
"maxWidth", "500px",
|
||||
"overflowY", "visible",
|
||||
"overflowX", "hidden",
|
||||
"color", "#333",
|
||||
"pointerEvents", "auto",
|
||||
"scrollbarWidth", "thin"
|
||||
))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理节点的扩展信息,构建用于流程图悬浮提示的内容
|
||||
*
|
||||
* @param nodeJson 当前节点对象
|
||||
* @param taskList 当前节点对应的历史审批任务列表
|
||||
*/
|
||||
private void processNodeExtInfo(NodeJson nodeJson, List<FlowHisTask> taskList, Map<Long, RemoteUserVo> userMap, Map<String, String> dictType) {
|
||||
|
||||
// 获取节点提示内容对象中的 info 列表,用于追加提示项
|
||||
List<PromptContent.InfoItem> info = nodeJson.getPromptContent().getInfo();
|
||||
|
||||
// 遍历所有任务记录,构建提示内容
|
||||
for (FlowHisTask task : taskList) {
|
||||
RemoteUserVo userDTO = userMap.get(Convert.toLong(task.getApprover()));
|
||||
if (ObjectUtil.isEmpty(userDTO)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 查询用户所属部门名称
|
||||
String deptName = remoteDeptService.selectDeptNameByIds(Convert.toStr(userDTO.getDeptId()));
|
||||
|
||||
// 添加标题项,如:👤 张三(市场部)
|
||||
info.add(new PromptContent.InfoItem()
|
||||
.setPrefix(StringUtils.format("👥 {}({})", userDTO.getNickName(), deptName))
|
||||
.setPrefixStyle(Map.of(
|
||||
"fontWeight", "bold",
|
||||
"fontSize", "15px",
|
||||
"color", "#333"
|
||||
))
|
||||
.setRowStyle(Map.of(
|
||||
"margin", "8px 0",
|
||||
"borderBottom", "1px dashed #ccc"
|
||||
))
|
||||
);
|
||||
|
||||
// 添加具体信息项:账号、耗时、时间
|
||||
info.add(buildInfoItem("用户账号", userDTO.getUserName()));
|
||||
info.add(buildInfoItem("审批状态", dictType.get(task.getFlowStatus())));
|
||||
info.add(buildInfoItem("审批耗时", DateUtils.getTimeDifference(task.getUpdateTime(), task.getCreateTime())));
|
||||
info.add(buildInfoItem("办理时间", DateUtils.formatDateTime(task.getUpdateTime())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单条提示内容对象 InfoItem,用于悬浮窗显示(key: value)
|
||||
*
|
||||
* @param key 字段名(作为前缀)
|
||||
* @param value 字段值
|
||||
* @return 提示项对象
|
||||
*/
|
||||
private PromptContent.InfoItem buildInfoItem(String key, String value) {
|
||||
return new PromptContent.InfoItem()
|
||||
// 前缀
|
||||
.setPrefix(key + ": ")
|
||||
// 前缀样式
|
||||
.setPrefixStyle(Map.of(
|
||||
"textAlign", "right",
|
||||
"color", "#444",
|
||||
"userSelect", "none",
|
||||
"display", "inline-block",
|
||||
"width", "100px",
|
||||
"paddingRight", "8px",
|
||||
"fontWeight", "500",
|
||||
"fontSize", "14px",
|
||||
"lineHeight", "24px",
|
||||
"verticalAlign", "middle"
|
||||
))
|
||||
// 内容
|
||||
.setContent(value)
|
||||
// 内容样式
|
||||
.setContentStyle(Map.of(
|
||||
"backgroundColor", "#f7faff",
|
||||
"color", "#005cbf",
|
||||
"padding", "4px 8px",
|
||||
"fontSize", "14px",
|
||||
"borderRadius", "4px",
|
||||
"whiteSpace", "normal",
|
||||
"border", "1px solid #d0e5ff",
|
||||
"userSelect", "text",
|
||||
"lineHeight", "20px"
|
||||
))
|
||||
// 行样式
|
||||
.setRowStyle(Map.of(
|
||||
"color", "#222",
|
||||
"alignItems", "center",
|
||||
"display", "flex",
|
||||
"marginBottom", "6px",
|
||||
"fontWeight", "400",
|
||||
"fontSize", "14px"
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程实例ID获取历史任务列表
|
||||
*
|
||||
* @param instanceId 流程实例ID
|
||||
* @return 历史任务列表
|
||||
*/
|
||||
public List<FlowHisTask> getHisTaskGroupedByNode(Long instanceId) {
|
||||
LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(FlowHisTask::getInstanceId, instanceId)
|
||||
.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
|
||||
.orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
|
||||
return flowHisTaskMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
}
|
@@ -96,10 +96,8 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
|
||||
LambdaQueryWrapper<FlowDefinition> wrapper = buildQueryWrapper(flowDefinition);
|
||||
wrapper.in(FlowDefinition::getIsPublish, Arrays.asList(PublishStatus.UNPUBLISHED.getKey(), PublishStatus.EXPIRED.getKey()));
|
||||
Page<FlowDefinition> page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper);
|
||||
TableDataInfo<FlowDefinitionVo> build = TableDataInfo.build();
|
||||
build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class));
|
||||
build.setTotal(page.getTotal());
|
||||
return build;
|
||||
List<FlowDefinitionVo> list = BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class);
|
||||
return new TableDataInfo<>(list, page.getTotal());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<FlowDefinition> buildQueryWrapper(FlowDefinition flowDefinition) {
|
||||
|
@@ -304,9 +304,9 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
|
||||
}
|
||||
//历史任务
|
||||
LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(FlowHisTask::getInstanceId, instanceId);
|
||||
wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey());
|
||||
wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime);
|
||||
wrapper.eq(FlowHisTask::getInstanceId, instanceId)
|
||||
.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey())
|
||||
.orderByDesc(FlowHisTask::getCreateTime, FlowHisTask::getUpdateTime);
|
||||
List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper);
|
||||
if (CollUtil.isNotEmpty(flowHisTasks)) {
|
||||
list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class));
|
||||
|
@@ -2,6 +2,7 @@ package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -238,13 +239,21 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
|
||||
* @return Pair(TaskAssigneeEnum, Long),如果格式非法返回 null
|
||||
*/
|
||||
private Pair<TaskAssigneeEnum, Long> parseStorageId(String storageId) {
|
||||
if (StringUtils.isBlank(storageId)) {
|
||||
return null;
|
||||
}
|
||||
// 跳过以 $ 或 # 开头的字符串
|
||||
if (StringUtils.startsWith(storageId, "$") || StringUtils.startsWith(storageId, "#")) {
|
||||
log.debug("跳过 storageId 解析,检测到内置变量表达式:{}", storageId);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String[] parts = storageId.split(StrUtil.COLON, 2);
|
||||
if (parts.length < 2) {
|
||||
return Pair.of(TaskAssigneeEnum.USER, Long.valueOf(parts[0]));
|
||||
return Pair.of(TaskAssigneeEnum.USER, Convert.toLong(parts[0]));
|
||||
} else {
|
||||
TaskAssigneeEnum type = TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON);
|
||||
return Pair.of(type, Long.valueOf(parts[1]));
|
||||
return Pair.of(type, Convert.toLong(parts[1]));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析 storageId 失败,格式非法:{},错误信息:{}", storageId, e.getMessage());
|
||||
|
@@ -534,7 +534,10 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
//构建以下节点数据
|
||||
List<Task> buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance, definition, FlowParams.build()));
|
||||
//办理人变量替换
|
||||
ExpressionUtil.evalVariable(buildNextTaskList, mergeVariable);
|
||||
ExpressionUtil.evalVariable(buildNextTaskList,
|
||||
FlowParams.build()
|
||||
.variable(mergeVariable)
|
||||
);
|
||||
for (FlowNode flowNode : nextFlowNodes) {
|
||||
buildNextTaskList.stream().filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())).findFirst().ifPresent(t -> {
|
||||
if (CollUtil.isNotEmpty(t.getPermissionList())) {
|
||||
@@ -718,7 +721,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
for (Map.Entry<Long, List<User>> entry : listMap.entrySet()) {
|
||||
List<User> value = entry.getValue();
|
||||
if (CollUtil.isNotEmpty(value)) {
|
||||
List<RemoteUserVo> userDtoList = remoteUserService.selectListByIds(StreamUtils.toList(value, e -> Long.valueOf(e.getProcessedBy())));
|
||||
List<RemoteUserVo> userDtoList = remoteUserService.selectListByIds(StreamUtils.toList(value, e -> Convert.toLong(e.getProcessedBy())));
|
||||
map.put(entry.getKey(), userDtoList);
|
||||
}
|
||||
}
|
||||
@@ -737,7 +740,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
if (CollUtil.isEmpty(userList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return remoteUserService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy())));
|
||||
return remoteUserService.selectListByIds(StreamUtils.toList(userList, e -> Convert.toLong(e.getProcessedBy())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -147,7 +147,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
public void processHandler(ProcessEvent processEvent) {
|
||||
TenantHelper.dynamic(processEvent.getTenantId(), () -> {
|
||||
log.info("当前任务执行了{}", processEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId()));
|
||||
TestLeave testLeave = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
|
||||
testLeave.setStatus(processEvent.getStatus());
|
||||
// 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
|
||||
Map<String, Object> params = processEvent.getParams();
|
||||
|
@@ -4,8 +4,4 @@
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.workflow.mapper.FlwCategoryMapper">
|
||||
|
||||
<select id="countCategoryById" resultType="Long">
|
||||
select count(*) from flow_category where del_flag = '0' and category_id = #{categoryId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -213,17 +213,17 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-websocket</artifactId>
|
||||
<version>9.0.98</version>
|
||||
<version>9.0.105</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>9.0.98</version>
|
||||
<version>9.0.105</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-el</artifactId>
|
||||
<version>9.0.98</version>
|
||||
<version>9.0.105</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
@@ -27,11 +27,11 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<seata.version>2.3.0</seata.version>
|
||||
<seata.version>2.4.0</seata.version>
|
||||
<spring-boot-for-server.version>2.7.18</spring-boot-for-server.version>
|
||||
<spring-framework-for-server.version>5.3.39</spring-framework-for-server.version>
|
||||
<snakeyaml-for-server.version>2.0</snakeyaml-for-server.version>
|
||||
<tomcat-embed.version>9.0.98</tomcat-embed.version>
|
||||
<tomcat-embed.version>9.0.105</tomcat-embed.version>
|
||||
<logstash-logback-encoder.version>7.2</logstash-logback-encoder.version>
|
||||
<jedis.version>3.8.0</jedis.version>
|
||||
<jackson-mapper.version>1.9.13</jackson-mapper.version>
|
||||
@@ -161,6 +161,12 @@
|
||||
<version>${seata.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.seata</groupId>
|
||||
<artifactId>seata-all</artifactId>
|
||||
<version>${seata.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.seata</groupId>
|
||||
<artifactId>seata-core</artifactId>
|
||||
@@ -199,11 +205,11 @@
|
||||
<version>${seata.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.seata</groupId>
|
||||
<artifactId>seata-console</artifactId>
|
||||
<version>${seata.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.seata</groupId>-->
|
||||
<!-- <artifactId>seata-namingserver</artifactId>-->
|
||||
<!-- <version>${seata.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- for database -->
|
||||
<dependency>
|
||||
|
@@ -16,13 +16,14 @@
|
||||
*/
|
||||
package org.apache.seata.core.store.db;
|
||||
|
||||
import org.apache.seata.common.ConfigurationKeys;
|
||||
import org.apache.seata.common.exception.ShouldNeverHappenException;
|
||||
import org.apache.seata.common.exception.StoreException;
|
||||
import org.apache.seata.common.executor.Initialize;
|
||||
import org.apache.seata.common.util.ConfigTools;
|
||||
import org.apache.seata.common.util.StringUtils;
|
||||
import org.apache.seata.config.Configuration;
|
||||
import org.apache.seata.config.ConfigurationFactory;
|
||||
import org.apache.seata.core.constants.ConfigurationKeys;
|
||||
import org.apache.seata.core.constants.DBType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -55,13 +56,13 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
*/
|
||||
protected static final Configuration CONFIG = ConfigurationFactory.getInstance();
|
||||
|
||||
private final static String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
|
||||
private static final String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
|
||||
|
||||
private final static String MYSQL8_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
|
||||
private static final String MYSQL8_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
|
||||
|
||||
private final static String MYSQL_DRIVER_FILE_PREFIX = "mysql-connector-java-";
|
||||
private static final String MYSQL_DRIVER_FILE_PREFIX = "mysql-connector-j";
|
||||
|
||||
private final static Map<String, ClassLoader> MYSQL_DRIVER_LOADERS;
|
||||
private static final Map<String, ClassLoader> MYSQL_DRIVER_LOADERS;
|
||||
|
||||
private static final long DEFAULT_DB_MAX_WAIT = 5000;
|
||||
|
||||
@@ -85,7 +86,7 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
//valid driver class name
|
||||
// valid driver class name
|
||||
String driverClassName = getDriverClassName();
|
||||
// ClassLoader loader = getDriverClassLoader();
|
||||
// if (null == loader) {
|
||||
@@ -95,15 +96,31 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
// loader.loadClass(driverClassName);
|
||||
Class.forName(driverClassName);
|
||||
} catch (ClassNotFoundException exx) {
|
||||
String driverClassPath = null;
|
||||
String folderPath = System.getProperty("loader.path");
|
||||
if (null != folderPath) {
|
||||
driverClassPath = folderPath + "/jdbc/";
|
||||
if (folderPath == null) {
|
||||
folderPath = System.getProperty("java.class.path");
|
||||
}
|
||||
String driverClassPath = Stream.of(folderPath.split(File.pathSeparator))
|
||||
.map(File::new)
|
||||
.filter(File::exists)
|
||||
.map(file -> file.isFile() ? file.getParentFile() : file)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(File::isDirectory)
|
||||
// Only the MySQL driver needs to be placed in the jdbc folder.
|
||||
.map(file -> (MYSQL8_DRIVER_CLASS_NAME.equals(driverClassName)
|
||||
|| MYSQL_DRIVER_CLASS_NAME.equals(driverClassName))
|
||||
? new File(file, "jdbc")
|
||||
: file)
|
||||
.filter(File::exists)
|
||||
.filter(File::isDirectory)
|
||||
.distinct()
|
||||
.findAny()
|
||||
.map(File::getAbsolutePath)
|
||||
.orElseThrow(() -> new ShouldNeverHappenException("cannot find jdbc folder"));
|
||||
throw new StoreException(String.format(
|
||||
"The driver {%s} cannot be found in the path %s. Please ensure that the appropriate database driver dependencies are included in the classpath.", driverClassName, driverClassPath));
|
||||
"The driver {%s} cannot be found in the path %s. Please ensure that the appropriate database driver dependencies are included in the classpath.",
|
||||
driverClassName, driverClassPath));
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* generate the datasource
|
||||
@@ -140,17 +157,20 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
* @return the db max wait
|
||||
*/
|
||||
protected Long getMaxWait() {
|
||||
Long maxWait = CONFIG.getLong(ConfigurationKeys.STORE_DB_MAX_WAIT, DEFAULT_DB_MAX_WAIT);
|
||||
return maxWait;
|
||||
return CONFIG.getLong(ConfigurationKeys.STORE_DB_MAX_WAIT, DEFAULT_DB_MAX_WAIT);
|
||||
}
|
||||
|
||||
protected ClassLoader getDriverClassLoader() {
|
||||
return MYSQL_DRIVER_LOADERS.getOrDefault(getDriverClassName(), ClassLoader.getSystemClassLoader());
|
||||
return MYSQL_DRIVER_LOADERS.getOrDefault(
|
||||
getDriverClassName(), this.getClass().getClassLoader());
|
||||
}
|
||||
|
||||
private static Map<String, ClassLoader> createMysqlDriverClassLoaders() {
|
||||
Map<String, ClassLoader> loaders = new HashMap<>();
|
||||
String cp = System.getProperty("java.class.path");
|
||||
String cp = System.getProperty("loader.path");
|
||||
if (cp == null) {
|
||||
cp = System.getProperty("java.class.path");
|
||||
}
|
||||
if (cp == null || cp.isEmpty()) {
|
||||
return loaders;
|
||||
}
|
||||
@@ -178,7 +198,7 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
}
|
||||
try {
|
||||
URL url = file.toURI().toURL();
|
||||
ClassLoader loader = new URLClassLoader(new URL[]{url}, ClassLoader.getSystemClassLoader());
|
||||
ClassLoader loader = new URLClassLoader(new URL[] {url}, ClassLoader.getSystemClassLoader());
|
||||
try {
|
||||
loader.loadClass(MYSQL8_DRIVER_CLASS_NAME);
|
||||
loaders.putIfAbsent(MYSQL8_DRIVER_CLASS_NAME, loader);
|
||||
@@ -279,5 +299,4 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider,
|
||||
protected String getPublicKey() {
|
||||
return CONFIG.getConfig(ConfigurationKeys.STORE_PUBLIC_KEY);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,11 +19,6 @@ logging:
|
||||
# bootstrap-servers: 127.0.0.1:9092
|
||||
# topic: logback_to_logstash
|
||||
|
||||
console:
|
||||
user:
|
||||
username: seata
|
||||
password: seata
|
||||
|
||||
seata:
|
||||
config:
|
||||
# support: nacos 、 consul 、 apollo 、 zk 、 etcd3
|
||||
@@ -52,9 +47,3 @@ seata:
|
||||
##if use MSE Nacos with auth, mutex with username/password attribute
|
||||
#access-key: ""
|
||||
#secret-key: ""
|
||||
security:
|
||||
secretKey: rE7bYayhpvduYwCxuhckybEPDXyna6xwm5m7MZjtjrdXjVxAbXAMccXHyaJvB346
|
||||
tokenValidityInMilliseconds: 1800000
|
||||
csrf-ignore-urls: /metadata/v1/**
|
||||
ignore:
|
||||
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/health,/error,/vgroup/v1/**
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
|
||||
#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.15-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.7-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user