From f141d64eb2bd755a44564157d3c5254506230d11 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 6 Feb 2025 16:05:56 +0800 Subject: [PATCH 01/17] =?UTF-8?q?=E3=80=90=E4=BE=9D=E8=B5=96=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E3=80=91AWS=20SDK=20for=20Java=201.x=20to=202.x?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 16 +- .../yudao-module-infra-biz/pom.xml | 13 +- .../file/core/client/s3/S3FileClient.java | 174 ++++++++++++------ 3 files changed, 133 insertions(+), 70 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 4ecaa83e29..9787ede53c 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -68,7 +68,7 @@ 2.17.0 1.27.1 - 1.12.777 + 2.30.14 2.0.5 1.8.1 4.6.0 @@ -91,6 +91,13 @@ pom import + + software.amazon.awssdk + bom + ${awssdk.version} + pom + import + @@ -538,13 +545,6 @@ ${jsoup.version} - - - com.amazonaws - aws-java-sdk-s3 - ${aws-java-sdk-s3.version} - - com.xingyuv spring-boot-starter-justauth diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index 9786c000dd..3c40314889 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -115,9 +115,18 @@ com.jcraft jsch + - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 + + + software.amazon.awssdk + auth + + + software.amazon.awssdk + regions diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java index 5c76e1a7c8..16a49bba4e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java @@ -4,65 +4,68 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; -import com.amazonaws.HttpMethod; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.S3Object; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; +import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; -import java.io.ByteArrayInputStream; -import java.util.Date; -import java.util.concurrent.TimeUnit; +import java.net.URI; +import java.time.Duration; /** * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务 - *

- * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库 * * @author 芋道源码 */ public class S3FileClient extends AbstractFileClient { - private AmazonS3Client client; + private S3Client client; public S3FileClient(Long id, S3FileClientConfig config) { super(id, config); } - @Override - protected void doInit() { - // 补全 domain - if (StrUtil.isEmpty(config.getDomain())) { - config.setDomain(buildDomain()); - } - // 初始化客户端 - client = (AmazonS3Client)AmazonS3ClientBuilder.standard() - .withCredentials(buildCredentials()) - .withEndpointConfiguration(buildEndpointConfiguration()) + /** + * 动态创建 S3Presigner + * + * @param endpoint 节点地址 + * @param accessKey 访问 Key + * @param secretKey 访问 Secret + * @return S3Presigner + */ + private static S3Presigner createPresigner(String endpoint, String accessKey, String secretKey) { + return S3Presigner.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) + .endpointOverride(URI.create(endpoint)) .build(); } /** - * 基于 config 秘钥,构建 S3 客户端的认证信息 + * 生成动态的预签名上传 URL * - * @return S3 客户端的认证信息 + * @param bucket 存储 Bucket + * @param path 相对路径 + * @param duration 过期时间 + * @param endpoint 节点地址 + * @param accessKey 访问 Key + * @param secretKey 访问 Secret + * @return 生成的上传 URL */ - private AWSStaticCredentialsProvider buildCredentials() { - return new AWSStaticCredentialsProvider( - new BasicAWSCredentials(config.getAccessKey(), config.getAccessSecret())); - } - - /** - * 构建 S3 客户端的 Endpoint 配置,包括 region、endpoint - * - * @return S3 客户端的 EndpointConfiguration 配置 - */ - private AwsClientBuilder.EndpointConfiguration buildEndpointConfiguration() { - return new AwsClientBuilder.EndpointConfiguration(config.getEndpoint(), - null); // 无需设置 region + public static String getPresignedUrl(String bucket, String path, Duration duration, + String endpoint, String accessKey, String secretKey) { + try (S3Presigner presigner = createPresigner(endpoint, accessKey, secretKey)) { + return presigner.presignPutObject(PutObjectPresignRequest.builder() + .signatureDuration(duration) + .putObjectRequest(b -> b.bucket(bucket).key(path)) + .build()).url().toString(); + } } /** @@ -80,39 +83,90 @@ public class S3FileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path, String type) throws Exception { - // 元数据,主要用于设置文件类型 - ObjectMetadata objectMetadata = new ObjectMetadata(); - objectMetadata.setContentType(type); - objectMetadata.setContentLength(content.length); // 如果不设置,会有 “ No content length specified for stream data” 警告日志 - // 执行上传 - client.putObject(config.getBucket(), - path, // 相对路径 - new ByteArrayInputStream(content), // 文件内容 - objectMetadata); + protected void doInit() { + // 补全 domain + if (StrUtil.isEmpty(config.getDomain())) { + config.setDomain(buildDomain()); + } + // 初始化 S3 客户端 + client = S3Client.builder() + .credentialsProvider(buildCredentials()) + .region(Region.of(config.getEndpoint())) // 这里随便填,SDK 需要 + .endpointOverride(URI.create(buildEndpoint())) + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问 + .build(); + } + /** + * 基于 config 秘钥,构建 S3 客户端的认证信息 + * + * @return S3 客户端的认证信息 + */ + private StaticCredentialsProvider buildCredentials() { + return StaticCredentialsProvider.create( + AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); + } + + /** + * 节点地址补全协议头 + * + * @return 节点地址 + */ + private String buildEndpoint() { + // 如果已经是 http 或者 https,则不进行拼接 + if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) { + return config.getEndpoint(); + } + return StrUtil.format("https://{}", config.getEndpoint()); + } + + @Override + public String upload(byte[] content, String path, String type) { + // 构造 PutObjectRequest + PutObjectRequest putRequest = PutObjectRequest.builder() + .bucket(config.getBucket()) + .key(path) + .contentType(type) + .contentLength((long) content.length) + .build(); + + // 上传文件 + client.putObject(putRequest, RequestBody.fromBytes(content)); // 拼接返回路径 return config.getDomain() + "/" + path; } @Override - public void delete(String path) throws Exception { - client.deleteObject(config.getBucket(), path); + public void delete(String path) { + DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() + .bucket(config.getBucket()) + .key(path) + .build(); + client.deleteObject(deleteRequest); } @Override - public byte[] getContent(String path) throws Exception { - S3Object tempS3Object = client.getObject(config.getBucket(), path); - return IoUtil.readBytes(tempS3Object.getObjectContent()); + public byte[] getContent(String path) { + GetObjectRequest getRequest = GetObjectRequest.builder() + .bucket(config.getBucket()) + .key(path) + .build(); + + return IoUtil.readBytes(client.getObject(getRequest)); } @Override - public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { - // 设定过期时间为 10 分钟。取值范围:1 秒 ~ 7 天 - Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); - // 生成上传 URL - String uploadUrl = String.valueOf(client.generatePresignedUrl(config.getBucket(), path, expiration , HttpMethod.PUT)); - return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path); + public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) { + String presignedUrl = getPresignedUrl( + config.getBucket(), + path, + Duration.ofMinutes(10), + config.getEndpoint(), + config.getAccessKey(), + config.getAccessSecret() + ); + + return new FilePresignedUrlRespDTO(presignedUrl, config.getDomain() + "/" + path); } } From cf40cce552590995096e1b081cce34fe7e23421d Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 7 Feb 2025 18:10:03 +0800 Subject: [PATCH 02/17] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91S3FileClient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../file/core/client/s3/S3FileClient.java | 153 ++++++++---------- 1 file changed, 68 insertions(+), 85 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java index 16a49bba4e..57a3561565 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java @@ -9,7 +9,6 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -32,56 +31,6 @@ public class S3FileClient extends AbstractFileClient { super(id, config); } - /** - * 动态创建 S3Presigner - * - * @param endpoint 节点地址 - * @param accessKey 访问 Key - * @param secretKey 访问 Secret - * @return S3Presigner - */ - private static S3Presigner createPresigner(String endpoint, String accessKey, String secretKey) { - return S3Presigner.builder() - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) - .endpointOverride(URI.create(endpoint)) - .build(); - } - - /** - * 生成动态的预签名上传 URL - * - * @param bucket 存储 Bucket - * @param path 相对路径 - * @param duration 过期时间 - * @param endpoint 节点地址 - * @param accessKey 访问 Key - * @param secretKey 访问 Secret - * @return 生成的上传 URL - */ - public static String getPresignedUrl(String bucket, String path, Duration duration, - String endpoint, String accessKey, String secretKey) { - try (S3Presigner presigner = createPresigner(endpoint, accessKey, secretKey)) { - return presigner.presignPutObject(PutObjectPresignRequest.builder() - .signatureDuration(duration) - .putObjectRequest(b -> b.bucket(bucket).key(path)) - .build()).url().toString(); - } - } - - /** - * 基于 bucket + endpoint 构建访问的 Domain 地址 - * - * @return Domain 地址 - */ - private String buildDomain() { - // 如果已经是 http 或者 https,则不进行拼接.主要适配 MinIO - if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) { - return StrUtil.format("{}/{}", config.getEndpoint(), config.getBucket()); - } - // 阿里云、腾讯云、华为云都适合。七牛云比较特殊,必须有自定义域名 - return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); - } - @Override protected void doInit() { // 补全 domain @@ -91,35 +40,12 @@ public class S3FileClient extends AbstractFileClient { // 初始化 S3 客户端 client = S3Client.builder() .credentialsProvider(buildCredentials()) - .region(Region.of(config.getEndpoint())) // 这里随便填,SDK 需要 + .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 .endpointOverride(URI.create(buildEndpoint())) - .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问 + //.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问 .build(); } - /** - * 基于 config 秘钥,构建 S3 客户端的认证信息 - * - * @return S3 客户端的认证信息 - */ - private StaticCredentialsProvider buildCredentials() { - return StaticCredentialsProvider.create( - AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); - } - - /** - * 节点地址补全协议头 - * - * @return 节点地址 - */ - private String buildEndpoint() { - // 如果已经是 http 或者 https,则不进行拼接 - if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) { - return config.getEndpoint(); - } - return StrUtil.format("https://{}", config.getEndpoint()); - } - @Override public String upload(byte[] content, String path, String type) { // 构造 PutObjectRequest @@ -157,16 +83,73 @@ public class S3FileClient extends AbstractFileClient { @Override public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) { - String presignedUrl = getPresignedUrl( - config.getBucket(), - path, - Duration.ofMinutes(10), - config.getEndpoint(), - config.getAccessKey(), - config.getAccessSecret() - ); + return new FilePresignedUrlRespDTO(getPresignedUrl(path, Duration.ofMinutes(10)), config.getDomain() + "/" + path); + } - return new FilePresignedUrlRespDTO(presignedUrl, config.getDomain() + "/" + path); + /** + * 动态创建 S3Presigner + * + * @return S3Presigner + */ + private S3Presigner createPresigner() { + return S3Presigner.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()))) + .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 + .endpointOverride(URI.create(buildEndpoint())) + .build(); + } + + /** + * 生成动态的预签名上传 URL + * + * @param path 相对路径 + * @param duration 过期时间 + * @return 生成的上传 URL + */ + public String getPresignedUrl(String path, Duration duration) { + try (S3Presigner presigner = createPresigner()) { + return presigner.presignPutObject(PutObjectPresignRequest.builder() + .signatureDuration(duration) + .putObjectRequest(b -> b.bucket(config.getBucket()).key(path)) + .build()).url().toString(); + } + } + + /** + * 基于 bucket + endpoint 构建访问的 Domain 地址 + * + * @return Domain 地址 + */ + private String buildDomain() { + // 如果已经是 http 或者 https,则不进行拼接.主要适配 MinIO + if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) { + return StrUtil.format("{}/{}", config.getEndpoint(), config.getBucket()); + } + // 阿里云、腾讯云、华为云都适合。七牛云比较特殊,必须有自定义域名 + return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); + } + + /** + * 基于 config 秘钥,构建 S3 客户端的认证信息 + * + * @return S3 客户端的认证信息 + */ + private StaticCredentialsProvider buildCredentials() { + return StaticCredentialsProvider.create( + AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); + } + + /** + * 节点地址补全协议头 + * + * @return 节点地址 + */ + private String buildEndpoint() { + // 如果已经是 http 或者 https,则不进行拼接 + if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) { + return config.getEndpoint(); + } + return StrUtil.format("https://{}", config.getEndpoint()); } } From 09aa6b25675e03dddb70afa2730d275ba07ad967 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 2 Apr 2025 11:35:36 +0800 Subject: [PATCH 03/17] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E4=BC=98=E6=83=A0?= =?UTF-8?q?=E5=88=B8=E5=9C=A8=E9=A2=86=E5=8F=96=E7=B1=BB=E5=9E=8B=E4=B8=BA?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E5=8F=91=E6=94=BE=E5=92=8C=E6=96=B0=E4=BA=BA?= =?UTF-8?q?=E5=88=B8=E6=97=B6=E6=97=A0=E6=B3=95=E5=8F=91=E9=80=81=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/service/coupon/CouponServiceImpl.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 7a0ae512f6..22741e4023 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -263,13 +263,17 @@ public class CouponServiceImpl implements CouponService { if (CollUtil.isEmpty(userIds)) { throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE); } - // 校验模板 if (couponTemplate == null) { throw exception(COUPON_TEMPLATE_NOT_EXISTS); } + // 校验领取方式 + if (ObjUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) { + throw exception(COUPON_TEMPLATE_CANNOT_TAKE); + } // 校验剩余数量 - if (ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 + if (ObjUtil.equal(CouponTakeTypeEnum.USER.getType(), couponTemplate.getTakeType()) // 直接领取 + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { throw exception(COUPON_TEMPLATE_NOT_ENOUGH); } @@ -279,10 +283,7 @@ public class CouponServiceImpl implements CouponService { throw exception(COUPON_TEMPLATE_EXPIRED); } } - // 校验领取方式 - if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) { - throw exception(COUPON_TEMPLATE_CANNOT_TAKE); - } + } /** From d5c1a2ff9f356dfe7dde4d15af21441dedd83072 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 2 Apr 2025 17:48:10 +0800 Subject: [PATCH 04/17] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E6=94=B6=E5=9B=9E=E4=BC=98=E6=83=A0=E5=88=B8?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E5=AF=BC=E8=87=B4=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E7=A1=AE=E8=AE=A4=E9=80=80=E6=AC=BE=E4=B8=8D=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/promotion/service/coupon/CouponServiceImpl.java | 3 ++- .../module/trade/service/aftersale/AfterSaleServiceImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 22741e4023..b8759436bd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -22,6 +22,7 @@ import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityType import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -176,7 +177,7 @@ public class CouponServiceImpl implements CouponService { * @param couponId 模版编号 * @param userId 用户编号 */ - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) // 每次调用开启一个新的事务 public void invalidateCoupon(Long couponId, Long userId) { // 1.1 校验优惠券 CouponDO coupon = couponMapper.selectByIdAndUserId(couponId, userId); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java index bcac6b5b6a..a01e350424 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java @@ -36,6 +36,7 @@ import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -44,7 +45,6 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -386,7 +386,7 @@ public class AfterSaleServiceImpl implements AfterSaleService { public void afterCommit() { // 创建退款单 PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties) - .setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));; + .setReason(StrUtil.format("退款【{}】", afterSale.getSpuName())); Long payRefundId = payRefundApi.createRefund(createReqDTO); // 更新售后单的退款单号 tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); From 46676a439d22477b9e240c81614cdc594c2dbb94 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 25 Apr 2025 21:48:37 +0800 Subject: [PATCH 05/17] =?UTF-8?q?feat=EF=BC=9A=E3=80=90INFRA=E3=80=91?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=AD=98=E5=82=A8=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20enablePathStyleAccess=20=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 4 +- .../yudao-module-infra-biz/pom.xml | 8 --- .../file/core/client/s3/S3FileClient.java | 65 ++++++++----------- .../core/client/s3/S3FileClientConfig.java | 6 ++ 4 files changed, 34 insertions(+), 49 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index a5f3da25ff..5afe05a94c 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -96,10 +96,8 @@ software.amazon.awssdk - bom + s3 ${awssdk.version} - pom - import diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index 3c40314889..8dc7d96e0e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -120,14 +120,6 @@ software.amazon.awssdk s3 - - software.amazon.awssdk - auth - - - software.amazon.awssdk - regions - org.apache.tika diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java index 57a3561565..d74d805601 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java @@ -5,10 +5,12 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -26,6 +28,7 @@ import java.time.Duration; public class S3FileClient extends AbstractFileClient { private S3Client client; + private S3Presigner presigner; public S3FileClient(Long id, S3FileClientConfig config) { super(id, config); @@ -38,11 +41,23 @@ public class S3FileClient extends AbstractFileClient { config.setDomain(buildDomain()); } // 初始化 S3 客户端 + Region region = Region.of("us-east-1"); // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 + AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create( + AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); + URI endpoint = URI.create(buildEndpoint()); + S3Configuration serviceConfiguration = S3Configuration.builder() // Path-style 访问 + .pathStyleAccessEnabled(Boolean.TRUE.equals(config.getEnablePathStyleAccess())).build(); client = S3Client.builder() - .credentialsProvider(buildCredentials()) - .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 - .endpointOverride(URI.create(buildEndpoint())) - //.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问 + .credentialsProvider(credentialsProvider) + .region(region) + .endpointOverride(endpoint) + .serviceConfiguration(serviceConfiguration) + .build(); + presigner = S3Presigner.builder() + .credentialsProvider(credentialsProvider) + .region(region) + .endpointOverride(endpoint) + .serviceConfiguration(serviceConfiguration) .build(); } @@ -55,7 +70,6 @@ public class S3FileClient extends AbstractFileClient { .contentType(type) .contentLength((long) content.length) .build(); - // 上传文件 client.putObject(putRequest, RequestBody.fromBytes(content)); // 拼接返回路径 @@ -77,42 +91,27 @@ public class S3FileClient extends AbstractFileClient { .bucket(config.getBucket()) .key(path) .build(); - return IoUtil.readBytes(client.getObject(getRequest)); } @Override public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) { - return new FilePresignedUrlRespDTO(getPresignedUrl(path, Duration.ofMinutes(10)), config.getDomain() + "/" + path); - } - - /** - * 动态创建 S3Presigner - * - * @return S3Presigner - */ - private S3Presigner createPresigner() { - return S3Presigner.builder() - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()))) - .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 - .endpointOverride(URI.create(buildEndpoint())) - .build(); + Duration expiration = Duration.ofHours(24); + return new FilePresignedUrlRespDTO(getPresignedUrl(path, expiration), config.getDomain() + "/" + path); } /** * 生成动态的预签名上传 URL * * @param path 相对路径 - * @param duration 过期时间 + * @param expiration 过期时间 * @return 生成的上传 URL */ - public String getPresignedUrl(String path, Duration duration) { - try (S3Presigner presigner = createPresigner()) { - return presigner.presignPutObject(PutObjectPresignRequest.builder() - .signatureDuration(duration) - .putObjectRequest(b -> b.bucket(config.getBucket()).key(path)) - .build()).url().toString(); - } + private String getPresignedUrl(String path, Duration expiration) { + return presigner.presignPutObject(PutObjectPresignRequest.builder() + .signatureDuration(expiration) + .putObjectRequest(b -> b.bucket(config.getBucket()).key(path)) + .build()).url().toString(); } /** @@ -129,16 +128,6 @@ public class S3FileClient extends AbstractFileClient { return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); } - /** - * 基于 config 秘钥,构建 S3 客户端的认证信息 - * - * @return S3 客户端的认证信息 - */ - private StaticCredentialsProvider buildCredentials() { - return StaticCredentialsProvider.create( - AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); - } - /** * 节点地址补全协议头 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClientConfig.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClientConfig.java index e59a7594d2..fb19317e02 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClientConfig.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClientConfig.java @@ -67,6 +67,12 @@ public class S3FileClientConfig implements FileClientConfig { @NotNull(message = "accessSecret 不能为空") private String accessSecret; + /** + * 是否启用 PathStyle 访问 + */ + @NotNull(message = "enablePathStyleAccess 不能为空") + private Boolean enablePathStyleAccess; + @SuppressWarnings("RedundantIfStatement") @AssertTrue(message = "domain 不能为空") @JsonIgnore From a9bb55340bf55647bfb050cec72fa66bd5d0f0f5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 10:00:53 +0800 Subject: [PATCH 06/17] =?UTF-8?q?feat=EF=BC=9A=E4=BD=BF=E7=94=A8=20aws=20s?= =?UTF-8?q?3=202.0=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 5afe05a94c..c9ebf24e58 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -94,11 +94,6 @@ pom import - - software.amazon.awssdk - s3 - ${awssdk.version} - @@ -556,6 +551,13 @@ ${jsoup.version} + + + software.amazon.awssdk + s3 + ${awssdk.version} + + com.xingyuv spring-boot-starter-justauth From cf3a13d4ff3ffbaa89f7c8e649676dbfb4045d24 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 11:19:31 +0800 Subject: [PATCH 07/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E5=AE=9E=E4=BE=8B=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20LinkedHashSet=20=E4=BF=9D=E6=8C=81=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/collection/CollectionUtils.java | 14 ++++++++++++++ .../form/BpmTaskCandidateFormUserStrategy.java | 6 +++--- .../other/BpmTaskCandidateExpressionStrategy.java | 6 +++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index ed58c4f166..aa523b94db 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -11,6 +11,7 @@ import java.util.function.*; import java.util.stream.Collectors; import java.util.stream.Stream; +import static cn.hutool.core.convert.Convert.toCollection; import static java.util.Arrays.asList; /** @@ -335,4 +336,17 @@ public class CollectionUtils { return list.stream().filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()); } + /** + * 转换为 LinkedHashSet + * + * @param 元素类型 + * @param elementType 集合中元素类型 + * @param value 被转换的值 + * @return {@link LinkedHashSet} + */ + @SuppressWarnings("unchecked") + public static LinkedHashSet toLinkedHashSet(Class elementType, Object value) { + return (LinkedHashSet) toCollection(LinkedHashSet.class, elementType, value); + } + } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java index 2d315979a0..6298c3259f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.form; -import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user.BpmTaskCandidateUserStrategy; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; @@ -33,7 +33,7 @@ public class BpmTaskCandidateFormUserStrategy implements BpmTaskCandidateStrateg @Override public Set calculateUsersByTask(DelegateExecution execution, String param) { Object result = execution.getVariable(param); - return Convert.toSet(Long.class, result); + return CollectionUtils.toLinkedHashSet(Long.class, result); } @Override @@ -41,7 +41,7 @@ public class BpmTaskCandidateFormUserStrategy implements BpmTaskCandidateStrateg String param, Long startUserId, String processDefinitionId, Map processVariables) { Object result = processVariables == null ? null : processVariables.get(param); - return Convert.toSet(Long.class, result); + return CollectionUtils.toLinkedHashSet(Long.class, result); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java index c008c1cb6f..64ca9e8538 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other; -import cn.hutool.core.convert.Convert; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; @@ -37,7 +37,7 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat @Override public Set calculateUsersByTask(DelegateExecution execution, String param) { Object result = FlowableUtils.getExpressionValue(execution, param); - return Convert.toSet(Long.class, result); + return CollectionUtils.toLinkedHashSet(Long.class, result); } @Override @@ -46,7 +46,7 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat Map variables = processVariables == null ? new HashMap<>() : processVariables; try { Object result = FlowableUtils.getExpressionValue(variables, param); - return Convert.toSet(Long.class, result); + return CollectionUtils.toLinkedHashSet(Long.class, result); } catch (FlowableException ex) { // 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常, log.warn("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex); From dd068eb94f2097d3e6c51b81ee1e95aa8779e0ce Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 16:48:55 +0800 Subject: [PATCH 08/17] =?UTF-8?q?refactor=EF=BC=9A=E3=80=90INFRA=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20vben5.0=20=E6=A0=87=E5=87=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E7=9A=84=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmTaskServiceImpl.java | 2 +- .../enums/codegen/CodegenFrontTypeEnum.java | 5 ++++- .../service/codegen/inner/CodegenEngine.java | 18 +++++++++--------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index e59144cb3a..0be674682a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -6,7 +6,6 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.*; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; @@ -882,6 +881,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { return; } runExecutionIds.add(task.getExecutionId()); + // 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务 if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记 // 2.1.1 添加评论 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java index edcb85e474..741d7d9664 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java @@ -13,10 +13,13 @@ import lombok.Getter; public enum CodegenFrontTypeEnum { VUE2_ELEMENT_UI(10), // Vue2 Element UI 标准模版 + VUE3_ELEMENT_PLUS(20), // Vue3 Element Plus 标准模版 + VUE3_VBEN2_ANTD_SCHEMA(30), // Vue3 VBEN2 + ANTD + Schema 模版 + VUE3_VBEN5_ANTD_SCHEMA(40), // Vue3 VBEN5 + ANTD + schema 模版 - VUE3_VBEN5_ANTD(50), // Vue3 VBEN5 + ANTD 模版 + VUE3_VBEN5_ANTD_GENERAL(41), // Vue3 VBEN5 + ANTD 标准模版 ; /** diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 89737fe937..0b5b870eb9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -164,23 +164,23 @@ public class CodegenEngine { .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) // VUE3_VBEN5_ANTD - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/data.ts"), + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/data.ts"), vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/index.vue"), + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/index.vue"), vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/form.vue"), + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/form.vue"), vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("api/api.ts"), + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .build(); From cca592a15bdb90733479fd1ba70e176538f73e61 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 16:51:41 +0800 Subject: [PATCH 09/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=9B=E5=BB=BA=E7=A7=9F=E6=88=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E6=97=B6=EF=BC=8Cselect/update=20=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=8B=BC=E6=8E=A5user=5Fid=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/system/service/tenant/TenantServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index c3b09ec5a9..5060b16e05 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.tenant.config.TenantProperties; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; @@ -96,6 +97,7 @@ public class TenantServiceImpl implements TenantService { @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 + @DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明 public Long createTenant(TenantSaveReqVO createReqVO) { // 校验租户名称是否重复 validTenantNameDuplicate(createReqVO.getName(), null); From 4a9e9961b0169e57fab5b5d3c294d9849e7d0d41 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 17:04:20 +0800 Subject: [PATCH 10/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=E3=80=91Admin?= =?UTF-8?q?UserServiceImplTest=20=E7=9A=84=20testUpdateUserProfile=5Fsucce?= =?UTF-8?q?ss=20=E5=8D=95=E6=B5=8B=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/system/service/user/AdminUserServiceImplTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java index c811c3c741..5286f7a0f1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java @@ -212,6 +212,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { UserProfileUpdateReqVO reqVO = randomPojo(UserProfileUpdateReqVO.class, o -> { o.setMobile(randomString()); o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); + o.setAvatar(randomURL()); }); // 调用 From abfbe1ea83570a00106dedebb283dc8b065ac929 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 17:22:42 +0800 Subject: [PATCH 11/17] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=E3=80=91?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=B3=BB=E7=BB=9F=E9=85=8D=E7=BD=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=9D=A5=E8=AE=BE=E7=BD=AE=E7=B3=BB=E7=BB=9F=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=8F=AF=E6=B3=A8=E5=86=8C=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/system/enums/ErrorCodeConstants.java | 1 + .../system/service/user/AdminUserServiceImpl.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 6db0e567c4..6ed77aeef7 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -45,6 +45,7 @@ public interface ErrorCodeConstants { ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!"); ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册"); + ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭"); // ========== 部门模块 1-002-004-000 ========== ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index 09e7b61e1f..eaa5710074 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; @@ -61,6 +62,8 @@ public class AdminUserServiceImpl implements AdminUserService { static final String USER_INIT_PASSWORD_KEY = "system.user.init-password"; + static final String USER_REGISTER_ENABLED_KEY = "system.user.register-enabled"; + @Resource private AdminUserMapper userMapper; @@ -117,14 +120,18 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public Long registerUser(AuthRegisterReqVO registerReqVO) { - // 1.1 校验账户配合 + // 1.1 校验是否开启注册 + if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY), "true")) { + throw exception(USER_REGISTER_DISABLED); + } + // 1.2 校验账户配合 tenantService.handleTenantInfo(tenant -> { long count = userMapper.selectCount(); if (count >= tenant.getAccountCount()) { throw exception(USER_COUNT_MAX, tenant.getAccountCount()); } }); - // 1.2 校验正确性 + // 1.3 校验正确性 validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null); // 2. 插入用户 From 03e510adfde31b3040f184ac2007f0b4ff3aa1c7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Apr 2025 17:34:17 +0800 Subject: [PATCH 12/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1315?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/promotion/service/coupon/CouponServiceImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index daccecd236..e6f82a69fc 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -181,7 +181,7 @@ public class CouponServiceImpl implements CouponService { * @param couponId 模版编号 * @param userId 用户编号 */ - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) // 每次调用开启一个新的事务 + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) // 每次调用开启一个新的事务,避免在一个大的事务里面 public void invalidateCoupon(Long couponId, Long userId) { if (couponId == null || couponId <= 0) { return; @@ -279,8 +279,8 @@ public class CouponServiceImpl implements CouponService { if (ObjUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) { throw exception(COUPON_TEMPLATE_CANNOT_TAKE); } - // 校验剩余数量 - if (ObjUtil.equal(CouponTakeTypeEnum.USER.getType(), couponTemplate.getTakeType()) // 直接领取 + // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) + if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { throw exception(COUPON_TEMPLATE_NOT_ENOUGH); @@ -291,7 +291,6 @@ public class CouponServiceImpl implements CouponService { throw exception(COUPON_TEMPLATE_EXPIRED); } } - } /** From 3395a3d86bd4e3795b4fbcc48bad2ef6bf744d0f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 27 Apr 2025 08:58:54 +0800 Subject: [PATCH 13/17] =?UTF-8?q?feat=EF=BC=9A=E3=80=90MALL=E3=80=91?= =?UTF-8?q?=E5=95=86=E5=9F=8E=E8=AE=A2=E5=8D=95=E5=8F=96=E6=B6=88=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E9=A2=9D=E5=A4=96=E6=A0=A1=E9=AA=8C=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=8D=95=E7=9A=84=E7=8A=B6=E6=80=81=EF=BC=8C=E8=BF=9B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=E5=85=9C=E5=BA=95=E5=9B=9E=E8=B0=83=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/TradeOrderUpdateServiceImpl.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 92036fa7e7..d47da484e2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -545,6 +545,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); } + // 1.3 校验是否支持延迟(不允许取消) + if (TradeOrderStatusEnum.isUnpaid(order.getStatus())) { + PayOrderRespDTO payOrder = payOrderApi.getOrder(order.getPayOrderId()); + if (payOrder != null && PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { + log.warn("[cancelOrderByMember][order({}) 支付单已支付(支付回调延迟),不支持取消]", order.getId()); + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); + } + } // 2. 取消订单 cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); @@ -581,6 +589,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Transactional(rollbackFor = Exception.class) @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL) public void cancelOrderBySystem(TradeOrderDO order) { + // 校验是否支持延迟(不允许取消) + if (TradeOrderStatusEnum.isUnpaid(order.getStatus())) { + PayOrderRespDTO payOrder = payOrderApi.getOrder(order.getPayOrderId()); + if (payOrder != null && PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { + log.warn("[cancelOrderBySystem][order({}) 支付单已支付(支付回调延迟),不支持取消]", order.getId()); + return; + } + } + cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT); } @@ -895,12 +912,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (order == null) { throw exception(ORDER_NOT_FOUND); } - // 1.3 校验订单是否支付 if (!order.getPayStatus()) { throw exception(ORDER_CANCEL_PAID_FAIL, "已支付"); } - // 1.3 校验订单是否未退款 + // 1.4 校验订单是否未退款 if (ObjUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { throw exception(ORDER_CANCEL_PAID_FAIL, "未退款"); } From ec76c1ae6ecb068a213ce635ce8af50bf5e670c7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 27 Apr 2025 09:44:27 +0800 Subject: [PATCH 14/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20addBrokerage=20=E5=88=9B=E5=BB=BA=E5=88=86?= =?UTF-8?q?=E9=94=80=E8=AE=B0=E5=BD=95=E6=97=B6=EF=BC=8C=E6=AF=8F=E4=B8=AA?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E9=A1=B9=EF=BC=8C=E7=94=9F=E6=88=90=E5=88=86?= =?UTF-8?q?=E9=94=80=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/product/api/sku/ProductSkuApi.java | 13 +++++++++++++ .../module/product/api/spu/ProductSpuApi.java | 2 +- .../admin/point/PointActivityController.java | 2 +- .../app/point/AppPointActivityController.java | 2 +- .../order/handler/TradeBrokerageOrderHandler.java | 15 ++++++++++----- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java index 3581fdb913..f6e6034875 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java @@ -5,6 +5,9 @@ import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商品 SKU API 接口 @@ -30,6 +33,16 @@ public interface ProductSkuApi { */ List getSkuList(Collection ids); + /** + * 批量查询 SKU MAP + * + * @param ids SKU 编号列表 + * @return SKU MAP + */ + default Map getSkuMap(Collection ids) { + return convertMap(getSkuList(ids), ProductSkuRespDTO::getId); + } + /** * 批量查询 SKU 数组 * diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java index 64d24c399a..499a0ca896 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java @@ -30,7 +30,7 @@ public interface ProductSpuApi { * @param ids SPU 编号列表 * @return SPU MAP */ - default Map getSpusMap(Collection ids) { + default Map getSpuMap(Collection ids) { return convertMap(getSpuList(ids), ProductSpuRespDTO::getId); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java index d8fb54b081..f545db6f50 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java @@ -124,7 +124,7 @@ public class PointActivityController { List products = pointActivityService.getPointProductListByActivityIds( convertSet(activityList, PointActivityDO::getId)); Map> productsMap = convertMultiMap(products, PointProductDO::getActivityId); - Map spuMap = productSpuApi.getSpusMap( + Map spuMap = productSpuApi.getSpuMap( convertSet(activityList, PointActivityDO::getSpuId)); List result = BeanUtils.toBean(activityList, PointActivityRespVO.class); result.forEach(activity -> { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java index c364b64f2a..9730056870 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java @@ -104,7 +104,7 @@ public class AppPointActivityController { List products = pointActivityService.getPointProductListByActivityIds( convertSet(activityList, PointActivityDO::getId)); Map> productsMap = convertMultiMap(products, PointProductDO::getActivityId); - Map spuMap = productSpuApi.getSpusMap( + Map spuMap = productSpuApi.getSpuMap( convertSet(activityList, PointActivityDO::getSpuId)); List result = BeanUtils.toBean(activityList, AppPointActivityRespVO.class); result.forEach(activity -> { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java index 026d98c238..36d31402eb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java @@ -20,6 +20,7 @@ import org.springframework.stereotype.Component; import jakarta.annotation.Resource; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -101,13 +102,17 @@ public class TradeBrokerageOrderHandler implements TradeOrderHandler { protected void addBrokerage(Long userId, List orderItems) { MemberUserRespDTO user = memberUserApi.getUser(userId); Assert.notNull(user); - ProductSpuRespDTO spu = productSpuApi.getSpu(orderItems.get(0).getSpuId()); - Assert.notNull(spu); - ProductSkuRespDTO sku = productSkuApi.getSku(orderItems.get(0).getSkuId()); + Map spusMap = productSpuApi.getSpuMap(convertList(orderItems, TradeOrderItemDO::getSpuId)); + Map skusMap = productSkuApi.getSkuMap(convertList(orderItems, TradeOrderItemDO::getSkuId)); // 每一个订单项,都会去生成分销记录 - List addList = convertList(orderItems, - item -> TradeOrderConvert.INSTANCE.convert(user, item, spu, sku)); + List addList = convertList(orderItems, item -> { + ProductSpuRespDTO spu = spusMap.get(item.getSpuId()); + Assert.notNull(spu); + ProductSkuRespDTO sku = skusMap.get(item.getSkuId()); + Assert.notNull(sku); + return TradeOrderConvert.INSTANCE.convert(user, item, spu, sku); + }); brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); } From 00a08d6cb62e8be2e81fca90371b14f02b561f84 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 28 Apr 2025 00:24:59 +0800 Subject: [PATCH 15/17] =?UTF-8?q?reactor=EF=BC=9A=E3=80=90MALL=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=B4=AD=E7=89=A9=E8=BD=A6=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E8=BF=94=E5=9B=9E=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E3=80=81=E7=8A=B6=E6=80=81=E7=AD=89=E7=8A=B6=E6=80=81=EF=BC=8C?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=8D=E8=87=AA=E5=8A=A8=E5=8F=96=E6=B6=88?= =?UTF-8?q?=20selected=20=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/base/spu/AppProductSpuBaseRespVO.java | 8 ++++++-- .../yudao/module/trade/convert/cart/TradeCartConvert.java | 8 +++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/spu/AppProductSpuBaseRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/spu/AppProductSpuBaseRespVO.java index d30417818f..c7a3c1d9e7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/spu/AppProductSpuBaseRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/spu/AppProductSpuBaseRespVO.java @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.trade.controller.app.base.spu; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.util.List; - /** * 商品 SPU 基础 Response VO * @@ -25,4 +23,10 @@ public class AppProductSpuBaseRespVO { @Schema(description = "商品分类编号", example = "1") private Long categoryId; + @Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private Integer stock; + + @Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java index 83cd459542..fa5fccd54e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.trade.convert.cart; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; @@ -33,21 +34,18 @@ public interface TradeCartConvert { cartVO.setId(cart.getId()).setCount(cart.getCount()).setSelected(cart.getSelected()); ProductSpuRespDTO spu = spuMap.get(cart.getSpuId()); ProductSkuRespDTO sku = skuMap.get(cart.getSkuId()); - cartVO.setSpu(convert(spu)).setSku(convert(sku)); + cartVO.setSpu(BeanUtils.toBean(spu, AppProductSpuBaseRespVO.class)) + .setSku(BeanUtils.toBean(sku, AppProductSkuBaseRespVO.class)); // 如果 SPU 不存在,或者下架,或者库存不足,说明是无效的 if (spu == null || !ProductSpuStatusEnum.isEnable(spu.getStatus()) || spu.getStock() <= 0) { - cartVO.setSelected(false); // 强制设置成不可选中 invalidList.add(cartVO); } else { - // 虽然 SKU 可能也会不存在,但是可以通过购物车重新选择 validList.add(cartVO); } }); return new AppCartListRespVO().setValidList(validList).setInvalidList(invalidList); } - AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu); - AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku); } From 4dde700f35b57db4d6eee3fa7c7a678f26552492 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 28 Apr 2025 23:16:54 +0800 Subject: [PATCH 16/17] =?UTF-8?q?feat=EF=BC=9A=E3=80=90MALL=E3=80=91App=20?= =?UTF-8?q?=E5=94=AE=E5=90=8E=E7=AD=9B=E9=80=89=E6=97=B6=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20status=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/aftersale/AppAfterSaleController.java | 14 +++++++------ .../aftersale/vo/AppAfterSalePageReqVO.java | 20 +++++++++++++++++++ .../pickup/AppDeliveryPickUpStoreRespVO.java | 14 +++++++++++++ .../convert/aftersale/AfterSaleConvert.java | 5 ----- .../dal/mysql/aftersale/AfterSaleMapper.java | 9 +++++---- .../service/aftersale/AfterSaleService.java | 6 +++--- .../aftersale/AfterSaleServiceImpl.java | 6 +++--- 7 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSalePageReqVO.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java index 2328119d06..46495c003e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.trade.controller.app.aftersale; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSalePageReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO; -import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -31,16 +32,17 @@ public class AppAfterSaleController { @GetMapping(value = "/page") @Operation(summary = "获得售后分页") - public CommonResult> getAfterSalePage(PageParam pageParam) { - return success(AfterSaleConvert.INSTANCE.convertPage02( - afterSaleService.getAfterSalePage(getLoginUserId(), pageParam))); + public CommonResult> getAfterSalePage(AppAfterSalePageReqVO pageReqVO) { + PageResult pageResult = afterSaleService.getAfterSalePage(getLoginUserId(), pageReqVO); + return success(BeanUtils.toBean(pageResult, AppAfterSaleRespVO.class)); } @GetMapping(value = "/get") @Operation(summary = "获得售后订单") @Parameter(name = "id", description = "售后编号", required = true, example = "1") public CommonResult getAfterSale(@RequestParam("id") Long id) { - return success(AfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id))); + AfterSaleDO afterSale = afterSaleService.getAfterSale(getLoginUserId(), id); + return success(BeanUtils.toBean(afterSale, AppAfterSaleRespVO.class)); } @PostMapping(value = "/create") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSalePageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSalePageReqVO.java new file mode 100644 index 0000000000..35e2429b39 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSalePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Set; + +@Schema(description = "用户 App - 交易售后分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppAfterSalePageReqVO extends PageParam { + + @Schema(description = "售后状态", example = "10, 20") + private Set statuses; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java index 1ca25ade5f..685a8f23fc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java @@ -1,8 +1,12 @@ package cn.iocoder.yudao.module.trade.controller.app.delivery.vo.pickup; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.time.LocalTime; + @Schema(description = "用户 App - 自提门店 Response VO") @Data public class AppDeliveryPickUpStoreRespVO { @@ -28,6 +32,16 @@ public class AppDeliveryPickUpStoreRespVO { @Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号") private String detailAddress; + @Schema(description = "营业开始时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "营业开始时间不能为空") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + private LocalTime openingTime; + + @Schema(description = "营业结束时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "营业结束时间不能为空") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + private LocalTime closingTime; + @Schema(description = "纬度", requiredMode = Schema.RequiredMode.REQUIRED, example = "5.88") private Double latitude; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java index 45f6e31891..54480f696b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUse import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; @@ -63,10 +62,6 @@ public interface AfterSaleConvert { ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); - AppAfterSaleRespVO convert(AfterSaleDO bean); - - PageResult convertPage02(PageResult page); - default AfterSaleDetailRespVO convert(AfterSaleDO afterSale, TradeOrderDO order, TradeOrderItemDO orderItem, MemberUserRespDTO user, List logs) { AfterSaleDetailRespVO respVO = convert02(afterSale); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java index 341dabc45e..9901792e37 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSalePageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -27,9 +27,10 @@ public interface AfterSaleMapper extends BaseMapperX { .orderByDesc(AfterSaleDO::getId)); } - default PageResult selectPage(Long userId, PageParam pageParam) { - return selectPage(pageParam, new LambdaQueryWrapperX() - .eqIfPresent(AfterSaleDO::getUserId, userId) + default PageResult selectPage(Long userId, AppAfterSalePageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(AfterSaleDO::getUserId, userId) + .inIfPresent(AfterSaleDO::getStatus, pageReqVO.getStatuses()) .orderByDesc(AfterSaleDO::getId)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java index 1a0c1e95d9..486a68b7c0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.trade.service.aftersale; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSalePageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; /** @@ -28,10 +28,10 @@ public interface AfterSaleService { * 【会员】获得售后订单分页 * * @param userId 用户编号 - * @param pageParam 分页参数 + * @param pageReqVO 分页参数 * @return 售后订单分页 */ - PageResult getAfterSalePage(Long userId, PageParam pageParam); + PageResult getAfterSalePage(Long userId, AppAfterSalePageReqVO pageReqVO); /** * 【会员】获得售后单 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java index a01e350424..915f253f0f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.aftersale; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePage import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSalePageReqVO; import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; @@ -87,8 +87,8 @@ public class AfterSaleServiceImpl implements AfterSaleService { } @Override - public PageResult getAfterSalePage(Long userId, PageParam pageParam) { - return tradeAfterSaleMapper.selectPage(userId, pageParam); + public PageResult getAfterSalePage(Long userId, AppAfterSalePageReqVO pageReqVO) { + return tradeAfterSaleMapper.selectPage(userId, pageReqVO); } @Override From cb701d7d7f4ead4e3063b93536c53ef2abf0ec2f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 29 Apr 2025 19:11:50 +0800 Subject: [PATCH 17/17] =?UTF-8?q?fix=EF=BC=9A=E3=80=90INFRA=E3=80=91?= =?UTF-8?q?=E9=98=BF=E9=87=8C=E4=BA=91=20S3=20=E4=B8=8A=E4=BC=A0=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E4=BC=9A=20aws-chunked=20encoding=20is=20not=20suppor?= =?UTF-8?q?ted=20=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/framework/file/core/client/s3/S3FileClient.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java index d74d805601..a33f0d738c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java @@ -46,7 +46,9 @@ public class S3FileClient extends AbstractFileClient { AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())); URI endpoint = URI.create(buildEndpoint()); S3Configuration serviceConfiguration = S3Configuration.builder() // Path-style 访问 - .pathStyleAccessEnabled(Boolean.TRUE.equals(config.getEnablePathStyleAccess())).build(); + .pathStyleAccessEnabled(Boolean.TRUE.equals(config.getEnablePathStyleAccess())) + .chunkedEncodingEnabled(false) // 禁用分块编码,参见 https://t.zsxq.com/kBy57 + .build(); client = S3Client.builder() .credentialsProvider(credentialsProvider) .region(region)