diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index 5da557089..0a19bf8e7 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -138,6 +138,12 @@ jsoup + + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java index bfb291b6d..e29292dd8 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java @@ -41,7 +41,7 @@ public class CommonResult implements Serializable { * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。 * * @param result 传入的 result 对象 - * @param 返回的泛型 + * @param 返回的泛型 * @return 新的 CommonResult 对象 */ public static CommonResult error(CommonResult result) { diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java index 98411730e..07a68b064 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortingField.java @@ -1,5 +1,9 @@ package cn.iocoder.yudao.framework.common.pojo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.io.Serializable; /** @@ -7,6 +11,9 @@ import java.io.Serializable; * * 类名加了 ing 的原因是,避免和 ES SortField 重名。 */ +@Data +@NoArgsConstructor +@AllArgsConstructor public class SortingField implements Serializable { /** @@ -27,30 +34,4 @@ public class SortingField implements Serializable { */ private String order; - // 空构造方法,解决反序列化 - public SortingField() { - } - - public SortingField(String field, String order) { - this.field = field; - this.order = order; - } - - public String getField() { - return field; - } - - public SortingField setField(String field) { - this.field = field; - return this; - } - - public String getOrder() { - return order; - } - - public SortingField setOrder(String order) { - this.order = order; - return this; - } } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index ad79784ed..732592ac3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -27,7 +27,7 @@ public class ServletUtils { * 返回 JSON 字符串 * * @param response 响应 - * @param object 对象,会序列化成 JSON 字符串 + * @param object 对象,会序列化成 JSON 字符串 */ @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 public static void writeJSON(HttpServletResponse response, Object object) { @@ -40,7 +40,7 @@ public class ServletUtils { * * @param response 响应 * @param filename 文件名 - * @param content 附件内容 + * @param content 附件内容 */ public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { // 设置 header 和 contentType @@ -88,6 +88,8 @@ public class ServletUtils { return ServletUtil.getClientIP(request); } + // TODO @疯狂:terminal 还是从 ServletUtils 里拿,更容易全局治理; + public static boolean isJsonRequest(ServletRequest request) { return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); } @@ -107,4 +109,5 @@ public class ServletUtils { public static Map getParamMap(HttpServletRequest request) { return ServletUtil.getParamMap(request); } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index 5e82d5e3b..ae8bcf904 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.common.util.spring; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; -import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -87,47 +86,4 @@ public class SpringExpressionUtils { return result; } - /** - * JoinPoint 切面 批量解析 EL 表达式,转换 jspl参数 - * - * @param joinPoint 切面点 - * @param info 返回值 - * @param expressionStrings EL 表达式数组 - * @return Map 结果 - * @author 陈賝 - * @since 2023/6/18 11:20 - */ - // TODO @chenchen: 这个方法,和 parseExpressions 比较接近,是不是可以合并下; - public static Map parseExpression(JoinPoint joinPoint, Object info, List expressionStrings) { - // 如果为空,则不进行解析 - if (CollUtil.isEmpty(expressionStrings)) { - return MapUtil.newHashMap(); - } - - // 第一步,构建解析的上下文 EvaluationContext - // 通过 joinPoint 获取被注解方法 - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 - String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); - // Spring 的表达式上下文对象 - EvaluationContext context = new StandardEvaluationContext(); - if (ArrayUtil.isNotEmpty(parameterNames)) { - //获取方法参数值 - Object[] args = joinPoint.getArgs(); - for (int i = 0; i < args.length; i++) { - // 替换 SP EL 里的变量值为实际值, 比如 #user --> user对象 - context.setVariable(parameterNames[i], args[i]); - } - context.setVariable("info", info); - } - // 第二步,逐个参数解析 - Map result = MapUtil.newHashMap(expressionStrings.size(), true); - expressionStrings.forEach(key -> { - Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); - result.put(key, value); - }); - return result; - } - } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java index c2d56b0c5..139b08965 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java @@ -17,7 +17,7 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( - validatedBy = InEnumValidator.class + validatedBy = {InEnumValidator.class, InEnumCollectionValidator.class} ) public @interface InEnum { diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java new file mode 100644 index 000000000..d20a71703 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.framework.common.validation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class InEnumCollectionValidator implements ConstraintValidator> { + + private List values; + + @Override + public void initialize(InEnum annotation) { + IntArrayValuable[] values = annotation.value().getEnumConstants(); + if (values.length == 0) { + this.values = Collections.emptyList(); + } else { + this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList()); + } + } + + @Override + public boolean isValid(Collection list, ConstraintValidatorContext context) { + // 校验通过 + if (CollUtil.containsAll(values, list)) { + return true; + } + // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值) + context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 + context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate() + .replaceAll("\\{value}", CollUtil.join(list, ","))).addConstraintViolation(); // 重新添加错误提示语句 + return false; + } + +} + diff --git a/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java b/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java new file mode 100644 index 000000000..0e44645bc --- /dev/null +++ b/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.framework.common.util.collection; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.BiFunction; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link CollectionUtils} 的单元测试 + */ +public class CollectionUtilsTest { + + @Data + @AllArgsConstructor + private static class Dog { + + private Integer id; + private String name; + private String code; + + } + + @Test + public void testDiffList() { + // 准备参数 + Collection oldList = Arrays.asList( + new Dog(1, "花花", "hh"), + new Dog(2, "旺财", "wc") + ); + Collection newList = Arrays.asList( + new Dog(null, "花花2", "hh"), + new Dog(null, "小白", "xb") + ); + BiFunction sameFunc = (oldObj, newObj) -> { + boolean same = oldObj.getCode().equals(newObj.getCode()); + // 如果相等的情况下,需要设置下 id,后续好更新 + if (same) { + newObj.setId(oldObj.getId()); + } + return same; + }; + + // 调用 + List> result = CollectionUtils.diffList(oldList, newList, sameFunc); + // 断言 + assertEquals(result.size(), 3); + // 断言 create + assertEquals(result.get(0).size(), 1); + assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb")); + // 断言 update + assertEquals(result.get(1).size(), 1); + assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh")); + // 断言 delete + assertEquals(result.get(2).size(), 1); + assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc")); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java index 50485cb93..98f64d11a 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java @@ -507,7 +507,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme // 单条规则的条件 String tableName = MyBatisUtils.getTableName(table); Expression oneExpress = rule.getExpression(tableName, table.getAlias()); - if(oneExpress == null){ + if (oneExpress == null){ continue; } // 拼接到 allExpression 中 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DictFrameworkUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java similarity index 93% rename from yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DictFrameworkUtilsTest.java rename to yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java index f0a6eb1a6..cb34cac68 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DictFrameworkUtilsTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java @@ -1,8 +1,7 @@ -package cn.iocoder.yudao.framework.datapermission.core.util; +package cn.iocoder.yudao.framework.dict.core.util; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java index 852f4e29b..b9a226fdb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java @@ -11,40 +11,40 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface SmsFrameworkErrorCodeConstants { - ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); + ErrorCode SMS_UNKNOWN = new ErrorCode(2_001_000_000, "未知错误,需要解析"); - // ========== 权限 / 限流等相关 2001000100 ========== + // ========== 权限 / 限流等相关 2-001-000-100 ========== - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); - ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); + ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2_001_000_100, "没有发送短信的权限"); + ErrorCode SMS_IP_DENY = new ErrorCode(2_001_000_100, "IP 不允许发送短信"); // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); + ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2_001_000_102, "指定手机的发送限流"); // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); + ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2_001_000_103, "每天的发送限流"); - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); + ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2_001_000_104, "短信内容有敏感词"); // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。 - ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2001000105, "营销短信发送时间限制"); + ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2_001_000_105, "营销短信发送时间限制"); - // ========== 模板相关 2001000200 ========== - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); + // ========== 模板相关 2-001-000-200 ========== + ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2_001_000_200, "短信模板不合法"); // 包括短信模板不存在 + ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2_001_000_201, "模板参数不正确"); - // ========== 签名相关 2001000300 ========== - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); + // ========== 签名相关 2-001-000-300 ========== + ErrorCode SMS_SIGN_INVALID = new ErrorCode(2_001_000_300, "短信签名不可用"); - // ========== 账户相关 2001000400 ========== - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); + // ========== 账户相关 2-001-000-400 ========== + ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2_001_000_400, "账户余额不足"); + ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2_001_000_401, "apiKey 不存在"); - // ========== 其它相关 2001000900 开头 ========== - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); - ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2001000903, "SdkAppId不合法"); + // ========== 其它相关 2-001-000-900 开头 ========== + ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2_001_000_900, "请求参数缺失"); + ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2_001_000_901, "手机格式不正确"); + ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2_001_000_902, "手机号在黑名单中"); + ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2_001_000_903, "SdkAppId不合法"); - ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常"); + ErrorCode EXCEPTION = new ErrorCode(2_001_000_999, "调用异常"); } diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java index ad6ef439f..2797e2117 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java @@ -8,6 +8,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.BatchStrategies; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; @@ -62,10 +63,12 @@ public class YudaoCacheAutoConfiguration { @Bean public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate, - RedisCacheConfiguration redisCacheConfiguration) { + RedisCacheConfiguration redisCacheConfiguration, + YudaoCacheProperties yudaoCacheProperties) { // 创建 RedisCacheWriter 对象 RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory()); - RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory, + BatchStrategies.scan(yudaoCacheProperties.getRedisScanBatchSize())); // 创建 TenantRedisCacheManager 对象 return new TimeoutRedisCacheManager(cacheWriter, redisCacheConfiguration); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java index b42a58c7c..6ea95b196 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java @@ -7,11 +7,17 @@ import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer; import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; @AutoConfiguration @@ -27,6 +33,10 @@ public class YudaoJacksonAutoConfiguration { // 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型 .addSerializer(Long.class, NumberSerializer.INSTANCE) .addSerializer(Long.TYPE, NumberSerializer.INSTANCE) + .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE) + .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE) + .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE) + .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE) // 新增 LocalDateTime 序列化、反序列化规则 .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE) .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java index f4cb71330..53c40254b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.framework.jackson.core.databind; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -20,7 +19,7 @@ public class LocalDateTimeDeserializer extends JsonDeserializer { public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer(); @Override - public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault()); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java index b20f43b6c..1dd762280 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java @@ -258,12 +258,12 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { Long id = fileConfig.getId(); // mock 获得 Client FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig()); - when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient); + when(fileClientFactory.getFileClient(eq(fileConfig.getId()))).thenReturn(fileClient); // 调用,并断言 assertSame(fileClient, fileConfigService.getMasterFileClient()); // 断言缓存 - verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()), + verify(fileClientFactory).createOrUpdateFileClient(eq(fileConfig.getId()), eq(fileConfig.getStorage()), eq(fileConfig.getConfig())); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java index 197bb2943..602eb1e63 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java @@ -18,33 +18,39 @@ public enum SocialTypeEnum implements IntArrayValuable { /** * Gitee - * 文档链接:https://gitee.com/api/v5/oauth_doc#/ + * + * @see 接入文档 */ GITEE(10, "GITEE"), /** * 钉钉 - * 文档链接:https://developers.dingtalk.com/document/app/obtain-identity-credentials + * + * @see 接入文档 */ DINGTALK(20, "DINGTALK"), /** * 企业微信 - * 文档链接:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html + * + * @see 接入文档 */ WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), /** * 微信公众平台 - 移动端 H5 - * 文档链接:https://www.cnblogs.com/juewuzhe/p/11905461.html + * + * @see 接入文档 */ WECHAT_MP(31, "WECHAT_MP"), /** * 微信开放平台 - 网站应用 PC 端扫码授权登录 - * 文档链接:https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证 + * + * @see 接入文档 */ WECHAT_OPEN(32, "WECHAT_OPEN"), /** * 微信小程序 - * 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html + * + * @see 接入文档 */ WECHAT_MINI_APP(34, "WECHAT_MINI_APP"), ; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java index b3bc0c03c..2d5c766fd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -6,17 +6,17 @@ import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.IPUtils; import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; -import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; import java.util.List; -import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -34,28 +34,6 @@ public class AreaController { return success(AreaConvert.INSTANCE.convertList(area.getChildren())); } - @GetMapping("/get-children") - @Operation(summary = "获得地区的下级区域") - @Parameter(name = "id", description = "区域编号", required = true, example = "150000") - public CommonResult> getChildren(@RequestParam("id") Integer id) { - Area area = AreaUtils.getArea(id); - Assert.notNull(area, String.format("获取不到 id : %d 的区域", id)); - return success(AreaConvert.INSTANCE.convertList2(area.getChildren())); - } - - // 4)方法改成 getAreaChildrenList 获得子节点们;5)url 可以已改成 children-list - //@芋艿 是不是叫 getAreaListByIds 更合适。 因为不一定是子节点。 用于前端树选择获取缓存数据。 见 - @GetMapping("/get-by-ids") - @Operation(summary = "通过区域 ids 获得地区列表") - @Parameter(name = "ids", description = "区域编号 ids", required = true, example = "1,150000") - public CommonResult> getAreaListByIds(@RequestParam("ids") Set ids) { - List areaList = new ArrayList<>(ids.size()); - for (Integer areaId : ids) { - areaList.add(AreaUtils.getArea(areaId)); - } - return success(AreaConvert.INSTANCE.convertList2(areaList)); - } - @GetMapping("/get-by-ip") @Operation(summary = "获得 IP 对应的地区名") @Parameter(name = "ip", description = "IP", required = true) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java deleted file mode 100644 index a37430248..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.ip.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 简洁的地区节点 Response VO") -@Data -public class AreaNodeSimpleRespVO { - - @Schema(description = "编号", required = true, example = "110000") - private Integer id; - - @Schema(description = "名字", required = true, example = "北京") - private String name; - - @Schema(description = "是否叶子节点", required = false, example = "false") - private Boolean leaf; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java index c4946c371..1f4f78c80 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java @@ -1,4 +1,39 @@ package cn.iocoder.yudao.module.system.controller.app.dict; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.system.controller.app.dict.vo.AppDictDataRespVO; +import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 字典数据") +@RestController +@RequestMapping("/system/dict-data") +@Validated public class AppDictDataController { + + @Resource + private DictDataService dictDataService; + + @GetMapping("/type") + @Operation(summary = "根据字典类型查询字典数据信息") + @Parameter(name = "type", description = "字典类型", required = true, example = "common_status") + public CommonResult> getDictDataListByType(@RequestParam("type") String type) { + List list = dictDataService.getEnabledDictDataListByType(type); + return success(DictDataConvert.INSTANCE.convertList03(list)); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/vo/AppDictDataRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/vo/AppDictDataRespVO.java new file mode 100644 index 000000000..5e3bc1c13 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/vo/AppDictDataRespVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.controller.app.dict.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "用户 App - 字典数据信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AppDictDataRespVO { + + @Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String label; + + @Schema(description = "字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "iocoder") + private String value; + + @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex") + private String dictType; + +}