From 4068548c452021595a69ea5347b885366da0a964 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Wed, 26 Apr 2023 17:38:42 +0800
Subject: [PATCH 01/10] =?UTF-8?q?=E7=A7=BB=E9=99=A4ProductSpuSpecTypeEnum?=
 =?UTF-8?q?=E5=8F=8A=E7=9B=B8=E5=85=B3=E5=BC=95=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../api/spu/dto/ProductSpuRespDTO.java        |  3 --
 .../enums/spu/ProductSpuSpecTypeEnum.java     | 38 -------------------
 .../admin/spu/vo/ProductSpuBaseVO.java        |  1 -
 .../dal/dataobject/spu/ProductSpuDO.java      |  1 -
 .../service/sku/ProductSkuServiceImpl.java    |  3 +-
 .../spu/ProductSpuServiceImplTest.java        | 13 +++----
 6 files changed, 7 insertions(+), 52 deletions(-)
 delete mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java

diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
index 5c4ee9bb7..b1c0b802f 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.product.api.spu.dto;
 
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
-import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import lombok.Data;
 
@@ -76,8 +75,6 @@ public class ProductSpuRespDTO {
 
     /**
      * 规格类型
-     * <p>
-     * 枚举 {@link ProductSpuSpecTypeEnum}
      */
     private Boolean specType;
     /**
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
deleted file mode 100644
index 24488df62..000000000
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cn.iocoder.yudao.module.product.enums.spu;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 商品 SPU 规格类型
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-@Deprecated
-public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
-
-    RECYCLE(false, "统一规格"),
-    DISABLE(true, "多规格");
-
-    //public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();// TODO 暂时先这样跑起来
-    public static final int[] ARRAYS = {};
-    /**
-     * 规格类型
-     */
-    private final Boolean type;
-    /**
-     * 规格名称
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-}
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 f69006364..5725617d4 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
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
index df935d74d..d09a3bb7e 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.delivery.DeliveryTemplateDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
-import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableField;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index 058699aeb..04430764b 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyVa
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
 import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
-import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
 import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
@@ -81,7 +80,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
     @Override
     public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Boolean specType) {
         // 非多规格,不需要校验
-        if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
+        if (ObjectUtil.notEqual(specType, true)) {
             return;
         }
 
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
index 17027fc55..8048e9344 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -18,7 +18,6 @@ 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.dal.mysql.spu.ProductSpuMapper;
-import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl;
 import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl;
@@ -83,7 +82,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
     public void testCreateSpu_success() {
         // 准备参数
         ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class, o -> {
-            o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
+            o.setSpecType(true);
             o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
         });
 
@@ -111,7 +110,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         // 准备参数
         ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
             o.setId(createReqVO.getId()); // 设置更新的 ID
-            o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
+            o.setSpecType(true);
             o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
         });
         // 调用
@@ -132,7 +131,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testValidateSpuExists_exception() {
         ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
-            o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
+            o.setSpecType(true);
             o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
         });
         // 调用
@@ -199,7 +198,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
             //o.setMinPrice(1);  // TODO ProductSpuDO中已没有相关属性
             //o.setMaxPrice(50);
             o.setMarketPrice(25);
-            o.setSpecType(ProductSpuSpecTypeEnum.RECYCLE.getType());
+            o.setSpecType(false);
             o.setBrandId(brandId);
             o.setCategoryId(categoryId);
             //o.setClickCount(100);
@@ -247,7 +246,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
             //o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性
             //o.setMaxPrice(1);
             o.setMarketPrice(1);
-            o.setSpecType(ProductSpuSpecTypeEnum.RECYCLE.getType());
+            o.setSpecType(false);
             o.setBrandId(brandId);
             o.setCategoryId(categoryId);
             //o.setClickCount(1); // TODO ProductSpuDO中已没有相关属性
@@ -266,7 +265,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus())));
         productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setStatus(ProductSpuStatusEnum.RECYCLE.getStatus())));
         // 测试 SpecType 不匹配
-        productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType())));
+        productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setSpecType(true)));
         // 测试 BrandId 不匹配
         productSpuMapper.insert(cloneIgnoreId(createReqVO, o -> o.setBrandId(generateId())));
         // 测试 CategoryId 不匹配

From 668d493b7f17b72826c95ab90866538c9ef102f4 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Sat, 29 Apr 2023 21:22:52 +0800
Subject: [PATCH 02/10] =?UTF-8?q?Product=E7=9B=B8=E5=85=B3Do=E6=B7=BB?=
 =?UTF-8?q?=E5=8A=A0TenantBaseDO?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../product/dal/dataobject/property/ProductPropertyDO.java | 7 ++++++-
 .../dal/dataobject/property/ProductPropertyValueDO.java    | 3 ++-
 .../module/product/dal/dataobject/sku/ProductSkuDO.java    | 3 ++-
 .../module/product/dal/dataobject/spu/ProductSpuDO.java    | 3 ++-
 4 files changed, 12 insertions(+), 4 deletions(-)

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 2976674c1..bf631c420 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,7 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.property;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -19,7 +20,7 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ProductPropertyDO extends BaseDO {
+public class ProductPropertyDO extends TenantBaseDO {
 
     /**
      * 主键
@@ -30,6 +31,10 @@ public class ProductPropertyDO extends BaseDO {
      * 名称
      */
     private String name;
+    /**
+     * 状态
+     */
+    private Integer status;
     /**
      * 备注
      */
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 d73fe06b2..4043afc61 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,7 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.property;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -20,7 +21,7 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ProductPropertyValueDO extends BaseDO {
+public class ProductPropertyValueDO extends TenantBaseDO {
 
     /**
      * 主键
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 a9488563a..6b37d68fa 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
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.dal.dataobject.sku;
 
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 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.dal.dataobject.spu.ProductSpuDO;
@@ -27,7 +28,7 @@ import java.util.List;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ProductSkuDO extends BaseDO {
+public class ProductSkuDO extends TenantBaseDO {
 
     /**
      * 商品 SKU 编号,自增
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
index d09a3bb7e..1260c7170 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.spu;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.delivery.DeliveryTemplateDO;
@@ -28,7 +29,7 @@ import java.util.List;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ProductSpuDO extends BaseDO {
+public class ProductSpuDO extends TenantBaseDO {
 
     /**
      * 商品 SPU 编号,自增

From f56d3948305aaf92b27f8f4b3dfe4f1d9b29a71b Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Sat, 29 Apr 2023 21:28:09 +0800
Subject: [PATCH 03/10] =?UTF-8?q?=E4=BF=AE=E6=94=B9ProductSpuBaseVO?=
 =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../admin/spu/vo/ProductSpuBaseVO.java        | 125 ++++++++++++++----
 1 file changed, 102 insertions(+), 23 deletions(-)

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 5725617d4..e7a30484d 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
@@ -1,7 +1,13 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.delivery.DeliveryTemplateDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -20,55 +26,128 @@ public class ProductSpuBaseVO {
     @NotEmpty(message = "商品名称不能为空")
     private String name;
 
-    @Schema(description = "商品编码", example = "yudaoyuanma")
-    private String code;
+    @Schema(description = "关键字", required = true, example = "芋道")
+    @NotEmpty(message = "商品关键字不能为空")
+    private String keyword;
 
-    @Schema(description = "促销语", example = "好吃!")
-    private String sellPoint;
+    @Schema(description = "商品简介", required = true, example = "芋道")
+    @NotEmpty(message = "商品简介不能为空")
+    private String introduction;
 
-    @Schema(description = "商品详情", required = true, example = "我是商品描述")
-    @NotNull(message = "商品详情不能为空")
+    @Schema(description = "商品详情", required = true, example = "芋道")
+    @NotEmpty(message = "商品详情不能为空")
     private String description;
 
-    @Schema(description = "商品分类编号", required = true, example = "1")
-    @NotNull(message = "商品分类编号不能为空")
+    @Schema(description = "商品条码(一维码)", required = true, example = "芋道")
+    @NotEmpty(message = "商品条码(一维码)不能为空")
+    private String barCode;
+
+    @Schema(description = "商品分类编号", required = true, example = "芋道")
+    @NotEmpty(message = "商品分类编号不能为空")
     private Long categoryId;
 
-    @Schema(description = "商品品牌编号", example = "1")
+    @Schema(description = "商品品牌编号", required = true, example = "芋道")
+    @NotEmpty(message = "商品品牌编号不能为空")
     private Long brandId;
 
-    @Schema(description = "商品图片的数组", required = true)
-    @NotNull(message = "商品图片的数组不能为空")
-    private List<String> picUrls;
+    @Schema(description = "商品封面图", required = true, example = "芋道")
+    @NotEmpty(message = "商品封面图不能为空")
+    private String picUrl;
 
-    @Schema(description = "商品视频", required = true)
+    @Schema(description = "商品轮播图", required = true)
+    @NotEmpty(message = "商品轮播图不能为空")
+    private List<String> sliderPicUrls;
+
+    @Schema(description = "商品视频")
     private String videoUrl;
 
+    @Schema(description = "单位", required = true, example = "1")
+    @NotEmpty(message = "商品单位不能为空")
+    private Integer unit;
+
     @Schema(description = "排序字段", required = true, example = "1")
+    @NotEmpty(message = "商品排序字段不能为空")
     private Integer sort;
 
     @Schema(description = "商品状态", required = true, example = "1")
-    @NotNull(message = "商品状态不能为空")
-    @InEnum(ProductSpuStatusEnum.class)
+    @NotEmpty(message = "商品状态不能为空")
     private Integer status;
 
     // ========== SKU 相关字段 =========
 
-    @Schema(description = "规格类型", required = true, example = "1")
-    @NotNull(message = "规格类型不能为空")
+    @Schema(description = "规格类型", required = true, example = "true")
+    @NotEmpty(message = "商品规格类型不能为空")
     private Boolean specType;
 
-    @Schema(description = "是否展示库存", required = true, example = "true")
-    @NotNull(message = "是否展示库存不能为空")
-    private Boolean showStock;
+    @Schema(description = "商品价格", required = true, example = "1212")
+    @NotEmpty(message = "商品价格不能为空")
+    private Integer price;
 
-    @Schema(description = "市场价", example = "1024")
+    @Schema(description = "市场价", required = true, example = "3")
+    @NotEmpty(message = "商品市场价不能为空")
     private Integer marketPrice;
 
+    @Schema(description = "成本价", required = true, example = "12")
+    @NotEmpty(message = "商品成本价不能为空")
+    private Integer costPrice;
+
+    @Schema(description = "库存", required = true, example = "111")
+    @NotEmpty(message = "商品库存不能为空")
+    private Integer stock;
+
+    // ========== 物流相关字段 =========
+
+    @Schema(description = "物流配置模板编号", required = true, example = "111")
+    @NotEmpty(message = "物流配置模板编号不能为空")
+    private Long deliveryTemplateId;
+
+    // ========== 营销相关字段 =========
+
+    @Schema(description = "是否热卖推荐", required = true, example = "true")
+    @NotEmpty(message = "商品推荐不能为空")
+    private Boolean recommendHot;
+
+    @Schema(description = "是否优惠推荐", required = true, example = "true")
+    @NotEmpty(message = "商品推荐不能为空")
+    private Boolean recommendBenefit;
+
+    @Schema(description = "是否精品推荐", required = true, example = "true")
+    @NotEmpty(message = "商品推荐不能为空")
+    private Boolean recommendBest;
+
+    @Schema(description = "是否新品推荐", required = true, example = "true")
+    @NotEmpty(message = "商品推荐不能为空")
+    private Boolean recommendNew;
+
+    @Schema(description = "是否优品推荐", required = true, example = "true")
+    @NotEmpty(message = "商品推荐不能为空")
+    private Boolean recommendGood;
+
+    @Schema(description = "赠送积分", required = true, example = "111")
+    @NotEmpty(message = "商品赠送积分不能为空")
+    private Integer giveIntegral;
+
+    @Schema(description = "赠送的优惠劵编号的数组")
+    private List<Long> giveCouponTemplateIds;
+
+    @Schema(description = "分销类型")
+    private Boolean subCommissionType;
+
+    @Schema(description = "活动展示顺序")
+    private List<Integer> activityOrders;
+
     // ========== 统计相关字段 =========
 
-    @Schema(description = "虚拟销量", required = true, example = "1024")
-    @NotNull(message = "虚拟销量不能为空")
+    @Schema(description = "商品销量", required = true, example = "芋道")
+    @NotEmpty(message = "商品销量不能为空")
+    private Integer salesCount;
+
+    @Schema(description = "虚拟销量", required = true, example = "芋道")
+    @NotEmpty(message = "商品虚拟销量不能为空")
     private Integer virtualSalesCount;
 
+    @Schema(description = "浏览量", required = true, example = "芋道")
+    @NotEmpty(message = "商品浏览量不能为空")
+    private Integer browseCount;
+
 }

From 24a56bb45f9bd11145042aa3781aa7d51b877e3d Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Sun, 30 Apr 2023 17:34:56 +0800
Subject: [PATCH 04/10] =?UTF-8?q?=E7=A7=BB=E9=99=A4ProductSku=E7=9B=B8?=
 =?UTF-8?q?=E5=85=B3=E7=9A=84status=E5=B1=9E=E6=80=A7=EF=BC=8C=E4=BF=AE?=
 =?UTF-8?q?=E6=94=B9Property?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ProductPropertyValueController.java       | 13 ++++++----
 .../admin/sku/vo/ProductSkuBaseVO.java        | 22 -----------------
 .../sku/vo/ProductSkuCreateOrUpdateReqVO.java | 20 +++++++++++++---
 .../admin/sku/vo/ProductSkuRespVO.java        | 24 +++++++++++++++----
 .../service/sku/ProductSkuServiceImpl.java    |  4 ++--
 .../service/sku/ProductSkuServiceTest.java    |  2 --
 6 files changed, 48 insertions(+), 37 deletions(-)

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 92ce6bee0..fbac32712 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
@@ -1,5 +1,7 @@
 package cn.iocoder.yudao.module.product.controller.admin.property;
 
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.crypto.symmetric.AES;
 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.value.ProductPropertyValueCreateReqVO;
@@ -18,6 +20,9 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 
+import java.util.Arrays;
+import java.util.List;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 商品属性值")
@@ -32,14 +37,14 @@ public class ProductPropertyValueController {
     @PostMapping("/create")
     @Operation(summary = "创建属性值")
     @PreAuthorize("@ss.hasPermission('product:property:create')")
-    public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
+    public CommonResult<Long> createPropertyValue(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
         return success(productPropertyValueService.createPropertyValue(createReqVO));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新属性值")
     @PreAuthorize("@ss.hasPermission('product:property:update')")
-    public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
+    public CommonResult<Boolean> updatePropertyValue(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
         productPropertyValueService.updatePropertyValue(updateReqVO);
         return success(true);
     }
@@ -48,7 +53,7 @@ public class ProductPropertyValueController {
     @Operation(summary = "删除属性值")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('product:property:delete')")
-    public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
+    public CommonResult<Boolean> deletePropertyValue(@RequestParam("id") Long id) {
         productPropertyValueService.deletePropertyValue(id);
         return success(true);
     }
@@ -57,7 +62,7 @@ public class ProductPropertyValueController {
     @Operation(summary = "获得属性值")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('product:property:query')")
-    public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) {
+    public CommonResult<ProductPropertyValueRespVO> getPropertyValue(@RequestParam("id") Long id) {
         return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id)));
     }
 
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 f28220046..e9c9bb48c 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
@@ -38,11 +38,6 @@ public class ProductSkuBaseVO {
     @NotNull(message = "图片地址不能为空")
     private String picUrl;
 
-    @Schema(description = "SKU 状态", required = true, example = "1")
-    @NotNull(message = "SKU 状态不能为空")
-    @InEnum(CommonStatusEnum.class)
-    private Integer status;
-
     @Schema(description = "库存", required = true, example = "1")
     @NotNull(message = "库存不能为空")
     private Integer stock;
@@ -55,21 +50,4 @@ public class ProductSkuBaseVO {
 
     @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米
     private Double volume;
-
-    @Schema(description = "商品属性")
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class Property {
-
-        @Schema(description = "属性编号", required = true, example = "1")
-        @NotNull(message = "属性编号不能为空")
-        private Long propertyId;
-
-        @Schema(description = "属性值编号", required = true, example = "1024")
-        @NotNull(message = "属性值编号不能为空")
-        private Long valueId;
-
-    }
-
 }
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 496475f99..54de91cf1 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,10 +1,9 @@
 package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
+import lombok.*;
 
+import javax.validation.constraints.NotNull;
 import java.util.List;
 
 @Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO")
@@ -12,6 +11,21 @@ import java.util.List;
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
+    @Schema(description = "商品属性")
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Property {
+
+        @Schema(description = "属性编号", required = true, example = "1")
+        @NotNull(message = "属性编号不能为空")
+        private Long propertyId;
+
+        @Schema(description = "属性值编号", required = true, example = "1024")
+        @NotNull(message = "属性值编号不能为空")
+        private Long valueId;
+
+    }
 
     /**
      * 属性数组
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 95e394ada..a229fa826 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
@@ -1,10 +1,9 @@
 package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
+import lombok.*;
 
+import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -20,9 +19,26 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
 
+    @Schema(description = "商品属性")
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Property {
+
+        @Schema(description = "属性编号", required = true, example = "1")
+        @NotNull(message = "属性编号不能为空")
+        private Long propertyId;
+
+        @Schema(description = "属性值编号", required = true, example = "1024")
+        @NotNull(message = "属性值编号不能为空")
+        private Long valueId;
+
+        @Schema(description = "属性值", example = "1024")
+        private String value;
+    }
     /**
      * 属性数组
      */
-    private List<Property> properties;
+    private List<ProductSkuCreateOrUpdateReqVO.Property> properties;
 
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index 04430764b..a314318fc 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -87,7 +87,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
         // 1、校验属性项存在
         Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null)
                 .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
-                .map(ProductSkuBaseVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
+                .map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
                 .collect(Collectors.toSet());
         List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyIds);
         if (propertyList.size() != propertyIds.size()) {
@@ -114,7 +114,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
         // 4. 最后校验,每个 Sku 之间不是重复的
         Set<Set<Long>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
         for (ProductSkuCreateOrUpdateReqVO sku : skus) {
-            if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuBaseVO.Property::getValueId))) { // 添加失败,说明重复
+            if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) { // 添加失败,说明重复
                 throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE);
             }
         }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
