فهرست منبع

product:优化商品属性项的代码

YunaiV 2 سال پیش
والد
کامیت
98ca807d4b
19فایلهای تغییر یافته به همراه150 افزوده شده و 152 حذف شده
  1. 1 0
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
  2. 22 6
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
  3. 15 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
  4. 0 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
  5. 0 3
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
  6. 0 4
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
  7. 14 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
  8. 0 9
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
  9. 0 7
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
  10. 8 1
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
  11. 9 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
  12. 3 19
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
  13. 27 44
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
  14. 28 3
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
  15. 18 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
  16. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
  17. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
  18. 1 1
      yudao-ui-admin/src/api/mall/product/property.js
  19. 0 32
      yudao-ui-admin/src/views/mall/product/property/index.vue

+ 1 - 0
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java

@@ -25,6 +25,7 @@ public interface ErrorCodeConstants {
     // ========== 商品属性项 1008003000 ==========
     ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
     ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
+    ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
 
     // ========== 商品属性值 1008004000 ==========
     ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");

+ 22 - 6
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java

@@ -1,9 +1,14 @@
 package cn.iocoder.yudao.module.product.controller.admin.property;
 
+import cn.hutool.core.collection.CollUtil;
 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.*;
+import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
 import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
@@ -13,10 +18,11 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
-
+import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 
 @Api(tags = "管理后台 - 商品属性项")
 @RestController
@@ -26,6 +32,8 @@ public class ProductPropertyController {
 
     @Resource
     private ProductPropertyService productPropertyService;
+    @Resource
+    private ProductPropertyValueService productPropertyValueService;
 
     @PostMapping("/create")
     @ApiOperation("创建属性项")
@@ -56,28 +64,36 @@ public class ProductPropertyController {
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
     @PreAuthorize("@ss.hasPermission('product:property:query')")
     public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
-        return success(productPropertyService.getProperty(id));
+        return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id)));
     }
 
     @GetMapping("/list")
     @ApiOperation("获得属性项列表")
     @PreAuthorize("@ss.hasPermission('product:property:query')")
     public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
-        return success(productPropertyService.getPropertyVOList(listReqVO));
+        return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO)));
     }
 
     @GetMapping("/page")
     @ApiOperation("获得属性项分页")
     @PreAuthorize("@ss.hasPermission('product:property:query')")
     public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
-        return success(productPropertyService.getPropertyPage(pageVO));
+        return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
     }
 
-    @GetMapping("/listAndValue")
+    @GetMapping("/get-value-list")
     @ApiOperation("获得属性项列表")
     @PreAuthorize("@ss.hasPermission('product:property:query')")
     public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
-        return success(productPropertyService.getPropertyAndValueList(listReqVO));
+        // 查询属性项
+        List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO);
+        if (CollUtil.isEmpty(keys)) {
+            return success(Collections.emptyList());
+        }
+        // 查询属性值
+        List<ProductPropertyValueDO> values = productPropertyValueService.getPropertyValueListByPropertyId(
+                convertSet(keys, ProductPropertyDO::getId));
+        return success(ProductPropertyConvert.INSTANCE.convertList(keys, values));
     }
 
 }

+ 15 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java

@@ -1,13 +1,11 @@
 package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
 
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-import java.time.LocalDateTime;
 import java.util.List;
 
 @ApiModel("管理后台 - 商品属性项 + 属性值 Response VO")
@@ -19,12 +17,24 @@ public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
     @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
     private Long id;
 
-    @ApiModelProperty(value = "创建时间", required = true)
-    private LocalDateTime createTime;
+    @ApiModelProperty(value = "属性项的名称", required = true, example = "颜色")
+    private String name;
 
     /**
      * 属性值的集合
      */
-    private List<ProductPropertyValueRespVO> values;
+    private List<Value> values;
+
+    @ApiModel("管理后台 - 属性值的简单 Response VO")
+    @Data
+    public static class Value {
+
+        @ApiModelProperty(value = "属性值的编号", required = true, example = "2048")
+        private Long id;
+
+        @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+        private String name;
+
+    }
 
 }

