Commit a11dd1be282b9c92d70b60458958c4d65690ba1e

Authored by YunaiV
2 parents f03d679f 8de29d30

Merge remote-tracking branch 'origin/feature/1.8.0-uniapp' into feature/1.8.0-uniapp

# Conflicts:
#	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/controller/admin/spu/vo/ProductSpuBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
sql/optional/mall/mall.sql
@@ -298,3 +298,27 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, ` @@ -298,3 +298,27 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `
298 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2027, 'Banner创建', 'market:banner:create', 3, 2, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0'); 298 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2027, 'Banner创建', 'market:banner:create', 3, 2, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
299 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'market:banner:update', 3, 3, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0'); 299 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2028, 'Banner更新', 'market:banner:update', 3, 3, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
300 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0'); 300 INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0');
  301 +
  302 +alter table product_spu add `code` varchar(128) COMMENT '商品编码';
  303 +alter table product_spu add total_stock int COMMENT '总库存';
  304 +alter table product_spu add warn_stock int COMMENT '预警预存';
  305 +alter table product_spu add show_stock int COMMENT '是否展示库存';
  306 +alter table product_spu add sales_count int COMMENT '商品销量';
  307 +alter table product_spu add virtual_sales_count int COMMENT '虚拟销量';
  308 +alter table product_spu add click_count int COMMENT '商品点击量';
  309 +alter table product_spu add banner_url varchar(128) COMMENT '主图地址';
  310 +alter table product_spu add spec_type int COMMENT '规格类型';
  311 +alter table product_spu add brand_id int COMMENT '商品品牌编号';
  312 +alter table product_spu add video_url varchar(128) COMMENT '商品视频';
  313 +alter table product_spu add min_price int COMMENT '最小价格,单位使用:分';
  314 +alter table product_spu add max_price int COMMENT '最大价格,单位使用:分';
  315 +alter table product_spu add market_price int COMMENT '市场价,单位使用:分';
  316 +
  317 +
  318 +alter table product_sku add `name` varchar(128) COMMENT '商品 SKU 名字';
  319 +alter table product_sku add `stock` int COMMENT '库存';
  320 +alter table product_sku add `weight` double COMMENT '商品重量';
  321 +alter table product_sku add `volume` double COMMENT '商品体积';
  322 +
  323 +
  324 +alter table product_sku DROP `original_price`;
301 \ No newline at end of file 325 \ No newline at end of file
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
@@ -38,7 +38,6 @@ public class ProductSkuBaseVO { @@ -38,7 +38,6 @@ public class ProductSkuBaseVO {
38 private Integer costPrice; 38 private Integer costPrice;
39 39
40 @ApiModelProperty(value = "条形码", example = "haha") 40 @ApiModelProperty(value = "条形码", example = "haha")
41 - @NotNull(message = "条形码不能为空")  
42 private String barCode; 41 private String barCode;
43 42
44 @ApiModelProperty(value = "图片地址") 43 @ApiModelProperty(value = "图片地址")
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
@@ -49,7 +49,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @@ -49,7 +49,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
49 //插入属性值 49 //插入属性值
50 List<ProductPropertyValueCreateReqVO> propertyValueList = createReqVO.getPropertyValueList(); 50 List<ProductPropertyValueCreateReqVO> propertyValueList = createReqVO.getPropertyValueList();
51 List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); 51 List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList);
52 - productPropertyValueDOList.stream().forEach(x-> x.setPropertyId(property.getId())); 52 + productPropertyValueDOList.forEach(x-> x.setPropertyId(property.getId()));
53 productPropertyValueMapper.insertBatch(productPropertyValueDOList); 53 productPropertyValueMapper.insertBatch(productPropertyValueDOList);
54 // 返回 54 // 返回
55 return property.getId(); 55 return property.getId();
@@ -67,7 +67,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @@ -67,7 +67,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
67 productPropertyValueMapper.deletePropertyValueByPropertyId(updateReqVO.getId()); 67 productPropertyValueMapper.deletePropertyValueByPropertyId(updateReqVO.getId());
68 List<ProductPropertyValueCreateReqVO> propertyValueList = updateReqVO.getPropertyValueList(); 68 List<ProductPropertyValueCreateReqVO> propertyValueList = updateReqVO.getPropertyValueList();
69 List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList); 69 List<ProductPropertyValueDO> productPropertyValueDOList = ProductPropertyValueConvert.INSTANCE.convertList03(propertyValueList);
70 - productPropertyValueDOList.stream().forEach(x-> x.setPropertyId(updateReqVO.getId())); 70 + productPropertyValueDOList.forEach(x-> x.setPropertyId(updateReqVO.getId()));
71 productPropertyValueMapper.insertBatch(productPropertyValueDOList); 71 productPropertyValueMapper.insertBatch(productPropertyValueDOList);
72 } 72 }
73 73
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -2,9 +2,14 @@ package cn.iocoder.yudao.module.product.service.sku; @@ -2,9 +2,14 @@ package cn.iocoder.yudao.module.product.service.sku;
2 2
3 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 3 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyCreateReqVO;
5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO;
  7 +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO;
6 import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; 8 import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
7 -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; 9 +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
  10 +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
  11 +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReqVO;
  12 +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuUpdateReqVO;
8 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 13 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
9 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
10 import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; 15 import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
@@ -84,11 +89,9 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -84,11 +89,9 @@ public class ProductSkuServiceImpl implements ProductSkuService {
84 return productSkuMapper.selectPage(pageReqVO); 89 return productSkuMapper.selectPage(pageReqVO);
85 } 90 }
86 91
87 - // TODO @franky:这个方法,貌似实现的还是有点问题哈。例如说,throw 异常,后面还执行逻辑~  
88 - // TODO @艿艿 咳咳,throw 那里我是偷懒省略了{},哈哈,我加上,然后我调试下,在优化下  
89 @Override 92 @Override
90 - public void validateSkus(List<ProductSkuCreateOrUpdateReqVO> list) {  
91 - List<ProductSkuBaseVO.Property> skuPropertyList = list.stream().flatMap(p -> p.getProperties().stream()).collect(Collectors.toList()); 93 + public void validateSkus(List<ProductSkuCreateReqVO> list) {
  94 + List<ProductSkuBaseVO.Property> skuPropertyList = list.stream().flatMap(p -> Optional.of(p.getProperties()).orElse(new ArrayList<>()).stream()).collect(Collectors.toList());
92 // 校验规格属性以及规格值是否存在 95 // 校验规格属性以及规格值是否存在
93 List<Long> propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); 96 List<Long> propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList());
94 List<ProductPropertyRespVO> propertyAndValueList = productPropertyService.selectByIds(propertyIds); 97 List<ProductPropertyRespVO> propertyAndValueList = productPropertyService.selectByIds(propertyIds);
@@ -99,8 +102,9 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -99,8 +102,9 @@ public class ProductSkuServiceImpl implements ProductSkuService {
99 skuPropertyList.forEach(p -> { 102 skuPropertyList.forEach(p -> {
100 ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId()); 103 ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId());
101 // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示 104 // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示
102 - if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) 105 + if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) {
103 throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); 106 throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS);
  107 + }
104 // 判断改属性名对应的属性值是否存在,不存在,给出提示 108 // 判断改属性名对应的属性值是否存在,不存在,给出提示
105 if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) { 109 if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) {
106 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); 110 throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS);
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -56,8 +56,10 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -56,8 +56,10 @@ public class ProductSpuServiceImpl implements ProductSpuService {
56 // 校验分类 56 // 校验分类
57 categoryService.validateProductCategory(createReqVO.getCategoryId()); 57 categoryService.validateProductCategory(createReqVO.getCategoryId());
58 // 校验SKU 58 // 校验SKU
59 - List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();  
60 - productSkuService.validateSkus(skuCreateReqList); 59 + List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getSkus();
  60 + if(createReqVO.getSpecType() == 1) {
  61 + productSkuService.validateSkus(skuCreateReqList);
  62 + }
61 // 插入SPU 63 // 插入SPU
62 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); 64 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
63 ProductSpuMapper.insert(spu); 65 ProductSpuMapper.insert(spu);
@@ -76,8 +78,10 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -76,8 +78,10 @@ public class ProductSpuServiceImpl implements ProductSpuService {
76 // 校验分类 78 // 校验分类
77 categoryService.validateProductCategory(updateReqVO.getCategoryId()); 79 categoryService.validateProductCategory(updateReqVO.getCategoryId());
78 // 校验SKU 80 // 校验SKU
79 - List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus();  
80 - productSkuService.validateSkus(skuCreateReqList); 81 + List<ProductSkuCreateReqVO> skuCreateReqList = updateReqVO.getSkus();
  82 + if(updateReqVO.getSpecType() == 1) {
  83 + productSkuService.validateSkus(skuCreateReqList);
  84 + }
81 // 更新 85 // 更新
82 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); 86 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
83 ProductSpuMapper.updateById(updateObj); 87 ProductSpuMapper.updateById(updateObj);
yudao-ui-admin/src/views/mall/product/spu/index.vue
1 <template> 1 <template>
2 <div class="app-container"> 2 <div class="app-container">
3 -  
4 <!-- 搜索工作栏 --> 3 <!-- 搜索工作栏 -->
5 - <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> 4 + <el-form
  5 + :model="queryParams"
  6 + ref="queryForm"
  7 + size="small"
  8 + :inline="true"
  9 + v-show="showSearch"
  10 + label-width="68px"
  11 + >