index ec088cfdd..a6651c8b2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
@@ -68,11 +68,9 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
         List<ProductSkuCreateOrUpdateReqVO> skus = Arrays.asList(
                 randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试更新
                     o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 20L)));
-                    o.setStatus(CommonStatusEnum.ENABLE.getStatus());
                 }),
                 randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试新增
                     o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 40L)));
-                    o.setStatus(CommonStatusEnum.ENABLE.getStatus());
                 })
         );
 

From c10ea9d9de6101e257c9e13d27f4b452f7950310 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Sun, 30 Apr 2023 17:35:05 +0800
Subject: [PATCH 05/10] =?UTF-8?q?=E7=A7=BB=E9=99=A4ProductSku=E7=9B=B8?=
 =?UTF-8?q?=E5=85=B3=E7=9A=84status=E5=B1=9E=E6=80=A7=EF=BC=8C=E4=BF=AE?=
 =?UTF-8?q?=E6=94=B9Property?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../convert/property/ProductPropertyConvert.java      | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

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 211bcc293..368da9416 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,5 +1,6 @@
 package cn.iocoder.yudao.module.product.convert.property;
 
+import cn.hutool.core.collection.CollUtil;
 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;
@@ -11,9 +12,12 @@ import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyVa
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
 /**
  * 属性项 Convert
  *
@@ -38,7 +42,12 @@ public interface ProductPropertyConvert {
         Map<Long, List<ProductPropertyValueDO>> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
         return CollectionUtils.convertList(keys, key -> {
             ProductPropertyAndValueRespVO respVO = convert02(key);
-            respVO.setValues(convertList02(valueMap.get(key.getId())));
+            // 如果属性值为空value不为null,返回空列表
+            if (CollUtil.isEmpty(values)) {
+                respVO.setValues(Collections.emptyList());
+            }else {
+                respVO.setValues(convertList02(valueMap.get(key.getId())));
+            }
             return respVO;
         });
     }

From 15ced47b170f75ccb52c45953a6ea38344333c08 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Sun, 30 Apr 2023 17:35:38 +0800
Subject: [PATCH 06/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=9A=E7=A7=9F?=
 =?UTF-8?q?=E6=88=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 yudao-module-mall/yudao-module-product-biz/pom.xml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml
index 8a06a4cde..72c37cb20 100644
--- a/yudao-module-mall/yudao-module-product-biz/pom.xml
+++ b/yudao-module-mall/yudao-module-product-biz/pom.xml
@@ -35,6 +35,10 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
+        </dependency>
 
         <!-- Web 相关 -->
         <dependency>

From 6428f0fcafdb667c0266fe3d2df90ff323285b14 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Mon, 1 May 2023 14:47:00 +0800
Subject: [PATCH 07/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=95=86=E5=93=81?=
 =?UTF-8?q?=E6=9E=9A=E4=B8=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../product/enums/spu/ProductUnitEnum.java    | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductUnitEnum.java

diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductUnitEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductUnitEnum.java
new file mode 100644
index 000000000..6d463ffb5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductUnitEnum.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.product.enums.spu;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 产品单位枚举
+ *
+ * @author HUIHUI
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductUnitEnum implements IntArrayValuable {
+    PIECE(1, "个"),
+    DOZEN(2, "打"),
+    BOX(3, "盒"),
+    BAG(4, "袋"),
+    CASE(5, "箱"),
+    SET(6, "套"),
+    PACK(7, "包"),
+    PAIR(8, "双"),
+    ROLL(9, "卷"),
+    SHEET(10, "张"),
+    WEIGHT(11, "克"),
+    KILOGRAM(12, "千克"),
+    MILLIGRAM(13, "毫克"),
+    MICROGRAM(14, "微克"),
+    TON(15, "吨"),
+    LITER(16, "升"),
+    MILLILITER(17, "毫升"),
+    SQUARE_METER(19, "平方米"),
+    SQUARE_KILOMETER(20, "平方千米"),
+    SQUARE_MILE(21, "平方英里"),
+    SQUARE_YARD(22, "平方码"),
+    SQUARE_FOOT(23, "平方英尺"),
+    CUBIC_METER(24, "立方米"),
+    CUBIC_CENTIMETER(25, "立方厘米"),
+    CUBIC_INCH(26, "立方英寸"),
+    METER(27, "米"),
+    CENTIMETER(29, "厘米"),
+    MILLIMETER(30, "毫米"),
+    INCH(31, "英寸"),
+    FOOT(32, "英尺"),
+    YARD(33, "码"),
+    ;
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductUnitEnum::getStatus).toArray();
+
+    /**
+     * 状态
+     */
+    private final Integer status;
+    /**
+     * 状态名
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+}

From 70816371e51ae57c3b85ee236c28b437dfd65c81 Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Tue, 2 May 2023 02:33:14 +0800
Subject: [PATCH 08/10] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90?=
 =?UTF-8?q?=E5=95=86=E5=93=81CRUD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../admin/sku/vo/ProductSkuBaseVO.java        | 10 +++
 .../admin/spu/ProductSpuController.java       |  2 +-
 .../admin/spu/vo/ProductSpuBaseVO.java        | 61 ++++-------------
 .../admin/spu/vo/ProductSpuPageReqVO.java     | 24 -------
 .../admin/spu/vo/ProductSpuPageRespVO.java    | 31 +++++++++
 .../admin/spu/vo/ProductSpuRespVO.java        | 18 -----
 .../convert/sku/ProductSkuConvert.java        |  3 +-
 .../convert/spu/ProductSpuConvert.java        |  2 +-
 .../dal/dataobject/spu/ProductSpuDO.java      |  6 +-
 .../dal/mysql/spu/ProductSpuMapper.java       | 13 ----
 .../category/ProductCategoryServiceImpl.java  |  2 +-
 .../service/sku/ProductSkuService.java        |  6 +-
 .../service/sku/ProductSkuServiceImpl.java    | 30 ++++++---
 .../service/spu/ProductSpuServiceImpl.java    | 65 +++++++++++--------
 .../service/sku/ProductSkuServiceTest.java    |  2 +-
 .../spu/ProductSpuServiceImplTest.java        | 42 +++---------
 16 files changed, 133 insertions(+), 184 deletions(-)
 create mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java

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 e9c9bb48c..dde623b50 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
@@ -50,4 +50,14 @@ public class ProductSkuBaseVO {
 
     @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米
     private Double volume;
+    /**
+     * 一级分销的佣金,单位:分
+     */
+    @Schema(description = "一级分销的佣金", example = "1024")
+    private Integer subCommissionFirstPrice;
+    /**
+     * 二级分销的佣金,单位:分
+     */
+    @Schema(description = "二级分销的佣金", example = "1024")
+    private Integer subCommissionSecondPrice;
 }
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 85fa93f8e..f2ce90c1d 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
@@ -94,7 +94,7 @@ public class ProductSpuController {
     @GetMapping("/page")
     @Operation(summary = "获得商品 SPU 分页")
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
-    public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
+    public CommonResult<PageResult<ProductSpuPageRespVO>> getSpuPage(@Valid ProductSpuPageReqVO 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 e7a30484d..251b4be47 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
@@ -38,16 +38,11 @@ public class ProductSpuBaseVO {
     @NotEmpty(message = "商品详情不能为空")
     private String description;
 
-    @Schema(description = "商品条码(一维码)", required = true, example = "芋道")
-    @NotEmpty(message = "商品条码(一维码)不能为空")
-    private String barCode;
-
     @Schema(description = "商品分类编号", required = true, example = "芋道")
-    @NotEmpty(message = "商品分类编号不能为空")
+    @NotNull(message = "商品分类编号不能为空")
     private Long categoryId;
 
     @Schema(description = "商品品牌编号", required = true, example = "芋道")
-    @NotEmpty(message = "商品品牌编号不能为空")
     private Long brandId;
 
     @Schema(description = "商品封面图", required = true, example = "芋道")
@@ -55,99 +50,71 @@ public class ProductSpuBaseVO {
     private String picUrl;
 
     @Schema(description = "商品轮播图", required = true)
-    @NotEmpty(message = "商品轮播图不能为空")
     private List<String> sliderPicUrls;
 
     @Schema(description = "商品视频")
     private String videoUrl;
 
     @Schema(description = "单位", required = true, example = "1")
-    @NotEmpty(message = "商品单位不能为空")
+    @NotNull(message = "商品单位不能为空")
     private Integer unit;
 
     @Schema(description = "排序字段", required = true, example = "1")
-    @NotEmpty(message = "商品排序字段不能为空")
+    @NotNull(message = "商品排序字段不能为空")
     private Integer sort;
 
-    @Schema(description = "商品状态", required = true, example = "1")
-    @NotEmpty(message = "商品状态不能为空")
-    private Integer status;
-
     // ========== SKU 相关字段 =========
 
     @Schema(description = "规格类型", required = true, example = "true")
-    @NotEmpty(message = "商品规格类型不能为空")
+    @NotNull(message = "商品规格类型不能为空")
     private Boolean specType;
 
-    @Schema(description = "商品价格", required = true, example = "1212")
-    @NotEmpty(message = "商品价格不能为空")
-    private Integer price;
-
-    @Schema(description = "市场价", required = true, example = "3")
-    @NotEmpty(message = "商品市场价不能为空")
-    private Integer marketPrice;
-
-    @Schema(description = "成本价", required = true, example = "12")
-    @NotEmpty(message = "商品成本价不能为空")
-    private Integer costPrice;
-
-    @Schema(description = "库存", required = true, example = "111")
-    @NotEmpty(message = "商品库存不能为空")
-    private Integer stock;
-
     // ========== 物流相关字段 =========
 
     @Schema(description = "物流配置模板编号", required = true, example = "111")
-    @NotEmpty(message = "物流配置模板编号不能为空")
+    @NotNull(message = "物流配置模板编号不能为空")
     private Long deliveryTemplateId;
 
     // ========== 营销相关字段 =========
 
     @Schema(description = "是否热卖推荐", required = true, example = "true")
-    @NotEmpty(message = "商品推荐不能为空")
+    @NotNull(message = "商品推荐不能为空")
     private Boolean recommendHot;
 
     @Schema(description = "是否优惠推荐", required = true, example = "true")
-    @NotEmpty(message = "商品推荐不能为空")
+    @NotNull(message = "商品推荐不能为空")
     private Boolean recommendBenefit;
 
     @Schema(description = "是否精品推荐", required = true, example = "true")
-    @NotEmpty(message = "商品推荐不能为空")
+    @NotNull(message = "商品推荐不能为空")
     private Boolean recommendBest;
 
     @Schema(description = "是否新品推荐", required = true, example = "true")
-    @NotEmpty(message = "商品推荐不能为空")
+    @NotNull(message = "商品推荐不能为空")
     private Boolean recommendNew;
 
     @Schema(description = "是否优品推荐", required = true, example = "true")
-    @NotEmpty(message = "商品推荐不能为空")
+    @NotNull(message = "商品推荐不能为空")
     private Boolean recommendGood;
 
     @Schema(description = "赠送积分", required = true, example = "111")
-    @NotEmpty(message = "商品赠送积分不能为空")
+    @NotNull(message = "商品赠送积分不能为空")
     private Integer giveIntegral;
 
-    @Schema(description = "赠送的优惠劵编号的数组")
+    @Schema(description = "赠送的优惠劵编号的数组") // TODO 这块前端还未实现
     private List<Long> giveCouponTemplateIds;
 
     @Schema(description = "分销类型")
+    @NotNull(message = "商品分销类型不能为空")
     private Boolean subCommissionType;
 
-    @Schema(description = "活动展示顺序")
+    @Schema(description = "活动展示顺序") // TODO 这块前端还未实现
     private List<Integer> activityOrders;
 
     // ========== 统计相关字段 =========
 
-    @Schema(description = "商品销量", required = true, example = "芋道")
-    @NotEmpty(message = "商品销量不能为空")
-    private Integer salesCount;
-
     @Schema(description = "虚拟销量", required = true, example = "芋道")
-    @NotEmpty(message = "商品虚拟销量不能为空")
     private Integer virtualSalesCount;
 
-    @Schema(description = "浏览量", required = true, example = "芋道")
-    @NotEmpty(message = "商品浏览量不能为空")
-    private Integer browseCount;
 
 }
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 0bfefb8d4..91cd54ab2 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
@@ -15,31 +15,7 @@ public class ProductSpuPageReqVO extends PageParam {
     @Schema(description = "商品名称", example = "yutou")
     private String name;
 
-    @Schema(description = "商品编码", example = "yudaoyuanma")
-    private String code;
-
     @Schema(description = "分类编号", example = "1")
     private Long categoryId;
 
-    @Schema(description = "商品品牌编号", example = "1")
-    private Long brandId;
-
-    @Schema(description = "上下架状态", example = "1")
-    private Integer status;
-
-    @Schema(description = "销量最小值", example = "1")
-    private Integer salesCountMin;
-
-    @Schema(description = "销量最大值", example = "1024")
-    private Integer salesCountMax;
-
-    @Schema(description = "市场价最小值", example = "1")
-    private Integer marketPriceMin;
-
-    @Schema(description = "市场价最大值", example = "1024")
-    private Integer marketPriceMax;
-
-    @Schema(description = "是否库存告警", example = "true")
-    private Boolean alarmStock;
-
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java
new file mode 100644
index 000000000..0517cd41c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 商品 SPU 分页 response VO")
+@Data
+public class ProductSpuPageRespVO {
+    @Schema(description = "spuId", example = "1")
+    private Long id;
+    @Schema(description = "商品封面图", example = "1")
+    private String picUrl;
+    @Schema(description = "商品名称", example = "1")
+    private String name;
+    @Schema(description = "商品价格", example = "1")
+    private Integer price;
+    @Schema(description = "商品销量", example = "1")
+    private Integer salesCount;
+    @Schema(description = "商品排序", example = "1")
+    private Integer stock;
+    @Schema(description = "商品封面图", example = "1")
+    private Integer sort;
+    @Schema(description = "商品创建时间", example = "1")
+    private LocalDateTime createTime;
+    @Schema(description = "商品状态", example = "1")
+    private Integer status;
+}
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 5f088b74b..d550cb0c2 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
@@ -19,22 +19,4 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
 
-    // ========== SKU 相关字段 =========
-
-    @Schema(description = "库存", required = true, example = "true")
-    private Integer totalStock;
-
-    @Schema(description = " 最小价格,单位使用:分", required = true, example = "1024")
-    private Integer minPrice;
-
-    @Schema(description = "最大价格,单位使用:分", required = true, example = "1024")
-    private Integer maxPrice;
-
-    @Schema(description = "商品销量", example = "1024")
-    private Integer salesCount;
-
-    // ========== 统计相关字段 =========
-
-    @Schema(description = "点击量", example = "1024")
-    private Integer clickCount;
 }
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 9b7714bb9..8336242b4 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
@@ -35,9 +35,8 @@ public interface ProductSkuConvert {
 
     List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list);
 
-    default List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId, String spuName) {
+    default List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId) {
         List<ProductSkuDO> result = convertList06(list);
-        // result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName)); TODO ProductSkuDO中已经没有name相关属性
         result.forEach(item -> item.setSpuId(spuId));
         return result;
     }
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 fcf6d6436..4ceddab4d 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
@@ -38,7 +38,7 @@ public interface ProductSpuConvert {
 
     List<ProductSpuDO> convertList(List<ProductSpuDO> list);
 
-    PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
+    PageResult<ProductSpuPageRespVO> convertPage(PageResult<ProductSpuDO> page);
 
     ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
 
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
index 1260c7170..e2ed9f2a1 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
@@ -116,19 +116,19 @@ public class ProductSpuDO extends TenantBaseDO {
     /**
      * 商品价格,单位使用:分
      *
-     * 基于其对应的 {@link ProductSkuDO#getPrice()} 最小值
+     * 基于其对应的 {@link ProductSkuDO#getPrice()} sku单价最低的商品的
      */
     private Integer price;
     /**
      * 市场价,单位使用:分
      *
-     * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} 最大值 TODO 芋艿:待确定最大还是最小
+     * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} sku单价最低的商品的
      */
     private Integer marketPrice;
     /**
      * 成本价,单位使用:分
      *
-     * 基于其对应的 {@link ProductSkuDO#getCostPrice()} 最大值 TODO 芋艿:待确定最大还是最小
+     * 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的
      */
     private Integer costPrice;
     /**
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 256bc43f1..6ac1e8611 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
@@ -24,11 +24,6 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
         return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
                 .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
                 .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
-                .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus())
-                .leIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMax())
-                .geIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMin())
-                .leIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMax())
-                .geIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMin())
                 .orderByDesc(ProductSpuDO::getSort));
     }
 
@@ -36,13 +31,7 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
         return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
                 .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
                 .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
-                .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus())
-                .leIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMax())
-                .geIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMin())
-                .leIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMax())
-                .geIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMin())
                 .inIfPresent(ProductSpuDO::getId, alarmStockSpuIds) // 库存告警
-                .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus())
                 .orderByDesc(ProductSpuDO::getSort));
     }
 
@@ -52,8 +41,6 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
                 .eqIfPresent(ProductSpuDO::getStatus, status);
         // 排序逻辑
         if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
-            // TODO ProductSpuDO 已经没有maxPrice 属性
-            //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);
         }
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 21dfb9dee..02bde434d 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
@@ -100,7 +100,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
         if (category == null) {
             throw exception(CATEGORY_NOT_EXISTS);
         }
-        if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+        if (Objects.equals(category.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
             throw exception(CATEGORY_DISABLED, category.getName());
         }
     }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
index 8db4911ab..923603487 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -56,19 +56,17 @@ public interface ProductSkuService {
      * 批量创建 SKU
      *
      * @param spuId 商品 SPU 编号
-     * @param spuName 商品 SPU 名称
      * @param list SKU 对象集合
      */
-    void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list);
+    void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
 
     /**
      * 根据 SPU 编号,批量更新它的 SKU 信息
      *
      * @param spuId SPU 编码
-     * @param spuName 商品 SPU 名称
      * @param skus SKU 的集合
      */
-    void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus);
+    void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus);
 
     /**
      * 更新 SKU 库存(增量)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index a314318fc..62e59f2c9 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -84,10 +84,17 @@ public class ProductSkuServiceImpl implements ProductSkuService {
             return;
         }
 
+        // 0、校验skus是否为空
+        if (CollUtil.isEmpty(skus)){
+            throw exception(SKU_NOT_EXISTS);
+        }
+
         // 1、校验属性项存在
         Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null)
-                .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
-                .map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
+                // 遍历多个 Property 属性
+                .flatMap(p -> p.getProperties().stream())
+                // 将每个 Property 转换成对应的 propertyId,最后形成集合
+                .map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId)
                 .collect(Collectors.toSet());
         List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyIds);
         if (propertyList.size() != propertyIds.size()) {
@@ -107,22 +114,24 @@ public class ProductSkuServiceImpl implements ProductSkuService {
         int attrValueIdsSize = skus.get(0).getProperties().size();
         for (int i = 1; i < skus.size(); i++) {
             if (attrValueIdsSize != skus.get(i).getProperties().size()) {
-                throw exception(ErrorCodeConstants.SPU_ATTR_NUMBERS_MUST_BE_EQUALS);
+                throw exception(SPU_ATTR_NUMBERS_MUST_BE_EQUALS);
             }
         }
 
         // 4. 最后校验,每个 Sku 之间不是重复的
-        Set<Set<Long>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
+        // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
+        Set<Set<Long>> skuAttrValues = new HashSet<>();
         for (ProductSkuCreateOrUpdateReqVO sku : skus) {
-            if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) { // 添加失败,说明重复
-                throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE);
+            // 添加失败,说明重复
+            if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) {
+                throw exception(SPU_SKU_NOT_DUPLICATE);
             }
         }
     }
 
     @Override
-    public void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
-        productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId, spuName));
+    public void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
+        productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId));
     }
 
     @Override
@@ -152,7 +161,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) {
+    public void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) {
         // 构建属性与 SKU 的映射关系;
         Map<String, Long> existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId),
                 ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId);
@@ -160,13 +169,14 @@ public class ProductSkuServiceImpl implements ProductSkuService {
         // 拆分三个集合,新插入的、需要更新的、需要删除的
         List<ProductSkuDO> insertSkus = new ArrayList<>();
         List<ProductSkuDO> updateSkus = new ArrayList<>();
-        List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null, spuName);
+        List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null);
         allUpdateSkus.forEach(sku -> {
             String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku);
             // 1、找得到的,进行更新
             Long existsSkuId = existsSkuMap.remove(propertiesKey);
             if (existsSkuId != null) {
                 sku.setId(existsSkuId);
+                // TODO 那spuId岂不是为null了
                 updateSkus.add(sku);
                 return;
             }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
index 352c8b341..45bc23389 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -12,6 +12,7 @@ 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.dal.mysql.spu.ProductSpuMapper;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
@@ -21,10 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -54,20 +52,21 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createSpu(ProductSpuCreateReqVO createReqVO) {
-        // 校验分类
-        validateCategory(createReqVO.getCategoryId());
-        // 校验品牌
-        brandService.validateProductBrand(createReqVO.getBrandId());
-        // 校验SKU
-        List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
-        productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
+        // 校验分类 TODO 暂不清楚为什么只能选择第三层的结点
+        //validateCategory(createReqVO.getCategoryId());
+        // 校验品牌 TODO 暂不校验
+        //brandService.validateProductBrand(createReqVO.getBrandId());
 
-        // 插入 SPU
+        List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
+        // 校验SKU
+        productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
         ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
+        // 初始化SPU中SKU相关属性
         initSpuFromSkus(spu, skuSaveReqList);
+        // 插入 SPU
         productSpuMapper.insert(spu);
         // 插入 SKU
-        productSkuService.createSkuList(spu.getId(), spu.getName(), skuSaveReqList);
+        productSkuService.createSkuList(spu.getId(), skuSaveReqList);
         // 返回
         return spu.getId();
     }
@@ -90,7 +89,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
         initSpuFromSkus(updateObj, skuSaveReqList);
         productSpuMapper.updateById(updateObj);
         // 批量更新 SKU
-        productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus());
+        productSkuService.updateSkuList(updateObj.getId(), updateReqVO.getSkus());
     }
 
     /**
@@ -101,11 +100,25 @@ public class ProductSpuServiceImpl implements ProductSpuService {
      * @param skus 商品 SKU 数组
      */
     private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
-        spu.setMarketPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
-        // TODO ProductSpuDO中已没有相关属性
-        //spu.setMaxPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
-        //spu.setMinPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
-        //spu.setTotalStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
+        // 断言,避免告警
+        assert skus.size() > 0;
+        // 获取sku单价最低的商品
+        ProductSkuCreateOrUpdateReqVO vo = skus.stream().min(Comparator.comparing(ProductSkuCreateOrUpdateReqVO::getPrice)).get();
+        // sku单价最低的商品的价格
+        spu.setPrice(vo.getPrice());
+        // sku单价最低的商品的市场价格
+        spu.setMarketPrice(vo.getMarketPrice());
+        // sku单价最低的商品的成本价格
+        spu.setCostPrice(vo.getCostPrice());
+        // sku单价最低的商品的条形码
+        spu.setBarCode(vo.getBarCode());
+        // 默认状态为上架
+        spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
+        // TODO 默认商品销量和浏览量为零
+        spu.setSalesCount(0);
+        spu.setBrowseCount(0);
+        // skus库存总数
+        spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
     }
 
     /**
@@ -155,14 +168,14 @@ public class ProductSpuServiceImpl implements ProductSpuService {
 
     @Override
     public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
-        // 库存告警的 SPU 编号的集合
+        // 库存告警的 SPU 编号的集合 TODO 一个接口一个接口来
         Set<Long> alarmStockSpuIds = null;
-        if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
-            alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId);
-            if (CollUtil.isEmpty(alarmStockSpuIds)) {
-                return PageResult.empty();
-            }
-        }
+        //if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
+        //    alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId);
+        //    if (CollUtil.isEmpty(alarmStockSpuIds)) {
+        //        return PageResult.empty();
+        //    }
+        //}
         // 分页查询
         return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds);
     }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
index a6651c8b2..59305e22d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
@@ -75,7 +75,7 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
         );
 
         // 调用
-        productSkuService.updateSkuList(spuId, spuName, skus);
+        productSkuService.updateSkuList(spuId, skus);
         // 断言
         List<ProductSkuDO> dbSkus = productSkuMapper.selectListBySpuId(spuId);
         assertEquals(dbSkus.size(), 2);
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
index 8048e9344..d6e1bdb4e 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -9,10 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
@@ -37,6 +34,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
 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.RandomUtils.randomPojo;
@@ -83,21 +81,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         // 准备参数
         ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class, o -> {
             o.setSpecType(true);
-            o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
         });
-
-        // 校验SKU
-        List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();
-
         Long spu = productSpuService.createSpu(createReqVO);
         ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
-
-        createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
-        // TODO ProductSpuCreateReqVO中已没有相关属性
-//        createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
-//        createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
-//        createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
-
         assertPojoEquals(createReqVO, productSpuDO);
 
     }
@@ -111,18 +97,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
             o.setId(createReqVO.getId()); // 设置更新的 ID
             o.setSpecType(true);
-            o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
         });
         // 调用
         productSpuService.updateSpu(reqVO);
-
-        List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = reqVO.getSkus();
-        reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
-        // TODO ProductSpuUpdateReqVO中已没有相关属性
-//        reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
-//        reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
-//        reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
-
         // 校验是否更新正确
         ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的
         assertPojoEquals(reqVO, spu);
@@ -132,7 +109,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
     public void testValidateSpuExists_exception() {
         ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
             o.setSpecType(true);
-            o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
         });
         // 调用
         Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO));
@@ -175,7 +151,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
     void getSpuPage_alarmStock_empty() {
         // 调用
         ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
-        productSpuPageReqVO.setAlarmStock(true);
+        //productSpuPageReqVO.setAlarmStock(true);
 
         PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
 
@@ -225,10 +201,10 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
 
         // 调用
         ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
-        productSpuPageReqVO.setAlarmStock(true);
+        //productSpuPageReqVO.setAlarmStock(true);
         PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
 
-        PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
+        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
         Assertions.assertIterableEquals(result.getList(), spuPage.getList());
         assertEquals(spuPage.getTotal(), result.getTotal());
     }
@@ -273,14 +249,14 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
 
         // 调用
         ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
-        productSpuPageReqVO.setAlarmStock(false);
-        productSpuPageReqVO.setBrandId(brandId);
-        productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
+        //productSpuPageReqVO.setAlarmStock(false);
+        //productSpuPageReqVO.setBrandId(brandId);
+        //productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
         productSpuPageReqVO.setCategoryId(categoryId);
 
         PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
 
-        PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
+        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
         assertEquals(result, spuPage);
     }
 

From e163ae8b70cca549fea70ec850f39b79eac6d85f Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Wed, 3 May 2023 02:31:50 +0800
Subject: [PATCH 09/10] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=95=86=E5=93=81?=
 =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=92=8C=E7=BC=96=E8=BE=91=E6=95=B0=E6=8D=AE?=
 =?UTF-8?q?=E5=9B=9E=E6=98=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../enums/spu/ProductSpuStatusEnum.java       |  2 +-
 .../property/ProductPropertyController.java   |  5 +--
 .../vo/property/ProductPropertyListReqVO.java |  7 ++++-
 .../admin/sku/vo/ProductSkuRespVO.java        | 10 +++---
 .../admin/spu/ProductSpuController.java       | 14 +--------
 .../admin/spu/vo/ProductSpuDetailRespVO.java  | 25 +++++----------
 .../convert/sku/ProductSkuConvert.java        |  2 +-
 .../convert/spu/ProductSpuConvert.java        |  7 +++--
 .../property/ProductPropertyServiceImpl.java  |  5 +++
 .../service/sku/ProductSkuService.java        |  2 +-
 .../service/spu/ProductSpuService.java        |  7 +++++
 .../service/spu/ProductSpuServiceImpl.java    | 31 +++++++++++++++++++
 12 files changed, 72 insertions(+), 45 deletions(-)

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 2223cf23d..4ba6124e0 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
@@ -17,7 +17,7 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
 
     RECYCLE(-1, "回收站"),
     DISABLE(0, "下架"),
-    ENABLE(1, "上架"),;
+    ENABLE(1, "上架");
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStatus).toArray();
 
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 bd063e0ec..0c203b551 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
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueServ
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import oracle.jdbc.proxy.annotation.Post;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -81,10 +82,10 @@ public class ProductPropertyController {
         return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
     }
 
-    @GetMapping("/get-value-list")
+    @PostMapping("/get-value-list")
     @Operation(summary = "获得属性项列表")
     @PreAuthorize("@ss.hasPermission('product:property:query')")
-    public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
+    public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid @RequestBody ProductPropertyListReqVO listReqVO) {
         // 查询属性项
         List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO);
         if (CollUtil.isEmpty(keys)) {
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 242caff84..44935147c 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
@@ -4,12 +4,17 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.ToString;
 
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
 @Schema(description = "管理后台 - 属性项 List Request VO")
 @Data
 @ToString(callSuper = true)
 public class ProductPropertyListReqVO {
 
-    @Schema(description = "名称", example = "颜色")
+    @Schema(description = "属性名称", example = "颜色")
     private String name;
 
+    @Schema(description = "属性ids", example = "1,2")
+    private List<Long> propertyIds;
 }
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 a229fa826..11bf4a734 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
@@ -7,6 +7,9 @@ import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 import java.util.List;
 
+/**
+ * @author HUIHUI
+ */
 @Schema(description = "管理后台 - 商品 SKU Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
@@ -16,9 +19,6 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
     @Schema(description = "主键", required = true, example = "1024")
     private Long id;
 
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
     @Schema(description = "商品属性")
     @Data
     @AllArgsConstructor
@@ -34,11 +34,11 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
         private Long valueId;
 
         @Schema(description = "属性值", example = "1024")
-        private String value;
+        private String valueName;
     }
     /**
      * 属性数组
      */
