|
@@ -1,89 +1,94 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <div v-if="multipleSpec">
|
|
|
- <div style="margin-bottom: 16px">
|
|
|
- <el-button :plain="true" type="primary" size="small" @click="handleSpecificationShow">添加规格</el-button>
|
|
|
+ <div v-if="multiSku === 1" style="padding: 16px 0px">
|
|
|
+ <el-form ref="spec" :model="{ specList }" label-width="80px">
|
|
|
+ <div v-for="(spec, index) in specList" :key="index" style="margin-bottom: 20px">
|
|
|
+ <el-row style="margin-bottom: 10px">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="`规格项${index + 1}`" :prop="`specList.${index}.name`" :rules="{ required: true, message: '请输入规格名称', trigger: 'blur' }">
|
|
|
+ <el-input v-model="spec.name" :disabled="!spec.edit" @keyup.enter.native="spec.edit = false" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="16">
|
|
|
+ <el-button v-if="spec.edit" type="text" style="margin-left: 10px" @click="spec.edit = false">确定</el-button>
|
|
|
+ <template v-else>
|
|
|
+ <el-button type="text" style="margin-left: 10px" @click="spec.edit = true">编辑</el-button>
|
|
|
+ <el-button type="text" class="del" style="margin-left: 10px" @click="specList.splice(index, 1)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-form-item :prop="`specList.${index}.vals`" :rules="{ required: true, message: '请完善规格值', trigger: 'blur' }">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-tag v-for="(tag, index) in spec.vals" :key="index" closable style="margin-right: 10px" @close="spec.vals.splice(index, 1)">{{ tag }}</el-tag>
|
|
|
+ <el-input v-if="spec.editVals" v-model="specValTmp" style="display: inline-block;width: 120px; margin-right: 10px" size="mini" @keyup.enter.native="checkSpecVal(spec)" />
|
|
|
+ <el-button v-if="!spec.edit&&!spec.editVals" type="text" style="margin-left: 10px" icon="el-icon-plus" size="small" @click="spec.editVals = true">添加规格值</el-button>
|
|
|
+ <el-button v-if="spec.editVals" type="text" @click="checkSpecVal(spec)">确认</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-form-item>
|
|
|
+ </el-row>
|
|
|
</div>
|
|
|
- <el-table :data="specifications">
|
|
|
- <el-table-column property="specification" label="规格名"/>
|
|
|
- <el-table-column property="value" label="规格值">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-tag type="primary">
|
|
|
- {{ scope.row.value }}
|
|
|
- </el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column align="center" label="操作" width="120">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-button type="danger" size="small" @click="handleSpecificationDelete(scope.row)">删除</el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </div>
|
|
|
- <el-dialog :visible.sync="specVisiable" title="设置规格" :close-on-click-modal="false" width="400px">
|
|
|
- <el-form ref="specForm" :model="specForm" label-width="80px">
|
|
|
- <el-form-item label="规格名:" prop="specification">
|
|
|
- <el-input v-model="specForm.specification"/>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="规格值:" prop="value">
|
|
|
- <el-input v-model="specForm.value"/>
|
|
|
- <div class="tip">多个规格值请用逗号隔开</div>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <div slot="footer" class="dialog-footer">
|
|
|
- <el-button @click="specVisiable = false">取消</el-button>
|
|
|
- <el-button type="primary" @click="handleSpecificationAdd">确定</el-button>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
+ </el-form>
|
|
|
+ <el-button type="primary" size="small" plain @click="specList.push({ name: '', vals: [], edit: true, editVals: false })" style="margin-bottom: 10px">添加规格</el-button>
|
|
|
+ <el-button type="primary" size="small" style="margin-bottom: 10px;margin-left: 10px" :disabled="specList.length === 0" @click="genSku">重新生成SKU表格</el-button>
|
|
|
<br>
|
|
|
- <el-table v-if="multipleSpec" :data="products">
|
|
|
- <el-table-column property="name" label="sku名称" />
|
|
|
- <el-table-column property="picUrl" width="100" label="商品图片">
|
|
|
- <template slot-scope="scope">
|
|
|
- <img v-if="scope.row.picUrl" :src="IMG_URL+scope.row.picUrl" width="40">
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column property="value" label="价格"/>
|
|
|
- <!-- <el-table-column property="originPrice" label="原兑换价格"/> -->
|
|
|
- <el-table-column property="exchangePrice" label="兑换价格"/>
|
|
|
- <el-table-column property="cost" label="成本"/>
|
|
|
- <el-table-column property="quantity" label="库存数量"/>
|
|
|
- <el-table-column align="center" label="操作" width="120">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-button type="primary" size="mini" @click="handleProductShow(scope.row)">设置</el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <el-dialog :visible.sync="productVisiable" title="设置商品" :close-on-click-modal="false" width="400px">
|
|
|
- <el-form ref="productForm" :model="productForm" label-width="100px">
|
|
|
- <el-form-item label="sku名称:" prop="name">
|
|
|
- <el-input v-model="productForm.name" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="价格:" prop="value">
|
|
|
- <el-input-number v-model="productForm.value" />
|
|
|
- </el-form-item>
|
|
|
- <!-- <el-form-item label="原兑换价格:" prop="originPrice">
|
|
|
- <el-input-number v-model="productForm.originPrice"/>
|
|
|
- </el-form-item> -->
|
|
|
- <el-form-item label="兑换价格:" prop="exchangePrice">
|
|
|
- <el-input-number v-model="productForm.exchangePrice"/>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="成本:" prop="cost">
|
|
|
- <el-input-number v-model="productForm.cost"/>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="库存数量:" prop="quantity">
|
|
|
- <el-input-number v-model="productForm.quantity"/>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="商品图片:" prop="picUrl">
|
|
|
- <Upload :value="productForm.picUrl ? [{ fileName: productForm.picUrl }] : []" @input="productForm.picUrl = $event[0] ? $event[0].fileName : ''" :limit="1" />
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <div slot="footer" class="dialog-footer">
|
|
|
- <el-button @click="productVisiable = false">取消</el-button>
|
|
|
- <el-button type="primary" @click="handleProductEdit">确定</el-button>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
+ <el-form ref="sku" :model="{ skuList }">
|
|
|
+ <table v-if="skuList instanceof Array && skuList.length > 0" class="spec-table" border="1" bordercolor="#CCC">
|
|
|
+ <tr>
|
|
|
+ <th :colspan="specList.length">商品规格</th>
|
|
|
+ <th rowspan="2">SKU主图</th>
|
|
|
+ <th rowspan="2">名称</th>
|
|
|
+ <th rowspan="2">价格</th>
|
|
|
+ <th rowspan="2">兑换价格</th>
|
|
|
+ <th rowspan="2">成本</th>
|
|
|
+ <th rowspan="2">库存</th>
|
|
|
+ <th rowspan="2">启用</th>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <th v-for="(spec, index) in specList" :key="index" style="width: 80px">{{ spec.name }}</th>
|
|
|
+ </tr>
|
|
|
+ <!-- k1:v1;k2:v2 -->
|
|
|
+ <tr v-for="(sku, index) in skuList" :key="index">
|
|
|
+ <td v-for="(spec, i) in specList" :key="i" style="min-width: 50px">
|
|
|
+ {{ formatObj(sku.properties)[spec.name] }}
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.picUrl`" :rules="{ required: true, message: '请上传SKU图片', trigger: 'blur' }">
|
|
|
+ <Upload v-model="sku.picUrl" :limit="1" style="height: 40px;overflow: hidden" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.name`" :rules="{ required: true, message: '名称不能为空', trigger: 'blur' }">
|
|
|
+ <el-input v-model="sku.name" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.value`" :rules="[{ required: true, message: '请输入价格', trigger: 'blur' }, { pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/, message: "请输入正确的金额,最多两位小数", trigger: ["blur", "change"] }]">
|
|
|
+ <el-input v-model="sku.value" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.exchangePrice`" :rules="[{ required: true, message: '请输入兑换价格', trigger: 'blur' },{ pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/, message: "请输入正确的金额,最多两位小数", trigger: ["blur", "change"] }]">
|
|
|
+ <el-input v-model="sku.exchangePrice" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.cost`" :rules="[{ required: true, message: '请输入成本', trigger: 'blur' },{ pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/, message: "请输入正确的金额,最多两位小数", trigger: ["blur", "change"] }]">
|
|
|
+ <el-input v-model="sku.cost" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <el-form-item :prop="`skuList.${index}.quantity`" :rules="{ required: true, message: '请输入库存', trigger: 'blur' }">
|
|
|
+ <el-input-number v-model="sku.quantity" :min="0" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ <td style="padding: 0px 10px">
|
|
|
+ <el-form-item :prop="`skuList.${index}.status`" :rules="{ required: true, message: '请选择状态', trigger: 'blur' }">
|
|
|
+ <el-switch v-model="sku.status" active-color="#13ce66" inactive-color="#ff4949" />
|
|
|
+ </el-form-item>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </table>
|
|
|
+ </el-form>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
@@ -101,41 +106,60 @@ export default {
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
- specifications: [],
|
|
|
- products: [],
|
|
|
- specVisiable: false, // 规格弹窗
|
|
|
- specForm: {}, // 规格暂存
|
|
|
- productVisiable: false,
|
|
|
- productForm: {},
|
|
|
+ specList: [],
|
|
|
+ skuList: [],
|
|
|
+ specValTmp: '',
|
|
|
+ specifications: []
|
|
|
}
|
|
|
},
|
|
|
- computed: {
|
|
|
- multipleSpec() {
|
|
|
- return this.multiSku === 1
|
|
|
- },
|
|
|
- },
|
|
|
methods: {
|
|
|
- handleSpecificationShow() {
|
|
|
- this.specForm = {}
|
|
|
- this.specVisiable = true
|
|
|
- },
|
|
|
- handleSpecificationDelete(row) {
|
|
|
- const index = this.specifications.indexOf(row)
|
|
|
- this.specifications.splice(index, 1)
|
|
|
- this.specToProduct()
|
|
|
+ formatObj(properties) {
|
|
|
+ if (properties) {
|
|
|
+ let obj = {}
|
|
|
+ properties.split(';').forEach(item => {
|
|
|
+ obj[item.split(':')[0]] = item.split(':')[1]
|
|
|
+ })
|
|
|
+ return obj
|
|
|
+ }
|
|
|
+ return {}
|
|
|
},
|
|
|
- specToProduct() {
|
|
|
- if (this.specifications.length === 0) {
|
|
|
+ checkSpecVal(spec) {
|
|
|
+ if (!this.specValTmp) {
|
|
|
+ this.$message.warning('请输入规格值')
|
|
|
return
|
|
|
}
|
|
|
- // 根据specifications创建临时规格列表
|
|
|
+ if (spec.vals.find(item => item === this.specValTmp)) {
|
|
|
+ this.$message.warning('规格值已存在')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ spec.vals.push(this.specValTmp)
|
|
|
+ this.specValTmp = ''
|
|
|
+ spec.editVals = false
|
|
|
+ },
|
|
|
+ genSku() {
|
|
|
+ this.$refs.spec.validate((valid, items) => {
|
|
|
+ if (valid) {
|
|
|
+ this.genSkuList()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ genSkuList() {
|
|
|
+ let specificationsTmp = []
|
|
|
+ this.specList.forEach(spec => {
|
|
|
+ spec.vals.forEach(val => {
|
|
|
+ specificationsTmp.push({
|
|
|
+ specification: spec.name,
|
|
|
+ value: val
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
var specValues = []
|
|
|
- var spec = this.specifications[0].specification
|
|
|
+ var spec = specificationsTmp[0].specification
|
|
|
var values = []
|
|
|
values.push(0)
|
|
|
|
|
|
- for (var i = 1; i < this.specifications.length; i++) {
|
|
|
- const aspec = this.specifications[i].specification
|
|
|
+ for (var i = 1; i < specificationsTmp.length; i++) {
|
|
|
+ const aspec = specificationsTmp[i].specification
|
|
|
|
|
|
if (aspec === spec) {
|
|
|
values.push(i)
|
|
@@ -147,11 +171,8 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
specValues.push(values)
|
|
|
-
|
|
|
- // 根据临时规格列表生产商品规格
|
|
|
- // 算法基于 https://blog.csdn.net/tyhj_sf/article/details/53893125
|
|
|
var productsIndex = 0
|
|
|
- var products = []
|
|
|
+ var skuList = []
|
|
|
var combination = []
|
|
|
var n = specValues.length
|
|
|
for (var s = 0; s < n; s++) {
|
|
@@ -164,10 +185,10 @@ export default {
|
|
|
var properties = ''
|
|
|
for (var x = 0; x < n; x++) {
|
|
|
var z = specValues[x][combination[x]]
|
|
|
- specifications.push(this.specifications[z].value)
|
|
|
- properties = `${properties ? (properties + ';') : ''}${this.specifications[z].specification}:${this.specifications[z].value}`
|
|
|
+ specifications.push(specificationsTmp[z].value)
|
|
|
+ properties = `${properties ? (properties + ';') : ''}${specificationsTmp[z].specification}:${specificationsTmp[z].value}`
|
|
|
}
|
|
|
- products[productsIndex] = {
|
|
|
+ skuList[productsIndex] = {
|
|
|
idx: productsIndex,
|
|
|
name: specifications.toString(),
|
|
|
picUrl: '',
|
|
@@ -176,6 +197,7 @@ export default {
|
|
|
value: 0.00,
|
|
|
cost: 0.00,
|
|
|
quantity: 0,
|
|
|
+ status: true,
|
|
|
properties
|
|
|
}
|
|
|
productsIndex++
|
|
@@ -198,44 +220,41 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
} while (isContinue)
|
|
|
-
|
|
|
- this.products = products
|
|
|
+ this.skuList = skuList
|
|
|
},
|
|
|
- handleSpecificationAdd() {
|
|
|
- const valueArr = this.specForm.value.replace(/,/ig,',').replace(/\s*/g,"").split(',') // 替换所有的中文逗号为英文逗号并去空格
|
|
|
- valueArr.forEach(element => {
|
|
|
- let index = this.specifications.length - 1
|
|
|
- for (var i = 0; i < this.specifications.length; i++) {
|
|
|
- const v = this.specifications[i]
|
|
|
- if (v.specification === this.specForm.specification) {
|
|
|
- if (v.value !== element) {
|
|
|
- index = i
|
|
|
- }
|
|
|
+ getSkuList() {
|
|
|
+ if (this.skuList.length === 0) {
|
|
|
+ this.$message.warning('请完善规格并生成sku表格')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ this.$refs.sku.validate((valid, items) => {
|
|
|
+ if (valid) {
|
|
|
+ this.$emit('valid', this.skuList)
|
|
|
+ } else {
|
|
|
+ if (items && Object.keys(items).length>0) {
|
|
|
+ this.$message({
|
|
|
+ message: items[Object.keys(items)[0]][0].message,
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- this.specifications.splice(index + 1, 0, {
|
|
|
- specification: this.specForm.specification,
|
|
|
- value: element
|
|
|
- })
|
|
|
-
|
|
|
- });
|
|
|
- this.specToProduct()
|
|
|
- this.specVisiable = false
|
|
|
- },
|
|
|
- handleProductShow(row) {
|
|
|
- this.productForm = Object.assign({}, row)
|
|
|
- this.productVisiable = true
|
|
|
- },
|
|
|
- handleProductEdit() {
|
|
|
- for (var i = 0; i < this.products.length; i++) {
|
|
|
- const v = this.products[i]
|
|
|
- if (v.idx === this.productForm.idx) {
|
|
|
- this.products.splice(i, 1, this.productForm)
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- this.productVisiable = false
|
|
|
- },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.spec-table {
|
|
|
+ border-collapse: collapse;
|
|
|
+ width: 100%;
|
|
|
+ line-height: 32px;
|
|
|
+ color: #606266;
|
|
|
+ font-size: 14px;
|
|
|
+ th {
|
|
|
+ background-color: #ECECEC;
|
|
|
+ }
|
|
|
+ td {
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
}
|
|
|
-</script>
|
|
|
+</style>
|