+ 0 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java

@@ -4,7 +4,6 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
 
 /**
  * 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -20,8 +19,4 @@ public class ProductPropertyBaseVO {
     @ApiModelProperty(value = "备注", example = "颜色")
     private String remark;
 
-    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
-    @NotNull(message = "状态不能为空")
-    private Integer status;
-
 }

+ 0 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java

@@ -13,7 +13,4 @@ public class ProductPropertyListReqVO {
     @ApiModelProperty(value = "名称", example = "颜色")
     private String name;
 
-    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
-    private Integer status;
-
 }

+ 0 - 4
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java

@@ -21,10 +21,6 @@ public class ProductPropertyValueBaseVO {
     @NotEmpty(message = "名称名字不能为空")
     private String name;
 
-    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
-    @NotNull(message = "状态不能为空")
-    private Integer status;
-
     @ApiModelProperty(value = "备注", example = "颜色")
     private String remark;
 

+ 14 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java

@@ -1,15 +1,18 @@
 package cn.iocoder.yudao.module.product.convert.property;
 
 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.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 cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 属性项 Convert
@@ -25,12 +28,21 @@ public interface ProductPropertyConvert {
 
     ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
 
-    ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
-
     ProductPropertyRespVO convert(ProductPropertyDO bean);
 
     List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
 
     PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
 
+    default List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> keys, List<ProductPropertyValueDO> values) {
+        Map<Long, List<ProductPropertyValueDO>> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
+        return CollectionUtils.convertList(keys, key -> {
+            ProductPropertyAndValueRespVO respVO = convert02(key);
+            respVO.setValues(convertList02(valueMap.get(key.getId())));
+            return respVO;
+        });
+    }
+    ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean);
+    List<ProductPropertyAndValueRespVO.Value> convertList02(List<ProductPropertyValueDO> list);
+
 }

+ 0 - 9
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.property;
 
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -31,17 +30,9 @@ public class ProductPropertyDO extends BaseDO {
      * 名称
      */
     private String name;
-    /**
-     * 状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
     /**
      * 备注
      */
     private String remark;
 
-    // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索)
-
 }

+ 0 - 7
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.product.dal.dataobject.property;
 
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -38,12 +37,6 @@ public class ProductPropertyValueDO extends BaseDO {
      * 名称
      */
     private String name;
-    /**
-     * 状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
     /**
      * 备注
      *

+ 8 - 1
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java

@@ -3,17 +3,19 @@ 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.property.ProductPropertyListReqVO;
 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 @Mapper
 public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
 
     default PageResult<ProductPropertyDO> selectPage(ProductPropertyPageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyDO>()
                 .likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
-                .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
                 .orderByDesc(ProductPropertyDO::getId));
     }
@@ -23,4 +25,9 @@ public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
                 .eqIfPresent(ProductPropertyDO::getName, name));
     }
 
+    default List<ProductPropertyDO> selectList(ProductPropertyListReqVO listReqVO) {
+        return selectList(new LambdaQueryWrapperX<ProductPropertyDO>()
+                .eqIfPresent(ProductPropertyDO::getName, listReqVO.getName()));
+    }
+
 }

+ 9 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java

@@ -7,12 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Collection;
 import java.util.List;
 
 @Mapper
 public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> {
 
-    default List<ProductPropertyValueDO> selectListByPropertyId(List<Long> propertyIds) {
+    default List<ProductPropertyValueDO> selectListByPropertyId(Collection<Long> propertyIds) {
         return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>()
                 .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
     }
@@ -23,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyV
                 .eq(ProductPropertyValueDO::getName, name));
     }
 
-    default void deletePropertyValueByPropertyId(Long propertyId) {
-        delete(new LambdaQueryWrapperX<ProductPropertyValueDO>().eq(ProductPropertyValueDO::getPropertyId, propertyId)
-                .eq(ProductPropertyValueDO::getDeleted, false));
+    default void deleteByPropertyId(Long propertyId) {
+        delete(new LambdaQueryWrapperX<ProductPropertyValueDO>()
+                .eq(ProductPropertyValueDO::getPropertyId, propertyId));
     }
 
     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));
     }
 
+    default Integer selectCountByPropertyId(Long propertyId) {
+        return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue();
+    }
+
 }

+ 3 - 19
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java

@@ -42,7 +42,7 @@ public interface ProductPropertyService {
      * @param listReqVO 集合查询
      * @return 属性项集合
      */
-    List<ProductPropertyRespVO> getPropertyVOList(ProductPropertyListReqVO listReqVO);
+    List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO);
 
     /**
      * 获取属性名称分页
@@ -50,7 +50,7 @@ public interface ProductPropertyService {
      * @param pageReqVO 分页条件
      * @return 属性项分页
      */