6 <el-form-item label="商品名称" prop="name"> 12 <el-form-item label="商品名称" prop="name">
7 - <el-input v-model="queryParams.name" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/> 13 + <el-input
  14 + v-model="queryParams.name"
  15 + placeholder="请输入商品名称"
  16 + clearable
  17 + @keyup.enter.native="handleQuery"
  18 + />
8 </el-form-item> 19 </el-form-item>
9 <el-form-item label="卖点" prop="sellPoint"> 20 <el-form-item label="卖点" prop="sellPoint">
10 - <el-input v-model="queryParams.sellPoint" placeholder="请输入卖点" clearable @keyup.enter.native="handleQuery"/> 21 + <el-input
  22 + v-model="queryParams.sellPoint"
  23 + placeholder="请输入卖点"
  24 + clearable
  25 + @keyup.enter.native="handleQuery"
  26 + />
11 </el-form-item> 27 </el-form-item>
12 <el-form-item label="分类id" prop="categoryId"> 28 <el-form-item label="分类id" prop="categoryId">
13 - <el-input v-model="queryParams.categoryId" placeholder="请输入分类id" clearable @keyup.enter.native="handleQuery"/> 29 + <el-input
  30 + v-model="queryParams.categoryId"
  31 + placeholder="请输入分类id"
  32 + clearable
  33 + @keyup.enter.native="handleQuery"
  34 + />
14 </el-form-item> 35 </el-form-item>
15 <el-form-item label="价格(分)" prop="price"> 36 <el-form-item label="价格(分)" prop="price">
16 - <el-input v-model="queryParams.price" placeholder="请输入价格 单位使用:分" clearable @keyup.enter.native="handleQuery"/> 37 + <el-input
  38 + v-model="queryParams.price"
  39 + placeholder="请输入价格 单位使用:分"
  40 + clearable
  41 + @keyup.enter.native="handleQuery"
  42 + />
17 </el-form-item> 43 </el-form-item>
18 <el-form-item label="库存数量" prop="quantity"> 44 <el-form-item label="库存数量" prop="quantity">
19 - <el-input v-model="queryParams.quantity" placeholder="请输入库存数量" clearable @keyup.enter.native="handleQuery"/> 45 + <el-input
  46 + v-model="queryParams.quantity"
  47 + placeholder="请输入库存数量"
  48 + clearable
  49 + @keyup.enter.native="handleQuery"
  50 + />
20 </el-form-item> 51 </el-form-item>
21 <el-form-item label="状态" prop="status"> 52 <el-form-item label="状态" prop="status">
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"/> 53 + <el-select
  54 + v-model="queryParams.status"
  55 + placeholder="请选择上下架状态"
  56 + clearable
  57 + size="small"
  58 + >
  59 + <el-option label="请选择字典生成" value="" />
  60 + <el-option label="上架" value="0" />
  61 + <el-option label="下架" value="1" />
26 </el-select> 62 </el-select>
27 </el-form-item> 63 </el-form-item>
28 <el-form-item label="创建时间"> 64 <el-form-item label="创建时间">
29 - <el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"  
30 - type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/> 65 + <el-date-picker
  66 + v-model="dateRangeCreateTime"
  67 + style="width: 240px"
  68 + value-format="yyyy-MM-dd"
  69 + type="daterange"
  70 + range-separator="-"
  71 + start-placeholder="开始日期"
  72 + end-placeholder="结束日期"
  73 + />
31 </el-form-item> 74 </el-form-item>
32 <el-form-item> 75 <el-form-item>
33 - <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> 76 + <el-button type="primary" icon="el-icon-search" @click="handleQuery"
  77 + >搜索</el-button
  78 + >
34 <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> 79 <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
35 </el-form-item> 80 </el-form-item>
36 </el-form> 81 </el-form>
@@ -38,257 +83,123 @@ @@ -38,257 +83,123 @@
38 <!-- 操作工具栏 --> 83 <!-- 操作工具栏 -->
39 <el-row :gutter="10" class="mb8"> 84 <el-row :gutter="10" class="mb8">
40 <el-col :span="1.5"> 85 <el-col :span="1.5">
41 - <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"  
42 - v-hasPermi="['product:spu:create']">新增 86 + <el-button
  87 + type="primary"
  88 + plain
  89 + icon="el-icon-plus"
  90 + size="mini"
  91 + @click="handleAdd"
  92 + v-hasPermi="['product:spu:create']"
  93 + >新增
43 </el-button> 94 </el-button>
44 </el-col> 95 </el-col>
45 <el-col :span="1.5"> 96 <el-col :span="1.5">
46 - <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"  
47 - :loading="exportLoading"  
48 - v-hasPermi="['product:spu:export']">导出 97 + <el-button
  98 + type="warning"
  99 + plain
  100 + icon="el-icon-download"
  101 + size="mini"
  102 + @click="handleExport"
  103 + :loading="exportLoading"
  104 + v-hasPermi="['product:spu:export']"
  105 + >导出
49 </el-button> 106 </el-button>
50 </el-col> 107 </el-col>
51 - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> 108 + <right-toolbar
  109 + :showSearch.sync="showSearch"
  110 + @queryTable="getList"
  111 + ></right-toolbar>
52 </el-row> 112 </el-row>
53 113
54 <!-- 列表 --> 114 <!-- 列表 -->
55 <el-table v-loading="loading" :data="list"> 115 <el-table v-loading="loading" :data="list">
56 - <el-table-column label="主键" align="center" prop="id"/>  
57 - <el-table-column label="商品名称" align="center" prop="name"/> 116 + <el-table-column label="主键" align="center" prop="id" />
  117 + <el-table-column label="商品名称" align="center" prop="name" />
58 <!-- <el-table-column label="卖点" align="center" prop="sellPoint"/>--> 118 <!-- <el-table-column label="卖点" align="center" prop="sellPoint"/>-->
59 <!-- <el-table-column label="描述" align="center" prop="description"/>--> 119 <!-- <el-table-column label="描述" align="center" prop="description"/>-->
60 - <el-table-column label="分类id" align="center" prop="categoryId"/> 120 + <el-table-column label="分类id" align="center" prop="categoryId" />
61 <el-table-column label="商品主图地址" align="center" prop="picUrls"> 121 <el-table-column label="商品主图地址" align="center" prop="picUrls">
62 <template slot-scope="scope"> 122 <template slot-scope="scope">
63 - <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/> 123 + <img
  124 + v-if="scope.row.picUrls"
  125 + :src="scope.row.picUrls[0]"
  126 + alt="分类图片"
  127 + class="img-height"
  128 + />
64 </template> 129 </template>
65 </el-table-column> 130 </el-table-column>
66 - <el-table-column label="排序字段" align="center" prop="sort"/>  
67 - <el-table-column label="点赞初始人数" align="center" prop="likeCount"/>  
68 - <el-table-column label="价格 (分)" align="center" prop="price"/>  
69 - <el-table-column label="库存数量" align="center" prop="quantity"/> 131 + <el-table-column label="排序字段" align="center" prop="sort" />
  132 + <el-table-column label="点赞初始人数" align="center" prop="likeCount" />
  133 + <el-table-column label="价格 (分)" align="center" prop="price" />
  134 + <el-table-column label="库存数量" align="center" prop="quantity" />
70 <!-- <el-table-column label="状态" align="center" prop="status"/>--> 135 <!-- <el-table-column label="状态" align="center" prop="status"/>-->
71 - <el-table-column label="创建时间" align="center" prop="createTime" width="180"> 136 + <el-table-column
  137 + label="创建时间"
  138 + align="center"
  139 + prop="createTime"
  140 + width="180"
  141 + >
72 <template slot-scope="scope"> 142 <template slot-scope="scope">
73 <span>{{ parseTime(scope.row.createTime) }}</span> 143 <span>{{ parseTime(scope.row.createTime) }}</span>
74 </template> 144 </template>
75 </el-table-column> 145 </el-table-column>
76 - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> 146 + <el-table-column
  147 + label="操作"
  148 + align="center"
  149 + class-name="small-padding fixed-width"
  150 + >
