<template> <div class="goods-all"> <!-- 选择商品类目 start --> <el-card class="good-all-type" v-if="!isShowGoodsDetails"> <div slot="header" class="clearfix"> <p class="card-header-title"><span class="blue-block-goods"></span>选择商品所属类目</p> </div> <div> <div> <p class="goods-type-tip">为商品设置正确的类目,能让商品快速的被搜索到</p> </div> <div class="goods-type-options" v-loading="loading"> <el-cascader-panel v-model="SSQList" :props='props' @change="SSQChange" ref="ssqCascader"></el-cascader-panel> </div> <el-button type="primary" class="next-step" :disabled="isNextStep" @click="nextStep">下一步</el-button> </div> </el-card> <!-- 选择商品类目 end --> <!-- 添加商品 start --> <el-card class="box-card good-details-body" v-if="isShowGoodsDetails"> <div class="floor-nav" id="floorNavList"> <ul class="nav-list"> <li class="nav-list-item" :class="{'floor-item-active': isFIActive === index}" v-for="(item, index) in floorNav" :key="item.id" @click="setFloorNavMountClick(index)">{{ item.name }}</li> </ul> </div> <div class="floor-cont" ref="scrollview"> <!-- 商品信息 --> <div class="floor-item"> <div class="floor-item-box"> <p class="card-header-title floor-item-box-title"><span class="blue-block-goods blue-block-goods-title"></span>商品信息</p> <Goodsinfomation ref="goodsInfo" :goodsinfodata='goodsinfodata'/> </div> </div> <!-- 商品规格 --> <div class="floor-item"> <div class="floor-item-box"> <p class="card-header-title floor-item-box-title"><span class="blue-block-goods blue-block-goods-title"></span>商品规格</p> <GoodsSpecifications ref="goodsspecifications" :specificationsdata="specificationsdata" @calcSpeTable="calcSpeTable"/> </div> </div> <!-- 商品售价 --> <div class="floor-item"> <div class="floor-item-box"> <p class="card-header-title floor-item-box-title"><span class="blue-block-goods blue-block-goods-title"></span>商品售价</p> <GoodsParameter ref="goodsparameter" :parameterdata="parameterdata" /> </div> </div> <!-- 商品详情 --> <div class="floor-item"> <div class="floor-item-box"> <p class="card-header-title floor-item-box-title"><span class="blue-block-goods blue-block-goods-title"></span>商品详情</p> <Goodsimg ref="goodsdetailsimg" :imgdata="imgdata"/> </div> </div> <!-- 售后及服务 --> <div class="floor-item"> <div class="floor-item-box"> <p class="card-header-title floor-item-box-title"><span class="blue-block-goods blue-block-goods-title"></span>售后及服务</p> <Goodsaftersale ref="goodsaftersale" :goodsaftersale="goodsaftersale" /> <div class="submit-type-con"> <el-radio-group v-model="goodsAllData.submit" size="small"> <el-radio :label="0" border>放入仓库</el-radio> <el-radio :label="1" border>立即上架</el-radio> </el-radio-group> </div> </div> </div> </div> <div class="submit-cont"> <el-button type="primary" style="padding: 10px 30px;" @click="save">提 交</el-button> </div> </el-card> <!-- 添加商品 end --> </div> </template> <script> import { getAreaList } from '@/api/module/retreat/address'; import { NewGetCategory,addGoods,getGoodsNew,updateGoodsNew } from '@/api/module/goods'; import Goodsinfomation from './components/goodsinfomation'; import GoodsSpecifications from './components/goodsspecifications'; import GoodsParameter from './components/goodsparameter'; import Goodsimg from './components/goodsimg'; import Goodsaftersale from './components/goodsaftersale'; export default { name: 'Index', props: { option: { type: Number, required: true } }, components: { Goodsinfomation, GoodsSpecifications, GoodsParameter, Goodsimg, Goodsaftersale, }, data() { return { loading: false, SSQList: [], // 省市区 SSQStr: '', // 省市区 拼接 props: { expandTrigger: 'click', lazy: true, lazyLoad: this.lazyLoad, value: "id", label: 'label', leaf: 'leaf' }, isNextStep: true, isShowGoodsDetails: false, isFIActive: 0, /**/ floorNav: [ { id: 1, name: '商品信息' }, { id: 2, name: '商品规格' }, { id: 3, name: '商品售价' }, { id: 4, name: '商品详情' }, { id: 5, name: '售后及服务' } ], /* 商品信息 */ goodsinfodata: { // orgGoodsInfoForm: {}, categoryList: [], categoryStr: '' }, /* 商品规格 */ specificationsdata: [], /* 商品售价 */ parameterdata: { pamDataList: [], pamNameList: [], pamTableList: [], singleSpecTable: [] }, /* 商品详情 */ imgdata: { description: '' }, /* 售后及服务 */ goodsaftersale: { stags: [], freight_id: 310, delay_compensate: 24, aftersale_time: 7 }, goodsAllData: { submit: 0, }, // 商品所有数据 TIMER: null, } // return end }, created() { // option 商品的id //debugger if( this.option && this.option !== 0 ) { let data = { goodsId: this.option}; getGoodsNew(data).then(res => { //console.log("编辑接口返回", res); if(res.data) { this.isShowGoodsDetails = true; // 商品信息 this.goodsinfodata = { goods_id: res.data.goods_id, categoryStr: '', // 商品分类 地址拼接 categoryList: [], // 商品分类 id集合的数组 goods_des: res.data.goods_des, // 关键词 goods_name: res.data.goods_name, // 商品标题 category_id: res.data.category_id, producing_area: Number(res.data.producing_area), // 产地 deliver_area: Number(res.data.deliver_area), // 发货地 unit: res.data.unit, // 单位 goods_brand: res.data.goods_brand, // 品牌 web_url: res.data.web_url, // 外部链接 out_goods_id: res.data.out_goods_id, // 商品编码 imgs: res.data.imgs // 商品图片 } this.goodsinfodata.categoryStr = res.data.category_first_name + '/' + res.data.category_first_name + '/' + res.data.category_three_name; let arr = []; arr[0] = res.data.category_first_id; arr[0] = res.data.category_second_id; arr[0] = res.data.category_three_id; this.goodsinfodata.categoryList = arr; // 商品规格, 售价由规格决定 if(res.data.specs && res.data.specs.length > 0) { this.specificationsdata = res.data.specs; } // 商品售价 // debugger if(res.data.specs_group && res.data.specs_group.length > 0) { //this.parameterdata let prePriceArr = []; this.parameterdata.pamTableList = []; this.parameterdata.pamDataList = []; res.data.specs_group.forEach((item)=> { item.js_price = item.js_price / 100; item.sl_price = item.js_price / 100; item.price = item.price / 100; item.sc_price = item.sc_price / 100; // item.stock = item.stock; // item.weight = item.weight; prePriceArr = []; prePriceArr.push(item); this.parameterdata.pamTableList.push( prePriceArr ); this.parameterdata.pamDataList.push(item.spec_values); }) this.parameterdata.pamNameList = res.data.specs; }else { this.parameterdata.pamTableList = []; let singleSpecObj = { js_price:'', sl_price:'', price:'', sc_price:'', stock:'', weight:'', } this.parameterdata.singleSpecTable = []; singleSpecObj.js_price = res.data.js_price / 100; singleSpecObj.sl_price = res.data.js_price / 100; singleSpecObj.price = res.data.price / 100; singleSpecObj.sc_price = res.data.sc_price / 100; singleSpecObj.stock = res.data.stock; singleSpecObj.weight = res.data.weight; this.parameterdata.singleSpecTable.push(singleSpecObj); } // 商品详情 this.imgdata.description = res.data.description; // 售后服务 this.goodsaftersale.freight_id = res.data.freight_id; this.goodsaftersale.delay_compensate = res.data.delay_compensate; this.goodsaftersale.aftersale_time = res.data.aftersale_time; let stagArr = []; if( res.data.stags && !Array.isArray(res.data.stags)) { if( res.data.stags.indexOf(',') > -1 ) { stagArr = res.data.stags.split(','); stagArr.forEach(item => { if (item) { this.goodsaftersale.stags.push(Number(item)); } }) }else { this.goodsaftersale.stags.push( Number(res.data.stags) ) } }else { this.goodsaftersale.stags = []; } } }); } }, mounted() { }, methods: { // 规格子组件,传给父组件的数据 calcSpeTable(data) { if(data.pamTableList.length > 0) { // debugger data.pamTableList.forEach((item, index) => { if( Array.isArray(data.pamDataList[index]) ) { item[0].spec_values = data.pamDataList[index]; }else { item[0].spec_values.push(data.pamDataList[index]); } }) } this.parameterdata = data; //console.log(153,this.parameterdata); }, // 只有点击完最后一级,才会有值 SSQChange() { if(this.SSQList && this.SSQList.length > 0) { this.isNextStep = false }else { this.SSQList = [] this.isNextStep = true } }, lazyLoad(node, resolve) { this.SSQList = []; this.SSQStr = ''; //debugger this.getArea(node, resolve); if(this.SSQList && this.SSQList.length > 0) { this.isNextStep = false }else { this.isNextStep = true } }, getArea(node, resolve) { const level = node.level; let limboNode = {}; if(level === 0) { limboNode = {id: 0} } if(level === 1) { limboNode = { id: node.value }; } if(level === 2) { limboNode = { id: node.value }; } this.loading = true; NewGetCategory(limboNode).then(res => { let result = {}; //debugger if (level === 0) { result = res.data result.forEach(item => { item.value = item.id; item.label = item.label; item.children = []; item.leaf = 0; // 可以控制 是否有下级 值为true都不行,必须等于0 }) } if (level === 1) { for(let i = 0; i < res.data.length; i++) { if( limboNode.id === res.data[i].id ) { result = res.data[i].children; break; } } result.forEach(item => { item.value = item.id; item.label = item.label item.children=[]; //这句代码表示当点击最后一级的时候 label后面不会转圈圈 并把相关值赋值到选择器上 item.leaf = 0 }) } if (level === 2) { for(let i = 0; i < res.data.length; i++) { if( res.data[i].children.length > 0) { for(let j = 0; j < res.data[i].children.length; j++) { if( limboNode.id === res.data[i].children[j].id ) { result = res.data[i].children[j].children; break; } } } } result.forEach(item => { item.value = item.id; item.label = item.label item.leaf = 1; }) } resolve(result) this.loading = false; }); }, // 添加商品后,下一步 操作 nextStep() { // 注意数据格式 [1,2,3] 数组,且里面是数字类型 let ssqLabelList = this.$refs['ssqCascader'].getCheckedNodes()[0].pathLabels; this.goodsinfodata.categoryList = this.SSQList; this.goodsinfodata.categoryStr = ssqLabelList[0] + '/' + ssqLabelList[1] + '/' + ssqLabelList[2]; this.isShowGoodsDetails = true; // console.log(232,this.goodsinfodata.categoryStr,this.goodsinfodata.categoryList); }, // 保存/提交 save() { // 此处变量 有顺序 校验时,电梯至某处 // 商品信息 是否填写完整 let isGoodsInfoMsg = this.$refs['goodsInfo'].validateGoodsInfoForm(); // 商品规格 无需校验 // 商品售价,通过获取的数据,分别进行判断 let isGoodsPrice = true; let spsjData1 = this.$refs.goodsparameter.singleSpecTable; let spsjData2 = this.$refs.goodsparameter.orgGoodsPam; // 如果有,则说明有规格组合数据 if ( spsjData2.pamTableList && spsjData2.pamTableList.length > 0 ) { for(let i = 0; i < spsjData2.pamTableList.length; i++) { let itemObj = spsjData2.pamTableList[i][0]; for (let itemKey in itemObj) { //---------------- // 有多余字段,可能为空,需要对有效字段单独判断 if ( !itemObj['js_price'] || !itemObj['sl_price'] || !itemObj['price'] || !itemObj['sc_price'] || !itemObj['stock'] || !itemObj['weight']) { isGoodsPrice = false; break } else { // 所有校验通过,对价格进行处理,*100 if ( itemKey === 'js_price' || itemKey === 'sl_price' || itemKey === 'price' || itemKey === 'sc_price') { itemObj[itemKey] = itemObj[itemKey] * 100; } isGoodsPrice = true; } // --------------- } if (!isGoodsPrice) { break } } }else { // 无规格组合数据 let slingleSpeObj = spsjData1[0]; for (let key in slingleSpeObj) { if ( !slingleSpeObj[key] ) { isGoodsPrice = false; break } else { // 所有校验通过,对价格进行处理,*100 if ( key === 'js_price' || key === 'sl_price' || key === 'price' || key === 'sc_price') { slingleSpeObj[key] = slingleSpeObj[key] * 100; } isGoodsPrice = true; } } } // 商品详情 是否填写完整 let isGoodsDetailsImgMsg = this.$refs.goodsdetailsimg.goodsDeForm.description ? true : false; // 售后服务 是否填写完整 let isGoodsAfterSaleMsg = this.$refs['goodsaftersale'].validateGoodsAfterSaleForm(); if(!isGoodsInfoMsg) { this.$message({type:'error',message:'商品信息未填写完整'}); this.setFloorNavMountClick(0); return } if(!isGoodsPrice) { this.$message({type:'error',message:'商品售价未填写完整'}); this.setFloorNavMountClick(2); return } if(!isGoodsDetailsImgMsg) { this.$message({type:'error',message:'请先上传描述商品详情的图片'}); this.setFloorNavMountClick(3); return } if(!isGoodsAfterSaleMsg) { this.$message({type:'error',message:'售后及服务未填写完整'}); this.setFloorNavMountClick(4); return } // 所有校验通过,整理数据 // 获取 商品信息数据 let spxxData = this.$refs.goodsInfo.goodsInfoForm; // 商品规格 let spggData = this.$refs.goodsspecifications.speData; // 商品售价,上面已经获取, let spsjData = {}; if( spsjData2.pamTableList && spsjData2.pamTableList.length > 0 ) { this.goodsAllData['specs_group'] = []; this.goodsAllData['specs'] = spggData; spsjData2.pamTableList.forEach((item,index)=> { this.goodsAllData['specs_group'].push(item[0]); }); }else { spsjData = spsjData1[0]; } // 商品详情 数据 let spxqData = this.$refs.goodsdetailsimg.goodsDeForm; // 售后服务 数据 let ssffData = this.$refs.goodsaftersale.goodsAfterSaleForm; Object.assign( this.goodsAllData, spxxData, spsjData, spxqData, ssffData); // 经营类目,服务标签,需要单独处理数据格式 this.goodsAllData.category_id = spxxData.categoryList.slice(-1)[0] ? spxxData.categoryList.slice(-1)[0] : ''; if(this.goodsAllData.stags) { this.goodsAllData.stags = this.goodsAllData.stags.toString(); } // let msg = res.data.Apply.content; // this.$router.push({ // name: 'reviewFail', // params: { msg: msg } // }); // if(this.$route.params.msg) { // this.msg = this.$route.params.msg; // } // freight let routerParam = { fuck: "hxz" }; // 商品id 不为 0 是修改 if( this.goodsAllData.goods_id ) { updateGoodsNew(this.goodsAllData).then(res=> { if( res.code === 1 ) { this.$message({type: 'success', message:'编辑成功'}); this.initAllGoodsInfo(); this.$emit("closeEditDialog"); } if(res.code === 0) { let msg = res.message ? res.message : '编辑失败' this.$message({type: 'error', message: msg}); } }); }else { // 商品id 为 0 是新增 addGoods( this.goodsAllData ).then( res=> { if( res.code === 1 ) { this.$message({type: 'success', message:'新增成功'}); this.initAllGoodsInfo(); //this.$router.push({ name: 'system/goodsimport/goodsgement',params: routerParam }); //management //this.$router.push({ path: '/system/goodsimport/management' }); this.$router.push({ path: '/system/goods/management' }); } if(res.code === 0) { let msg = res.message ? res.message : '新增失败' this.$message({type: 'error', message: msg}); } }); } }, /*-----------------------*/ // 初始化 商品所有数据 initAllGoodsInfo() { // 初始化 商品信息 数据 this.$refs.goodsInfo.initInfo(); // 初始化 商品规格 数据 this.$refs.goodsspecifications.initInfo(); // 初始化 商品售价 数据 this.$refs.goodsparameter.initInfo(); // 初始化 商品详情 数据 this.$refs.goodsdetailsimg.initInfo(); // 初始化 商品售后 数据 this.$refs.goodsaftersale.initInfo(); }, /* 添加商品详细 */ /* 设置楼层导航事件驱动方法* @params Number index 楼层下标 */ setFloorNavMountClick(index) { let _this = this _this.isFIActive = index; clearInterval(_this.TIMER); // 可以通过 floor-cont的父元素,高度减去上下两个div的高度,来准确计算出来了,需要wtach监听,暂时用初步高来计算,一般问题不大 let floor_cont = document.getElementsByClassName('floor-cont')[0]; let floor_item = document.getElementsByClassName('floor-item'), // 每次点击,对应dom需要滚动的高度 floor_offsetTop = floor_item[index].offsetTop - floor_item[0].offsetTop, window_scrollTop = _this.$refs.scrollview.scrollTop, // 基本滚动动画配置 timer = { step: 45, times: 20, FLOOR_OFFSETTOP: 0 }; // floor_cont 可是窗口的 高 let hxz = 0; let resList = []; let list = []; for(let i = 0; i < floor_item.length; i++) { list.push(Number(floor_item[i].offsetHeight)); } resList = list.slice(index) for(let j = 0; j < resList.length; j++) { hxz += resList[j] } if( hxz > floor_cont.offsetHeight) { timer.FLOOR_OFFSETTOP = floor_offsetTop; }else { timer.FLOOR_OFFSETTOP = floor_cont.scrollHeight - floor_cont.offsetHeight } if (window_scrollTop > floor_offsetTop) { _this.setFloorScrollArrowUp(timer) } else if (window_scrollTop === floor_offsetTop) { return false } else { _this.setFloorScrollArrowDown(timer) } }, /* 设置楼层向上滚动* @params Object timer 定时器配置 */ setFloorScrollArrowUp(timer) { let _this = this clearInterval(_this.TIMER) _this.TIMER = setInterval(() => { const window_scrollTop = _this.$refs.scrollview.scrollTop if (window_scrollTop <= timer.FLOOR_OFFSETTOP) { _this.$refs.scrollview.scrollTop = timer.FLOOR_OFFSETTOP clearInterval(_this.TIMER) } else { _this.$refs.scrollview.scrollTop = window_scrollTop - timer.step } }, timer.times) }, /* 设置楼层向下滚动@params Object timer 定时器配置 */ setFloorScrollArrowDown(timer) { let _this = this clearInterval(_this.TIMER) _this.TIMER = setInterval(() => { const window_scrollTop = _this.$refs.scrollview.scrollTop if (window_scrollTop >= timer.FLOOR_OFFSETTOP) { _this.$refs.scrollview.scrollTop = timer.FLOOR_OFFSETTOP clearInterval(_this.TIMER) } else { _this.$refs.scrollview.scrollTop = window_scrollTop + timer.step } }, timer.times) }, } // methods end } </script> <style scoped lang="scss" type="text/css"> .goods-all { height: 100%; padding: 20px; } .goods-all .good-all-type { height: 100%; overflow: auto; } /deep/.goods-all .el-card .el-card__body{ height:100%; overflow: auto; } p { margin: 0; padding: 0; } /* el-card title hxz 样式统一 */ .card-header-title { display: flex; flex-direction: row; justify-content: start; align-items: center; font-size: 16px; color: #333; font-weight: 400; height: 24px; } .blue-block-goods { width: 5px; height: 24px; background: #3A84FF; margin: 0 7px 0 0; border-radius: 2px; } /* el-card title hxz 样式统一 end */ .goods-type-tip { width: 100%; background: #F1F7FD; border: 1px solid #3A84FF; font-size: 14px; font-weight: 400; color: #3A84FF; line-height: 1em; padding: 14px 15px; } .goods-type-options { margin: 25px 0; } /*------------ 联级面板样式重置 start ------------*/ /deep/.el-cascader-panel.is-bordered { border: none; } /deep/.el-cascader-menu { min-width: 280px; border: none; box-shadow: 0px 4px 9px 1px rgba(51, 51, 51, 0.09); border-radius: 2px; overflow: hidden; } /deep/.el-cascader-menu__wrap { width: 280px; height: 500px; overflow: auto; margin: 5px 0!important; } /* 很重要,不要问我为什么 */ /deep/.el-scrollbar:hover>.el-scrollbar__bar, /deep/.el-scrollbar:active>.el-scrollbar__bar, /deep/.el-scrollbar:focus>.el-scrollbar__bar { opacity: 0; } /*------------ 联级面板样式重置 end ---------------*/ .next-step { padding: 10px 25px; margin: 0 auto; display: block; } /* 电梯效果 样式 */ .floor-nav { width: 100%; } .floor-nav .nav-list { padding: 0; margin:0; display: flex; justify-content: start; flex-direction: row; border-bottom:1px solid #eee; } .floor-nav .nav-list .nav-list-item { font-size: 16px; font-weight: 400; color: #333333; padding: 0 25px 15px; list-style: none; vertical-align: middle; align-self: center; border-bottom: 2px solid #fff; cursor: pointer; } .floor-nav .nav-list .floor-item-active, .floor-nav .nav-list .nav-list-item:hover { color: #3A84FF; font-weight: bold; border-bottom: 2px solid #3A84FF; } .floor-item-box-title { background: #F1F1F6; height: 45px; } .blue-block-goods-title { margin: 0 20px 0 0; } .good-details-body { height: 100%; } /deep/.good-details-body .el-card__body { height: 100%; padding: 15px 20px 0px 20px; overflow: hidden; } .floor-cont{ height: calc(100% - 98px); overflow: auto; } .floor-item { padding: 0; margin: 20px; color: #333; box-shadow: 0 2px 12px 0 rgba(0, 0, 0 ,0.1); } .submit-type-con { width: 236px; margin: 0 auto 20px; } .submit-cont { width: calc(100% + 40px); padding: 12px 0 8px; margin-left: -20px; display: flex; flex-direction: row; justify-content: center; align-items: center; /*align-content: center;*/ box-shadow: 0px -8px 9px 1px rgba(51, 51, 51, 0.06); } </style>