一,在spu商品列表页,点击修改按钮,初始化请求页面数据
1.1。点击修改按钮,在spu组件中给子组件spuForn设置ref属性,调用子组件的函数(传递属性id,接口函数的参数),子组件调用四个接口函数,获取数据
<el-button type="primary" icon="el-icon-edit" size="mini" title="修改spu" @click="showUpdateSpuForm(row.id)" ></el-button>
<skuForm v-show="isShowSkuForm" ></skuForm> <spuForm v-show="isShowSpuForm" @visible="isShowSpuForm =$event" ref="spu"></spuForm>
js代码
// 点击修改spu按钮 showUpdateSpuForm(spuId){ this.isShowSpuForm =true // 获取子组件spuForm,调用他里头的方法,发送四个接口函数,获取数据 this.$refs.spu.initUpdateSpuForm(spuId) },
在子组件spuForm中定义该函数,调用四个接口函数,获取数据
//在spu管理列表页,点击修改按钮,父组件在该子组件中定义该函数 async initUpdateSpuForm(spuId) { //发送四个请求获取对应的初始化数据 //获取对应的spu的详情信息 ///admin/product/getSpuById/670 const spuinfoResult = await this.$API.spu.get(spuId); if (spuinfoResult.code === 200) { this.spuInfo = spuinfoResult.data; } //获取对应的spu图片列表 因为图片列表数据并没有在spu详情里面,需要单独发请求 ///admin/product/spuImageList/670 const imageResult = await this.$API.sku.getSpuImageList(spuId); if (imageResult.code === 200) { this.spuImageList = imageResult.data; } //所有的品牌信息 ///admin/product/baseTrademark/getTrademarkList const trademarkResult = await this.$API.trademark.getAll(); if (trademarkResult.code === 200) { this.trademarkList = trademarkResult.data; } //所有的spu基础销售属性 ///admin/product/baseSaleAttrList const baseSaleAttrResult = await this.$API.spu.getSaleList(); if (baseSaleAttrResult.code === 200) { this.baseSaleAttrList = baseSaleAttrResult.data; } },
数据收集
data() { return { dialogImageUrl: "", dialogVisible: false, // spu的详情信息 spuInfo: {}, //图片信息 spuImageList: [], // 所有的品牌信息 trademarkList: [], // 基础销售属性 baseSaleAttrList: [] }; },
2.动态展示spu名称,描述,品牌数据,渲染页面(el-select中收集的id是el-option中的id)
<el-form label-width="100px" :inline="false" size="normal" :model="spuInfo"> <el-form-item label="SPU名称"> <el-input placeholder="请输入spu名称" v-model="spuInfo.spuName"></el-input> </el-form-item> <el-form-item label="品牌"> <el-select placeholder="请选择品牌" value="" v-model="spuInfo.tmId"> <el-option :value="trademark.id" :label="trademark.tmName" v-for="(trademark, index) in trademarkList" :key="trademark.id"> </el-option> </el-select> </el-form-item> <el-form-item label="SPU描述"> <el-input placeholder="请输入spu描述" type="textarea" rows="4" v-model="spuInfo.description" ></el-input> </el-form-item>
3.动态展示spu图片列表
element-ui的upload有个属性file-list,上传图片墙的文件列表,需要url和name属性
而我们返回的spuImageList数据没有该属性,需要更改属性名称
<el-form-item label="SPU描述"> <el-upload action="https://jsonplaceholder.typicode.com/posts/" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :file-list="spuImageList" > <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt="" /> </el-dialog> </el-form-item>
对返回的数据进行整理
//获取对应的spu图片列表 因为图片列表数据并没有在spu详情里面,需要单独发请求 ///admin/product/spuImageList/670 const imageResult = await this.$API.sku.getSpuImageList(spuId); if (imageResult.code === 200) { let spuImageList = imageResult.data spuImageList.forEach(item=>{ item.name = item.imgName; item.url = item.imgUrl; }) this.spuImageList = imageResult.data; }
4.动态展示spu销售属性(表格当中部分)
<el-table border style=" 100%; margin-top:20px" :data="spuInfo.spuSaleAttrList" > <el-table-column align="center" type="index" label="序号" width="80"> </el-table-column> <el-table-column prop="saleAttrName" label="属性名" width="150"> </el-table-column> <el-table-column label="属性值列表" width="width"> <template slot-scope="{row,$index}"> <el-tag :key="spuSaleAttrValue.id" v-for="(spuSaleAttrValue, index) in row.spuSaleAttrValueList" closable :disable-transitions="false" > {{spuSaleAttrValue.saleAttrValueName}} </el-tag> <!-- isEdict先放在属性spuSaleAttrList中,新增的tag也放在属性中 ,编辑模式,查看模式--> <el-input v-if="row.isEdict" v-model="row.saleAttrValueName" ref="saveTagInput" size="small" > </el-input> <el-button v-else class="button-new-tag" size="small" >+ 新增属性值</el-button > </template> </el-table-column> <el-table-column prop="prop" label="操作" width="150"> <template slot-scope="{row,$index}"> <el-button type="danger" size="mini" icon="el-icon-delete" >删除</el-button> </template> </el-table-column> </el-table>
5.动态展示未使用的基础销售属性(计算属性)
computed:{ ///计算未使用的基础销售属性列表 //根据两个数组计算 一个是所有的基础销售属性数组baseSaleAttrList 和 spu的销售属性数组 spuInfo.spuSaleAttrList //从baseSaleAttrList拿到每一个 都去spuInfo.spuSaleAttrList里面对比所有的 如果前面拿到的和后面所有的名字都不相同,就是我们要 //拿的,放进新数组 unusedBaseSaleAttrList(){ return this.baseSaleAttrList.filter(baseSaleAttr => this.spuInfo.spuSaleAttrList.every(spuSaleAttr=> baseSaleAttr.name !== spuSaleAttr.saleAttrName)) } },
<el-form-item label="销售属性"> <el-select :placeholder="unusedBaseSaleAttrList.length >1 ? `还有${unusedBaseSaleAttrList.length}个` : `没有了`" v-model="unusedBaseSaleAttrId"> <el-option value="unusedBaseSaleAttr.id" :label="unusedBaseSaleAttr.name" v-for="(unusedBaseSaleAttr,index) in unusedBaseSaleAttrList" :key="unusedBaseSaleAttr.id"></el-option> </el-select> <el-button type="primary" icon="el-icon-plus">添加销售属性</el-button>
6.收集spu的图片列表
<el-form-item label="SPU描述"> <el-upload action="/dev-api/admin/product/fileUpload" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleUploadSuccess" :file-list="spuImageList" > <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt="" /> </el-dialog> </el-form-item>
js,函数
handleRemove(file, fileList) { //file 被删除的那一张图片信息 //fileList 删除过后剩余的图片列表 // console.log(file, fileList); console.log(file, fileList); }, handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, handleUploadSuccess(response,file, fileList){ console.log(response,file, fileList) // 上传成功后的图片列表中有部分没有response,新上传的有 this.spuImageList = fileList }
7.添加spu销售属性
选择销售属性,点击添加销售属性值,table会新增属性值
选中的属性收集的是id和name
<el-form-item label="销售属性"> <el-select :placeholder="unusedBaseSaleAttrList.length >0 ? `还有${unusedBaseSaleAttrList.length}个` : `没有了`" v-model="unusedBaseSaleAttrIdAndName"> <el-option :value="unusedBaseSaleAttr.id + ':' + unusedBaseSaleAttr.name " :label="unusedBaseSaleAttr.name" v-for="(unusedBaseSaleAttr,index) in unusedBaseSaleAttrList" :key="unusedBaseSaleAttr.id"></el-option> </el-select> <el-button type="primary" icon="el-icon-plus" @click="addSaleAttr">添加销售属性</el-button>
// 添加销售属性 addSaleAttr() { // { // "baseSaleAttrId": "1", // "saleAttrName": "选择颜色", // "spuSaleAttrValueList": [ // { // "saleAttrValueName": "a", // "baseSaleAttrId": "1" // } // ] // } let [ baseSaleAttrId, saleAttrName, ] = this.unusedBaseSaleAttrIdAndName.split(":"); //从select选中项收集数据当中提取id和name //构造销售属性的对象数据添加到销售属性列表当中 this.spuInfo.spuSaleAttrList.push({ baseSaleAttrId, saleAttrName, spuSaleAttrValueList: [], }); this.unusedBaseSaleAttrIdAndName = ""; //清空select的选中项 },
8. 添加spu销售属性属性值
点击添加属性值按钮 ,将查看模式修改成编辑模式
<el-tag :key="spuSaleAttrValue.id" v-for="(spuSaleAttrValue,index) in row.spuSaleAttrValueList" closable :disable-transitions="false" @close="row.spuSaleAttrValueList.splice(index,1)" >{{spuSaleAttrValue.saleAttrValueName}}</el-tag> <!-- 删除属性值,在对应的事件当中去删除当前下标对应的属性值对象 --> <el-input placeholder="请输入" style="150px" v-if="row.isEdit" v-model="row.saleAttrValueName" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)" ></el-input> <el-button v-else class="button-new-tag" size="small" @click="showInput(row)">+ 添加属性值</el-button> </template> </el-table-column>
js代码
//点击添加属性值的按钮切换为编辑模式 input showInput(row) { //要想后期添加的属性数据是响应式,必须使用以下写法 不能用点语法 this.$set(row, "isEdit", true); //自动获取焦点 this.$nextTick(() => { this.$refs.saveTagInput.focus(); }); },
切换成input编辑模式后,失去焦点后,需要将属性值添加到属性值列表中spuSaleAttrValueList
<!-- isEdict先放在属性spuSaleAttrList中,新增的tag也放在属性中 --> <el-input style="50%" placeholder="请输入" v-if="row.isEdict" v-model="row.saleAttrValueName" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)" > </el-input> <el-button v-else class="button-new-tag" size="small" @click="showInput(row)" >+ 新增属性值</el-button >
js代码
//input输入数据之后,数据被收集到了属性对象身上,回车或者失去焦点后 handleInputConfirm(row) { let { saleAttrValueName, baseSaleAttrId } = row; if (!saleAttrValueName.trim()) return; //前面平台属性属性值判定的时候要出去自身 因为平台属性先添加的对象,然后往对象内部才输入的值,最后失去焦点的 //现在我们根本没有添加对象,我们只需要去判断我们输入的属性值名称和目前已有的所有属性值名称对比就好了 let isRepeat = row.spuSaleAttrValueList.some( (item) => item.saleAttrValueName === saleAttrValueName ); if (isRepeat) { this.$message.warning("不能重复"); // row.saleAttrValueName = '' return; } // { // "saleAttrValueName": "a", // "baseSaleAttrId": "1" // } //构造属性值对象添加到对应的数组当中 row.spuSaleAttrValueList.push({ saleAttrValueName, baseSaleAttrId, }); row.isEdict = false; //切换为查看模式 row.saleAttrValueName = ""; //清空input输入框 },
9.删除属性值和删除属性的操作
<el-table-column label="属性值列表" width="width"> <template slot-scope="{row,$index}"> <el-tag :key="spuSaleAttrValue.id" v-for="(spuSaleAttrValue,index) in row.spuSaleAttrValueList" closable :disable-transitions="false" @close="row.spuSaleAttrValueList.splice(index,1)" >{{spuSaleAttrValue.saleAttrValueName}}</el-tag> <!-- 删除属性值,在对应的事件当中去删除当前下标对应的属性值对象 --> <el-input placeholder="请输入" style="150px" v-if="row.isEdit" v-model="row.saleAttrValueName" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)" ></el-input> <el-button v-else class="button-new-tag" size="small" @click="showInput(row)">+ 添加属性值</el-button> </template>
<el-table-column label="操作" width="150"> <template slot-scope="{row,$index}"> <el-button type="danger" size="mini" icon="el-icon-delete" @click="spuInfo.spuSaleAttrList.splice($index,1)" >删除</el-button> </template>