77 <template slot-scope="scope"> 151 <template slot-scope="scope">
78 - <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"  
79 - v-hasPermi="['product:spu:update']">修改 152 + <el-button
  153 + size="mini"
  154 + type="text"
  155 + icon="el-icon-edit"
  156 + @click="handleUpdate(scope.row)"
  157 + v-hasPermi="['product:spu:update']"
  158 + >修改
80 </el-button> 159 </el-button>
81 - <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"  
82 - v-hasPermi="['product:spu:delete']">删除 160 + <el-button
  161 + size="mini"
  162 + type="text"
  163 + icon="el-icon-delete"
  164 + @click="handleDelete(scope.row)"
  165 + v-hasPermi="['product:spu:delete']"
  166 + >删除
83 </el-button> 167 </el-button>
84 </template> 168 </template>
85 </el-table-column> 169 </el-table-column>
86 </el-table> 170 </el-table>
87 <!-- 分页组件 --> 171 <!-- 分页组件 -->
88 - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"  
89 - @pagination="getList"/> 172 + <pagination
  173 + v-show="total > 0"
  174 + :total="total"
  175 + :page.sync="queryParams.pageNo"
  176 + :limit.sync="queryParams.pageSize"
  177 + @pagination="getList"
  178 + />
  179 +
90 180
91 - <!-- 对话框(添加 / 修改) -->  
92 - <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>  
93 - <el-form ref="form" :model="form" :rules="rules" label-width="80px">  
94 - <el-form-item label="商品名称" prop="name">  
95 - <el-input v-model="form.name" placeholder="请输入商品名称"/>  
96 - </el-form-item>  
97 - <el-form-item label="卖点" prop="sellPoint">  
98 - <el-input v-model="form.sellPoint" placeholder="请输入卖点"/>  
99 - </el-form-item>  
100 - <el-form-item label="描述">  
101 - <editor v-model="form.description" :min-height="192"/>  
102 - </el-form-item>  
103 - <el-form-item label="分类id" prop="categoryIds">  
104 - <el-cascader  
105 - v-model="form.categoryIds"  
106 - placeholder="请输入分类id"  
107 - style="width: 100%"  
108 - :options="categoryList"  
109 - :props="propName"  
110 - clearable></el-cascader>  
111 - </el-form-item>  
112 - <el-form-item label="商品主图地址" prop="picUrls">  
113 - <ImageUpload v-model="form.picUrls" :limit="10"/>  
114 - </el-form-item>  
115 - <el-form-item label="商品规格">  
116 - <el-button size="mini" @click="shopTagInput()">添加规格</el-button>  
117 - <div v-for="(tag, tagIndex) in skuTags" :key="tagIndex">  
118 - <span>{{ tag.name }}</span>  
119 - <el-button style="margin-left: 10px" class="button-new-tag" type="text" icon="el-icon-delete"  
120 - @click="removeTag(tagIndex)">删除  
121 - </el-button>  
122 - <br/>  
123 - <el-tag  
124 - v-for="(tagItem, tagItemIndex) in tag.selectValues"  
125 - :key="tagItem"  
126 - style="margin-right: 10px"  
127 - :disable-transitions="false">  
128 - {{ tagItem }}  
129 - </el-tag>  
130 - <!-- <el-input-->  
131 - <!-- class="input-new-tag"-->  
132 - <!-- v-if="tagItemInputs[tagIndex] && tagItemInputs[tagIndex].visible"-->  
133 - <!-- v-model="tagItemInputs[tagIndex].value"-->  
134 - <!-- :ref="`saveTagInput${tagIndex}`"-->  
135 - <!-- size="small"-->  
136 - <!-- @keyup.enter.native="handleInputConfirm(tagIndex)"-->  
137 - <!-- @blur="handleInputConfirm(tagIndex)">-->  
138 - <!-- </el-input>-->  
139 - </div>  
140 - </el-form-item>  
141 - <el-form-item label="规格名" v-show="isShowTagInput">  
142 - <el-col :span="8">  
143 - <el-select v-model="addTagInput.name" filterable allow-create default-first-option placeholder="请选择"  
144 - @change="handleTagClick">  
145 - <el-option  
146 - v-for="item in unUseTags"  
147 - :key="item.id"  
148 - :label="item.name"  
149 - :value="item.name">  
150 - </el-option>  
151 - </el-select>  
152 - </el-col>  
153 - </el-form-item>  
154 - <el-form-item label="规格值" v-show="isShowTagInput">  
155 - <el-col :span="8">  
156 - <el-select v-model="addTagInput.selectValues" multiple filterable allow-create default-first-option  
157 - placeholder="请选择">  
158 - <el-option  
159 - v-for="item in dbTagValues"  
160 - :key="item.id"  
161 - :label="item.name"  
162 - :value="item.name">  
163 - </el-option>  
164 - </el-select>  
165 - </el-col>  
166 - </el-form-item>  
167 - <el-form-item>  
168 - <el-button size="mini" type="primary" @click="addTag()" v-show="isShowTagInput">确定</el-button>  
169 - <el-button size="mini" @click="hideTagInput()" v-show="isShowTagInput">取消</el-button>  
170 - </el-form-item>  
171 - <el-form-item v-if="form.skus.length>0">  
172 - <el-table  
173 - :data="form.skus"  
174 - border  
175 - style="width: 100%; margin-top: 20px"  
176 - :span-method="tableSpanMethod">  
177 - <el-table-column v-for="(leftTitle, index) in skuTags" :key="index" :label="leftTitle.name">  
178 - <template slot-scope="scope">  
179 - {{ scope.row.propertyChildNames[index] }}  
180 - </template>  
181 - </el-table-column>  
182 - <el-table-column v-if="skuTags.length"  
183 - prop="picUrl"  
184 - label="sku图片"  
185 - width="180">  
186 - <template slot-scope="scope">  
187 - <ImageUpload v-model="scope.row.picUrl" :limit="1">  
188 - </ImageUpload>  
189 - </template>  
190 - </el-table-column>  
191 - <el-table-column  
192 - prop="prodName"  
193 - label="条形码"  
194 - width="250" v-if="skuTags.length">  
195 - <template slot-scope="scope">  
196 - <el-input v-model="scope.row.barCode" type="textarea" :disabled="scope.row.status==1"></el-input>  
197 - </template>  
198 - </el-table-column>  
199 - <el-table-column  
200 - prop="price"  
201 - label="销售价">  
202 - <template slot-scope="scope">  
203 - <el-input-number  
204 - size="small"  
205 - v-model="scope.row.price"  
206 - controls-position="right"  
207 - :precision="2"  
208 - :max="1000000000"  
209 - :min="0.01"  
210 - :disabled="scope.row.status==1">  
211 - </el-input-number>  
212 - </template>  
213 - </el-table-column>  
214 - <el-table-column  
215 - prop="oriPrice"  
216 - label="成本价">  
217 - <template slot-scope="scope">  
218 - <el-input-number  
219 - size="small"  
220 - v-model="scope.row.costPrice"  
221 - controls-position="right"  
222 - :precision="2"  
223 - :max="1000000000"  
224 - :min="0.01"  
225 - :disabled="scope.row.status==1">  
226 - </el-input-number>  
227 - </template>  
228 - </el-table-column>  
229 - <el-table-column  
230 - prop="oriPrice"  
231 - label="原价">  
232 - <template slot-scope="scope">  
233 - <el-input-number  
234 - size="small"  
235 - v-model="scope.row.originalPrice"  
236 - controls-position="right"  
237 - :precision="2"  
238 - :max="1000000000"  
239 - :min="0.01"  
240 - :disabled="scope.row.status==1">  
241 - </el-input-number>  
242 - </template>  
243 - </el-table-column>  
244 - <el-table-column  
245 - label="操作">  
246 - <template slot-scope="scope">  
247 - <el-button type="text" size="small" @click="changeSkuStatus(`${scope.$index}`)"  
248 - v-if="scope.row.status===0">  
249 - 正常  
250 - </el-button>  
251 - <el-button type="text" size="small" @click="changeSkuStatus(`${scope.$index}`)" v-else>已禁用</el-button>  
252 - </template>  
253 - </el-table-column>  
254 - </el-table>  
255 - </el-form-item>  
256 - <el-form-item label="排序字段" prop="sort">  
257 - <el-input v-model="form.sort" placeholder="请输入排序字段"/>  
258 - </el-form-item>  
259 - <el-form-item label="点赞初始人数" prop="likeCount">  
260 - <el-input v-model="form.likeCount" placeholder="请输入点赞初始人数"/>  
261 - </el-form-item>  
262 - <el-form-item label="价格 单位使用:分" prop="price">  
263 - <el-input v-model="form.price" placeholder="请输入价格 单位使用:分"/>  
264 - </el-form-item>  
265 - <el-form-item label="库存数量" prop="quantity">  
266 - <el-input v-model="form.quantity" placeholder="请输入库存数量"/>  
267 - </el-form-item>  
268 - <el-form-item label="上下架状态" prop="status">  
269 - <el-radio-group v-model="form.status">  
270 - <el-radio label="0">上架</el-radio>  
271 - <el-radio label="1">下架</el-radio>  
272 - </el-radio-group>  
273 - </el-form-item>  
274 - </el-form>  
275 - <div slot="footer" class="dialog-footer">  
276 - <el-button type="primary" @click="submitForm">确 定</el-button>  
277 - <el-button @click="cancel">取 消</el-button>  
278 - </div> 181 + <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body destroy-on-close>
  182 + <save @closeDialog="open = false; getList()"/>