-    PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO);
+    PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO);
 
     /**
      * 获得指定编号的属性项
@@ -58,7 +58,7 @@ public interface ProductPropertyService {
      * @param id 编号
      * @return 属性项
      */
-    ProductPropertyRespVO getProperty(Long id);
+    ProductPropertyDO getProperty(Long id);
 
     /**
      * 根据属性项的编号的集合,获得对应的属性项数组
@@ -68,20 +68,4 @@ public interface ProductPropertyService {
      */
     List<ProductPropertyDO> getPropertyList(Collection<Long> ids);
 
-    /**
-     * 根据属性项的编号的集合,获得对应的属性项数组
-     *
-     * @param ids 属性项的编号的集合
-     * @return 属性项数组
-     */
-    List<ProductPropertyRespVO> getPropertyVOList(Collection<Long> ids);
-
-    /**
-     * 获得属性项 + 值的列表
-     *
-     * @param listReqVO 列表查询
-     * @return 属性项 + 值的列表
-     */
-    List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO);
-
 }

+ 27 - 44
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java

@@ -1,15 +1,15 @@
 package cn.iocoder.yudao.module.product.service.property;
 
+import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
+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.convert.property.ProductPropertyConvert;
-import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
-import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper;
-import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -17,11 +17,9 @@ import org.springframework.validation.annotation.Validated;
 import javax.annotation.Resource;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_EXISTS;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
 
 /**
  * 商品属性项 Service 实现类
@@ -36,15 +34,17 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
     private ProductPropertyMapper productPropertyMapper;
 
     @Resource
-    private ProductPropertyValueMapper productPropertyValueMapper;
+    @Lazy // 延迟加载,解决循环依赖问题
+    private ProductPropertyValueService productPropertyValueService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
-        // 校验存在
+        // 校验名字重复
         if (productPropertyMapper.selectByName(createReqVO.getName()) != null) {
             throw exception(PROPERTY_EXISTS);
         }
+
         // 插入
         ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO);
         productPropertyMapper.insert(property);
@@ -55,12 +55,14 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void updateProperty(ProductPropertyUpdateReqVO updateReqVO) {
-        // 校验存在
         validatePropertyExists(updateReqVO.getId());
+        // 校验名字重复
         ProductPropertyDO productPropertyDO = productPropertyMapper.selectByName(updateReqVO.getName());
-        if (productPropertyDO != null && !productPropertyDO.getId().equals(updateReqVO.getId())) {
+        if (productPropertyDO != null &&
+                ObjUtil.notEqual(productPropertyDO.getId(), updateReqVO.getId())) {
             throw exception(PROPERTY_EXISTS);
         }
+
         // 更新
         ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
         productPropertyMapper.updateById(updateObj);
@@ -70,10 +72,15 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
     public void deleteProperty(Long id) {
         // 校验存在
         validatePropertyExists(id);
+        // 校验其下是否有规格值
+        if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) {
+            throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS);
+        }
+
         // 删除
         productPropertyMapper.deleteById(id);
         // 同步删除属性值
-        productPropertyValueMapper.deletePropertyValueByPropertyId(id);
+        productPropertyValueService.deletePropertyValueByPropertyId(id);
     }
 
     private void validatePropertyExists(Long id) {
@@ -83,22 +90,18 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
     }
 
     @Override
-    public List<ProductPropertyRespVO> getPropertyVOList(ProductPropertyListReqVO listReqVO) {
-        return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectList(new LambdaQueryWrapperX<ProductPropertyDO>()
-                .likeIfPresent(ProductPropertyDO::getName, listReqVO.getName())
-                .eqIfPresent(ProductPropertyDO::getStatus, listReqVO.getStatus())));
+    public List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO) {
+        return productPropertyMapper.selectList(listReqVO);
     }
 
     @Override
-    public PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
-        PageResult<ProductPropertyDO> pageResult = productPropertyMapper.selectPage(pageReqVO);
-        return ProductPropertyConvert.INSTANCE.convertPage(pageResult);
+    public PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
+        return productPropertyMapper.selectPage(pageReqVO);
     }
 
     @Override
-    public ProductPropertyRespVO getProperty(Long id) {
-        ProductPropertyDO property = productPropertyMapper.selectById(id);
-        return ProductPropertyConvert.INSTANCE.convert(property);
+    public ProductPropertyDO getProperty(Long id) {
+        return productPropertyMapper.selectById(id);
     }
 
     @Override
@@ -106,24 +109,4 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
         return productPropertyMapper.selectBatchIds(ids);
     }
 
-    // TODO @芋艿:丢到 Controller
-    @Override
-    public List<ProductPropertyRespVO> getPropertyVOList(Collection<Long> ids) {
-        return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids));
-    }
-
-    // TODO @芋艿:丢到 Controller
-    @Override
-    public List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO) {
-        List<ProductPropertyRespVO> propertyList = getPropertyVOList(listReqVO);
-
-        // 查询属性值
-        List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.selectListByPropertyId(CollectionUtils.convertList(propertyList, ProductPropertyRespVO::getId));
-        Map<Long, List<ProductPropertyValueDO>> valueDOMap = CollectionUtils.convertMultiMap(valueDOList, ProductPropertyValueDO::getPropertyId);
-        return CollectionUtils.convertList(propertyList, m -> {
-            ProductPropertyAndValueRespVO productPropertyAndValueRespVO = ProductPropertyConvert.INSTANCE.convert(m);
-            productPropertyAndValueRespVO.setValues(ProductPropertyValueConvert.INSTANCE.convertList(valueDOMap.get(m.getId())));
-            return productPropertyAndValueRespVO;
-        });
-    }
 }

+ 28 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
 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.dal.dataobject.property.ProductPropertyValueDO;
 import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
 
 import java.util.Collection;
@@ -47,6 +48,14 @@ public interface ProductPropertyValueService {
      */
     ProductPropertyValueRespVO getPropertyValue(Long id);
 
