Commit 652428a723f44f2823deecdbbc80e08704742ad8

Authored by YunaiV
1 parent b7c44789

product:完善 App 商品详情接口

Showing 18 changed files with 300 additions and 70 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -33,6 +33,7 @@ public interface ErrorCodeConstants { @@ -33,6 +33,7 @@ public interface ErrorCodeConstants {
33 // ========== 商品 SPU 1008005000 ========== 33 // ========== 商品 SPU 1008005000 ==========
34 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); 34 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
35 ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下"); 35 ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
  36 + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
36 37
37 // ========== 商品 SKU 1008006000 ========== 38 // ========== 商品 SKU 1008006000 ==========
38 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在"); 39 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
@@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable { @@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
35 return ARRAYS; 35 return ARRAYS;
36 } 36 }
37 37
  38 + /**
  39 + * 判断是否处于【上架】状态
  40 + *
  41 + * @param status 状态
  42 + * @return 是否处于【上架】状态
  43 + */
  44 + public static boolean isEnable(Integer status) {
  45 + return ENABLE.getStatus().equals(status);
  46 + }
  47 +
38 } 48 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -66,7 +66,7 @@ public class ProductSpuController { @@ -66,7 +66,7 @@ public class ProductSpuController {
66 @ApiOperation("获得商品 SPU") 66 @ApiOperation("获得商品 SPU")
67 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) 67 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
68 @PreAuthorize("@ss.hasPermission('product:spu:query')") 68 @PreAuthorize("@ss.hasPermission('product:spu:query')")
69 - public CommonResult<ProductSpuRespVO> getSpu(@RequestParam("id") Long id) { 69 + public CommonResult<ProductSpuDO> getSpu(@RequestParam("id") Long id) {
70 return success(spuService.getSpu(id)); 70 return success(spuService.getSpu(id));
71 } 71 }
72 72
@@ -75,7 +75,7 @@ public class ProductSpuController { @@ -75,7 +75,7 @@ public class ProductSpuController {
75 @ApiOperation("获得商品 SPU 列表") 75 @ApiOperation("获得商品 SPU 列表")
76 @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) 76 @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
77 @PreAuthorize("@ss.hasPermission('product:spu:query')") 77 @PreAuthorize("@ss.hasPermission('product:spu:query')")
78 - public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) { 78 + public CommonResult<List<ProductSpuDO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
79 List<ProductSpuDO> list = spuService.getSpuList(ids); 79 List<ProductSpuDO> list = spuService.getSpuList(ids);
80 return success(ProductSpuConvert.INSTANCE.convertList(list)); 80 return success(ProductSpuConvert.INSTANCE.convertList(list));
81 } 81 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无时间作用,避免 package 缩进
  3 + */
  4 +package cn.iocoder.yudao.module.product.controller.app.property;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无时间作用,避免 package 缩进
  3 + */
  4 +package cn.iocoder.yudao.module.product.controller.app.property.vo.property;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.property.vo.value;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@ApiModel("用户 App - 商品属性值的明细 Response VO")
  8 +@Data
  9 +public class AppProductPropertyValueDetailRespVO {
  10 +
  11 + @ApiModelProperty(value = "属性的编号", required = true, example = "1")
  12 + private Long propertyId;
  13 +
  14 + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
  15 + private String propertyName;
  16 +
  17 + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
  18 + private Long valueId;
  19 +
  20 + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
  21 + private String valueName;
  22 +
  23 +}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http 0 → 100644
  1 +### 获得订单交易的分页 TODO
  2 +GET {{appApi}}/trade/order/page?pageNo=1&pageSize=10
  3 +Authorization: Bearer {{appToken}}
  4 +tenant-id: {{appTenentId}}
  5 +
  6 +### 获得商品 SPU 明细
  7 +GET {{appApi}}/product/spu/get-detail?id=4
  8 +tenant-id: {{appTenentId}}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
1 package cn.iocoder.yudao.module.product.controller.app.spu; 1 package cn.iocoder.yudao.module.product.controller.app.spu;
2 2
3 -import cn.hutool.core.bean.BeanUtil; 3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO;
6 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; 7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; 8 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
8 -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO; 9 +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
  10 +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
  11 +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
  12 +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  13 +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
  14 +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
  15 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
  16 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
9 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; 17 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
10 import io.swagger.annotations.Api; 18 import io.swagger.annotations.Api;
  19 +import io.swagger.annotations.ApiImplicitParam;
11 import io.swagger.annotations.ApiOperation; 20 import io.swagger.annotations.ApiOperation;
12 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
13 import org.springframework.web.bind.annotation.GetMapping; 22 import org.springframework.web.bind.annotation.GetMapping;
@@ -17,28 +26,53 @@ import org.springframework.web.bind.annotation.RestController; @@ -17,28 +26,53 @@ import org.springframework.web.bind.annotation.RestController;
17 26
18 import javax.annotation.Resource; 27 import javax.annotation.Resource;
19 import javax.validation.Valid; 28 import javax.validation.Valid;
  29 +import java.util.List;
20 30
  31 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 32 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  33 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
  34 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
22 35
23 -@Api(tags = "用户 APP - 商品spu") 36 +@Api(tags = "用户 APP - 商品 SPU")
24 @RestController 37 @RestController
25 @RequestMapping("/product/spu") 38 @RequestMapping("/product/spu")
26 @Validated 39 @Validated
27 public class AppProductSpuController { 40 public class AppProductSpuController {
28 41
29 @Resource 42 @Resource
30 - private ProductSpuService spuService; 43 + private ProductSpuService productSpuService;
  44 + @Resource
  45 + private ProductSkuService productSkuService;
  46 + @Resource
  47 + private ProductPropertyValueService productPropertyValueService;
31 48
32 @GetMapping("/page") 49 @GetMapping("/page")
33 @ApiOperation("获得商品spu分页") 50 @ApiOperation("获得商品spu分页")
34 public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) { 51 public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
35 - return success(spuService.getSpuPage(pageVO)); 52 + return success(productSpuService.getSpuPage(pageVO));
36 } 53 }
37 54
38 - @GetMapping("/")  
39 - @ApiOperation("获取商品 - 通过商品id")  
40 - public CommonResult<AppSpuRespVO> getSpu(@RequestParam("spuId") Long spuId) {  
41 - AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);  
42 - return success(appSpuRespVO); 55 + @GetMapping("/get-detail")
  56 + @ApiOperation("获得商品 SPU 明细")
  57 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  58 + public CommonResult<AppSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
  59 + // 获得商品 SPU
  60 + ProductSpuDO spu = productSpuService.getSpu(id);
  61 + if (spu == null) {
  62 + throw exception(SPU_NOT_EXISTS);
  63 + }
  64 + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
  65 + throw exception(SPU_NOT_ENABLE);
  66 + }
  67 +
  68 + // 查询商品 SKU
  69 + List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(),
  70 + CommonStatusEnum.ENABLE.getStatus());
  71 + // 查询商品属性
  72 + List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
  73 + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
  74 + // 拼接
  75 + return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues));
