Commit f07bf8b0fd5bf043a60b636b41d1dde0aa4be17e

Authored by franky
1 parent 6dca8e08

spu保存校验添加

yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
... ... @@ -28,4 +28,5 @@ public interface ErrorCodeConstants {
28 28  
29 29 // ========== 商品sku 1008006000 ==========
30 30 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在");
  31 + ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复");
31 32 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
... ... @@ -45,7 +45,9 @@ public class ProductSkuBaseVO {
45 45  
46 46 @Data
47 47 public static class Property {
  48 + @NotNull(message = "规格属性名id不能为空")
48 49 private Integer propertyId;
  50 + @NotNull(message = "规格属性值id不能为空")
49 51 private Integer valueId;
50 52 }
51 53  
... ...
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>
... ...