vue 商品规格生成sku,sku多维数组组合,sku组装spData json
1 <script lang="ts"> 2 import {Component, Prop, Vue, Watch} from "vue-property-decorator"; 3 import config from "@/config"; 4 import {queryProductSpecsListApi, queryProductSpecsValueListApi} from "@/apis/productSpecs"; 5 import {ISpecs, ISpecsValue} from "@/apis/productSpecs/types"; 6 import {Message} from "element-ui"; 7 import {IProduct} from "@/apis/product/types"; 8 9 @Component({}) 10 export default class ProductSpecs extends Vue { 11 config = config; 12 // 新增修改表单 13 @Prop(Object) modelForm!: IProduct; 14 // 新增修改表单rules 15 @Prop(Object) rules!: any; 16 // 新增修改表单 17 modelSpecsForm: any = {} 18 //商品规格下拉数据 19 productSpecsValueList: ISpecsValue[] = []; 20 //商品规格属性下拉数据 21 productSpecsList: ISpecs[] = []; 22 23 //列出的属性 二维数组 24 specsList: any[] = []; 25 //选中的规格属性 26 checkedSpecs: any[] = []; 27 //列表 规格列数组 28 tableColumnList:any[] = []; 29 30 //列表数据 31 tableData: any[] = [] 32 33 @Watch('modelForm') 34 onChangeValue(newVal: any, oldVal: any) { 35 console.log(newVal, '监听数据') 36 if (newVal.productSkuVoList) { 37 let SkuVoList: any = []; 38 for (let skuItem of newVal.productSkuVoList) { 39 let obj = skuItem; 40 let sku = JSON.parse(skuItem.spData); 41 sku.forEach((e: any, i: number) => { 42 obj[`specs${i}`] = e.value 43 }) 44 SkuVoList = [...SkuVoList, ...sku] 45 this.tableData.push(obj) 46 } 47 this.specsList = []; 48 this.productSpecsValueList.forEach(async (SpecsValue) => { 49 for (let Item of SkuVoList) { 50 if (SpecsValue.specsName == Item.key) { 51 let obj: any = SpecsValue; 52 let svIndex = this.specsList.findIndex(specs => specs.specsValueId == SpecsValue.id); 53 if (svIndex == -1) { 54 await this.getProductSpecsList(SpecsValue.id || ''); 55 obj.specsName = Item.key; 56 obj.specsValueId = SpecsValue.id; 57 obj.list = this.productSpecsList; 58 this.specsList.push(obj); 59 } 60 obj.list.forEach((e: any, i: number) => { 61 if (e.name == Item.value) 62 this.checkedSpecs.push(e.id) 63 }) 64 } 65 } 66 }) 67 this.tableColumnList=this.specsList; 68 } 69 } 70 71 /** 72 * 商品规格 73 */ 74 getProductSpecsValueList() { 75 queryProductSpecsValueListApi({}).then(e => { 76 this.productSpecsValueList = e; 77 return e; 78 }) 79 } 80 81 /** 82 * 商品规格属性 83 */ 84 async getProductSpecsList(id: string) { 85 await queryProductSpecsListApi({specsValueId: id}).then(e => { 86 this.productSpecsList = e; 87 }) 88 } 89 90 /** 91 * 商品规格 选择 92 * 93 */ 94 handleSpecsValue(value: any) { 95 this.modelSpecsForm.id = ''; 96 this.productSpecsList = []; 97 this.getProductSpecsList(value); 98 } 99 100 /** 101 * 商品规格列出 102 * 103 */ 104 handleSpecs() { 105 let svIndex = this.productSpecsValueList.findIndex(e => e.id == this.modelSpecsForm.specsValueId); 106 if (svIndex != -1) { 107 let obj = { 108 specsValueId: this.modelSpecsForm.specsValueId, 109 specsName: this.productSpecsValueList[svIndex].specsName, 110 list: [], 111 } 112 113 this.modelSpecsForm.id.forEach((id: any) => { 114 let sIndex = this.productSpecsList.findIndex(e => e.id == id); 115 if (sIndex != -1) { 116 let o = this.productSpecsList[sIndex]; 117 o.specsName = obj.specsName 118 obj.list.push(o as never) 119 } 120 }) 121 let index = this.specsList.findIndex((e: any) => e.specsValueId == this.modelSpecsForm.specsValueId); 122 if (index != -1) { 123 this.tableData = []; 124 this.modelForm.productSkuDtoList = []; 125 this.specsList.splice(index, 1, obj); 126 } else 127 this.specsList.push(obj); 128 } 129 130 } 131 132 133 /** 134 *选择规格属性 135 */ 136 handleCheckedSpecs(value: any) { 137 this.tableData = []; 138 this.modelForm.productSkuDtoList = []; 139 } 140 141 /** 142 * 添加规格属性 143 */ 144 handleAddCheckboxName(specsValueIndex: number) { 145 let specsValue = this.productSpecsValueList[specsValueIndex]; 146 let index = this.specsList.findIndex((e: any) => e.specsValueId == specsValue.id); 147 this.specsList[index].list.push({ 148 specsName: this.specsList[index].specsName, 149 specsValueId: this.specsList[index].specsValueId, 150 name: this.specsList[index].checkboxName, 151 id: ((index + this.specsList[index].list.length) * this.specsList[index].list.length) 152 }) 153 this.specsList[index].checkboxName = ''; 154 155 } 156 157 /** 158 * 多维数组组合 159 */ 160 // @ts-ignore 161 doExchange(arr: any) { 162 let len = arr.length; 163 // 当数组大于等于2个的时候 164 if (len >= 2) { 165 // 第一个数组的长度 166 let len1 = arr[0].length; 167 // 第二个数组的长度 168 let len2 = arr[1].length; 169 // 2个数组产生的组合数 170 let lenBoth = len1 * len2; 171 // 申明一个新数组 172 let items = new Array(lenBoth); 173 // 申明新数组的索引 174 let index = 0; 175 for (let i = 0; i < len1; i++) { 176 for (let j = 0; j < len2; j++) { 177 if (arr[0][i] instanceof Array) { 178 items[index] = arr[0][i].concat(arr[1][j]); 179 } else { 180 items[index] = [arr[0][i]].concat(arr[1][j]); 181 } 182 index++; 183 } 184 } 185 let newArr = new Array(len - 1); 186 for (let i = 2; i < arr.length; i++) { 187 newArr[i - 1] = arr[i]; 188 } 189 newArr[0] = items; 190 return this.doExchange(newArr); 191 } else { 192 return arr[0]; 193 } 194 } 195 /** 196 * 生成sku 197 */ 198 handleSKU() { 199 //列表 200 this.tableData = []; 201 //选择的sku 二维数组 202 let SKUList = new Array(); 203 //过滤重复选择的数据 204 let s = new Set( this.checkedSpecs); 205 this.checkedSpecs= Array.from(s) 206 207 this.specsList.forEach((item, index) => { 208 item.isChecked=false; 209 let specs: any = [] 210 item.list.forEach((sku: any) => { 211 this.checkedSpecs.forEach((checkedId: any) => { 212 let o: any = {id: '', specsValueId: item.specsValueId||'', skuName: item.specsName}; 213 if (sku.id == checkedId) { 214 item.isChecked=true; 215 o.id = sku.id; 216 o[`specs${index}`] = sku.name; 217 o.name = sku.name; 218 specs.push(o); 219 } 220 }) 221 }) 222 if(specs.length>0) 223 SKUList.push(specs); 224 }) 225 226 if (SKUList) { 227 this.tableColumnList=this.specsList.filter(e=>e.isChecked==true); 228 //多维数组组合 229 let newArr = this.doExchange(SKUList) as any; 230 //组装sku key value List 231 let spList = new Array(); 232 //组合完成 列表数据 233 let productSkuList = []; 234 //组合需要数据 235 for (let newArrElement of newArr) { 236 //列表对象 237 let obj = {spData: null, skuPic: '', skuPrice: '', stock: '', productId: this.modelForm.id} as any; 238 239 if (!newArrElement.length) { 240 for (let skuListElement of this.specsList) { 241 for (let skuVoListElement of skuListElement.list) { 242 if (skuVoListElement.specsValueId == newArrElement.specsValueId && skuVoListElement.name == newArrElement.name) { 243 //规格列 key,value 244 obj.specs0 = newArrElement.name; 245 //spData key value 246 spList.push({key: skuListElement.specsName, value: newArrElement.name}); 247 continue; 248 } 249 } 250 } 251 } else { 252 for (let i = 0; i < newArrElement.length; i++) { 253 for (let skuListElement of this.specsList) { 254 for (let skuVoListElement of skuListElement.list) { 255 if (skuVoListElement.specsValueId == newArrElement[i].specsValueId && skuVoListElement.name == newArrElement[i].name) { 256 //规格列 key,value 257 obj[`specs${i}`] = newArrElement[i].name 258 //spData key value 259 spList.push({key: skuListElement.specsName, value: newArrElement[i].name}); 260 continue; 261 } 262 } 263 } 264 } 265 } 266 obj.spData = JSON.stringify(spList); 267 productSkuList.push(obj) 268 spList = []; 269 } 270 this.tableData = productSkuList; 271 this.modelForm.productSkuDtoList = this.tableData; 272 console.log(this.tableData, 'productSkuDtoList') 273 } 274 275 } 276 277 /** 278 * 上传前检验 279 * @param file 280 */ 281 beforeUpload(file: File) { 282 if (file.type != "image/png" && file.type != "image/jpg" && file.type != "image/jpeg") { 283 Message.error("请选择正确格式") 284 return false 285 } 286 } 287 288 /** 289 * 下一步,上一步 290 * @param number 291 * 292 */ 293 handleNext(tab: string) { 294 this.$emit('Next', this.modelForm,tab) 295 } 296 297 created() { 298 this.getProductSpecsValueList(); 299 } 300 } 301 </script> 302 303 <template> 304 <div class="divBox"> 305 <el-form ref="form" :model="modelForm" label-width="180px" :rules="rules"> 306 <el-row :gutter="24"> 307 <el-form-item label="商品规格:" prop="productSkuDtoList"> 308 <el-col :span="8"> 309 <el-select v-model="modelSpecsForm.specsValueId" clearable filterable placeholder="请选择规格" 310 @change="handleSpecsValue"> 311 <el-option 312 v-for="(item,index) in productSpecsValueList" 313 :key="index" 314 :label="item.specsName" 315 :value="item.id"> 316 </el-option> 317 </el-select> 318 </el-col> 319 <el-col :span="15"> 320 <el-select v-model="modelSpecsForm.id" clearable filterable multiple 321 collapse-tags placeholder="请选择规格属性"> 322 <el-option 323 v-for="(item,index) in productSpecsList" 324 :key="index" 325 :label="item.name" 326 :value="item.id" 327 :disabled="item.disabled"> 328 </el-option> 329 </el-select> 330 <el-button style="margin-left: 20px" :disabled="!modelSpecsForm.id" size="small" type="primary" plain 331 @click="handleSpecs"> 332 列出规格属性 333 </el-button> 334 </el-col> 335 </el-form-item> 336 </el-row> 337 <el-row :gutter="24"> 338 <el-col :span="21" :offset="3"> 339 <div class="specsLine" v-for="(k,index) in specsList" :key="index"> 340 <div class="title"> 341 {{ k.specsName }} 342 </div> 343 <div class="dec"> 344 <el-row :gutter="24"> 345 <el-col :span="12"> 346 <el-checkbox-group v-model="checkedSpecs" @change="handleCheckedSpecs"> 347 <el-checkbox v-for="(c,i) in k.list" :label="c.id" :key="i">{{ c.name }}</el-checkbox> 348 </el-checkbox-group> 349 </el-col> 350 <el-col :span="7"> 351 <el-input v-model="k.checkboxName" maxlength="8" 352 :placeholder="`请输入${ k.specsName}属性名称`"></el-input> 353 </el-col> 354 <el-col :span="3"> 355 <el-button :disabled="!k.checkboxName" size="small" type="primary" plain 356 @click="handleAddCheckboxName(index)"> 357 添加规格属性 358 </el-button> 359 </el-col> 360 </el-row> 361 </div> 362 </div> 363 </el-col> 364 </el-row> 365 <el-row :gutter="24"> 366 <el-col :span="21" :offset="3"> 367 <el-button :disabled="checkedSpecs.length==0" size="small" type="primary" plain @click="handleSKU"> 368 生成SKU 369 </el-button> 370 </el-col> 371 </el-row> 372 <el-row v-if="tableData.length>0"> 373 <el-form-item label="商品属性:"> 374 </el-form-item> 375 <el-table :data="tableData"> 376 <template v-for="(item,index) in tableColumnList"> 377 <el-table-column :label="item.specsName" width="200" align="center"> 378 <template #default="scope"> 379 <span> {{ scope.row[`specs${index}`] }}</span> 380 </template> 381 </el-table-column> 382 </template> 383 <el-table-column label="图片" align="center" width="200" > 384 <template #default="scope"> 385 <span> 386 <picture-upload ref="fileUpload" :limit="1" v-model="scope.row.skuPic" 387 :before-upload="beforeUpload"> 388 389 </picture-upload> 390 </span> 391 </template> 392 </el-table-column> 393 <el-table-column label="售价" align="center" width="250" prop="skuPrice"> 394 <template #default="scope"> 395 <span> 396 <el-input maxlength="12" 397 oninput="value=value.replace(/^\D*([0-9]\d*\.?\d{0,2})?.*$/,'$1')" style="width: 80%" 398 v-model="scope.row.skuPrice" placeholder="请输入售价"></el-input> 399 </span> 400 </template> 401 </el-table-column> 402 <el-table-column label="库存" align="center" width="250" prop="stock"> 403 <template #default="scope"> 404 <span> 405 <el-input oninput="value=value.replace(/[^\d]/g,'')" style="width:80%" v-model="scope.row.stock" 406 placeholder="请输入库存"></el-input> 407 </span> 408 </template> 409 </el-table-column> 410 <el-table-column label="产品编号" align="center"> 411 <template #default="scope"> 412 <span> 413 {{ (scope.$index + 1) > 10 ? (scope.$index + 1) : '0' + (scope.$index + 1) }} 414 </span> 415 </template> 416 </el-table-column> 417 </el-table> 418 </el-row> 419 420 <el-form-item> 421 <el-button size="small" type="primary" plain @click="handleNext('first')">上一步</el-button> 422 <el-button size="small" type="primary" plain @click="handleNext('third')">下一步</el-button> 423 </el-form-item> 424 </el-form> 425 </div> 426 </template> 427 428 <style lang="scss" scoped> 429 .specsLine { 430 padding: 10px; 431 432 .dec { 433 padding-top: 3px; 434 font-size: 22px; 435 } 436 } 437 </style>