279 </el-dialog> 183 </el-dialog>
280 </div> 184 </div>
281 </template> 185 </template>
282 186
283 <script> 187 <script>
284 -import {createSpu, updateSpu, deleteSpu, getSpu, getSpuPage, exportSpuExcel} from "@/api/mall/product/spu"; 188 +import {
  189 + createSpu,
  190 + updateSpu,
  191 + deleteSpu,
  192 + getSpu,
  193 + getSpuPage,
  194 + exportSpuExcel,
  195 +} from "@/api/mall/product/spu";
285 import { 196 import {
286 createProductCategory, 197 createProductCategory,
287 deleteProductCategory, 198 deleteProductCategory,
288 exportCategoryExcel, 199 exportCategoryExcel,
289 getProductCategory, 200 getProductCategory,
290 getProductCategoryList, 201 getProductCategoryList,
291 - updateProductCategory 202 + updateProductCategory,
292 } from "@/api/mall/product/category"; 203 } from "@/api/mall/product/category";
293 import { 204 import {
294 createProperty, 205 createProperty,
@@ -296,16 +207,19 @@ import { @@ -296,16 +207,19 @@ import {
296 deleteProperty, 207 deleteProperty,
297 getProperty, 208 getProperty,
298 getPropertyPage, 209 getPropertyPage,
299 - exportPropertyExcel 210 + exportPropertyExcel,
300 } from "@/api/mall/product/property"; 211 } from "@/api/mall/product/property";
301 212
302 -import Editor from '@/components/Editor';  
303 -import ImageUpload from '@/components/ImageUpload'; 213 +import Editor from "@/components/Editor";
  214 +import ImageUpload from "@/components/ImageUpload";
  215 +import save from "./save";
304 216
305 export default { 217 export default {
306 name: "Spu", 218 name: "Spu",
307 components: { 219 components: {
308 - Editor, ImageUpload 220 + Editor,
  221 + ImageUpload,
  222 + save,
309 }, 223 },
310 data() { 224 data() {
311 return { 225 return {
@@ -316,17 +230,17 @@ export default { @@ -316,17 +230,17 @@ export default {
316 propertyPageList: [], 230 propertyPageList: [],
317 isShowTagInput: false, 231 isShowTagInput: false,
318 addTagInput: { 232 addTagInput: {
319 - name: '',  
320 - propertyId: '', 233 + name: "",
  234 + propertyId: "",
321 selectValues: [], 235 selectValues: [],
322 selectValueIds: [], 236 selectValueIds: [],
323 - selectObect:[], 237 + selectObect: [],
324 }, 238 },
325 skuTags: [], 239 skuTags: [],
326 propName: { 240 propName: {
327 checkStrictly: true, 241 checkStrictly: true,
328 - label: 'name',  
329 - value: 'id' 242 + label: "name",
  243 + value: "id",
330 }, 244 },
331 categoryList: [], 245 categoryList: [],
332 // 遮罩层 246 // 遮罩层
@@ -378,91 +292,101 @@ export default { @@ -378,91 +292,101 @@ export default {
378 }, 292 },
379 // 表单校验 293 // 表单校验
380 rules: { 294 rules: {
381 - sellPoint: [{required: true, message: "卖点不能为空", trigger: "blur"}],  
382 - description: [{required: true, message: "描述不能为空", trigger: "blur"}],  
383 - categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"}],  
384 - picUrls: [{required: true, message: "商品主图地址", trigger: "blur"}],  
385 - sort: [{required: true, message: "排序字段不能为空", trigger: "blur"}], 295 + sellPoint: [
  296 + { required: true, message: "卖点不能为空", trigger: "blur" },
  297 + ],
  298 + description: [
  299 + { required: true, message: "描述不能为空", trigger: "blur" },
  300 + ],
  301 + categoryIds: [
  302 + { required: true, message: "分类id不能为空", trigger: "blur" },
  303 + ],
  304 + picUrls: [{ required: true, message: "商品主图地址", trigger: "blur" }],
  305 + sort: [
  306 + { required: true, message: "排序字段不能为空", trigger: "blur" },
  307 + ],
386 }, 308 },
387 tagIndex: 0, 309 tagIndex: 0,
388 }; 310 };
389 }, 311 },
390 created() { 312 created() {
391 -  
392 this.getList(); 313 this.getList();
393 this.getPropertyPageList(); 314 this.getPropertyPageList();
394 this.getListCategory(); 315 this.getListCategory();
395 }, 316 },
396 methods: { 317 methods: {
397 getTableSpecData() { 318 getTableSpecData() {
398 - return this.value  
399 - },  
400 - tableSpanMethod({row, column, rowIndex, columnIndex}) {  
401 - 319 + return this.value;
402 }, 320 },
  321 + tableSpanMethod({ row, column, rowIndex, columnIndex }) {},
403 changeSkuStatus(tagIndex) { 322 changeSkuStatus(tagIndex) {
404 if (this.form.skus[tagIndex].status == 0) { 323 if (this.form.skus[tagIndex].status == 0) {
405 this.form.skus[tagIndex].status = 1; 324 this.form.skus[tagIndex].status = 1;
406 } else { 325 } else {
407 this.form.skus[tagIndex].status = 0; 326 this.form.skus[tagIndex].status = 0;
408 } 327 }
409 -  
410 }, 328 },
411 skuAddProdName() { 329 skuAddProdName() {
412 if (this.initing) { 330 if (this.initing) {
413 - return 331 + return;
414 } 332 }
415 - let skuList = [] 333 + let skuList = [];
416 for (let i = 0; i < this.value.length; i++) { 334 for (let i = 0; i < this.value.length; i++) {
417 - const sku = Object.assign({}, this.value[i]) 335 + const sku = Object.assign({}, this.value[i]);
418 if (!sku.properties) { 336 if (!sku.properties) {
419 - return 337 + return;
420 } 338 }
421 - sku.skuName = ''  
422 - let properties = sku.properties.split(';') 339 + sku.skuName = "";
  340 + let properties = sku.properties.split(";");
423 for (const propertiesKey in properties) { 341 for (const propertiesKey in properties) {
424 - sku.skuName += properties[propertiesKey].split(':')[1] + ' ' 342 + sku.skuName += properties[propertiesKey].split(":")[1] + " ";
425 } 343 }
426 - sku.prodName = this.prodName + ' ' + sku.skuName  
427 - skuList.push(sku) 344 + sku.prodName = this.prodName + " " + sku.skuName;
  345 + skuList.push(sku);
428 } 346 }
429 - this.$emit('input', skuList)  
430 - },  
431 - handleTagClose(tagIndex, tagItemIndex) {  
432 - 347 + this.$emit("input", skuList);
433 }, 348 },
  349 + handleTagClose(tagIndex, tagItemIndex) {},
434 //确定添加sku规格 350 //确定添加sku规格
435 addTag() { 351 addTag() {
436 -  
437 let skus = this.unUseTags.map(function (item, index) { 352 let skus = this.unUseTags.map(function (item, index) {
438 - return item.name 353 + return item.name;
439 }); 354 });
440 let index = skus.indexOf(this.addTagInput.name); 355 let index = skus.indexOf(this.addTagInput.name);
441 356
442 this.addTagInput.propertyId = this.unUseTags[index].id; 357 this.addTagInput.propertyId = this.unUseTags[index].id;
443 for (let i = 0; i < this.addTagInput.selectValues.length; i++) { 358 for (let i = 0; i < this.addTagInput.selectValues.length; i++) {
444 - for (let j = 0; j < this.unUseTags[index].propertyValueList.length; j++) {  
445 - if (this.addTagInput.selectValues[i] === this.unUseTags[index].propertyValueList[j].name) {  
446 - this.addTagInput.selectValueIds.push(this.unUseTags[index].propertyValueList[j].id) 359 + for (
  360 + let j = 0;
  361 + j < this.unUseTags[index].propertyValueList.length;
  362 + j++
  363 + ) {
  364 + if (
  365 + this.addTagInput.selectValues[i] ===
  366 + this.unUseTags[index].propertyValueList[j].name
  367 + ) {
  368 + this.addTagInput.selectValueIds.push(
  369 + this.unUseTags[index].propertyValueList[j].id
  370 + );
447 this.addTagInput.selectObect.push({ 371 this.addTagInput.selectObect.push({
448 - id:this.unUseTags[index].propertyValueList[j].id,  
449 - name:this.unUseTags[index].propertyValueList[j].name,  
450 - }) 372 + id: this.unUseTags[index].propertyValueList[j].id,
  373 + name: this.unUseTags[index].propertyValueList[j].name,
  374 + });
451 } 375 }
452 } 376 }
453 } 377 }
454 - let addTagInput = JSON.parse(JSON.stringify(this.addTagInput)) 378 + let addTagInput = JSON.parse(JSON.stringify(this.addTagInput));
455 this.skuTags.push(addTagInput); 379 this.skuTags.push(addTagInput);
456 380
457 // if (this.skuTags.length > 1) { 381 // if (this.skuTags.length > 1) {
458 this.skuTags = this.skuTags.sort((a, b) => a.propertyId - b.propertyId); 382 this.skuTags = this.skuTags.sort((a, b) => a.propertyId - b.propertyId);
459 - this.skuTags.forEach(function (item,index) {  
460 - item.selectObect = item.selectObect.sort((a, b) => a.id - b.id)  
461 - }) 383 + this.skuTags.forEach(function (item, index) {
  384 + item.selectObect = item.selectObect.sort((a, b) => a.id - b.id);
  385 + });
462 386
463 - for (let i = 0; i <this.skuTags.length ; i++) {  
464 - let selectValueIds=[];  
465 - let selectValues=[]; 387 + for (let i = 0; i < this.skuTags.length; i++) {
  388 + let selectValueIds = [];
  389 + let selectValues = [];
466 for (let j = 0; j < this.skuTags[i].selectObect.length; j++) { 390 for (let j = 0; j < this.skuTags[i].selectObect.length; j++) {
467 selectValueIds.push(this.skuTags[i].selectObect[j].id); 391 selectValueIds.push(this.skuTags[i].selectObect[j].id);
468 selectValues.push(this.skuTags[i].selectObect[j].name); 392 selectValues.push(this.skuTags[i].selectObect[j].name);
@@ -489,17 +413,23 @@ export default { @@ -489,17 +413,23 @@ export default {
489 propertyNames.push(skuTags[i].name); 413 propertyNames.push(skuTags[i].name);
490 } 414 }
491 415
492 - let skuAll = sku1s.reduce((x, y) => {  
493 - let arr = [];  
494 - x.forEach(m => y.forEach(y => arr.push(m.concat([y]))))  
495 - return arr;  
496 - }, [[]]) 416 + let skuAll = sku1s.reduce(
  417 + (x, y) => {
  418 + let arr = [];
  419 + x.forEach((m) => y.forEach((y) => arr.push(m.concat([y]))));
  420 + return arr;
  421 + },
  422 + [[]]
  423 + );
497 424
498 - let skuIdAll = skuIds.reduce((x, y) => {  
499 - let arr = [];  
500 - x.forEach(m => y.forEach(y => arr.push(m.concat([y]))))  
501 - return arr;  
502 - }, [[]]) 425 + let skuIdAll = skuIds.reduce(
  426 + (x, y) => {
  427 + let arr = [];
  428 + x.forEach((m) => y.forEach((y) => arr.push(m.concat([y]))));
  429 + return arr;
  430 + },
  431 + [[]]
  432 + );
503 433
504 for (let i = 0; i < skuAll.length; i++) { 434 for (let i = 0; i < skuAll.length; i++) {
505 let han = { 435 let han = {
@@ -508,33 +438,32 @@ export default { @@ -508,33 +438,32 @@ export default {
508 propertyChildNames: skuAll[i], 438 propertyChildNames: skuAll[i],
509 propertyChildIds: skuIdAll[i], 439 propertyChildIds: skuIdAll[i],
510 properties: [], 440 properties: [],
511 - picUrl: '',  
512 - costPrice: '',  
513 - originalPrice: '',  
514 - spuId: '',  
515 - prodName: '',  
516 - price: '',  
517 - barCode: '',  
518 - status: '0',  
519 - } 441 + picUrl: "",
  442 + costPrice: "",
  443 + originalPrice: "",
  444 + spuId: "",
  445 + prodName: "",
  446 + price: "",
  447 + barCode: "",
  448 + status: "0",
  449 + };
520 this.form.skus.push(han); 450 this.form.skus.push(han);
521 } 451 }
522 - this.form.skus.forEach(x => { 452 + this.form.skus.forEach((x) => {
523 x.properties = []; 453 x.properties = [];
524 for (let i = 0; i < x.propertyIds.length; i++) { 454 for (let i = 0; i < x.propertyIds.length; i++) {
525 x.properties.push({ 455 x.properties.push({
526 propertyId: x.propertyIds[i], 456 propertyId: x.propertyIds[i],
527 - valueId: x.propertyChildIds[i]  
528 - }) 457 + valueId: x.propertyChildIds[i],
  458 + });
529 } 459 }
530 - })  
531 - 460 + });
532 }, 461 },
533 hideTagInput() { 462 hideTagInput() {
534 this.isShowTagInput = false; 463 this.isShowTagInput = false;
535 this.addTagInput = { 464 this.addTagInput = {
536 - name: '',  
537 - propertyId: '', 465 + name: "",
  466 + propertyId: "",
538 selectValues: [], 467 selectValues: [],
539 selectValueIds: [], 468 selectValueIds: [],
540 selectObect: [], 469 selectObect: [],
@@ -542,12 +471,12 @@ export default { @@ -542,12 +471,12 @@ export default {
542 }, 471 },
543 shopTagInput() { 472 shopTagInput() {
544 if (this.unUseTags.length <= 0) { 473 if (this.unUseTags.length <= 0) {
545 - return this.$message.error("规格已经添加完毕") 474 + return this.$message.error("规格已经添加完毕");
546 } 475 }
547 this.isShowTagInput = true; 476 this.isShowTagInput = true;
548 this.addTagInput = { 477 this.addTagInput = {
549 - name: '',  
550 - propertyId: '', 478 + name: "",
  479 + propertyId: "",
551 selectValues: [], 480 selectValues: [],
552 selectValueIds: [], 481 selectValueIds: [],
553 selectObect: [], 482 selectObect: [],
@@ -556,8 +485,8 @@ export default { @@ -556,8 +485,8 @@ export default {
556 //删除已选的规格 485 //删除已选的规格
557 removeTag(row) { 486 removeTag(row) {
558 let skus = this.allhistoryTags.map(function (item, index) { 487 let skus = this.allhistoryTags.map(function (item, index) {
559 - return item.name  
560 - }) 488 + return item.name;
  489 + });
561 let index = skus.indexOf(this.skuTags[row].name); 490 let index = skus.indexOf(this.skuTags[row].name);
562 this.unUseTags.push(this.allhistoryTags[index]); 491 this.unUseTags.push(this.allhistoryTags[index]);
563 this.skuTags.splice(row, 1); 492 this.skuTags.splice(row, 1);
@@ -566,38 +495,37 @@ export default { @@ -566,38 +495,37 @@ export default {
566 handleTagClick(row) { 495 handleTagClick(row) {
567 for (let i = 0; i < this.propertyPageList.length; i++) { 496 for (let i = 0; i < this.propertyPageList.length; i++) {
568 if (row == this.propertyPageList[i].name) { 497 if (row == this.propertyPageList[i].name) {
569 - this.dbTagValues = this.propertyPageList[i].propertyValueList 498 + this.dbTagValues = this.propertyPageList[i].propertyValueList;
570 } 499 }
571 } 500 }
572 }, 501 },
573 /** 查询规格 */ 502 /** 查询规格 */
574 getPropertyPageList() { 503 getPropertyPageList() {
575 // 执行查询 504 // 执行查询
576 - getPropertyPage().then(response => { 505 + getPropertyPage().then((response) => {
577 this.propertyPageList = response.data.list; 506 this.propertyPageList = response.data.list;
578 507
579 this.unUseTags = this.propertyPageList.map(function (item, index) { 508 this.unUseTags = this.propertyPageList.map(function (item, index) {
580 - return item  
581 - }) 509 + return item;
  510 + });
582 this.allhistoryTags = JSON.parse(JSON.stringify(this.unUseTags)); 511 this.allhistoryTags = JSON.parse(JSON.stringify(this.unUseTags));
583 }); 512 });
584 }, 513 },
585 /** 查询分类 */ 514 /** 查询分类 */
586 getListCategory() { 515 getListCategory() {
587 // 执行查询 516 // 执行查询
588 - getProductCategoryList().then(response => { 517 + getProductCategoryList().then((response) => {
589 this.categoryList = this.handleTree(response.data, "id", "parentId"); 518 this.categoryList = this.handleTree(response.data, "id", "parentId");
590 -  
591 }); 519 });
592 }, 520 },
593 /** 查询列表 */ 521 /** 查询列表 */
594 getList() { 522 getList() {
595 this.loading = true; 523 this.loading = true;
596 // 处理查询参数 524 // 处理查询参数
597 - let params = {...this.queryParams};  
598 - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); 525 + let params = { ...this.queryParams };
  526 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime");
599 // 执行查询 527 // 执行查询
600 - getSpuPage(params).then(response => { 528 + getSpuPage(params).then((response) => {
601 this.list = response.data.list; 529 this.list = response.data.list;
602 this.total = response.data.total; 530 this.total = response.data.total;
603 this.loading = false; 531 this.loading = false;
@@ -610,7 +538,6 @@ export default { @@ -610,7 +538,6 @@ export default {
610 }, 538 },
611 /** 表单重置 */ 539 /** 表单重置 */
612 reset() { 540 reset() {
613 -  
614 this.form = { 541 this.form = {
615 id: undefined, 542 id: undefined,
616 name: undefined, 543 name: undefined,
@@ -652,7 +579,7 @@ export default { @@ -652,7 +579,7 @@ export default {
652 handleUpdate(row) { 579 handleUpdate(row) {
653 this.reset(); 580 this.reset();
654 const id = row.id; 581 const id = row.id;
655 - getSpu(id).then(response => { 582 + getSpu(id).then((response) => {
656 let dataSpu = response.data; 583 let dataSpu = response.data;
657 this.form = { 584 this.form = {
658 id: dataSpu.id, 585 id: dataSpu.id,
@@ -680,11 +607,15 @@ export default { @@ -680,11 +607,15 @@ export default {
680 }, 607 },
681 getDataHandle() { 608 getDataHandle() {
682 let that = this; 609 let that = this;
683 - let productPropertyViews = JSON.parse(JSON.stringify(this.form.productPropertyViews));  
684 - productPropertyViews = productPropertyViews.sort((a, b) => a.propertyId - b.propertyId);  
685 - productPropertyViews.forEach(item => { 610 + let productPropertyViews = JSON.parse(
  611 + JSON.stringify(this.form.productPropertyViews)
  612 + );
  613 + productPropertyViews = productPropertyViews.sort(
  614 + (a, b) => a.propertyId - b.propertyId
  615 + );
  616 + productPropertyViews.forEach((item) => {
686 item.propertyValues = item.propertyValues.sort((a, b) => a.v1 - b.v1); 617 item.propertyValues = item.propertyValues.sort((a, b) => a.v1 - b.v1);
687 - }) 618 + });
688 let skuIds = []; 619 let skuIds = [];
689 for (let i = 0; i < productPropertyViews.length; i++) { 620 for (let i = 0; i < productPropertyViews.length; i++) {
690 let han = { 621 let han = {
@@ -692,17 +623,21 @@ export default { @@ -692,17 +623,21 @@ export default {
692 propertyId: productPropertyViews[i].propertyId, 623 propertyId: productPropertyViews[i].propertyId,
693 selectValues: [], 624 selectValues: [],
694 selectValueIds: [], 625 selectValueIds: [],
695 - }  
696 - for (let j = 0; j < productPropertyViews[i].propertyValues.length; j++) { 626 + };
  627 + for (
  628 + let j = 0;
  629 + j < productPropertyViews[i].propertyValues.length;
  630 + j++
  631 + ) {
697 han.selectValues.push(productPropertyViews[i].propertyValues[j].v2); 632 han.selectValues.push(productPropertyViews[i].propertyValues[j].v2);
698 han.selectValueIds.push(productPropertyViews[i].propertyValues[j].v1); 633 han.selectValueIds.push(productPropertyViews[i].propertyValues[j].v1);
699 } 634 }
700 - skuIds.push(han) 635 + skuIds.push(han);
701 } 636 }
702 this.skuTags = skuIds; 637 this.skuTags = skuIds;
703 this.unUseTags = this.allhistoryTags.filter((v) => 638 this.unUseTags = this.allhistoryTags.filter((v) =>
704 - skuIds.every((val) => val.name != v.name)  
705 - ) 639 + skuIds.every((val) => val.name != v.name)
  640 + );
706 this.getHandleTable(); 641 this.getHandleTable();
707 }, 642 },
708 getHandleTable() { 643 getHandleTable() {
@@ -718,17 +653,23 @@ export default { @@ -718,17 +653,23 @@ export default {
718 propertyIds.push(skuTags[i].propertyId); 653 propertyIds.push(skuTags[i].propertyId);
719 propertyNames.push(skuTags[i].name); 654 propertyNames.push(skuTags[i].name);
720 } 655 }
721 - let skuAll = sku1s.reduce((x, y) => {  
722 - let arr = [];  
723 - x.forEach(m => y.forEach(y => arr.push(m.concat([y]))))  
724 - return arr;  
725 - }, [[]]) 656 + let skuAll = sku1s.reduce(
  657 + (x, y) => {
  658 + let arr = [];
  659 + x.forEach((m) => y.forEach((y) => arr.push(m.concat([y]))));
  660 + return arr;
  661 + },
  662 + [[]]
  663 + );
726 664
727 - let skuIdAll = skuIds.reduce((x, y) => {  
728 - let arr = [];  
729 - x.forEach(m => y.forEach(y => arr.push(m.concat([y]))))  
730 - return arr;  
731 - }, [[]]) 665 + let skuIdAll = skuIds.reduce(
  666 + (x, y) => {
  667 + let arr = [];
  668 + x.forEach((m) => y.forEach((y) => arr.push(m.concat([y]))));
  669 + return arr;
  670 + },
  671 + [[]]
  672 + );
732 673
733 for (let i = 0; i < skuAll.length; i++) { 674 for (let i = 0; i < skuAll.length; i++) {
734 let han = { 675 let han = {
@@ -745,33 +686,32 @@ export default { @@ -745,33 +686,32 @@ export default {
745 price: this.form.skusList[i].price, 686 price: this.form.skusList[i].price,
746 barCode: this.form.skusList[i].barCode, 687 barCode: this.form.skusList[i].barCode,
747 status: this.form.skusList[i].status, 688 status: this.form.skusList[i].status,
748 - } 689 + };
749 this.form.skus.push(han); 690 this.form.skus.push(han);
750 } 691 }
751 - this.form.skus.forEach(x => { 692 + this.form.skus.forEach((x) => {
752 x.properties = []; 693 x.properties = [];
753 for (let i = 0; i < x.propertyIds.length; i++) { 694 for (let i = 0; i < x.propertyIds.length; i++) {
754 x.properties.push({ 695 x.properties.push({
755 propertyId: x.propertyIds[i], 696 propertyId: x.propertyIds[i],
756 - valueId: x.propertyChildIds[i]  
757 - }) 697 + valueId: x.propertyChildIds[i],
  698 + });
758 } 699 }
759 - })  
760 - 700 + });
761 }, 701 },
762 /** 提交按钮 */ 702 /** 提交按钮 */
763 submitForm() { 703 submitForm() {
764 -  
765 - this.$refs["form"].validate(valid => { 704 + this.$refs["form"].validate((valid) => {
766 if (!valid) { 705 if (!valid) {
767 return; 706 return;
768 } 707 }
769 - this.form.picUrls = this.form.picUrls.split(',');  
770 - this.form.categoryId = this.form.categoryIds[(this.form.categoryIds.length - 1)]; 708 + this.form.picUrls = this.form.picUrls.split(",");
  709 + this.form.categoryId =
  710 + this.form.categoryIds[this.form.categoryIds.length - 1];
771 this.form.status = Number(this.form.status); 711 this.form.status = Number(this.form.status);
772 // 修改的提交 712 // 修改的提交
773 if (this.form.id != null) { 713 if (this.form.id != null) {
774 - updateSpu(this.form).then(response => { 714 + updateSpu(this.form).then((response) => {
775 this.$modal.msgSuccess("修改成功"); 715 this.$modal.msgSuccess("修改成功");
776 this.open = false; 716 this.open = false;
777 this.getList(); 717 this.getList();
@@ -779,7 +719,7 @@ export default { @@ -779,7 +719,7 @@ export default {
779 return; 719 return;
780 } 720 }
781 // 添加的提交 721 // 添加的提交
782 - createSpu(this.form).then(response => { 722 + createSpu(this.form).then((response) => {
783 this.$modal.msgSuccess("新增成功"); 723 this.$modal.msgSuccess("新增成功");
784 this.open = false; 724 this.open = false;
785 this.getList(); 725 this.getList();
@@ -789,32 +729,38 @@ export default { @@ -789,32 +729,38 @@ export default {
789 /** 删除按钮操作 */ 729 /** 删除按钮操作 */
790 handleDelete(row) { 730 handleDelete(row) {
791 const id = row.id; 731 const id = row.id;
792 - this.$modal.confirm('是否确认删除商品spu编号为"' + id + '"的数据项?').then(function () {  
793 - return deleteSpu(id);  
794 - }).then(() => {  
795 - this.getList();  
796 - this.$modal.msgSuccess("删除成功");  
797 - }).catch(() => {  
798 - }); 732 + this.$modal
  733 + .confirm('是否确认删除商品spu编号为"' + id + '"的数据项?')
  734 + .then(function () {
  735 + return deleteSpu(id);
  736 + })
  737 + .then(() => {
  738 + this.getList();
  739 + this.$modal.msgSuccess("删除成功");
  740 + })
  741 + .catch(() => {});
799 }, 742 },
800 /** 导出按钮操作 */ 743 /** 导出按钮操作 */
801 handleExport() { 744 handleExport() {
802 // 处理查询参数 745 // 处理查询参数
803 - let params = {...this.queryParams}; 746 + let params = { ...this.queryParams };
804 params.pageNo = undefined; 747 params.pageNo = undefined;
805 params.pageSize = undefined; 748 params.pageSize = undefined;
806 - this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime'); 749 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime");
807 // 执行导出 750 // 执行导出
808 - this.$modal.confirm('是否确认导出所有商品spu数据项?').then(() => {  
809 - this.exportLoading = true;  
810 - return exportSpuExcel(params);  
811 - }).then(response => {  
812 - this.$download.excel(response, '商品spu.xls');  
813 - this.exportLoading = false;  
814 - }).catch(() => {  
815 - });  
816 - }  
817 - } 751 + this.$modal
  752 + .confirm("是否确认导出所有商品spu数据项?")
  753 + .then(() => {
  754 + this.exportLoading = true;
  755 + return exportSpuExcel(params);
  756 + })
  757 + .then((response) => {
  758 + this.$download.excel(response, "商品spu.xls");
  759 + this.exportLoading = false;
  760 + })
  761 + .catch(() => {});
  762 + },
  763 + },
818 }; 764 };
819 </script> 765 </script>
820 <style lang="scss"> 766 <style lang="scss">
yudao-ui-admin/src/views/mall/product/spu/save.vue 0 → 100644
  1 +<template>
  2 + <div class="container">
  3 + <el-tabs v-model="activeName" class="tabs">
  4 + <!-- 基础设置 -->
  5 + <el-tab-pane label="基础设置" name="base">
  6 + <el-form ref="baseForm" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
  7 + <el-form-item label="商品名称" prop="name">
  8 + <el-input v-model="baseForm.name" placeholder="请输入商品名称"/>
  9 + </el-form-item>
  10 + <el-form-item label="卖点" prop="sellPoint">
  11 + <el-input v-model="baseForm.sellPoint" placeholder="请输入卖点"/>
  12 + </el-form-item>
  13 + <el-form-item label="分类id" prop="categoryIds">
  14 + <el-cascader
  15 + v-model="baseForm.categoryIds"
  16 + placeholder="请输入分类id"
  17 + style="width: 100%"
  18 + :options="categoryList"
  19 + :props="propName"
  20 + clearable
  21 + ></el-cascader>
  22 + </el-form-item>
  23 + <el-form-item label="商品主图" prop="bannerUrl">
  24 + <ImageUpload v-model="baseForm.bannerUrl" :limit="1"/>
  25 + </el-form-item>
  26 + <el-form-item label="商品轮播图" prop="picUrls">
  27 + <ImageUpload v-model="baseForm.picUrls" :limit="10"/>
  28 + </el-form-item>
  29 + <el-form-item label="排序字段" prop="sort">
  30 + <el-input v-model="baseForm.sort" placeholder="请输入排序字段"/>
  31 + </el-form-item>
  32 + </el-form>
  33 + </el-tab-pane>
  34 +
  35 + <!-- 价格库存 -->
  36 + <el-tab-pane label="价格库存" name="rates" class="rates">
  37 + <el-form :model="ratesForm" :rules="rules.ratesForm">
  38 + <el-form-item label="商品规格">
  39 + <el-radio-group v-model="ratesForm.spec" @change="changeRadio">
  40 + <el-radio :label="0">单规格</el-radio>
  41 + <el-radio :label="1">多规格</el-radio>
  42 + </el-radio-group>
  43 + </el-form-item>
  44 +
  45 + <!-- 动态添加规格属性 -->
  46 + <div v-show="ratesForm.spec === 1">
  47 + <div
  48 + v-for="(specs, index) in dynamicSpec"
  49 + :key="index"
  50 + class="dynamic-spec"
  51 + >
  52 + <!-- 删除按钮 -->
  53 + <el-button
  54 + type="danger"
  55 + icon="el-icon-delete"
  56 + circle
  57 + class="spec-delete"
  58 + @click="dynamicSpec.splice(index, 1)"
  59 + ></el-button>
  60 +
  61 + <div class="spec-header">
  62 + 规格项:
  63 + <el-select v-model="specs.specId" filterable placeholder="请选择" @change="changeSpec">
  64 + <el-option
  65 + v-for="item in propertyPageList"
  66 + :key="item.id"
  67 + :label="item.name"
  68 + :value="item.id">
  69 + </el-option>
  70 + </el-select>
  71 + </div>
  72 + <div class="spec-values">
  73 + <template v-for="(v, i) in specs.specValue">
  74 + <el-input v-model="v.name" class="spec-value" :key="i"/>
  75 + </template>
  76 + <!-- <el-button
  77 + type="primary"
  78 + icon="el-icon-plus"
  79 + circle
  80 + @click="dialogForSpec = true; currentSpec = index"
  81 + ></el-button> -->
  82 + </div>
  83 + </div>
  84 + <el-button type="primary" @click="dynamicSpec.push({specValue: []}); ratesForm.rates = []"
  85 + >添加规格项目
  86 + </el-button
  87 + >
  88 + </div>
  89 +
  90 + <!-- 规格明细 -->
  91 + <el-form-item label="规格明细">
  92 + <el-table :data="ratesForm.rates" border style="width: 100%" ref="rates">
  93 +
  94 + <template v-if="ratesForm.spec == 1">
  95 + <el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v=>v.specName != undefined)"
  96 + :label="item.specName">
  97 + <template slot-scope="scope">
  98 + <el-input
  99 + v-if="scope.row.spec"
  100 + v-model="scope.row.spec[index]"
  101 + disabled
  102 + ></el-input>
  103 + </template>
  104 + </el-table-column>
  105 + </template>
  106 +
  107 + <el-table-column label="规格图片" width="120px">
  108 + <template slot-scope="scope">
  109 + <ImageUpload v-model="scope.row.picUrl" :limit="1" :isShowTip="false"
  110 + style="width: 100px; height: 50px"/>
  111 + </template>
  112 + </el-table-column>
  113 + <el-table-column label="市场价(元)">
  114 + <template slot-scope="scope">
  115 + <el-input
  116 + v-model="scope.row.marketPrice"
  117 + type="number"
  118 + ></el-input>
  119 + </template>
  120 + </el-table-column>
  121 + <el-table-column label="销售价(元)" re>
  122 + <template slot-scope="scope">
  123 + <el-input v-model="scope.row.price" type="number"></el-input>
  124 + </template>
  125 + </el-table-column>
  126 + <el-table-column label="成本价">
  127 + <template slot-scope="scope">
  128 + <el-input
  129 + v-model="scope.row.costPrice"
  130 + type="number"
  131 + ></el-input>
  132 + </template>
  133 + </el-table-column>
  134 + <el-table-column label="库存">
  135 + <template slot-scope="scope">
  136 + <el-input v-model="scope.row.stock" type="number"></el-input>
  137 + </template>
  138 + </el-table-column>
  139 + <el-table-column label="体积">
  140 + <template slot-scope="scope">
  141 + <el-input v-model="scope.row.volume" type="number"></el-input>
  142 + </template>
  143 + </el-table-column>
  144 + <el-table-column label="重量">
  145 + <template slot-scope="scope">
  146 + <el-input v-model="scope.row.weight" type="number"></el-input>
  147 + </template>
  148 + </el-table-column>
  149 + <el-table-column label="条码">
  150 + <template slot-scope="scope">
  151 + <el-input v-model="scope.row.barCode"></el-input>
  152 + </template>
  153 + </el-table-column>
  154 + </el-table>
  155 + </el-form-item>
  156 + </el-form>
  157 + </el-tab-pane>
  158 +
  159 + <!-- 商品详情 -->
  160 + <el-tab-pane label="商品描述" name="third">
  161 + <editor v-model="baseForm.description" :min-height="400"/>
  162 + </el-tab-pane>
  163 +
  164 + <!-- 销售设置 -->
  165 + <el-tab-pane label="销售设置" name="fourth">
  166 + <el-form ref="baseForm" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
  167 + <el-form-item label="库存数量" prop="totalStock">
  168 + <el-input v-model="baseForm.totalStock" placeholder="请输入库存数量"/>
  169 + </el-form-item>
  170 + <el-form-item label="上下架状态" prop="status">
  171 + <el-radio-group v-model="baseForm.status">
  172 + <el-radio :label="0">上架</el-radio>
  173 + <el-radio :label="1">下架</el-radio>
  174 + </el-radio-group>
  175 + </el-form-item>
  176 + </el-form>
  177 + </el-tab-pane>
  178 + </el-tabs>
  179 +
  180 + <div class="buttons">
  181 + <el-button type="info" round @click="cancel">取消</el-button>
  182 + <el-button type="success" round @click="submit">确认</el-button>
  183 + </div>
  184 +
  185 + </div>
  186 +</template>
  187 +
  188 +<script>
  189 +import {getProductCategoryList} from "@/api/mall/product/category";
  190 +import {createSpu,} from "@/api/mall/product/spu";
  191 +import {getPropertyPage,} from "@/api/mall/product/property";
  192 +import Editor from "@/components/Editor";
  193 +import ImageUpload from "@/components/ImageUpload";
  194 +
  195 +export default {
  196 + components: {
  197 + Editor,
  198 + ImageUpload
  199 + },
  200 + data() {
  201 + return {
  202 + activeName: "base",
  203 + propName: {
  204 + checkStrictly: true,
  205 + label: "name",
  206 + value: "id",
  207 + },
  208 + // 基础设置
  209 + baseForm: {
  210 + name: null,
  211 + sellPoint: null,
  212 + categoryIds: null,
  213 + sort: null,
  214 + description: null,
  215 + bannerUrl: null,
  216 + picUrls: [],
  217 + totalStock: null,
  218 + status: 0
  219 + },
  220 + categoryList: [],
  221 + // 价格库存
  222 + ratesForm: {
  223 + spec: 0,
  224 + // 规格明细
  225 + rates: [{}]
  226 + },
  227 + dynamicSpec: [
  228 + // {
  229 + // specId: 86,
  230 + // specName: "颜色",
  231 + // specValue:[{
  232 + // name: "红色",
  233 + // id: 225,
  234 + // }]
  235 + // },
  236 + ],
  237 + propertyPageList: [],
  238 + specValue: null,
  239 +
  240 + // 表单校验
  241 + rules: {
  242 + description: [
  243 + {required: true, message: "描述不能为空", trigger: "blur"},
  244 + ],
  245 + categoryIds: [
  246 + {required: true, message: "分类id不能为空", trigger: "blur"},
  247 + ],
  248 + bannerUrl: [{required: true, message: "商品主图地址", trigger: "blur"}],
  249 + sort: [
  250 + {required: true, message: "排序字段不能为空", trigger: "blur"},
  251 + ],
  252 + },
  253 + };
  254 + },
  255 + created() {
  256 + this.getListCategory();
  257 + this.getPropertyPageList();
  258 + },
  259 + methods: {
  260 + changeRadio() {
  261 +
  262 + this.$refs.rates.doLayout()
  263 + if (this.ratesForm.spec == 0) {
  264 + this.ratesForm.rates = [{}]
  265 + } else {
  266 + this.ratesForm.rates = []
  267 + if (this.dynamicSpec.length > 0) {
  268 + this.buildRatesFormRates()
  269 + }
  270 + }
  271 + },
  272 + // 构建规格明细笛卡尔积
  273 + buildRatesFormRates() {
  274 + let rates = [];
  275 + this.dynamicSpec.map(v => v.specValue.map(m => m.name))
  276 + .reduce((last, current) => {
  277 + const array = [];
  278 + last.forEach(par1 => {
  279 + current.forEach(par2 => {
  280 + let v
  281 + if (par1 instanceof Array) {
  282 + v = par1.concat(par2)
  283 + } else {
  284 + v = [par1, par2];
  285 + }
  286 + array.push(v)
  287 + });
  288 + });
  289 + return array;
  290 + })
  291 + .forEach(v => {
  292 + rates.push({spec: v})
  293 + });
  294 + this.ratesForm.rates = rates
  295 + },
  296 + /** 查询分类 */
  297 + getListCategory() {
  298 + // 执行查询
  299 + getProductCategoryList().then((response) => {
  300 + this.categoryList = this.handleTree(response.data, "id", "parentId");
  301 + });
  302 + },
  303 + cancel() {
  304 + this.$emit("closeDialog");
  305 + },
  306 + submit() {
  307 + let rates = this.ratesForm.rates;
  308 + // 动态规格调整字段
  309 + if (this.ratesForm.spec == 1) {
  310 + rates.forEach(r => {
  311 + let properties = []
  312 + if(r.spec instanceof Array){
  313 + r.spec.forEach((v, i) => {
  314 + let specValue = this.dynamicSpec[i].specValue.find(o => o.name == v);
  315 + let propertie = {};
  316 + propertie.propertyId = this.dynamicSpec[i].specId;
  317 + propertie.valueId = specValue.id;
  318 + properties.push(propertie);
  319 + })
  320 + }else{
  321 + let specValue = this.dynamicSpec[0].specValue.find(o => o.name == r.spec);
  322 + let propertie = {};
  323 + propertie.propertyId = this.dynamicSpec[0].specId;
  324 + propertie.valueId = specValue.id;
  325 + properties.push(propertie);
  326 + }
  327 + r.properties = properties;
  328 + })
  329 + }
  330 + this.baseForm.skus = rates;
  331 + this.baseForm.specType = this.ratesForm.spec;
  332 + this.baseForm.categoryId = this.baseForm.categoryIds[this.baseForm.categoryIds.length - 1];
  333 + createSpu(this.baseForm).then((response) => {
  334 + console.log(response)
  335 + this.$modal.msgSuccess("新增成功");
  336 + this.$emit("closeDialog");
  337 + });
  338 +
  339 + },
  340 + /** 查询规格 */
  341 + getPropertyPageList() {
  342 + // 执行查询
  343 + getPropertyPage().then((response) => {
  344 + this.propertyPageList = response.data.list;
  345 + });
  346 + },
  347 + changeSpec(val) {
  348 + let obj = this.propertyPageList.find(o => o.id == val);
  349 + let dynamicSpec = this.dynamicSpec;
  350 + let spec = dynamicSpec.find(o => o.specId == val)
  351 + spec.specId = obj.id;
  352 + spec.specName = obj.name;
  353 + spec.specValue = obj.propertyValueList;
  354 + this.dynamicSpec = dynamicSpec;
  355 + this.buildRatesFormRates();
  356 + }
  357 + },
  358 +};
  359 +</script>
  360 +
  361 +<style lang="scss">
  362 +.spec-dialog {
  363 + width: 400px;
  364 + height: 300px;
  365 +}
  366 +
  367 +.dynamic-spec {
  368 + background-color: #f2f2f2;
  369 + width: 85%;
  370 + margin: auto;
  371 + margin-bottom: 10px;
  372 +
  373 + .spec-header {
  374 + padding: 30px;
  375 + padding-bottom: 20px;
  376 +
  377 + .spec-name {
  378 + display: inline;
  379 +
  380 + input {
  381 + width: 30%;
  382 + }
  383 + }
  384 + }
  385 +
  386 + .spec-values {
  387 + width: 84%;
  388 + padding: 25px;
  389 + margin: auto;
  390 + padding-top: 5px;
  391 +
  392 + .spec-value {
  393 + display: inline-block;
  394 + margin-right: 10px;
  395 + margin-bottom: 10px;
  396 + width: 13%;
  397 +
  398 + }
  399 + }
  400 +
  401 + .spec-delete {
  402 + float: right;
  403 + margin-top: 10px;
  404 + margin-right: 10px;
  405 + }
  406 +}
  407 +
  408 +.tabs {
  409 + height: 500px;
  410 + border-bottom: 2px solid #f2f2f2;
  411 +
  412 + .el-tab-pane {
  413 + height: 445px;
  414 + overflow-y: auto;
  415 + }
  416 +}
  417 +
  418 +// 库存价格图片样式修改
  419 +.rates {
  420 + .component-upload-image {
  421 + margin: auto;
  422 + }
  423 +
  424 + .el-upload--picture-card {
  425 + width: 100px;
  426 + height: 50px;
  427 + line-height: 60px;
  428 + margin: auto;
  429 + }
  430 +
  431 + .el-upload-list__item {
  432 + width: 100px !important;
  433 + height: 50px !important;
  434 + }
  435 +}
  436 +
  437 +.buttons {
  438 + margin-top: 20px;
  439 + height: 36px;
  440 +
  441 + button {
  442 + float: right;
  443 + margin-left: 15px;
  444 + }
  445 +}
  446 +</style>