-    private List<ProductSkuCreateOrUpdateReqVO.Property> properties;
+    private List<Property> properties;
 
 }
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 f2ce90c1d..2e2871faa 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
@@ -68,19 +68,7 @@ public class ProductSpuController {
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
     public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
-        // 获得商品 SPU
-        ProductSpuDO spu = productSpuService.getSpu(id);
-        if (spu == null) {
-            throw exception(SPU_NOT_EXISTS);
-        }
-
-        // 查询商品 SKU
-        List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
-        // 查询商品属性
-        List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
-                .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
-        // 拼接
-        return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
+        return success(productSpuService.getSpuDetail(id));
     }
 
     @GetMapping("/get-simple-list")
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 58f9565c8..4672911ff 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
@@ -2,37 +2,26 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+import javax.validation.constraints.NotNull;
 import java.util.List;
 
 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO") // 包括关联的 SKU 等信息
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ProductSpuDetailRespVO extends ProductSpuRespVO {
+public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
 
+    @Schema(description = "商品编号", example = "1")
+    private Long id;
     // ========== SKU 相关字段 =========
 
-    /**
-     * SKU 数组
-     */
-    private List<Sku> skus;
-
-    @Schema(description = "管理后台 - 商品 SKU 详细 Response VO")
-    @Data
-    @EqualsAndHashCode(callSuper = true)
-    @ToString(callSuper = true)
-    public static class Sku extends ProductSkuBaseVO {
-
-        /**
-         * 属性数组
-         */
-        private List<ProductPropertyValueDetailRespVO> properties;
-
-    }
+    @Schema(description = "SKU 数组", example = "1")
+    private List<ProductSkuRespVO> skus;
 
 }
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 8336242b4..dd69646af 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
@@ -43,7 +43,7 @@ public interface ProductSkuConvert {
 
     ProductSkuRespDTO convert02(ProductSkuDO bean);
 
-    List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list);
+    List<ProductSkuRespVO> convertList03(List<ProductSkuDO> list);
 
     List<ProductSkuRespDTO> convertList04(List<ProductSkuDO> list);
 
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 4ceddab4d..9fd142b28 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
@@ -4,6 +4,7 @@ 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.sku.vo.ProductSkuRespVO;
 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
 import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
