Commit 8ad1439fda6e05f59a710fca7b24df5887a0639c
1 parent
81666e3b
feature(uniapp商品): 新增商品
Showing
6 changed files
with
156 additions
and
93 deletions
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
| @@ -21,10 +21,7 @@ public class ProductSkuBaseVO { | @@ -21,10 +21,7 @@ public class ProductSkuBaseVO { | ||
| 21 | @NotEmpty(message = "商品 SKU 名字不能为空") | 21 | @NotEmpty(message = "商品 SKU 名字不能为空") |
| 22 | private String name; | 22 | private String name; |
| 23 | 23 | ||
| 24 | - /** | ||
| 25 | - * 规格值数组 | ||
| 26 | - */ | ||
| 27 | - @NotNull(message = "规格值数组不能为空") | 24 | + @ApiModelProperty(value = "规格值数组-json格式 单规格中无此列表, [{propertyId: , valueId: }, {propertyId: , valueId: }]") |
| 28 | private List<Property> properties; | 25 | private List<Property> properties; |
| 29 | 26 | ||
| 30 | @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分") | 27 | @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分") |
| @@ -32,7 +29,7 @@ public class ProductSkuBaseVO { | @@ -32,7 +29,7 @@ public class ProductSkuBaseVO { | ||
| 32 | private Integer price; | 29 | private Integer price; |
| 33 | 30 | ||
| 34 | @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分") | 31 | @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分") |
| 35 | - private Integer originalPrice; | 32 | + private Integer marketPrice; |
| 36 | 33 | ||
| 37 | @ApiModelProperty(value = "成本价", example = "1024", notes = "单位:分") | 34 | @ApiModelProperty(value = "成本价", example = "1024", notes = "单位:分") |
| 38 | private Integer costPrice; | 35 | private Integer costPrice; |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
| @@ -36,7 +36,7 @@ public class ProductSpuBaseVO { | @@ -36,7 +36,7 @@ public class ProductSpuBaseVO { | ||
| 36 | private Long categoryId; | 36 | private Long categoryId; |
| 37 | 37 | ||
| 38 | @ApiModelProperty(value = "商品品牌编号", required = true, example = "1") | 38 | @ApiModelProperty(value = "商品品牌编号", required = true, example = "1") |
| 39 | - @NotNull(message = "商品品牌编号不能为空") | 39 | +// @NotNull(message = "商品品牌编号不能为空") |
| 40 | private Long brandId; | 40 | private Long brandId; |
| 41 | 41 | ||
| 42 | @ApiModelProperty(value = "商品图片的数组", required = true) | 42 | @ApiModelProperty(value = "商品图片的数组", required = true) |
| @@ -44,7 +44,6 @@ public class ProductSpuBaseVO { | @@ -44,7 +44,6 @@ public class ProductSpuBaseVO { | ||
| 44 | private List<String> picUrls; | 44 | private List<String> picUrls; |
| 45 | 45 | ||
| 46 | @ApiModelProperty(value = "商品视频", required = true) | 46 | @ApiModelProperty(value = "商品视频", required = true) |
| 47 | - @NotEmpty(message = "商品视频不能为空") | ||
| 48 | private String videoUrl; | 47 | private String videoUrl; |
| 49 | 48 | ||
| 50 | @ApiModelProperty(value = "排序字段", required = true, example = "1") | 49 | @ApiModelProperty(value = "排序字段", required = true, example = "1") |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | ||
| 15 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 15 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 16 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 16 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 17 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | 17 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; |
| 18 | +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; | ||
| 18 | import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; | 19 | import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; |
| 19 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; | 20 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; |
| 20 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | 21 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| @@ -57,13 +58,18 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -57,13 +58,18 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 57 | categoryService.validateProductCategory(createReqVO.getCategoryId()); | 58 | categoryService.validateProductCategory(createReqVO.getCategoryId()); |
| 58 | // 校验SKU | 59 | // 校验SKU |
| 59 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus(); | 60 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus(); |
| 60 | - if(createReqVO.getSpecType() == 1) { | 61 | + // 多规格才需校验 |
| 62 | + if(Objects.equals(createReqVO.getSpecType(), ProductSpuSpecTypeEnum.DISABLE.getType())) { | ||
| 61 | productSkuService.validateSkus(skuCreateReqList); | 63 | productSkuService.validateSkus(skuCreateReqList); |
| 62 | } | 64 | } |
| 63 | // 插入SPU | 65 | // 插入SPU |
| 64 | ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); | 66 | ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); |
| 67 | + spu.setMarketPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getMarketPrice).max(Integer::compare).orElse(0)); | ||
| 68 | + spu.setMaxPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getPrice).max(Integer::compare).orElse(0)); | ||
| 69 | + spu.setMinPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getPrice).min(Integer::compare).orElse(0)); | ||
| 65 | ProductSpuMapper.insert(spu); | 70 | ProductSpuMapper.insert(spu); |
| 66 | List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); | 71 | List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); |
| 72 | + skuDOList.forEach(v->v.setSpuId(spu.getId())); | ||
| 67 | // 批量插入sku | 73 | // 批量插入sku |
| 68 | productSkuService.createSkus(skuDOList); | 74 | productSkuService.createSkus(skuDOList); |
| 69 | // 返回 | 75 | // 返回 |
| @@ -79,7 +85,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -79,7 +85,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 79 | categoryService.validateProductCategory(updateReqVO.getCategoryId()); | 85 | categoryService.validateProductCategory(updateReqVO.getCategoryId()); |
| 80 | // 校验SKU | 86 | // 校验SKU |
| 81 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus(); | 87 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus(); |
| 82 | - if(updateReqVO.getSpecType() == 1) { | 88 | + // 多规格才需校验 |
| 89 | + if(updateReqVO.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { | ||
| 83 | productSkuService.validateSkus(skuCreateReqList); | 90 | productSkuService.validateSkus(skuCreateReqList); |
| 84 | } | 91 | } |
| 85 | // 更新 | 92 | // 更新 |
yudao-ui-admin/src/components/ImageUpload/index.vue
| @@ -85,8 +85,8 @@ export default { | @@ -85,8 +85,8 @@ export default { | ||
| 85 | value: { | 85 | value: { |
| 86 | handler(val) { | 86 | handler(val) { |
| 87 | if (val) { | 87 | if (val) { |
| 88 | - // 首先将值转为数组 | ||
| 89 | - const list = Array.isArray(val) ? val : this.value.split(','); | 88 | + // 首先将值转为数组, 当只穿了一个图片时,会报map方法错误 |
| 89 | + const list = Array.isArray(val) ? val : Array.isArray(this.value.split(',')) ? this.value.split(','): Array.of(this.value); | ||
| 90 | // 然后将数组转为对象数组 | 90 | // 然后将数组转为对象数组 |
| 91 | this.fileList = list.map(item => { | 91 | this.fileList = list.map(item => { |
| 92 | if (typeof item === "string") { | 92 | if (typeof item === "string") { |
yudao-ui-admin/src/views/mall/product/spu/index.vue
| @@ -178,7 +178,7 @@ | @@ -178,7 +178,7 @@ | ||
| 178 | /> | 178 | /> |
| 179 | 179 | ||
| 180 | 180 | ||
| 181 | - <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body destroy-on-close> | 181 | + <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body destroy-on-close :close-on-click-modal="false" > |
| 182 | <save @closeDialog="open = false; getList()"/> | 182 | <save @closeDialog="open = false; getList()"/> |
| 183 | </el-dialog> | 183 | </el-dialog> |
| 184 | </div> | 184 | </div> |
yudao-ui-admin/src/views/mall/product/spu/save.vue
| 1 | <template> | 1 | <template> |
| 2 | <div class="container"> | 2 | <div class="container"> |
| 3 | - <el-tabs v-model="activeName" class="tabs"> | 3 | + <el-tabs v-model="activeName" class="tabs" :before-leave="confirmLeave"> |
| 4 | <!-- 基础设置 --> | 4 | <!-- 基础设置 --> |
| 5 | <el-tab-pane label="基础设置" name="base"> | 5 | <el-tab-pane label="基础设置" name="base"> |
| 6 | - <el-form ref="baseForm" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%"> | 6 | + <el-form ref="base" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%"> |
| 7 | <el-form-item label="商品名称" prop="name"> | 7 | <el-form-item label="商品名称" prop="name"> |
| 8 | <el-input v-model="baseForm.name" placeholder="请输入商品名称"/> | 8 | <el-input v-model="baseForm.name" placeholder="请输入商品名称"/> |
| 9 | </el-form-item> | 9 | </el-form-item> |
| 10 | - <el-form-item label="卖点" prop="sellPoint"> | 10 | + <el-form-item label="卖点"> |
| 11 | <el-input v-model="baseForm.sellPoint" placeholder="请输入卖点"/> | 11 | <el-input v-model="baseForm.sellPoint" placeholder="请输入卖点"/> |
| 12 | </el-form-item> | 12 | </el-form-item> |
| 13 | <el-form-item label="分类id" prop="categoryIds"> | 13 | <el-form-item label="分类id" prop="categoryIds"> |
| @@ -20,30 +20,27 @@ | @@ -20,30 +20,27 @@ | ||
| 20 | clearable | 20 | clearable |
| 21 | ></el-cascader> | 21 | ></el-cascader> |
| 22 | </el-form-item> | 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"> | 23 | <el-form-item label="商品轮播图" prop="picUrls"> |
| 27 | - <ImageUpload v-model="baseForm.picUrls" :limit="10"/> | 24 | + <ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10"/> |
| 28 | </el-form-item> | 25 | </el-form-item> |
| 29 | - <el-form-item label="排序字段" prop="sort"> | ||
| 30 | - <el-input v-model="baseForm.sort" placeholder="请输入排序字段"/> | 26 | + <el-form-item label="排序字段"> |
| 27 | + <el-input v-model="baseForm.sort" placeholder="请输入排序字段" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/> | ||
| 31 | </el-form-item> | 28 | </el-form-item> |
| 32 | </el-form> | 29 | </el-form> |
| 33 | </el-tab-pane> | 30 | </el-tab-pane> |
| 34 | 31 | ||
| 35 | <!-- 价格库存 --> | 32 | <!-- 价格库存 --> |
| 36 | <el-tab-pane label="价格库存" name="rates" class="rates"> | 33 | <el-tab-pane label="价格库存" name="rates" class="rates"> |
| 37 | - <el-form :model="ratesForm" :rules="rules.ratesForm"> | 34 | + <el-form ref="rates" :model="ratesForm" :rules="rules"> |
| 38 | <el-form-item label="商品规格"> | 35 | <el-form-item label="商品规格"> |
| 39 | <el-radio-group v-model="ratesForm.spec" @change="changeRadio"> | 36 | <el-radio-group v-model="ratesForm.spec" @change="changeRadio"> |
| 40 | - <el-radio :label="0">单规格</el-radio> | ||
| 41 | - <el-radio :label="1">多规格</el-radio> | 37 | + <el-radio :label="1">单规格</el-radio> |
| 38 | + <el-radio :label="2">多规格</el-radio> | ||
| 42 | </el-radio-group> | 39 | </el-radio-group> |
| 43 | </el-form-item> | 40 | </el-form-item> |
| 44 | 41 | ||
| 45 | <!-- 动态添加规格属性 --> | 42 | <!-- 动态添加规格属性 --> |
| 46 | - <div v-show="ratesForm.spec === 1"> | 43 | + <div v-show="ratesForm.spec === 2"> |
| 47 | <div | 44 | <div |
| 48 | v-for="(specs, index) in dynamicSpec" | 45 | v-for="(specs, index) in dynamicSpec" |
| 49 | :key="index" | 46 | :key="index" |
| @@ -71,14 +68,8 @@ | @@ -71,14 +68,8 @@ | ||
| 71 | </div> | 68 | </div> |
| 72 | <div class="spec-values"> | 69 | <div class="spec-values"> |
| 73 | <template v-for="(v, i) in specs.specValue"> | 70 | <template v-for="(v, i) in specs.specValue"> |
| 74 | - <el-input v-model="v.name" class="spec-value" :key="i"/> | 71 | + <el-input v-model="v.name" class="spec-value" :key="i" disabled/> |
| 75 | </template> | 72 | </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> | 73 | </div> |
| 83 | </div> | 74 | </div> |
| 84 | <el-button type="primary" @click="dynamicSpec.push({specValue: []}); ratesForm.rates = []" | 75 | <el-button type="primary" @click="dynamicSpec.push({specValue: []}); ratesForm.rates = []" |
| @@ -89,9 +80,8 @@ | @@ -89,9 +80,8 @@ | ||
| 89 | 80 | ||
| 90 | <!-- 规格明细 --> | 81 | <!-- 规格明细 --> |
| 91 | <el-form-item label="规格明细"> | 82 | <el-form-item label="规格明细"> |
| 92 | - <el-table :data="ratesForm.rates" border style="width: 100%" ref="rates"> | ||
| 93 | - | ||
| 94 | - <template v-if="ratesForm.spec == 1"> | 83 | + <el-table :data="ratesForm.rates" border style="width: 100%" ref="ratesTable"> |
| 84 | + <template v-if="ratesForm.spec == 2"> | ||
| 95 | <el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v=>v.specName != undefined)" | 85 | <el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v=>v.specName != undefined)" |
| 96 | :label="item.specName"> | 86 | :label="item.specName"> |
| 97 | <template slot-scope="scope"> | 87 | <template slot-scope="scope"> |
| @@ -103,54 +93,90 @@ | @@ -103,54 +93,90 @@ | ||
| 103 | </template> | 93 | </template> |
| 104 | </el-table-column> | 94 | </el-table-column> |
| 105 | </template> | 95 | </template> |
| 106 | - | ||
| 107 | - <el-table-column label="规格图片" width="120px"> | 96 | + <el-table-column label="规格图片" width="120px" :render-header="addRedStar" key="90"> |
| 108 | <template slot-scope="scope"> | 97 | <template slot-scope="scope"> |
| 109 | - <ImageUpload v-model="scope.row.picUrl" :limit="1" :isShowTip="false" | 98 | + <ImageUpload v-model="scope.row.picUrl" :limit="1" :isShowTip="false" |
| 110 | style="width: 100px; height: 50px"/> | 99 | style="width: 100px; height: 50px"/> |
| 111 | </template> | 100 | </template> |
| 112 | </el-table-column> | 101 | </el-table-column> |
| 113 | - <el-table-column label="市场价(元)"> | 102 | + <template v-if="ratesForm.spec == 2"> |
| 103 | + <el-table-column label="sku名称" :render-header="addRedStar" key="91"> | ||
| 104 | + <template slot-scope="scope"> | ||
| 105 | + <el-form-item :prop="'rates.'+ scope.$index + '.name'" :rules="[{required: true, trigger: 'change'}]"> | ||
| 106 | + <el-input | ||
| 107 | + v-model="scope.row.name" | ||
| 108 | + ></el-input> | ||
| 109 | + </el-form-item> | ||
| 110 | + </template> | ||
| 111 | + </el-table-column> | ||
| 112 | + </template> | ||
| 113 | + | ||
| 114 | + <el-table-column label="市场价(元)" :render-header="addRedStar" key="92"> | ||
| 114 | <template slot-scope="scope"> | 115 | <template slot-scope="scope"> |
| 115 | - <el-input | ||
| 116 | - v-model="scope.row.marketPrice" | ||
| 117 | - type="number" | ||
| 118 | - ></el-input> | 116 | + <el-form-item :prop="'rates.'+ scope.$index + '.marketPrice'" :rules="[{required: true, trigger: 'change'}]"> |
| 117 | + <el-input | ||
| 118 | + v-model="scope.row.marketPrice" | ||
| 119 | + oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" | ||
| 120 | + ></el-input> | ||
| 121 | + </el-form-item> | ||
| 119 | </template> | 122 | </template> |
| 120 | </el-table-column> | 123 | </el-table-column> |
| 121 | - <el-table-column label="销售价(元)" re> | 124 | + <el-table-column label="销售价(元)" :render-header="addRedStar" key="93"> |
| 122 | <template slot-scope="scope"> | 125 | <template slot-scope="scope"> |
| 123 | - <el-input v-model="scope.row.price" type="number"></el-input> | 126 | + <el-form-item :prop="'rates.'+ scope.$index + '.price'" :rules="[{required: true, trigger: 'change'}]"> |
| 127 | + <el-input v-model="scope.row.price" oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''"></el-input> | ||
| 128 | + </el-form-item> | ||
| 124 | </template> | 129 | </template> |
| 125 | </el-table-column> | 130 | </el-table-column> |
| 126 | - <el-table-column label="成本价"> | 131 | + <el-table-column label="成本价" :render-header="addRedStar" key="94"> |
| 127 | <template slot-scope="scope"> | 132 | <template slot-scope="scope"> |
| 133 | + <el-form-item :prop="'rates.'+ scope.$index + '.costPrice'" :rules="[{required: true, trigger: 'change'}]"> | ||
| 128 | <el-input | 134 | <el-input |
| 129 | v-model="scope.row.costPrice" | 135 | v-model="scope.row.costPrice" |
| 130 | - type="number" | 136 | + oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" |
| 131 | ></el-input> | 137 | ></el-input> |
| 138 | + </el-form-item> | ||
| 139 | + </template> | ||
| 140 | + </el-table-column> | ||
| 141 | + <el-table-column label="库存" :render-header="addRedStar" key="95"> | ||
| 142 | + <template slot-scope="scope"> | ||
| 143 | + <el-form-item :prop="'rates.'+ scope.$index + '.stock'" :rules="[{required: true, trigger: 'change'}]"> | ||
| 144 | + <el-input v-model="scope.row.stock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input> | ||
| 145 | + </el-form-item> | ||
| 132 | </template> | 146 | </template> |
| 133 | </el-table-column> | 147 | </el-table-column> |
| 134 | - <el-table-column label="库存"> | 148 | + <el-table-column label="预警库存" key="96"> |
| 135 | <template slot-scope="scope"> | 149 | <template slot-scope="scope"> |
| 136 | - <el-input v-model="scope.row.stock" type="number"></el-input> | 150 | + <el-input v-model="scope.row.warnStock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input> |
| 137 | </template> | 151 | </template> |
| 138 | </el-table-column> | 152 | </el-table-column> |
| 139 | - <el-table-column label="体积"> | 153 | + <el-table-column label="体积" key="97"> |
| 140 | <template slot-scope="scope"> | 154 | <template slot-scope="scope"> |
| 141 | - <el-input v-model="scope.row.volume" type="number"></el-input> | 155 | + <el-input v-model="scope.row.volume" ></el-input> |
| 142 | </template> | 156 | </template> |
| 143 | </el-table-column> | 157 | </el-table-column> |
| 144 | - <el-table-column label="重量"> | 158 | + <el-table-column label="重量" key="98"> |
| 145 | <template slot-scope="scope"> | 159 | <template slot-scope="scope"> |
| 146 | - <el-input v-model="scope.row.weight" type="number"></el-input> | 160 | + <el-input v-model="scope.row.weight" ></el-input> |
| 147 | </template> | 161 | </template> |
| 148 | </el-table-column> | 162 | </el-table-column> |
| 149 | - <el-table-column label="条码"> | 163 | + <el-table-column label="条码" key="99"> |
| 150 | <template slot-scope="scope"> | 164 | <template slot-scope="scope"> |
| 151 | <el-input v-model="scope.row.barCode"></el-input> | 165 | <el-input v-model="scope.row.barCode"></el-input> |
| 152 | </template> | 166 | </template> |
| 153 | </el-table-column> | 167 | </el-table-column> |
| 168 | + <template v-if="ratesForm.spec == 2"> | ||
| 169 | + <el-table-column | ||
| 170 | + fixed="right" | ||
| 171 | + label="操作" | ||
| 172 | + width="50" | ||
| 173 | + key="100"> | ||
| 174 | + <template slot-scope="scope"> | ||
| 175 | + <el-button @click="scope.row.status = 1" type="text" size="small" v-show="scope.row.status == undefined || scope.row.status == 0 ">禁用</el-button> | ||
| 176 | + <el-button @click="scope.row.status = 0" type="text" size="small" v-show="scope.row.status == 1">启用</el-button> | ||
| 177 | + </template> | ||
| 178 | + </el-table-column> | ||
| 179 | + </template> | ||
| 154 | </el-table> | 180 | </el-table> |
| 155 | </el-form-item> | 181 | </el-form-item> |
| 156 | </el-form> | 182 | </el-form> |
| @@ -158,16 +184,26 @@ | @@ -158,16 +184,26 @@ | ||
| 158 | 184 | ||
| 159 | <!-- 商品详情 --> | 185 | <!-- 商品详情 --> |
| 160 | <el-tab-pane label="商品描述" name="third"> | 186 | <el-tab-pane label="商品描述" name="third"> |
| 161 | - <editor v-model="baseForm.description" :min-height="400"/> | 187 | + <el-form ref="third" :model="baseForm" :rules="rules"> |
| 188 | + <el-form-item prop="description"> | ||
| 189 | + <editor v-model="baseForm.description" :min-height="380"/> | ||
| 190 | + </el-form-item> | ||
| 191 | + </el-form> | ||
| 162 | </el-tab-pane> | 192 | </el-tab-pane> |
| 163 | 193 | ||
| 164 | <!-- 销售设置 --> | 194 | <!-- 销售设置 --> |
| 165 | <el-tab-pane label="销售设置" name="fourth"> | 195 | <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="请输入库存数量"/> | 196 | + <el-form ref="fourth" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%"> |
| 197 | + <el-form-item label="虚拟销量" prop="virtualSalesCount"> | ||
| 198 | + <el-input v-model="baseForm.virtualSalesCount" placeholder="请输入虚拟销量" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/> | ||
| 169 | </el-form-item> | 199 | </el-form-item> |
| 170 | - <el-form-item label="上下架状态" prop="status"> | 200 | + <el-form-item label="是否展示库存" prop="showStock"> |
| 201 | + <el-radio-group v-model="baseForm.showStock"> | ||
| 202 | + <el-radio :label="true">是</el-radio> | ||
| 203 | + <el-radio :label="false">否</el-radio> | ||
| 204 | + </el-radio-group> | ||
| 205 | + </el-form-item> | ||
| 206 | + <el-form-item label="商品状态" prop="status"> | ||
| 171 | <el-radio-group v-model="baseForm.status"> | 207 | <el-radio-group v-model="baseForm.status"> |
| 172 | <el-radio :label="0">上架</el-radio> | 208 | <el-radio :label="0">上架</el-radio> |
| 173 | <el-radio :label="1">下架</el-radio> | 209 | <el-radio :label="1">下架</el-radio> |
| @@ -212,15 +248,15 @@ export default { | @@ -212,15 +248,15 @@ export default { | ||
| 212 | categoryIds: null, | 248 | categoryIds: null, |
| 213 | sort: null, | 249 | sort: null, |
| 214 | description: null, | 250 | description: null, |
| 215 | - bannerUrl: null, | ||
| 216 | - picUrls: [], | ||
| 217 | - totalStock: null, | ||
| 218 | - status: 0 | 251 | + picUrls: null, |
| 252 | + status: 0, | ||
| 253 | + virtualSalesCount: 0, | ||
| 254 | + showStock: true, | ||
| 219 | }, | 255 | }, |
| 220 | categoryList: [], | 256 | categoryList: [], |
| 221 | // 价格库存 | 257 | // 价格库存 |
| 222 | ratesForm: { | 258 | ratesForm: { |
| 223 | - spec: 0, | 259 | + spec: 1, |
| 224 | // 规格明细 | 260 | // 规格明细 |
| 225 | rates: [{}] | 261 | rates: [{}] |
| 226 | }, | 262 | }, |
| @@ -239,28 +275,39 @@ export default { | @@ -239,28 +275,39 @@ export default { | ||
| 239 | 275 | ||
| 240 | // 表单校验 | 276 | // 表单校验 |
| 241 | rules: { | 277 | 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 | - ], | 278 | + name:[{required: true, message: "商品名称不能为空", trigger: "blur"},], |
| 279 | + description: [{required: true, message: "描述不能为空", trigger: "blur"},], | ||
| 280 | + categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"},], | ||
| 281 | + status: [{required: true, message: "商品状态不能为空", trigger: "blur"}], | ||
| 282 | + picUrls: [{required: true, message: "商品轮播图地址不能为空", trigger: "blur"}], | ||
| 283 | + virtualSalesCount: [{required: true, message: "虚拟销量不能为空", trigger: "blur"}], | ||
| 252 | }, | 284 | }, |
| 253 | }; | 285 | }; |
| 254 | }, | 286 | }, |
| 287 | + | ||
| 255 | created() { | 288 | created() { |
| 256 | this.getListCategory(); | 289 | this.getListCategory(); |
| 257 | this.getPropertyPageList(); | 290 | this.getPropertyPageList(); |
| 258 | }, | 291 | }, |
| 259 | methods: { | 292 | methods: { |
| 293 | + async confirmLeave(active, old){ | ||
| 294 | + await this.$refs[old].validate((valid) => { | ||
| 295 | + console.log(valid) | ||
| 296 | + if (!valid) { | ||
| 297 | + return reject(); | ||
| 298 | + } | ||
| 299 | + }); | ||
| 300 | + }, | ||
| 301 | + // 必选标识 | ||
| 302 | + addRedStar(h, { column }) { | ||
| 303 | + return [ | ||
| 304 | + h('span', { style: 'color: #F56C6C' }, '*'), | ||
| 305 | + h('span', ' ' + column.label) | ||
| 306 | + ]; | ||
| 307 | + }, | ||
| 260 | changeRadio() { | 308 | changeRadio() { |
| 261 | - | ||
| 262 | - this.$refs.rates.doLayout() | ||
| 263 | - if (this.ratesForm.spec == 0) { | 309 | + this.$refs.ratesTable.doLayout() |
| 310 | + if (this.ratesForm.spec == 1) { | ||
| 264 | this.ratesForm.rates = [{}] | 311 | this.ratesForm.rates = [{}] |
| 265 | } else { | 312 | } else { |
| 266 | this.ratesForm.rates = [] | 313 | this.ratesForm.rates = [] |
| @@ -289,7 +336,7 @@ export default { | @@ -289,7 +336,7 @@ export default { | ||
| 289 | return array; | 336 | return array; |
| 290 | }) | 337 | }) |
| 291 | .forEach(v => { | 338 | .forEach(v => { |
| 292 | - rates.push({spec: v}) | 339 | + rates.push({spec: v, status: 0, name: Array.of(v).join()}) |
| 293 | }); | 340 | }); |
| 294 | this.ratesForm.rates = rates | 341 | this.ratesForm.rates = rates |
| 295 | }, | 342 | }, |
| @@ -304,38 +351,51 @@ export default { | @@ -304,38 +351,51 @@ export default { | ||
| 304 | this.$emit("closeDialog"); | 351 | this.$emit("closeDialog"); |
| 305 | }, | 352 | }, |
| 306 | submit() { | 353 | submit() { |
| 354 | + this.$refs[this.activeName].validate((valid) => { | ||
| 355 | + if (!valid) { | ||
| 356 | + return; | ||
| 357 | + } | ||
| 307 | let rates = this.ratesForm.rates; | 358 | let rates = this.ratesForm.rates; |
| 308 | // 动态规格调整字段 | 359 | // 动态规格调整字段 |
| 309 | - if (this.ratesForm.spec == 1) { | 360 | + if (this.ratesForm.spec == 2) { |
| 310 | rates.forEach(r => { | 361 | rates.forEach(r => { |
| 311 | let properties = [] | 362 | let properties = [] |
| 312 | - if(r.spec instanceof Array){ | ||
| 313 | - r.spec.forEach((v, i) => { | 363 | + Array.of(r.spec).forEach((v, i) => { |
| 314 | let specValue = this.dynamicSpec[i].specValue.find(o => o.name == v); | 364 | let specValue = this.dynamicSpec[i].specValue.find(o => o.name == v); |
| 315 | let propertie = {}; | 365 | let propertie = {}; |
| 316 | propertie.propertyId = this.dynamicSpec[i].specId; | 366 | propertie.propertyId = this.dynamicSpec[i].specId; |
| 317 | propertie.valueId = specValue.id; | 367 | propertie.valueId = specValue.id; |
| 318 | properties.push(propertie); | 368 | properties.push(propertie); |
| 319 | }) | 369 | }) |
| 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; | 370 | r.properties = properties; |
| 328 | }) | 371 | }) |
| 372 | + }else{ | ||
| 373 | + rates[0].name = this.baseForm.name; | ||
| 374 | + rates[0].status = this.baseForm.status; | ||
| 329 | } | 375 | } |
| 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) => { | 376 | + |
| 377 | + console.log(rates) | ||
| 378 | + | ||
| 379 | + let form = this.baseForm | ||
| 380 | + if(form.picUrls instanceof Array){ | ||
| 381 | + form.picUrls = form.picUrls.flatMap(m=>m.split(',')) | ||
| 382 | + }else if(form.picUrls.split(',') instanceof Array){ | ||
| 383 | + form.picUrls = form.picUrls.split(',').flatMap(m=>m.split(',')) | ||
| 384 | + }else{ | ||
| 385 | + form.picUrls = Array.of(form.picUrls) | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + form.skus = rates; | ||
| 389 | + form.specType = this.ratesForm.spec; | ||
| 390 | + form.categoryId = form.categoryIds[this.baseForm.categoryIds.length - 1]; | ||
| 391 | + createSpu(form).then((response) => { | ||
| 334 | console.log(response) | 392 | console.log(response) |
| 335 | this.$modal.msgSuccess("新增成功"); | 393 | this.$modal.msgSuccess("新增成功"); |
| 336 | this.$emit("closeDialog"); | 394 | this.$emit("closeDialog"); |
| 395 | + }).catch((err) => { | ||
| 396 | + console.log(this.baseForm.picUrls) | ||
| 397 | + }); | ||
| 337 | }); | 398 | }); |
| 338 | - | ||
| 339 | }, | 399 | }, |
| 340 | /** 查询规格 */ | 400 | /** 查询规格 */ |
| 341 | getPropertyPageList() { | 401 | getPropertyPageList() { |