43 } 76 }
  77 +
44 } 78 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.spu.vo;
  2 +
  3 +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +
  8 +import java.util.List;
  9 +
  10 +@ApiModel("用户 App - 商品 SPU 明细 Response VO")
  11 +@Data
  12 +public class AppSpuDetailRespVO {
  13 +
  14 + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
  15 + private Long id;
  16 +
  17 + // ========== 基本信息 =========
  18 +
  19 + @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
  20 + private String name;
  21 +
  22 + @ApiModelProperty(value = "促销语", example = "好吃!")
  23 + private String sellPoint;
  24 +
  25 + @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
  26 + private String description;
  27 +
  28 + @ApiModelProperty(value = "商品分类编号", required = true, example = "1")
  29 + private Long categoryId;
  30 +
  31 + @ApiModelProperty(value = "商品图片的数组", required = true)
  32 + private List<String> picUrls;
  33 +
  34 + @ApiModelProperty(value = "商品视频", required = true)
  35 + private String videoUrl;
  36 +
  37 + // ========== SKU 相关字段 =========
  38 +
  39 + @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
  40 + private Integer specType;
  41 +
  42 + @ApiModelProperty(value = "是否展示库存", required = true, example = "true")
  43 + private Boolean showStock;
  44 +
  45 + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
  46 + private Integer minPrice;
  47 +
  48 + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
  49 + private Integer maxPrice;
  50 +
  51 + /**
  52 + * SKU 数组
  53 + */
  54 + private List<Sku> skus;
  55 +
  56 + // ========== 统计相关字段 =========
  57 +
  58 + @ApiModelProperty(value = "商品销量", required = true, example = "1024")
  59 + private Integer salesCount;
  60 +
  61 + @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息")
  62 + @Data
  63 + public static class Sku {
  64 +
  65 + @ApiModelProperty(value = "商品 SKU 编号", example = "1")
  66 + private Long id;
  67 +
  68 + /**
  69 + * 商品属性数组
  70 + */
  71 + private List<AppProductPropertyValueDetailRespVO> properties;
  72 +
  73 + @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
  74 + private Integer price;
  75 +
  76 + @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
  77 + private Integer marketPrice;
  78 +
  79 + @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
  80 + private String picUrl;
  81 +
  82 + @ApiModelProperty(value = "库存", required = true, example = "1")
  83 + private Integer stock;
  84 +
  85 + @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
  86 + private Double weight;
  87 +
  88 + @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
  89 + private Double volume;
  90 + }
  91 +
  92 +}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java deleted