@@ -88,7 +89,7 @@ public interface ProductSpuConvert {
             if (CollUtil.isEmpty(properties)) {
                 continue;
             }
-            ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
+            ProductSkuRespVO sku = spuVO.getSkus().get(i);
             sku.setProperties(new ArrayList<>(properties.size()));
             // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
             properties.forEach(property -> {
@@ -96,13 +97,13 @@ public interface ProductSpuConvert {
                 if (propertyValue == null) {
                     return;
                 }
-                sku.getProperties().add(convert04(propertyValue));
+                //sku.getProperties().add(convert04(propertyValue)); TODO 需要重写
             });
         }
         return spuVO;
     }
     ProductSpuDetailRespVO convert03(ProductSpuDO spu);
-    List<ProductSpuDetailRespVO.Sku> convertList04(List<ProductSkuDO> skus);
+    List<ProductSkuRespVO> convertList04(List<ProductSkuDO> skus);
     ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
 
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
index 328c343d6..96b41de8d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.product.service.property;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
@@ -92,6 +93,10 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
 
     @Override
     public List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO) {
+        // 增加使用属性id查询
+        if (CollUtil.isNotEmpty(listReqVO.getPropertyIds())){
+            return productPropertyMapper.selectBatchIds(listReqVO.getPropertyIds());
+        }
         return productPropertyMapper.selectList(listReqVO);
     }
 
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
index 923603487..8eb5f73fb 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -87,7 +87,7 @@ public interface ProductSkuService {
 
     /**
      * 基于 SPU 编号和状态,获得商品 SKU 集合
-     *
+     * TODO SKU中已经不存在status属性
      * @param spuId SPU 编号
      * @param status 状态
      * @return 商品 SKU 集合
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
index 0ae7359eb..f088a7e79 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
@@ -98,4 +98,11 @@ public interface ProductSpuService {
      */
     void updateSpuStock(Map<Long, Integer> stockIncrCounts);
 
+    /**
+     * 得到spu详细
+     *
+     * @param id id
+     * @return {@link ProductSpuDetailRespVO}
+     */
+    ProductSpuDetailRespVO getSpuDetail(Long id);
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
index 45bc23389..4355f05ab 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -4,10 +4,13 @@ import cn.hutool.core.collection.CollUtil;
 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.sku.vo.ProductSkuCreateOrUpdateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuDetailRespVO;
 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
+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;
@@ -15,6 +18,8 @@ import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
+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 org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -23,6 +28,7 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -48,6 +54,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     private ProductBrandService brandService;
     @Resource
     private ProductCategoryService categoryService;
+    @Resource
+    private ProductPropertyValueService productPropertyValueService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -191,4 +199,27 @@ public class ProductSpuServiceImpl implements ProductSpuService {
         stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount));
     }
 
