ElementUI开发商品规格组件
电商后台需求-商品规格组件,参数是我们业务上需要的,不过八九不离十,使用elementUI库写的该组件,组件中的上传图片使用了oss-upload组件(详见另一文:阿里oss上传组件)
<template> <div class="sku-list"> <template v-if="!disabled"> <div class="sku-list-head"> <el-button type="primary" size="mini" @click="addSkuRow" >添加规格</el-button > </div> <div class="sku-list-item" v-for="(item, index) in skuData.attrList" :key="index" > <div class="sku-list-item-main"> <div class="sku-list-item__layout"> <span class="span">规格名</span> <el-input size="small" v-model="item.attrName" class="input" ></el-input> </div> <div class="sku-list-item__layout"> <span class="span">规格值</span> <div class="sku-list-item-tags"> <el-tag class="sku-list-item-tag" closable @close="removeSkuAttr(index)" v-for="(subitem, i) in item.attrValue" :key="i" >{{ subitem.attrValue }}</el-tag > <el-button size="small" icon="el-icon-plus" @click="addSkuAttr(index)" >添加</el-button > </div> </div> </div> <el-button type="text" size="small" class="sku-list-item-removeBtn" @click="removeSkuRow(index)" >删除规格</el-button > </div> </template> <el-table border :data="skuData.skuList"> <el-table-column label="图片" align="center" width="120"> <template slot-scope="scope"> <oss-upload :disabled="disabled" :on-success=" (res, file) => onUploadImgSuccess(res, file, scope.row) " dir="erp/goods" > <img v-if="scope.row.icon" :src="scope.row.icon" class="goods-img" /> <el-button v-else-if="!disabled" type="text" size="small" >上传图片</el-button > </oss-upload> </template> </el-table-column> <el-table-column label="规格" align="center" prop="attrPath" ></el-table-column> <el-table-column label="供货价格" align="center"> <template slot-scope="scope"> <el-input :readonly="disabled" v-model="scope.row.priceCost" ></el-input> </template> </el-table-column> <el-table-column label="销售价格" align="center"> <template slot-scope="scope"> <el-input :readonly="disabled" v-model="scope.row.priceCash" ></el-input> </template> </el-table-column> <el-table-column label="划线价格" align="center"> <template slot-scope="scope"> <el-input :readonly="disabled" v-model="scope.row.priceOriginal" ></el-input> </template> </el-table-column> <el-table-column label="商品库存" align="center"> <template slot-scope="scope"> <el-input :readonly="disabled" v-model="scope.row.stock"></el-input> </template> </el-table-column> <!-- <el-table-column label="商品预警值" align="center"> <template slot-scope="scope"> <el-input :readonly="disabled" v-model="scope.row.stock"></el-input> </template> </el-table-column> --> <!-- <el-table-column v-if="!disabled" label="操作" align="center"> <template> <el-button type="text" size="small">删除</el-button> <el-button type="text" size="small">上移</el-button> </template> </el-table-column> --> </el-table> </div> </template> <script> export default { model: { prop: "skuData", event: "change", }, props: { skuData: { type: Object, default: () => ({}), }, disabled: { type: Boolean, default: false, }, }, data() { return {}; }, watch: { "skuData.attrList": { handler() { if (!this.disabled) { this.$set(this.skuData, "skuList", this.getTable()); } }, deep: true, immediate: true, }, }, methods: { // 添加规格行 addSkuRow(i) { this.skuData.attrList.push({ attrName: "", attrValue: [], }); this.$emit("change", this.skuData); }, // 删除规格行 removeSkuRow(i) { this.skuData.attrList.splice(i, 1); this.$emit("change", this.skuData); }, // 删除规格属性值 removeSkuAttr(a, b) { this.skuData.attrList[a].attrValue.splice(b, 1); this.$emit("change", this.skuData); }, // 添加规格属性值 addSkuAttr(i) { this.$prompt("请输入规格值", "添加规格值", { confirmButtonText: "确定", cancelButtonText: "取消", inputPattern: /\S+/, inputErrorMessage: "规格值不能为空", closeOnClickModal: false, }).then(({ value }) => { this.skuData.attrList[i].attrValue.push({ attrValue: value, }); this.$emit("change", this.skuData); }); }, onUploadImgSuccess(res, file, row) { if (!file) { return; } row.icon = file; this.$emit("change", this.skuData); }, getTable() { const table = []; const attrValueAry = []; const arr = []; const tmpSkuData = (this.skuData.attrList || []).filter( (d) => d.attrName != "" && d.attrValue.length > 0 ); if (!tmpSkuData || tmpSkuData.length == 0) { return []; } tmpSkuData.forEach((item) => { attrValueAry.push(item.attrValue); }); function func(skuarr = [], i) { for (let j = 0; j < attrValueAry[i].length; j++) { if (i < attrValueAry.length - 1) { skuarr[i] = attrValueAry[i][j]; func(skuarr, i + 1); } else { arr.push([...skuarr, attrValueAry[i][j]]); } } } func([], 0); arr.forEach((item) => { let attrPath = "", findItem, tableItem; item.forEach((d, idx) => { attrPath += `${tmpSkuData[idx].attrName}:${d.attrValue};`; }); findItem = this.skuData.initSkulist.find((item) => { return attrPath.includes(item.attrPath); }) || {}; tableItem = Object.assign( { priceCost: 0, priceCash: 0, priceOriginal: 0, stock: 0, icon: null, }, findItem, { attrPath, } ); table.push(tableItem); }); return table; }, }, }; </script> <style lang="scss" scoped> .sku-list { &-head { margin-bottom: 10px; } &-item { display: flex; align-items: center; border: 1px solid #eee; border-radius: 5px; margin-bottom: 20px; padding: 20px 50px; &-main { flex: 1; } &-removeBtn { margin-left: 20px; color: #f56c6c; } &__layout { display: flex; align-items: center; margin-bottom: 20px; &:last-child { margin-bottom: 0; } .input { width: 240px; } .span { font-size: 13px; font-weight: bold; margin-right: 10px; } } &-tags { flex: 1; } &-tag { margin-bottom: 10px; margin-right: 10px; } } } </style>