<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>快速入門</title> <!-- 引入元件庫 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <style type="text/css"> .Multiple-specifications { margin: 18px 0 0 0; } .Specification-list { margin: 18px 0 0 0; } .img_marsk { width: 80px; height: 80px; border-radius: 5px; background-color: rgba(0, 0, 0, 0.7); position: absolute; z-index: 999999; top: 0px; left: 0; display: flex; justify-content: center; align-items: center; } .checkout_icon { padding: 3px; display: inline-block; font-size: 16px; margin-right: 10px; ; text-align: center; position: relative; border-radius: 2px; cursor: pointer; } </style> </head> <body> <div id="app"> <div> <div> <!-- 多規格 --> <div class="Multiple-specifications"> <el-card title="多規格" style="border-radius: 10px;"> <div style="display: flex;flex-flow: row wrap;"> <div v-for="(item, index) in dragData" :key="index"> <div label="規格名" :rules="{required: true, message: '請輸入規格名',trigger: 'blur'}"> <div> <el-input v-model="item.title" placeholder="規格名" style="width:200px" @change="makenewTabel(item, 'ruleName', '')" ></el-input> <el-button @click="deletRow(index, item)">刪除</el-button> </div> </div> <div label="規格值" :rules="{required: true, message: '請輸入規格值',trigger: 'blur'}"> <div v-for="(it, ix) in item.num" :key="ix" style="margin-left: 20px;"> <div> <el-input v-model="it.value" placeholder="規格值" style="width:200px" @change="makenewTabel(item, 'value', it)" ></el-input> <el-button @click="deletNum(ix, it, item, index)">刪除</el-button> </div> </div> </div> <div @click="addSku(index)">+新增規格值</div> </div> </div> <div @click="addOtherSku">+新增其他規格 </div> </el-card> </div> <!-- 規格列表 --> <div class="Specification-list"> <el-card title="規格列表" style="border-radius: 10px;"> <el-table :data="duoTableData"> <el-table-column v-for="(val, key) in columns2" :key="key" :prop="val.dataIndex" :label="val.title"> <template slot-scope="scope"> <el-input placeholder="請輸入" v-model="scope.row[val.dataIndex]" @blur="emitTableData"></el-input> </template> </el-table-column> </el-table> </el-card> </div> </div> </div> </div> </body> <!-- 引入vue mete --> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <!-- import JavaScript --> <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <script> new Vue({ el: '#app', data() { return { tableData:[], duoTableData: [], dragData: [], columns2: [], columns: [], specificationListdata: [], } }, created() { this.initDrag() this.columns = [ { title: `售價(US$})`, dataIndex: 'salesPrice', }, { title: `原價(US$})`, dataIndex: 'originalPrice', }, { title: '重量', width: '180', }, { title: '庫存數量', dataIndex: 'goodsStock', }, { title: 'SKU(貨號)', dataIndex: 'skuNo', }, { title: '條形碼', dataIndex: 'barCode', }, { title: '操作', dataIndex: 'action', } ] this.resetColumns() }, methods: { // 重置表頭 /*** * dragData的預設資料 */ initDrag() { this.dragData = this.tableData.length > 0 ? JSON.parse(JSON.stringify(this.tableData)) : [{ title: '', oldTitle: '', num: [{ value: '', oldValue: '' }] }] // 如果是新增取消確定 // 或者單規格,就要清空表頭and 表格資料 // 把old 也要清空 this.duoTableData = [] }, /** * 得到列 */ resetColumns() { const rules = [] for (var j = 0; j < this.dragData.length; j++) { const obj = {} obj.title = this.dragData[j].title obj.dataIndex = `newHead${obj.title}` rules.push(obj) } const columns = [...this.columns] columns.splice(1, 0, ...rules) this.columns2 = columns }, async deletRow(index, item) { if (item.title) { const ret = await this.$confirm(`確定要刪除 ${item.title} 規格?`) if (!ret) { return false } } this.dragData.splice(index, 1) this.tableData = this.dragData this.makenewTabel(item, 'deleteRule', index) }, async deletNum(index, ix, item, iii) { if (item.num < 1) { this.$message.error('必須有一個規格值', 2) return false } if (ix.value) { let title = `確定要刪除 ${item.title} 規格中的 ${ix.value}?` if (!item.title) { title = `確定要刪除 ${ix.value} 規格值?` } const ret = await this.$confirm(title) if (!ret) { return false } } this.dragData[iii].num.splice(index, 1) this.makenewTabel(item, 'deleteRule', ix) }, addSku(index) { this.dragData[index].num.push({ value: '', oldValue: '' }) }, addOtherSku() { this.dragData.push({ title: '', oldTitle: '', num: [{ value: '', oldValue: '' }] }) }, /** 按規格得到笛卡爾乘積列表 handleList */ getDecareList() { const ret = [] if (this.dragData.length === 0) { return ret } else if (this.dragData.length === 1) { for (var m = 0; m < this.dragData[0].num.length; m++) { const e = {} e[`newHead${this.dragData[0].title}`] = this.dragData[0].num[m].value e['weightUnit'] = 'g' e['goodsStock'] = 0 ret.push(e) } return ret } // 展開table中的資料 const arr1 = this.dragData.map((item) => { const res = [] item.num.forEach(v => { res.push({ value: v.value, ruleName: item.title }) }) return res }) // 構造笛卡爾乘積 const r = arr1.reduce((col, row) => { const res = [] col.forEach(c => { row.forEach(r => { const t = Array.isArray(c) ? [...c] : [`#${c.ruleName}#${c.value}`] t.push(`#${r.ruleName}#${r.value}`) res.push(t) }) }) return res }) const pattern = new RegExp('#([^#]+)#(.*)') let match = [] for (var i = 0; i < r.length; i++) { const e = {} for (var k = 0; k < r[i].length; k++) { match = pattern.exec(r[i][k]) if (match) { e[`newHead${match[1]}`] = match[2] e['weightUnit'] = 'g' e['goodsStock'] = 0 } } ret.push(e) } return ret }, /*** 規格生成 */ makenewTabel(item, type, value) { this.resetColumns() // 深複製一個值 const copyListData = JSON.parse(`${JSON.stringify(this.duoTableData)}`) // 得到笛卡爾列 const specificationListdata = this.getDecareList() const oldDataList = {} let speckey = [] // 原值 let key = '' let title = '' // 得到規格名用於data中舊的規格資訊 const ruleNames = this.dragData.map(table => { return `newHead${table.title}` }) copyListData.forEach(data => { speckey = [] this.dragData.forEach(table => { // 值變化 title = `newHead${table.title}` key = data[title] if (!key) { if (type === 'value') { data[title] = value.value key = value.value } } if (type === 'value' && table === item && key === value.oldValue) { data[`newHead${table.title}`] = value.value key = value.value } else { if (type === 'ruleName' && table === item) { data[`newHead${table.title}`] = data[`newHead${table.oldTitle}`] key = data[`newHead${table.oldTitle}`] } } speckey.push(key) }) // 刪除原來的舊列原來的舊值 Object.keys(data).forEach(key => { if (key.startsWith('newHead') && !ruleNames.includes(key)) { delete data[key] } }) oldDataList[speckey.join('-')] = data }) // 新值 const temps = specificationListdata temps.forEach((data, index) => { speckey = [] this.dragData.forEach(table => { speckey.push(data[`newHead${table.title}`]) }) key = speckey.join('-') if (oldDataList[key]) { temps[index] = oldDataList[key] } }) this.duoTableData = temps if (type !== 'reset') { if (type === 'value') { value.oldValue = value.value } else { item.oldTitle = item.title } } }, // 每次失去焦點後,把值emit emitTableData() { const emitData = { tableData: this.tableData, specificationListdata: this.specificationListdata } }, } }); </script> </html>