vue 商品规格生成sku,sku多维数组组合,sku组装spData json

发布时间 2023-06-08 16:51:02作者: 假装学习
  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>

 

  1. skuPic: ""
  2. skuPrice: ""
  3. spData: "[{\"key\":\"款式\",\"value\":\"男款\"},{\"key\":\"颜色\",\"value\":\"红色\"}]"
  4. specs0: "男款"
  5. specs1: "红色"
  6. stock: ""