+    @Override
+    public ProductSpuDetailRespVO getSpuDetail(Long id) {
+        // 获得商品 SPU
+        ProductSpuDO spu = getSpu(id);
+        if (spu == null) {
+            throw exception(SPU_NOT_EXISTS);
+        }
+        ProductSpuDetailRespVO productSpuDetailRespVO = ProductSpuConvert.INSTANCE.convert03(spu);
+        // 查询商品 SKU
+        List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
+        if (CollUtil.isNotEmpty(skus)){
+            List<ProductSkuRespVO> skuRespVoS = ProductSkuConvert.INSTANCE.convertList(skus);
+            // 获取所有的属性值id
+            Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuDO.Property::getValueId).collect(Collectors.toSet());
+            List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds);
+            Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
+            // 设置属性值名称
+            skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId())));
+            productSpuDetailRespVO.setSkus(skuRespVoS);
+        }
+        return productSpuDetailRespVO;
+    }
+
 }

From 810c7ed040242de3672494d6c366532757a70d9e Mon Sep 17 00:00:00 2001
From: puhui999 <puhui999@163.com>
Date: Thu, 4 May 2023 01:32:25 +0800
Subject: [PATCH 10/10] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=95=86=E5=93=81?=
 =?UTF-8?q?=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 sql/mysql/optional/mall.sql                   | 87 +++++++++++++------
 .../enums/spu/ProductSpuTabTypeEnum.java      | 27 ++++++
 .../admin/spu/ProductSpuController.java       | 15 ++++
 .../admin/spu/vo/ProductSpuPageReqVO.java     | 13 ++-
 .../spu/vo/ProductSpuUpdateStatusReqVO.java   | 26 ++++++
 .../dal/mysql/spu/ProductSpuMapper.java       | 58 +++++++++----
 .../service/spu/ProductSpuService.java        | 21 ++++-
 .../service/spu/ProductSpuServiceImpl.java    | 80 +++++++++++------
 .../spu/ProductSpuServiceImplTest.java        |  9 +-
 9 files changed, 257 insertions(+), 79 deletions(-)
 create mode 100644 yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuTabTypeEnum.java
 create mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java

