Commit 98f9e44b24022b0cc7d7b743d0aae1d2fc02fda5
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot
Showing
22 changed files
with
164 additions
and
53 deletions
yudao-dependencies/pom.xml
| @@ -61,7 +61,7 @@ | @@ -61,7 +61,7 @@ | ||
| 61 | <transmittable-thread-local.version>2.14.5</transmittable-thread-local.version> | 61 | <transmittable-thread-local.version>2.14.5</transmittable-thread-local.version> |
| 62 | <commons-net.version>3.11.1</commons-net.version> | 62 | <commons-net.version>3.11.1</commons-net.version> |
| 63 | <commons-lang3.version>3.18.0</commons-lang3.version> | 63 | <commons-lang3.version>3.18.0</commons-lang3.version> |
| 64 | - <jsch.version>0.1.55</jsch.version> | 64 | + <jsch.version>2.27.3</jsch.version> |
| 65 | <tika-core.version>3.2.2</tika-core.version> | 65 | <tika-core.version>3.2.2</tika-core.version> |
| 66 | <ip2region.version>2.7.0</ip2region.version> | 66 | <ip2region.version>2.7.0</ip2region.version> |
| 67 | <bizlog-sdk.version>3.0.6</bizlog-sdk.version> | 67 | <bizlog-sdk.version>3.0.6</bizlog-sdk.version> |
| @@ -526,7 +526,7 @@ | @@ -526,7 +526,7 @@ | ||
| 526 | <version>${commons-net.version}</version> | 526 | <version>${commons-net.version}</version> |
| 527 | </dependency> | 527 | </dependency> |
| 528 | <dependency> | 528 | <dependency> |
| 529 | - <groupId>com.jcraft</groupId> | 529 | + <groupId>com.github.mwiede</groupId> |
| 530 | <artifactId>jsch</artifactId> <!-- 解决 sftp 连接 --> | 530 | <artifactId>jsch</artifactId> <!-- 解决 sftp 连接 --> |
| 531 | <version>${jsch.version}</version> | 531 | <version>${jsch.version}</version> |
| 532 | </dependency> | 532 | </dependency> |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
| @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler; | 6 | import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler; |
| 7 | import com.baomidou.mybatisplus.annotation.DbType; | 7 | import com.baomidou.mybatisplus.annotation.DbType; |
| 8 | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; | 8 | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; |
| 9 | +import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler; | ||
| 9 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | 10 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; |
| 10 | import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; | 11 | import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; |
| 11 | import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | 12 | import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; |
| @@ -80,8 +81,8 @@ public class YudaoMybatisAutoConfiguration { | @@ -80,8 +81,8 @@ public class YudaoMybatisAutoConfiguration { | ||
| 80 | throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType)); | 81 | throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType)); |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | - @Bean | ||
| 84 | - public JacksonTypeHandler jacksonTypeHandler(List<ObjectMapper> objectMappers) { | 84 | + @Bean // 特殊:返回结果使用 Object 而不用 JacksonTypeHandler 的原因,避免因为 JacksonTypeHandler 被 mybatis 全局使用! |
| 85 | + public Object jacksonTypeHandler(List<ObjectMapper> objectMappers) { | ||
| 85 | // 特殊:设置 JacksonTypeHandler 的 ObjectMapper! | 86 | // 特殊:设置 JacksonTypeHandler 的 ObjectMapper! |
| 86 | ObjectMapper objectMapper = CollUtil.getFirst(objectMappers); | 87 | ObjectMapper objectMapper = CollUtil.getFirst(objectMappers); |
| 87 | if (objectMapper == null) { | 88 | if (objectMapper == null) { |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
| @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic; | @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic; | ||
| 6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | 6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| 7 | import com.fhs.core.trans.vo.TransPojo; | 7 | import com.fhs.core.trans.vo.TransPojo; |
| 8 | import lombok.Data; | 8 | import lombok.Data; |
| 9 | +import org.apache.ibatis.type.JdbcType; | ||
| 9 | 10 | ||
| 10 | import java.io.Serializable; | 11 | import java.io.Serializable; |
| 11 | import java.time.LocalDateTime; | 12 | import java.time.LocalDateTime; |
| @@ -37,14 +38,14 @@ public abstract class BaseDO implements Serializable, TransPojo { | @@ -37,14 +38,14 @@ public abstract class BaseDO implements Serializable, TransPojo { | ||
| 37 | * | 38 | * |
| 38 | * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。 | 39 | * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。 |
| 39 | */ | 40 | */ |
| 40 | - @TableField(fill = FieldFill.INSERT) | 41 | + @TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR) |
| 41 | private String creator; | 42 | private String creator; |
| 42 | /** | 43 | /** |
| 43 | * 更新者,目前使用 SysUser 的 id 编号 | 44 | * 更新者,目前使用 SysUser 的 id 编号 |
| 44 | * | 45 | * |
| 45 | * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。 | 46 | * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。 |
| 46 | */ | 47 | */ |
| 47 | - @TableField(fill = FieldFill.INSERT_UPDATE) | 48 | + @TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR) |
| 48 | private String updater; | 49 | private String updater; |
| 49 | /** | 50 | /** |
| 50 | * 是否删除 | 51 | * 是否删除 |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
| 1 | package cn.iocoder.yudao.framework.swagger.config; | 1 | package cn.iocoder.yudao.framework.swagger.config; |
| 2 | 2 | ||
| 3 | +import com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration; | ||
| 3 | import io.swagger.v3.oas.models.Components; | 4 | import io.swagger.v3.oas.models.Components; |
| 4 | import io.swagger.v3.oas.models.OpenAPI; | 5 | import io.swagger.v3.oas.models.OpenAPI; |
| 5 | import io.swagger.v3.oas.models.info.Contact; | 6 | import io.swagger.v3.oas.models.info.Contact; |
| @@ -11,6 +12,7 @@ import io.swagger.v3.oas.models.parameters.Parameter; | @@ -11,6 +12,7 @@ import io.swagger.v3.oas.models.parameters.Parameter; | ||
| 11 | import io.swagger.v3.oas.models.security.SecurityRequirement; | 12 | import io.swagger.v3.oas.models.security.SecurityRequirement; |
| 12 | import io.swagger.v3.oas.models.security.SecurityScheme; | 13 | import io.swagger.v3.oas.models.security.SecurityScheme; |
| 13 | import org.springdoc.core.customizers.OpenApiBuilderCustomizer; | 14 | import org.springdoc.core.customizers.OpenApiBuilderCustomizer; |
| 15 | +import org.springdoc.core.customizers.OperationCustomizer; | ||
| 14 | import org.springdoc.core.customizers.ServerBaseUrlCustomizer; | 16 | import org.springdoc.core.customizers.ServerBaseUrlCustomizer; |
| 15 | import org.springdoc.core.models.GroupedOpenApi; | 17 | import org.springdoc.core.models.GroupedOpenApi; |
| 16 | import org.springdoc.core.properties.SpringDocConfigProperties; | 18 | import org.springdoc.core.properties.SpringDocConfigProperties; |
| @@ -43,7 +45,7 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_ | @@ -43,7 +45,7 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_ | ||
| 43 | * | 45 | * |
| 44 | * @author 芋道源码 | 46 | * @author 芋道源码 |
| 45 | */ | 47 | */ |
| 46 | -@AutoConfiguration | 48 | +@AutoConfiguration(before = Knife4jAutoConfiguration.class) // before 原因,保证覆写的 Knife4jOpenApiCustomizer 先生效!相关 https://github.com/YunaiV/ruoyi-vue-pro/issues/954 讨论 |
| 47 | @ConditionalOnClass({OpenAPI.class}) | 49 | @ConditionalOnClass({OpenAPI.class}) |
| 48 | @EnableConfigurationProperties(SwaggerProperties.class) | 50 | @EnableConfigurationProperties(SwaggerProperties.class) |
| 49 | @ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用 | 51 | @ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用 |
| @@ -127,6 +129,7 @@ public class YudaoSwaggerAutoConfiguration { | @@ -127,6 +129,7 @@ public class YudaoSwaggerAutoConfiguration { | ||
| 127 | .addOperationCustomizer((operation, handlerMethod) -> operation | 129 | .addOperationCustomizer((operation, handlerMethod) -> operation |
| 128 | .addParametersItem(buildTenantHeaderParameter()) | 130 | .addParametersItem(buildTenantHeaderParameter()) |
| 129 | .addParametersItem(buildSecurityHeaderParameter())) | 131 | .addParametersItem(buildSecurityHeaderParameter())) |
| 132 | + .addOperationCustomizer(buildOperationIdCustomizer()) | ||
| 130 | .build(); | 133 | .build(); |
| 131 | } | 134 | } |
| 132 | 135 | ||
| @@ -158,5 +161,26 @@ public class YudaoSwaggerAutoConfiguration { | @@ -158,5 +161,26 @@ public class YudaoSwaggerAutoConfiguration { | ||
| 158 | .schema(new StringSchema()._default("Bearer test1").name(HEADER_TENANT_ID).description("认证 Token")); // 默认:使用用户编号为 1 | 161 | .schema(new StringSchema()._default("Bearer test1").name(HEADER_TENANT_ID).description("认证 Token")); // 默认:使用用户编号为 1 |
| 159 | } | 162 | } |
| 160 | 163 | ||
| 164 | + /** | ||
| 165 | + * 核心:自定义OperationId生成规则,组合「类名前缀 + 方法名」 | ||
| 166 | + * | ||
| 167 | + * @see <a href="https://github.com/YunaiV/ruoyi-vue-pro/issues/957">app-api 前缀不生效,都是使用 admin-api</a> | ||
| 168 | + */ | ||
| 169 | + private static OperationCustomizer buildOperationIdCustomizer() { | ||
| 170 | + return (operation, handlerMethod) -> { | ||
| 171 | + // 1. 获取控制器类名(如 UserController) | ||
| 172 | + String className = handlerMethod.getBeanType().getSimpleName(); | ||
| 173 | + // 2. 提取类名前缀(去除 Controller 后缀,如 UserController -> User) | ||
| 174 | + String classPrefix = className.replaceAll("Controller$", ""); | ||
| 175 | + // 3. 获取方法名(如 list) | ||
| 176 | + String methodName = handlerMethod.getMethod().getName(); | ||
| 177 | + // 4. 组合生成 operationId(如 User_list) | ||
| 178 | + String operationId = classPrefix + "_" + methodName; | ||
| 179 | + // 5. 设置自定义 operationId | ||
| 180 | + operation.setOperationId(operationId); | ||
| 181 | + return operation; | ||
| 182 | + }; | ||
| 183 | + } | ||
| 184 | + | ||
| 161 | } | 185 | } |
| 162 | 186 |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
| 1 | package cn.iocoder.yudao.framework.web.config; | 1 | package cn.iocoder.yudao.framework.web.config; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; | 4 | import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; |
| 4 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; |
| 5 | import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; | 6 | import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; |
| @@ -7,6 +8,7 @@ import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; | @@ -7,6 +8,7 @@ import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; | ||
| 7 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | 8 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; |
| 8 | import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; | 9 | import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; |
| 9 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 10 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 11 | +import com.google.common.collect.Maps; | ||
| 10 | import jakarta.annotation.Resource; | 12 | import jakarta.annotation.Resource; |
| 11 | import jakarta.servlet.Filter; | 13 | import jakarta.servlet.Filter; |
| 12 | import org.springframework.beans.factory.annotation.Value; | 14 | import org.springframework.beans.factory.annotation.Value; |
| @@ -14,6 +16,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; | @@ -14,6 +16,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
| 14 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | 16 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| 15 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 16 | import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; | 18 | import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; |
| 19 | +import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; | ||
| 17 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 20 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 18 | import org.springframework.boot.web.client.RestTemplateBuilder; | 21 | import org.springframework.boot.web.client.RestTemplateBuilder; |
| 19 | import org.springframework.boot.web.servlet.FilterRegistrationBean; | 22 | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| @@ -26,35 +29,57 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | @@ -26,35 +29,57 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
| 26 | import org.springframework.web.filter.CorsFilter; | 29 | import org.springframework.web.filter.CorsFilter; |
| 27 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; | 30 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; |
| 28 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | 31 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| 32 | +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||
| 33 | + | ||
| 34 | +import java.util.Map; | ||
| 35 | +import java.util.function.Predicate; | ||
| 29 | 36 | ||
| 30 | @AutoConfiguration | 37 | @AutoConfiguration |
| 31 | @EnableConfigurationProperties(WebProperties.class) | 38 | @EnableConfigurationProperties(WebProperties.class) |
| 32 | -public class YudaoWebAutoConfiguration implements WebMvcConfigurer { | 39 | +public class YudaoWebAutoConfiguration { |
| 33 | 40 | ||
| 34 | - @Resource | ||
| 35 | - private WebProperties webProperties; | ||
| 36 | /** | 41 | /** |
| 37 | * 应用名 | 42 | * 应用名 |
| 38 | */ | 43 | */ |
| 39 | @Value("${spring.application.name}") | 44 | @Value("${spring.application.name}") |
| 40 | private String applicationName; | 45 | private String applicationName; |
| 41 | 46 | ||
| 42 | - @Override | ||
| 43 | - public void configurePathMatch(PathMatchConfigurer configurer) { | ||
| 44 | - configurePathMatch(configurer, webProperties.getAdminApi()); | ||
| 45 | - configurePathMatch(configurer, webProperties.getAppApi()); | ||
| 46 | - } | 47 | + @Bean |
| 48 | + public WebMvcRegistrations webMvcRegistrations(WebProperties webProperties) { | ||
| 49 | + return new WebMvcRegistrations() { | ||
| 47 | 50 | ||
| 48 | - /** | ||
| 49 | - * 设置 API 前缀,仅仅匹配 controller 包下的 | ||
| 50 | - * | ||
| 51 | - * @param configurer 配置 | ||
| 52 | - * @param api API 配置 | ||
| 53 | - */ | ||
| 54 | - private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) { | ||
| 55 | - AntPathMatcher antPathMatcher = new AntPathMatcher("."); | ||
| 56 | - configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class) | ||
| 57 | - && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包 | 51 | + @Override |
| 52 | + public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { | ||
| 53 | + var mapping = new RequestMappingHandlerMapping(); | ||
| 54 | + // 实例化时就带上前缀 | ||
| 55 | + mapping.setPathPrefixes(buildPathPrefixes(webProperties)); | ||
| 56 | + return mapping; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * 构建 prefix → 匹配条件的映射 | ||
| 61 | + */ | ||
| 62 | + private Map<String, Predicate<Class<?>>> buildPathPrefixes(WebProperties webProperties) { | ||
| 63 | + AntPathMatcher antPathMatcher = new AntPathMatcher("."); | ||
| 64 | + Map<String, Predicate<Class<?>>> pathPrefixes = Maps.newLinkedHashMapWithExpectedSize(2); | ||
| 65 | + putPathPrefix(pathPrefixes, webProperties.getAdminApi(), antPathMatcher); | ||
| 66 | + putPathPrefix(pathPrefixes, webProperties.getAppApi(), antPathMatcher); | ||
| 67 | + return pathPrefixes; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 设置 API 前缀,仅仅匹配 controller 包下的 | ||
| 72 | + */ | ||
| 73 | + private void putPathPrefix(Map<String, Predicate<Class<?>>> pathPrefixes, WebProperties.Api api, AntPathMatcher matcher) { | ||
| 74 | + if (api == null || StrUtil.isEmpty(api.getPrefix())) { | ||
| 75 | + return; | ||
| 76 | + } | ||
| 77 | + pathPrefixes.put(api.getPrefix(), // api 前缀 | ||
| 78 | + clazz -> clazz.isAnnotationPresent(RestController.class) | ||
| 79 | + && matcher.match(api.getController(), clazz.getPackage().getName())); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + }; | ||
| 58 | } | 83 | } |
| 59 | 84 | ||
| 60 | @Bean | 85 | @Bean |
yudao-module-ai/pom.xml
| @@ -78,6 +78,12 @@ | @@ -78,6 +78,12 @@ | ||
| 78 | <groupId>org.springframework.ai</groupId> | 78 | <groupId>org.springframework.ai</groupId> |
| 79 | <artifactId>spring-ai-starter-model-openai</artifactId> | 79 | <artifactId>spring-ai-starter-model-openai</artifactId> |
| 80 | <version>${spring-ai.version}</version> | 80 | <version>${spring-ai.version}</version> |
| 81 | + <exclusions> | ||
| 82 | + <exclusion> | ||
| 83 | + <groupId>io.swagger.core.v3</groupId> | ||
| 84 | + <artifactId>swagger-annotations-jakarta</artifactId> | ||
| 85 | + </exclusion> | ||
| 86 | + </exclusions> | ||
| 81 | </dependency> | 87 | </dependency> |
| 82 | <dependency> | 88 | <dependency> |
| 83 | <groupId>org.springframework.ai</groupId> | 89 | <groupId>org.springframework.ai</groupId> |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
| @@ -51,8 +51,8 @@ public class BpmProcessIdRedisDAO { | @@ -51,8 +51,8 @@ public class BpmProcessIdRedisDAO { | ||
| 51 | String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix(); | 51 | String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix(); |
| 52 | String key = RedisKeyConstants.BPM_PROCESS_ID + noPrefix; | 52 | String key = RedisKeyConstants.BPM_PROCESS_ID + noPrefix; |
| 53 | Long no = stringRedisTemplate.opsForValue().increment(key); | 53 | Long no = stringRedisTemplate.opsForValue().increment(key); |
| 54 | - if (StrUtil.isNotEmpty(infix)) { | ||
| 55 | - // 特殊:没有前缀,则不能过期,不能每次都是从 0 开始 | 54 | + if (StrUtil.isEmpty(infix)) { |
| 55 | + // 特殊:没有前缀,则不能过期,不能每次都是从 0 开始。可见 https://t.zsxq.com/MU1E2 讨论 | ||
| 56 | stringRedisTemplate.expire(key, Duration.ofDays(1L)); | 56 | stringRedisTemplate.expire(key, Duration.ofDays(1L)); |
| 57 | } | 57 | } |
| 58 | return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no); | 58 | return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no); |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -737,10 +737,10 @@ public class SimpleModelUtils { | @@ -737,10 +737,10 @@ public class SimpleModelUtils { | ||
| 737 | BoundaryEvent boundaryEvent = null; | 737 | BoundaryEvent boundaryEvent = null; |
| 738 | if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { | 738 | if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { |
| 739 | boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), | 739 | boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), |
| 740 | - node.getDelaySetting().getDelayTime(), null, null); | 740 | + null, null, node.getDelaySetting().getDelayTime()); |
| 741 | } else if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { | 741 | } else if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { |
| 742 | boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), | 742 | boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), |
| 743 | - null, null, node.getDelaySetting().getDelayTime()); | 743 | + node.getDelaySetting().getDelayTime(), null, null); |
| 744 | } else { | 744 | } else { |
| 745 | throw new UnsupportedOperationException("不支持的延迟类型:" + node.getDelaySetting()); | 745 | throw new UnsupportedOperationException("不支持的延迟类型:" + node.getDelaySetting()); |
| 746 | } | 746 | } |
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java
| @@ -7,6 +7,11 @@ import io.swagger.v3.oas.annotations.media.Schema; | @@ -7,6 +7,11 @@ import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | import lombok.Data; | 7 | import lombok.Data; |
| 8 | import lombok.EqualsAndHashCode; | 8 | import lombok.EqualsAndHashCode; |
| 9 | import lombok.ToString; | 9 | import lombok.ToString; |
| 10 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 11 | + | ||
| 12 | +import java.time.LocalDateTime; | ||
| 13 | + | ||
| 14 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 10 | 15 | ||
| 11 | @Schema(description = "管理后台 - 线索分页 Request VO") | 16 | @Schema(description = "管理后台 - 线索分页 Request VO") |
| 12 | @Data | 17 | @Data |
| @@ -42,4 +47,8 @@ public class CrmCluePageReqVO extends PageParam { | @@ -42,4 +47,8 @@ public class CrmCluePageReqVO extends PageParam { | ||
| 42 | @Schema(description = "跟进状态", example = "true") | 47 | @Schema(description = "跟进状态", example = "true") |
| 43 | private Boolean followUpStatus; | 48 | private Boolean followUpStatus; |
| 44 | 49 | ||
| 50 | + @Schema(description = "创建时间", example = "[2023-01-01 00:00:00, 2023-01-31 23:59:59]") | ||
| 51 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 52 | + private LocalDateTime[] createTime; | ||
| 53 | + | ||
| 45 | } | 54 | } |
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
| @@ -33,6 +33,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | @@ -33,6 +33,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | ||
| 33 | .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel()) | 33 | .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel()) |
| 34 | .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource()) | 34 | .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource()) |
| 35 | .eqIfPresent(CrmClueDO::getFollowUpStatus, pageReqVO.getFollowUpStatus()) | 35 | .eqIfPresent(CrmClueDO::getFollowUpStatus, pageReqVO.getFollowUpStatus()) |
| 36 | + .betweenIfPresent(CrmClueDO::getCreateTime, pageReqVO.getCreateTime()) | ||
| 36 | .orderByDesc(CrmClueDO::getId); | 37 | .orderByDesc(CrmClueDO::getId); |
| 37 | return selectJoinPage(pageReqVO, CrmClueDO.class, query); | 38 | return selectJoinPage(pageReqVO, CrmClueDO.class, query); |
| 38 | } | 39 | } |
yudao-module-infra/pom.xml
| @@ -101,7 +101,7 @@ | @@ -101,7 +101,7 @@ | ||
| 101 | <artifactId>commons-net</artifactId> <!-- 文件客户端:解决 ftp 连接 --> | 101 | <artifactId>commons-net</artifactId> <!-- 文件客户端:解决 ftp 连接 --> |
| 102 | </dependency> | 102 | </dependency> |
| 103 | <dependency> | 103 | <dependency> |
| 104 | - <groupId>com.jcraft</groupId> | 104 | + <groupId>com.github.mwiede</groupId> |
| 105 | <artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 --> | 105 | <artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 --> |
| 106 | </dependency> | 106 | </dependency> |
| 107 | <!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 --> | 107 | <!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 --> |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
| @@ -26,6 +26,7 @@ import org.springframework.validation.annotation.Validated; | @@ -26,6 +26,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 26 | import org.springframework.web.bind.annotation.*; | 26 | import org.springframework.web.bind.annotation.*; |
| 27 | import org.springframework.web.multipart.MultipartFile; | 27 | import org.springframework.web.multipart.MultipartFile; |
| 28 | 28 | ||
| 29 | +import java.nio.charset.StandardCharsets; | ||
| 29 | import java.util.List; | 30 | import java.util.List; |
| 30 | 31 | ||
| 31 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -99,8 +100,10 @@ public class FileController { | @@ -99,8 +100,10 @@ public class FileController { | ||
| 99 | if (StrUtil.isEmpty(path)) { | 100 | if (StrUtil.isEmpty(path)) { |
| 100 | throw new IllegalArgumentException("结尾的 path 路径必须传递"); | 101 | throw new IllegalArgumentException("结尾的 path 路径必须传递"); |
| 101 | } | 102 | } |
| 102 | - // 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/ | ||
| 103 | - path = URLUtil.decode(path); | 103 | + // 解码,解决中文路径的问题 |
| 104 | + // https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/ | ||
| 105 | + // https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1432/ | ||
| 106 | + path = URLUtil.decode(path, StandardCharsets.UTF_8, false); | ||
| 104 | 107 | ||
| 105 | // 读取内容 | 108 | // 读取内容 |
| 106 | byte[] content = fileService.getFileContent(configId, path); | 109 | byte[] content = fileService.getFileContent(configId, path); |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/ftp/FtpFileClient.java
| @@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil; | @@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil; | ||
| 4 | import cn.hutool.core.util.CharsetUtil; | 4 | import cn.hutool.core.util.CharsetUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.hutool.extra.ftp.Ftp; | 6 | import cn.hutool.extra.ftp.Ftp; |
| 7 | +import cn.hutool.extra.ftp.FtpConfig; | ||
| 7 | import cn.hutool.extra.ftp.FtpException; | 8 | import cn.hutool.extra.ftp.FtpException; |
| 8 | import cn.hutool.extra.ftp.FtpMode; | 9 | import cn.hutool.extra.ftp.FtpMode; |
| 9 | import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; | 10 | import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; |
| @@ -18,6 +19,15 @@ import java.io.ByteArrayOutputStream; | @@ -18,6 +19,15 @@ import java.io.ByteArrayOutputStream; | ||
| 18 | */ | 19 | */ |
| 19 | public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { | 20 | public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { |
| 20 | 21 | ||
| 22 | + /** | ||
| 23 | + * 连接超时时间,单位:毫秒 | ||
| 24 | + */ | ||
| 25 | + private static final Long CONNECTION_TIMEOUT = 3000L; | ||
| 26 | + /** | ||
| 27 | + * 读写超时时间,单位:毫秒 | ||
| 28 | + */ | ||
| 29 | + private static final Long SO_TIMEOUT = 10000L; | ||
| 30 | + | ||
| 21 | private Ftp ftp; | 31 | private Ftp ftp; |
| 22 | 32 | ||
| 23 | public FtpFileClient(Long id, FtpFileClientConfig config) { | 33 | public FtpFileClient(Long id, FtpFileClientConfig config) { |
| @@ -26,9 +36,12 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { | @@ -26,9 +36,12 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { | ||
| 26 | 36 | ||
| 27 | @Override | 37 | @Override |
| 28 | protected void doInit() { | 38 | protected void doInit() { |
| 29 | - // 初始化 Ftp 对象 | ||
| 30 | - this.ftp = new Ftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(), | ||
| 31 | - CharsetUtil.CHARSET_UTF_8, null, null, FtpMode.valueOf(config.getMode())); | 39 | + // 初始化 Ftp 对象:https://gitee.com/zhijiantianya/yudao-cloud/pulls/207/ |
| 40 | + FtpConfig ftpConfig = new FtpConfig(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(), | ||
| 41 | + CharsetUtil.CHARSET_UTF_8, null, null); | ||
| 42 | + ftpConfig.setConnectionTimeout(CONNECTION_TIMEOUT); | ||
| 43 | + ftpConfig.setSoTimeout(SO_TIMEOUT); | ||
| 44 | + this.ftp = new Ftp(ftpConfig, FtpMode.valueOf(config.getMode())); | ||
| 32 | } | 45 | } |
| 33 | 46 | ||
| 34 | @Override | 47 | @Override |
| @@ -72,4 +85,4 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { | @@ -72,4 +85,4 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> { | ||
| 72 | ftp.reconnectIfTimeout(); | 85 | ftp.reconnectIfTimeout(); |
| 73 | } | 86 | } |
| 74 | 87 | ||
| 75 | -} | ||
| 76 | \ No newline at end of file | 88 | \ No newline at end of file |
| 89 | +} |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/ftp/FtpFileClientConfig.java
| 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.ftp; | 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.ftp; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; | 3 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; |
| 4 | -import lombok.Data; | ||
| 5 | -import org.hibernate.validator.constraints.URL; | ||
| 6 | - | ||
| 7 | import jakarta.validation.constraints.NotEmpty; | 4 | import jakarta.validation.constraints.NotEmpty; |
| 8 | import jakarta.validation.constraints.NotNull; | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | ||
| 7 | +import org.hibernate.validator.constraints.URL; | ||
| 9 | 8 | ||
| 10 | /** | 9 | /** |
| 11 | * Ftp 文件客户端的配置类 | 10 | * Ftp 文件客户端的配置类 |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/sftp/SftpFileClient.java
| 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp; | 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.io.FileUtil; | 3 | import cn.hutool.core.io.FileUtil; |
| 4 | +import cn.hutool.core.util.CharsetUtil; | ||
| 5 | +import cn.hutool.core.util.StrUtil; | ||
| 6 | +import cn.hutool.extra.ftp.FtpConfig; | ||
| 7 | +import cn.hutool.extra.ssh.JschRuntimeException; | ||
| 4 | import cn.hutool.extra.ssh.Sftp; | 8 | import cn.hutool.extra.ssh.Sftp; |
| 5 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; | 9 | import cn.iocoder.yudao.framework.common.util.io.FileUtils; |
| 6 | import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; | 10 | import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; |
| 11 | +import com.jcraft.jsch.JSch; | ||
| 7 | 12 | ||
| 8 | import java.io.File; | 13 | import java.io.File; |
| 9 | 14 | ||
| @@ -14,6 +19,20 @@ import java.io.File; | @@ -14,6 +19,20 @@ import java.io.File; | ||
| 14 | */ | 19 | */ |
| 15 | public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> { | 20 | public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> { |
| 16 | 21 | ||
| 22 | + /** | ||
| 23 | + * 连接超时时间,单位:毫秒 | ||
| 24 | + */ | ||
| 25 | + private static final Long CONNECTION_TIMEOUT = 3000L; | ||
| 26 | + /** | ||
| 27 | + * 读写超时时间,单位:毫秒 | ||
| 28 | + */ | ||
| 29 | + private static final Long SO_TIMEOUT = 10000L; | ||
| 30 | + | ||
| 31 | + static { | ||
| 32 | + // 某些旧的 sftp 服务器仅支持 ssh-dss 协议,该协议并不安全,默认不支持该协议,按需添加 | ||
| 33 | + JSch.setConfig("server_host_key", JSch.getConfig("server_host_key") + ",ssh-dss"); | ||
| 34 | + } | ||
| 35 | + | ||
| 17 | private Sftp sftp; | 36 | private Sftp sftp; |
| 18 | 37 | ||
| 19 | public SftpFileClient(Long id, SftpFileClientConfig config) { | 38 | public SftpFileClient(Long id, SftpFileClientConfig config) { |
| @@ -22,18 +41,27 @@ public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> { | @@ -22,18 +41,27 @@ public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> { | ||
| 22 | 41 | ||
| 23 | @Override | 42 | @Override |
| 24 | protected void doInit() { | 43 | protected void doInit() { |
| 25 | - // 初始化 Ftp 对象 | ||
| 26 | - this.sftp = new Sftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword()); | 44 | + // 初始化 Sftp 对象 |
| 45 | + FtpConfig ftpConfig = new FtpConfig(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(), | ||
| 46 | + CharsetUtil.CHARSET_UTF_8, null, null); | ||
| 47 | + ftpConfig.setConnectionTimeout(CONNECTION_TIMEOUT); | ||
| 48 | + ftpConfig.setSoTimeout(SO_TIMEOUT); | ||
| 49 | + this.sftp = new Sftp(ftpConfig); | ||
| 27 | } | 50 | } |
| 28 | 51 | ||
| 29 | @Override | 52 | @Override |
| 30 | public String upload(byte[] content, String path, String type) { | 53 | public String upload(byte[] content, String path, String type) { |
| 31 | // 执行写入 | 54 | // 执行写入 |
| 32 | String filePath = getFilePath(path); | 55 | String filePath = getFilePath(path); |
| 56 | + String fileName = FileUtil.getName(filePath); | ||
| 57 | + String dir = StrUtil.removeSuffix(filePath, fileName); | ||
| 33 | File file = FileUtils.createTempFile(content); | 58 | File file = FileUtils.createTempFile(content); |
| 34 | reconnectIfTimeout(); | 59 | reconnectIfTimeout(); |
| 35 | - sftp.mkDirs(FileUtil.getParent(filePath, 1)); // 需要创建父目录,不然会报错 | ||
| 36 | - sftp.upload(filePath, file); | 60 | + sftp.mkDirs(dir); // 需要创建父目录,不然会报错 |
| 61 | + boolean success = sftp.upload(filePath, file); | ||
| 62 | + if (!success) { | ||
| 63 | + throw new JschRuntimeException(StrUtil.format("上传文件到目标目录 ({}) 失败", filePath)); | ||
| 64 | + } | ||
| 37 | // 拼接返回路径 | 65 | // 拼接返回路径 |
| 38 | return super.formatFileUrl(config.getDomain(), path); | 66 | return super.formatFileUrl(config.getDomain(), path); |
| 39 | } | 67 | } |
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/sftp/SftpFileClientConfig.java
| 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp; | 1 | package cn.iocoder.yudao.module.infra.framework.file.core.client.sftp; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; | 3 | import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig; |
| 4 | -import lombok.Data; | ||
| 5 | -import org.hibernate.validator.constraints.URL; | ||
| 6 | - | ||
| 7 | import jakarta.validation.constraints.NotEmpty; | 4 | import jakarta.validation.constraints.NotEmpty; |
| 8 | import jakarta.validation.constraints.NotNull; | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | ||
| 7 | +import org.hibernate.validator.constraints.URL; | ||
| 9 | 8 | ||
| 10 | /** | 9 | /** |
| 11 | * Sftp 文件客户端的配置类 | 10 | * Sftp 文件客户端的配置类 |
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotDeviceMessageMethodEnum.java
| @@ -43,7 +43,7 @@ public enum IotDeviceMessageMethodEnum implements ArrayValuable<String> { | @@ -43,7 +43,7 @@ public enum IotDeviceMessageMethodEnum implements ArrayValuable<String> { | ||
| 43 | // ========== 设备配置 ========== | 43 | // ========== 设备配置 ========== |
| 44 | // 可参考:https://help.aliyun.com/zh/iot/user-guide/remote-configuration-1 | 44 | // 可参考:https://help.aliyun.com/zh/iot/user-guide/remote-configuration-1 |
| 45 | 45 | ||
| 46 | - CONFIG_PUSH("thing.config.push", "配置推送", true), | 46 | + CONFIG_PUSH("thing.config.push", "配置推送", false), |
| 47 | 47 | ||
| 48 | // ========== OTA 固件 ========== | 48 | // ========== OTA 固件 ========== |
| 49 | // 可参考:https://help.aliyun.com/zh/iot/user-guide/perform-ota-updates | 49 | // 可参考:https://help.aliyun.com/zh/iot/user-guide/perform-ota-updates |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/manager/IotMqttConnectionManager.java
| @@ -125,7 +125,7 @@ public class IotMqttConnectionManager { | @@ -125,7 +125,7 @@ public class IotMqttConnectionManager { | ||
| 125 | */ | 125 | */ |
| 126 | public IotMqttConnectionManager.ConnectionInfo getConnectionInfoByDeviceId(Long deviceId) { | 126 | public IotMqttConnectionManager.ConnectionInfo getConnectionInfoByDeviceId(Long deviceId) { |
| 127 | // 通过设备 ID 获取连接端点 | 127 | // 通过设备 ID 获取连接端点 |
| 128 | - var endpoint = getDeviceEndpoint(deviceId); | 128 | + MqttEndpoint endpoint = getDeviceEndpoint(deviceId); |
| 129 | if (endpoint == null) { | 129 | if (endpoint == null) { |
| 130 | return null; | 130 | return null; |
| 131 | } | 131 | } |
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/reward/vo/RewardActivityRespVO.java
| @@ -14,7 +14,7 @@ import java.time.LocalDateTime; | @@ -14,7 +14,7 @@ import java.time.LocalDateTime; | ||
| 14 | public class RewardActivityRespVO extends RewardActivityBaseVO { | 14 | public class RewardActivityRespVO extends RewardActivityBaseVO { |
| 15 | 15 | ||
| 16 | @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 16 | @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 17 | - private Integer id; | 17 | + private Long id; |
| 18 | 18 | ||
| 19 | @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 19 | @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 20 | private Integer status; | 20 | private Integer status; |
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| @@ -284,8 +284,8 @@ public class CouponServiceImpl implements CouponService { | @@ -284,8 +284,8 @@ public class CouponServiceImpl implements CouponService { | ||
| 284 | } | 284 | } |
| 285 | // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) | 285 | // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) |
| 286 | if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) | 286 | if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) |
| 287 | - && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制 | ||
| 288 | - && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { | 287 | + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 校验不限制领取数 |
| 288 | + && ObjUtil.notEqual(couponTemplate.getTotalCount(), CouponTemplateDO.TOTAL_COUNT_MAX) // 校验不限制发放数量 | ||
| 289 | throw exception(COUPON_TEMPLATE_NOT_ENOUGH); | 289 | throw exception(COUPON_TEMPLATE_NOT_ENOUGH); |
| 290 | } | 290 | } |
| 291 | // 校验"固定日期"的有效期类型是否过期 | 291 | // 校验"固定日期"的有效期类型是否过期 |
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
| @@ -610,7 +610,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { | @@ -610,7 +610,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { | ||
| 610 | orderExtensionMapper.insert(orderExtension); | 610 | orderExtensionMapper.insert(orderExtension); |
| 611 | // 重要:需要将 order 的 extensionId 更新下 | 611 | // 重要:需要将 order 的 extensionId 更新下 |
| 612 | order.setExtensionId(orderExtension.getId()); | 612 | order.setExtensionId(orderExtension.getId()); |
| 613 | - orderMapper.updateById(new PayOrderDO().setId(order.getId()).setExtensionId(orderExtension.getId())); | 613 | + orderMapper.updateById(order); |
| 614 | // 准备参数 | 614 | // 准备参数 |
| 615 | PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | 615 | PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); |
| 616 | PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, | 616 | PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java
| @@ -54,6 +54,7 @@ import me.zhyd.oauth.model.AuthResponse; | @@ -54,6 +54,7 @@ import me.zhyd.oauth.model.AuthResponse; | ||
| 54 | import me.zhyd.oauth.model.AuthUser; | 54 | import me.zhyd.oauth.model.AuthUser; |
| 55 | import me.zhyd.oauth.request.AuthRequest; | 55 | import me.zhyd.oauth.request.AuthRequest; |
| 56 | import me.zhyd.oauth.utils.AuthStateUtils; | 56 | import me.zhyd.oauth.utils.AuthStateUtils; |
| 57 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 57 | import org.springframework.beans.factory.annotation.Value; | 58 | import org.springframework.beans.factory.annotation.Value; |
| 58 | import org.springframework.cache.annotation.Cacheable; | 59 | import org.springframework.cache.annotation.Cacheable; |
| 59 | import org.springframework.data.redis.core.StringRedisTemplate; | 60 | import org.springframework.data.redis.core.StringRedisTemplate; |
| @@ -101,7 +102,8 @@ public class SocialClientServiceImpl implements SocialClientService { | @@ -101,7 +102,8 @@ public class SocialClientServiceImpl implements SocialClientService { | ||
| 101 | @Value("${yudao.wxa-subscribe-message.miniprogram-state:formal}") | 102 | @Value("${yudao.wxa-subscribe-message.miniprogram-state:formal}") |
| 102 | public String miniprogramState; | 103 | public String miniprogramState; |
| 103 | 104 | ||
| 104 | - @Resource | 105 | + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") |
| 106 | + @Autowired(required = false) // 由于 justauth.enable 配置项,可以关闭 AuthRequestFactory 的功能,所以这里只能不强制注入 | ||
| 105 | private AuthRequestFactory authRequestFactory; | 107 | private AuthRequestFactory authRequestFactory; |
| 106 | 108 | ||
| 107 | @Resource | 109 | @Resource |