franky před 2 roky
rodič
revize
6dca8e082b
19 změnil soubory, kde provedl 153 přidání a 52 odebrání
  1. 6 6
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java
  2. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
  3. 1 1
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuUpdateReqVO.java
  4. 8 7
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
  5. 7 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
  6. 8 1
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuUpdateReqVO.java
  7. 24 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
  8. 18 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
  9. 2 8
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
  10. 3 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
  11. 6 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java
  12. 8 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java
  13. 9 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
  14. 14 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
  15. 4 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
  16. 26 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
  17. 3 3
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java
  18. 3 3
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
  19. 1 1
      yudao-ui-admin/src/views/mall/product/spu/index.vue

+ 6 - 6
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java

@@ -38,7 +38,7 @@ public class ProductSkuController {
     @PostMapping("/create")
     @ApiOperation("创建商品sku")
     @PreAuthorize("@ss.hasPermission('product:sku:create')")
-    public CommonResult<Integer> createSku(@Valid @RequestBody ProductSkuCreateReqVO createReqVO) {
+    public CommonResult<Long> createSku(@Valid @RequestBody ProductSkuCreateReqVO createReqVO) {
         return success(ProductSkuService.createSku(createReqVO));
     }
 
@@ -52,18 +52,18 @@ public class ProductSkuController {
 
     @DeleteMapping("/delete")
     @ApiOperation("删除商品sku")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Integer.class)
+    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:sku:delete')")
-    public CommonResult<Boolean> deleteSku(@RequestParam("id") Integer id) {
+    public CommonResult<Boolean> deleteSku(@RequestParam("id") Long id) {
         ProductSkuService.deleteSku(id);
         return success(true);
     }
 
     @GetMapping("/get")
     @ApiOperation("获得商品sku")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Integer.class)
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:sku:query')")
-    public CommonResult<ProductSkuRespVO> getSku(@RequestParam("id") Integer id) {
+    public CommonResult<ProductSkuRespVO> getSku(@RequestParam("id") Long id) {
         ProductSkuDO sku = ProductSkuService.getSku(id);
         return success(ProductSkuConvert.INSTANCE.convert(sku));
     }
@@ -72,7 +72,7 @@ public class ProductSkuController {
     @ApiOperation("获得商品sku列表")
     @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
     @PreAuthorize("@ss.hasPermission('product:sku:query')")
-    public CommonResult<List<ProductSkuRespVO>> getSkuList(@RequestParam("ids") Collection<Integer> ids) {
+    public CommonResult<List<ProductSkuRespVO>> getSkuList(@RequestParam("ids") Collection<Long> ids) {
         List<ProductSkuDO> list = ProductSkuService.getSkuList(ids);
         return success(ProductSkuConvert.INSTANCE.convertList(list));
     }

+ 2 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java

@@ -16,8 +16,8 @@ public class ProductSkuBaseVO {
     @NotNull(message = "spu编号不能为空")
     private Long spuId;
 
-    @ApiModelProperty(value = "规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]", required = true)
-    @NotNull(message = "规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]不能为空")
+    @ApiModelProperty(value = "规格值数组-json格式, [{propertyId: , valueId: }, {propertyId: , valueId: }]", required = true)
+    @NotNull(message = "规格值数组-json格式, [{propertyId: , valueId: }, {propertyId: , valueId: }]不能为空")
     private List<Property> properties;
 
     @ApiModelProperty(value = "销售价格,单位:分", required = true)

+ 1 - 1
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuUpdateReqVO.java

@@ -13,6 +13,6 @@ public class ProductSkuUpdateReqVO extends ProductSkuBaseVO {
 
     @ApiModelProperty(value = "主键", required = true)
     @NotNull(message = "主键不能为空")
-    private Integer id;
+    private Long id;
 
 }

+ 8 - 7
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu;
 
+import nonapi.io.github.classgraph.utils.LogNode;
 import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
@@ -38,7 +39,7 @@ public class ProductSpuController {
     @PostMapping("/create")
     @ApiOperation("创建商品spu")
     @PreAuthorize("@ss.hasPermission('product:spu:create')")
-    public CommonResult<Integer> createSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
+    public CommonResult<Long> createSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
         return success(spuService.createSpu(createReqVO));
     }
 
@@ -52,27 +53,27 @@ public class ProductSpuController {
 
     @DeleteMapping("/delete")
     @ApiOperation("删除商品spu")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Integer.class)
+    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:spu:delete')")
-    public CommonResult<Boolean> deleteSpu(@RequestParam("id") Integer id) {
+    public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
         spuService.deleteSpu(id);
         return success(true);
     }
 
     @GetMapping("/get")
     @ApiOperation("获得商品spu")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Integer.class)
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
-    public CommonResult<SpuRespVO> getSpu(@RequestParam("id") Integer id) {
+    public CommonResult<SpuRespVO> getSpu(@RequestParam("id") Long id) {
         ProductSpuDO spu = spuService.getSpu(id);
         return success(ProductSpuConvert.INSTANCE.convert(spu));
     }
 
     @GetMapping("/list")
     @ApiOperation("获得商品spu列表")
-    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
-    public CommonResult<List<SpuRespVO>> getSpuList(@RequestParam("ids") Collection<Integer> ids) {
+    public CommonResult<List<SpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
         List<ProductSpuDO> list = spuService.getSpuList(ids);
         return success(ProductSpuConvert.INSTANCE.convertList(list));
     }

+ 7 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java

@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
 import lombok.*;
 import java.util.*;
 import io.swagger.annotations.*;
+
+import javax.validation.Valid;
 import javax.validation.constraints.*;
 
 @ApiModel("管理后台 - 商品spu创建 Request VO")
@@ -11,4 +14,8 @@ import javax.validation.constraints.*;
 @ToString(callSuper = true)
 public class ProductSpuCreateReqVO extends ProductSpuBaseVO {
 
+    @ApiModelProperty(value = "sku组合")
+    @Valid
+    List<ProductSkuCreateReqVO> productSkuCreateReqVOS;
+
 }

+ 8 - 1
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuUpdateReqVO.java

@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
 
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
 import lombok.*;
 import java.util.*;
 import io.swagger.annotations.*;
+
+import javax.validation.Valid;
 import javax.validation.constraints.*;
 
 @ApiModel("管理后台 - 商品spu更新 Request VO")
@@ -13,6 +16,10 @@ public class SpuUpdateReqVO extends ProductSpuBaseVO {
 
     @ApiModelProperty(value = "主键", required = true)
     @NotNull(message = "主键不能为空")
-    private Integer id;
+    private Long id;
+
+    @ApiModelProperty(value = "sku组合")
+    @Valid
+    List<ProductSkuCreateReqVO> productSkuCreateReqVOS;
 
 }

+ 24 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java

@@ -2,12 +2,16 @@ package cn.iocoder.yudao.module.product.convert.sku;
 
 import java.util.*;
 
+import cn.hutool.json.JSONUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
 import org.mapstruct.factory.Mappers;
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
+import org.springframework.util.StringUtils;
 
 /**
  * 商品sku Convert
@@ -19,16 +23,36 @@ public interface ProductSkuConvert {
 
     ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class);
 
+    @Mapping(source = "properties", target = "properties", qualifiedByName = "translateStringFromList")
     ProductSkuDO convert(ProductSkuCreateReqVO bean);
 
+    @Mapping(source = "properties", target = "properties", qualifiedByName = "translateStringFromList")
     ProductSkuDO convert(ProductSkuUpdateReqVO bean);
 
+    @Mapping(source = "properties", target = "properties", qualifiedByName = "tokenizeToBeanArray")
     ProductSkuRespVO convert(ProductSkuDO bean);
 
+    @Mapping(source = "properties", target = "properties", qualifiedByName = "tokenizeToExcelBeanArray")
+    ProductSkuExcelVO convertToExcelVO(ProductSkuDO bean);
+
     List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
 
     PageResult<ProductSkuRespVO> convertPage(PageResult<ProductSkuDO> page);
 
     List<ProductSkuExcelVO> convertList02(List<ProductSkuDO> list);
 
+    @Named("tokenizeToBeanArray")
+    default List<ProductSkuBaseVO.Property> translatePropertyArrayFromString(String properties) {
+        return JSONUtil.toList(properties, ProductSkuBaseVO.Property.class);
+    }
+
+    @Named("tokenizeToExcelBeanArray")
+    default List<ProductSkuExcelVO.Property> translateExcelPropertyArrayFromString(String properties) {
+        return JSONUtil.toList(properties, ProductSkuExcelVO.Property.class);
+    }
+
+    @Named("translateStringFromList")
+    default String translatePropertyStringFromList(List<ProductSkuBaseVO.Property> properties) {
+        return JSONUtil.toJsonStr(properties);
+    }
 }

+ 18 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java

@@ -5,9 +5,12 @@ import java.util.*;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
 import org.mapstruct.factory.Mappers;
 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import org.springframework.util.StringUtils;
 
 /**
  * 商品spu Convert
@@ -19,16 +22,31 @@ public interface ProductSpuConvert {
 
     ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);
 
+    @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "translatePicUrlsFromStringList")
     ProductSpuDO convert(ProductSpuCreateReqVO bean);
 
+    @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "translatePicUrlsFromStringList")
     ProductSpuDO convert(SpuUpdateReqVO bean);
 
+    @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "tokenizeToStringArray")
     SpuRespVO convert(ProductSpuDO bean);
 
+    @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "tokenizeToStringArray")
+    SpuExcelVO convertToExcelVO(ProductSpuDO bean);
+
     List<SpuRespVO> convertList(List<ProductSpuDO> list);
 
     PageResult<SpuRespVO> convertPage(PageResult<ProductSpuDO> page);
 
     List<SpuExcelVO> convertList02(List<ProductSpuDO> list);
 
+    @Named("tokenizeToStringArray")
+    default List<String> translatePicUrlsArrayFromString(String picUrls) {
+        return Arrays.asList(StringUtils.tokenizeToStringArray(picUrls, ","));
+    }
+
+    @Named("translatePicUrlsFromStringList")
+    default String translatePicUrlsFromList(List<String> picUrls) {
+        return StringUtils.collectionToCommaDelimitedString(picUrls);
+    }
 }

+ 2 - 8
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java

@@ -27,7 +27,7 @@ public class ProductSkuDO extends BaseDO {
      * 主键
      */
     @TableId
-    private Integer id;
+    private Long id;
     /**
      * spu编号
      */
@@ -36,7 +36,7 @@ public class ProductSkuDO extends BaseDO {
      * 规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]
      */
     // TODO franky:可以定义一个内部的 Property 类,然后 List<Property>
-    private List<Property> properties;
+    private String properties;
     /**
      * 销售价格,单位:分
      */
@@ -62,11 +62,5 @@ public class ProductSkuDO extends BaseDO {
      */
     private Integer status;
 
-    @Data
-    public static class Property {
-        private Integer propertyId;
-        private Integer valueId;
-    }
-
 }
 

+ 3 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.spu;
 
+import cn.hutool.log.Log;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -27,7 +28,7 @@ public class ProductSpuDO extends BaseDO {
      * 主键
      */
     @TableId
-    private Integer id;
+    private Long id;
     /**
      * 商品名称
      */
@@ -48,7 +49,7 @@ public class ProductSpuDO extends BaseDO {
      * 商品主图地址,* 数组,以逗号分隔,最多上传15张
      */
     // TODO franky:List<String>
-    private List<String> picUrls;
+    private String picUrls;
     /**
      * 排序字段
      */

+ 6 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java

@@ -76,4 +76,10 @@ public interface CategoryService {
      * @return 商品分类列表
      */
     List<CategoryDO> getCategoryTreeList(CategoryTreeListReqVO treeListReqVO);
+
+    /**
+     *  验证选择的分类的合法性
+     * @param categoryId 分类id
+     */
+    void validatedCategoryById(Long categoryId);
 }

+ 8 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java

@@ -65,6 +65,9 @@ public class CategoryServiceImpl implements CategoryService {
     }
 
     private CategoryDO validateCategoryExists(Long id, ErrorCode errorCode) {
+        if (id == 0) {
+            return new CategoryDO().setId(id);
+        }
         CategoryDO categoryDO = categoryMapper.selectById(id);
         if (categoryDO == null) {
             throw exception(errorCode);
@@ -72,6 +75,11 @@ public class CategoryServiceImpl implements CategoryService {
         return categoryDO;
     }
 
+    @Override
+    public void validatedCategoryById(Long categoryId) {
+        this.validateCategoryExists(categoryId, CATEGORY_NOT_EXISTS);
+    }
+
     @Override
     public CategoryDO getCategory(Long id) {
         return categoryMapper.selectById(id);

+ 9 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java

@@ -19,7 +19,7 @@ public interface ProductSkuService {
      * @param createReqVO 创建信息
      * @return 编号
      */
-    Integer createSku(@Valid ProductSkuCreateReqVO createReqVO);
+    Long createSku(@Valid ProductSkuCreateReqVO createReqVO);
 
     /**
      * 更新商品sku
@@ -33,7 +33,7 @@ public interface ProductSkuService {
      *
      * @param id 编号
      */
-    void deleteSku(Integer id);
+    void deleteSku(Long id);
 
     /**
      * 获得商品sku
@@ -41,7 +41,7 @@ public interface ProductSkuService {
      * @param id 编号
      * @return 商品sku
      */
-    ProductSkuDO getSku(Integer id);
+    ProductSkuDO getSku(Long id);
 
     /**
      * 获得商品sku列表
@@ -49,7 +49,7 @@ public interface ProductSkuService {
      * @param ids 编号
      * @return 商品sku列表
      */
-    List<ProductSkuDO> getSkuList(Collection<Integer> ids);
+    List<ProductSkuDO> getSkuList(Collection<Long> ids);
 
     /**
      * 获得商品sku分页
@@ -67,4 +67,9 @@ public interface ProductSkuService {
      */
     List<ProductSkuDO> getSkuList(ProductSkuExportReqVO exportReqVO);
 
+    /**
+     *对sku的组合的属性等进行合法性校验
+     * @param skuCreateReqList sku组合的集合
+     */
+    void validatedSkuReq(List<ProductSkuCreateReqVO> skuCreateReqList);
 }

+ 14 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java

@@ -5,6 +5,8 @@ import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.*;
+import java.util.stream.Collectors;
+
 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -28,7 +30,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
     private ProductSkuMapper ProductSkuMapper;
 
     @Override
-    public Integer createSku(ProductSkuCreateReqVO createReqVO) {
+    public Long createSku(ProductSkuCreateReqVO createReqVO) {
         // 插入
         ProductSkuDO sku = ProductSkuConvert.INSTANCE.convert(createReqVO);
         ProductSkuMapper.insert(sku);
@@ -46,26 +48,26 @@ public class ProductSkuServiceImpl implements ProductSkuService {
     }
 
     @Override
-    public void deleteSku(Integer id) {
+    public void deleteSku(Long id) {
         // 校验存在
         this.validateSkuExists(id);
         // 删除
         ProductSkuMapper.deleteById(id);
     }
 
-    private void validateSkuExists(Integer id) {
+    private void validateSkuExists(Long id) {
         if (ProductSkuMapper.selectById(id) == null) {
             throw exception(SKU_NOT_EXISTS);
         }
     }
 
     @Override
-    public ProductSkuDO getSku(Integer id) {
+    public ProductSkuDO getSku(Long id) {
         return ProductSkuMapper.selectById(id);
     }
 
     @Override
-    public List<ProductSkuDO> getSkuList(Collection<Integer> ids) {
+    public List<ProductSkuDO> getSkuList(Collection<Long> ids) {
         return ProductSkuMapper.selectBatchIds(ids);
     }
 
@@ -79,4 +81,11 @@ public class ProductSkuServiceImpl implements ProductSkuService {
         return ProductSkuMapper.selectList(exportReqVO);
     }
 
+    @Override
+    public void validatedSkuReq(List<ProductSkuCreateReqVO> skuCreateReqList) {
+        // 校验规格属性以及规格值是否存在
+        List<Integer> propertyIds = skuCreateReqList.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList());
+
+        // 校验是否有重复的sku组合
+    }
 }

+ 4 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java

@@ -19,7 +19,7 @@ public interface ProductSpuService {
      * @param createReqVO 创建信息
      * @return 编号
      */
-    Integer createSpu(@Valid ProductSpuCreateReqVO createReqVO);
+    Long createSpu(@Valid ProductSpuCreateReqVO createReqVO);
 
     /**
      * 更新商品spu
@@ -33,7 +33,7 @@ public interface ProductSpuService {
      *
      * @param id 编号
      */
-    void deleteSpu(Integer id);
+    void deleteSpu(Long id);
 
     /**
      * 获得商品spu
@@ -41,7 +41,7 @@ public interface ProductSpuService {
      * @param id 编号
      * @return 商品spu
      */
-    ProductSpuDO getSpu(Integer id);
+    ProductSpuDO getSpu(Long id);
 
     /**
      * 获得商品spu列表
@@ -49,7 +49,7 @@ public interface ProductSpuService {
      * @param ids 编号
      * @return 商品spu列表
      */
-    List<ProductSpuDO> getSpuList(Collection<Integer> ids);
+    List<ProductSpuDO> getSpuList(Collection<Long> ids);
 
     /**
      * 获得商品spu分页

+ 26 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java

@@ -1,7 +1,13 @@
 package cn.iocoder.yudao.module.product.service.spu;
 
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
+import cn.iocoder.yudao.module.product.service.category.CategoryService;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.*;
@@ -27,10 +33,25 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     @Resource
     private ProductSpuMapper ProductSpuMapper;
 
+    @Resource
+    private CategoryService categoryService;
+
+    @Resource
+    private ProductSkuService productSkuService;
+
     @Override
-    public Integer createSpu(ProductSpuCreateReqVO createReqVO) {
+    @Transactional
+    public Long createSpu(ProductSpuCreateReqVO createReqVO) {
+        // 校验分类
+        categoryService.validatedCategoryById(createReqVO.getCategoryId());
+        // 校验SKU
+        List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getProductSkuCreateReqVOS();
+        productSkuService.validatedSkuReq(skuCreateReqList);
         // 插入
         ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
+        skuCreateReqList.forEach(p -> {
+            p.setSpuId(spu.getId());
+        });
         ProductSpuMapper.insert(spu);
         // 返回
         return spu.getId();
@@ -46,26 +67,26 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     }
 
     @Override
-    public void deleteSpu(Integer id) {
+    public void deleteSpu(Long id) {
         // 校验存在
         this.validateSpuExists(id);
         // 删除
         ProductSpuMapper.deleteById(id);
     }
 
-    private void validateSpuExists(Integer id) {
+    private void validateSpuExists(Long id) {
         if (ProductSpuMapper.selectById(id) == null) {
             throw exception(SPU_NOT_EXISTS);
         }
     }
 
     @Override
-    public ProductSpuDO getSpu(Integer id) {
+    public ProductSpuDO getSpu(Long id) {
         return ProductSpuMapper.selectById(id);
     }
 
     @Override
-    public List<ProductSpuDO> getSpuList(Collection<Integer> ids) {
+    public List<ProductSpuDO> getSpuList(Collection<Long> ids) {
         return ProductSpuMapper.selectBatchIds(ids);
     }
 

+ 3 - 3
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java

@@ -46,7 +46,7 @@ public class SkuServiceImplTest extends BaseDbUnitTest {
         ProductSkuCreateReqVO reqVO = randomPojo(ProductSkuCreateReqVO.class);
 
         // 调用
-        Integer skuId = ProductSkuService.createSku(reqVO);
+        Long skuId = ProductSkuService.createSku(reqVO);
         // 断言
         assertNotNull(skuId);
         // 校验记录的属性是否正确
@@ -86,7 +86,7 @@ public class SkuServiceImplTest extends BaseDbUnitTest {
         ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);
         ProductSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据
         // 准备参数
-        Integer id = dbSku.getId();
+        Long id = dbSku.getId();
 
         // 调用
         ProductSkuService.deleteSku(id);
@@ -97,7 +97,7 @@ public class SkuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testDeleteSku_notExists() {
         // 准备参数
-        Integer id = 1;
+        Long id = 1L;
 
         // 调用, 并断言异常
         assertServiceException(() -> ProductSkuService.deleteSku(id), SKU_NOT_EXISTS);

+ 3 - 3
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java

@@ -46,7 +46,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         ProductSpuCreateReqVO reqVO = randomPojo(ProductSpuCreateReqVO.class);
 
         // 调用
-        Integer spuId = spuService.createSpu(reqVO);
+        Long spuId = spuService.createSpu(reqVO);
         // 断言
         assertNotNull(spuId);
         // 校验记录的属性是否正确
@@ -86,7 +86,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
         ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class);
         ProductSpuMapper.insert(dbSpu);// @Sql: 先插入出一条存在的数据
         // 准备参数
-        Integer id = dbSpu.getId();
+        Long id = dbSpu.getId();
 
         // 调用
         spuService.deleteSpu(id);
@@ -97,7 +97,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testDeleteSpu_notExists() {
         // 准备参数
-        Integer id = 1;
+        Long id = 1L;
 
         // 调用, 并断言异常
         assertServiceException(() -> spuService.deleteSpu(id), SPU_NOT_EXISTS);

+ 1 - 1
yudao-ui-admin/src/views/mall/product/spu/index.vue

@@ -95,7 +95,7 @@
           <el-input v-model="form.categoryId" placeholder="请输入分类id" />
         </el-form-item>
         <el-form-item label="商品主图地址" prop="picUrls">
-          <el-input v-model="form.picUrls" placeholder="请输入商品主图地址" />
+          <ImageUpload v-model="form.picUrls" :limit="1"/>
         </el-form-item>
         <el-form-item label="排序字段" prop="sort">
           <el-input v-model="form.sort" placeholder="请输入排序字段" />