diff --git a/sql/mysql/optional/mall.sql b/sql/mysql/optional/mall.sql
index 0e8483155..6a4b73e54 100644
--- a/sql/mysql/optional/mall.sql
+++ b/sql/mysql/optional/mall.sql
@@ -163,19 +163,20 @@ COMMIT;
 -- Table structure for product_property
 -- ----------------------------
 DROP TABLE IF EXISTS `product_property`;
-CREATE TABLE `product_property`  (
-                                     `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
-                                     `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格名称',
-                                     `status` tinyint NULL DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用',
-                                     `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-                                     `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-                                     `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
-                                     `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
-                                     `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
-                                     `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
-                                     PRIMARY KEY (`id`) USING BTREE,
-                                     INDEX `idx_name`(`name`(32) ASC) USING BTREE COMMENT '规格名称索引'
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格名称';
+CREATE TABLE `product_property` (
+                                    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+                                    `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规格名称',
+                                    `status` tinyint DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用',
+                                    `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                    `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                                    `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
+                                    `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
+                                    `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
+                                    `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+                                    `remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+                                    PRIMARY KEY (`id`) USING BTREE,
+                                    KEY `idx_name` (`name`(32)) USING BTREE COMMENT '规格名称索引'
+) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='规格名称';
 
 -- ----------------------------
 -- Records of product_property
@@ -187,19 +188,20 @@ COMMIT;
 -- Table structure for product_property_value
 -- ----------------------------
 DROP TABLE IF EXISTS `product_property_value`;
-CREATE TABLE `product_property_value`  (
-                                           `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
-                                           `property_id` bigint NULL DEFAULT NULL COMMENT '规格键id',
-                                           `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格值名字',
-                                           `status` tinyint NULL DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用',
-                                           `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-                                           `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-                                           `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
-                                           `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
-                                           `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
-                                           `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
-                                           PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格值';
+CREATE TABLE `product_property_value` (
+                                          `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+                                          `property_id` bigint DEFAULT NULL COMMENT '规格键id',
+                                          `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规格值名字',
+                                          `status` tinyint DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用',
+                                          `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                          `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                                          `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
+                                          `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
+                                          `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
+                                          `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+                                          `remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+                                          PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='规格值';
 
 -- ----------------------------
 -- Records of product_property_value
@@ -325,3 +327,36 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `
 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'market:banner:update', 3, 3, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
 
+INSERT INTO `system_dict_data`(`sort`,`label`,`value`,`dict_type`,`status`,`color_type`,`css_class`,`remark`,`creator`,`create_time`,`updater`,`update_time`,`deleted`) VALUES
+                                                                                                                                                                            (1,'打',2,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'盒',3,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'袋',4,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'箱',5,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'套',6,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'包',7,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'双',8,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'卷',9,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'张',10,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'克',11,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'千克',12,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'毫克',13,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'微克',14,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'吨',15,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'升',16,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1,'毫升',17,'product_unit',0,'','','',1, NOW(),1, NOW(),0),
+                                                                                                                                                                            (1, '平方米', 18, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '平方千米', 19, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '平方英里', 20, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '平方码', 21, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '平方英尺', 22, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '立方米', 23, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '立方厘米', 24, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '立方英寸', 25, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '米', 26, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '千米', 27, 'product_unit', 0, '', '', '',  1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '厘米', 28, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '毫米', 29, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '英寸', 30, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '英尺', 31, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1, '码', 32, 'product_unit', 0, '', '', '', 1, NOW(), 1, NOW(), 0),
+                                                                                                                                                                            (1,'个',1,'product_unit',0,'','','',1, NOW(),1, NOW(),0);
\ No newline at end of file
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuTabTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuTabTypeEnum.java
new file mode 100644
index 000000000..13dfc1a06
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuTabTypeEnum.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.product.enums.spu;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 商品spu标签枚举类型
+ *
+ * @author HUIHUI
+ */
+@Getter
+@AllArgsConstructor
+public enum ProductSpuTabTypeEnum {
+    FOR_SALE(0,"出售中商品"),
+    IN_WAREHOUSE(1,"仓库中商品"),
+    SOLD_OUT(2,"已售空商品"),
+    ALERT_STOCK(3,"警戒库存"),
+    RECYCLE_BIN(4,"商品回收站");
+    /**
+     * 状态
+     */
+    private final Integer type;
+    /**
+     * 状态名
+     */
+    private final String name;
+}
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 2e2871faa..3a4923bbe 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
@@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
+import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -54,6 +55,14 @@ public class ProductSpuController {
         return success(true);
     }
 
+    @PutMapping("/updateStatus")
+    @Operation(summary = "更新商品 SPU Status")
+    @PreAuthorize("@ss.hasPermission('product:spu:update')")
+    public CommonResult<Boolean> updateStatus(@Valid @RequestBody ProductSpuUpdateStatusReqVO updateReqVO) {
+        productSpuService.updateStatus(updateReqVO);
+        return success(true);
+    }
+
     @DeleteMapping("/delete")
     @Operation(summary = "删除商品 SPU")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
@@ -85,5 +94,11 @@ public class ProductSpuController {
     public CommonResult<PageResult<ProductSpuPageRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
         return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
     }
+    @GetMapping("/tabsCount")
+    @Operation(summary = "获得商品 SPU tabsCount")
+    @PreAuthorize("@ss.hasPermission('product:spu:query')")
+    public CommonResult<Map<Integer, Long>> getTabsCount() {
+        return success(productSpuService.getTabsCount());
+    }
 
 }
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 91cd54ab2..cee193637 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
@@ -5,6 +5,11 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO")
 @Data
@@ -15,7 +20,11 @@ public class ProductSpuPageReqVO extends PageParam {
     @Schema(description = "商品名称", example = "yutou")
     private String name;
 
-    @Schema(description = "分类编号", example = "1")
-    private Long categoryId;
+    @Schema(description = "前端请求的tab类型", example = "1")
+    private Integer tabType;
+
+    @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
 
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
new file mode 100644
index 000000000..9838dd610
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
+@Data
+public class ProductSpuUpdateStatusReqVO{
+
+    @Schema(description = "商品编号", required = true, example = "1")
+    @NotNull(message = "商品编号不能为空")
+    private Long id;
+
+    @Schema(description = "商品状态", required = true, example = "1")
+    @NotNull(message = "商品状态不能为空")
+    private Integer status;
+
+
+}
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 6ac1e8611..f3101ab4e 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
@@ -1,14 +1,20 @@
 package cn.iocoder.yudao.module.product.dal.mysql.spu;
 
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
 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.framework.mybatis.core.util.MyBatisUtils;
 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 cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTabTypeEnum;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -20,29 +26,51 @@ import java.util.Set;
 @Mapper
 public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
 
+    //default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) {
+    //    return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
+    //            .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
+    //            .orderByDesc(ProductSpuDO::getSort));
+    //}
     default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
+                // 商品名称
                 .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
-                .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
+                .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime())
+                // 出售中商品
+                .eq(ProductSpuTabTypeEnum.FOR_SALE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.ENABLE.getStatus())
+                // 仓储中商品
+                .eq(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.DISABLE.getStatus())
+                // 已售空商品
+                .eq(ProductSpuTabTypeEnum.SOLD_OUT.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,0)
+                // TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换
+                .le(ProductSpuTabTypeEnum.ALERT_STOCK.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,10)
+                // 回收站
+                .eq(ProductSpuTabTypeEnum.RECYCLE_BIN.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.RECYCLE.getStatus())
                 .orderByDesc(ProductSpuDO::getSort));
     }
 
