mirror of
https://gitee.com/yudaocode/yudao-boot-mini.git
synced 2026-03-22 05:27:15 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts: # yudao-module-ai/pom.xml # yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java # yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java # yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmCopyTaskDelegate.java # yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java # yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImplTest.java # yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue2Test.java # yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue3Test.java # yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java # yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java # yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java # yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java # yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java # yudao-module-member/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java # yudao-module-pay/pom.xml # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletRechargeController.java # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java # yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java # yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java # yudao-module-system/src/test/resources/sql/create_tables.sql
This commit is contained in:
@@ -27,10 +27,10 @@ public class PageParam implements Serializable {
|
||||
@Min(value = 1, message = "页码最小值为 1")
|
||||
private Integer pageNo = PAGE_NO;
|
||||
|
||||
@Schema(description = "每页条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@Schema(description = "每页条数,最大值为 200", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "每页条数不能为空")
|
||||
@Min(value = 1, message = "每页条数最小值为 1")
|
||||
@Max(value = 100, message = "每页条数最大值为 100")
|
||||
@Max(value = 200, message = "每页条数最大值为 200")
|
||||
private Integer pageSize = PAGE_SIZE;
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -37,6 +38,17 @@ public class HttpUtils {
|
||||
return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码 URL 参数
|
||||
*
|
||||
* @param value 参数
|
||||
* @return 解码后的参数
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static String decodeUtf8(String value) {
|
||||
return URLDecoder.decode(value, StandardCharsets.UTF_8.name());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String replaceUrlQuery(String url, String key, String value) {
|
||||
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());
|
||||
|
||||
@@ -1,42 +1,85 @@
|
||||
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 基于时间戳的 LocalDateTime 序列化器
|
||||
*
|
||||
* @author 老五
|
||||
*/
|
||||
@Slf4j
|
||||
public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
||||
|
||||
public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
|
||||
|
||||
private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
String fieldName = gen.getOutputContext().getCurrentName();
|
||||
Class<?> clazz = gen.getOutputContext().getCurrentValue().getClass();
|
||||
Field field = ReflectUtil.getField(clazz, fieldName);
|
||||
// 情况一:有 JsonFormat 自定义注解,则使用它。https://github.com/YunaiV/ruoyi-vue-pro/pull/1019
|
||||
JsonFormat[] jsonFormats = field.getAnnotationsByType(JsonFormat.class);
|
||||
if (jsonFormats.length > 0) {
|
||||
String pattern = jsonFormats[0].pattern();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
gen.writeString(formatter.format(value));
|
||||
return;
|
||||
String fieldName = gen.getOutputContext().getCurrentName();
|
||||
if (fieldName != null) {
|
||||
Object currentValue = gen.getOutputContext().getCurrentValue();
|
||||
if (currentValue != null) {
|
||||
Class<?> clazz = currentValue.getClass();
|
||||
Map<String, Field> fieldMap = FIELD_CACHE.computeIfAbsent(clazz, this::buildFieldMap);
|
||||
Field field = fieldMap.get(fieldName);
|
||||
// 进一步修复:https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1480
|
||||
if (field != null && field.isAnnotationPresent(JsonFormat.class)) {
|
||||
JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class);
|
||||
try {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonFormat.pattern());
|
||||
gen.writeString(formatter.format(value));
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
log.warn("[serialize][({}#{}) 使用 JsonFormat pattern 失败,尝试使用默认的 Long 时间戳]",
|
||||
clazz.getName(), fieldName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 情况二:默认将 LocalDateTime 对象,转换为 Long 时间戳
|
||||
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建字段映射(缓存)
|
||||
*
|
||||
* @param clazz 类
|
||||
* @return 字段映射
|
||||
*/
|
||||
private Map<String, Field> buildFieldMap(Class<?> clazz) {
|
||||
Map<String, Field> fieldMap = new HashMap<>();
|
||||
for (Field field : ReflectUtil.getFields(clazz)) {
|
||||
String fieldName = field.getName();
|
||||
JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
|
||||
if (jsonProperty != null) {
|
||||
String value = jsonProperty.value();
|
||||
if (StrUtil.isNotEmpty(value) && ObjUtil.notEqual("\u0000", value)) {
|
||||
fieldName = value;
|
||||
}
|
||||
}
|
||||
fieldMap.put(fieldName, field);
|
||||
}
|
||||
return fieldMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.framework.tenant.core.redis;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.redis.core.TimeoutRedisCacheManager;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -21,6 +22,8 @@ import java.util.Set;
|
||||
@Slf4j
|
||||
public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
|
||||
|
||||
private static final String SPLIT = "#";
|
||||
|
||||
private final Set<String> ignoreCaches;
|
||||
|
||||
public TenantRedisCacheManager(RedisCacheWriter cacheWriter,
|
||||
@@ -32,10 +35,11 @@ public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
|
||||
|
||||
@Override
|
||||
public Cache getCache(String name) {
|
||||
String[] names = StrUtil.splitToArray(name, SPLIT);
|
||||
// 如果开启多租户,则 name 拼接租户后缀
|
||||
if (!TenantContextHolder.isIgnore()
|
||||
&& TenantContextHolder.getTenantId() != null
|
||||
&& !CollUtil.contains(ignoreCaches, name)) {
|
||||
&& TenantContextHolder.getTenantId() != null
|
||||
&& !CollUtil.contains(ignoreCaches, names[0])) {
|
||||
name = name + ":" + TenantContextHolder.getTenantId();
|
||||
}
|
||||
|
||||
@@ -43,4 +47,4 @@ public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
|
||||
return super.getCache(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user