1 -package cn.iocoder.yudao.module.product.controller.app.spu.vo;  
2 -  
3 -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;  
4 -import io.swagger.annotations.ApiModel;  
5 -import lombok.Data;  
6 -import lombok.EqualsAndHashCode;  
7 -  
8 -/**  
9 - * <p>  
10 - *  
11 - * </p>  
12 - *  
13 - * @author LuoWenFeng  
14 - */  
15 -@ApiModel("App - 商品spu Response VO")  
16 -@Data  
17 -@EqualsAndHashCode(callSuper = true)  
18 -public class AppSpuRespVO extends ProductSpuRespVO {  
19 -  
20 -  
21 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
1 package cn.iocoder.yudao.module.product.convert.sku; 1 package cn.iocoder.yudao.module.product.convert.sku;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
5 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
@@ -10,9 +11,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; @@ -10,9 +11,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
10 import org.mapstruct.Mapper; 11 import org.mapstruct.Mapper;
11 import org.mapstruct.factory.Mappers; 12 import org.mapstruct.factory.Mappers;
12 13
13 -import java.util.HashMap;  
14 -import java.util.List;  
15 -import java.util.Map; 14 +import java.util.*;
  15 +import java.util.stream.Collectors;
16 16
17 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; 17 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
18 18
@@ -72,4 +72,14 @@ public interface ProductSkuConvert { @@ -72,4 +72,14 @@ public interface ProductSkuConvert {
72 return spuIdAndStockMap; 72 return spuIdAndStockMap;
73 } 73 }
74 74
  75 + default Collection<Long> convertPropertyValueIds(List<ProductSkuDO> list) {
  76 + if (CollUtil.isEmpty(list)) {
  77 + return new HashSet<>();
  78 + }
  79 + return list.stream().filter(item -> item.getProperties() != null)
  80 + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
  81 + .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
  82 + .collect(Collectors.toSet());
  83 + }
  84 +
75 } 85 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
1 package cn.iocoder.yudao.module.product.convert.spu; 1 package cn.iocoder.yudao.module.product.convert.spu;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
5 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 6 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
  7 +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
  8 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO;
6 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; 9 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
  11 +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
8 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 12 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  13 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
9 import org.mapstruct.Mapper; 14 import org.mapstruct.Mapper;
10 import org.mapstruct.factory.Mappers; 15 import org.mapstruct.factory.Mappers;
11 16
  17 +import java.util.ArrayList;
12 import java.util.List; 18 import java.util.List;
  19 +import java.util.Map;
  20 +
  21 +import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
  22 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
