result = requestConsumer.get();
- if (result.getThrowable() != null) {
- throw result.getThrowable();
- }
- // 解析结果
- R data = null;
- if (result.getData() != null) {
- data = responseConsumer.apply(result.getData());
- }
- // 拼接结果
- return SmsCommonResult.build(String.valueOf(result.getCode()), formatResultMsg(result), null, data, codeMapping);
- }
-
- private static String formatResultMsg(Result> sendResult) {
- if (StrUtil.isEmpty(sendResult.getDetail())) {
- return sendResult.getMsg();
- }
- return sendResult.getMsg() + " => " + sendResult.getDetail();
- }
-
- /**
- * 短信接收状态
- *
- * 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档
- *
- * @author 芋道源码
- */
- @Data
- public static class SmsReceiveStatus {
-
- /**
- * 接收状态
- *
- * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收
- */
- @JsonProperty("report_status")
- private String reportStatus;
- /**
- * 接收手机号
- */
- private String mobile;
- /**
- * 运营商返回的代码,如:"DB:0103"
- *
- * 由于不同运营商信息不同,此字段仅供参考;
- */
- @JsonProperty("error_msg")
- private String errorMsg;
- /**
- * 运营商反馈代码的中文解释
- *
- * 默认不推送此字段,如需推送,请联系客服
- */
- @JsonProperty("error_detail")
- private String errorDetail;
- /**
- * 短信编号
- */
- private Long sid;
- /**
- * 用户自定义 id
- *
- * 这里我们传递的是 SysSmsLogDO 的日志编号
- */
- private Long uid;
- /**
- * 用户接收时间
- */
- @JsonProperty("user_receive_time")
- @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
- private LocalDateTime userReceiveTime;
-
- }
-
-}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java
deleted file mode 100644
index f467ceb4f..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian;
-
-import cn.iocoder.yudao.framework.common.exception.ErrorCode;
-import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping;
-import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS;
-import static com.yunpian.sdk.constant.Code.*;
-
-/**
- * 云片的 SmsCodeMapping 实现类
- *
- * 参见 https://www.yunpian.com/official/document/sms/zh_CN/returnvalue_common 文档
- *
- * @author 芋道源码
- */
-public class YunpianSmsCodeMapping implements SmsCodeMapping {
-
- @Override
- public ErrorCode apply(String apiCode) {
- int code = Integer.parseInt(apiCode);
- switch (code) {
- case OK:
- return SUCCESS;
- case ARGUMENT_MISSING:
- return SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR;
- case BAD_ARGUMENT_FORMAT:
- return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR;
- case TPL_NOT_FOUND:
- case TPL_NOT_VALID:
- return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID;
- case MONEY_NOT_ENOUGH:
- return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH;
- case BLACK_WORD:
- return SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID;
- case DUP_IN_SHORT_TIME:
- case TOO_MANY_TIME_IN_5:
- case DAY_LIMIT_PER_MOBILE:
- case HOUR_LIMIT_PER_MOBILE:
- return SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL;
- case BLACK_PHONE_FILTER:
- return SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK;
- case SIGN_NOT_MATCH:
- case BAD_SIGN_FORMAT:
- case SIGN_NOT_VALID:
- return SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID;
- case BAD_API_KEY:
- return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID;
- case API_NOT_ALLOWED:
- return SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY;
- case IP_NOT_ALLOWED:
- return SmsFrameworkErrorCodeConstants.SMS_IP_DENY;
- default:
- break;
- }
- return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
- }
-
-}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java
index b1b386b98..66410bd2c 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java
@@ -15,7 +15,6 @@ import lombok.Getter;
public enum SmsChannelEnum {
DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
- YUN_PIAN("YUN_PIAN", "云片"),
ALIYUN("ALIYUN", "阿里云"),
TENCENT("TENCENT", "腾讯云"),
// HUA_WEI("HUA_WEI", "华为云"),
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
index 7af1dd21c..852f4e29b 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
@@ -16,7 +16,6 @@ public interface SmsFrameworkErrorCodeConstants {
// ========== 权限 / 限流等相关 2001000100 ==========
ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限");
- // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信
ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信");
// 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index bb26b5327..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..7c9b740ca
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java
deleted file mode 100644
index a23094a88..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian;
-
-import cn.iocoder.yudao.framework.common.core.KeyValue;
-import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
-import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
-import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import cn.iocoder.yudao.framework.sms.core.client.impl.yunpian.YunpianSmsClient;
-import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum;
-import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * {@link YunpianSmsClient} 的集成测试
- */
-public class YunpianSmsClientIntegrationTest {
-
- private static YunpianSmsClient smsClient;
-
- @BeforeAll
- public static void init() {
- // 创建配置类
- SmsChannelProperties properties = new SmsChannelProperties();
- properties.setId(1L);
- properties.setSignature("芋道");
- properties.setCode(SmsChannelEnum.YUN_PIAN.getCode());
- properties.setApiKey("1555a14277cb8a608cf45a9e6a80d510");
- // 创建客户端
- smsClient = new YunpianSmsClient(properties);
- smsClient.init();
- }
-
- @Test
- public void testSendSms() {
- List> templateParams = new ArrayList<>();
- templateParams.add(new KeyValue<>("code", "1024"));
- templateParams.add(new KeyValue<>("operation", "嘿嘿"));
-// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
- SmsCommonResult result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams);
- System.out.println(result);
- }
-
- @Test
- public void testGetSmsTemplate() {
- String apiTemplateId = "4383920";
- SmsCommonResult result = smsClient.getSmsTemplate(apiTemplateId);
- System.out.println(result);
- }
-
-}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java
deleted file mode 100644
index 3fc05ce77..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian;
-
-import cn.hutool.core.util.ReflectUtil;
-import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
-import cn.iocoder.yudao.framework.common.core.KeyValue;
-import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
-import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
-import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
-import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
-import com.google.common.collect.Lists;
-import com.yunpian.sdk.YunpianClient;
-import com.yunpian.sdk.api.SmsApi;
-import com.yunpian.sdk.api.TplApi;
-import com.yunpian.sdk.constant.YunpianConstant;
-import com.yunpian.sdk.model.Result;
-import com.yunpian.sdk.model.SmsSingleSend;
-import com.yunpian.sdk.model.Template;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static com.yunpian.sdk.constant.Code.OK;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-/**
- * 对 {@link YunpianSmsClient} 的单元测试
- *
- * @author 芋道源码
- */
-public class YunpianSmsClientTest extends BaseMockitoUnitTest {
-
- private final SmsChannelProperties properties = new SmsChannelProperties()
- .setApiKey(randomString()); // 随机一个 apiKey,避免构建报错
-
- @InjectMocks
- private final YunpianSmsClient smsClient = new YunpianSmsClient(properties);
-
- @Mock
- private YunpianClient client;
-
- @Test
- public void testDoInit() {
- // 准备参数
- // mock 方法
-
- // 调用
- smsClient.doInit();
- // 断言
- assertNotEquals(client, ReflectUtil.getFieldValue(smsClient, "client"));
- verify(client, times(1)).close();
- }
-
- @Test
- @SuppressWarnings("unchecked")
- public void testDoSendSms() throws Throwable {
- // 准备参数
- Long sendLogId = randomLongId();
- String mobile = randomString();
- String apiTemplateId = randomString();
- List> templateParams = Lists.newArrayList(
- new KeyValue<>("code", 1234), new KeyValue<>("op", "login"));
- // mock sms 方法
- SmsApi smsApi = mock(SmsApi.class);
- when(client.sms()).thenReturn(smsApi);
- // mock tpl_single_send 方法
- Map request = new HashMap<>();
- request.put(YunpianConstant.MOBILE, mobile);
- request.put(YunpianConstant.TPL_ID, apiTemplateId);
- request.put(YunpianConstant.TPL_VALUE, "#code#=1234op#=login");
- request.put(YunpianConstant.UID, String.valueOf(sendLogId));
- request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl());
- Result responseResult = randomPojo(Result.class, SmsSingleSend.class,
- o -> o.setCode(OK)); // API 发送成功的 code
- when(smsApi.tpl_single_send(eq(request))).thenReturn(responseResult);
-
- // 调用
- SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile,
- apiTemplateId, templateParams);
- // 断言
- assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode());
- assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg());
- assertNull(result.getApiRequestId());
- // 断言结果
- assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo());
- }
-
- @Test
- public void testDoParseSmsReceiveStatus() throws Throwable {
- // 准备参数
- String text = "[{\"sid\":9527,\"uid\":1024,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"}]";
- // mock 方法
-
- // 调用
-
- // 断言
- // 调用
- List statuses = smsClient.doParseSmsReceiveStatus(text);
- // 断言
- assertEquals(1, statuses.size());
- assertTrue(statuses.get(0).getSuccess());
- assertEquals("", statuses.get(0).getErrorCode());
- assertNull(statuses.get(0).getErrorMsg());
- assertEquals("15205201314", statuses.get(0).getMobile());
- assertEquals(LocalDateTime.of(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime());
- assertEquals("9527", statuses.get(0).getSerialNo());
- assertEquals(1024L, statuses.get(0).getLogId());
- }
-
- @Test
- @SuppressWarnings("unchecked")
- public void testDoGetSmsTemplate() throws Throwable {
- // 准备参数
- String apiTemplateId = String.valueOf(randomLongId());
- // mock tpl 方法
- TplApi tplApi = mock(TplApi.class);
- when(client.tpl()).thenReturn(tplApi);
- // mock get 方法
- Map request = new HashMap<>();
- request.put(YunpianConstant.APIKEY, properties.getApiKey());
- request.put(YunpianConstant.TPL_ID, apiTemplateId);
- Result> responseResult = randomPojo(Result.class, List.class, o -> {
- o.setCode(OK); // API 发送成功的 code
- o.setData(randomPojoList(Template.class, t -> t.setCheck_status("SUCCESS")));
- });
- when(tplApi.get(eq(request))).thenReturn(responseResult);
-
- // 调用
- SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId);
- // 断言
- assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode());
- assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg());
- assertNull(result.getApiRequestId());
- // 断言结果
- Template template = responseResult.getData().get(0);
- assertEquals(template.getTpl_id().toString(), result.getData().getId());
- assertEquals(template.getTpl_content(), result.getData().getContent());
- assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus());
- assertEquals(template.getReason(), result.getData().getAuditReason());
- }
-
- @Test
- public void testConvertSmsTemplateAuditStatus() {
- assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(),
- smsClient.convertSmsTemplateAuditStatus("CHECKING"));
- assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(),
- smsClient.convertSmsTemplateAuditStatus("SUCCESS"));
- assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(),
- smsClient.convertSmsTemplateAuditStatus("FAIL"));
- assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus("test"),
- "未知审核状态(test)");
- }
-
- @Test
- public void testInvoke_throwable() {
- // 准备参数
- Supplier> requestConsumer =
- () -> new Result<>().setThrowable(new NullPointerException());
- // mock 方法
-
- // 调用,并断言异常
- assertThrows(NullPointerException.class,
- () -> smsClient.invoke(requestConsumer, null));
- }
-
- @Test
- @SuppressWarnings("unchecked")
- public void testInvoke_success() throws Throwable {
- // 准备参数
- Result responseResult = randomPojo(Result.class, SmsSingleSend.class, o -> o.setCode(OK));
- Supplier> requestConsumer = () -> responseResult;
- Function responseConsumer =
- smsSingleSend -> new SmsSendRespDTO().setSerialNo(String.valueOf(responseResult.getData().getSid()));
- // mock 方法
-
- // 调用
- SmsCommonResult result = smsClient.invoke(requestConsumer, responseConsumer);
- // 断言
- assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode());
- assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());
- assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg());
- assertNull(result.getApiRequestId());
- assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo());
- }
-
-}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java
deleted file mode 100644
index 8a292e325..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
-import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
-import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-
-import static com.yunpian.sdk.constant.Code.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link YunpianSmsCodeMapping} 的单元测试
- *
- * @author 芋道源码
- */
-class YunpianSmsCodeMappingTest extends BaseMockitoUnitTest {
-
- @InjectMocks
- private YunpianSmsCodeMapping codeMapping;
-
- @Test
- public void testApply() {
- assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(String.valueOf(OK)));
- Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply(String.valueOf(ARGUMENT_MISSING)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply(String.valueOf(BAD_ARGUMENT_FORMAT)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply(String.valueOf(MONEY_NOT_ENOUGH)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_FOUND)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_VALID)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DUP_IN_SHORT_TIME)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(TOO_MANY_TIME_IN_5)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DAY_LIMIT_PER_MOBILE)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(HOUR_LIMIT_PER_MOBILE)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply(String.valueOf(BLACK_PHONE_FILTER)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_MATCH)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_VALID)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(BAD_SIGN_FORMAT)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply(String.valueOf(BAD_API_KEY)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply(String.valueOf(API_NOT_ALLOWED)));
- assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply(String.valueOf(IP_NOT_ALLOWED)));
- }
-
-}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java
index 976f677ce..5c2f7f8bb 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java
@@ -6,10 +6,10 @@ import com.xkcoding.http.support.hutool.HutoolImpl;
import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.cache.AuthStateCache;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
@@ -19,7 +19,7 @@ import org.springframework.context.annotation.Primary;
* @date 2021-10-30
*/
@Slf4j
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties(JustAuthProperties.class)
public class YudaoSocialAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java
index b2cd28ec6..22be344d9 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java
@@ -43,6 +43,7 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory {
* @param source {@link AuthSource}
* @return {@link AuthRequest}
*/
+ @Override
public AuthRequest get(String source) {
// 先尝试获取自定义扩展的
AuthRequest authRequest = getExtendRequest(source);
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index dcd4dcf71..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..5d9b35599
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
index e351d82e1..bc53c244e 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
@@ -21,11 +21,11 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
@@ -35,7 +35,7 @@ import org.springframework.data.redis.core.RedisTemplate;
import java.util.Objects;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java
index 89dfeff4b..b7d0fa362 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.framework.tenant.core.aop;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -11,6 +12,8 @@ import org.aspectj.lang.annotation.Aspect;
* 例如说,一个定时任务,读取所有数据,进行处理。
* 又例如说,读取所有数据,进行缓存。
*
+ * 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致
+ *
* @author 芋道源码
*/
@Aspect
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java
index 3ea29b227..e45822b7e 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java
@@ -2,6 +2,10 @@ package cn.iocoder.yudao.framework.tenant.core.util;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
+
/**
* 多租户 Util
*
@@ -32,4 +36,32 @@ public class TenantUtils {
}
}
+ /**
+ * 忽略租户,执行对应的逻辑
+ *
+ * @param runnable 逻辑
+ */
+ public static void executeIgnore(Runnable runnable) {
+ Boolean oldIgnore = TenantContextHolder.isIgnore();
+ try {
+ TenantContextHolder.setIgnore(true);
+ // 执行逻辑
+ runnable.run();
+ } finally {
+ TenantContextHolder.setIgnore(oldIgnore);
+ }
+ }
+
+ /**
+ * 将多租户编号,添加到 header 中
+ *
+ * @param headers HTTP 请求 headers
+ */
+ public static void addTenantHeader(Map headers) {
+ Long tenantId = TenantContextHolder.getTenantId();
+ if (tenantId != null) {
+ headers.put(HEADER_TENANT_ID, tenantId.toString());
+ }
+ }
+
}
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 95ab510a4..000000000
--- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.tenant.config.YudaoTenantAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..603831e3f
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.tenant.config.YudaoTenantAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java
index 314368d32..f446819e7 100644
--- a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java
@@ -4,11 +4,11 @@ import cn.hutool.core.util.ClassUtil;
import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
import com.anji.captcha.service.CaptchaCacheService;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
public class YudaoCaptchaConfiguration {
static {
diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index ed8b528ff..000000000
--- a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..8411d2cc3
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java
index c7aa832bf..e22ee3dd0 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java
@@ -2,15 +2,15 @@ package cn.iocoder.yudao.framework.file.config;
import cn.iocoder.yudao.framework.file.core.client.FileClientFactory;
import cn.iocoder.yudao.framework.file.core.client.FileClientFactoryImpl;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
/**
* 文件配置类
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
public class YudaoFileAutoConfiguration {
@Bean
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java
index 178c27d4c..fb576d508 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java
@@ -22,7 +22,7 @@ public interface FileClient {
* @return 完整路径,即 HTTP 访问地址
* @throws Exception 上传文件时,抛出 Exception 异常
*/
- String upload(byte[] content, String path) throws Exception;
+ String upload(byte[] content, String path, String type) throws Exception;
/**
* 删除文件
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java
index a227cc314..1e2c082fe 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java
@@ -21,7 +21,7 @@ public class DBFileClient extends AbstractFileClient {
}
@Override
- public String upload(byte[] content, String path) {
+ public String upload(byte[] content, String path, String type) {
getDao().insert(getId(), path, content);
// 拼接返回路径
return super.formatFileUrl(config.getDomain(), path);
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java
index e9c837dfd..796044f3f 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java
@@ -38,7 +38,7 @@ public class FtpFileClient extends AbstractFileClient {
}
@Override
- public String upload(byte[] content, String path) {
+ public String upload(byte[] content, String path, String type) {
// 执行写入
String filePath = getFilePath(path);
String fileName = FileUtil.getName(filePath);
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java
index 1c79f8999..cac13f1fb 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java
@@ -25,7 +25,7 @@ public class LocalFileClient extends AbstractFileClient {
}
@Override
- public String upload(byte[] content, String path) {
+ public String upload(byte[] content, String path, String type) {
// 执行写入
String filePath = getFilePath(path);
FileUtil.writeBytes(content, filePath);
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
index ab95d4bda..a2b11b1dc 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
@@ -82,10 +82,11 @@ public class S3FileClient extends AbstractFileClient {
}
@Override
- public String upload(byte[] content, String path) throws Exception {
+ public String upload(byte[] content, String path, String type) throws Exception {
// 执行上传
client.putObject(PutObjectArgs.builder()
.bucket(config.getBucket()) // bucket 必须传递
+ .contentType(type)
.object(path) // 相对路径作为 key
.stream(new ByteArrayInputStream(content), content.length, -1) // 文件内容
.build());
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java
index 3e18e888d..facddcea0 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java
@@ -31,7 +31,7 @@ public class SftpFileClient extends AbstractFileClient {
}
@Override
- public String upload(byte[] content, String path) {
+ public String upload(byte[] content, String path, String type) {
// 执行写入
String filePath = getFilePath(path);
File file = FileUtils.createTempFile(content);
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 8d2a4be45..000000000
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.file.config.YudaoFileAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..9e5f42239
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.file.config.YudaoFileAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java
index 00a3a268e..619e52db8 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java
@@ -25,7 +25,7 @@ public class FtpFileClientTest {
// 上传文件
String path = IdUtil.fastSimpleUUID() + ".jpg";
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
- String fullPath = client.upload(content, path);
+ String fullPath = client.upload(content, path, "image/jpeg");
System.out.println("访问地址:" + fullPath);
if (false) {
byte[] bytes = client.getContent(path);
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java
index 2062d63d7..d48609bc6 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java
@@ -19,7 +19,7 @@ public class LocalFileClientTest {
// 上传文件
String path = IdUtil.fastSimpleUUID() + ".jpg";
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
- String fullPath = client.upload(content, path);
+ String fullPath = client.upload(content, path, "image/jpeg");
System.out.println("访问地址:" + fullPath);
client.delete(path);
}
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java
index de77477cd..1d0ed2091 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java
@@ -101,7 +101,7 @@ public class S3FileClientTest {
// 上传文件
String path = IdUtil.fastSimpleUUID() + ".jpg";
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
- String fullPath = client.upload(content, path);
+ String fullPath = client.upload(content, path, "image/jpeg");
System.out.println("访问地址:" + fullPath);
// 读取文件
if (true) {
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java
index 412df1ea8..4785c0d89 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java
@@ -23,7 +23,7 @@ public class SftpFileClientTest {
// 上传文件
String path = IdUtil.fastSimpleUUID() + ".jpg";
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
- String fullPath = client.upload(content, path);
+ String fullPath = client.upload(content, path, "image/jpeg");
System.out.println("访问地址:" + fullPath);
if (false) {
byte[] bytes = client.getContent(path);
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
index ef6720d16..7c29a6462 100644
--- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
@@ -2,13 +2,13 @@ package cn.iocoder.yudao.framework.flowable.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
public class YudaoFlowableConfiguration {
/**
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index c667d5e55..000000000
--- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..1df61598c
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java
index f1eef178c..6d517e5e4 100644
--- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java
@@ -3,15 +3,15 @@ package cn.iocoder.yudao.framework.quartz.config;
import com.alibaba.ttl.TtlRunnable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* 异步任务 Configuration
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableAsync
public class YudaoAsyncAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java
index 881e59913..f414e989a 100644
--- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java
@@ -2,14 +2,14 @@ package cn.iocoder.yudao.framework.quartz.config;
import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager;
import org.quartz.Scheduler;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 定时任务 Configuration
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableScheduling // 开启 Spring 自带的定时任务
public class YudaoQuartzAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index cecc4094c..000000000
--- a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.quartz.config.YudaoQuartzAutoConfiguration,\
- cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..4086f7a4a
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.quartz.config.YudaoQuartzAutoConfiguration
+cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java
index 7537f3eae..cc2a0df4e 100644
--- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java
@@ -3,17 +3,17 @@ package cn.iocoder.yudao.framework.tracer.config;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
/**
* Metrics 配置类
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({MeterRegistryCustomizer.class})
@ConditionalOnProperty(prefix = "yudao.metrics", value = "enable", matchIfMissing = true) // 允许使用 yudao.metrics.enable=false 禁用 Metrics
public class YudaoMetricsAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
index 74bbf1ed7..c7d9e2c0d 100644
--- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
@@ -3,19 +3,19 @@ package cn.iocoder.yudao.framework.tracer.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect;
import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
/**
* Tracer 配置类
*
* @author mashu
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({BizTraceAspect.class})
@EnableConfigurationProperties(TracerProperties.class)
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 9b69f01ea..000000000
--- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.tracer.config.YudaoTracerAutoConfiguration,\
- cn.iocoder.yudao.framework.tracer.config.YudaoMetricsAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..218ee31a2
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.tracer.config.YudaoTracerAutoConfiguration
+cn.iocoder.yudao.framework.tracer.config.YudaoMetricsAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java
index 89c2d4e59..c369d49d6 100644
--- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java
@@ -10,9 +10,8 @@ import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.connection.stream.Consumer;
import org.springframework.data.redis.connection.stream.ObjectRecord;
@@ -35,9 +34,8 @@ import java.util.Properties;
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
-@AutoConfigureAfter(YudaoRedisAutoConfiguration.class)
@Slf4j
+@AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
public class YudaoMQAutoConfiguration {
@Bean
@@ -55,7 +53,6 @@ public class YudaoMQAutoConfiguration {
* 创建 Redis Pub/Sub 广播消费的容器
*/
@Bean
- @Async // 异步化,可降低 2 秒左右的启动时间
public RedisMessageListenerContainer redisMessageListenerContainer(
RedisMQTemplate redisMQTemplate, List> listeners) {
// 创建 RedisMessageListenerContainer 对象
diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java
index 8585aafe6..e7d737d1b 100644
--- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java
+++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java
@@ -39,7 +39,7 @@ public abstract class AbstractChannelMessageListener
- mysql
- mysql-connector-java
+ com.mysql
+ mysql-connector-j
com.oracle.database.jdbc
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java
index 3e237f232..71d4ea466 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java
@@ -2,11 +2,11 @@ package cn.iocoder.yudao.framework.datasource.config;
import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
@@ -14,7 +14,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理
@EnableConfigurationProperties(DruidStatProperties.class)
public class YudaoDataSourceAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java
new file mode 100644
index 000000000..54198e496
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.framework.expression;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
+
+/**
+ * AndExpression 的扩展类(会在原有表达式两端加上括号)
+ */
+public class AndExpressionX extends AndExpression {
+
+ public AndExpressionX() {
+ }
+
+ public AndExpressionX(Expression leftExpression, Expression rightExpression) {
+ this.setLeftExpression(leftExpression);
+ this.setRightExpression(rightExpression);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + super.toString() + ")";
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java
new file mode 100644
index 000000000..19b4695cf
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.framework.expression;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
+
+/**
+ * OrExpression 的扩展类(会在原有表达式两端加上括号)
+ */
+public class OrExpressionX extends OrExpression {
+
+ public OrExpressionX() {
+ }
+
+ public OrExpressionX(Expression leftExpression, Expression rightExpression) {
+ this.setLeftExpression(leftExpression);
+ this.setRightExpression(rightExpression);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + super.toString() + ")";
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
index ce0596498..78ee259c8 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
@@ -13,9 +13,9 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
/**
@@ -23,7 +23,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@MapperScan(value = "${yudao.info.base-package}", annotationClass = Mapper.class,
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
public class YudaoMybatisAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
index fb4af6d69..e220d011d 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.mybatis.core.mapper;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -75,9 +76,13 @@ public interface BaseMapperX extends BaseMapper {
return selectList(new LambdaQueryWrapper().in(field, values));
}
+ default List selectList(SFunction leField, SFunction geField, Object value) {
+ return selectList(new LambdaQueryWrapper().le(leField, value).ge(geField, value));
+ }
+
/**
* 逐条插入,适合少量数据插入,或者对性能要求不高的场景
- *
+ *
* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
* 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
*
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories
index 96e3d8bcd..eb172e4ce 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories
@@ -1,5 +1,2 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\
- cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=\
cn.iocoder.yudao.framework.mybatis.config.IdTypeEnvironmentPostProcessor
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..1c159fd6f
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration
+cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java
index 3760bed19..23a75588f 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java
@@ -5,16 +5,14 @@ import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempo
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.List;
-@Configuration(proxyBeanMethods = false)
-@AutoConfigureAfter(YudaoRedisAutoConfiguration.class)
+@AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
public class YudaoIdempotentConfiguration {
@Bean
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java
index 2d2f4fd2f..2986da6c8 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java
@@ -4,12 +4,10 @@ import cn.hutool.core.util.ClassUtil;
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
import cn.iocoder.yudao.framework.lock4j.core.Lock4jRedisKeyConstants;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-@Configuration(proxyBeanMethods = false)
-@AutoConfigureBefore(LockAutoConfiguration.class)
+@AutoConfiguration(before = LockAutoConfiguration.class)
public class YudaoLock4jConfiguration {
static {
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 0e55a1f2a..000000000
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration,\
- cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..be5c0990d
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
+cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java
index 3814d487a..0b837569e 100644
--- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java
@@ -1,10 +1,10 @@
package cn.iocoder.yudao.framework.redis.config;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.RedisSerializationContext;
@@ -13,7 +13,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
/**
* Cache 配置类,基于 Redis 实现
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties({CacheProperties.class})
@EnableCaching
public class YudaoCacheAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java
index d814afe16..901830c69 100644
--- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java
@@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.redis.config;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
@@ -9,7 +9,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
/**
* Redis 配置类
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
public class YudaoRedisAutoConfiguration {
/**
diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index e4cefbab1..000000000
--- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration,\
- cn.iocoder.yudao.framework.redis.config.YudaoCacheAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..02d4a6835
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration
+cn.iocoder.yudao.framework.redis.config.YudaoCacheAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
index e9045c76f..7a766eb83 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
@@ -11,9 +11,9 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -30,7 +30,7 @@ import javax.annotation.Resource;
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties(SecurityProperties.class)
public class YudaoSecurityAutoConfiguration {
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
index fd1773c37..c3715c185 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
@@ -4,17 +4,17 @@ import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter
import cn.iocoder.yudao.framework.web.config.WebProperties;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.method.HandlerMethod;
@@ -32,9 +32,9 @@ import java.util.Set;
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
-public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+public class YudaoWebSecurityConfigurerAdapter {
@Resource
private WebProperties webProperties;
@@ -72,11 +72,9 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
* 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
* 通过覆写父类的该方法,添加 @Bean 注解,解决该问题
*/
- @Override
@Bean
- @ConditionalOnMissingBean(AuthenticationManager.class)
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
+ public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration) throws Exception {
+ return authenticationConfiguration.getAuthenticationManager();
}
/**
@@ -96,8 +94,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
- @Override
- protected void configure(HttpSecurity httpSecurity) throws Exception {
+ @Bean
+ protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
// 登出
httpSecurity
// 开启跨域
@@ -141,6 +139,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
// 添加 Token Filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+
+ return httpSecurity.build();
}
private String buildAppApi(String url) {
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 564bb0f78..000000000
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.security.config.YudaoSecurityAutoConfiguration,\
- cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..f64277f01
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+cn.iocoder.yudao.framework.security.config.YudaoSecurityAutoConfiguration
+cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
index c18bd248c..e98f4980f 100644
--- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
@@ -33,6 +33,10 @@ public class AssertUtils {
public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
Arrays.stream(expectedFields).forEach(expectedField -> {
+ // 忽略 jacoco 自动生成的 $jacocoData 属性的情况
+ if (expectedField.isSynthetic()) {
+ return;
+ }
// 如果是忽略的属性,则不进行比对
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
return;
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java
index e4f644173..6ced68756 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java
@@ -11,16 +11,14 @@ import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
-@Configuration(proxyBeanMethods = false)
-@AutoConfigureAfter(YudaoWebAutoConfiguration.class)
+@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
public class YudaoApiLogAutoConfiguration {
@Bean
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
index c44e770a1..c9dc5a2d9 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.jackson.config;
+import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -8,12 +9,12 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@Slf4j
public class YudaoJacksonAutoConfiguration {
@@ -32,8 +33,8 @@ public class YudaoJacksonAutoConfiguration {
* 2. 新增LocalDateTime序列化、反序列化规则
*/
simpleModule
-// .addSerializer(Long.class, ToStringSerializer.instance)
-// .addSerializer(Long.TYPE, ToStringSerializer.instance)
+ .addSerializer(Long.class, NumberSerializer.INSTANCE)
+ .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java
new file mode 100644
index 000000000..f9ff37511
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.framework.jackson.core.databind;
+
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
+
+public class LocalTimeJson {
+
+ public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
+ .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
+ .withZone(ZoneId.systemDefault()));
+
+ public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
+ .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
+ .withZone(ZoneId.systemDefault()));
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java
new file mode 100644
index 000000000..f6ddd3f27
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java
@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.framework.jackson.core.databind;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
+
+import java.io.IOException;
+
+/**
+ * Long 序列化规则
+ *
+ * 会将超长 long 值转换为 string,解决前端 JavaScript 最大安全整数是 2^53-1 的问题
+ *
+ * @author 星语
+ */
+@JacksonStdImpl
+public class NumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer {
+
+ private static final long MAX_SAFE_INTEGER = 9007199254740991L;
+ private static final long MIN_SAFE_INTEGER = -9007199254740991L;
+
+ public static final NumberSerializer INSTANCE = new NumberSerializer(Number.class);
+
+ public NumberSerializer(Class extends Number> rawType) {
+ super(rawType);
+ }
+
+ @Override
+ public void serialize(Number value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ // 超出范围 序列化位字符串
+ if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
+ super.serialize(value, gen, serializers);
+ } else {
+ gen.writeString(value.toString());
+ }
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
index 9e4233baf..240f0f284 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
@@ -2,11 +2,11 @@ package cn.iocoder.yudao.framework.swagger.config;
import cn.iocoder.yudao.framework.swagger.core.SpringFoxHandlerProviderBeanPostProcessor;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ExampleBuilder;
@@ -29,7 +29,7 @@ import static springfox.documentation.builders.RequestHandlerSelectors.basePacka
*
* @author 芋道源码
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableSwagger2
@EnableKnife4j
@ConditionalOnClass({Docket.class, ApiInfoBuilder.class})
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
index d5ad84eab..d2bffb166 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
@@ -9,11 +9,11 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.bind.annotation.RestController;
@@ -26,7 +26,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import javax.servlet.Filter;
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties({WebProperties.class, XssProperties.class})
public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 3b0e1d772..000000000
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,5 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration,\
- cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration,\
- cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration,\
- cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 000000000..2a422bfa2
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,4 @@
+cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
+cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
+cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
+cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
index a4ba5cc85..015fd0fd9 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -48,7 +48,7 @@ public interface BpmTaskConvert {
return null;
}
try {
- T newInstance = target.newInstance();
+ T newInstance = target.getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(source, newInstance);
return newInstance;
} catch (Exception e) {
@@ -77,6 +77,8 @@ public interface BpmTaskConvert {
}
@Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
+ @Mapping(target = "claimTime", expression = "java(bean.getClaimTime()==null?null: LocalDateTime.ofInstant(bean.getClaimTime().toInstant(),ZoneId.systemDefault()))")
+ @Mapping(target = "createTime", expression = "java(bean.getCreateTime()==null?null:LocalDateTime.ofInstant(bean.getCreateTime().toInstant(),ZoneId.systemDefault()))")
BpmTaskTodoPageItemRespVO convert1(Task bean);
@Named("convertSuspendedToSuspensionState")
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
index bb027d80e..abf4f4579 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -1 +1 @@
-package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1.
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1.
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
@Resource
private RuntimeService runtimeService;
@Resource
private BpmProcessInstanceExtMapper processInstanceExtMapper;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService taskService;
@Resource
private BpmProcessDefinitionService processDefinitionService;
@Resource
private HistoryService historyService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
@Resource
private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
@Resource
private BpmMessageService messageService;
@Override
public ProcessInstance getProcessInstance(String id) {
return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getProcessInstances(Set ids) {
return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public PageResult getMyProcessInstancePage(Long userId,
BpmProcessInstanceMyPageReqVO pageReqVO) {
// 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return new PageResult<>(pageResult.getTotal());
}
// 获得流程 Task Map
List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
// 转换返回
return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
// 发起流程
return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
}
@Override
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// 发起流程
return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
}
@Override
public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
// 获得流程实例
HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
if (processInstance == null) {
return null;
}
BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
// 获得流程定义
ProcessDefinition processDefinition = processDefinitionService
.getProcessDefinition(processInstance.getProcessDefinitionId());
Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
processInstance.getProcessDefinitionId());
Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
// 获得 User
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
DeptRespDTO dept = null;
if (startUser != null) {
dept = deptApi.getDept(startUser.getDeptId());
}
// 拼接结果
return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
}
@Override
public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// 校验流程实例存在
ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
if (instance == null) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
}
// 只能取消自己的
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
}
// 通过删除流程实例,实现流程实例的取消,
// 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询
deleteProcessInstance(cancelReqVO.getId(),
BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
}
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
@Override
public HistoricProcessInstance getHistoricProcessInstance(String id) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getHistoricProcessInstances(Set ids) {
return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public void createProcessInstanceExt(ProcessInstance instance) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
// 插入 BpmProcessInstanceExtDO 对象
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getId())
.setProcessDefinitionId(definition.getId())
.setName(instance.getProcessDefinitionName())
.setStartUserId(Long.valueOf(instance.getStartUserId()))
.setCategory(definition.getCategory())
.setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
processInstanceExtMapper.insert(instanceExtDO);
}
@Override
public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
// 判断是否为 Reject 不通过。如果是,则不进行更新.
// 因为,updateProcessInstanceExtReject 方法,已经进行更新了
if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
return;
}
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(event.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
public void updateProcessInstanceExtComplete(ProcessInstance instance) {
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被通过的消息
messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例,以实现驳回任务时,取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
// 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
private void deleteProcessInstance(String id, String reason) {
runtimeService.deleteProcessInstance(id, reason);
}
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map variables, String businessKey) {
// 校验流程定义
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 创建流程实例
ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
// 设置流程名字
runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
// 补全流程实例的拓展表
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
.setFormVariables(variables));
return instance.getId();
}
}
\ No newline at end of file
+package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1.
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1.
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
@Resource
private RuntimeService runtimeService;
@Resource
private BpmProcessInstanceExtMapper processInstanceExtMapper;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService taskService;
@Resource
private BpmProcessDefinitionService processDefinitionService;
@Resource
private HistoryService historyService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
@Resource
private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
@Resource
private BpmMessageService messageService;
@Override
public ProcessInstance getProcessInstance(String id) {
return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getProcessInstances(Set ids) {
return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public PageResult getMyProcessInstancePage(Long userId,
BpmProcessInstanceMyPageReqVO pageReqVO) {
// 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return new PageResult<>(pageResult.getTotal());
}
// 获得流程 Task Map
List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
// 转换返回
return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
// 发起流程
return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
}
@Override
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// 发起流程
return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
}
@Override
public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
// 获得流程实例
HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
if (processInstance == null) {
return null;
}
BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
// 获得流程定义
ProcessDefinition processDefinition = processDefinitionService
.getProcessDefinition(processInstance.getProcessDefinitionId());
Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
processInstance.getProcessDefinitionId());
Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
// 获得 User
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
DeptRespDTO dept = null;
if (startUser != null) {
dept = deptApi.getDept(startUser.getDeptId());
}
// 拼接结果
return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
}
@Override
public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// 校验流程实例存在
ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
if (instance == null) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
}
// 只能取消自己的
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
}
// 通过删除流程实例,实现流程实例的取消,
// 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询
deleteProcessInstance(cancelReqVO.getId(),
BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
}
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
@Override
public HistoricProcessInstance getHistoricProcessInstance(String id) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getHistoricProcessInstances(Set ids) {
return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public void createProcessInstanceExt(ProcessInstance instance) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
// 插入 BpmProcessInstanceExtDO 对象
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getId())
.setProcessDefinitionId(definition.getId())
.setName(instance.getProcessDefinitionName())
.setStartUserId(Long.valueOf(instance.getStartUserId()))
.setCategory(definition.getCategory())
.setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
processInstanceExtMapper.insert(instanceExtDO);
}
@Override
public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
// 判断是否为 Reject 不通过。如果是,则不进行更新.
// 因为,updateProcessInstanceExtReject 方法,已经进行更新了
if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
return;
}
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(event.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
public void updateProcessInstanceExtComplete(ProcessInstance instance) {
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被通过的消息
messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例,以实现驳回任务时,取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
// 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
private void deleteProcessInstance(String id, String reason) {
runtimeService.deleteProcessInstance(id, reason);
}
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map variables, String businessKey) {
// 校验流程定义
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 创建流程实例
ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
// 设置流程名字
runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
// 补全流程实例的拓展表
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
.setFormVariables(variables));
return instance.getId();
}
}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
index de62eb28a..36541f1ab 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.service.definition;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
@@ -19,7 +18,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS;
@@ -106,7 +105,7 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest {
BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到
o.setName("芋道源码");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
- o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11));
+ o.setCreateTime(buildTime(2021, 11, 11));
});
userGroupMapper.insert(dbUserGroup);
// 测试 name 不匹配
@@ -114,12 +113,12 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest {
// 测试 status 不匹配
userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 测试 createTime 不匹配
- userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12))));
+ userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildTime(2021, 12, 12))));
// 准备参数
BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO();
reqVO.setName("源码");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
// 调用
PageResult pageResult = userGroupService.getUserGroupPage(reqVO);
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
index 90f5816f3..8293ffef0 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
@@ -18,6 +18,8 @@ import org.springframework.stereotype.Component;
import java.util.*;
import static cn.hutool.core.text.CharSequenceUtil.*;
+import static cn.hutool.core.util.RandomUtil.randomEle;
+import static cn.hutool.core.util.RandomUtil.randomInt;
/**
* 代码生成器的 Builder,负责:
@@ -128,6 +130,7 @@ public class CodegenBuilder {
// 初始化 Column 列的默认字段
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
processColumnUI(column); // 处理 UI 相关的字段的默认值
+ processColumnExample(column); // 处理字段的 swagger example 示例
}
return columns;
}
@@ -169,4 +172,42 @@ public class CodegenBuilder {
}
}
+ /**
+ * 处理字段的 swagger example 示例
+ *
+ * @param column 字段
+ */
+ private void processColumnExample(CodegenColumnDO column) {
+ // id、price、count 等可能是整数的后缀
+ if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) {
+ column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE)));
+ return;
+ }
+ // name
+ if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) {
+ column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"}));
+ return;
+ }
+ // status
+ if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) {
+ column.setExample(randomEle(new String[]{"1", "2"}));
+ return;
+ }
+ // url
+ if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) {
+ column.setExample("https://www.iocoder.cn");
+ return;
+ }
+ // reason
+ if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) {
+ column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"}));
+ return;
+ }
+ // description、memo、remark
+ if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) {
+ column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"}));
+ return;
+ }
+ }
+
}
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 cec246bfc..132e903d9 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
@@ -91,8 +91,6 @@ public class CodegenEngine {
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
.put(vue3TemplatePath("api/api.ts"),
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
- .put(vue3TemplatePath("api/types.ts"),
- vue3FilePath("api/${table.moduleName}/${classNameVar}/types.ts"))
// SQL
.put("codegen/sql/sql.vm", "sql/sql.sql")
.put("codegen/sql/h2.vm", "sql/h2.sql")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
index 88a0ff59e..48361c14c 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.infra.service.file;
-import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -20,7 +19,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -79,20 +77,36 @@ public class FileConfigServiceImpl implements FileConfigService {
@Resource
private Validator validator;
- @Resource
- @Lazy // 注入自己,所以延迟加载
- private FileConfigService self;
-
@Override
@PostConstruct
public void initFileClients() {
- // 获取文件配置,如果有更新
- List configs = loadFileConfigIfUpdate(maxUpdateTime);
- if (CollUtil.isEmpty(configs)) {
+ initLocalCacheIfUpdate(null);
+ }
+
+ @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
+ public void schedulePeriodicRefresh() {
+ initLocalCacheIfUpdate(this.maxUpdateTime);
+ }
+
+ /**
+ * 刷新本地缓存
+ *
+ * @param maxUpdateTime 最大更新时间
+ * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
+ * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
+ */
+ private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
+ // 第一步:基于 maxUpdateTime 判断缓存是否刷新。
+ // 如果没有增量的数据变化,则不进行本地缓存的刷新
+ if (maxUpdateTime != null
+ && fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
+ log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
return;
}
+ List configs = fileConfigMapper.selectList();
+ log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size());
- // 创建或更新支付 Client
+ // 第二步:构建缓存。创建或更新文件 Client
configs.forEach(config -> {
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
// 如果是 master,进行设置
@@ -101,35 +115,8 @@ public class FileConfigServiceImpl implements FileConfigService {
}
});
- // 写入缓存
- maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
- log.info("[initFileClients][初始化 FileConfig 数量为 {}]", configs.size());
- }
-
- @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
- public void schedulePeriodicRefresh() {
- self.initFileClients();
- }
-
- /**
- * 如果文件配置发生变化,从数据库中获取最新的全量文件配置。
- * 如果未发生变化,则返回空
- *
- * @param maxUpdateTime 当前文件配置的最大更新时间
- * @return 文件配置列表
- */
- private List loadFileConfigIfUpdate(LocalDateTime maxUpdateTime) {
- // 第一步,判断是否要更新。
- if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
- log.info("[loadFileConfigIfUpdate][首次加载全量文件配置]");
- } else { // 判断数据库中是否有更新的文件配置
- if (fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
- return null;
- }
- log.info("[loadFileConfigIfUpdate][增量加载全量文件配置]");
- }
- // 第二步,如果有更新,则从数据库加载所有文件配置
- return fileConfigMapper.selectList();
+ // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
+ this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
}
@Override
@@ -230,7 +217,7 @@ public class FileConfigServiceImpl implements FileConfigService {
this.validateFileConfigExists(id);
// 上传文件
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
- return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg");
+ return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg");
}
@Override
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index 493a9ed1f..2226e7bae 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
@@ -52,7 +52,7 @@ public class FileServiceImpl implements FileService {
// 上传到文件存储器
FileClient client = fileConfigService.getMasterFileClient();
Assert.notNull(client, "客户端(master) 不能为空");
- String url = client.upload(content, path);
+ String url = client.upload(content, path, type);
// 保存到数据库
FileDO file = new FileDO();
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm
index dc6cee6b6..bf6408c9c 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm
@@ -9,7 +9,7 @@ import javax.validation.constraints.*;
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult})
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
-
+import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm
index 4034b6f63..19bc32db6 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm
@@ -1,7 +1,12 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import lombok.*;
-import java.util.*;
+#foreach ($column in $columns)
+#if (${column.javaType} == "LocalDateTime")
+import java.time.LocalDateTime;
+#break
+#end
+#end
import io.swagger.annotations.*;
@ApiModel("${sceneEnum.name} - ${table.classComment} Response VO")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
index d1099ecbf..df49a002b 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
@@ -1,7 +1,48 @@
import request from '@/config/axios'
-import { ${simpleClassName}VO, ${simpleClassName}PageReqVO, ${simpleClassName}ExcelReqVO } from './types'
+export interface ${simpleClassName}VO {
+#foreach ($column in $columns)
+#if ($column.createOperation || $column.updateOperation)
+#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
+ ${column.javaField}: number
+#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
+ ${column.javaField}: Date
+#else
+ ${column.javaField}: ${column.javaType.toLowerCase()}
+#end
+#end
+#end
+}
+
+export interface ${simpleClassName}PageReqVO extends PageParam {
+#foreach ($column in $columns)
+#if (${column.listOperation})##查询操作
+#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
+ ${column.javaField}?: number
+#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
+ ${column.javaField}?: Date[]
+#else
+ ${column.javaField}?: ${column.javaType.toLowerCase()}
+#end
+#end
+#end
+}
+
+export interface ${simpleClassName}ExcelReqVO {
+#foreach ($column in $columns)
+#if (${column.listOperation})##查询操作
+#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
+ ${column.javaField}?: number
+#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
+ ${column.javaField}?: Date[]
+#else
+ ${column.javaField}?: ${column.javaType.toLowerCase()}
+#end
+#end
+#end
+}
#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
+
// 查询${table.classComment}列表
export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => {
return await request.get({ url: '${baseURL}/page', params })
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm
deleted file mode 100644
index 54ab47e02..000000000
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm
+++ /dev/null
@@ -1,41 +0,0 @@
-export type ${simpleClassName}VO = {
-#foreach ($column in $columns)
-#if ($column.createOperation || $column.updateOperation)
-#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
- ${column.javaField}: number
-#elseif(${column.javaType.toLowerCase()} == "date")
- ${column.javaField}: string
-#else
- ${column.javaField}: ${column.javaType.toLowerCase()}
-#end
-#end
-#end
-}
-
-export type ${simpleClassName}PageReqVO = {
-#foreach ($column in $columns)
-#if (${column.listOperation})##查询操作
-#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
- ${column.javaField}: number
-#elseif(${column.javaType.toLowerCase()} == "date")
- ${column.javaField}: string
-#else
- ${column.javaField}: ${column.javaType.toLowerCase()}
-#end
-#end
-#end
-}
-
-export type ${simpleClassName}ExcelReqVO = {
-#foreach ($column in $columns)
-#if (${column.listOperation})##查询操作
-#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
- ${column.javaField}: number
-#elseif(${column.javaType.toLowerCase()} == "date")
- ${column.javaField}: string
-#else
- ${column.javaField}: ${column.javaType.toLowerCase()}
-#end
-#end
-#end
-}
\ No newline at end of file
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
index fa64bc883..33e204a46 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
@@ -1,111 +1,110 @@
import { reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
-import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
import { DICT_TYPE } from '@/utils/dict'
+import { required } from '@/utils/formRules'
+import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
const { t } = useI18n() // 国际化
// 表单校验
export const rules = reactive({
#foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
- $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == "select")'change'#else'blur'#end }],
+ $column.javaField: [required],
#end
#end
})
// CrudSchema
-const crudSchemas = reactive([
-#foreach($column in $columns)
- #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
- #set ($dictType = $column.dictType)
- {
- label: '${column.columnComment}',
- field: '${column.javaField}',
- #if ("" != $dictType)## 有数据字典
- dictType: DICT_TYPE.$dictType.toUpperCase(),
- #end
- #if($column.primaryKey)
- type: 'index',
- form: {
- show: false
- },
- detail: {
- show: false
- }
- #else
- #if (!$column.createOperation && !$column.updateOperation)
- form: {
- show: false
- },
- #elseif(!("" != $column.dictType))
- form: {
- show: true,
- #if ($column.htmlType == "datetime")## 时间框
- component: 'DatePicker',
- componentProps: {
- type: 'datetime',
- valueFormat: 'YYYY-MM-DD HH:mm:ss'
- }
+const crudSchemas = reactive({
+ primaryKey: 'id', // 默认的主键ID
+ primaryTitle: t('common.index'), // 默认显示的值
+ primaryType: 'seq', // 默认为seq,序号模式
+ action: true,
+ actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可
+ columns: [
+ #foreach($column in $columns)
+ #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
+ #set ($dictType = $column.dictType)
+ #if(!$column.primaryKey)
+ {
+ title: '${column.columnComment}',
+ field: '${column.javaField}',
+ #if (!$column.listOperationResult)
+ isTable: false,
+ #end
+ #if ("" != $dictType)## 有数据字典
+ dictType: DICT_TYPE.$dictType.toUpperCase(),
+ #if (${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
+ dictClass: 'number',
+ #else
+ dictClass: 'string',
+ #end
+ #end
+ #if (!$column.createOperation && !$column.updateOperation)
+ isForm: false,
+ #elseif(!("" != $column.dictType))
+ #if (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
+ form: {
+ component: 'DatePicker',
+ componentProps: {
+ type: 'datetime',
+ valueFormat: 'x'
+ }
+ },
#elseif($column.htmlType == "editor")## 文本编辑器
- component: 'Editor',
- colProps: {
- span: 24
+ form: {
+ component: 'Editor',
+ colProps: {
+ span: 24
+ },
+ componentProps: {
+ valueHtml: ''
+ }
},
- componentProps: {
- valueHtml: ''
- }
#elseif($column.htmlType == "textarea")## 文本框
- component: 'Input',
- componentProps: {
- type: 'textarea',
- rows: 4
+ form: {
+ component: 'Input',
+ componentProps: {
+ type: 'textarea',
+ rows: 4
+ },
+ colProps: {
+ span: 24
+ }
+ },
+ #elseif(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")## 数字类型
+ form: {
+ component: 'InputNumber',
+ value: 0
+ },
+ #elseif($column.htmlType == "imageUpload")## 图片上传
+ form: {
+ component: 'UploadImg' // 单图上传,多图为UploadImgs
+ },
+ #elseif($column.htmlType == "fileUpload")## 图片上传
+ form: {
+ component: 'UploadFile'
},
- colProps: {
- span: 24
- }
#end
- },
- #end
- #if ($column.listOperationResult)
- search: {
+ #end
+ #if ($column.listOperation)
#if($column.htmlType == "input")
- show: true
- #else
- #if($column.htmlType == "datetime")
- show: true,
- component: 'DatePicker',
- componentProps: {
- type: 'datetimerange',
- valueFormat: 'YYYY-MM-DD HH:mm:ss'
- }
- #elseif($column.htmlType == "select" || $column.htmlType == "radio")
- #if ("" == $dictType)## 没有数据字典
- show: true,
- component: 'Select',
- componentProps: {
- option: [{'','请选择字典生成'}]
- }
- #else
- show: true
+ isSearch: true,
+ #elseif("" != $dictType)
+ isSearch: true,
+ #elseif($column.htmlType == "datetime")
+ formatter: 'formatDate',
+ search: {
+ show: true,
+ itemRender: {
+ name: 'XDataTimePicker'
+ }
+ },
#end
#end
- #end
- }
- #end
- #end
- },
- #end
-#end
- {
- label: t('table.action'),
- field: 'action',
- width: '240px',
- form: {
- show: false
},
- detail: {
- show: false
- }
- }
-])
-
-export const { allSchemas } = useCrudSchemas(crudSchemas)
\ No newline at end of file
+ #end
+ #end
+ #end
+ ]
+})
+export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
\ No newline at end of file
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
index 509f1493f..06fe3002a 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
@@ -1,51 +1,151 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#foreach($column in $columns)
-#if ($column.listOperationResult)
- #set ($dictType=$column.dictType)
- #if ($column.javaType == "LocalDateTime")## 时间类型
-
- {{ dayjs(row.${column.javaField}).format('YYYY-MM-DD HH:mm:ss') }}
-
- #elseif("" != $column.dictType)## 数据字典
-
-
-
- #end
-#end
-#end
-
-
-
-
-
-
-
-
-
-
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java
index 5220a8cad..5f29e79ec 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java
@@ -22,7 +22,7 @@ import java.util.List;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.randomEle;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
@@ -153,7 +153,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
o.setName("芋艿");
o.setConfigKey("yunai");
o.setType(ConfigTypeEnum.SYSTEM.getType());
- o.setCreateTime(buildLocalDateTime(2021, 2, 1));
+ o.setCreateTime(buildTime(2021, 2, 1));
});
configMapper.insert(dbConfig);
// 测试 name 不匹配
@@ -163,13 +163,13 @@ public class ConfigServiceTest extends BaseDbUnitTest {
// 测试 type 不匹配
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType())));
// 测试 createTime 不匹配
- configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1))));
+ configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
// 准备参数
ConfigPageReqVO reqVO = new ConfigPageReqVO();
reqVO.setName("艿");
reqVO.setKey("nai");
reqVO.setType(ConfigTypeEnum.SYSTEM.getType());
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 15),buildLocalDateTime(2021, 2, 15)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 15),buildTime(2021, 2, 15)}));
// 调用
PageResult pageResult = configService.getConfigPage(reqVO);
@@ -186,7 +186,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
o.setName("芋艿");
o.setConfigKey("yunai");
o.setType(ConfigTypeEnum.SYSTEM.getType());
- o.setCreateTime(buildLocalDateTime(2021, 2, 1));
+ o.setCreateTime(buildTime(2021, 2, 1));
});
configMapper.insert(dbConfig);
// 测试 name 不匹配
@@ -196,13 +196,13 @@ public class ConfigServiceTest extends BaseDbUnitTest {
// 测试 type 不匹配
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType())));
// 测试 createTime 不匹配
- configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1))));
+ configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
// 准备参数
ConfigExportReqVO reqVO = new ConfigExportReqVO();
reqVO.setName("艿");
reqVO.setKey("nai");
reqVO.setType(ConfigTypeEnum.SYSTEM.getType());
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 15),buildLocalDateTime(2021, 2, 15)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 15),buildTime(2021, 2, 15)}));
// 调用
List list = configService.getConfigList(reqVO);
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
index 1b28b0e12..33d0d1ad7 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
@@ -28,7 +28,7 @@ import java.time.LocalDateTime;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.randomEle;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
@@ -219,8 +219,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
FileConfigPageReqVO reqVO = new FileConfigPageReqVO();
reqVO.setName("芋道");
reqVO.setStorage(FileStorageEnum.LOCAL.getStorage());
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 1, 1),
- buildLocalDateTime(2020, 1, 24)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 1, 1),
+ buildTime(2020, 1, 24)}));
// 调用
PageResult pageResult = fileConfigService.getFileConfigPage(reqVO);
@@ -240,7 +240,7 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
// mock 获得 Client
FileClient fileClient = mock(FileClient.class);
when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
- when(fileClient.upload(any(), any())).thenReturn("https://www.iocoder.cn");
+ when(fileClient.upload(any(), any(), any())).thenReturn("https://www.iocoder.cn");
// 调用,并断言
assertEquals("https://www.iocoder.cn", fileConfigService.testFileConfig(id));
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
index 80fd90ece..2d4285bee 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
@@ -17,7 +17,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;
@@ -43,7 +43,7 @@ public class FileServiceTest extends BaseDbUnitTest {
FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
o.setPath("yunai");
o.setType("image/jpg");
- o.setCreateTime(buildLocalDateTime(2021, 1, 15));
+ o.setCreateTime(buildTime(2021, 1, 15));
});
fileMapper.insert(dbFile);
// 测试 path 不匹配
@@ -54,13 +54,13 @@ public class FileServiceTest extends BaseDbUnitTest {
}));
// 测试 createTime 不匹配
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
- o.setCreateTime(buildLocalDateTime(2020, 1, 15));
+ o.setCreateTime(buildTime(2020, 1, 15));
}));
// 准备参数
FilePageReqVO reqVO = new FilePageReqVO();
reqVO.setPath("yunai");
reqVO.setType("jp");
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 10), buildLocalDateTime(2021, 1, 20)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 10), buildTime(2021, 1, 20)}));
// 调用
PageResult pageResult = fileService.getFilePage(reqVO);
@@ -79,7 +79,7 @@ public class FileServiceTest extends BaseDbUnitTest {
FileClient client = mock(FileClient.class);
when(fileConfigService.getMasterFileClient()).thenReturn(client);
String url = randomString();
- when(client.upload(same(content), same(path))).thenReturn(url);
+ when(client.upload(same(content), same(path), same("image/jpeg"))).thenReturn(url);
when(client.getId()).thenReturn(10L);
String name = "单测文件名";
// 调用
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java
index 89323b142..665e9c509 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
import java.util.List;
import static cn.hutool.core.util.RandomUtil.randomEle;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -96,8 +96,8 @@ public class JobLogServiceTest extends BaseDbUnitTest {
o.setExecuteIndex(1);
o.setHandlerName("handlerName 单元测试");
o.setStatus(JobLogStatusEnum.SUCCESS.getStatus());
- o.setBeginTime(buildLocalDateTime(2021, 1, 8));
- o.setEndTime(buildLocalDateTime(2021, 1, 8));
+ o.setBeginTime(buildTime(2021, 1, 8));
+ o.setEndTime(buildTime(2021, 1, 8));
});
jobLogMapper.insert(dbJobLog);
// 测试 jobId 不匹配
@@ -105,9 +105,9 @@ public class JobLogServiceTest extends BaseDbUnitTest {
// 测试 handlerName 不匹配
jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
// 测试 beginTime 不匹配
- jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildLocalDateTime(2021, 1, 7))));
+ jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
// 测试 endTime 不匹配
- jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildLocalDateTime(2021, 1, 9))));
+ jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
// 测试 status 不匹配
jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus())));
// 准备参数
@@ -132,8 +132,8 @@ public class JobLogServiceTest extends BaseDbUnitTest {
o.setExecuteIndex(1);
o.setHandlerName("handlerName 单元测试");
o.setStatus(JobLogStatusEnum.SUCCESS.getStatus());
- o.setBeginTime(buildLocalDateTime(2021, 1, 8));
- o.setEndTime(buildLocalDateTime(2021, 1, 8));
+ o.setBeginTime(buildTime(2021, 1, 8));
+ o.setEndTime(buildTime(2021, 1, 8));
});
jobLogMapper.insert(dbJobLog);
// 测试 jobId 不匹配
@@ -141,9 +141,9 @@ public class JobLogServiceTest extends BaseDbUnitTest {
// 测试 handlerName 不匹配
jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
// 测试 beginTime 不匹配
- jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildLocalDateTime(2021, 1, 7))));
+ jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
// 测试 endTime 不匹配
- jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildLocalDateTime(2021, 1, 9))));
+ jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
// 测试 status 不匹配
jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus())));
// 准备参数
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java
index cb1e52b23..b650fb603 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java
@@ -19,7 +19,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -40,7 +40,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
int userType = UserTypeEnum.ADMIN.getValue();
String applicationName = "yudao-test";
String requestUrl = "foo";
- LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13);
+ LocalDateTime beginTime = buildTime(2021, 3, 13);
int duration = 1000;
int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode();
@@ -65,7 +65,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
// requestUrl 不同的
apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
// 构造一个早期时间 2021-02-06 00:00:00
- apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildLocalDateTime(2021, 2, 6))));
+ apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
// duration 不同的
apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
// resultCode 不同的
@@ -77,7 +77,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
reqVO.setUserType(userType);
reqVO.setApplicationName(applicationName);
reqVO.setRequestUrl(requestUrl);
- reqVO.setBeginTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)}));
+ reqVO.setBeginTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)}));
reqVO.setDuration(duration);
reqVO.setResultCode(resultCode);
@@ -97,7 +97,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
int userType = UserTypeEnum.ADMIN.getValue();
String applicationName = "yudao-test";
String requestUrl = "foo";
- LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13);
+ LocalDateTime beginTime = buildTime(2021, 3, 13);
int duration = 1000;
int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode();
@@ -122,7 +122,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
// requestUrl 不同的
apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
// 构造一个早期时间 2021-02-06 00:00:00
- apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildLocalDateTime(2021, 2, 6))));
+ apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
// duration 不同的
apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
// resultCode 不同的
@@ -134,7 +134,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest {
reqVO.setUserType(userType);
reqVO.setApplicationName(applicationName);
reqVO.setRequestUrl(requestUrl);
- reqVO.setBeginTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)}));
+ reqVO.setBeginTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)}));
reqVO.setDuration(duration);
reqVO.setResultCode(resultCode);
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java
index bffdf46e8..4e35ba7ea 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java
@@ -20,7 +20,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
@@ -44,7 +44,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
int userType = UserTypeEnum.ADMIN.getValue();
String applicationName = "yudao-test";
String requestUrl = "foo";
- LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13);
+ LocalDateTime beginTime = buildTime(2021, 3, 13);
int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus();
ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> {
@@ -67,7 +67,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
// requestUrl 不同的
infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
// 构造一个早期时间 2021-02-06 00:00:00
- infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildLocalDateTime(2021, 2, 6))));
+ infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
// progressStatus 不同的
infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus())));
@@ -77,7 +77,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
reqVO.setUserType(userType);
reqVO.setApplicationName(applicationName);
reqVO.setRequestUrl(requestUrl);
- reqVO.setExceptionTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)}));
+ reqVO.setExceptionTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)}));
reqVO.setProcessStatus(progressStatus);
// 调用service方法
@@ -96,7 +96,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
int userType = UserTypeEnum.ADMIN.getValue();
String applicationName = "yudao-test";
String requestUrl = "foo";
- LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13);
+ LocalDateTime beginTime = buildTime(2021, 3, 13);
int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus();
ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> {
@@ -119,7 +119,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
// requestUrl 不同的
infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
// 构造一个早期时间 2021-02-06 00:00:00
- infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildLocalDateTime(2021, 2, 6))));
+ infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
// progressStatus 不同的
infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus())));
@@ -129,7 +129,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest {
reqVO.setUserType(userType);
reqVO.setApplicationName(applicationName);
reqVO.setRequestUrl(requestUrl);
- reqVO.setExceptionTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)}));
+ reqVO.setExceptionTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)}));
reqVO.setProcessStatus(progressStatus);
// 调用service方法
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java
index 356b98b00..c4a7fb46e 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.test;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO;
@@ -17,7 +16,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
@@ -112,7 +111,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
o.setType(1);
o.setCategory(2);
o.setRemark("哈哈哈");
- o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11));
+ o.setCreateTime(buildTime(2021, 11, 11));
});
testDemoMapper.insert(dbTestDemo);
// 测试 name 不匹配
@@ -126,7 +125,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
// 测试 remark 不匹配
testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵")));
// 测试 createTime 不匹配
- testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12))));
+ testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(buildTime(2021, 12, 12))));
// 准备参数
TestDemoPageReqVO reqVO = new TestDemoPageReqVO();
reqVO.setName("芋道");
@@ -134,7 +133,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
reqVO.setType(1);
reqVO.setCategory(2);
reqVO.setRemark("哈哈哈");
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
// 调用
PageResult pageResult = testDemoService.getTestDemoPage(reqVO);
@@ -153,7 +152,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
o.setType(1);
o.setCategory(2);
o.setRemark("哈哈哈");
- o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11));
+ o.setCreateTime(buildTime(2021, 11, 11));
});
testDemoMapper.insert(dbTestDemo);
// 测试 name 不匹配
@@ -167,7 +166,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
// 测试 remark 不匹配
testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵")));
// 测试 createTime 不匹配
- testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12))));
+ testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(buildTime(2021, 12, 12))));
// 准备参数
TestDemoExportReqVO reqVO = new TestDemoExportReqVO();
reqVO.setName("芋道");
@@ -175,7 +174,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest {
reqVO.setType(1);
reqVO.setCategory(2);
reqVO.setRemark("哈哈哈");
- reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)}));
+ reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
// 调用
List list = testDemoService.getTestDemoList(reqVO);
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java
new file mode 100644
index 000000000..83269f91d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.api.property;
+
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品属性值 API 接口
+ *
+ * @author 芋道源码
+ */
+public interface ProductPropertyValueApi {
+
+ /**
+ * 根据编号数组,获得属性值列表
+ *
+ * @param ids 编号数组
+ * @return 属性值明细列表
+ */
+ List getPropertyValueDetailList(Collection ids);
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java
new file mode 100644
index 000000000..2a1ab71a9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.product.api.property.dto;
+
+import lombok.Data;
+
+/**
+ * 商品属性项的明细 Response DTO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class ProductPropertyValueDetailRespDTO {
+
+ /**
+ * 属性的编号
+ */
+ private Long propertyId;
+
+ /**
+ * 属性的名称
+ */
+ private String propertyName;
+
+ /**
+ * 属性值的编号
+ */
+ private Long valueId;
+
+ /**
+ * 属性值的名称
+ */
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
index 4b324149b..aaaf767f2 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
@@ -18,17 +18,17 @@ public class ProductSkuRespDTO {
* 商品 SKU 编号,自增
*/
private Long id;
- /**
- * 商品 SKU 名字
- */
- private String name;
/**
* SPU 编号
*/
private Long spuId;
+ /**
+ * SPU 名字
+ */
+ private String spuName;
/**
- * 规格值数组,JSON 格式
+ * 属性数组,JSON 格式
*/
private List properties;
/**
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
index 86875b119..4adad0afc 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -15,28 +15,30 @@ public interface ErrorCodeConstants {
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
- ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
// ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
- // ========== 商品规格名称 1008003000 ==========
- ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
- ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在");
+ // ========== 商品属性项 1008003000 ==========
+ ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
+ ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
+ ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
- // ========== 规格值 1008004000 ==========
- ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
- ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在");
+ // ========== 商品属性值 1008004000 ==========
+ ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
+ ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
// ========== 商品 SPU 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
+ ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
+ ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
// ========== 商品 SKU 1008006000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
- ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
+ ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
index 30ece744d..fbc227b53 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
@@ -21,11 +21,11 @@ public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
/**
- * 规格
+ * 规格类型
*/
private final Integer type;
/**
- * 规格名
+ * 规格名称
*/
private final String name;
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
index 6b7f03ac2..2223cf23d 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
@@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
return ARRAYS;
}
+ /**
+ * 判断是否处于【上架】状态
+ *
+ * @param status 状态
+ * @return 是否处于【上架】状态
+ */
+ public static boolean isEnable(Integer status) {
+ return ENABLE.getStatus().equals(status);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
new file mode 100644
index 000000000..9aab9e560
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.product.api.property;
+
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
+import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品属性值 API 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {
+
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
+
+ @Override
+ public List getPropertyValueDetailList(Collection ids) {
+ return ProductPropertyValueConvert.INSTANCE.convertList02(
+ productPropertyValueService.getPropertyValueDetailList(ids));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
index 9a4c20c58..5efecd0c7 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
@@ -1,9 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.property;
+import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
+import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@@ -13,12 +18,13 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
-
+import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
-@Api(tags = "管理后台 - 规格名称")
+@Api(tags = "管理后台 - 商品属性项")
@RestController
@RequestMapping("/product/property")
@Validated
@@ -26,16 +32,18 @@ public class ProductPropertyController {
@Resource
private ProductPropertyService productPropertyService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
- @ApiOperation("创建规格名称")
+ @ApiOperation("创建属性项")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
return success(productPropertyService.createProperty(createReqVO));
}
@PutMapping("/update")
- @ApiOperation("更新规格名称")
+ @ApiOperation("更新属性项")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
productPropertyService.updateProperty(updateReqVO);
@@ -43,7 +51,7 @@ public class ProductPropertyController {
}
@DeleteMapping("/delete")
- @ApiOperation("删除规格名称")
+ @ApiOperation("删除属性项")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult deleteProperty(@RequestParam("id") Long id) {
@@ -52,32 +60,40 @@ public class ProductPropertyController {
}
@GetMapping("/get")
- @ApiOperation("获得规格名称")
+ @ApiOperation("获得属性项")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult getProperty(@RequestParam("id") Long id) {
- return success(productPropertyService.getProperty(id));
+ return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id)));
}
@GetMapping("/list")
- @ApiOperation("获得规格名称列表")
+ @ApiOperation("获得属性项列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
- return success(productPropertyService.getPropertyList(listReqVO));
+ return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO)));
}
@GetMapping("/page")
- @ApiOperation("获得规格名称分页")
+ @ApiOperation("获得属性项分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
- return success(productPropertyService.getPropertyPage(pageVO));
+ return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
}
- @GetMapping("/listAndValue")
- @ApiOperation("获得规格名称列表")
+ @GetMapping("/get-value-list")
+ @ApiOperation("获得属性项列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
- return success(productPropertyService.getPropertyAndValueList(listReqVO));
+ // 查询属性项
+ List keys = productPropertyService.getPropertyList(listReqVO);
+ if (CollUtil.isEmpty(keys)) {
+ return success(Collections.emptyList());
+ }
+ // 查询属性值
+ List values = productPropertyValueService.getPropertyValueListByPropertyId(
+ convertSet(keys, ProductPropertyDO::getId));
+ return success(ProductPropertyConvert.INSTANCE.convertList(keys, values));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
index e88c91415..fec327946 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.property;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
+import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -20,7 +20,7 @@ import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-@Api(tags = "管理后台 - 规格值名称")
+@Api(tags = "管理后台 - 商品属性值")
@RestController
@RequestMapping("/product/property/value")
@Validated
@@ -30,14 +30,14 @@ public class ProductPropertyValueController {
private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
- @ApiOperation("创建规格名称")
+ @ApiOperation("创建属性值")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
return success(productPropertyValueService.createPropertyValue(createReqVO));
}
@PutMapping("/update")
- @ApiOperation("更新规格名称")
+ @ApiOperation("更新属性值")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
productPropertyValueService.updatePropertyValue(updateReqVO);
@@ -45,7 +45,7 @@ public class ProductPropertyValueController {
}
@DeleteMapping("/delete")
- @ApiOperation("删除规格名称")
+ @ApiOperation("删除属性值")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult deleteProperty(@RequestParam("id") Long id) {
@@ -54,17 +54,17 @@ public class ProductPropertyValueController {
}
@GetMapping("/get")
- @ApiOperation("获得规格名称")
+ @ApiOperation("获得属性值")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult getProperty(@RequestParam("id") Long id) {
- return success(productPropertyValueService.getPropertyValue(id));
+ return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id)));
}
@GetMapping("/page")
- @ApiOperation("获得规格名称分页")
+ @ApiOperation("获得属性值分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
- return success(productPropertyValueService.getPropertyValueListPage(pageVO));
+ return success(ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueService.getPropertyValuePage(pageVO)));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
deleted file mode 100644
index 9bdc70bd7..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.ToString;
-
-import java.util.List;
-
-/**
- * @Description: ProductPropertyViewRespVO
- * @Author: franky
- * @CreateDate: 2022/7/5 21:29
- * @Version: 1.0.0
- */
-@ApiModel("管理后台 - 规格名称详情展示 Request VO")
-@Data
-@ToString(callSuper = true)
-public class ProductPropertyViewRespVO {
-
- @ApiModelProperty(value = "规格名称id", example = "1")
- public Long propertyId;
-
- @ApiModelProperty(value = "规格名称", example = "内存")
- public String name;
-
- @ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]")
- public List propertyValues;
-
- @Data
- @ApiModel(value = "规格属性值元组")
- public static class Tuple2 {
- private final long id;
- private final String name;
-
- public Tuple2(Long id, String name) {
- this.id = id;
- this.name = name;
- }
-
- }
-
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
index e7b3c352f..a739bc0f2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
@@ -1,30 +1,36 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import java.time.LocalDateTime;
import java.util.List;
-@ApiModel("管理后台 - 规格 + 规格值 Response VO")
+@ApiModel("管理后台 - 商品属性项 + 属性值 Response VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
+public class ProductPropertyAndValueRespVO {
- @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
+ @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
private Long id;
- @ApiModelProperty(value = "创建时间", required = true)
- private LocalDateTime createTime;
+ @ApiModelProperty(value = "属性项的名称", required = true, example = "颜色")
+ private String name;
/**
- * 规格值的集合
+ * 属性值的集合
*/
- private List values;
+ private List values;
+
+ @ApiModel("管理后台 - 属性值的简单 Response VO")
+ @Data
+ public static class Value {
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "2048")
+ private Long id;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String name;
+
+ }
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
index 25fc4c01a..fb089dce1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
@@ -4,24 +4,19 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
/**
- * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductPropertyBaseVO {
- @ApiModelProperty(value = "规格名称", required = true, example = "颜色")
- @NotBlank(message = "规格名称不能为空")
+ @ApiModelProperty(value = "名称", required = true, example = "颜色")
+ @NotBlank(message = "名称不能为空")
private String name;
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- @NotNull(message = "状态不能为空")
- private Integer status;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
index 8dfd58a5d..2e68f21e3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
@@ -5,7 +5,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-@ApiModel("管理后台 - 规格名称创建 Request VO")
+@ApiModel("管理后台 - 属性项创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
index 314288ffb..1233480d1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
@@ -5,15 +5,12 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
-@ApiModel("管理后台 - 规格名称 List Request VO")
+@ApiModel("管理后台 - 属性项 List Request VO")
@Data
@ToString(callSuper = true)
public class ProductPropertyListReqVO {
- @ApiModelProperty(value = "规格名称", example = "颜色")
+ @ApiModelProperty(value = "名称", example = "颜色")
private String name;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- private Integer status;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
index 05a67e874..60bd7db5b 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
@@ -12,13 +12,13 @@ import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-@ApiModel("管理后台 - 规格名称分页 Request VO")
+@ApiModel("管理后台 - 属性项 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyPageReqVO extends PageParam {
- @ApiModelProperty(value = "规格名称", example = "颜色")
+ @ApiModelProperty(value = "名称", example = "颜色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
index 75a9a5eea..299aa56e4 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
@@ -8,13 +8,13 @@ import lombok.ToString;
import java.time.LocalDateTime;
-@ApiModel("管理后台 - 规格 + 规格值 Response VO")
+@ApiModel("管理后台 - 属性项 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
- @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
+ @ApiModelProperty(value = "编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
index f4630d874..4dfa48366 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
@@ -1,12 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
-import lombok.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-import java.util.List;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
-@ApiModel("管理后台 - 规格名称更新 Request VO")
+import javax.validation.constraints.NotNull;
+
+@ApiModel("管理后台 - 属性项更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
index 142a8e6e2..76b2f1a8b 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
@@ -7,24 +7,20 @@ import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
-* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
+* 属性值 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "规格编号", required = true, example = "1024")
- @NotNull(message = "规格编号不能为空")
+ @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
+ @NotNull(message = "属性项的编号不能为空")
private Long propertyId;
- @ApiModelProperty(value = "规格值名字", required = true, example = "红色")
- @NotEmpty(message = "规格值名字不能为空")
+ @ApiModelProperty(value = "名称", required = true, example = "红色")
+ @NotEmpty(message = "名称名字不能为空")
private String name;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- @NotNull(message = "状态不能为空")
- private Integer status;
-
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
index f7237f9cd..8930f6ba3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import lombok.*;
import io.swagger.annotations.*;
-@ApiModel("管理后台 - 规格值创建 Request VO")
+@ApiModel("管理后台 - 商品属性值创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java
new file mode 100644
index 000000000..55bae16df
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("管理后台 - 商品属性值的明细 Response VO")
+@Data
+public class ProductPropertyValueDetailRespVO {
+
+ @ApiModelProperty(value = "属性的编号", required = true, example = "1")
+ private Long propertyId;
+
+ @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
+ private String propertyName;
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
+ private Long valueId;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
index ae77d822b..3f5ffee3d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
@@ -6,23 +6,17 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-import javax.validation.constraints.NotEmpty;
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel("管理后台 - 规格名称值分页 Request VO")
+@ApiModel("管理后台 - 商品属性值分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValuePageReqVO extends PageParam {
- @ApiModelProperty(value = "规格id", example = "1024")
+ @ApiModelProperty(value = "属性项的编号", example = "1024")
private String propertyId;
- @ApiModelProperty(value = "规格值", example = "红色")
+ @ApiModelProperty(value = "名称", example = "红色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
index 501afd752..fb5ecead9 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
@@ -8,13 +8,13 @@ import lombok.ToString;
import java.time.LocalDateTime;
-@ApiModel("管理后台 - 规格值 Response VO")
+@ApiModel("管理后台 - 商品属性值 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "主键", required = true, example = "10")
+ @ApiModelProperty(value = "编号", required = true, example = "10")
private Long id;
@ApiModelProperty(value = "创建时间")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
index 2437600a8..f13d434b3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
@@ -4,7 +4,7 @@ import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
-@ApiModel("管理后台 - 规格值更新 Request VO")
+@ApiModel("管理后台 - 商品属性值更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
index 45cb447b8..1bb08ff32 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
@@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@@ -55,8 +57,10 @@ public class ProductSkuBaseVO {
@ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
private Double volume;
- @ApiModel("规格值")
+ @ApiModel("商品属性")
@Data
+ @AllArgsConstructor
+ @NoArgsConstructor
public static class Property {
@ApiModelProperty(value = "属性编号", required = true, example = "1")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
index 6d5ce024d..ab83eeeac 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -14,11 +13,8 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
- @ApiModelProperty(value = "商品 SKU 编号", example = "1")
- private Long id;
-
/**
- * 规格值数组
+ * 属性数组
*/
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
index 1ac29724b..85f5903cc 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
@@ -22,7 +22,7 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
private LocalDateTime createTime;
/**
- * 规格值数组
+ * 属性数组
*/
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http
new file mode 100644
index 000000000..4ab7b4f71
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http
@@ -0,0 +1,4 @@
+### 获得商品 SPU 明细
+GET {{baseUrl}}/product/spu/get-detail?id=4
+Authorization: Bearer {{token}}
+tenant-id: {{adminTenentId}}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
index 155fd0265..f19fde594 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
+import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
-import java.util.Collection;
import java.util.List;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@Api(tags = "管理后台 - 商品 SPU")
@RestController
@@ -27,20 +33,24 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
public class ProductSpuController {
@Resource
- private ProductSpuService spuService;
+ private ProductSpuService productSpuService;
+ @Resource
+ private ProductSkuService productSkuService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
@ApiOperation("创建商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:create')")
public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
- return success(spuService.createSpu(createReqVO));
+ return success(productSpuService.createSpu(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
- spuService.updateSpu(updateReqVO);
+ productSpuService.updateSpu(updateReqVO);
return success(true);
}
@@ -49,42 +59,35 @@ public class ProductSpuController {
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
public CommonResult deleteSpu(@RequestParam("id") Long id) {
- spuService.deleteSpu(id);
+ productSpuService.deleteSpu(id);
return success(true);
}
- // TODO 芋艿:修改接口
- @GetMapping("/get/detail")
- @ApiOperation("获得商品 SPU")
+ @GetMapping("/get-detail")
+ @ApiOperation("获得商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult getSpuDetail(@RequestParam("id") Long id) {
- return success(spuService.getSpuDetail(id));
- }
+ // 获得商品 SPU
+ ProductSpuDO spu = productSpuService.getSpu(id);
+ if (spu == null) {
+ throw exception(SPU_NOT_EXISTS);
+ }
- @GetMapping("/get")
- @ApiOperation("获得商品 SPU")
- @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult getSpu(@RequestParam("id") Long id) {
- return success(spuService.getSpu(id));
- }
-
-
- @GetMapping("/list")
- @ApiOperation("获得商品 SPU 列表")
- @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
- @PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult> getSpuList(@RequestParam("ids") Collection ids) {
- List list = spuService.getSpuList(ids);
- return success(ProductSpuConvert.INSTANCE.convertList(list));
+ // 查询商品 SKU
+ List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
+ // 查询商品属性
+ List propertyValues = productPropertyValueService
+ .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
+ // 拼接
+ return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
}
@GetMapping("/get-simple-list")
@ApiOperation("获得商品 SPU 精简列表")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult> getSpuSimpleList() {
- List list = spuService.getSpuList();
+ List list = productSpuService.getSpuList();
return success(ProductSpuConvert.INSTANCE.convertList02(list));
}
@@ -92,7 +95,7 @@ public class ProductSpuController {
@ApiOperation("获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
- return success(spuService.getSpuPage(pageVO));
+ return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
index 54f0986dd..5f9f8a24c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
@@ -64,28 +64,13 @@ public class ProductSpuBaseVO {
@NotNull(message = "是否展示库存不能为空")
private Boolean showStock;
- @ApiModelProperty(value = "库存", required = true, example = "true")
- private Integer totalStock;
-
@ApiModelProperty(value = "市场价", example = "1024")
private Integer marketPrice;
- @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
- private Integer minPrice;
-
- @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
- private Integer maxPrice;
-
// ========== 统计相关字段 =========
- @ApiModelProperty(value = "商品销量", example = "1024")
- private Integer salesCount;
-
@ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
@NotNull(message = "虚拟销量不能为空")
private Integer virtualSalesCount;
- @ApiModelProperty(value = "点击量", example = "1024")
- private Integer clickCount;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
index de41d1416..65cdd22a2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -1,27 +1,21 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-import java.time.LocalDateTime;
import java.util.List;
@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
+public class ProductSpuDetailRespVO extends ProductSpuRespVO {
- @ApiModelProperty(value = "主键", required = true, example = "1")
- private Long id;
-
- @ApiModelProperty(value = "创建时间")
- private LocalDateTime createTime;
+ // ========== SKU 相关字段 =========
/**
* SKU 数组
@@ -35,31 +29,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
public static class Sku extends ProductSkuBaseVO {
/**
- * 规格的数组
+ * 属性数组
*/
- private List properties;
+ private List properties;
}
- @ApiModel(value = "管理后台 - 商品规格的详细 Response VO")
- @Data
- @EqualsAndHashCode(callSuper = true)
- @ToString(callSuper = true)
- public static class Property extends ProductSkuBaseVO.Property {
-
- @ApiModelProperty(value = "规格的名字", required = true, example = "颜色")
- private String propertyName;
-
- @ApiModelProperty(value = "规格值的名字", required = true, example = "蓝色")
- private String valueName;
-
- }
-
- @ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4")
- private Long categoryId;
-
- // TODO @芋艿:在瞅瞅~
- @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
- private List productPropertyViews;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
index 8d1bbee5f..3d74dc80c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -19,7 +19,7 @@ public class ProductSpuPageReqVO extends PageParam {
@ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
private String code;
- @ApiModelProperty(value = "分类id", example = "1")
+ @ApiModelProperty(value = "分类编号", example = "1")
private Long categoryId;
@ApiModelProperty(value = "商品品牌编号", example = "1")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
index a8dca328b..66b86e0a5 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,7 +7,6 @@ import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
-import java.util.List;
@ApiModel("管理后台 - 商品 SPU Response VO")
@Data
@@ -21,4 +20,22 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
+ // ========== SKU 相关字段 =========
+
+ @ApiModelProperty(value = "库存", required = true, example = "true")
+ private Integer totalStock;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ @ApiModelProperty(value = "商品销量", example = "1024")
+ private Integer salesCount;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "点击量", example = "1024")
+ private Integer clickCount;
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java
new file mode 100644
index 000000000..379e85180
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位符,无时间作用,避免 package 缩进
+ */
+package cn.iocoder.yudao.module.product.controller.app.property;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java
new file mode 100644
index 000000000..6538bea3c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位符,无时间作用,避免 package 缩进
+ */
+package cn.iocoder.yudao.module.product.controller.app.property.vo.property;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java
new file mode 100644
index 000000000..516dd077f
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.controller.app.property.vo.value;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("用户 App - 商品属性值的明细 Response VO")
+@Data
+public class AppProductPropertyValueDetailRespVO {
+
+ @ApiModelProperty(value = "属性的编号", required = true, example = "1")
+ private Long propertyId;
+
+ @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
+ private String propertyName;
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
+ private Long valueId;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
new file mode 100644
index 000000000..04df7bfec
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
@@ -0,0 +1,8 @@
+### 获得订单交易的分页 TODO
+GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10
+Authorization: Bearer {{appToken}}
+tenant-id: {{appTenentId}}
+
+### 获得商品 SPU 明细
+GET {{appApi}}/product/spu/get-detail?id=4
+tenant-id: {{appTenentId}}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
index 7e0f912b4..9116f29cf 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
@@ -1,13 +1,22 @@
package cn.iocoder.yudao.module.product.controller.app.spu;
-import cn.hutool.core.bean.BeanUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
+import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
+import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@@ -17,28 +26,54 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
+import java.util.List;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
-@Api(tags = "用户 APP - 商品spu")
+@Api(tags = "用户 APP - 商品 SPU")
@RestController
@RequestMapping("/product/spu")
@Validated
public class AppProductSpuController {
@Resource
- private ProductSpuService spuService;
+ private ProductSpuService productSpuService;
+ @Resource
+ private ProductSkuService productSkuService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@GetMapping("/page")
- @ApiOperation("获得商品spu分页")
- public CommonResult> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
- return success(spuService.getSpuPage(pageVO));
+ @ApiOperation("获得商品 SPU 分页")
+ public CommonResult> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
+ PageResult pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus());
+ return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult));
}
- @GetMapping("/")
- @ApiOperation("获取商品 - 通过商品id")
- public CommonResult getSpu(@RequestParam("spuId") Long spuId) {
- AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);
- return success(appSpuRespVO);
+ @GetMapping("/get-detail")
+ @ApiOperation("获得商品 SPU 明细")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+ public CommonResult getSpuDetail(@RequestParam("id") Long id) {
+ // 获得商品 SPU
+ ProductSpuDO spu = productSpuService.getSpu(id);
+ if (spu == null) {
+ throw exception(SPU_NOT_EXISTS);
+ }
+ if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
+ throw exception(SPU_NOT_ENABLE);
+ }
+
+ // 查询商品 SKU
+ List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(),
+ CommonStatusEnum.ENABLE.getStatus());
+ // 查询商品属性
+ List propertyValues = productPropertyValueService
+ .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
+ // 拼接
+ return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues));
}
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
new file mode 100644
index 000000000..699ca1caa
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
@@ -0,0 +1,92 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@ApiModel("用户 App - 商品 SPU 明细 Response VO")
+@Data
+public class AppProductSpuDetailRespVO {
+
+ @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
+ private Long id;
+
+ // ========== 基本信息 =========
+
+ @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
+ private String name;
+
+ @ApiModelProperty(value = "促销语", example = "好吃!")
+ private String sellPoint;
+
+ @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
+ private String description;
+
+ @ApiModelProperty(value = "商品分类编号", required = true, example = "1")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "商品图片的数组", required = true)
+ private List picUrls;
+
+ @ApiModelProperty(value = "商品视频", required = true)
+ private String videoUrl;
+
+ // ========== SKU 相关字段 =========
+
+ @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
+ private Integer specType;
+
+ @ApiModelProperty(value = "是否展示库存", required = true, example = "true")
+ private Boolean showStock;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ /**
+ * SKU 数组
+ */
+ private List skus;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "商品销量", required = true, example = "1024")
+ private Integer salesCount;
+
+ @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息")
+ @Data
+ public static class Sku {
+
+ @ApiModelProperty(value = "商品 SKU 编号", example = "1")
+ private Long id;
+
+ /**
+ * 商品属性数组
+ */
+ private List properties;
+
+ @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
+ private Integer price;
+
+ @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
+ private Integer marketPrice;
+
+ @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
+ private String picUrl;
+
+ @ApiModelProperty(value = "库存", required = true, example = "1")
+ private Integer stock;
+
+ @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
+ private Double weight;
+
+ @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
+ private Double volume;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java
new file mode 100644
index 000000000..60fc9235e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("用户 App - 商品 SPU 分页项 Response VO")
+@Data
+public class AppProductSpuPageItemRespVO {
+
+ @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
+ private Long id;
+
+ @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
+ @NotEmpty(message = "商品名称不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "分类编号", required = true)
+ @NotNull(message = "分类编号不能为空")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "商品图片的数组", required = true)
+ private List picUrls;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "商品销量", example = "1024")
+ private Integer salesCount;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java
new file mode 100644
index 000000000..f19a7c21a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.AssertTrue;
+
+@ApiModel("用户 App - 商品 SPU 分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AppProductSpuPageReqVO extends PageParam {
+
+ public static final String SORT_FIELD_PRICE = "price";
+ public static final String SORT_FIELD_SALES_COUNT = "salesCount";
+
+ @ApiModelProperty(value = "分类编号", example = "1")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "关键字", example = "好看")
+ private String keyword;
+
+ @ApiModelProperty(value = "排序字段", example = "price", notes = "参见 AppSpuPageReqVO.SORT_FIELD_XXX 常量")
+ private String sortField;
+
+ @ApiModelProperty(value = "排序方式", example = "true", notes = "true - 升序;false - 降序")
+ private Boolean sortAsc;
+
+ @AssertTrue(message = "排序字段不合法")
+ @JsonIgnore
+ public boolean isSortFieldValid() {
+ if (StrUtil.isEmpty(sortField)) {
+ return true;
+ }
+ return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
deleted file mode 100644
index 38ed4975e..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@ApiModel("App - 商品spu分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class AppSpuPageReqVO extends PageParam {
-
- @ApiModelProperty(value = "分类id")
- private Long categoryId;
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
deleted file mode 100644
index c0a0f0eb8..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import java.util.List;
-
-@ApiModel("App - 商品spu分页 Request VO")
-@Data
-public class AppSpuPageRespVO {
-
- @ApiModelProperty(value = "主键", required = true, example = "1")
- private Long id;
-
- @ApiModelProperty(value = "商品名称")
- private String name;
-
- @ApiModelProperty(value = "卖点", required = true)
- @NotNull(message = "卖点不能为空")
- private String sellPoint;
-
- @ApiModelProperty(value = "描述", required = true)
- @NotNull(message = "描述不能为空")
- private String description;
-
- @ApiModelProperty(value = "分类id", required = true)
- @NotNull(message = "分类id不能为空")
- private Long categoryId;
-
- @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
- @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
- private List picUrls;
-
- @ApiModelProperty(value = "排序字段", required = true)
- @NotNull(message = "排序字段不能为空")
- private Integer sort;
-
- @ApiModelProperty(value = "点赞初始人数")
- private Integer likeCount;
-
- @ApiModelProperty(value = "价格 单位使用:分")
- private Integer price;
-
- @ApiModelProperty(value = "库存数量")
- private Integer quantity;
-
- @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Integer status;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
deleted file mode 100644
index b45987370..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.vo;
-
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
-import io.swagger.annotations.ApiModel;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- *
- *
- *
- *
- * @author LuoWenFeng
- */
-@ApiModel("App - 商品spu Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class AppSpuRespVO extends ProductSpuRespVO {
-
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
index 91f811ad6..211bcc293 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
@@ -1,20 +1,21 @@
package cn.iocoder.yudao.module.product.convert.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
+import java.util.Map;
/**
- * 规格名称 Convert
+ * 属性项 Convert
*
* @author 芋道源码
*/
@@ -27,12 +28,21 @@ public interface ProductPropertyConvert {
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
- ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
-
ProductPropertyRespVO convert(ProductPropertyDO bean);
List convertList(List list);
PageResult convertPage(PageResult page);
+ default List convertList(List keys, List values) {
+ Map> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
+ return CollectionUtils.convertList(keys, key -> {
+ ProductPropertyAndValueRespVO respVO = convert02(key);
+ respVO.setValues(convertList02(valueMap.get(key.getId())));
+ return respVO;
+ });
+ }
+ ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean);
+ List convertList02(List list);
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
index 331ad623f..d6167c174 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
@@ -1,18 +1,25 @@
package cn.iocoder.yudao.module.product.convert.propertyvalue;
-import java.util.*;
-
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
/**
- * 规格值 Convert
+ * 属性值 Convert
*
* @author 芋道源码
*/
@@ -31,6 +38,18 @@ public interface ProductPropertyValueConvert {
PageResult convertPage(PageResult page);
- List convertList03(List list);
+ default List convertList(List values, List keys) {
+ Map keyMap = convertMap(keys, ProductPropertyDO::getId);
+ return CollectionUtils.convertList(values, value -> {
+ ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()
+ .setValueId(value.getId()).setValueName(value.getName());
+ // 设置属性项
+ MapUtils.findAndThen(keyMap, value.getPropertyId(),
+ key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));
+ return valueDetail;
+ });
+ }
+
+ List convertList02(List list);
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
index b29d612be..f397dfc48 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.product.convert.sku;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
@@ -10,9 +12,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@@ -32,12 +33,16 @@ public interface ProductSkuConvert {
List convertList(List list);
- List convertSkuDOList(List list);
+ List convertList06(List list);
+
+ default List convertList06(List list, Long spuId, String spuName) {
+ List result = convertList06(list);
+ result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName));
+ return result;
+ }
ProductSkuRespDTO convert02(ProductSkuDO bean);
- List convertList02(List list);
-
List convertList03(List list);
List convertList04(List list);
@@ -66,4 +71,23 @@ public interface ProductSkuConvert {
return spuIdAndStockMap;
}
+ default Collection convertPropertyValueIds(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return new HashSet<>();
+ }
+ return list.stream().filter(item -> item.getProperties() != null)
+ .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
+ .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
+ .collect(Collectors.toSet());
+ }
+
+ default String buildPropertyKey(ProductSkuDO bean) {
+ if (CollUtil.isEmpty(bean.getProperties())) {
+ return StrUtil.EMPTY;
+ }
+ List properties = new ArrayList<>(bean.getProperties());
+ properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId));
+ return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
index 98b7d8837..fcf6d6436 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -1,18 +1,29 @@
package cn.iocoder.yudao.module.product.convert.spu;
+import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
+import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+
+import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
- * 商品spu Convert
+ * 商品 SPU Convert
*
* @author 芋道源码
*/
@@ -25,18 +36,73 @@ public interface ProductSpuConvert {
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
- ProductSpuRespVO convert(ProductSpuDO bean);
-
- List convertList(List list);
+ List convertList(List list);
PageResult convertPage(PageResult page);
- ProductSpuPageReqVO convert(AppSpuPageReqVO bean);
-
- AppSpuPageRespVO convertAppResp(ProductSpuDO list);
+ ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
List convertList2(List list);
List convertList02(List list);
+ default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List skus,
+ List propertyValues) {
+ AppProductSpuDetailRespVO spuVO = convert02(spu)
+ .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
+ spuVO.setSkus(convertList03(skus));
+ // 处理商品属性
+ Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
+ for (int i = 0; i < skus.size(); i++) {
+ List properties = skus.get(i).getProperties();
+ if (CollUtil.isEmpty(properties)) {
+ continue;
+ }
+ AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
+ sku.setProperties(new ArrayList<>(properties.size()));
+ // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
+ properties.forEach(property -> {
+ ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
+ if (propertyValue == null) {
+ return;
+ }
+ sku.getProperties().add(convert03(propertyValue));
+ });
+ }
+ return spuVO;
+ }
+ AppProductSpuDetailRespVO convert02(ProductSpuDO spu);
+ List convertList03(List skus);
+ AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
+
+ PageResult convertPage02(PageResult page);
+
+ default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List skus,
+ List propertyValues) {
+ ProductSpuDetailRespVO spuVO = convert03(spu);
+ spuVO.setSkus(convertList04(skus));
+ // 处理商品属性
+ Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
+ for (int i = 0; i < skus.size(); i++) {
+ List properties = skus.get(i).getProperties();
+ if (CollUtil.isEmpty(properties)) {
+ continue;
+ }
+ ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
+ sku.setProperties(new ArrayList<>(properties.size()));
+ // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
+ properties.forEach(property -> {
+ ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
+ if (propertyValue == null) {
+ return;
+ }
+ sku.getProperties().add(convert04(propertyValue));
+ });
+ }
+ return spuVO;
+ }
+ ProductSpuDetailRespVO convert03(ProductSpuDO spu);
+ List convertList04(List skus);
+ ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
index b3831491e..2976674c1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -8,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
- * 规格名称 DO
+ * 商品属性项 DO
*
* @author 芋道源码
*/
@@ -28,20 +27,12 @@ public class ProductPropertyDO extends BaseDO {
@TableId
private Long id;
/**
- * 规格名称
+ * 名称
*/
private String name;
- /**
- * 状态
- *
- * 枚举 {@link CommonStatusEnum}
- */
- private Integer status;
/**
* 备注
*/
private String remark;
- // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索)
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
index b75f0d592..d73fe06b2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -9,7 +8,7 @@ import lombok.*;
/**
- * 规格值 DO
+ * 商品属性值 DO
*
* @author 芋道源码
*/
@@ -29,21 +28,15 @@ public class ProductPropertyValueDO extends BaseDO {
@TableId
private Long id;
/**
- * 规格键编号
+ * 属性项的编号
*
* 关联 {@link ProductPropertyDO#getId()}
*/
private Long propertyId;
/**
- * 规格值名字
+ * 名称
*/
private String name;
- /**
- * 状态
- *
- * 枚举 {@link CommonStatusEnum}
- */
- private Integer status;
/**
* 备注
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
index f953534ed..3836f20e5 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
@@ -35,10 +35,6 @@ public class ProductSkuDO extends BaseDO {
*/
@TableId
private Long id;
- /**
- * 商品 SKU 名字
- */
- private String name;
/**
* SPU 编号
*
@@ -46,7 +42,13 @@ public class ProductSkuDO extends BaseDO {
*/
private Long spuId;
/**
- * 规格值数组,JSON 格式
+ * SPU 名字
+ *
+ * 冗余 {@link ProductSkuDO#getSpuName()}
+ */
+ private String spuName;
+ /**
+ * 属性数组,JSON 格式
*/
@TableField(typeHandler = PropertyTypeHandler.class)
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
index 890df3477..26f8d5239 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
@@ -3,31 +3,30 @@ package cn.iocoder.yudao.module.product.dal.mysql.property;
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.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
-/**
- * 规格名称 Mapper
- *
- * @author 芋道源码
- */
@Mapper
public interface ProductPropertyMapper extends BaseMapperX {
default PageResult selectPage(ProductPropertyPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX()
.likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
- .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus())
.betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ProductPropertyDO::getId));
}
default ProductPropertyDO selectByName(String name) {
- return selectOne(new LambdaQueryWrapperX()
- .eqIfPresent(ProductPropertyDO::getName, name));
+ return selectOne(ProductPropertyDO::getName, name);
+ }
+
+ default List selectList(ProductPropertyListReqVO listReqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .eqIfPresent(ProductPropertyDO::getName, listReqVO.getName()));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
index ca9bafab2..402df51e7 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
@@ -7,17 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Collection;
import java.util.List;
-/**
- * 规格值 Mapper
- *
- * @author 芋道源码
- */
@Mapper
public interface ProductPropertyValueMapper extends BaseMapperX {
- default List selectListByPropertyId(List propertyIds) {
+ default List selectListByPropertyId(Collection propertyIds) {
return selectList(new LambdaQueryWrapperX()
.inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
}
@@ -28,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX().eq(ProductPropertyValueDO::getPropertyId, propertyId)
- .eq(ProductPropertyValueDO::getDeleted, false));
+ default void deleteByPropertyId(Long propertyId) {
+ delete(new LambdaQueryWrapperX()
+ .eq(ProductPropertyValueDO::getPropertyId, propertyId));
}
default PageResult selectPage(ProductPropertyValuePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX()
.eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId())
.likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName())
- .eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus())
.orderByDesc(ProductPropertyValueDO::getId));
}
+ default Integer selectCountByPropertyId(Long propertyId) {
+ return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue();
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
index 3e5a9ce8f..56bc54499 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Collection;
import java.util.List;
/**
@@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX {
return selectList(ProductSkuDO::getSpuId, spuId);
}
+ default List selectListBySpuIdAndStatus(Long spuId,
+ Integer status) {
+ return selectList(new LambdaQueryWrapperX()
+ .eq(ProductSkuDO::getSpuId, spuId)
+ .eqIfPresent(ProductSkuDO::getStatus, status));
+ }
+
+ default List selectListBySpuId(Collection spuIds) {
+ return selectList(ProductSkuDO::getSpuId, spuIds);
+ }
+
default void deleteBySpuId(Long spuId) {
delete(new LambdaQueryWrapperX().eq(ProductSkuDO::getSpuId, spuId));
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
index a271b5051..57a3125d8 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
@@ -4,10 +4,12 @@ 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.product.controller.admin.spu.vo.ProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Objects;
import java.util.Set;
/**
@@ -44,6 +46,19 @@ public interface ProductSpuMapper extends BaseMapperX {
.orderByDesc(ProductSpuDO::getSort));
}
+ default PageResult selectPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
+ LambdaQueryWrapperX query = new LambdaQueryWrapperX()
+ .eqIfPresent(ProductSpuDO::getCategoryId, pageReqVO.getCategoryId())
+ .eqIfPresent(ProductSpuDO::getStatus, status);
+ // 排序逻辑
+ if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
+ query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getMaxPrice);
+ } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
+ query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount);
+ }
+ return selectPage(pageReqVO, query);
+ }
+
/**
* 更新商品 SPU 库存
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
index 117f35931..01967857e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
@@ -2,7 +2,7 @@
* trade 模块,主要实现交易相关功能
* 例如:订单、退款、购物车等功能。
*
- * 1. Controller URL:以 /trade/ 开头,避免和其它 Module 冲突
- * 2. DataObject 表名:以 trade_ 开头,方便在数据库中区分
+ * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突
+ * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分
*/
package cn.iocoder.yudao.module.product;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
index 118e8118b..32a4c030d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
import javax.validation.Valid;
-import java.util.Collection;
import java.util.List;
/**
@@ -47,12 +46,19 @@ public interface ProductCategoryService {
ProductCategoryDO getCategory(Long id);
/**
- * 获得商品分类列表
+ * 校验商品分类
*
- * @param ids 编号
- * @return 商品分类列表
+ * @param id 分类编号
*/
- List getEnableCategoryList(Collection ids);
+ void validateCategory(Long id);
+
+ /**
+ * 获得商品分类的层级
+ *
+ * @param id 编号
+ * @return 商品分类的层级
+ */
+ Integer getCategoryLevel(Long id);
/**
* 获得商品分类列表
@@ -62,14 +68,6 @@ public interface ProductCategoryService {
*/
List getEnableCategoryList(ProductCategoryListReqVO listReqVO);
- /**
- * 验证选择的商品分类的级别是否合法
- * 例如说,商品发布的时候,必须在第 3 级别
- *
- * @param id 分类编号
- */
- void validateCategoryLevel(Long id);
-
/**
* 获得开启状态的商品分类列表
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
index ffe55e9bf..f0d10b8b8 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
@@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
-import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -90,31 +89,40 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
}
}
- @Override
- public void validateCategoryLevel(Long id) {
- // TODO @芋艿:在看看,杂能优化下
- Long parentId = id;
- int i = 2;
- for (; i >= 0; --i) {
- ProductCategoryDO category = productCategoryMapper.selectById(parentId);
- parentId = category.getParentId();
- if(Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL)){
- break;
- }
- }
- if (!Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL) || i != 0) {
- throw exception(CATEGORY_LEVEL_ERROR);
- }
- }
-
@Override
public ProductCategoryDO getCategory(Long id) {
return productCategoryMapper.selectById(id);
}
@Override
- public List getEnableCategoryList(Collection ids) {
- return productCategoryMapper.selectBatchIds(ids);
+ public void validateCategory(Long id) {
+ ProductCategoryDO category = productCategoryMapper.selectById(id);
+ if (category == null) {
+ throw exception(CATEGORY_NOT_EXISTS);
+ }
+ if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+ throw exception(CATEGORY_DISABLED, category.getName());
+ }
+ }
+
+ @Override
+ public Integer getCategoryLevel(Long id) {
+ if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
+ return 0;
+ }
+ int level = 1;
+ for (int i = 0; i < 100; i++) {
+ ProductCategoryDO category = productCategoryMapper.selectById(id);
+ // 如果没有父节点,break 结束
+ if (category == null
+ || Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
+ break;
+ }
+ // 继续递归父节点
+ level++;
+ id = category.getParentId();
+ }
+ return level;
}
@Override
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
index 8780c7865..564bc82a9 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.service.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
@@ -10,14 +9,15 @@ import java.util.Collection;
import java.util.List;
/**
- * 规格名称 Service 接口
+ * 商品属性项 Service 接口
*
* @author 芋道源码
*/
public interface ProductPropertyService {
/**
- * 创建规格名称
+ * 创建属性项
+ * 注意,如果已经存在该属性项,直接返回它的编号即可
*
* @param createReqVO 创建信息
* @return 编号
@@ -25,56 +25,48 @@ public interface ProductPropertyService {
Long createProperty(@Valid ProductPropertyCreateReqVO createReqVO);
/**
- * 更新规格名称
+ * 更新属性项
*
* @param updateReqVO 更新信息
*/
void updateProperty(@Valid ProductPropertyUpdateReqVO updateReqVO);
/**
- * 删除规格名称
+ * 删除属性项
*
* @param id 编号
*/
void deleteProperty(Long id);
/**
- * 获得规格名称列表
+ * 获得属性项列表
* @param listReqVO 集合查询
- * @return 规格名称集合
+ * @return 属性项集合
*/
- List getPropertyList(ProductPropertyListReqVO listReqVO);
+ List getPropertyList(ProductPropertyListReqVO listReqVO);
/**
* 获取属性名称分页
*
* @param pageReqVO 分页条件
- * @return 规格名称分页
+ * @return 属性项分页
*/
- PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO);
+ PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO);
/**
- * 获得指定编号的规格名称
+ * 获得指定编号的属性项
*
* @param id 编号
- * @return 规格名称
+ * @return 属性项
*/
- ProductPropertyRespVO getProperty(Long id);
+ ProductPropertyDO getProperty(Long id);
/**
- * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合
+ * 根据属性项的编号的集合,获得对应的属性项数组
*
- * @param ids 规格编号的集合
- * @return 对应的规格
+ * @param ids 属性项的编号的集合
+ * @return 属性项数组
*/
- List getPropertyList(Collection ids);
-
- /**
- * 获得规格名称 + 值的列表
- *
- * @param listReqVO 列表查询
- * @return 规格名称 + 值的列表
- */
- List