mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-30 09:48:43 +08:00 
			
		
		
		
	feature(商品添加): 规格调整连带商品调整
This commit is contained in:
		| @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; | ||||
| import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; | ||||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiImplicitParam; | ||||
| @@ -17,6 +14,8 @@ import org.springframework.web.bind.annotation.*; | ||||
| import javax.annotation.Resource; | ||||
| import javax.validation.Valid; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
|  | ||||
| @Api(tags = "管理后台 - 规格名称") | ||||
| @@ -56,15 +55,29 @@ public class ProductPropertyController { | ||||
|     @ApiOperation("获得规格名称") | ||||
|     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<ProductPropertyAndValueRespVO> getProperty(@RequestParam("id") Long id) { | ||||
|     public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) { | ||||
|         return success(productPropertyService.getPropertyResp(id)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/list") | ||||
|     @ApiOperation("获得规格名称列表") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) { | ||||
|         return success(productPropertyService.getPropertyList(listReqVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/page") | ||||
|     @ApiOperation("获得规格名称分页") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<PageResult<ProductPropertyAndValueRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { | ||||
|         return success(productPropertyService.getPropertyListPage(pageVO)); | ||||
|     public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { | ||||
|         return success(productPropertyService.getPropertyPage(pageVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/listAndValue") | ||||
|     @ApiOperation("获得规格名称列表") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) { | ||||
|         return success(productPropertyService.getPropertyAndValueList(listReqVO)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,70 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | ||||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiImplicitParam; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.validation.Valid; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
|  | ||||
| @Api(tags = "管理后台 - 规格值名称") | ||||
| @RestController | ||||
| @RequestMapping("/product/property/value") | ||||
| @Validated | ||||
| public class ProductPropertyValueController { | ||||
|  | ||||
|     @Resource | ||||
|     private ProductPropertyValueService productPropertyValueService; | ||||
|  | ||||
|     @PostMapping("/create") | ||||
|     @ApiOperation("创建规格名称") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:create')") | ||||
|     public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) { | ||||
|         return success(productPropertyValueService.createPropertyValue(createReqVO)); | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/update") | ||||
|     @ApiOperation("更新规格名称") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:update')") | ||||
|     public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) { | ||||
|         productPropertyValueService.updatePropertyValue(updateReqVO); | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping("/delete") | ||||
|     @ApiOperation("删除规格名称") | ||||
|     @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:delete')") | ||||
|     public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) { | ||||
|         productPropertyValueService.deletePropertyValue(id); | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get") | ||||
|     @ApiOperation("获得规格名称") | ||||
|     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) { | ||||
|         return success(productPropertyValueService.getPropertyValue(id)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/page") | ||||
|     @ApiOperation("获得规格名称分页") | ||||
|     @PreAuthorize("@ss.hasPermission('product:property:query')") | ||||
|     public CommonResult<PageResult<ProductPropertyValueRespVO>> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) { | ||||
|         return success(productPropertyValueService.getPropertyValueListPage(pageVO)); | ||||
|     } | ||||
| } | ||||
| @@ -3,21 +3,25 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | ||||
|  | ||||
| import javax.validation.constraints.NotEmpty; | ||||
| import javax.validation.constraints.NotBlank; | ||||
| import javax.validation.constraints.NotNull; | ||||
|  | ||||
| /** | ||||
| * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用 | ||||
| * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||||
| */ | ||||
|  * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用 | ||||
|  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||||
|  */ | ||||
| @Data | ||||
| public class ProductPropertyBaseVO { | ||||
|  | ||||
|     @ApiModelProperty(value = "规格名称", required = true, example = "颜色") | ||||
|     @NotEmpty(message = "规格名称不能为空") | ||||
|     @NotBlank(message = "规格名称不能为空") | ||||
|     private String name; | ||||
|  | ||||
|     @ApiModelProperty(value = "备注", example = "颜色") | ||||
|     private String remark; | ||||
|  | ||||
|     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") | ||||
|     @NotEmpty(message = "状态不能为空") | ||||
|     @NotNull(message = "状态不能为空") | ||||
|     private Integer status; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; | ||||
|  | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | ||||
| import lombok.*; | ||||
| import io.swagger.annotations.*; | ||||
|  | ||||
| import javax.validation.constraints.NotNull; | ||||
| import java.util.List; | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| @ApiModel("管理后台 - 规格名称创建 Request VO") | ||||
| @Data | ||||
| @@ -13,9 +11,5 @@ import java.util.List; | ||||
| @ToString(callSuper = true) | ||||
| public class ProductPropertyCreateReqVO extends ProductPropertyBaseVO { | ||||
|  | ||||
|     // TODO @Luowenfeng:规格值的 CRUD 可以单独;前端 + 后端,改成类似字典类型、字典数据的这种交互;在加一个 ProductPropertyValueController | ||||
|     @ApiModelProperty(value = "属性值") | ||||
|     @NotNull(message = "属性值不能为空") | ||||
|     List<ProductPropertyValueCreateReqVO> propertyValueList; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,19 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; | ||||
|  | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | ||||
| import lombok.ToString; | ||||
|  | ||||
| @ApiModel("管理后台 - 规格名称 List Request VO") | ||||
| @Data | ||||
| @ToString(callSuper = true) | ||||
| public class ProductPropertyListReqVO { | ||||
|  | ||||
|     @ApiModelProperty(value = "规格名称", example = "颜色") | ||||
|     private String name; | ||||
|  | ||||
|     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") | ||||
|     private Integer status; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,24 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; | ||||
|  | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.util.Date; | ||||
|  | ||||
| @ApiModel("管理后台 - 规格 + 规格值 Response VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class ProductPropertyRespVO extends ProductPropertyBaseVO { | ||||
|  | ||||
|     @ApiModelProperty(value = "规格的编号", required = true, example = "1024") | ||||
|     private Long id; | ||||
|  | ||||
|     @ApiModelProperty(value = "创建时间", required = true) | ||||
|     private Date createTime; | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -16,8 +16,4 @@ public class ProductPropertyUpdateReqVO extends ProductPropertyBaseVO { | ||||
|     @NotNull(message = "主键不能为空") | ||||
|     private Long id; | ||||
|  | ||||
|     @ApiModelProperty(value = "属性值") | ||||
|     @NotNull(message = "属性值不能为空") | ||||
|     List<ProductPropertyValueCreateReqVO> propertyValueList; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,9 @@ public class ProductPropertyValueBaseVO { | ||||
|     private String name; | ||||
|  | ||||
|     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") | ||||
|     @NotEmpty(message = "状态不能为空") | ||||
|     @NotNull(message = "状态不能为空") | ||||
|     private Integer status; | ||||
|  | ||||
|     @ApiModelProperty(value = "备注", example = "颜色") | ||||
|     private String remark; | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
| import org.springframework.format.annotation.DateTimeFormat; | ||||
|  | ||||
| import javax.validation.constraints.NotEmpty; | ||||
| import java.util.Date; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||||
|  | ||||
| @ApiModel("管理后台 - 规格名称值分页 Request VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class ProductPropertyValuePageReqVO extends PageParam { | ||||
|  | ||||
|     @ApiModelProperty(value = "规格id", example = "1024") | ||||
|     private String propertyId; | ||||
|  | ||||
|     @ApiModelProperty(value = "规格值", example = "红色") | ||||
|     private String name; | ||||
|  | ||||
|     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") | ||||
|     private Integer status; | ||||
|  | ||||
| } | ||||
| @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.spu; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; | ||||
| 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.ProductSpuPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | ||||
| import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | ||||
| import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | ||||
| @@ -56,6 +53,14 @@ public class ProductSpuController { | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get/detail") | ||||
|     @ApiOperation("获得商品 SPU") | ||||
|     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||||
|     @PreAuthorize("@ss.hasPermission('product:spu:query')") | ||||
|     public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) { | ||||
|         return success(spuService.getSpuDetail(id)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get") | ||||
|     @ApiOperation("获得商品 SPU") | ||||
|     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) | ||||
| @@ -64,7 +69,6 @@ public class ProductSpuController { | ||||
|         return success(spuService.getSpu(id)); | ||||
|     } | ||||
|  | ||||
|     // TODO @luowenfeng:新增 get-detail,返回 SpuDetailRespVO | ||||
|  | ||||
|     @GetMapping("/list") | ||||
|     @ApiOperation("获得商品 SPU 列表") | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| 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.sku.ProductSkuDO; | ||||
| import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; | ||||
| import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| @@ -67,6 +68,9 @@ public class ProductSpuBaseVO { | ||||
|     @ApiModelProperty(value = "库存", required = true, example = "true") | ||||
|     private Integer totalStock; | ||||
|  | ||||
|     @ApiModelProperty(value = "市场价", example = "1024") | ||||
|     private Integer marketPrice; | ||||
|  | ||||
|     @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") | ||||
|     private Integer minPrice; | ||||
|  | ||||
| @@ -75,10 +79,14 @@ public class ProductSpuBaseVO { | ||||
|  | ||||
|     // ========== 统计相关字段 ========= | ||||
|  | ||||
|     @ApiModelProperty(value = "商品销量", example = "1024") | ||||
|     private Integer salesCount; | ||||
|  | ||||
|     @ApiModelProperty(value = "虚拟销量", required = true, example = "1024") | ||||
|     @NotNull(message = "虚拟销量不能为空") | ||||
|     private Integer virtualSalesCount; | ||||
|  | ||||
|     @ApiModelProperty(value = "点击量", example = "1024") | ||||
|     private Integer clickCount; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.spu.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| @@ -54,4 +55,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]") | ||||
|     private List<Long> categoryIds; | ||||
|  | ||||
|     @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]") | ||||
|     private List<ProductPropertyViewRespVO> productPropertyViews; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -17,35 +17,16 @@ public class ProductSpuPageReqVO extends PageParam { | ||||
|     @ApiModelProperty(value = "商品名称") | ||||
|     private String name; | ||||
|  | ||||
|     @ApiModelProperty(value = "卖点") | ||||
|     private String sellPoint; | ||||
|  | ||||
|     @ApiModelProperty(value = "描述") | ||||
|     private String description; | ||||
|     @ApiModelProperty(value = "商品编码", example = "yudaoyuanma") | ||||
|     private String code; | ||||
|  | ||||
|     @ApiModelProperty(value = "分类id") | ||||
|     private Long categoryId; | ||||
|  | ||||
|     @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张") | ||||
|     private String picUrls; | ||||
|  | ||||
|     @ApiModelProperty(value = "排序字段") | ||||
|     private Integer sort; | ||||
|  | ||||
|     @ApiModelProperty(value = "点赞初始人数") | ||||
|     private Integer likeCount; | ||||
|  | ||||
|     @ApiModelProperty(value = "价格 单位使用:分") | ||||
|     private Integer price; | ||||
|  | ||||
|     @ApiModelProperty(value = "库存数量") | ||||
|     private Integer quantity; | ||||
|     @ApiModelProperty(value = "商品品牌编号", example = "1") | ||||
|     private Long brandId; | ||||
|  | ||||
|     @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)") | ||||
|     private Integer status; | ||||
|  | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     @ApiModelProperty(value = "创建时间") | ||||
|     private Date[] createTime; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| package cn.iocoder.yudao.module.product.controller.admin.spu.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; | ||||
| import io.swagger.annotations.ApiModel; | ||||
| import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | ||||
| @@ -9,9 +7,7 @@ import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| // TODO @Luowenfeng:这个类只返回 SPU 相关的信息,删除 skus、categoryIds、productPropertyViews;明细使用 SpuDetailRespVO 替代 | ||||
| @ApiModel("管理后台 - 商品 SPU Response VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @@ -24,18 +20,4 @@ public class ProductSpuRespVO extends ProductSpuBaseVO { | ||||
|     @ApiModelProperty(value = "创建时间") | ||||
|     private Date createTime; | ||||
|  | ||||
|     /** | ||||
|      * SKU 数组 | ||||
|      */ | ||||
|     @ApiModelProperty(value = "sku 数组", example = "[{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":10}],\"price\":12,\"originalPrice\":32,\"costPrice\":22,\"barCode\":\"765670123123\",\"picUrl\":\"http://test.yudao.iocoder.cn/72938088f1ca8438837c3b51394aea43.jpg\",\"status\":0,\"id\":7,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":11}],\"price\":13,\"originalPrice\":33,\"costPrice\":23,\"barCode\":\"888788770999\",\"picUrl\":\"http://test.yudao.iocoder.cn/6b902c700e5d32e862b6fd9af2e1c0e4.jpg\",\"status\":0,\"id\":8,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":10}],\"price\":14,\"originalPrice\":34,\"costPrice\":24,\"barCode\":\"9999981212\",\"picUrl\":\"http://test.yudao.iocoder.cn/eddf3c79b1917160d94d05244e1f47da.jpg\",\"status\":0,\"id\":9,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":11}],\"price\":15,\"originalPrice\":35,\"costPrice\":25,\"barCode\":\"4444121212\",\"picUrl\":\"http://test.yudao.iocoder.cn/88ac3eb068ea9cfac4726879b2776ccf.jpg\",\"status\":0,\"id\":10,\"createTime\":1656683270000}]") | ||||
|     private List<ProductSkuRespVO> skus; | ||||
|  | ||||
|     @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]") | ||||
|     private List<Long> categoryIds; | ||||
|  | ||||
|     // TODO @芋艿:再琢磨下 这个 VO 类,其实变成 SpuRespVO 内嵌的 VO 类会更好一点;然后把 SpuRespVO 改成 SpuDetailSpuVO | ||||
|  | ||||
|     @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]") | ||||
|     private List<ProductPropertyViewRespVO> productPropertyViews; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package cn.iocoder.yudao.module.product.convert.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | ||||
| import org.mapstruct.Mapper; | ||||
| @@ -24,10 +24,10 @@ public interface ProductPropertyConvert { | ||||
|  | ||||
|     ProductPropertyDO convert(ProductPropertyUpdateReqVO bean); | ||||
|  | ||||
|     ProductPropertyAndValueRespVO convert(ProductPropertyDO bean); | ||||
|     ProductPropertyRespVO convert(ProductPropertyDO bean); | ||||
|  | ||||
|     List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> list); | ||||
|     List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list); | ||||
|  | ||||
|     PageResult<ProductPropertyAndValueRespVO> convertPage(PageResult<ProductPropertyDO> page); | ||||
|     PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.convert.sku; | ||||
| import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | ||||
| 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.ProductSpuDetailRespVO; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.factory.Mappers; | ||||
| @@ -31,4 +32,6 @@ public interface ProductSkuConvert { | ||||
|  | ||||
|     List<ProductSkuRespDTO> convertList02(List<ProductSkuDO> list); | ||||
|  | ||||
|     List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,6 +37,10 @@ public class ProductPropertyDO extends BaseDO { | ||||
|      * 枚举 {@link CommonStatusEnum} | ||||
|      */ | ||||
|     private Integer status; | ||||
|     /** | ||||
|      * 备注 | ||||
|      */ | ||||
|     private String remark; | ||||
|  | ||||
|     // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索) | ||||
|  | ||||
|   | ||||
| @@ -44,5 +44,10 @@ public class ProductPropertyValueDO extends BaseDO { | ||||
|      * 枚举 {@link CommonStatusEnum} | ||||
|      */ | ||||
|     private Integer status; | ||||
|     /** | ||||
|      * 备注 | ||||
|      * | ||||
|      */ | ||||
|     private String remark; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| package cn.iocoder.yudao.module.product.dal.mysql.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @@ -16,17 +18,25 @@ import java.util.List; | ||||
| public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> { | ||||
|  | ||||
|     // TODO @franky:方法名,selectListByXXX。mapper 的操作都是 crud | ||||
|     default List<ProductPropertyValueDO> getPropertyValueListByPropertyId(List<Long> propertyIds){ | ||||
|     default List<ProductPropertyValueDO> getPropertyValueListByPropertyId(List<Long> propertyIds) { | ||||
|         // TODO @franky:调用父类的 selectList | ||||
|         return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>() | ||||
|                 .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds)); | ||||
|     } | ||||
|  | ||||
|     default void deletePropertyValueByPropertyId(Long propertyId){ | ||||
|     default void deletePropertyValueByPropertyId(Long propertyId) { | ||||
|         // TODO @franky:delete(new ) 即可 | ||||
|         LambdaQueryWrapperX<ProductPropertyValueDO> queryWrapperX = new LambdaQueryWrapperX<>(); | ||||
|         queryWrapperX.eq(ProductPropertyValueDO::getPropertyId, propertyId) | ||||
|                 .eq(ProductPropertyValueDO::getDeleted, false); | ||||
|         delete(queryWrapperX); | ||||
|     } | ||||
|  | ||||
|     default PageResult<ProductPropertyValueDO> selectPage(ProductPropertyValuePageReqVO reqVO) { | ||||
|         return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyValueDO>() | ||||
|                 .eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId()) | ||||
|                 .likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName()) | ||||
|                 .eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus()) | ||||
|                 .orderByDesc(ProductPropertyValueDO::getId)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -18,11 +18,8 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> { | ||||
|     default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) { | ||||
|         return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>() | ||||
|                 .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) | ||||
|                 .eqIfPresent(ProductSpuDO::getSellPoint, reqVO.getSellPoint()) | ||||
|                 .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) | ||||
|                 .eqIfPresent(ProductSpuDO::getPicUrls, reqVO.getPicUrls()) | ||||
|                 .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) | ||||
|                 .betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime()) | ||||
|                 .orderByDesc(ProductSpuDO::getSort)); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.product.service.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | ||||
|  | ||||
| @@ -48,35 +48,35 @@ public interface ProductPropertyService { | ||||
|  | ||||
|     /** | ||||
|      * 获得规格名称列表 | ||||
|      * | ||||
|      * @param ids 编号 | ||||
|      * @return 规格名称列表 | ||||
|      * @param listReqVO 集合查询 | ||||
|      * @return 规格名称集合 | ||||
|      */ | ||||
|     List<ProductPropertyDO> getPropertyList(Collection<Long> ids); | ||||
|  | ||||
|     /** | ||||
|      * 获得规格名称分页 | ||||
|      * | ||||
|      * @param pageReqVO 分页查询 | ||||
|      * @return 规格名称分页 | ||||
|      */ | ||||
|     PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO); | ||||
|     List<ProductPropertyRespVO> getPropertyList(ProductPropertyListReqVO listReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获取属性及属性值列表 分页 | ||||
|      * @param pageReqVO | ||||
|      * @return | ||||
|      */ | ||||
|     PageResult<ProductPropertyAndValueRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO); | ||||
|     PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO); | ||||
|  | ||||
|     ProductPropertyAndValueRespVO getPropertyResp(Long id); | ||||
|  | ||||
|     ProductPropertyRespVO getPropertyResp(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合 | ||||
|      * | ||||
|      * @param ids 规格编号的集合 | ||||
|      * @return 对应的规格 + 规格值的集合 | ||||
|      * @return 对应的规格 | ||||
|      */ | ||||
|     List<ProductPropertyAndValueRespVO> getPropertyAndValueList(Collection<Long> ids); | ||||
|     List<ProductPropertyRespVO> getPropertyList(Collection<Long> ids); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 获得规格名称列表 | ||||
|      * @param listReqVO 集合查询 | ||||
|      * @return 规格名称集合 | ||||
|      */ | ||||
|     List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| package cn.iocoder.yudao.module.product.service.property; | ||||
|  | ||||
| import cn.hutool.core.bean.BeanUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| @@ -46,12 +49,6 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | ||||
|         // 插入 | ||||
|         ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO); | ||||
|         productPropertyMapper.insert(property); | ||||
|  | ||||
|         //插入属性值 | ||||
|         List<ProductPropertyValueCreateReqVO> propertyValueList = createReqVO.getPropertyValueList(); | ||||
|         List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); | ||||
|         productPropertyValueDOList.forEach(x-> x.setPropertyId(property.getId())); | ||||
|         productPropertyValueMapper.insertBatch(productPropertyValueDOList); | ||||
|         // 返回 | ||||
|         return property.getId(); | ||||
|     } | ||||
| @@ -64,12 +61,6 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | ||||
|         // 更新 | ||||
|         ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO); | ||||
|         productPropertyMapper.updateById(updateObj); | ||||
|         //更新属性值,先删后加 | ||||
|         productPropertyValueMapper.deletePropertyValueByPropertyId(updateReqVO.getId()); | ||||
|         List<ProductPropertyValueCreateReqVO> propertyValueList = updateReqVO.getPropertyValueList(); | ||||
|         List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); | ||||
|         productPropertyValueDOList.forEach(x-> x.setPropertyId(updateReqVO.getId())); | ||||
|         productPropertyValueMapper.insertBatch(productPropertyValueDOList); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -94,31 +85,28 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<ProductPropertyDO> getPropertyList(Collection<Long> ids) { | ||||
|         return productPropertyMapper.selectBatchIds(ids); | ||||
|     public List<ProductPropertyRespVO> getPropertyList(ProductPropertyListReqVO listReqVO) { | ||||
|         return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectList(new LambdaQueryWrapperX<ProductPropertyDO>() | ||||
|                 .likeIfPresent(ProductPropertyDO::getName, listReqVO.getName()) | ||||
|                 .eqIfPresent(ProductPropertyDO::getStatus, listReqVO.getStatus()))); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) { | ||||
|         return productPropertyMapper.selectPage(pageReqVO); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<ProductPropertyAndValueRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO) { | ||||
|     public PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) { | ||||
|         //获取属性列表 | ||||
|         PageResult<ProductPropertyDO> pageResult = productPropertyMapper.selectPage(pageReqVO); | ||||
|         PageResult<ProductPropertyAndValueRespVO> propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); | ||||
|         List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyAndValueRespVO::getId).collect(Collectors.toList()); | ||||
|  | ||||
|         //获取属性值列表 | ||||
|         List<ProductPropertyValueDO> productPropertyValueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); | ||||
|         List<ProductPropertyValueRespVO> propertyValueRespVOList = ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueDOList); | ||||
|         //组装一对多 | ||||
|         propertyRespVOPageResult.getList().forEach(x->{ | ||||
|             Long propertyId = x.getId(); | ||||
|             List<ProductPropertyValueRespVO> valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); | ||||
|             x.setValues(valueDOList); | ||||
|         }); | ||||
|         PageResult<ProductPropertyRespVO> propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); | ||||
| //        List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyAndValueRespVO::getId).collect(Collectors.toList()); | ||||
| // | ||||
| //        //获取属性值列表 | ||||
| //        List<ProductPropertyValueDO> productPropertyValueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); | ||||
| //        List<ProductPropertyValueRespVO> propertyValueRespVOList = ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueDOList); | ||||
| //        //组装一对多 | ||||
| //        propertyRespVOPageResult.getList().forEach(x->{ | ||||
| //            Long propertyId = x.getId(); | ||||
| //            List<ProductPropertyValueRespVO> valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); | ||||
| //            x.setValues(valueDOList); | ||||
| //        }); | ||||
|         return propertyRespVOPageResult; | ||||
|     } | ||||
|  | ||||
| @@ -127,25 +115,31 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ProductPropertyAndValueRespVO getPropertyResp(Long id) { | ||||
|     public ProductPropertyRespVO getPropertyResp(Long id) { | ||||
|         //查询规格 | ||||
|         ProductPropertyDO property = getProperty(id); | ||||
|         ProductPropertyAndValueRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property); | ||||
|         //查询属性值 | ||||
|         List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(Arrays.asList(id)); | ||||
|         List<ProductPropertyValueRespVO> propertyValueRespVOS = ProductPropertyValueConvert.INSTANCE.convertList(valueDOList); | ||||
|         //组装 | ||||
|         propertyRespVO.setValues(propertyValueRespVOS); | ||||
|         return propertyRespVO; | ||||
|         return ProductPropertyConvert.INSTANCE.convert(property); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<ProductPropertyAndValueRespVO> getPropertyAndValueList(Collection<Long> ids) { | ||||
|         List<ProductPropertyAndValueRespVO> productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids)); | ||||
|     public List<ProductPropertyRespVO> getPropertyList(Collection<Long> ids) { | ||||
|         return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO) { | ||||
|         List<ProductPropertyRespVO> propertyList = getPropertyList(listReqVO); | ||||
|  | ||||
|         //查询属性值 | ||||
|         List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.selectBatchIds(ids); | ||||
|         Map<Long, List<ProductPropertyValueDO>> propertyValuesMap = valueDOList.stream().collect(Collectors.groupingBy(ProductPropertyValueDO::getPropertyId)); | ||||
|         productPropertyRespVO.forEach(p -> p.setValues(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId())))); | ||||
|         return productPropertyRespVO; | ||||
|         List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(CollectionUtils.convertList(propertyList, ProductPropertyRespVO::getId)); | ||||
|         Map<Long, List<ProductPropertyValueRespVO>> valueDOMap = valueDOList.stream() | ||||
|                 .map(ProductPropertyValueConvert.INSTANCE::convert) | ||||
|                 .collect(Collectors.groupingBy(ProductPropertyValueRespVO::getPropertyId)); | ||||
|         //组装 | ||||
|         return propertyList.stream().map(m -> { | ||||
|             ProductPropertyAndValueRespVO productPropertyAndValueRespVO = BeanUtil.copyProperties(m, ProductPropertyAndValueRespVO.class); | ||||
|             productPropertyAndValueRespVO.setValues(valueDOMap.get(m.getId())); | ||||
|             return productPropertyAndValueRespVO; | ||||
|         }).collect(Collectors.toList()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,65 @@ | ||||
| package cn.iocoder.yudao.module.product.service.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  * | ||||
|  * </p> | ||||
|  * | ||||
|  * @author LuoWenFeng | ||||
|  */ | ||||
| public interface ProductPropertyValueService { | ||||
|  | ||||
|     /** | ||||
|      * 创建规格值 | ||||
|      * | ||||
|      * @param createReqVO 创建信息 | ||||
|      * @return 编号 | ||||
|      */ | ||||
|     Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 更新规格值 | ||||
|      * | ||||
|      * @param updateReqVO 更新信息 | ||||
|      */ | ||||
|     void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 删除规格值 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      */ | ||||
|     void deletePropertyValue(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得规格值 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      * @return 规格名称 | ||||
|      */ | ||||
|     ProductPropertyValueRespVO getPropertyValue(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得规格值 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      * @return 规格名称 | ||||
|      */ | ||||
|     List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id); | ||||
|  | ||||
|     /** | ||||
|      * 获取规格值 分页 | ||||
|      * | ||||
|      * @param pageReqVO 查询条件 | ||||
|      * @return | ||||
|      */ | ||||
|     PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO); | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| package cn.iocoder.yudao.module.product.service.property; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; | ||||
| import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * <p> | ||||
|  * | ||||
|  * </p> | ||||
|  * | ||||
|  * @author LuoWenFeng | ||||
|  */ | ||||
| @Service | ||||
| @Validated | ||||
| public class ProductPropertyValueServiceImpl implements ProductPropertyValueService { | ||||
|  | ||||
|     @Resource | ||||
|     private ProductPropertyValueMapper productPropertyValueMapper; | ||||
|  | ||||
|     @Override | ||||
|     public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) { | ||||
|         ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(createReqVO); | ||||
|         productPropertyValueMapper.insert(convert); | ||||
|         return convert.getId(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO) { | ||||
|         ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); | ||||
|         productPropertyValueMapper.updateById(convert); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void deletePropertyValue(Long id) { | ||||
|         productPropertyValueMapper.deleteById(id); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ProductPropertyValueRespVO getPropertyValue(Long id) { | ||||
|         ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectOne(new LambdaQueryWrapper<ProductPropertyValueDO>() | ||||
|                 .eq(ProductPropertyValueDO::getId, id)); | ||||
|         return ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueDO); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id) { | ||||
|         return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", id)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO) { | ||||
|         return ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueMapper.selectPage(pageReqVO)); | ||||
|     } | ||||
| } | ||||
| @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku; | ||||
| import cn.hutool.core.collection.CollectionUtil; | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; | ||||
| @@ -13,6 +13,7 @@ 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 org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -39,6 +40,9 @@ public class ProductSkuServiceImpl implements ProductSkuService { | ||||
|     @Resource | ||||
|     private ProductPropertyService productPropertyService; | ||||
|  | ||||
|     @Resource | ||||
|     private ProductPropertyValueService productPropertyValueService; | ||||
|  | ||||
|     @Override | ||||
|     public void deleteSku(Long id) { | ||||
|         // 校验存在 | ||||
| @@ -71,17 +75,15 @@ public class ProductSkuServiceImpl implements ProductSkuService { | ||||
|         } | ||||
|  | ||||
|         // 1、校验规格属性存在 | ||||
|         // TODO @Luowenfeng:stream 的写法;不用改哈,就是说下可以酱紫写; | ||||
|         Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 | ||||
|                 .map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合 | ||||
|         List<ProductPropertyAndValueRespVO> propertyAndValueList = productPropertyService.getPropertyAndValueList(propertyIds); | ||||
|         if (propertyAndValueList.size() == propertyIds.size()) { | ||||
|         List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyList(propertyIds); | ||||
|         if (propertyList.size() != propertyIds.size()) { | ||||
|             throw exception(PROPERTY_NOT_EXISTS); | ||||
|         } | ||||
|  | ||||
|         // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId | ||||
|         Map<Long, ProductPropertyValueRespVO> propertyValueMap = propertyAndValueList.stream().filter(p -> p.getValues() != null).flatMap(p -> p.getValues().stream()) | ||||
|                 .collect(Collectors.toMap(ProductPropertyValueRespVO::getId, value -> value)); // KEY:规格属性值的编号 | ||||
|         Map<Long, ProductPropertyValueRespVO> propertyValueMap = CollectionUtils.convertMap(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyIds)), ProductPropertyValueRespVO::getId); | ||||
|         skus.forEach(sku -> { | ||||
|             Set<Long> skuPropertyIds = CollectionUtils.convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); | ||||
|             if (skuPropertyIds.size() != sku.getProperties().size()) { | ||||
| @@ -100,8 +102,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { | ||||
|         // 4. 最后校验,每个 Sku 之间不是重复的 | ||||
|         Set<Set<Long>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. | ||||
|         for (ProductSkuCreateOrUpdateReqVO sku : skus) { | ||||
|             // TODO @Luowenfeng:可以使用 CollectionUtils.convertSet(),简化下面的 stream 操作 | ||||
|             if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复 | ||||
|             if (!skuAttrValues.add(CollectionUtils.convertSet(sku.getProperties(), ProductSkuBaseVO.Property::getValueId))) { // 添加失败,说明重复 | ||||
|                 throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,10 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.product.service.spu; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; | ||||
| 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.ProductSpuPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | ||||
| import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||||
| import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | ||||
| @@ -42,6 +39,14 @@ public interface ProductSpuService { | ||||
|      */ | ||||
|     void deleteSpu(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得商品spu详情 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      * @return 商品spu | ||||
|      */ | ||||
|     ProductSpuDetailRespVO getSpuDetail(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得商品spu | ||||
|      * | ||||
|   | ||||
| @@ -1,17 +1,15 @@ | ||||
| package cn.iocoder.yudao.module.product.service.spu; | ||||
|  | ||||
| import cn.hutool.core.bean.BeanUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | ||||
| import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | ||||
| 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.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.AppSpuPageReqVO; | ||||
| import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||||
| import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | ||||
| @@ -22,6 +20,7 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; | ||||
| 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.ProductPropertyService; | ||||
| import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | ||||
| import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| @@ -55,6 +54,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||||
|     @Resource | ||||
|     private ProductPropertyService productPropertyService; | ||||
|  | ||||
|     @Resource | ||||
|     private ProductPropertyValueService productPropertyValueService; | ||||
|  | ||||
|     @Resource | ||||
|     private ProductBrandService brandService; | ||||
|  | ||||
| @@ -125,28 +127,31 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||||
|  | ||||
|     @Override | ||||
|     // TODO @芋艿:需要再 review 下 | ||||
|     public ProductSpuRespVO getSpu(Long id) { | ||||
|     public ProductSpuDetailRespVO getSpuDetail(Long id) { | ||||
|         ProductSpuDO spu = ProductSpuMapper.selectById(id); | ||||
|         ProductSpuRespVO spuVO = ProductSpuConvert.INSTANCE.convert(spu); | ||||
|         if (null != spuVO) { | ||||
|             List<ProductSkuRespVO> skuReqs = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuId(id)); | ||||
|             spuVO.setSkus(skuReqs); | ||||
|             List<ProductSkuRespVO.Property> properties = new ArrayList<>(); | ||||
|         ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class); | ||||
|         if (null != spu) { | ||||
|             List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkusBySpuId(id)); | ||||
|             respVO.setSkus(skuReqs); | ||||
|             // 组合 sku 规格属性 | ||||
|             if(spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { | ||||
|                 for (ProductSkuRespVO productSkuRespVO : skuReqs) { | ||||
|                 List<ProductSkuRespVO.Property> properties = new ArrayList<>(); | ||||
|                 for (ProductSpuDetailRespVO.Sku productSkuRespVO : skuReqs) { | ||||
|                     properties.addAll(productSkuRespVO.getProperties()); | ||||
|                 } | ||||
|                 Map<Long, List<ProductSkuBaseVO.Property>> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId)); | ||||
|                 List<ProductPropertyAndValueRespVO> propertyAndValueList = productPropertyService.getPropertyAndValueList(new ArrayList<>(propertyMaps.keySet())); | ||||
|  | ||||
|                 List<ProductPropertyValueRespVO> propertyValueList = productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyMaps.keySet())); | ||||
|                 List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyList(new ArrayList<>(propertyMaps.keySet())); | ||||
|                 // 装载组装过后的属性 | ||||
|                 List<ProductPropertyViewRespVO> productPropertyViews = new ArrayList<>(); | ||||
|                 propertyAndValueList.forEach(p -> { | ||||
|                 propertyList.forEach(p -> { | ||||
|                     ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO(); | ||||
|                     productPropertyViewRespVO.setPropertyId(p.getId()); | ||||
|                     productPropertyViewRespVO.setName(p.getName()); | ||||
|                     List<ProductPropertyViewRespVO.Tuple2> propertyValues = new ArrayList<>(); | ||||
|                     Map<Long, ProductPropertyValueRespVO> propertyValueMaps = p.getValues().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv)); | ||||
|                     // 转换成map是为了能快速获取 | ||||
|                     Map<Long, ProductPropertyValueRespVO> propertyValueMaps = CollectionUtils.convertMap(propertyValueList, ProductPropertyValueRespVO::getId); | ||||
|                     propertyMaps.get(p.getId()).forEach(pv -> { | ||||
|                         ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName()); | ||||
|                         propertyValues.add(tuple2); | ||||
| @@ -154,12 +159,12 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||||
|                     productPropertyViewRespVO.setPropertyValues(propertyValues.stream().distinct().collect(Collectors.toList())); | ||||
|                     productPropertyViews.add(productPropertyViewRespVO); | ||||
|                 }); | ||||
|                 spuVO.setProductPropertyViews(productPropertyViews); | ||||
|                 respVO.setProductPropertyViews(productPropertyViews); | ||||
|             } | ||||
|             // 组合分类 | ||||
|             if (null != spuVO.getCategoryId()) { | ||||
|             if (null != respVO.getCategoryId()) { | ||||
|                 LinkedList<Long> categoryArray = new LinkedList<>(); | ||||
|                 Long parentId = spuVO.getCategoryId(); | ||||
|                 Long parentId = respVO.getCategoryId(); | ||||
|                 categoryArray.addFirst(parentId); | ||||
|                 while (parentId != 0) { | ||||
|                     parentId = categoryService.getCategory(parentId).getParentId(); | ||||
| @@ -167,10 +172,15 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||||
|                         categoryArray.addFirst(parentId); | ||||
|                     } | ||||
|                 } | ||||
|                 spuVO.setCategoryIds(categoryArray); | ||||
|                 respVO.setCategoryIds(categoryArray); | ||||
|             } | ||||
|         } | ||||
|         return spuVO; | ||||
|         return respVO; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ProductSpuRespVO getSpu(Long id) { | ||||
|         return ProductSpuConvert.INSTANCE.convert(ProductSpuMapper.selectById(id)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -182,8 +192,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||||
|     public PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO) { | ||||
|         PageResult<ProductSpuRespVO> spuVOs = ProductSpuConvert.INSTANCE.convertPage(ProductSpuMapper.selectPage(pageReqVO)); | ||||
|         // 查询 sku 的信息 | ||||
|         List<Long> spuIds = spuVOs.getList().stream().map(ProductSpuRespVO::getId).collect(Collectors.toList()); | ||||
|         List<ProductSkuRespVO> skus = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuIds(spuIds)); | ||||
| //        List<Long> spuIds = spuVOs.getList().stream().map(ProductSpuRespVO::getId).collect(Collectors.toList()); | ||||
| //        List<ProductSkuRespVO> skus = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuIds(spuIds)); | ||||
|         // TODO @franky:使用 CollUtil 里的方法替代哈 | ||||
|         // TODO 芋艿:临时注释 | ||||
| //        Map<Long, List<ProductSkuRespVO>> skuMap = skus.stream().collect(Collectors.groupingBy(ProductSkuRespVO::getSpuId)); | ||||
|   | ||||
| @@ -43,6 +43,25 @@ export function getPropertyPage(query) { | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 获得规格名称列表 | ||||
| export function getPropertyList(query) { | ||||
|   return request({ | ||||
|     url: '/product/property/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 获得规格名称列表 | ||||
| export function getPropertyListAndValue(query) { | ||||
|   return request({ | ||||
|     url: '/product/property/listAndValue', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }) | ||||
| } | ||||
|  | ||||
|  | ||||
| // 导出规格名称 Excel | ||||
| export function exportPropertyExcel(query) { | ||||
|   return request({ | ||||
| @@ -52,3 +71,49 @@ export function exportPropertyExcel(query) { | ||||
|     responseType: 'blob' | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // ------------------------ 规格名称值 ------------------- | ||||
|  | ||||
| // 获得规格名称值分页 | ||||
| export function getPropertyValuePage(query) { | ||||
|   return request({ | ||||
|     url: '/product/property/value/page', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 获得规格名称值 | ||||
| export function getPropertyValue(id) { | ||||
|   return request({ | ||||
|     url: '/product/property/value/get?id=' + id, | ||||
|     method: 'get' | ||||
|   }) | ||||
| } | ||||
|  | ||||
|  | ||||
| // 创建规格名称值 | ||||
| export function createPropertyValue(data) { | ||||
|   return request({ | ||||
|     url: '/product/property/value/create', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 更新规格名称值 | ||||
| export function updatePropertyValue(data) { | ||||
|   return request({ | ||||
|     url: '/product/property/value/update', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 删除规格名称 | ||||
| export function deletePropertyValue(id) { | ||||
|   return request({ | ||||
|     url: '/product/property/value/delete?id=' + id, | ||||
|     method: 'delete' | ||||
|   }) | ||||
| } | ||||
|   | ||||
| @@ -34,6 +34,14 @@ export function getSpu(id) { | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 获得商品spu详情 | ||||
| export function getSpuDetail(id) { | ||||
|   return request({ | ||||
|     url: '/product/spu/get/detail?id=' + id, | ||||
|     method: 'get' | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // 获得商品spu分页 | ||||
| export function getSpuPage(query) { | ||||
|   return request({ | ||||
|   | ||||
| @@ -96,6 +96,17 @@ export const constantRoutes = [ | ||||
|         meta: {title: '字典数据', icon: '', activeMenu: '/system/dict'} | ||||
|       } | ||||
|     ] | ||||
|   }, { | ||||
|     path: '/property', | ||||
|     component: Layout, | ||||
|     hidden: true, | ||||
|     children: [{ | ||||
|         path: 'value/:propertyId(\\d+)', | ||||
|         component: (resolve) => require(['@/views/mall/product/property/value'], resolve), | ||||
|         name: 'PropertyValue', | ||||
|         meta: {title: '规格数据', icon: '', activeMenu: '/mall/property'} | ||||
|       } | ||||
|     ] | ||||
|   }, { | ||||
|     path: '/job', | ||||
|     component: Layout, | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|       <el-form-item label="规格名称" prop="name"> | ||||
|         <el-input v-model="queryParams.name" placeholder="请输入规格名称" clearable @keyup.enter.native="handleQuery"/> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="开启状态" prop="status"> | ||||
|       <el-form-item label="状态" prop="status"> | ||||
|         <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small"> | ||||
|           <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" | ||||
|                      :key="dict.value" :label="dict.label" :value="dict.value"/> | ||||
| @@ -33,10 +33,12 @@ | ||||
|  | ||||
|     <!-- 列表 --> | ||||
|     <el-table v-loading="loading" :data="list"> | ||||
|       <el-table-column label="规格名称" align="center" prop="name" /> | ||||
|        <el-table-column label="规格名称" align="center" prop="propertyValueList"> | ||||
|       <el-table-column label="规格id" align="center" prop="id" /> | ||||
|       <el-table-column label="规格名称" align="center" :show-overflow-tooltip="true"> | ||||
|         <template slot-scope="scope"> | ||||
|           <span>{{formatList(scope.row.propertyValueList)}}</span> | ||||
|           <router-link :to="'/property/value/' + scope.row.id" class="link-type"> | ||||
|             <span>{{ scope.row.name }}</span> | ||||
|           </router-link> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|       <el-table-column label="开启状态" align="center" prop="status"> | ||||
| @@ -49,6 +51,7 @@ | ||||
|           <span>{{ parseTime(scope.row.createTime) }}</span> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|       <el-table-column label="备注" align="center" prop="left" /> | ||||
|       <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|         <template slot-scope="scope"> | ||||
|           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | ||||
| @@ -65,6 +68,9 @@ | ||||
|     <!-- 对话框(添加 / 修改) --> | ||||
|     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> | ||||
|       <el-form ref="form" :model="form" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="规格id" prop="id" v-if="form.id != null"> | ||||
|           <el-input v-model="form.id" disabled /> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="规格名称" prop="name"> | ||||
|           <el-input v-model="form.name" placeholder="请输入规格名称" /> | ||||
|         </el-form-item> | ||||
| @@ -75,25 +81,8 @@ | ||||
|             </el-radio> | ||||
|           </el-radio-group> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="属性值"> | ||||
|           <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="addPropertyValue()">添加</el-button> | ||||
|         </el-form-item> | ||||
|         <el-form-item | ||||
|             v-for="(domain, index) in form.propertyValueList" | ||||
|             :key="domain.key" | ||||
|             :prop="'propertyValueList.' + index + '.name'" | ||||
|             :rules="{ | ||||
|               required: true, message: '属性值不能为空', trigger: 'blur' | ||||
|             }" | ||||
|           > | ||||
|             <el-row> | ||||
|               <el-col :span="18"> | ||||
|                 <el-input v-model="domain.name" size="mini"></el-input> | ||||
|               </el-col> | ||||
|               <el-col :span="6"> | ||||
|                 <el-button style="margin-left: 20px;" size="mini" @click.prevent="removePropertyValue(domain)">删除</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|         <el-form-item label="备注" prop="remark"> | ||||
|           <el-input v-model="form.remark" placeholder="备注" /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <div slot="footer" class="dialog-footer"> | ||||
| @@ -139,12 +128,17 @@ export default { | ||||
|       form: { | ||||
|         name:'', | ||||
|         status:'', | ||||
|         propertyValueList: [{ | ||||
|           name: '' | ||||
|         }], | ||||
|         remark:"", | ||||
|         id: null, | ||||
|       }, | ||||
|       // 表单校验 | ||||
|       rules: { | ||||
|         name: [ | ||||
|           { required: true, message: "规格不能为空", trigger: "blur" } | ||||
|         ], | ||||
|         status: [ | ||||
|           { required: true, message: "状态不能为空", trigger: "blur" } | ||||
|         ] | ||||
|       } | ||||
|     }; | ||||
|   }, | ||||
| @@ -170,12 +164,10 @@ export default { | ||||
|     /** 表单重置 */ | ||||
|     reset() { | ||||
|       this.form = { | ||||
|         id: undefined, | ||||
|         name: undefined, | ||||
|         status: undefined, | ||||
|         propertyValueList: [{ | ||||
|           name: '' | ||||
|         }] | ||||
|         name:'', | ||||
|         status:'', | ||||
|         remark:"", | ||||
|         id: null, | ||||
|       }; | ||||
|       this.resetForm("form"); | ||||
|     }, | ||||
| @@ -253,27 +245,6 @@ export default { | ||||
|           this.exportLoading = false; | ||||
|         }).catch(() => {}); | ||||
|     }, | ||||
|     removePropertyValue(item) { | ||||
|       var index = this.form.propertyValueList.indexOf(item) | ||||
|       if (index !== -1) { | ||||
|         this.form.propertyValueList.splice(index, 1) | ||||
|       } | ||||
|     }, | ||||
|     addPropertyValue() { | ||||
|       this.form.propertyValueList.push({ | ||||
|         name: '' | ||||
|       }); | ||||
|     }, | ||||
|     formatList(list) { | ||||
|       let str = '' | ||||
|       for (var i = 0; i < list.length; i++) { | ||||
|         str += list[i].name; | ||||
|         if(i != list.length-1){ | ||||
|           str+="/"; | ||||
|         } | ||||
|       } | ||||
|       return str | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -9,20 +9,22 @@ | ||||
|       <el-form-item label="商品名称" prop="name"> | ||||
|         <el-input v-model="queryParams.name" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="分类id" prop="categoryId"> | ||||
|         <el-input v-model="queryParams.categoryId" placeholder="请输入分类id" clearable @keyup.enter.native="handleQuery"/> | ||||
|  | ||||
|       <el-form-item label="商品编码" prop="code"> | ||||
|         <el-input v-model="queryParams.code" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="状态" prop="status"> | ||||
|         <el-select v-model="queryParams.status" placeholder="请选择上下架状态" clearable size="small"> | ||||
|           <el-option label="请选择字典生成" value="" /> | ||||
|           <el-option label="上架" value="0" /> | ||||
|           <el-option label="下架" value="1" /> | ||||
|  | ||||
|       <el-form-item label="商品分类" prop="categoryId"> | ||||
|         <el-cascader v-model="queryParams.categoryIds" placeholder="请输入商品分类" | ||||
|                          :options="categoryList" :props="propName" clearable ref="category" /> | ||||
|       </el-form-item> | ||||
|  | ||||
|       <el-form-item label="商品品牌" prop="brandId"> | ||||
|         <el-select v-model="queryParams.brandId" placeholder="请输入商品品牌" clearable @keyup.enter.native="handleQuery"> | ||||
|           <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="创建时间"> | ||||
|         <el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" | ||||
|           range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/> | ||||
|       </el-form-item> | ||||
|  | ||||
|       <el-form-item> | ||||
|         <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | ||||
|         <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | ||||
| @@ -46,33 +48,35 @@ | ||||
|        1. 字段:商品信息、价格、库存、销量、排序、创建时间、状态、操作; | ||||
|        2. tab 分成全部、销售中、仓库中、预警中 | ||||
|        --> | ||||
|       <el-table-column label="主键" align="center" prop="id" /> | ||||
|       <el-table-column label="商品名称" align="center" prop="name" /> | ||||
|       <el-table-column label="分类id" align="center" prop="categoryId" /> | ||||
|       <el-table-column label="商品主图地址" align="center" prop="picUrls"> | ||||
|         <template slot-scope="scope"> | ||||
|       <el-table-column label="商品信息" align="center" width="260"> | ||||
|  | ||||
|         <template slot-scope="scope" > | ||||
|           <div class="product-info"> | ||||
|             <img | ||||
|               v-if="scope.row.picUrls" | ||||
|               :src="scope.row.picUrls[0]" | ||||
|               alt="分类图片" | ||||
|               class="img-height" | ||||
|             /> | ||||
|             <div class="message">{{scope.row.name}}</div> | ||||
|           </div> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|       <el-table-column label="排序字段" align="center" prop="sort" /> | ||||
|       <el-table-column label="点击量" align="center" prop="clickCount" /> | ||||
|       <el-table-column label="价格区间" align="center" prop="price" /> | ||||
|       <el-table-column label="总库存" align="center" prop="totalStock" /> | ||||
|       <el-table-column label="状态" align="center" prop="status"> | ||||
|         <template slot-scope="scope"> | ||||
|           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|       <el-table-column label="价格" align="center" prop="marketPrice" :formatter="unitConversion"/> | ||||
|       <el-table-column label="库存" align="center" prop="totalStock" /> | ||||
|       <el-table-column label="销量" align="center" prop="salesCount" /> | ||||
|       <el-table-column label="排序" align="center" prop="sort" /> | ||||
|       <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | ||||
|         <template slot-scope="scope"> | ||||
|           <span>{{ parseTime(scope.row.createTime) }}</span> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|       <el-table-column label="状态" align="center" prop="status"> | ||||
|         <template slot-scope="scope"> | ||||
|           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|  | ||||
|       <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|         <template slot-scope="scope"> | ||||
|           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" | ||||
| @@ -87,7 +91,7 @@ | ||||
|                 @pagination="getList"/> | ||||
|  | ||||
|     <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body destroy-on-close :close-on-click-modal="false" > | ||||
|       <save @closeDialog="closeDialog" :type="dialogType" :obj="dialogObj" v-if="open" /> | ||||
|       <save @closeDialog="closeDialog" :obj="dialogObj" v-if="open" /> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| @@ -97,7 +101,8 @@ import { | ||||
|   deleteSpu, | ||||
|   getSpuPage, | ||||
| } from "@/api/mall/product/spu"; | ||||
|  | ||||
| import {getProductCategoryList} from "@/api/mall/product/category"; | ||||
| import {getBrandList} from "@/api/mall/product/brand"; | ||||
| import Editor from "@/components/Editor"; | ||||
| import ImageUpload from "@/components/ImageUpload"; | ||||
| import save  from "./save"; | ||||
| @@ -114,20 +119,12 @@ export default { | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       tableLeftTitles: [], | ||||
|       dbTagValues: [], | ||||
|       allhistoryTags: [], | ||||
|       unUseTags: [], | ||||
|       propertyPageList: [], | ||||
|       isShowTagInput: false, | ||||
|       addTagInput: { | ||||
|         name: "", | ||||
|         propertyId: "", | ||||
|         selectValues: [], | ||||
|         selectValueIds: [], | ||||
|         selectObect: [], | ||||
|       propName: { | ||||
|         checkStrictly: true, | ||||
|         label: "name", | ||||
|         value: "id", | ||||
|       }, | ||||
|       skuTags: [], | ||||
|       brandList: [], | ||||
|       categoryList: [], | ||||
|       // 遮罩层 | ||||
|       loading: true, | ||||
| @@ -143,8 +140,6 @@ export default { | ||||
|       title: "", | ||||
|       // 是否显示弹出层 | ||||
|       open: false, | ||||
|       // 弹出层类型 | ||||
|       dialogType: "add", | ||||
|       // 弹出层参数 | ||||
|       dialogObj:{}, | ||||
|       dateRangeCreateTime: [], | ||||
| @@ -153,14 +148,10 @@ export default { | ||||
|         pageNo: 1, | ||||
|         pageSize: 10, | ||||
|         name: null, | ||||
|         sellPoint: null, | ||||
|         description: null, | ||||
|         code: null, | ||||
|         categoryIds: [], | ||||
|         categoryId: null, | ||||
|         picUrls: null, | ||||
|         sort: null, | ||||
|         likeCount: null, | ||||
|         price: null, | ||||
|         quantity: null, | ||||
|         brandId: null, | ||||
|         status: null, | ||||
|       }, | ||||
|       tagIndex: 0, | ||||
| @@ -168,13 +159,30 @@ export default { | ||||
|   }, | ||||
|   created() { | ||||
|     this.getList(); | ||||
|     this.getListCategory() | ||||
|     this.getListBrand() | ||||
|   }, | ||||
|   methods: { | ||||
|     /** 查询分类列表 */ | ||||
|     getListCategory() { | ||||
|       // 执行查询 | ||||
|       getProductCategoryList().then((response) => { | ||||
|         this.categoryList = this.handleTree(response.data, "id", "parentId"); | ||||
|       }); | ||||
|     }, | ||||
|     /** 查询品牌列表 */ | ||||
|     getListBrand() { | ||||
|       // 执行查询 | ||||
|       getBrandList().then((response) => { | ||||
|         this.brandList = response.data; | ||||
|       }); | ||||
|     }, | ||||
|     /** 查询列表 */ | ||||
|     getList() { | ||||
|       this.loading = true; | ||||
|       // 处理查询参数 | ||||
|       let params = { ...this.queryParams }; | ||||
|       params.categoryId =  this.queryParams.categoryIds[ this.queryParams.categoryIds.length - 1]; | ||||
|       this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime"); | ||||
|       // 执行查询 | ||||
|       getSpuPage(params).then((response) => { | ||||
| @@ -200,27 +208,26 @@ export default { | ||||
|     /** 重置按钮操作 */ | ||||
|     resetQuery() { | ||||
|       this.dateRangeCreateTime = []; | ||||
|       this.$refs.category.$refs.panel.checkedValue = [];//也可以是指定的值,默认返回值是数组,也可以返回单个值 | ||||
|     this.$refs.category.$refs.panel.activePath = []; | ||||
|     this.$refs.category.$refs.panel.syncActivePath(); | ||||
|       this.queryParams.categoryIds = []; | ||||
|       this.resetForm("queryForm"); | ||||
|       this.handleQuery(); | ||||
|     }, | ||||
|     /** 新增按钮操作 */ | ||||
|     handleAdd() { | ||||
|       this.dialogType = "add"; | ||||
|       this.dialogObj={}; | ||||
|       this.open = true; | ||||
|       this.title = "添加商品spu"; | ||||
|     }, | ||||
|     /** 修改按钮操作 */ | ||||
|     handleUpdate(row) { | ||||
|       this.dialogType = "upd"; | ||||
|       this.dialogObj.id = row.id; | ||||
|       this.open = true; | ||||
|       console.log("修改") | ||||
|       this.title = "修改商品spu"; | ||||
|     }, | ||||
|     closeDialog(){ | ||||
|       console.log("关闭") | ||||
|       this.dialogType = "add"; | ||||
|       this.dialogObj={}; | ||||
|       this.open = false; | ||||
|       this.getList() | ||||
| @@ -238,6 +245,9 @@ export default { | ||||
|           this.$modal.msgSuccess("删除成功"); | ||||
|         }) | ||||
|         .catch(() => {}); | ||||
|     }, | ||||
|     unitConversion(row, column, cellValue){ | ||||
|       return this.divide(cellValue, 100); | ||||
|     } | ||||
|   }, | ||||
| }; | ||||
| @@ -262,8 +272,25 @@ export default { | ||||
|     vertical-align: bottom; | ||||
|   } | ||||
|  | ||||
|   .product-info{ | ||||
|     display: flex; | ||||
|     .img-height { | ||||
|     height: 65px; | ||||
|       height: 50px; | ||||
|       width: 50px; | ||||
|     } | ||||
|     .message{ | ||||
|       margin-left: 10px; | ||||
|       text-overflow: ellipsis; | ||||
|       display: -webkit-box; | ||||
|       -webkit-line-clamp: 2; | ||||
|       word-break: break-all; | ||||
|       -webkit-box-orient: vertical; | ||||
|       white-space: normal; | ||||
|       overflow: hidden; | ||||
|       height: 50px; | ||||
|       line-height: 25px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template> | ||||
|   <div class="container"> | ||||
|     <el-tabs v-model="activeName" class="tabs"  :before-leave="confirmLeave"> | ||||
|     <el-tabs v-model="activeName" class="tabs"  > | ||||
|       <!-- 基础设置 --> | ||||
|       <el-tab-pane label="基础设置" name="base"> | ||||
|         <el-form ref="base" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%"> | ||||
| @@ -12,7 +12,7 @@ | ||||
|           </el-form-item> | ||||
|           <!-- TODO @Luowenfeng:商品主图,80 x 80 即可 --> | ||||
|           <el-form-item label="商品主图" prop="picUrls"> | ||||
|             <ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10"/> | ||||
|             <ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" /> | ||||
|           </el-form-item> | ||||
|           <!-- TODO @Luowenfeng:商品视频 --> | ||||
|           <el-form-item label="商品品牌" prop="brandId"> | ||||
| @@ -38,10 +38,7 @@ | ||||
|         <el-form ref="rates" :model="ratesForm" :rules="rules"> | ||||
|           <el-form-item label="启用多规格"> | ||||
|             <!-- TODO @Luowenfeng:改成开关的按钮;关闭,单规格;开启,多规格 --> | ||||
|             <el-radio-group v-model="ratesForm.spec" @change="changeRadio"> | ||||
|               <el-radio :label="1">单规格</el-radio> | ||||
|               <el-radio :label="2">多规格</el-radio> | ||||
|             </el-radio-group> | ||||
|             <el-switch v-model="activeSwitch" @change="changeRadio"></el-switch> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <!-- 动态添加规格属性 --> | ||||
| @@ -67,7 +64,7 @@ | ||||
|           <!-- 规格明细 --> | ||||
|           <el-form-item label="规格明细"> | ||||
|             <el-table :data="ratesForm.rates" border style="width: 100%" ref="ratesTable"> | ||||
|               <template v-if="ratesForm.spec == 2"> | ||||
|               <template v-if="this.activeSwitch"> | ||||
|                 <el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v => v.specName !== undefined)" | ||||
|                                  :label="item.specName"> | ||||
|                   <template slot-scope="scope"> | ||||
| @@ -81,7 +78,7 @@ | ||||
|                                style="width: 100px; height: 50px"/> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <template v-if="ratesForm.spec === 2"> | ||||
|               <template v-if="this.activeSwitch"> | ||||
|                <el-table-column label="sku名称" :render-header="addRedStar" key="91"> | ||||
|                   <template slot-scope="scope"> | ||||
|                     <el-form-item :prop="'rates.'+ scope.$index + '.name'" :rules="[{required: true, trigger: 'change'}]"> | ||||
| @@ -142,7 +139,7 @@ | ||||
|                   <el-input v-model="scope.row.barCode"></el-input> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|                <template v-if="ratesForm.spec === 2"> | ||||
|                <template v-if="this.activeSwitch"> | ||||
|                 <el-table-column fixed="right" label="操作" width="50" key="100"> | ||||
|                   <template slot-scope="scope"> | ||||
|                     <el-button @click="scope.row.status = 1" type="text" size="small" v-show="scope.row.status == undefined || scope.row.status == 0 ">禁用</el-button> | ||||
| @@ -153,7 +150,6 @@ | ||||
|             </el-table> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="虚拟销量" prop="virtualSalesCount"> | ||||
|             <!-- TODO @Luowenfeng:使用 input 类型即可 --> | ||||
|             <el-input v-model="baseForm.virtualSalesCount" placeholder="请输入虚拟销量" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
| @@ -196,8 +192,8 @@ | ||||
|  | ||||
| import {getBrandList} from "@/api/mall/product/brand"; | ||||
| import {getProductCategoryList} from "@/api/mall/product/category"; | ||||
| import {createSpu, updateSpu, getSpu} from "@/api/mall/product/spu"; | ||||
| import {getPropertyPage,} from "@/api/mall/product/property"; | ||||
| import {createSpu, updateSpu, getSpuDetail} from "@/api/mall/product/spu"; | ||||
| import {getPropertyListAndValue,} from "@/api/mall/product/property"; | ||||
| import Editor from "@/components/Editor"; | ||||
| import ImageUpload from "@/components/ImageUpload"; | ||||
|  | ||||
| @@ -206,16 +202,13 @@ export default { | ||||
|     Editor, | ||||
|     ImageUpload | ||||
|   }, | ||||
|   props:{//props列表 | ||||
|     type:{ | ||||
|       type:String, | ||||
|       default:"add" //定义参数默认值 | ||||
|     }, | ||||
|   props:{ | ||||
|     obj: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       activeName: "base", // TODO @Luowenfeng:切换时,不需要校验通过 | ||||
|       activeSwitch: false, | ||||
|       activeName: "base", | ||||
|       propName: { | ||||
|         checkStrictly: true, | ||||
|         label: "name", | ||||
| @@ -271,7 +264,7 @@ export default { | ||||
|     this.getListBrand(); | ||||
|     this.getListCategory(); | ||||
|     this.getPropertyPageList(); | ||||
|     if(this.type == 'upd'){ | ||||
|     if(this.obj.id != null){ | ||||
|       this.updateType(this.obj.id) | ||||
|     } | ||||
|   }, | ||||
| @@ -280,14 +273,6 @@ export default { | ||||
|         this.dynamicSpec.splice(index, 1); | ||||
|         this.changeRadio() | ||||
|     }, | ||||
|     async confirmLeave(active, old){ | ||||
|       await this.$refs[old].validate((valid) => { | ||||
|         console.log(valid) | ||||
|         if (!valid) { | ||||
|           return reject(); | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     // 必选标识 | ||||
|     addRedStar(h, { column }) { | ||||
|       return [ | ||||
| @@ -296,13 +281,13 @@ export default { | ||||
|       ]; | ||||
|     }, | ||||
|     changeRadio() { | ||||
|       this.activeSwitch ? this.ratesForm.spec = 2:  this.ratesForm.spec = 1; | ||||
|       this.$refs.ratesTable.doLayout(); | ||||
|       if (this.ratesForm.spec == 1) { | ||||
|         this.ratesForm.rates = [{}] | ||||
|       } else { | ||||
|         this.ratesForm.rates = [] | ||||
|         if (this.dynamicSpec.length > 0) { | ||||
|           console.log( this.dynamicSpec) | ||||
|           this.buildRatesFormRates() | ||||
|         } | ||||
|       } | ||||
| @@ -316,6 +301,7 @@ export default { | ||||
|           last.forEach(par1 => { | ||||
|             current.forEach(par2 => { | ||||
|               let v | ||||
|               // 当两个对象合并时,需使用[1,2]方式生成数组,而当数组和对象合并时,需使用concat | ||||
|               if (par1 instanceof Array) { | ||||
|                 v = par1.concat(par2) | ||||
|               } else { | ||||
| @@ -327,7 +313,12 @@ export default { | ||||
|           return array; | ||||
|         }) | ||||
|         .forEach(v => { | ||||
|           rates.push({spec: v, status: 0, name: Array.of(v).join()}) | ||||
|           let spec = v; | ||||
|           // 当v为单个规格项时,会变成字符串。造成表格只截取第一个字符串,而不是数组的第一个元素 | ||||
|           if (typeof v == 'string') { | ||||
|             spec = Array.of(v) | ||||
|           } | ||||
|           rates.push({spec: spec, status: 0, name: Array.of(v).join()}) | ||||
|         }); | ||||
|       this.ratesForm.rates = rates | ||||
|     }, | ||||
| @@ -363,7 +354,7 @@ export default { | ||||
|       }) | ||||
|  | ||||
|       // 动态规格调整字段 | ||||
|       if (this.ratesForm.spec == 2) { | ||||
|       if (this.activeSwitch) { | ||||
|         rates.forEach(r => { | ||||
|           let properties = [] | ||||
|             Array.of(r.spec).forEach(s => { | ||||
| @@ -396,43 +387,42 @@ export default { | ||||
|       }else{ | ||||
|         form.picUrls = Array.of(form.picUrls) | ||||
|       } | ||||
|       console.log(rates) | ||||
|       form.skus = rates; | ||||
|       form.specType = this.ratesForm.spec; | ||||
|       form.categoryId = form.categoryIds[this.baseForm.categoryIds.length - 1]; | ||||
|  | ||||
|  | ||||
|       if(form.id == null){ | ||||
|         createSpu(form).then((response) => { | ||||
|           this.$modal.msgSuccess("新增成功"); | ||||
|           this.$emit("closeDialog"); | ||||
|         }) | ||||
|       }else{ | ||||
|         updateSpu(form).then((response) => { | ||||
|           this.$modal.msgSuccess("修改成功"); | ||||
|           this.$emit("closeDialog"); | ||||
|         }) | ||||
|       } | ||||
|       }); | ||||
|       this.$emit("closeDialog"); | ||||
|  | ||||
|     }, | ||||
|     /** 查询规格 */ | ||||
|     getPropertyPageList() { | ||||
|       // 执行查询 | ||||
|       getPropertyPage().then((response) => { | ||||
|         this.propertyPageList = response.data.list; | ||||
|       getPropertyListAndValue().then((response) => { | ||||
|         this.propertyPageList = response.data; | ||||
|       }); | ||||
|     }, | ||||
|     // 添加规格项目 | ||||
|     changeSpec(val) { | ||||
|       let obj = this.propertyPageList.find(o => o.id == val); | ||||
|       let dynamicSpec = this.dynamicSpec; | ||||
|       let spec = dynamicSpec.find(o => o.specId == val) | ||||
|       let spec = this.dynamicSpec.find(o => o.specId == val) | ||||
|       spec.specId = obj.id; | ||||
|       spec.specName = obj.name; | ||||
|       spec.specValue = obj.propertyValueList; | ||||
|       this.dynamicSpec = dynamicSpec; | ||||
|       spec.specValue = obj.values; | ||||
|       this.buildRatesFormRates(); | ||||
|     }, | ||||
|     updateType(id){ | ||||
|         getSpu(id).then((response) =>{ | ||||
|       getSpuDetail(id).then((response) =>{ | ||||
|             let data = response.data; | ||||
|             this.baseForm.id=data.id; | ||||
|             this.baseForm.name=data.name; | ||||
| @@ -452,6 +442,7 @@ export default { | ||||
|               r.costPrice = this.divide(r.costPrice, 100) | ||||
|             }) | ||||
|             if(this.ratesForm.spec == 2){ | ||||
|               this.activeSwitch = true; | ||||
|               data.productPropertyViews.forEach(p=>{ | ||||
|                 let obj = {}; | ||||
|                 obj.specId = p.propertyId; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 luowenfeng
					luowenfeng