Commit f07bf8b0fd5bf043a60b636b41d1dde0aa4be17e
1 parent
6dca8e08
spu保存校验添加
Showing
9 changed files
with
418 additions
and
219 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
| ... | ... | @@ -37,6 +37,8 @@ public interface ProductSkuConvert { |
| 37 | 37 | |
| 38 | 38 | List<ProductSkuRespVO> convertList(List<ProductSkuDO> list); |
| 39 | 39 | |
| 40 | + List<ProductSkuDO> convertSkuDOList(List<ProductSkuCreateReqVO> list); | |
| 41 | + | |
| 40 | 42 | PageResult<ProductSkuRespVO> convertPage(PageResult<ProductSkuDO> page); |
| 41 | 43 | |
| 42 | 44 | List<ProductSkuExcelVO> convertList02(List<ProductSkuDO> list); | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
| ... | ... | @@ -76,4 +76,10 @@ public interface ProductPropertyService { |
| 76 | 76 | |
| 77 | 77 | ProductPropertyRespVO getPropertyResp(Long id); |
| 78 | 78 | |
| 79 | + /** | |
| 80 | + * 根据数据名id集合查询属性名以及属性值的集合 | |
| 81 | + * @param propertyIds 属性名id集合 | |
| 82 | + * @return | |
| 83 | + */ | |
| 84 | + List<ProductPropertyRespVO> selectByIds(List<Integer> propertyIds); | |
| 79 | 85 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.product.service.property; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; |
| 5 | 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyCreateReqVO; |
| ... | ... | @@ -113,13 +114,13 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { |
| 113 | 114 | //获取属性列表 |
| 114 | 115 | PageResult<ProductPropertyDO> pageResult = productPropertyMapper.selectPage(pageReqVO); |
| 115 | 116 | PageResult<ProductPropertyRespVO> propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); |
| 116 | - List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(x -> x.getId()).collect(Collectors.toList()); | |
| 117 | + List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyRespVO::getId).collect(Collectors.toList()); | |
| 117 | 118 | |
| 118 | 119 | //获取属性值列表 |
| 119 | 120 | List<ProductPropertyValueDO> productPropertyValueDOList = productPropertyValueService.getPropertyValueListByPropertyId(propertyIds); |
| 120 | 121 | List<ProductPropertyValueRespVO> propertyValueRespVOList = ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueDOList); |
| 121 | 122 | //组装一对多 |
| 122 | - propertyRespVOPageResult.getList().stream().forEach(x->{ | |
| 123 | + propertyRespVOPageResult.getList().forEach(x->{ | |
| 123 | 124 | Long propertyId = x.getId(); |
| 124 | 125 | List<ProductPropertyValueRespVO> valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); |
| 125 | 126 | x.setPropertyValueList(valueDOList); |
| ... | ... | @@ -140,4 +141,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { |
| 140 | 141 | return propertyRespVO; |
| 141 | 142 | } |
| 142 | 143 | |
| 144 | + @Override | |
| 145 | + public List<ProductPropertyRespVO> selectByIds(List<Integer> propertyIds) { | |
| 146 | + return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(propertyIds)); | |
| 147 | + } | |
| 143 | 148 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
| ... | ... | @@ -72,4 +72,11 @@ public interface ProductSkuService { |
| 72 | 72 | * @param skuCreateReqList sku组合的集合 |
| 73 | 73 | */ |
| 74 | 74 | void validatedSkuReq(List<ProductSkuCreateReqVO> skuCreateReqList); |
| 75 | + | |
| 76 | + /** | |
| 77 | + * 批量保存sku | |
| 78 | + * @param skuDOList sku对象集合 | |
| 79 | + * @return | |
| 80 | + */ | |
| 81 | + void batchSave(List<ProductSkuDO> skuDOList); | |
| 75 | 82 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.product.service.sku; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; | |
| 6 | +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; | |
| 7 | +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; | |
| 8 | +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | |
| 9 | +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | |
| 10 | +import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; | |
| 11 | +import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants; | |
| 12 | +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; | |
| 3 | 13 | import org.springframework.stereotype.Service; |
| 4 | -import javax.annotation.Resource; | |
| 5 | 14 | import org.springframework.validation.annotation.Validated; |
| 6 | 15 | |
| 16 | +import javax.annotation.Resource; | |
| 7 | 17 | import java.util.*; |
| 8 | 18 | import java.util.stream.Collectors; |
| 9 | 19 | |
| 10 | -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; | |
| 11 | -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | |
| 12 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 13 | - | |
| 14 | -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | |
| 15 | -import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; | |
| 16 | - | |
| 17 | 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 18 | -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; | |
| 21 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS; | |
| 22 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | |
| 19 | 23 | |
| 20 | 24 | /** |
| 21 | 25 | * 商品sku Service 实现类 |
| ... | ... | @@ -27,13 +31,16 @@ import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; |
| 27 | 31 | public class ProductSkuServiceImpl implements ProductSkuService { |
| 28 | 32 | |
| 29 | 33 | @Resource |
| 30 | - private ProductSkuMapper ProductSkuMapper; | |
| 34 | + private ProductSkuMapper productSkuMapper; | |
| 35 | + | |
| 36 | + @Resource | |
| 37 | + private ProductPropertyService productPropertyService; | |
| 31 | 38 | |
| 32 | 39 | @Override |
| 33 | 40 | public Long createSku(ProductSkuCreateReqVO createReqVO) { |
| 34 | 41 | // 插入 |
| 35 | 42 | ProductSkuDO sku = ProductSkuConvert.INSTANCE.convert(createReqVO); |
| 36 | - ProductSkuMapper.insert(sku); | |
| 43 | + productSkuMapper.insert(sku); | |
| 37 | 44 | // 返回 |
| 38 | 45 | return sku.getId(); |
| 39 | 46 | } |
| ... | ... | @@ -44,7 +51,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 44 | 51 | this.validateSkuExists(updateReqVO.getId()); |
| 45 | 52 | // 更新 |
| 46 | 53 | ProductSkuDO updateObj = ProductSkuConvert.INSTANCE.convert(updateReqVO); |
| 47 | - ProductSkuMapper.updateById(updateObj); | |
| 54 | + productSkuMapper.updateById(updateObj); | |
| 48 | 55 | } |
| 49 | 56 | |
| 50 | 57 | @Override |
| ... | ... | @@ -52,40 +59,67 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 52 | 59 | // 校验存在 |
| 53 | 60 | this.validateSkuExists(id); |
| 54 | 61 | // 删除 |
| 55 | - ProductSkuMapper.deleteById(id); | |
| 62 | + productSkuMapper.deleteById(id); | |
| 56 | 63 | } |
| 57 | 64 | |
| 58 | 65 | private void validateSkuExists(Long id) { |
| 59 | - if (ProductSkuMapper.selectById(id) == null) { | |
| 66 | + if (productSkuMapper.selectById(id) == null) { | |
| 60 | 67 | throw exception(SKU_NOT_EXISTS); |
| 61 | 68 | } |
| 62 | 69 | } |
| 63 | 70 | |
| 64 | 71 | @Override |
| 65 | 72 | public ProductSkuDO getSku(Long id) { |
| 66 | - return ProductSkuMapper.selectById(id); | |
| 73 | + return productSkuMapper.selectById(id); | |
| 67 | 74 | } |
| 68 | 75 | |
| 69 | 76 | @Override |
| 70 | 77 | public List<ProductSkuDO> getSkuList(Collection<Long> ids) { |
| 71 | - return ProductSkuMapper.selectBatchIds(ids); | |
| 78 | + return productSkuMapper.selectBatchIds(ids); | |
| 72 | 79 | } |
| 73 | 80 | |
| 74 | 81 | @Override |
| 75 | 82 | public PageResult<ProductSkuDO> getSkuPage(ProductSkuPageReqVO pageReqVO) { |
| 76 | - return ProductSkuMapper.selectPage(pageReqVO); | |
| 83 | + return productSkuMapper.selectPage(pageReqVO); | |
| 77 | 84 | } |
| 78 | 85 | |
| 79 | 86 | @Override |
| 80 | 87 | public List<ProductSkuDO> getSkuList(ProductSkuExportReqVO exportReqVO) { |
| 81 | - return ProductSkuMapper.selectList(exportReqVO); | |
| 88 | + return productSkuMapper.selectList(exportReqVO); | |
| 82 | 89 | } |
| 83 | 90 | |
| 84 | 91 | @Override |
| 85 | 92 | public void validatedSkuReq(List<ProductSkuCreateReqVO> skuCreateReqList) { |
| 93 | + List<ProductSkuBaseVO.Property> skuPropertyList = skuCreateReqList.stream().flatMap(p -> p.getProperties().stream()).collect(Collectors.toList()); | |
| 86 | 94 | // 校验规格属性以及规格值是否存在 |
| 87 | - List<Integer> propertyIds = skuCreateReqList.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); | |
| 88 | - | |
| 95 | + List<Integer> propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); | |
| 96 | + List<ProductPropertyRespVO> propertyAndValueList = productPropertyService.selectByIds(propertyIds); | |
| 97 | + if (propertyAndValueList.isEmpty()) | |
| 98 | + throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); | |
| 99 | + Map<Long, ProductPropertyRespVO> propertyMap = propertyAndValueList.stream().collect(Collectors.toMap(ProductPropertyRespVO::getId, p -> p)); | |
| 100 | + skuPropertyList.forEach(p -> { | |
| 101 | + ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId()); | |
| 102 | + // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示 | |
| 103 | + if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) | |
| 104 | + throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); | |
| 105 | + // 判断改属性名对应的属性值是否存在,不存在,给出提示 | |
| 106 | + if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) { | |
| 107 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); | |
| 108 | + } | |
| 109 | + }); | |
| 89 | 110 | // 校验是否有重复的sku组合 |
| 111 | + List<List<ProductSkuBaseVO.Property>> skuProperties = skuCreateReqList.stream().map(ProductSkuBaseVO::getProperties).collect(Collectors.toList()); | |
| 112 | + Set<String> skuPropertiesConvertSet = new HashSet<>(); | |
| 113 | + skuProperties.forEach(p -> { | |
| 114 | + // 组合属性值id为 1~2~3.... 形式的字符串,通过set的特性判断是否有重复的组合 | |
| 115 | + if (!skuPropertiesConvertSet.add(p.stream().map(pr -> String.valueOf(pr.getValueId())).sorted().collect(Collectors.joining("~")))) { | |
| 116 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); | |
| 117 | + } | |
| 118 | + }); | |
| 119 | + } | |
| 120 | + | |
| 121 | + @Override | |
| 122 | + public void batchSave(List<ProductSkuDO> skuDOList) { | |
| 123 | + productSkuMapper.insertBatch(skuDOList); | |
| 90 | 124 | } |
| 91 | 125 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.product.service.spu; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; |
| 4 | +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | |
| 5 | +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | |
| 4 | 6 | import cn.iocoder.yudao.module.product.service.category.CategoryService; |
| 5 | 7 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| 6 | 8 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -11,6 +13,8 @@ import org.springframework.transaction.annotation.Transactional; |
| 11 | 13 | import org.springframework.validation.annotation.Validated; |
| 12 | 14 | |
| 13 | 15 | import java.util.*; |
| 16 | +import java.util.stream.Collectors; | |
| 17 | + | |
| 14 | 18 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 15 | 19 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 16 | 20 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| ... | ... | @@ -47,12 +51,16 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 47 | 51 | // 校验SKU |
| 48 | 52 | List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getProductSkuCreateReqVOS(); |
| 49 | 53 | productSkuService.validatedSkuReq(skuCreateReqList); |
| 50 | - // 插入 | |
| 54 | + // 插入SPU | |
| 51 | 55 | ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); |
| 56 | + ProductSpuMapper.insert(spu); | |
| 57 | + // sku关联SPU属性 | |
| 52 | 58 | skuCreateReqList.forEach(p -> { |
| 53 | 59 | p.setSpuId(spu.getId()); |
| 54 | 60 | }); |
| 55 | - ProductSpuMapper.insert(spu); | |
| 61 | + List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); | |
| 62 | + // 批量插入sku | |
| 63 | + productSkuService.batchSave(skuDOList); | |
| 56 | 64 | // 返回 |
| 57 | 65 | return spu.getId(); |
| 58 | 66 | } | ... | ... |
yudao-ui-admin/src/views/mall/product/spu/index.vue
| ... | ... | @@ -20,14 +20,14 @@ |
| 20 | 20 | </el-form-item> |
| 21 | 21 | <el-form-item label="状态" prop="status"> |
| 22 | 22 | <el-select v-model="queryParams.status" placeholder="请选择上下架状态" clearable size="small"> |
| 23 | - <el-option label="请选择字典生成" value="" /> | |
| 24 | - <el-option label="上架" value="0" /> | |
| 25 | - <el-option label="下架" value="1" /> | |
| 23 | + <el-option label="请选择字典生成" value=""/> | |
| 24 | + <el-option label="上架" value="0"/> | |
| 25 | + <el-option label="下架" value="1"/> | |
| 26 | 26 | </el-select> |
| 27 | 27 | </el-form-item> |
| 28 | 28 | <el-form-item label="创建时间"> |
| 29 | 29 | <el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd" |
| 30 | - type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" /> | |
| 30 | + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/> | |
| 31 | 31 | </el-form-item> |
| 32 | 32 | <el-form-item> |
| 33 | 33 | <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> |
| ... | ... | @@ -39,28 +39,31 @@ |
| 39 | 39 | <el-row :gutter="10" class="mb8"> |
| 40 | 40 | <el-col :span="1.5"> |
| 41 | 41 | <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" |
| 42 | - v-hasPermi="['product:spu:create']">新增</el-button> | |
| 42 | + v-hasPermi="['product:spu:create']">新增 | |
| 43 | + </el-button> | |
| 43 | 44 | </el-col> |
| 44 | 45 | <el-col :span="1.5"> |
| 45 | - <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading" | |
| 46 | - v-hasPermi="['product:spu:export']">导出</el-button> | |
| 46 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" | |
| 47 | + :loading="exportLoading" | |
| 48 | + v-hasPermi="['product:spu:export']">导出 | |
| 49 | + </el-button> | |
| 47 | 50 | </el-col> |
| 48 | 51 | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| 49 | 52 | </el-row> |
| 50 | 53 | |
| 51 | 54 | <!-- 列表 --> |
| 52 | 55 | <el-table v-loading="loading" :data="list"> |
| 53 | - <el-table-column label="主键" align="center" prop="id" /> | |
| 54 | - <el-table-column label="商品名称" align="center" prop="name" /> | |
| 55 | - <el-table-column label="卖点" align="center" prop="sellPoint" /> | |
| 56 | - <el-table-column label="描述" align="center" prop="description" /> | |
| 57 | - <el-table-column label="分类id" align="center" prop="categoryId" /> | |
| 58 | - <el-table-column label="商品主图地址" align="center" prop="picUrls" /> | |
| 59 | - <el-table-column label="排序字段" align="center" prop="sort" /> | |
| 60 | - <el-table-column label="点赞初始人数" align="center" prop="likeCount" /> | |
| 61 | - <el-table-column label="价格 (分)" align="center" prop="price" /> | |
| 62 | - <el-table-column label="库存数量" align="center" prop="quantity" /> | |
| 63 | - <el-table-column label="状态" align="center" prop="status" /> | |
| 56 | + <el-table-column label="主键" align="center" prop="id"/> | |
| 57 | + <el-table-column label="商品名称" align="center" prop="name"/> | |
| 58 | + <el-table-column label="卖点" align="center" prop="sellPoint"/> | |
| 59 | + <el-table-column label="描述" align="center" prop="description"/> | |
| 60 | + <el-table-column label="分类id" align="center" prop="categoryId"/> | |
| 61 | + <el-table-column label="商品主图地址" align="center" prop="picUrls"/> | |
| 62 | + <el-table-column label="排序字段" align="center" prop="sort"/> | |
| 63 | + <el-table-column label="点赞初始人数" align="center" prop="likeCount"/> | |
| 64 | + <el-table-column label="价格 (分)" align="center" prop="price"/> | |
| 65 | + <el-table-column label="库存数量" align="center" prop="quantity"/> | |
| 66 | + <el-table-column label="状态" align="center" prop="status"/> | |
| 64 | 67 | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| 65 | 68 | <template slot-scope="scope"> |
| 66 | 69 | <span>{{ parseTime(scope.row.createTime) }}</span> |
| ... | ... | @@ -69,9 +72,11 @@ |
| 69 | 72 | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| 70 | 73 | <template slot-scope="scope"> |
| 71 | 74 | <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" |
| 72 | - v-hasPermi="['product:spu:update']">修改</el-button> | |
| 75 | + v-hasPermi="['product:spu:update']">修改 | |
| 76 | + </el-button> | |
| 73 | 77 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" |
| 74 | - v-hasPermi="['product:spu:delete']">删除</el-button> | |
| 78 | + v-hasPermi="['product:spu:delete']">删除 | |
| 79 | + </el-button> | |
| 75 | 80 | </template> |
| 76 | 81 | </el-table-column> |
| 77 | 82 | </el-table> |
| ... | ... | @@ -83,31 +88,91 @@ |
| 83 | 88 | <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body> |
| 84 | 89 | <el-form ref="form" :model="form" :rules="rules" label-width="80px"> |
| 85 | 90 | <el-form-item label="商品名称" prop="name"> |
| 86 | - <el-input v-model="form.name" placeholder="请输入商品名称" /> | |
| 91 | + <el-input v-model="form.name" placeholder="请输入商品名称"/> | |
| 87 | 92 | </el-form-item> |
| 88 | 93 | <el-form-item label="卖点" prop="sellPoint"> |
| 89 | - <el-input v-model="form.sellPoint" placeholder="请输入卖点" /> | |
| 94 | + <el-input v-model="form.sellPoint" placeholder="请输入卖点"/> | |
| 90 | 95 | </el-form-item> |
| 91 | 96 | <el-form-item label="描述"> |
| 92 | 97 | <editor v-model="form.description" :min-height="192"/> |
| 93 | 98 | </el-form-item> |
| 94 | - <el-form-item label="分类id" prop="categoryId"> | |
| 95 | - <el-input v-model="form.categoryId" placeholder="请输入分类id" /> | |
| 99 | + <el-form-item label="分类id" prop="categoryIds"> | |
| 100 | + <el-cascader | |
| 101 | + v-model="form.categoryIds" | |
| 102 | + placeholder="请输入分类id" | |
| 103 | + style="width: 100%" | |
| 104 | + :options="categoryList" | |
| 105 | + :props="propName" | |
| 106 | + clearable></el-cascader> | |
| 96 | 107 | </el-form-item> |
| 97 | 108 | <el-form-item label="商品主图地址" prop="picUrls"> |
| 98 | - <ImageUpload v-model="form.picUrls" :limit="1"/> | |
| 109 | + <ImageUpload v-model="form.picUrls" :limit="10"/> | |
| 99 | 110 | </el-form-item> |
| 111 | + <el-form-item label="商品规格"> | |
| 112 | + <el-button size="mini" @click="shopTagInput()">添加规格</el-button> | |
| 113 | + <div v-for="(tag, tagIndex) in skuTags" :key="tagIndex"> | |
| 114 | + <span>{{tag.tagName}}</span> | |
| 115 | + <el-button class="button-new-tag" type="text" icon="el-icon-delete" @click="removeTag(tagIndex)">删除</el-button> | |
| 116 | + <br/> | |
| 117 | + <el-tag | |
| 118 | + v-for="(tagItem, tagItemIndex) in tag.tagItems" | |
| 119 | + :key="tagItem.valueId" | |
| 120 | + closable | |
| 121 | + :disable-transitions="false" | |
| 122 | + @close="handleTagClose(tagIndex, tagItemIndex)"> | |
| 123 | + {{tagItem.propValue}} | |
| 124 | + </el-tag> | |
| 125 | + <el-input | |
| 126 | + class="input-new-tag" | |
| 127 | + v-if="tagItemInputs[tagIndex] && tagItemInputs[tagIndex].visible" | |
| 128 | + v-model="tagItemInputs[tagIndex].value" | |
| 129 | + :ref="`saveTagInput${tagIndex}`" | |
| 130 | + size="small" | |
| 131 | + @keyup.enter.native="handleInputConfirm(tagIndex)" | |
| 132 | + @blur="handleInputConfirm(tagIndex)"> | |
| 133 | + </el-input> | |
| 134 | + </div> | |
| 135 | + </el-form-item> | |
| 136 | + <el-form-item label="规格名" v-show="isShowTagInput"> | |
| 137 | + <el-col :span="8"> | |
| 138 | + <el-select v-model="addTagInput.name" filterable allow-create default-first-option placeholder="请选择" @change="handleTagClick"> | |
| 139 | + <el-option | |
| 140 | + v-for="item in unUseTags" | |
| 141 | + :key="item.id" | |
| 142 | + :label="item.name" | |
| 143 | + :value="item.name"> | |
| 144 | + </el-option> | |
| 145 | + </el-select> | |
| 146 | + </el-col> | |
| 147 | + </el-form-item> | |
| 148 | + <el-form-item label="规格值" v-show="isShowTagInput"> | |
| 149 | + <el-col :span="8"> | |
| 150 | + <el-select v-model="addTagInput.selectValues" multiple filterable allow-create default-first-option placeholder="请选择"> | |
| 151 | + <el-option | |
| 152 | + v-for="item in dbTagValues" | |
| 153 | + :key="item.valueId" | |
| 154 | + :label="item.propValue" | |
| 155 | + :value="item.propValue"> | |
| 156 | + </el-option> | |
| 157 | + </el-select> | |
| 158 | + </el-col> | |
| 159 | + </el-form-item> | |
| 160 | + <el-form-item> | |
| 161 | + <el-button size="mini" type="primary" @click="addTag()" v-show="isShowTagInput">确定</el-button> | |
| 162 | + <el-button size="mini" @click="hideTagInput()" v-show="isShowTagInput">取消</el-button> | |
| 163 | + </el-form-item> | |
| 164 | + | |
| 100 | 165 | <el-form-item label="排序字段" prop="sort"> |
| 101 | - <el-input v-model="form.sort" placeholder="请输入排序字段" /> | |
| 166 | + <el-input v-model="form.sort" placeholder="请输入排序字段"/> | |
| 102 | 167 | </el-form-item> |
| 103 | 168 | <el-form-item label="点赞初始人数" prop="likeCount"> |
| 104 | - <el-input v-model="form.likeCount" placeholder="请输入点赞初始人数" /> | |
| 169 | + <el-input v-model="form.likeCount" placeholder="请输入点赞初始人数"/> | |
| 105 | 170 | </el-form-item> |
| 106 | 171 | <el-form-item label="价格 单位使用:分" prop="price"> |
| 107 | - <el-input v-model="form.price" placeholder="请输入价格 单位使用:分" /> | |
| 172 | + <el-input v-model="form.price" placeholder="请输入价格 单位使用:分"/> | |
| 108 | 173 | </el-form-item> |
| 109 | 174 | <el-form-item label="库存数量" prop="quantity"> |
| 110 | - <el-input v-model="form.quantity" placeholder="请输入库存数量" /> | |
| 175 | + <el-input v-model="form.quantity" placeholder="请输入库存数量"/> | |
| 111 | 176 | </el-form-item> |
| 112 | 177 | <el-form-item label="上下架状态" prop="status"> |
| 113 | 178 | <el-radio-group v-model="form.status"> |
| ... | ... | @@ -125,173 +190,242 @@ |
| 125 | 190 | </template> |
| 126 | 191 | |
| 127 | 192 | <script> |
| 128 | -import { createSpu, updateSpu, deleteSpu, getSpu, getSpuPage, exportSpuExcel } from "@/api/mall/product/spu"; | |
| 129 | -import Editor from '@/components/Editor'; | |
| 193 | + import {createSpu, updateSpu, deleteSpu, getSpu, getSpuPage, exportSpuExcel} from "@/api/mall/product/spu"; | |
| 194 | + import { | |
| 195 | + createCategory, | |
| 196 | + deleteCategory, | |
| 197 | + exportCategoryExcel, | |
| 198 | + getCategory, | |
| 199 | + listCategory, | |
| 200 | + updateCategory | |
| 201 | + } from "@/api/mall/product/category"; | |
| 202 | + import { createProperty, updateProperty, deleteProperty, getProperty, getPropertyPage, exportPropertyExcel } from "@/api/mall/product/property"; | |
| 130 | 203 | |
| 131 | -export default { | |
| 132 | - name: "Spu", | |
| 133 | - components: { | |
| 134 | - Editor, | |
| 135 | - }, | |
| 136 | - data() { | |
| 137 | - return { | |
| 138 | - // 遮罩层 | |
| 139 | - loading: true, | |
| 140 | - // 导出遮罩层 | |
| 141 | - exportLoading: false, | |
| 142 | - // 显示搜索条件 | |
| 143 | - showSearch: true, | |
| 144 | - // 总条数 | |
| 145 | - total: 0, | |
| 146 | - // 商品spu列表 | |
| 147 | - list: [], | |
| 148 | - // 弹出层标题 | |
| 149 | - title: "", | |
| 150 | - // 是否显示弹出层 | |
| 151 | - open: false, | |
| 152 | - dateRangeCreateTime: [], | |
| 153 | - // 查询参数 | |
| 154 | - queryParams: { | |
| 155 | - pageNo: 1, | |
| 156 | - pageSize: 10, | |
| 157 | - name: null, | |
| 158 | - sellPoint: null, | |
| 159 | - description: null, | |
| 160 | - categoryId: null, | |
| 161 | - picUrls: null, | |
| 162 | - sort: null, | |
| 163 | - likeCount: null, | |
| 164 | - price: null, | |
| 165 | - quantity: null, | |
| 166 | - status: null, | |
| 167 | - }, | |
| 168 | - // 表单参数 | |
| 169 | - form: {}, | |
| 170 | - // 表单校验 | |
| 171 | - rules: { | |
| 172 | - sellPoint: [{ required: true, message: "卖点不能为空", trigger: "blur" }], | |
| 173 | - description: [{ required: true, message: "描述不能为空", trigger: "blur" }], | |
| 174 | - categoryId: [{ required: true, message: "分类id不能为空", trigger: "blur" }], | |
| 175 | - picUrls: [{ required: true, message: "商品主图地址", trigger: "blur" }], | |
| 176 | - sort: [{ required: true, message: "排序字段不能为空", trigger: "blur" }], | |
| 177 | - } | |
| 178 | - }; | |
| 179 | - }, | |
| 180 | - created() { | |
| 181 | - this.getList(); | |
| 182 | - }, | |
| 183 | - methods: { | |
| 184 | - /** 查询列表 */ | |
| 185 | - getList() { | |
| 186 | - this.loading = true; | |
| 187 | - // 处理查询参数 | |
| 188 | - let params = {...this.queryParams}; | |
| 189 | - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 190 | - // 执行查询 | |
| 191 | - getSpuPage(params).then(response => { | |
| 192 | - this.list = response.data.list; | |
| 193 | - this.total = response.data.total; | |
| 194 | - this.loading = false; | |
| 195 | - }); | |
| 196 | - }, | |
| 197 | - /** 取消按钮 */ | |
| 198 | - cancel() { | |
| 199 | - this.open = false; | |
| 200 | - this.reset(); | |
| 201 | - }, | |
| 202 | - /** 表单重置 */ | |
| 203 | - reset() { | |
| 204 | - this.form = { | |
| 205 | - id: undefined, | |
| 206 | - name: undefined, | |
| 207 | - sellPoint: undefined, | |
| 208 | - description: undefined, | |
| 209 | - categoryId: undefined, | |
| 210 | - picUrls: undefined, | |
| 211 | - sort: undefined, | |
| 212 | - likeCount: undefined, | |
| 213 | - price: undefined, | |
| 214 | - quantity: undefined, | |
| 215 | - status: undefined, | |
| 216 | - }; | |
| 217 | - this.resetForm("form"); | |
| 218 | - }, | |
| 219 | - /** 搜索按钮操作 */ | |
| 220 | - handleQuery() { | |
| 221 | - this.queryParams.pageNo = 1; | |
| 222 | - this.getList(); | |
| 223 | - }, | |
| 224 | - /** 重置按钮操作 */ | |
| 225 | - resetQuery() { | |
| 226 | - this.dateRangeCreateTime = []; | |
| 227 | - this.resetForm("queryForm"); | |
| 228 | - this.handleQuery(); | |
| 229 | - }, | |
| 230 | - /** 新增按钮操作 */ | |
| 231 | - handleAdd() { | |
| 232 | - this.reset(); | |
| 233 | - this.open = true; | |
| 234 | - this.title = "添加商品spu"; | |
| 235 | - }, | |
| 236 | - /** 修改按钮操作 */ | |
| 237 | - handleUpdate(row) { | |
| 238 | - this.reset(); | |
| 239 | - const id = row.id; | |
| 240 | - getSpu(id).then(response => { | |
| 241 | - this.form = response.data; | |
| 242 | - this.open = true; | |
| 243 | - this.title = "修改商品spu"; | |
| 244 | - }); | |
| 245 | - }, | |
| 246 | - /** 提交按钮 */ | |
| 247 | - submitForm() { | |
| 248 | - this.$refs["form"].validate(valid => { | |
| 249 | - if (!valid) { | |
| 250 | - return; | |
| 251 | - } | |
| 252 | - // 修改的提交 | |
| 253 | - if (this.form.id != null) { | |
| 254 | - updateSpu(this.form).then(response => { | |
| 255 | - this.$modal.msgSuccess("修改成功"); | |
| 256 | - this.open = false; | |
| 204 | + import Editor from '@/components/Editor'; | |
| 205 | + import ImageUpload from '@/components/ImageUpload'; | |
| 206 | + export default { | |
| 207 | + name: "Spu", | |
| 208 | + components: { | |
| 209 | + Editor,ImageUpload | |
| 210 | + }, | |
| 211 | + data() { | |
| 212 | + return { | |
| 213 | + dbTagValues:[], | |
| 214 | + unUseTags:[], | |
| 215 | + propertyPageList:[], | |
| 216 | + isShowTagInput: false, | |
| 217 | + addTagInput: { | |
| 218 | + name: '', | |
| 219 | + selectValues: [] | |
| 220 | + }, | |
| 221 | + skuTags:[], | |
| 222 | + propName: { | |
| 223 | + checkStrictly: true, | |
| 224 | + label:'name', | |
| 225 | + value:'id' | |
| 226 | + }, | |
| 227 | + categoryList: [], | |
| 228 | + // 遮罩层 | |
| 229 | + loading: true, | |
| 230 | + // 导出遮罩层 | |
| 231 | + exportLoading: false, | |
| 232 | + // 显示搜索条件 | |
| 233 | + showSearch: true, | |
| 234 | + // 总条数 | |
| 235 | + total: 0, | |
| 236 | + // 商品spu列表 | |
| 237 | + list: [], | |
| 238 | + // 弹出层标题 | |
| 239 | + title: "", | |
| 240 | + // 是否显示弹出层 | |
| 241 | + open: false, | |
| 242 | + dateRangeCreateTime: [], | |
| 243 | + // 查询参数 | |
| 244 | + queryParams: { | |
| 245 | + pageNo: 1, | |
| 246 | + pageSize: 10, | |
| 247 | + name: null, | |
| 248 | + sellPoint: null, | |
| 249 | + description: null, | |
| 250 | + categoryId: null, | |
| 251 | + picUrls: null, | |
| 252 | + sort: null, | |
| 253 | + likeCount: null, | |
| 254 | + price: null, | |
| 255 | + quantity: null, | |
| 256 | + status: null, | |
| 257 | + }, | |
| 258 | + // 表单参数 | |
| 259 | + form: {}, | |
| 260 | + // 表单校验 | |
| 261 | + rules: { | |
| 262 | + sellPoint: [{required: true, message: "卖点不能为空", trigger: "blur"}], | |
| 263 | + description: [{required: true, message: "描述不能为空", trigger: "blur"}], | |
| 264 | + categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"}], | |
| 265 | + picUrls: [{required: true, message: "商品主图地址", trigger: "blur"}], | |
| 266 | + sort: [{required: true, message: "排序字段不能为空", trigger: "blur"}], | |
| 267 | + } | |
| 268 | + }; | |
| 269 | + }, | |
| 270 | + created() { | |
| 257 | 271 | this.getList(); |
| 258 | - }); | |
| 259 | - return; | |
| 272 | + this.getListCategory(); | |
| 273 | + this.getPropertyPageList(); | |
| 274 | + }, | |
| 275 | + methods: { | |
| 276 | + addTag(){ | |
| 277 | + | |
| 278 | + }, | |
| 279 | + hideTagInput(){ | |
| 280 | + | |
| 281 | + }, | |
| 282 | + shopTagInput(){ | |
| 283 | + | |
| 284 | + }, | |
| 285 | + removeTag(row){ | |
| 286 | + | |
| 287 | + }, | |
| 288 | + handleTagClick(row){ | |
| 289 | + | |
| 290 | + }, | |
| 291 | + /** 查询规格 */ | |
| 292 | + getPropertyPageList() { | |
| 293 | + // 执行查询 | |
| 294 | + getPropertyPage().then(response => { | |
| 295 | + this.propertyPageList = response.data.list; | |
| 296 | + this.unUseTags= this.propertyPageList.map(function (item,index) { | |
| 297 | + return item | |
| 298 | + }) | |
| 299 | + console.log(this.propertyPageList) | |
| 300 | + }); | |
| 301 | + }, | |
| 302 | + /** 查询分类 */ | |
| 303 | + getListCategory() { | |
| 304 | + // 执行查询 | |
| 305 | + listCategory().then(response => { | |
| 306 | + this.categoryList = this.handleTree(response.data, "id", "parentId"); | |
| 307 | + | |
| 308 | + }); | |
| 309 | + }, | |
| 310 | + /** 查询列表 */ | |
| 311 | + getList() { | |
| 312 | + this.loading = true; | |
| 313 | + // 处理查询参数 | |
| 314 | + let params = {...this.queryParams}; | |
| 315 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 316 | + // 执行查询 | |
| 317 | + getSpuPage(params).then(response => { | |
| 318 | + this.list = response.data.list; | |
| 319 | + this.total = response.data.total; | |
| 320 | + this.loading = false; | |
| 321 | + }); | |
| 322 | + }, | |
| 323 | + /** 取消按钮 */ | |
| 324 | + cancel() { | |
| 325 | + this.open = false; | |
| 326 | + this.reset(); | |
| 327 | + }, | |
| 328 | + /** 表单重置 */ | |
| 329 | + reset() { | |
| 330 | + this.form = { | |
| 331 | + id: undefined, | |
| 332 | + name: undefined, | |
| 333 | + sellPoint: undefined, | |
| 334 | + description: undefined, | |
| 335 | + categoryId: undefined, | |
| 336 | + categoryIds: [], | |
| 337 | + picUrls: undefined, | |
| 338 | + sort: undefined, | |
| 339 | + likeCount: undefined, | |
| 340 | + price: undefined, | |
| 341 | + quantity: undefined, | |
| 342 | + status: undefined, | |
| 343 | + isShowTagInput:undefined, | |
| 344 | + | |
| 345 | + }; | |
| 346 | + this.resetForm("form"); | |
| 347 | + }, | |
| 348 | + /** 搜索按钮操作 */ | |
| 349 | + handleQuery() { | |
| 350 | + this.queryParams.pageNo = 1; | |
| 351 | + this.getList(); | |
| 352 | + }, | |
| 353 | + /** 重置按钮操作 */ | |
| 354 | + resetQuery() { | |
| 355 | + this.dateRangeCreateTime = []; | |
| 356 | + this.resetForm("queryForm"); | |
| 357 | + this.handleQuery(); | |
| 358 | + }, | |
| 359 | + /** 新增按钮操作 */ | |
| 360 | + handleAdd() { | |
| 361 | + this.reset(); | |
| 362 | + this.open = true; | |
| 363 | + this.title = "添加商品spu"; | |
| 364 | + }, | |
| 365 | + /** 修改按钮操作 */ | |
| 366 | + handleUpdate(row) { | |
| 367 | + this.reset(); | |
| 368 | + const id = row.id; | |
| 369 | + getSpu(id).then(response => { | |
| 370 | + this.form = response.data; | |
| 371 | + this.open = true; | |
| 372 | + this.title = "修改商品spu"; | |
| 373 | + }); | |
| 374 | + }, | |
| 375 | + /** 提交按钮 */ | |
| 376 | + submitForm() { | |
| 377 | + console.log(this.form.picUrls.split(',')); | |
| 378 | + | |
| 379 | + this.$refs["form"].validate(valid => { | |
| 380 | + if (!valid) { | |
| 381 | + return; | |
| 382 | + } | |
| 383 | + this.form.categoryId= this.form.categoryIds[(this.form.categoryIds.length-1)] | |
| 384 | + // 修改的提交 | |
| 385 | + if (this.form.id != null) { | |
| 386 | + updateSpu(this.form).then(response => { | |
| 387 | + this.$modal.msgSuccess("修改成功"); | |
| 388 | + this.open = false; | |
| 389 | + this.getList(); | |
| 390 | + }); | |
| 391 | + return; | |
| 392 | + } | |
| 393 | + // 添加的提交 | |
| 394 | + createSpu(this.form).then(response => { | |
| 395 | + this.$modal.msgSuccess("新增成功"); | |
| 396 | + this.open = false; | |
| 397 | + this.getList(); | |
| 398 | + }); | |
| 399 | + }); | |
| 400 | + }, | |
| 401 | + /** 删除按钮操作 */ | |
| 402 | + handleDelete(row) { | |
| 403 | + const id = row.id; | |
| 404 | + this.$modal.confirm('是否确认删除商品spu编号为"' + id + '"的数据项?').then(function () { | |
| 405 | + return deleteSpu(id); | |
| 406 | + }).then(() => { | |
| 407 | + this.getList(); | |
| 408 | + this.$modal.msgSuccess("删除成功"); | |
| 409 | + }).catch(() => { | |
| 410 | + }); | |
| 411 | + }, | |
| 412 | + /** 导出按钮操作 */ | |
| 413 | + handleExport() { | |
| 414 | + // 处理查询参数 | |
| 415 | + let params = {...this.queryParams}; | |
| 416 | + params.pageNo = undefined; | |
| 417 | + params.pageSize = undefined; | |
| 418 | + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 419 | + // 执行导出 | |
| 420 | + this.$modal.confirm('是否确认导出所有商品spu数据项?').then(() => { | |
| 421 | + this.exportLoading = true; | |
| 422 | + return exportSpuExcel(params); | |
| 423 | + }).then(response => { | |
| 424 | + this.$download.excel(response, '商品spu.xls'); | |
| 425 | + this.exportLoading = false; | |
| 426 | + }).catch(() => { | |
| 427 | + }); | |
| 428 | + } | |
| 260 | 429 | } |
| 261 | - // 添加的提交 | |
| 262 | - createSpu(this.form).then(response => { | |
| 263 | - this.$modal.msgSuccess("新增成功"); | |
| 264 | - this.open = false; | |
| 265 | - this.getList(); | |
| 266 | - }); | |
| 267 | - }); | |
| 268 | - }, | |
| 269 | - /** 删除按钮操作 */ | |
| 270 | - handleDelete(row) { | |
| 271 | - const id = row.id; | |
| 272 | - this.$modal.confirm('是否确认删除商品spu编号为"' + id + '"的数据项?').then(function() { | |
| 273 | - return deleteSpu(id); | |
| 274 | - }).then(() => { | |
| 275 | - this.getList(); | |
| 276 | - this.$modal.msgSuccess("删除成功"); | |
| 277 | - }).catch(() => {}); | |
| 278 | - }, | |
| 279 | - /** 导出按钮操作 */ | |
| 280 | - handleExport() { | |
| 281 | - // 处理查询参数 | |
| 282 | - let params = {...this.queryParams}; | |
| 283 | - params.pageNo = undefined; | |
| 284 | - params.pageSize = undefined; | |
| 285 | - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); | |
| 286 | - // 执行导出 | |
| 287 | - this.$modal.confirm('是否确认导出所有商品spu数据项?').then(() => { | |
| 288 | - this.exportLoading = true; | |
| 289 | - return exportSpuExcel(params); | |
| 290 | - }).then(response => { | |
| 291 | - this.$download.excel(response, '商品spu.xls'); | |
| 292 | - this.exportLoading = false; | |
| 293 | - }).catch(() => {}); | |
| 294 | - } | |
| 295 | - } | |
| 296 | -}; | |
| 430 | + }; | |
| 297 | 431 | </script> | ... | ... |