mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2026-01-13 10:45:58 +08:00
Compare commits
47 Commits
f07c20afab
...
v5.5.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6eacfa5a8 | ||
|
|
961bca462e | ||
|
|
496df8494e | ||
|
|
da4dffcfce | ||
|
|
2f1f9689e0 | ||
|
|
8110413fdf | ||
|
|
c1f64d3450 | ||
|
|
cb00f4c9c1 | ||
|
|
79512c69b2 | ||
|
|
a5fb128f11 | ||
|
|
8a04e3c88f | ||
|
|
dac447b76f | ||
|
|
35a9e4c8e8 | ||
|
|
0d87c12d3c | ||
|
|
f20a0c4342 | ||
|
|
6c8d637bd2 | ||
|
|
20e9957db2 | ||
|
|
9baded9326 | ||
|
|
b5902debb6 | ||
|
|
bcd5bb0f86 | ||
|
|
1a461f7d3d | ||
|
|
e23d99d85b | ||
|
|
b58085fde1 | ||
|
|
b30ffa952f | ||
|
|
fd5d028e95 | ||
|
|
64100cf1ff | ||
|
|
7e7d857ba5 | ||
|
|
d22b2a10df | ||
|
|
957a4d1fcd | ||
|
|
49ef8378fe | ||
|
|
57dd6831d3 | ||
|
|
8aa60abb1f | ||
|
|
7a9f51fc7a | ||
|
|
159e30c982 | ||
|
|
7334d91d6b | ||
|
|
95c01301f6 | ||
|
|
296466fa13 | ||
|
|
3c8d864b5f | ||
|
|
ea50a57602 | ||
|
|
7e14b98676 | ||
|
|
015b406001 | ||
|
|
098d3347a0 | ||
|
|
08d4493994 | ||
|
|
367d739e2d | ||
|
|
d6688a367d | ||
|
|
0b331796e2 | ||
|
|
456620b638 |
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.5.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:5.5.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
|
||||
</settings>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-server:5.5.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-server:5.5.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-admin/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:5.5.1" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-snailjob-server:5.5.2" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-snailjob-server/Dockerfile" />
|
||||
</settings>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/5.X/LICENSE)
|
||||
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
||||
<br>
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -13,8 +13,8 @@
|
||||
<description>Dromara RuoYi-Vue-Plus多租户管理系统</description>
|
||||
|
||||
<properties>
|
||||
<revision>5.5.1</revision>
|
||||
<spring-boot.version>3.5.8</spring-boot.version>
|
||||
<revision>5.5.2</revision>
|
||||
<spring-boot.version>3.5.9</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
@@ -31,7 +31,7 @@
|
||||
<redisson.version>3.52.0</redisson.version>
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<dynamic-ds.version>4.3.1</dynamic-ds.version>
|
||||
<snailjob.version>1.8.0</snailjob.version>
|
||||
<snailjob.version>1.9.0</snailjob.version>
|
||||
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<lombok.version>1.18.40</lombok.version>
|
||||
@@ -46,7 +46,7 @@
|
||||
<!-- 限制框架中的fastjson版本 -->
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<!-- 面向运行时的D-ORM依赖 -->
|
||||
<anyline.version>8.7.2-20250603</anyline.version>
|
||||
<anyline.version>8.7.3-20251210</anyline.version>
|
||||
<!-- 工作流配置 -->
|
||||
<warm-flow.version>1.8.4</warm-flow.version>
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -106,7 +107,7 @@ public class AuthController {
|
||||
Long userId = LoginHelper.getUserId();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SseMessageDto dto = new SseMessageDto();
|
||||
dto.setMessage("欢迎登录RuoYi-Vue-Plus后台管理系统");
|
||||
dto.setMessage(DateUtils.getTodayHour(new Date()) + "好,欢迎登录 RuoYi-Vue-Plus 后台管理系统");
|
||||
dto.setUserIds(List.of(userId));
|
||||
SseMessageUtils.publishMessage(dto);
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
@@ -147,8 +148,8 @@ public class AuthController {
|
||||
StpUtil.checkLogin();
|
||||
// 获取第三方登录信息
|
||||
AuthResponse<AuthUser> response = SocialUtils.loginAuth(
|
||||
loginBody.getSource(), loginBody.getSocialCode(),
|
||||
loginBody.getSocialState(), socialProperties);
|
||||
loginBody.getSource(), loginBody.getSocialCode(),
|
||||
loginBody.getSocialState(), socialProperties);
|
||||
AuthUser authUserData = response.getData();
|
||||
// 判断授权响应是否成功
|
||||
if (!response.ok()) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>5.5.1</revision>
|
||||
<revision>5.5.2</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
@@ -3,10 +3,8 @@ package org.dromara.common.core.config;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.dromara.common.core.config.properties.ThreadPoolProperties;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
|
||||
@@ -19,7 +17,6 @@ import java.util.concurrent.*;
|
||||
**/
|
||||
@Slf4j
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(ThreadPoolProperties.class)
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.dromara.common.core.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 线程池 配置属性
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "thread-pool")
|
||||
public class ThreadPoolProperties {
|
||||
|
||||
/**
|
||||
* 是否开启线程池
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* 队列最大长度
|
||||
*/
|
||||
private int queueCapacity;
|
||||
|
||||
/**
|
||||
* 线程池维护线程所允许的空闲时间
|
||||
*/
|
||||
private int keepAliveSeconds;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.dromara.common.core.utils;
|
||||
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.dromara.common.core.enums.FormatsType;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
@@ -297,4 +299,80 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定日期时间获取时间段(凌晨 / 上午 / 中午 / 下午 / 晚上)
|
||||
*
|
||||
* @param date 日期时间
|
||||
* @return 时间段描述
|
||||
*/
|
||||
public static String getTodayHour(Date date) {
|
||||
int hour = DateUtil.hour(date, true);
|
||||
if (hour <= 6) {
|
||||
return "凌晨";
|
||||
} else if (hour < 12) {
|
||||
return "上午";
|
||||
} else if (hour == 12) {
|
||||
return "中午";
|
||||
} else if (hour <= 18) {
|
||||
return "下午";
|
||||
} else {
|
||||
return "晚上";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将日期格式化为仿微信的友好时间
|
||||
* <p>
|
||||
* 规则说明:
|
||||
* 1. 未来时间:yyyy-MM-dd HH:mm
|
||||
* 2. 今天:
|
||||
* - 1 分钟内:刚刚
|
||||
* - 1 小时内:X 分钟前
|
||||
* - 超过 1 小时:凌晨/上午/中午/下午/晚上 HH:mm
|
||||
* 3. 昨天:昨天 HH:mm
|
||||
* 4. 本周:周X HH:mm
|
||||
* 5. 今年内:MM-dd HH:mm
|
||||
* 6. 非今年:yyyy-MM-dd HH:mm
|
||||
*
|
||||
* @param date 日期时间
|
||||
* @return 格式化后的时间描述
|
||||
*/
|
||||
public static String formatFriendlyTime(Date date) {
|
||||
if (date == null) {
|
||||
return "";
|
||||
}
|
||||
Date now = DateUtil.date();
|
||||
|
||||
// 未来时间或非今年
|
||||
if (date.after(now) || DateUtil.year(date) != DateUtil.year(now)) {
|
||||
return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM, date);
|
||||
}
|
||||
|
||||
// 今天
|
||||
if (DateUtil.isSameDay(date, now)) {
|
||||
long minutes = DateUtil.between(date, now, DateUnit.MINUTE);
|
||||
if (minutes < 1) {
|
||||
return "刚刚";
|
||||
}
|
||||
if (minutes < 60) {
|
||||
return minutes + "分钟前";
|
||||
}
|
||||
return getTodayHour(date) + " " + DateUtil.format(date, "HH:mm");
|
||||
}
|
||||
|
||||
// 昨天
|
||||
if (DateUtil.isSameDay(date, DateUtil.yesterday())) {
|
||||
return "昨天 " + DateUtil.format(date, "HH:mm");
|
||||
}
|
||||
|
||||
// 本周
|
||||
if (DateUtil.isSameWeek(date, now, true)) {
|
||||
return DateUtil.dayOfWeekEnum(date).toChinese("周")
|
||||
+ " " + DateUtil.format(date, "HH:mm");
|
||||
}
|
||||
|
||||
// 今年内其它时间
|
||||
return DateUtil.format(date, "MM-dd HH:mm");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,27 +28,60 @@ public class DesensitizedUtils extends DesensitizedUtil {
|
||||
}
|
||||
|
||||
int len = value.length();
|
||||
int prefixMaskLimit = prefixVisible + maskLength;
|
||||
int fullLimit = prefixMaskLimit + suffixVisible;
|
||||
|
||||
// 总长度小于等于前后可见长度 → 全部掩码
|
||||
if (len <= prefixVisible + suffixVisible) {
|
||||
// 规则 1:长度 <= 中间掩码长度 → 全掩码
|
||||
if (len <= maskLength) {
|
||||
return StrUtil.repeat('*', len);
|
||||
}
|
||||
String mask = StrUtil.repeat('*', maskLength);
|
||||
|
||||
// 规则 2:长度 <= 前缀 + 中间掩码
|
||||
if (len <= prefixMaskLimit) {
|
||||
return value.substring(0, len - maskLength) + mask;
|
||||
}
|
||||
|
||||
String prefix = value.substring(0, prefixVisible);
|
||||
|
||||
// 规则 3:长度 <= 前缀 + 中间掩码 + 后缀
|
||||
if (len <= fullLimit) {
|
||||
int suffixLen = len - prefixMaskLimit;
|
||||
return prefix + mask + value.substring(len - suffixLen);
|
||||
}
|
||||
|
||||
// 规则 4:标准形态
|
||||
return prefix + mask + value.substring(len - suffixVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高安全级别脱敏方法(Token / 私钥)
|
||||
*
|
||||
* @param value 原始字符串
|
||||
* @param prefixVisible 前面可见长度(推荐0~4)
|
||||
* @param suffixVisible 后面可见长度(推荐0~4)
|
||||
* @return 脱敏后字符串
|
||||
*/
|
||||
public static String maskHighSecurity(String value, int prefixVisible, int suffixVisible) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
return value;
|
||||
}
|
||||
int len = value.length();
|
||||
|
||||
// 规则1:长度 <= 前缀可见长度 → 全部掩码
|
||||
if (len <= prefixVisible) {
|
||||
return StrUtil.repeat('*', len);
|
||||
}
|
||||
|
||||
// 可用长度 = 总长度 - 前后可见长度
|
||||
int available = len - prefixVisible - suffixVisible;
|
||||
// 规则2:长度 <= 前缀 + 后缀可见长度 → 优先掩码后面
|
||||
if (len <= prefixVisible + suffixVisible) {
|
||||
return value.substring(0, len - prefixVisible) + StrUtil.repeat('*', prefixVisible);
|
||||
}
|
||||
|
||||
// 中间掩码长度不能超过可用长度
|
||||
int actualMaskLength = Math.min(maskLength, available);
|
||||
|
||||
// 剩余字符尽量显示在中间掩码旁
|
||||
int remaining = available - actualMaskLength;
|
||||
String middleChars = remaining > 0 ? value.substring(prefixVisible, prefixVisible + remaining) : "";
|
||||
String middleMask = StrUtil.repeat('*', actualMaskLength);
|
||||
|
||||
String prefix = value.substring(0, prefixVisible);
|
||||
String suffix = value.substring(len - suffixVisible);
|
||||
|
||||
return prefix + middleChars + middleMask + suffix;
|
||||
// 规则3:标准形态 → 前后可见,中间全部掩码
|
||||
return value.substring(0, prefixVisible)
|
||||
+ StrUtil.repeat('*', len - prefixVisible - suffixVisible)
|
||||
+ value.substring(len - suffixVisible);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.dromara.common.core.utils.ip;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
@@ -8,6 +9,7 @@ import org.lionsoul.ip2region.service.Config;
|
||||
import org.lionsoul.ip2region.service.Ip2Region;
|
||||
import org.lionsoul.ip2region.xdb.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -43,11 +45,18 @@ public class RegionUtils {
|
||||
// 因为加载整个xdb文件会耗费非常大的内存,如果你不希望加载整个xdb到内存中,更推荐使用 VIndexCache 或 NoCache(即实时读取文件)策略和 setXdbPath/setXdbFile 加载方法(需要注意的一点,setXdbPath 和 setXdbFile 不支持读取ClassPath(即源码和resource目录)中的文件)。
|
||||
// 一般而言,更建议把xdb数据库放到一个指定的文件目录中(即不打包进jar包中),然后使用 NoCache + 配合SearcherPool的并发池读取数据,更方便随时更新xdb数据库
|
||||
|
||||
// TODO 2025年12月23日 Ip2Region封装的 InputStream 读取函数 Searcher.loadContentFromInputStream 在Linux环境下会申请过大的byte[]空间而导致OOM,这里先用临时文件的方案解决,等后续 Ip2Region 更新解决方案
|
||||
// 创建临时文件
|
||||
File v4TempXdb = FileUtil.writeFromStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH), FileUtil.createTempFile());
|
||||
|
||||
// IPv4配置
|
||||
Config v4Config = Config.custom()
|
||||
.setCachePolicy(Config.BufferCache)
|
||||
.setXdbInputStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH))
|
||||
.setXdbFile(v4TempXdb)
|
||||
// .setXdbInputStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH))
|
||||
.asV4();
|
||||
// 删除临时文件
|
||||
v4TempXdb.delete();
|
||||
|
||||
// IPv6配置
|
||||
Config v6Config = null;
|
||||
@@ -55,17 +64,24 @@ public class RegionUtils {
|
||||
if (v6XdbInputStream == null) {
|
||||
log.warn("未加载 IPv6 地址库:未在类路径下找到文件 {}。当前仅启用 IPv4 查询。如需启用 IPv6,请将 ip2region_v6.xdb 放置到 resources 目录", DEFAULT_IPV6_XDB_PATH);
|
||||
} else {
|
||||
// 创建临时文件
|
||||
File v6TempXdb = FileUtil.writeFromStream(ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH), FileUtil.createTempFile());
|
||||
|
||||
v6Config = Config.custom()
|
||||
.setCachePolicy(Config.BufferCache)
|
||||
.setXdbInputStream(v6XdbInputStream)
|
||||
.setXdbFile(v6TempXdb)
|
||||
// .setXdbInputStream(v6XdbInputStream)
|
||||
.asV6();
|
||||
|
||||
// 删除临时文件
|
||||
v6TempXdb.delete();
|
||||
}
|
||||
|
||||
// 初始化Ip2Region实例
|
||||
RegionUtils.ip2Region = Ip2Region.create(v4Config, v6Config);
|
||||
log.debug("IP工具初始化成功,加载IP地址库数据成功!");
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("Ip2RegionHelper初始化失败,原因:{}", e.getMessage());
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,10 @@ public class CellMergeHandler {
|
||||
// 行合并开始下标
|
||||
this.rowIndex = hasTitle ? 1 : 0;
|
||||
}
|
||||
|
||||
private CellMergeHandler(final boolean hasTitle, final int rowIndex) {
|
||||
this.hasTitle = hasTitle;
|
||||
this.rowIndex = hasTitle ? rowIndex : 0;
|
||||
}
|
||||
@SneakyThrows
|
||||
public List<CellRangeAddress> handle(List<?> rows) {
|
||||
// 如果入参为空集合则返回空集
|
||||
@@ -103,6 +106,10 @@ public class CellMergeHandler {
|
||||
}
|
||||
|
||||
if (isAddResult && i > current) {
|
||||
//如果是同一行,则跳过合并
|
||||
if (current + rowIndex == lastRow) {
|
||||
continue;
|
||||
}
|
||||
result.add(new CellRangeAddress(current + rowIndex, lastRow, colNum, colNum));
|
||||
}
|
||||
}
|
||||
@@ -177,6 +184,16 @@ public class CellMergeHandler {
|
||||
return new FieldColumnIndex(colIndex, cellMerge);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 创建一个单元格合并处理器实例
|
||||
*
|
||||
* @param hasTitle 是否合并标题
|
||||
* @param rowIndex 行索引
|
||||
* @return 单元格合并处理器
|
||||
*/
|
||||
public static CellMergeHandler of(final boolean hasTitle, final int rowIndex) {
|
||||
return new CellMergeHandler(hasTitle, rowIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个单元格合并处理器实例
|
||||
|
||||
@@ -31,6 +31,10 @@ public class CellMergeStrategy extends AbstractMergeStrategy implements SheetWri
|
||||
this.cellList = CellMergeHandler.of(hasTitle).handle(list);
|
||||
}
|
||||
|
||||
public CellMergeStrategy(List<?> list, boolean hasTitle, int rowIndex) {
|
||||
this.cellList = CellMergeHandler.of(hasTitle, rowIndex).handle(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
|
||||
if (CollUtil.isEmpty(cellList)) {
|
||||
|
||||
@@ -88,6 +88,11 @@ public enum SensitiveStrategy {
|
||||
*/
|
||||
STRING_MASK(s -> DesensitizedUtils.mask(s, 4, 4, 4)),
|
||||
|
||||
/**
|
||||
* 高安全级别脱敏(Token / 私钥):前2位可见,后2位可见,中间全部掩码
|
||||
*/
|
||||
MASK_HIGH_SECURITY(s -> DesensitizedUtils.maskHighSecurity(s, 2, 2)),
|
||||
|
||||
/**
|
||||
* 清空为""
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ public class NicknameTranslationImpl implements TranslationInterface<String> {
|
||||
@Override
|
||||
public String translation(Object key, String other) {
|
||||
if (key instanceof Long id) {
|
||||
return userService.selectNicknameByIds(id.toString());
|
||||
return userService.selectNicknameById(id);
|
||||
} else if (key instanceof String ids) {
|
||||
return userService.selectNicknameByIds(ids);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.dromara.common.translation.core.impl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import org.dromara.common.core.service.UserService;
|
||||
import org.dromara.common.translation.annotation.TranslationType;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
@@ -19,9 +20,6 @@ public class UserNameTranslationImpl implements TranslationInterface<String> {
|
||||
|
||||
@Override
|
||||
public String translation(Object key, String other) {
|
||||
if (key instanceof Long id) {
|
||||
return userService.selectUserNameById(id);
|
||||
}
|
||||
return null;
|
||||
return userService.selectUserNameById(Convert.toLong(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ public class TestDemoServiceImpl implements ITestDemoService {
|
||||
private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(bo.getDeptId() != null, TestDemo::getDeptId, bo.getDeptId());
|
||||
lqw.eq(bo.getUserId() != null, TestDemo::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.dromara.demo.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.demo.domain.TestTree;
|
||||
@@ -9,7 +10,6 @@ import org.dromara.demo.domain.bo.TestTreeBo;
|
||||
import org.dromara.demo.domain.vo.TestTreeVo;
|
||||
import org.dromara.demo.mapper.TestTreeMapper;
|
||||
import org.dromara.demo.service.ITestTreeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -44,6 +44,8 @@ public class TestTreeServiceImpl implements ITestTreeService {
|
||||
private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(bo.getDeptId() != null, TestTree::getDeptId, bo.getDeptId());
|
||||
lqw.eq(bo.getUserId() != null, TestTree::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
||||
|
||||
@@ -4,13 +4,12 @@ import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 代码生成业务字段表 gen_table_column
|
||||
@@ -115,6 +114,7 @@ public class GenTableColumn extends BaseEntity {
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS, jdbcType = JdbcType.VARCHAR)
|
||||
private String dictType;
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,4 +92,20 @@ public interface FlowConstant {
|
||||
* 业务编码
|
||||
*/
|
||||
String BUSINESS_CODE = "businessCode";
|
||||
|
||||
/**
|
||||
* 忽略-办理权限校验(true:忽略,false:不忽略)
|
||||
*/
|
||||
String VAR_IGNORE = "ignore";
|
||||
|
||||
/**
|
||||
* 忽略-委派处理(true:忽略,false:不忽略)
|
||||
*/
|
||||
String VAR_IGNORE_DEPUTE = "ignoreDepute";
|
||||
|
||||
/**
|
||||
* 忽略-会签票签处理(true:忽略,false:不忽略)
|
||||
*/
|
||||
String VAR_IGNORE_COOPERATE = "ignoreCooperate";
|
||||
|
||||
}
|
||||
|
||||
@@ -253,4 +253,8 @@ public class FlowHisTaskVo implements Serializable {
|
||||
this.cooperateTypeName = CooperateType.getValueByKey(cooperateType);
|
||||
}
|
||||
|
||||
public String getCreateTime() {
|
||||
return DateUtils.formatFriendlyTime(createTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.dromara.workflow.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.translation.annotation.Translation;
|
||||
import org.dromara.common.translation.constant.TransConstant;
|
||||
import org.dromara.warm.flow.core.entity.User;
|
||||
@@ -8,7 +9,6 @@ import org.dromara.workflow.common.constant.FlowConstant;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -212,4 +212,8 @@ public class FlowTaskVo implements Serializable {
|
||||
private String businessTitle;
|
||||
//业务扩展信息结束
|
||||
|
||||
public String getCreateTime() {
|
||||
return DateUtils.formatFriendlyTime(createTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ public class WorkflowGlobalListener implements GlobalListener {
|
||||
String ext = listenerVariable.getNode().getExt();
|
||||
if (StringUtils.isNotBlank(ext)) {
|
||||
Map<String, Object> variable = listenerVariable.getVariable();
|
||||
if (CollUtil.isNotEmpty(variable)) {
|
||||
variable = new HashMap<>();
|
||||
}
|
||||
NodeExtVo nodeExt = nodeExtService.parseNodeExt(ext, variable);
|
||||
Set<String> copyList = nodeExt.getCopySettings();
|
||||
if (CollUtil.isNotEmpty(copyList)) {
|
||||
|
||||
@@ -208,10 +208,6 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncDef(String tenantId) {
|
||||
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>().eq(FlowDefinition::getTenantId, DEFAULT_TENANT_ID));
|
||||
if (CollUtil.isEmpty(flowDefinitions)) {
|
||||
return;
|
||||
}
|
||||
FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper<FlowCategory>()
|
||||
.eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID)
|
||||
.eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID));
|
||||
@@ -223,6 +219,11 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
|
||||
flowCategory.setUpdateBy(null);
|
||||
flowCategory.setUpdateTime(null);
|
||||
flwCategoryMapper.insert(flowCategory);
|
||||
|
||||
List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>().eq(FlowDefinition::getTenantId, DEFAULT_TENANT_ID));
|
||||
if (CollUtil.isEmpty(flowDefinitions)) {
|
||||
return;
|
||||
}
|
||||
List<Long> defIds = StreamUtils.toList(flowDefinitions, FlowDefinition::getId);
|
||||
List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().in(FlowNode::getDefinitionId, defIds));
|
||||
List<FlowSkip> flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper<FlowSkip>().in(FlowSkip::getDefinitionId, defIds));
|
||||
|
||||
@@ -232,6 +232,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
FlowParams flowParams = FlowParams.build()
|
||||
.handler(completeTaskBo.getHandler())
|
||||
.variable(variables)
|
||||
.ignore(Convert.toBool(variables.getOrDefault(VAR_IGNORE, false)))
|
||||
.ignoreDepute(Convert.toBool(variables.getOrDefault(VAR_IGNORE_DEPUTE, false)))
|
||||
.ignoreCooperate(Convert.toBool(variables.getOrDefault(VAR_IGNORE_COOPERATE, false)))
|
||||
.skipType(SkipType.PASS.getKey())
|
||||
.message(completeTaskBo.getMessage())
|
||||
.flowStatus(BusinessStatusEnum.WAITING.getStatus())
|
||||
|
||||
@@ -27,7 +27,10 @@
|
||||
d.flow_code,
|
||||
d.form_custom,
|
||||
d.category,
|
||||
COALESCE(t.form_path, d.form_path) as form_path,
|
||||
COALESCE(
|
||||
NULLIF(TRIM(t.form_path), ''),
|
||||
NULLIF(TRIM(d.form_path), '')
|
||||
) AS form_path,
|
||||
d.version,
|
||||
uu.processed_by,
|
||||
uu.type,
|
||||
|
||||
@@ -99,7 +99,7 @@ services:
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-server1:
|
||||
image: ruoyi/ruoyi-server:5.5.1
|
||||
image: ruoyi/ruoyi-server:5.5.2
|
||||
container_name: ruoyi-server1
|
||||
environment:
|
||||
# 时区上海
|
||||
@@ -115,7 +115,7 @@ services:
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-server2:
|
||||
image: ruoyi/ruoyi-server:5.5.1
|
||||
image: ruoyi/ruoyi-server:5.5.2
|
||||
container_name: ruoyi-server2
|
||||
environment:
|
||||
# 时区上海
|
||||
@@ -131,7 +131,7 @@ services:
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-monitor-admin:
|
||||
image: ruoyi/ruoyi-monitor-admin:5.5.1
|
||||
image: ruoyi/ruoyi-monitor-admin:5.5.2
|
||||
container_name: ruoyi-monitor-admin
|
||||
environment:
|
||||
# 时区上海
|
||||
@@ -143,7 +143,7 @@ services:
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-snailjob-server:
|
||||
image: ruoyi/ruoyi-snailjob-server:5.5.1
|
||||
image: ruoyi/ruoyi-snailjob-server:5.5.2
|
||||
container_name: ruoyi-snailjob-server
|
||||
environment:
|
||||
# 时区上海
|
||||
|
||||
@@ -106,11 +106,6 @@ http {
|
||||
proxy_buffering off;
|
||||
# 禁用代理缓存
|
||||
proxy_cache off;
|
||||
# 按 IP 限制连接数(防 CC 攻击) 小型站:10~20 就够 中型站:50~100
|
||||
limit_conn perip 20;
|
||||
|
||||
# 按 Server 限制总并发连接数 根据服务器的最大并发处理能力来定 太小会限制合法用户访问,太大会占满服务器资源
|
||||
limit_conn perserver 500;
|
||||
proxy_pass http://server/;
|
||||
}
|
||||
|
||||
|
||||
@@ -738,7 +738,7 @@ CREATE TABLE sj_retry_summary
|
||||
id number GENERATED ALWAYS AS IDENTITY,
|
||||
namespace_id varchar2(64) DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' NULL,
|
||||
group_name varchar2(64) DEFAULT '' NULL,
|
||||
scene_name varchar2(50) DEFAULT '' NULL,
|
||||
scene_name varchar2(64) DEFAULT '' NULL,
|
||||
trigger_at date DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
running_num number DEFAULT 0 NOT NULL,
|
||||
finish_num number DEFAULT 0 NOT NULL,
|
||||
|
||||
@@ -684,7 +684,7 @@ CREATE TABLE sj_retry_summary
|
||||
id bigserial PRIMARY KEY,
|
||||
namespace_id varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a',
|
||||
group_name varchar(64) NOT NULL DEFAULT '',
|
||||
scene_name varchar(50) NOT NULL DEFAULT '',
|
||||
scene_name varchar(64) NOT NULL DEFAULT '',
|
||||
trigger_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
running_num int NOT NULL DEFAULT 0,
|
||||
finish_num int NOT NULL DEFAULT 0,
|
||||
|
||||
@@ -423,7 +423,7 @@ CREATE TABLE `sj_retry_summary`
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`namespace_id` VARCHAR(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
|
||||
`group_name` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '组名称',
|
||||
`scene_name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '场景名称',
|
||||
`scene_name` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '场景名称',
|
||||
`trigger_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计时间',
|
||||
`running_num` int NOT NULL DEFAULT 0 COMMENT '重试中-日志数量',
|
||||
`finish_num` int NOT NULL DEFAULT 0 COMMENT '重试完成-日志数量',
|
||||
|
||||
@@ -2248,7 +2248,7 @@ CREATE TABLE sj_retry_summary
|
||||
id bigint NOT NULL PRIMARY KEY IDENTITY,
|
||||
namespace_id nvarchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a',
|
||||
group_name nvarchar(64) NOT NULL DEFAULT '',
|
||||
scene_name nvarchar(50) NOT NULL DEFAULT '',
|
||||
scene_name nvarchar(64) NOT NULL DEFAULT '',
|
||||
trigger_at datetime2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
running_num int NOT NULL DEFAULT 0,
|
||||
finish_num int NOT NULL DEFAULT 0,
|
||||
|
||||
Reference in New Issue
Block a user