13 23
14 /** 24 /**
15 * 商品spu Convert 25 * 商品spu Convert
@@ -25,18 +35,46 @@ public interface ProductSpuConvert { @@ -25,18 +35,46 @@ public interface ProductSpuConvert {
25 35
26 ProductSpuDO convert(ProductSpuUpdateReqVO bean); 36 ProductSpuDO convert(ProductSpuUpdateReqVO bean);
27 37
28 - ProductSpuRespVO convert(ProductSpuDO bean);  
29 -  
30 - List<ProductSpuRespVO> convertList(List<ProductSpuDO> list); 38 + List<ProductSpuDO> convertList(List<ProductSpuDO> list);
31 39
32 PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page); 40 PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
33 41
34 ProductSpuPageReqVO convert(AppSpuPageReqVO bean); 42 ProductSpuPageReqVO convert(AppSpuPageReqVO bean);
35 43
  44 + // TODO 芋艿:修改下
36 AppSpuPageRespVO convertAppResp(ProductSpuDO list); 45 AppSpuPageRespVO convertAppResp(ProductSpuDO list);
37 46
38 List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); 47 List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
39 48
40 List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); 49 List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
41 50
  51 + default AppSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus,
  52 + List<ProductPropertyValueDetailRespBO> propertyValues) {
  53 + AppSpuDetailRespVO spuVO = convert02(spu)
  54 + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
  55 + spuVO.setSkus(convertList03(skus));
  56 + // 处理商品属性
  57 + Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
  58 + for (int i = 0; i < skus.size(); i++) {
  59 + List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
  60 + if (CollUtil.isEmpty(properties)) {
  61 + continue;
  62 + }
  63 + AppSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
  64 + sku.setProperties(new ArrayList<>(properties.size()));
  65 + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
  66 + properties.forEach(property -> {
  67 + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
  68 + if (propertyValue == null) {
  69 + return;
  70 + }
  71 + sku.getProperties().add(convert03(propertyValue));
  72 + });
  73 + }
  74 + return spuVO;
  75 + }
  76 + AppSpuDetailRespVO convert02(ProductSpuDO spu);
  77 + List<AppSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus);
  78 + AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
  79 +
42 } 80 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
8 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 8 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
9 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
10 10
  11 +import java.util.Collection;
11 import java.util.List; 12 import java.util.List;
12 13
13 /** 14 /**
@@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX&lt;ProductSkuDO&gt; { @@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX&lt;ProductSkuDO&gt; {
22 return selectList(ProductSkuDO::getSpuId, spuId); 23 return selectList(ProductSkuDO::getSpuId, spuId);
23 } 24 }
24 25
  26 + default List<ProductSkuDO> selectListBySpuIdAndStatus(Long spuId,
  27 + Integer status) {
  28 + return selectList(new LambdaQueryWrapperX<ProductSkuDO>()
  29 + .eq(ProductSkuDO::getSpuId, spuId)
  30 + .eqIfPresent(ProductSkuDO::getStatus, status));
  31 + }
  32 +
  33 + default List<ProductSkuDO> selectListBySpuId(Collection<Long> spuIds) {
  34 + return selectList(ProductSkuDO::getSpuId, spuIds);
  35 + }
  36 +
25 default void deleteBySpuId(Long spuId) { 37 default void deleteBySpuId(Long spuId) {
26 delete(new LambdaQueryWrapperX<ProductSkuDO>().eq(ProductSkuDO::getSpuId, spuId)); 38 delete(new LambdaQueryWrapperX<ProductSkuDO>().eq(ProductSkuDO::getSpuId, spuId));
27 } 39 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku;
3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
5 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 5 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
  6 +import org.springframework.lang.Nullable;
6 7
7 import java.util.Collection; 8 import java.util.Collection;
8 import java.util.List; 9 import java.util.List;
@@ -49,25 +50,25 @@ public interface ProductSkuService { @@ -49,25 +50,25 @@ public interface ProductSkuService {
49 * 50 *
50 * @param list sku组合的集合 51 * @param list sku组合的集合
51 */ 52 */
52 - void validateSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType); 53 + void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType);
53 54
54 /** 55 /**
55 * 批量创建 SKU 56 * 批量创建 SKU
56 * 57 *
57 * @param spuId 商品 SPU 编号 58 * @param spuId 商品 SPU 编号
58 - * @para spuName 商品 SPU 名称 59 + * @param spuName 商品 SPU 名称
59 * @param list SKU 对象集合 60 * @param list SKU 对象集合
60 */ 61 */
61 - void createSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list); 62 + void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list);
62 63
63 /** 64 /**
64 * 根据 SPU 编号,批量更新它的 SKU 信息 65 * 根据 SPU 编号,批量更新它的 SKU 信息
65 * 66 *
66 * @param spuId SPU 编码 67 * @param spuId SPU 编码
67 - * @para spuName 商品 SPU 名称 68 + * @param spuName 商品 SPU 名称
68 * @param skus SKU 的集合 69 * @param skus SKU 的集合
69 */ 70 */
70 - void updateSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus); 71 + void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus);
71 72
72 /** 73 /**
73 * 更新 SKU 库存(增量) 74 * 更新 SKU 库存(增量)
@@ -79,20 +80,30 @@ public interface ProductSkuService { @@ -79,20 +80,30 @@ public interface ProductSkuService {
79 void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); 80 void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
80 81
81 /** 82 /**
82 - * 获得商品 sku 集合 83 + * 获得商品 SKU 集合
83 * 84 *
84 * @param spuId spu 编号 85 * @param spuId spu 编号
85 * @return 商品sku 集合 86 * @return 商品sku 集合
86 */ 87 */
87 - List<ProductSkuDO> getSkusBySpuId(Long spuId); 88 + List<ProductSkuDO> getSkuListBySpuId(Long spuId);
88 89
89 /** 90 /**
90 - * 获得 spu 对应的 sku 集合 91 + * 基于 SPU 编号和状态,获得商品 SKU 集合
  92 + *
  93 + * @param spuId SPU 编号
  94 + * @param status 状态
  95 + * @return 商品 SKU 集合
  96 + */
  97 + List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId,
  98 + @Nullable Integer status);
  99 +
  100 + /**
  101 + * 获得 spu 对应的 SKU 集合
91 * 102 *
92 * @param spuIds spu 编码集合 103 * @param spuIds spu 编码集合
93 * @return 商品 sku 集合 104 * @return 商品 sku 集合
94 */ 105 */
95 - List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds); 106 + List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds);
96 107
97 /** 108 /**
98 * 通过 spuId 删除 sku 信息 109 * 通过 spuId 删除 sku 信息
@@ -106,7 +117,6 @@ public interface ProductSkuService { @@ -106,7 +117,6 @@ public interface ProductSkuService {
106 * 117 *
107 * @return SKU 数组 118 * @return SKU 数组
108 */ 119 */
109 - List<ProductSkuDO> getSkusByAlarmStock();  
110 - 120 + List<ProductSkuDO> getSkuListByAlarmStock();
111 121
112 } 122 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -78,7 +78,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -78,7 +78,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
78 } 78 }
79 79
80 @Override 80 @Override
81 - public void validateSkus(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) { 81 + public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) {
82 // 非多规格,不需要校验 82 // 非多规格,不需要校验
83 if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) { 83 if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
84 return; 84 return;
@@ -121,7 +121,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -121,7 +121,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
121 } 121 }
122 122
123 @Override 123 @Override
124 - public void createSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) { 124 + public void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
125 // 批量插入 SKU 125 // 批量插入 SKU
126 List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuName); 126 List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuName);
127 skuDOList.forEach(v -> v.setSpuId(spuId)); 127 skuDOList.forEach(v -> v.setSpuId(spuId));
@@ -129,13 +129,18 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -129,13 +129,18 @@ public class ProductSkuServiceImpl implements ProductSkuService {
129 } 129 }
130 130
131 @Override 131 @Override
132 - public List<ProductSkuDO> getSkusBySpuId(Long spuId) {  
133 - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuId); 132 + public List<ProductSkuDO> getSkuListBySpuId(Long spuId) {
  133 + return productSkuMapper.selectListBySpuId(spuId);
134 } 134 }
135 135
136 @Override 136 @Override
137 - public List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds) {  
138 - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuIds); 137 + public List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId, Integer status) {
  138 + return productSkuMapper.selectListBySpuIdAndStatus(spuId, status);
  139 + }
  140 +
  141 + @Override
  142 + public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) {
  143 + return productSkuMapper.selectListBySpuId(spuIds);
139 } 144 }
140 145
141 @Override 146 @Override
@@ -144,13 +149,13 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -144,13 +149,13 @@ public class ProductSkuServiceImpl implements ProductSkuService {
144 } 149 }
145 150
146 @Override 151 @Override
147 - public List<ProductSkuDO> getSkusByAlarmStock() { 152 + public List<ProductSkuDO> getSkuListByAlarmStock() {
148 return productSkuMapper.selectListByAlarmStock(); 153 return productSkuMapper.selectListByAlarmStock();
149 } 154 }
150 155
151 @Override 156 @Override
152 @Transactional 157 @Transactional
153 - public void updateSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) { 158 + public void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) {
154 // 查询 SPU 下已经存在的 SKU 的集合 159 // 查询 SPU 下已经存在的 SKU 的集合
155 List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuId(spuId); 160 List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuId(spuId);
156 // 构建属性与 SKU 的映射关系; 161 // 构建属性与 SKU 的映射关系;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
@@ -56,7 +56,7 @@ public interface ProductSpuService { @@ -56,7 +56,7 @@ public interface ProductSpuService {
56 * @param id 编号 56 * @param id 编号
57 * @return 商品 SPU 57 * @return 商品 SPU
58 */ 58 */
59 - ProductSpuRespVO getSpu(Long id); 59 + ProductSpuDO getSpu(Long id);
60 60
61 /** 61 /**
62 * 获得商品 SPU 列表 62 * 获得商品 SPU 列表
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -72,7 +72,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -72,7 +72,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
72 brandService.validateProductBrand(createReqVO.getBrandId()); 72 brandService.validateProductBrand(createReqVO.getBrandId());
73 // 校验SKU 73 // 校验SKU
74 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus(); 74 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();
75 - productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType()); 75 + productSkuService.validateSkuList(skuCreateReqList, createReqVO.getSpecType());
76 // 插入 SPU 76 // 插入 SPU
77 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); 77 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
78 spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); 78 spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
@@ -81,7 +81,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -81,7 +81,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
81 spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); 81 spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
82 productSpuMapper.insert(spu); 82 productSpuMapper.insert(spu);
83 // 插入 SKU 83 // 插入 SKU
84 - productSkuService.createSkus(spu.getId(), spu.getName(), skuCreateReqList); 84 + productSkuService.createSkuList(spu.getId(), spu.getName(), skuCreateReqList);
85 // 返回 85 // 返回
86 return spu.getId(); 86 return spu.getId();
87 } 87 }
@@ -97,7 +97,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -97,7 +97,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
97 brandService.validateProductBrand(updateReqVO.getBrandId()); 97 brandService.validateProductBrand(updateReqVO.getBrandId());
98 // 校验SKU 98 // 校验SKU
99 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus(); 99 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus();
100 - productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType()); 100 + productSkuService.validateSkuList(skuCreateReqList, updateReqVO.getSpecType());
101 101
102 // 更新 SPU 102 // 更新 SPU
103 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); 103 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
@@ -107,7 +107,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -107,7 +107,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
107 updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); 107 updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
108 productSpuMapper.updateById(updateObj); 108 productSpuMapper.updateById(updateObj);
109 // 批量更新 SKU 109 // 批量更新 SKU
110 - productSkuService.updateSkus(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); 110 + productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus());
111 } 111 }
112 112
113 /** 113 /**
@@ -146,7 +146,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -146,7 +146,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
146 ProductSpuDO spu = productSpuMapper.selectById(id); 146 ProductSpuDO spu = productSpuMapper.selectById(id);
147 ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class); 147 ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class);
148 if (null != spu) { 148 if (null != spu) {
149 - List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkusBySpuId(id)); 149 + List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkuListBySpuId(id));
150 respVO.setSkus(skuReqs); 150 respVO.setSkus(skuReqs);
151 // 组合 sku 属性 151 // 组合 sku 属性
152 if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { 152 if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) {
@@ -181,8 +181,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -181,8 +181,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
181 } 181 }
182 182
183 @Override 183 @Override
184 - public ProductSpuRespVO getSpu(Long id) {  
185 - return ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectById(id)); 184 + public ProductSpuDO getSpu(Long id) {
  185 + return productSpuMapper.selectById(id);
186 } 186 }
187 187
188 @Override 188 @Override
@@ -200,7 +200,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -200,7 +200,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
200 // 库存告警的 SPU 编号的集合 200 // 库存告警的 SPU 编号的集合
201 Set<Long> alarmStockSpuIds = null; 201 Set<Long> alarmStockSpuIds = null;
202 if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { 202 if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
203 - alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkusByAlarmStock(), ProductSkuDO::getSpuId); 203 + alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId);
204 if (CollUtil.isEmpty(alarmStockSpuIds)) { 204 if (CollUtil.isEmpty(alarmStockSpuIds)) {
205 return PageResult.empty(); 205 return PageResult.empty();
206 } 206 }
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -186,7 +186,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -186,7 +186,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
186 186
187 }); 187 });
188 188
189 - Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS); 189 + Mockito.when(productSkuService.getSkuListBySpuId(createReqVO.getId())).thenReturn(productSkuDOS);
190 // Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO); 190 // Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);
191 // Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS); 191 // Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);
192 // 192 //
@@ -202,7 +202,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -202,7 +202,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
202 ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class); 202 ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
203 productSpuMapper.insert(createReqVO); 203 productSpuMapper.insert(createReqVO);
204 204
205 - ProductSpuRespVO spu = productSpuService.getSpu(createReqVO.getId()); 205 + ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId());
206 assertPojoEquals(createReqVO, spu); 206 assertPojoEquals(createReqVO, spu);
207 } 207 }
208 208
@@ -267,7 +267,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -267,7 +267,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
267 o.setSpuId(createReqVO.getId()); 267 o.setSpuId(createReqVO.getId());
268 })); 268 }));
269 269
270 - Mockito.when(productSkuService.getSkusByAlarmStock()).thenReturn(productSpuDOS); 270 + Mockito.when(productSkuService.getSkuListByAlarmStock()).thenReturn(productSpuDOS);
271 271
272 // 调用 272 // 调用
273 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); 273 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();