-    default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO, Set<Long> alarmStockSpuIds) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
-                .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
-                .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId())
-                .inIfPresent(ProductSpuDO::getId, alarmStockSpuIds) // 库存告警
-                .orderByDesc(ProductSpuDO::getSort));
-    }
-
-    default PageResult<ProductSpuDO> selectPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
+    /**
+     * 获得商品 SPU 分页,提供给用户 App 使用
+     */
+    default PageResult<ProductSpuDO> selectPage(AppProductSpuPageReqVO pageReqVO, Set<Long> categoryIds) {
         LambdaQueryWrapperX<ProductSpuDO> query = new LambdaQueryWrapperX<ProductSpuDO>()
-                .eqIfPresent(ProductSpuDO::getCategoryId, pageReqVO.getCategoryId())
-                .eqIfPresent(ProductSpuDO::getStatus, status);
+                .likeIfPresent(ProductSpuDO::getName, pageReqVO.getKeyword()) // 关键字匹配,目前只匹配商品名
+                .inIfPresent(ProductSpuDO::getCategoryId, categoryIds); // 分类
+        query.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()) // 上架状态
+                .gt(ProductSpuDO::getStock, 0); // 有库存
+        // 推荐类型的过滤条件
+        if (ObjUtil.equal(pageReqVO.getRecommendType(), AppProductSpuPageReqVO.RECOMMEND_TYPE_HOT)) {
+            query.eq(ProductSpuDO::getRecommendHot, true);
+        }
         // 排序逻辑