+    /**
+     * 根据属性项编号数组,获得属性值列表
+     *
+     * @param propertyIds 属性项目编号数组
+     * @return 属性值列表
+     */
+    List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds);
+
     /**
      * 根据编号数组,获得属性值列表
      *
@@ -56,12 +65,20 @@ public interface ProductPropertyValueService {
     List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids);
 
     /**
-     * 获得属性值
+     * 根据属性项编号,获得属性值数组
      *
-     * @param id 编号
+     * @param propertyIds 属性项编号数组
      * @return 属性值
      */
-    List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id);
+    List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> propertyIds);
+
+    /**
+     * 根据属性项编号,活的属性值数量
+     *
+     * @param propertyId 属性项编号数
+     * @return 属性值数量
+     */
+    Integer getPropertyValueCountByPropertyId(Long propertyId);
 
     /**
      * 获取属性值的分页
@@ -70,4 +87,12 @@ public interface ProductPropertyValueService {
      * @return 属性值的分页
      */
     PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO);
+
+    /**
+     * 删除指定属性项编号下的属性值们
+     *
+     * @param propertyId 属性项的编号
+     */
+    void deletePropertyValueByPropertyId(Long propertyId);
+
 }

+ 18 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java

@@ -73,6 +73,11 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
         return ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueDO);
     }
 
