Commit 2113e825d7b085478e8a352e077146f1c4e2581f
1 parent
3ced6a32
完善 App 商品详情逻辑的 10%
Showing
6 changed files
with
50 additions
and
58 deletions
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
| @@ -14,5 +14,5 @@ Authorization: Bearer {{appToken}} | @@ -14,5 +14,5 @@ Authorization: Bearer {{appToken}} | ||
| 14 | tenant-id: {{appTenentId}} | 14 | tenant-id: {{appTenentId}} |
| 15 | 15 | ||
| 16 | ### 获得商品 SPU 明细 | 16 | ### 获得商品 SPU 明细 |
| 17 | -GET {{appApi}}/product/spu/get-detail?id=4 | 17 | +GET {{appApi}}/product/spu/get-detail?id=102 |
| 18 | tenant-id: {{appTenentId}} | 18 | tenant-id: {{appTenentId}} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
| @@ -73,7 +73,7 @@ public class AppProductSpuController { | @@ -73,7 +73,7 @@ public class AppProductSpuController { | ||
| 73 | List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService | 73 | List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService |
| 74 | .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); | 74 | .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); |
| 75 | // 拼接 | 75 | // 拼接 |
| 76 | - return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues)); | 76 | + return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus, propertyValues)); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | } | 79 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
| @@ -18,17 +18,17 @@ public class AppProductSpuDetailRespVO { | @@ -18,17 +18,17 @@ public class AppProductSpuDetailRespVO { | ||
| 18 | @Schema(description = "商品名称", required = true, example = "芋道") | 18 | @Schema(description = "商品名称", required = true, example = "芋道") |
| 19 | private String name; | 19 | private String name; |
| 20 | 20 | ||
| 21 | - @Schema(description = "促销语", example = "好吃!") | ||
| 22 | - private String sellPoint; | ||
| 23 | - | ||
| 24 | @Schema(description = "商品详情", required = true, example = "我是商品描述") | 21 | @Schema(description = "商品详情", required = true, example = "我是商品描述") |
| 25 | private String description; | 22 | private String description; |
| 26 | 23 | ||
| 27 | @Schema(description = "商品分类编号", required = true, example = "1") | 24 | @Schema(description = "商品分类编号", required = true, example = "1") |
| 28 | private Long categoryId; | 25 | private Long categoryId; |
| 29 | 26 | ||
| 30 | - @Schema(description = "商品图片的数组", required = true) | ||
| 31 | - private List<String> picUrls; | 27 | + @Schema(description = "商品封面图", required = true) |
| 28 | + private String picUrl; | ||
| 29 | + | ||
| 30 | + @Schema(description = "商品轮播图", required = true) | ||
| 31 | + private List<String> sliderPicUrls; | ||
| 32 | 32 | ||
| 33 | @Schema(description = "商品视频", required = true) | 33 | @Schema(description = "商品视频", required = true) |
| 34 | private String videoUrl; | 34 | private String videoUrl; |
| @@ -38,14 +38,14 @@ public class AppProductSpuDetailRespVO { | @@ -38,14 +38,14 @@ public class AppProductSpuDetailRespVO { | ||
| 38 | @Schema(description = "规格类型", required = true, example = "true") | 38 | @Schema(description = "规格类型", required = true, example = "true") |
| 39 | private Boolean specType; | 39 | private Boolean specType; |
| 40 | 40 | ||
| 41 | - @Schema(description = "是否展示库存", required = true, example = "true") | ||
| 42 | - private Boolean showStock; | 41 | + @Schema(description = "商品价格,单位使用:分", required = true, example = "1024") |
| 42 | + private Integer price; | ||
| 43 | 43 | ||
| 44 | - @Schema(description = " 最小价格,单位使用:分", required = true, example = "1024") | ||
| 45 | - private Integer minPrice; | 44 | + @Schema(description = "市场价,单位使用:分", required = true, example = "1024") |
| 45 | + private Integer marketPrice; | ||
| 46 | 46 | ||
| 47 | - @Schema(description = "最大价格,单位使用:分", required = true, example = "1024") | ||
| 48 | - private Integer maxPrice; | 47 | + @Schema(description = "库存", required = true, example = "666") |
| 48 | + private Integer stock; | ||
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * SKU 数组 | 51 | * SKU 数组 |
| @@ -72,7 +72,7 @@ public class AppProductSpuDetailRespVO { | @@ -72,7 +72,7 @@ public class AppProductSpuDetailRespVO { | ||
| 72 | @Schema(description = "销售价格,单位:分", required = true, example = "1024") | 72 | @Schema(description = "销售价格,单位:分", required = true, example = "1024") |
| 73 | private Integer price; | 73 | private Integer price; |
| 74 | 74 | ||
| 75 | - @Schema(description = "市场价", example = "1024") | 75 | + @Schema(description = "市场价,单位使用:分", required = true, example = "1024") |
| 76 | private Integer marketPrice; | 76 | private Integer marketPrice; |
| 77 | 77 | ||
| 78 | @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png") | 78 | @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png") |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java
| 1 | package cn.iocoder.yudao.module.product.controller.app.spu.vo; | 1 | package cn.iocoder.yudao.module.product.controller.app.spu.vo; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | ||
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 4 | import lombok.Data; |
| 6 | 5 | ||
| 7 | -import javax.validation.constraints.NotEmpty; | ||
| 8 | -import javax.validation.constraints.NotNull; | ||
| 9 | import java.util.List; | 6 | import java.util.List; |
| 10 | 7 | ||
| 11 | @Schema(description = "用户 App - 商品 SPU 分页项 Response VO") | 8 | @Schema(description = "用户 App - 商品 SPU 分页项 Response VO") |
| @@ -27,17 +24,17 @@ public class AppProductSpuPageItemRespVO { | @@ -27,17 +24,17 @@ public class AppProductSpuPageItemRespVO { | ||
| 27 | @Schema(description = "商品轮播图", required = true) | 24 | @Schema(description = "商品轮播图", required = true) |
| 28 | private List<String> sliderPicUrls; | 25 | private List<String> sliderPicUrls; |
| 29 | 26 | ||
| 27 | + // ========== SKU 相关字段 ========= | ||
| 28 | + | ||
| 30 | @Schema(description = "商品价格,单位使用:分", required = true, example = "1024") | 29 | @Schema(description = "商品价格,单位使用:分", required = true, example = "1024") |
| 31 | private Integer price; | 30 | private Integer price; |
| 32 | 31 | ||
| 33 | - // ========== SKU 相关字段 ========= | ||
| 34 | - | ||
| 35 | @Schema(description = "库存", required = true, example = "666") | 32 | @Schema(description = "库存", required = true, example = "666") |
| 36 | private Integer stock; | 33 | private Integer stock; |
| 37 | 34 | ||
| 38 | // ========== 统计相关字段 ========= | 35 | // ========== 统计相关字段 ========= |
| 39 | 36 | ||
| 40 | - @Schema(description = "商品销量", example = "1024") | 37 | + @Schema(description = "商品销量", required = true, example = "1024") |
| 41 | private Integer salesCount; | 38 | private Integer salesCount; |
| 42 | 39 | ||
| 43 | } | 40 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
| @@ -13,7 +13,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | @@ -13,7 +13,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | ||
| 13 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 13 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 14 | import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | 14 | import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; |
| 15 | import org.mapstruct.Mapper; | 15 | import org.mapstruct.Mapper; |
| 16 | -import org.mapstruct.Named; | ||
| 17 | import org.mapstruct.factory.Mappers; | 16 | import org.mapstruct.factory.Mappers; |
| 18 | 17 | ||
| 19 | import java.util.ArrayList; | 18 | import java.util.ArrayList; |
| @@ -33,48 +32,18 @@ public interface ProductSpuConvert { | @@ -33,48 +32,18 @@ public interface ProductSpuConvert { | ||
| 33 | 32 | ||
| 34 | ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); | 33 | ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); |
| 35 | 34 | ||
| 36 | - ProductSpuDO convert(ProductSpuCreateReqVO bean); | 35 | + ProductSpuDO convertForGetSpuDetail(ProductSpuCreateReqVO bean); |
| 37 | 36 | ||
| 38 | - ProductSpuDO convert(ProductSpuUpdateReqVO bean); | 37 | + ProductSpuDO convertForGetSpuDetail(ProductSpuUpdateReqVO bean); |
| 39 | 38 | ||
| 40 | List<ProductSpuDO> convertList(List<ProductSpuDO> list); | 39 | List<ProductSpuDO> convertList(List<ProductSpuDO> list); |
| 41 | 40 | ||
| 42 | PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page); | 41 | PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page); |
| 43 | 42 | ||
| 44 | - ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean); | ||
| 45 | - | ||
| 46 | List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); | 43 | List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); |
| 47 | 44 | ||
| 48 | List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); | 45 | List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); |
| 49 | 46 | ||
| 50 | - default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus, | ||
| 51 | - List<ProductPropertyValueDetailRespBO> propertyValues) { | ||
| 52 | - AppProductSpuDetailRespVO spuVO = convert02(spu) | ||
| 53 | - .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0)); | ||
| 54 | - spuVO.setSkus(convertList03(skus)); | ||
| 55 | - // 处理商品属性 | ||
| 56 | - Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId); | ||
| 57 | - for (int i = 0; i < skus.size(); i++) { | ||
| 58 | - List<ProductSkuDO.Property> properties = skus.get(i).getProperties(); | ||
| 59 | - if (CollUtil.isEmpty(properties)) { | ||
| 60 | - continue; | ||
| 61 | - } | ||
| 62 | - AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i); | ||
| 63 | - sku.setProperties(new ArrayList<>(properties.size())); | ||
| 64 | - // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中 | ||
| 65 | - properties.forEach(property -> { | ||
| 66 | - ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId()); | ||
| 67 | - if (propertyValue == null) { | ||
| 68 | - return; | ||
| 69 | - } | ||
| 70 | - sku.getProperties().add(convert03(propertyValue)); | ||
| 71 | - }); | ||
| 72 | - } | ||
| 73 | - return spuVO; | ||
| 74 | - } | ||
| 75 | - AppProductSpuDetailRespVO convert02(ProductSpuDO spu); | ||
| 76 | - List<AppProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus); | ||
| 77 | - AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue); | ||
| 78 | 47 | ||
| 79 | default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus, | 48 | default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus, |
| 80 | List<ProductPropertyValueDetailRespBO> propertyValues) { | 49 | List<ProductPropertyValueDetailRespBO> propertyValues) { |
| @@ -114,4 +83,33 @@ public interface ProductSpuConvert { | @@ -114,4 +83,33 @@ public interface ProductSpuConvert { | ||
| 114 | } | 83 | } |
| 115 | PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page); | 84 | PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page); |
| 116 | 85 | ||
| 86 | + default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus, | ||
| 87 | + List<ProductPropertyValueDetailRespBO> propertyValues) { | ||
| 88 | + AppProductSpuDetailRespVO spuVO = convertForGetSpuDetail(spu) | ||
| 89 | + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0)); | ||
| 90 | + spuVO.setSkus(convertListForGetSpuDetail(skus)); | ||
| 91 | + // 处理商品属性 | ||
| 92 | + Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId); | ||
| 93 | + for (int i = 0; i < skus.size(); i++) { | ||
| 94 | + List<ProductSkuDO.Property> properties = skus.get(i).getProperties(); | ||
| 95 | + if (CollUtil.isEmpty(properties)) { | ||
| 96 | + continue; | ||
| 97 | + } | ||
| 98 | + AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i); | ||
| 99 | + sku.setProperties(new ArrayList<>(properties.size())); | ||
| 100 | + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中 | ||
| 101 | + properties.forEach(property -> { | ||
| 102 | + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId()); | ||
| 103 | + if (propertyValue == null) { | ||
| 104 | + return; | ||
| 105 | + } | ||
| 106 | + sku.getProperties().add(convertForGetSpuDetail(propertyValue)); | ||
| 107 | + }); | ||
| 108 | + } | ||
| 109 | + return spuVO; | ||
| 110 | + } | ||
| 111 | + AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu); | ||
| 112 | + List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus); | ||
| 113 | + AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue); | ||
| 114 | + | ||
| 117 | } | 115 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| 1 | package cn.iocoder.yudao.module.product.service.spu; | 1 | package cn.iocoder.yudao.module.product.service.spu; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.util.NumberUtil; | ||
| 5 | -import cn.hutool.core.util.ObjUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 9 | -import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 10 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; |
| 11 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| 12 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; | 9 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; |
| @@ -66,7 +63,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -66,7 +63,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 66 | productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); | 63 | productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); |
| 67 | 64 | ||
| 68 | // 插入 SPU | 65 | // 插入 SPU |
| 69 | - ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); | 66 | + ProductSpuDO spu = ProductSpuConvert.INSTANCE.convertForGetSpuDetail(createReqVO); |
| 70 | initSpuFromSkus(spu, skuSaveReqList); | 67 | initSpuFromSkus(spu, skuSaveReqList); |
| 71 | productSpuMapper.insert(spu); | 68 | productSpuMapper.insert(spu); |
| 72 | // 插入 SKU | 69 | // 插入 SKU |
| @@ -89,7 +86,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -89,7 +86,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 89 | productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); | 86 | productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); |
| 90 | 87 | ||
| 91 | // 更新 SPU | 88 | // 更新 SPU |
| 92 | - ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); | 89 | + ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convertForGetSpuDetail(updateReqVO); |
| 93 | initSpuFromSkus(updateObj, skuSaveReqList); | 90 | initSpuFromSkus(updateObj, skuSaveReqList); |
| 94 | productSpuMapper.updateById(updateObj); | 91 | productSpuMapper.updateById(updateObj); |
| 95 | // 批量更新 SKU | 92 | // 批量更新 SKU |