-        if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
-        } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
-            query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount);
+        if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
+            query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC",
+                    pageReqVO.getSortAsc() ? "ASC" : "DESC"));
+        } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
+            query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getPrice)
+                    .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId);
+        } else {
+            query.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId);
         }
         return selectPage(pageReqVO, query);
     }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
index f088a7e79..4b0444018 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
@@ -75,7 +75,7 @@ public interface ProductSpuService {
     List<ProductSpuDO> getSpuList();
 
     /**
-     * 获得商品 SPU 分页
+     * 获得商品 SPU 分页,提供给挂你兰后台使用
      *
      * @param pageReqVO 分页查询
      * @return 商品spu分页
@@ -83,13 +83,12 @@ public interface ProductSpuService {
     PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO);
 
     /**
-     * 获得商品 SPU 分页
+     * 获得商品 SPU 分页,提供给用户 App 使用
      *
      * @param pageReqVO 分页查询
-     * @param status 状态
      * @return 商品 SPU 分页
      */
-    PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status);
+    PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO);
 
     /**
      * 更新商品 SPU 库存(增量)
@@ -105,4 +104,18 @@ public interface ProductSpuService {
      * @return {@link ProductSpuDetailRespVO}
      */
     ProductSpuDetailRespVO getSpuDetail(Long id);
+
+    /**
+     * 更新状态
+     *
+     * @param updateReqVO 更新请求签证官
+     */
+    void updateStatus(ProductSpuUpdateStatusReqVO updateReqVO);
+
+    /**
+     * 获取spu列表标签对应的Count数量
+     *
+     * @return {@link Map}<{@link Integer}, {@link Integer}>
+     */
+    Map<Integer, Long> getTabsCount();
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
index 4355f05ab..23421c988 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -1,14 +1,15 @@
 package cn.iocoder.yudao.module.product.service.spu;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuDetailRespVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
@@ -16,11 +17,13 @@ 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.dal.mysql.spu.ProductSpuMapper;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTabTypeEnum;
 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
 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 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -62,7 +65,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     public Long createSpu(ProductSpuCreateReqVO createReqVO) {
         // 校验分类 TODO 暂不清楚为什么只能选择第三层的结点
         //validateCategory(createReqVO.getCategoryId());
-        // 校验品牌 TODO 暂不校验
+        // 校验品牌 TODO 暂不校验,前端没有做品牌选择
         //brandService.validateProductBrand(createReqVO.getBrandId());
 
         List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
@@ -84,14 +87,13 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
         // 校验 SPU 是否存在
         validateSpuExists(updateReqVO.getId());
-        // 校验分类
-        validateCategory(updateReqVO.getCategoryId());
-        // 校验品牌
-        brandService.validateProductBrand(updateReqVO.getBrandId());
+        // 校验分类 TODO 暂不清楚为什么只能选择第三层的结点
+        //validateCategory(updateReqVO.getCategoryId());
+        // 校验品牌 TODO 暂不校验,前端没有做品牌选择
+        //brandService.validateProductBrand(updateReqVO.getBrandId());
         // 校验SKU
         List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus();
         productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
-
         // 更新 SPU
         ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
         initSpuFromSkus(updateObj, skuSaveReqList);
@@ -176,21 +178,13 @@ public class ProductSpuServiceImpl implements ProductSpuService {
 
     @Override
     public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
-        // 库存告警的 SPU 编号的集合 TODO 一个接口一个接口来
-        Set<Long> alarmStockSpuIds = null;
-        //if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
-        //    alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId);
-        //    if (CollUtil.isEmpty(alarmStockSpuIds)) {
-        //        return PageResult.empty();
-        //    }
-        //}
-        // 分页查询
-        return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds);
+        return productSpuMapper.selectPage(pageReqVO);
     }
 
     @Override
-    public PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
-        return productSpuMapper.selectPage(pageReqVO, status);
+    public PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO) {
+        //return productSpuMapper.selectPage(pageReqVO); TODO 有差异接口接受参数类型不对
+        return null;
     }
 
     @Override
@@ -211,15 +205,45 @@ public class ProductSpuServiceImpl implements ProductSpuService {
         List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
         if (CollUtil.isNotEmpty(skus)){
             List<ProductSkuRespVO> skuRespVoS = ProductSkuConvert.INSTANCE.convertList(skus);
-            // 获取所有的属性值id
-            Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuDO.Property::getValueId).collect(Collectors.toSet());
-            List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds);
-            Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
-            // 设置属性值名称
-            skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId())));
+            // 非多规格,不需要处理
+            if (ObjectUtil.equal(productSpuDetailRespVO.getSpecType(), true)) {
+                // 获取所有的属性值id
+                Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuDO.Property::getValueId).collect(Collectors.toSet());
+                List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds);
+                Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
+                // 设置属性值名称
+                skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId())));
+            }
             productSpuDetailRespVO.setSkus(skuRespVoS);
         }
         return productSpuDetailRespVO;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateStatus(ProductSpuUpdateStatusReqVO updateReqVO) {
+        // 校验存在
+        validateSpuExists(updateReqVO.getId());
+        // 更新状态
+        ProductSpuDO productSpuDO = productSpuMapper.selectById(updateReqVO.getId()).setStatus(updateReqVO.getStatus());
+        productSpuMapper.updateById(productSpuDO);
+
+    }
+
+    @Override
+    public Map<Integer, Long> getTabsCount() {
+        Map<Integer, Long> map = new HashMap<>();
+        // 查询销售中的商品数量
+        map.put(ProductSpuTabTypeEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
+        // 查询仓库中的商品数量
+        map.put(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
+        // 查询售空的商品数量
+        map.put(ProductSpuTabTypeEnum.SOLD_OUT.getType(),productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
+        // 查询触发警戒库存的商品数量 TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换
+        map.put(ProductSpuTabTypeEnum.ALERT_STOCK.getType(),productSpuMapper.selectCount(new LambdaQueryWrapperX<ProductSpuDO>().le(ProductSpuDO::getStock, 10)));
+        // 查询回收站中的商品数量
+        map.put(ProductSpuTabTypeEnum.RECYCLE_BIN.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
+        return map;
+    }
+
 }
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
index d6e1bdb4e..bd61c4e93 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -189,7 +189,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         });
         productSpuMapper.insert(createReqVO);
 
-        Set<Long> alarmStockSpuIds = SetUtils.asSet(createReqVO.getId());
+        //Set<Long> alarmStockSpuIds = SetUtils.asSet(createReqVO.getId()); TODO 查询接口已改变没有使用到这个变量
 
         List<ProductSkuDO> productSpuDOS = Arrays.asList(randomPojo(ProductSkuDO.class, o -> {
             o.setSpuId(createReqVO.getId());
@@ -204,7 +204,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         //productSpuPageReqVO.setAlarmStock(true);
         PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
 
-        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
+        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
         Assertions.assertIterableEquals(result.getList(), spuPage.getList());
         assertEquals(spuPage.getTotal(), result.getTotal());
     }
@@ -249,14 +249,15 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
 
         // 调用
         ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
+        // TODO 已暂时没有相关属性,等用到时再添加
         //productSpuPageReqVO.setAlarmStock(false);
         //productSpuPageReqVO.setBrandId(brandId);
         //productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
-        productSpuPageReqVO.setCategoryId(categoryId);
+        //productSpuPageReqVO.setCategoryId(categoryId);
 
         PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
 
-        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
+        PageResult<ProductSpuPageRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
         assertEquals(result, spuPage);
     }