+    @Override
+    public List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds) {
+        return productPropertyValueMapper.selectListByPropertyId(propertyIds);
+    }
+
     @Override
     public List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids) {
         // 获得属性值列表
@@ -91,12 +96,23 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
     }
 
     @Override
-    public List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id) {
-        return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", id));
+    public List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> propertyIds) {
+        return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", propertyIds));
+    }
+
+    @Override
+    public Integer getPropertyValueCountByPropertyId(Long propertyId) {
+        return productPropertyValueMapper.selectCountByPropertyId(propertyId);
     }
 
     @Override
     public PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO) {
         return ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueMapper.selectPage(pageReqVO));
     }
+
+    @Override
+    public void deletePropertyValueByPropertyId(Long propertyId) {
+        productPropertyValueMapper.deleteByPropertyId(propertyId);
+    }
+
 }

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

@@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.product.service.sku;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
-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;
 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
 import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
@@ -89,7 +89,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
                 .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
                 .map(ProductSkuBaseVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
                 .collect(Collectors.toSet());
-        List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyVOList(propertyIds);
+        List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyIds);
         if (propertyList.size() != propertyIds.size()) {
             throw exception(PROPERTY_NOT_EXISTS);
         }

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

@@ -5,7 +5,6 @@ import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
-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;
@@ -15,6 +14,7 @@ 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;
 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
@@ -142,7 +142,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
                 Map<Long, List<ProductSkuBaseVO.Property>> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId));
 
                 List<ProductPropertyValueRespVO> propertyValueList = productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyMaps.keySet()));
-                List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyVOList(new ArrayList<>(propertyMaps.keySet()));
+                List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyMaps.keySet());
                 // 装载组装过后的属性
                 List<ProductPropertyViewRespVO> productPropertyViews = new ArrayList<>();
                 propertyList.forEach(p -> {

+ 1 - 1
yudao-ui-admin/src/api/mall/product/property.js

@@ -57,7 +57,7 @@ export function getPropertyList(query) {
 // 获得属性项列表
 export function getPropertyListAndValue(query) {
   return request({
-    url: '/product/property/listAndValue',
+    url: '/product/property/get-value-list',
     method: 'get',
     params: query
   })

+ 0 - 32
yudao-ui-admin/src/views/mall/product/property/index.vue

@@ -41,11 +41,6 @@
           </router-link>
         </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" prop="createTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.createTime) }}</span>
@@ -74,13 +69,6 @@
         <el-form-item label="名称" prop="name">
           <el-input v-model="form.name" placeholder="请输入名称" />
         </el-form-item>
-        <el-form-item label="状态" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
-                      :key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" placeholder="备注" />
         </el-form-item>
@@ -121,7 +109,6 @@ export default {
         pageNo: 1,
         pageSize: 10,
         name: null,
-        status: null,
         createTime: []
       },
       // 表单参数
@@ -135,9 +122,6 @@ export default {
       rules: {
         name: [
           { required: true, message: "名称不能为空", trigger: "blur" }
-        ],
-        status: [
-          { required: true, message: "状态不能为空", trigger: "blur" }
         ]
       }
     };
@@ -165,7 +149,6 @@ export default {
     reset() {
       this.form = {
         name:'',
-        status:'',
         remark:"",
         id: null,
       };
@@ -230,21 +213,6 @@ export default {
           this.$modal.msgSuccess("删除成功");
         }).catch(() => {});
     },
-    /** 导出按钮操作 */
-    handleExport() {
-      // 处理查询参数
-      let params = {...this.queryParams};
-      params.pageNo = undefined;
-      params.pageSize = undefined;
-      // 执行导出
-      this.$modal.confirm('是否确认导出所有名称数据项?').then(() => {
-          this.exportLoading = true;
-          return exportPropertyExcel(params);
-        }).then(response => {
-          this.$download.excel(response, '名称.xls');
-          this.exportLoading = false;
-        }).catch(() => {});
-    },
   }
 };
 </script>