12.31开源admin代码更新

This commit is contained in:
hejinfu1026
2021-12-31 15:58:40 +08:00
parent 21e0d0e136
commit 0616cde752
545 changed files with 9743 additions and 139371 deletions

View File

@@ -23,7 +23,7 @@
</el-form-item>
</el-col>
<el-col v-bind="grid2">
<el-form-item label="商品关键字:">
<el-form-item label="商品关键字:" prop="keyword">
<el-input v-model="formValidate.keyword" placeholder="请输入商品关键字" :disabled="isDisabled"/>
</el-form-item>
</el-col>
@@ -33,7 +33,7 @@
</el-form-item>
</el-col>
<el-col v-bind="grid2">
<el-form-item label="商品简介:">
<el-form-item label="商品简介:" prop="storeInfo">
<el-input v-model="formValidate.storeInfo" type="textarea" maxlength="250" :rows="3" placeholder="请输入商品简介" :disabled="isDisabled"/>
</el-form-item>
</el-col>
@@ -61,7 +61,7 @@
@dragend="handleDragEnd($event, item)"
>
<img :src="item">
<i v-if="!isDisabled" class="el-icon-error btndel" @click="handleRemove(index)" />
<i v-if="!isDisabled" class="el-icon-error btndel" @click="handleRemove(index)"/>
</div>
<div v-if="formValidate.sliderImages.length<10 && !isDisabled" class="upLoadPicBox" @click="modalPicTap('2')">
<div class="upLoad">
@@ -71,10 +71,9 @@
</div>
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :xs="18" :sm="18" :md="18" :lg="12" :xl="12">
<el-form-item label="运费模板:" prop="tempId">
<div class="acea-row">
<el-select v-model="formValidate.tempId" placeholder="请选择" class="selWidthd mr20" :disabled="isDisabled">
<el-select v-model="formValidate.tempId" placeholder="请选择" class="mr20" :disabled="isDisabled" style="width:100%;">
<el-option
v-for="item in shippingList"
:key="item.id"
@@ -82,10 +81,11 @@
:value="item.id"
/>
</el-select>
<el-button v-show="!isDisabled" class="mr15" @click="addTem">添加运费模板</el-button>
</div>
</el-form-item>
</el-col>
<el-col :xs="6" :sm="6" :md="6" :lg="12" :xl="12">
<el-button v-show="!isDisabled" class="mr15" @click="addTem">运费模板</el-button>
</el-col>
<el-col :span="24">
<el-form-item label="商品规格:" props="specType">
<el-radio-group v-model="formValidate.specType" @change="onChangeSpec(formValidate.specType)" :disabled="isDisabled">
@@ -163,7 +163,7 @@
</el-col>
<!-- 批量设置-->
<el-col v-if="formValidate.attr.length>0 && formValidate.specType && !isDisabled" :span="24" class="noForm">
<el-form-item label="批量设置:" class="labeltop">
<el-form-item label="批量设置:">
<el-table :data="oneFormBatch" border class="tabNumWidth" size="mini">
<el-table-column align="center" label="图片" min-width="80">
<template slot-scope="scope">
@@ -177,7 +177,7 @@
</el-table-column>
<el-table-column v-for="(item,iii) in attrValue" :key="iii" :label="formThead[iii].title" align="center" min-width="120">
<template slot-scope="scope">
<el-input v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" :min="0" class="priceBox" />
<el-input v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" :min="0" class="priceBox" @keyup.native='keyupEvent($event,oneFormBatch,scope.$index,iii, 1)' />
</template>
</el-table-column>
<template v-if="formValidate.isSub">
@@ -216,7 +216,7 @@
</el-table-column>
<el-table-column v-for="(item,iii) in attrValue" :key="iii" :label="formThead[iii].title" align="center" min-width="120">
<template slot-scope="scope">
<el-input :disabled="isDisabled" v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" :min="0" class="priceBox" />
<el-input :disabled="isDisabled" v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" :min="0" class="priceBox" @keyup.native='keyupEvent($event,oneFormBatch,scope.$index,iii, 2)' />
</template>
</el-table-column>
<template v-if="formValidate.isSub">
@@ -233,6 +233,10 @@
</template>
</el-table>
</el-form-item>
<!-- <div>manyTabDate:{{manyTabDate}}</div> -->
<el-form-item label="全部sku" v-if="$route.params.id && showAll">
<el-button type="default" @click="showAllSku()" :disabled="isDisabled">展示</el-button>
</el-form-item>
<!-- 多规格表格-->
<el-form-item v-if="formValidate.attr.length>0 && formValidate.specType" label="商品属性:" class="labeltop" :class="isDisabled?'disLabel':'disLabelmoren'">
<el-table :data="ManyAttrValue" border class="tabNumWidth" size="mini">
@@ -255,7 +259,8 @@
</el-table-column>
<el-table-column v-for="(item,iii) in attrValue" :key="iii" :label="formThead[iii].title" align="center" min-width="120">
<template slot-scope="scope">
<el-input :disabled="isDisabled" v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" class="priceBox" />
<!-- <span>scope.row:{{scope.row}}</span>-->
<el-input :disabled="isDisabled" v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" class="priceBox" @keyup.native='keyupEvent($event,oneFormBatch,scope.$index,iii, 3)' />
</template>
</el-table-column>
<el-table-column align="center" label="一级返佣(元)" min-width="120" v-if="formValidate.isSub">
@@ -281,7 +286,7 @@
<el-row v-show="currentTab === 1 && !isDisabled">
<el-col :span="24">
<el-form-item label="商品详情:">
<ueditor-from v-model="formValidate.content" :content="formValidate.content" />
<Tinymce v-model="formValidate.content"></Tinymce>
</el-form-item>
</el-col>
</el-row>
@@ -297,17 +302,17 @@
<el-col :span="24">
<el-col v-bind="grid">
<el-form-item label="排序:">
<el-input-number v-model="formValidate.sort" :max="9999" placeholder="请输入排序" :disabled="isDisabled" />
<el-input-number v-model="formValidate.sort" :min="0" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="积分:">
<el-input-number v-model="formValidate.giveIntegral" placeholder="请输入排序" :disabled="isDisabled" />
<el-input-number v-model="formValidate.giveIntegral" :min="0" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="虚拟销量:">
<el-input-number v-model="formValidate.ficti" placeholder="请输入排序" :disabled="isDisabled" />
<el-input-number v-model="formValidate.ficti" :min="0" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
</el-col>
@@ -340,7 +345,6 @@
<el-form-item label="优惠券:" class="proCoupon">
<div class="acea-row">
<el-tag
v-if="!isDisabled"
v-for="(tag, index) in formValidate.coupons"
:key="index"
class="mr10 mb10"
@@ -350,14 +354,14 @@
>
{{ tag.name }}
</el-tag>
<span v-if="isDisabled"></span>
<el-button v-if="!isDisabled" class="mr15" size="mini" @click="addCoupon">选择优惠券</el-button>
<!-- <span v-if="formValidate.couponIds == null"></span> -->
<el-button v-if="!isDisabled" class="mr15" @click="addCoupon">选择优惠券</el-button>
</div>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button v-show="currentTab>0" type="primary" class="submission" @click="handleSubmitUp">上一步</el-button>
<el-button v-show="currentTab>0" class="submission priamry_border" @click="handleSubmitUp">上一步</el-button>
<el-button v-show="currentTab<2" type="primary" class="submission" @click="handleSubmitNest('formValidate')">下一步</el-button>
<el-button v-show="(currentTab===2 || $route.params.id) && !isDisabled" type="primary" class="submission" @click="handleSubmit('formValidate')">提交</el-button>
</el-form-item>
@@ -368,14 +372,19 @@
</template>
<script>
import Tinymce from '@/components/Tinymce/index'
import { templateListApi, productCreateApi, categoryApi, productDetailApi, productUpdateApi } from '@/api/store'
import { marketingSendApi} from '@/api/marketing';
import { shippingTemplatesList } from '@/api/logistics'
import { goodDesignList } from "@/api/systemGroup";
import { clearTreeData } from '@/utils/ZBKJIutil'
import CreatTemplates from '@/views/systemSetting/logistics/shippingTemplates/creatTemplates'
import Templates from "../../appSetting/wxAccount/wxTemplate/index";
import {Debounce} from '@/utils/validate'
const defaultObj = {
image: '',
sliderImages: [],
videoLink:'',
sliderImage: '',
storeName: '',
storeInfo: '',
@@ -436,10 +445,9 @@
title: '体积(m³)'
}
}
const proOptions = [{ name: '是否热卖', value: 'isHot' }, { name: '优品推荐', value: 'isGood' }, { name: '促销单品', value: 'isBenefit' }, { name: '是否精品', value: 'isBest' }, { name: '是否新品', value: 'isNew' }]
export default {
name: 'ProductProductAdd',
components: {Templates, CreatTemplates },
components: {Templates, CreatTemplates,Tinymce },
data() {
return {
isDisabled: this.$route.params.isDisabled==='1'?true:false,
@@ -452,7 +460,7 @@
emitPath: false
},
checkboxGroup: [],
recommend: proOptions,
recommend: [],
tabs: [],
fullscreenLoading: false,
props: { multiple: true },
@@ -475,7 +483,7 @@
manyTabTit: {},
manyTabDate: {},
grid2: {
xl: 10,
xl: 12,
lg: 12,
md: 12,
sm: 24,
@@ -534,7 +542,9 @@
},
tempRoute: {},
keyNum: 0,
isAttr: false
isAttr: false,
showAll:false,
videoLink: "",
}
},
computed: {
@@ -552,7 +562,7 @@
watch: {
'formValidate.attr': {
handler: function(val) {
if (this.formValidate.specType && this.isAttr) this.watCh(val)
if (this.formValidate.specType && this.isAttr) this.watCh(val) //重要!!!
},
immediate: false,
deep: true
@@ -572,8 +582,40 @@
}
this.getCategorySelect()
this.getShippingList()
this.getGoodsType()
},
methods: {
keyupEvent(e,array,index,row,num){
e.target.value=e.target.value.replace(/[^\d.]/g, '');
e.target.value=e.target.value.replace(/\.{2,}/g, '.');
e.target.value=e.target.value.replace(/^\./g, '0.');
e.target.value=e.target.value.replace(/^\d*\.\d*\./g, e.target.value.substring(0,e.target.value.length-1));
e.target.value=e.target.value.replace(/^0[^\.]+/g, '0')
e.target.value=e.target.value.replace(/^(\d+)\.(\d\d).*$/, '$1.$2')
switch (num) {
case 1:
if(row == 'stock'){
this.oneFormBatch[index][row]=parseInt(e.target.value)
}else{
this.oneFormBatch[index][row]=e.target.value
}
break;
case 2:
if(row == 'stock'){
this.OneattrValue[index][row]=parseInt(e.target.value)
}else{
this.OneattrValue[index][row]=e.target.value
}
break;
default:
if(row == 'stock'){
this.ManyAttrValue[index][row]=parseInt(e.target.value)
}else{
this.ManyAttrValue[index][row]=e.target.value
}
break;
}
},
handleCloseCoupon(tag) {
this.isAttr = true
this.formValidate.coupons.splice(this.formValidate.coupons.indexOf(tag), 1)
@@ -605,15 +647,17 @@
const tmp = {}
const tmpTab = {}
this.formValidate.attr.forEach((o, i) => {
tmp['value' + i] = { title: o.attrName }
tmpTab['value' + i] = ''
})
this.ManyAttrValue = this.attrFormat(val)
// tmp['value' + i] = { title: o.attrName }
// tmpTab['value' + i] = ''
tmp[o.attrName] = { title: o.attrName };
tmpTab[o.attrName] = '';
});
this.ManyAttrValue = this.attrFormat(val);
this.ManyAttrValue.forEach((val, index) => {
const key = Object.values(val.attrValue).sort().join('/')
if (this.attrInfo[key]) this.ManyAttrValue[index] = this.attrInfo[key]
})
this.attrInfo = {}
this.attrInfo = [];
this.ManyAttrValue.forEach((val) => {
this.attrInfo[Object.values(val.attrValue).sort().join('/')] = val
})
@@ -630,6 +674,7 @@
arr.forEach((v, i) => {
if (i === 0) data = arr[i]['attrValue']
const tmp = []
if(!data) return;
data.forEach(function(vv) {
arr[i + 1] && arr[i + 1]['attrValue'] && arr[i + 1]['attrValue'].forEach(g => {
const rep2 = (i !== 0 ? '' : arr[i]['attrName'] + '_') + vv + '$&' + arr[i + 1]['attrName'] + '_' + g
@@ -648,13 +693,13 @@
brokerage_two: 0
}
rep2.split('$&').forEach((h, k) => {
const rep3 = h.split('_')
const rep3 = h.split('_');
if (!rep4['attrValue']) rep4['attrValue'] = {}
rep4['attrValue'][rep3[0]] = rep3.length > 1 ? rep3[1] : ''
})
Object.values(rep4.attrValue).forEach((v, i) => {
rep4['value' + i] = v
})
for (let attrValueKey in rep4.attrValue) {
rep4[attrValueKey] = rep4.attrValue[attrValueKey];
}
res.push(rep4)
}
})
@@ -679,9 +724,12 @@
brokerage_two: 0,
attrValue: { [v['attrName']]: vv }
}
Object.values(res[kk].attrValue).forEach((v, i) => {
res[kk]['value' + i] = v
})
// Object.values(res[kk].attrValue).forEach((v, i) => {
// res[kk]['value' + i] = v
// })
for (let attrValueKey in res[kk].attrValue) {
res[kk][attrValueKey] = res[kk].attrValue[attrValueKey];
}
})
})
data.push(dataArr.join('$&'))
@@ -722,13 +770,19 @@
})
})
}
this.formValidate.attr = data
})
this.formValidate.attr = data;
});
},
// 商品分类;
getCategorySelect() {
categoryApi({ status: -1, type: 1 }).then(res => {
this.merCateList = this.filerMerCateList(res)
let newArr = [];
res.forEach((value,index) => {
newArr[index] = value;
if(value.child) newArr[index].child = value.child.filter(item => item.status === true)
}) //过滤商品分类设置为隐藏的子分类不出现在树形列表里
this.merCateList = this.filerMerCateList(newArr)
})
},
filerMerCateList(treeData) {
@@ -860,17 +914,27 @@
/* eslint-disable */
hash[next] ? '' : hash[next] = true && item.push(next);
return item
}, [])
}, []);
this.formValidate.attr[idx].inputVisible = false
} else {
this.$message.warning('请添加属性');
}
},
//点击展示所有多规格属性
showAllSku(){
if(this.isAttr == false){
this.isAttr = true;
if (this.formValidate.specType && this.isAttr) this.watCh(this.formValidate.attr) //重要!!!
}else if(this.isAttr == true){
this.isAttr = false;
this.getInfo();
}
},
// 详情
getInfo () {
this.fullscreenLoading = true
productDetailApi(this.$route.params.id).then(async res => {
this.isAttr = true;
// this.isAttr = true;
let info = res
this.formValidate = {
image: this.$selfUtil.setDomain(info.image),
@@ -891,6 +955,7 @@
isBest: info.isBest,
tempId: info.tempId,
attr: info.attr,
attrValue: info.attrValue,
selectRule: info.selectRule,
isSub: info.isSub,
content: this.$selfUtil.replaceImgSrcHttps(info.content),
@@ -902,6 +967,24 @@
couponIds: info.couponIds,
activity: info.activityStr ? info.activityStr.split(',') : ['默认','秒杀','砍价','拼团']
}
marketingSendApi({type:3}).then(res=>{
if(this.formValidate.couponIds !== null){
let ids = this.formValidate.couponIds.toString();
let arr = res.list;
let obj = {};
for (let i in arr) {
obj[arr[i].id] = arr[i];
}
let strArr = ids.split(',');
let newArr = [];
for (let item of strArr) {
if (obj[item]) {
newArr.push(obj[item]);
}
}
this.$set(this.formValidate,'coupons',newArr); //在编辑回显时让返回数据中的优惠券id通过接口匹配显示,
}
})
let imgs = JSON.parse(info.sliderImage)
let imgss = []
Object.keys(imgs).map(i => {
@@ -921,35 +1004,55 @@
attrValue: item.attrValues.split(',')
}
})
this.ManyAttrValue = info.attrValues;
this.ManyAttrValue = info.attrValue;
this.ManyAttrValue.forEach((val) => {
val.image = this.$selfUtil.setDomain(val.image)
this.attrInfo[Object.values(val.attrValue).sort().join('/')] = val
val.image = this.$selfUtil.setDomain(val.image);
val.attrValue = JSON.parse(val.attrValue);
this.attrInfo[Object.values(val.attrValue).sort().join('/')] = val;
})
/***多规格商品如果被删除过sku优先展示api返回的数据,否则会有没有删除的错觉***/
let manyAttr = this.attrFormat(this.formValidate.attr)
if(manyAttr.length !== this.ManyAttrValue.length){
this.$set(this,'showAll',true)
this.isAttr = false;
}else{
this.isAttr = true;
}
/*******/
const tmp = {}
const tmpTab = {}
this.formValidate.attr.forEach((o, i) => {
tmp['value' + i] = { title: o.attrName }
tmpTab['value' + i] = ''
// tmp['value' + i] = { title: o.attrName }
// tmpTab['value' + i] = ''
tmp[o.attrName] = { title: o.attrName };
tmpTab[o.attrName] = '';
})
// 此处手动实现后台原本value0 value1的逻辑
this.formValidate.attrValue.forEach(item => {
for (let attrValueKey in item.attrValue) {
item[attrValueKey] = item.attrValue[attrValueKey];
}
});
this.manyTabTit = tmp
this.manyTabDate = tmpTab
this.formThead = Object.assign({}, this.formThead, tmp)
}else{
this.OneattrValue = info.attrValue
this.formValidate.attr = []
// this.formValidate.attr = [] //单规格商品规格设置为空
}
this.fullscreenLoading = false
}).catch(res => {
this.fullscreenLoading = false
this.$message.error(res.message);
})
});
},
handleRemove (i) {
this.formValidate.sliderImages.splice(i, 1)
},
// 点击商品图
modalPicTap (tit, num, i) {
modalPicTap (tit, num, i,status) {
const _this = this;
if(_this.isDisabled) return;
this.$modalUpload(function(img) {
@@ -993,18 +1096,31 @@
})
},
// 提交
handleSubmit (name) {
handleSubmit:Debounce(function(name) {
this.onChangeGroup()
if( this.formValidate.specType && this.formValidate.attr.length < 1 ) return this.$message.warning("请填写多规格属性!");
this.formValidate.cateId = this.formValidate.cateIds.join(',')
this.formValidate.sliderImage = JSON.stringify(this.formValidate.sliderImages)
if(this.formValidate.specType){
this.formValidate.attrValue=this.ManyAttrValue
for (var i = 0; i < this.formValidate.attr.length; i++) {
this.formValidate.attr[i].attrValues = this.formValidate.attr[i].attrValue.join(',')
this.formValidate.attrValue=this.ManyAttrValue;
this.formValidate.attr = this.formValidate.attr.map((item) =>{
return {
attrName:item.attrName,
id:item.id,
attrValues:item.attrValue.join(','),
}
})
for (var i = 0; i < this.formValidate.attrValue.length; i++) {
this.$set(this.formValidate.attrValue[i],'id',0);
this.$set(this.formValidate.attrValue[i],'productId',0);
this.$set(this.formValidate.attrValue[i],'attrValue',JSON.stringify(this.formValidate.attrValue[i].attrValue)); //
delete this.formValidate.attrValue[i].value0
}
}else{
this.formValidate.attr = []
this.formValidate.attr = [{attrName:'规格',attrValues:'默认',id: this.$route.params.id? this.formValidate.attr[0].id : 0}]
this.OneattrValue.map(item => {
this.$set(item, 'attrValue', JSON.stringify({'规格':'默认'}))
})
this.formValidate.attrValue=this.OneattrValue
}
this.$refs[name].validate((valid) => {
@@ -1033,8 +1149,8 @@
this.$message.warning("请填写完整商品信息!");
}
}
})
},
});
}),
// 表单验证
validate (prop, status, error) {
if (status === false) {
@@ -1076,7 +1192,47 @@
newItems.splice(dst, 0, ...newItems.splice(src, 1))
this.formValidate.activity = newItems;
}
}
},
getGoodsType(){
/** 让商品推荐列表的name属性与页面设置tab的name匹配**/
goodDesignList({gid:70}).then((response)=>{
let list = response.list;
let arr = [],arr1 = [];
const listArr = [{ name: '是否热卖', value: 'isGood' }];
let typeLists = [
{ name: '', value: 'isHot',type:'2' }, //热门榜单
{ name: '', value: 'isBenefit' ,type:'4'}, //促销单品
{ name: '', value: 'isBest',type:'1' }, //精品推荐
{ name: '', value: 'isNew',type:'3' }]; //首发新品
list.forEach((item)=>{
let obj = {};
obj.value = JSON.parse(item.value);
obj.id = item.id;
obj.gid = item.gid;
obj.status = item.status;
arr.push(obj);
})
arr.forEach((item1)=>{
let obj1 = {};
obj1.name = item1.value.fields[1].value;
obj1.status = item1.status;
obj1.type = item1.value.fields[3].value;
arr1.push(obj1);
})
typeLists.forEach((item)=>{
arr1.forEach((item1)=>{
if(item.type == item1.type){
listArr.push({
name:item1.name,
value:item.value,
type:item.type
})
}
})
})
this.recommend = listArr
})
},
}
}
</script>
@@ -1091,7 +1247,10 @@
margin-left: 120px !important;
}
}
.priamry_border{
border: 1px solid #1890FF;
color: #1890FF;
}
.color-item{
height: 30px;
line-height: 30px;
@@ -1180,6 +1339,10 @@
width: 100%;
height: 100%;
}
video{
width: 100%;
height: 100%;
}
}
.btndel{
position: absolute;
@@ -1196,4 +1359,35 @@
width: auto !important;
}
}
.iview-video-style {
width: 300px;
height: 180px;
border-radius: 10px;
background-color: #707070;
margin: 0 120px 20px;
position: relative;
overflow: hidden;
}
.iview-video-style .iconv {
color: #fff;
line-height: 180px;
width: 50px;
height: 50px;
display: inherit;
font-size: 26px;
position: absolute;
top: -74px;
left: 50%;
margin-left: -25px;
}
.iview-video-style .mark {
position: absolute;
width: 100%;
height: 30px;
top: 0;
background-color: rgba(0, 0, 0, 0.5);
text-align: center;
}
</style>

View File

@@ -1,34 +1,35 @@
<template>
<div class="divBox">
<div class="divBox relative">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-tabs v-model="tableFrom.type" @tab-click="seachList">
<el-tabs v-model="tableFrom.type" @tab-click="seachList" v-if="checkPermi(['admin:product:tabs:headers'])">
<el-tab-pane :label="item.name +'('+item.count +')' " :name="item.type.toString()" v-for="(item,index) in headeNum" :key="index"/>
</el-tabs>
<div class="container">
<div class="container mt-1">
<el-form inline size="small">
<el-form-item label="商品分类:">
<el-cascader v-model="tableFrom.cateId" :options="merCateList" :props="props" clearable class="selWidth mr20" @change="seachList" size="small"/>
</el-form-item>
<el-form-item label="商品搜索:">
<el-input v-model="tableFrom.keywords" placeholder="请输入商品名称关键字商品ID" class="selWidth" size="small" clearable>
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small" v-hasPermi="['admin:product:list']" />
</el-input>
</el-form-item>
</el-form>
</div>
<router-link :to=" { path:'/store/list/creatProduct' } ">
<el-button size="small" type="primary" class="mr10">添加商品</el-button>
<el-button size="small" type="primary" class="mr10" v-hasPermi="['admin:product:save']">添加商品</el-button>
</router-link>
<el-button size="small" type="success" class="mr10" @click="onCopy">商品采集</el-button>
<el-button size="small" @click="exports">导出</el-button>
<el-button size="small" type="success" class="mr10" @click="onCopy" v-hasPermi="['admin:product:save']">商品采集</el-button>
<el-button size="small" icon="el-icon-upload2" @click="exports" v-hasPermi="['admin:export:excel:product']">导出</el-button>
</div>
<el-table
v-loading="listLoading"
:data="tableData.data"
style="width: 100%"
size="mini"
highlight-current-row
:highlight-current-row="true"
:header-cell-style=" {fontWeight:'bold'}"
>
<el-table-column type="expand">
<template slot-scope="props">
@@ -67,36 +68,52 @@
</div>
</template>
</el-table-column>
<el-table-column
prop="storeName"
label="商品名称"
min-width="200"
/>
<el-table-column label="商品名称"
prop="storeName"
min-width="300"
:show-overflow-tooltip="true">
</el-table-column>
<el-table-column
prop="price"
label="商品售价"
min-width="90"
align="center"
/>
<el-table-column
prop="sales"
label="销量"
min-width="90"
align="center"
/>
<el-table-column
prop="stock"
label="库存"
min-width="90"
align="center"
/>
<el-table-column
prop="sort"
label="排序"
min-width="70"
align="center"
/>
<el-table-column
label="状态"
min-width="150"
label="添加时间"
min-width="120"
align="center"
>
<template slot-scope="scope">
<span>{{scope.row.addTime | formatDate}}</span>
</template>
</el-table-column>
<el-table-column
label="状态"
min-width="80"
fixed="right"
>
<template slot-scope="scope"
v-if="checkPermi(['admin:product:up','admin:product:down'])">
<el-switch
:disabled="Number(tableFrom.type) > 2"
v-model="scope.row.isShow"
@@ -108,24 +125,16 @@
/>
</template>
</el-table-column>
<el-table-column
label="操作时间"
min-width="120"
>
<template slot-scope="scope">
<span>{{scope.row.addTime | formatDate}}</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="150" fixed="right" align="center">
<template slot-scope="scope">
<router-link :to="{path: '/store/list/creatProduct/' + scope.row.id + '/1'}">
<el-button type="text" size="small" class="mr10">详情</el-button>
<el-button type="text" size="small" class="mr10" v-hasPermi="['admin:product:info']">详情</el-button>
</router-link>
<router-link :to="{path: '/store/list/creatProduct/' + scope.row.id}">
<el-button type="text" size="small" class="mr10" v-if="tableFrom.type !== '5' && tableFrom.type !== '1'">编辑</el-button>
<el-button type="text" size="small" class="mr10" v-if="tableFrom.type !== '5' && tableFrom.type !== '1'" v-hasPermi="['admin:product:update']">编辑</el-button>
</router-link>
<el-button v-if="tableFrom.type === '5'" type="text" size="small" @click="handleRestore(scope.row.id, scope.$index)">恢复商品</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, tableFrom.type)">{{ tableFrom.type === '5' ? '删除' : '加入回收站' }}</el-button>
<el-button v-if="tableFrom.type === '5'" type="text" size="small" @click="handleRestore(scope.row.id, scope.$index)" v-hasPermi="['admin:product:restore']">恢复商品</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, tableFrom.type)" v-hasPermi="['admin:product:delete']">{{ tableFrom.type === '5' ? '删除' : '加入回收站' }}</el-button>
</template>
</el-table-column>
</el-table>
@@ -141,7 +150,6 @@
/>
</div>
</el-card>
<el-dialog
title="复制淘宝、天猫、京东、苏宁"
:visible.sync="dialogVisible"
@@ -158,6 +166,7 @@
import { productLstApi, productDeleteApi, categoryApi, putOnShellApi, offShellApi, productHeadersApi, productExportApi, restoreApi, productExcelApi } from '@/api/store'
import { getToken } from '@/utils/auth'
import taoBao from './taoBao'
import { checkPermi } from "@/utils/permission"; // 权限判断函数
export default {
name: 'ProductList',
components: { taoBao },
@@ -186,15 +195,17 @@ export default {
categoryList: [],
merCateList: [],
objectUrl: process.env.VUE_APP_BASE_API,
dialogVisible: false
dialogVisible: false,
}
},
mounted() {
this.goodHeade()
this.getList()
this.getCategorySelect()
this.checkedCities = this.$cache.local.has('goods_stroge') ? this.$cache.local.getJSON('goods_stroge') : this.checkedCities;
},
methods: {
checkPermi,
handleRestore(id) {
this.$modalSure("恢复商品").then(() => {
restoreApi(id)
@@ -241,7 +252,6 @@ export default {
this.merCateList = res
}).catch(res => {
this.$message.error(res.message)
this.$message.error(res.message)
})
},
// 列表
@@ -290,12 +300,17 @@ export default {
}).catch(()=>{
row.isShow = !row.isShow
})
}
},
}
}
</script>
<style scoped lang="scss">
.el-table__body {
width: 100%;
table-layout: fixed !important;
}
.taoBaoModal{
// z-index: 3333 !important;
}
@@ -315,4 +330,7 @@ export default {
.seachTiele{
line-height: 30px;
}
.relative{
position: relative;
}
</style>

View File

@@ -12,8 +12,8 @@
</el-form>
</div>
<div class="acea-row">
<el-button size="small" type="primary" @click="add">添加商品规格</el-button>
<el-button size="small" @click="handleDeleteAll">批量删除</el-button>
<el-button size="small" type="primary" @click="add" v-hasPermi="['admin:product:rule:save']">添加商品规格</el-button>
<el-button size="small" @click="handleDeleteAll" v-hasPermi="['admin:product:rule:delete']">批量删除</el-button>
</div>
</div>
<el-table
@@ -57,8 +57,8 @@
</el-table-column>
<el-table-column label="操作" min-width="120" align="center">
<template slot-scope="scope">
<el-button type="text" size="small" @click="onEdit(scope.row)" class="mr10">编辑</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
<el-button type="text" size="small" @click="onEdit(scope.row)" class="mr10" v-hasPermi="['admin:product:rule:update','admin:product:rule:info']">编辑</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)" v-hasPermi="['admin:product:rule:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -76,7 +76,6 @@
</el-card>
</div>
</template>
<script>
import { templateListApi, attrDeleteApi } from '@/api/store'
export default {

View File

@@ -62,6 +62,7 @@
<script>
import { replyCreatApi, replyEditApi, replyInfoApi } from '@/api/store'
import {Debounce} from '@/utils/validate'
const defaultObj= {
avatar: '',
comment: '',
@@ -155,7 +156,7 @@
handleRemove (i) {
this.pics.splice(i, 1)
},
submitForm(formName) {
submitForm:Debounce(function(formName) {
this.formValidate.pics = this.pics.length>0 ? JSON.stringify(this.pics) : ''
this.$refs[formName].validate((valid) => {
if (valid) {
@@ -174,7 +175,7 @@
return false;
}
});
},
}),
resetForm(formName) {
this.$refs[formName].resetFields()
this.pics=[]

View File

@@ -26,19 +26,9 @@
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
</el-input>
</el-form-item>
<!--<el-select v-model="uids" class="selWidth" reserve-keyword multiple remote filterable-->
<!--:remote-method="remoteMethod" :loading="loading" placeholder="请输入用户名称" clearable @change="seachList">-->
<!--<el-option-->
<!--v-for="item in options"-->
<!--:key="item.uid"-->
<!--:label="item.nickname"-->
<!--:value="item.uid">-->
<!--</el-option>-->
<!--</el-select>-->
</el-form>
</div>
<el-button size="small" type="primary" @click="add">添加虚拟评论</el-button>
<el-button size="small" type="primary" @click="add" v-hasPermi="['admin:product:reply:save']">添加虚拟评论</el-button>
</div>
<el-table
v-loading="listLoading"
@@ -52,7 +42,7 @@
label="ID"
width="50"
/>
<el-table-column label="商品信息" min-width="300">
<el-table-column label="商品信息" min-width="400">
<template slot-scope="scope">
<div class="demo-image__preview acea-row row-middle" v-if="scope.row.storeProduct">
<el-image
@@ -68,7 +58,7 @@
<el-table-column
prop="nickname"
label="用户名称"
min-width="200"
min-width="100"
/>
<el-table-column
prop="productScore"
@@ -113,8 +103,8 @@
</el-table-column>
<el-table-column label="操作" min-width="120" fixed="right" align="center">
<template slot-scope="scope">
<el-button type="text" size="small" @click="reply(scope.row.id)" class="mr10">回复</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
<el-button type="text" size="small" @click="reply(scope.row.id)" class="mr10" v-hasPermi="['admin:product:reply:comment']">回复</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)" v-hasPermi="['admin:product:reply:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>

View File

@@ -1,10 +1,10 @@
<template>
<div class="Box">
<el-card>
<div>生成的商品默认是没有上架的请手动上架商品
<div class="line-ht">生成的商品默认是没有上架的请手动上架商品
<span v-if="copyConfig.copyType && copyConfig.copyType==1">您当前剩余{{copyConfig.copyNum}}条采集次数
<router-link :to="{path:'/operation/systemSms/pay?type=copy'}">
<el-link type="primary" :underline="false">增加采集次数</el-link>
<span style="color:#1890ff;">增加采集次数</span>
</router-link>
</span>
<el-link v-if="copyConfig.copyType && copyConfig.copyType!=1" type="primary" :underline="false"
@@ -29,7 +29,7 @@
<el-col :span="24" v-if="copyConfig.copyType">
<el-form-item label="链接地址:">
<el-input v-model="url" placeholder="请输入链接地址" class="selWidth" size="small">
<el-button slot="append" icon="el-icon-search" @click="add" size="small"/>
<el-button slot="append" icon="el-icon-search" @click="add" size="small" v-hasPermi="['admin:product:copy:product','admin:product:import:product']" />
</el-input>
</el-form-item>
</el-col>
@@ -61,16 +61,6 @@
<el-input v-model="formValidate.unitName" placeholder="请输入单位" class="selWidth"></el-input>
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="积分:">
<el-input-number v-model="formValidate.giveIntegral" placeholder="请输入排序" class="selWidth"/>
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="虚拟销量:">
<el-input-number v-model="formValidate.ficti" placeholder="请输入排序" class="selWidth"/>
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="运费模板:" prop="tempId">
<el-select v-model="formValidate.tempId" placeholder="请选择" class="selWidth">
@@ -186,13 +176,47 @@
</el-col>
<el-col :span="24">
<el-form-item label="商品详情:">
<ueditor-from v-model="formValidate.content" :content="formValidate.content"/>
<Tinymce v-model="formValidate.content"></Tinymce>
</el-form-item>
</el-col>
<el-col :span="24">
<template>
<el-row :gutter="24">
<el-col :span="24">
<template>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="排序:">
<el-input-number v-model="formValidate.sort" :max="9999" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="积分:">
<el-input-number v-model="formValidate.giveIntegral" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="虚拟销量:">
<el-input-number v-model="formValidate.ficti" placeholder="请输入排序" :disabled="isDisabled" />
</el-form-item>
</el-col>
</el-row>
</template>
</el-col>
<el-col :span="24">
<el-form-item label="商品推荐:">
<el-checkbox-group v-model="checkboxGroup" size="small" @change="onChangeGroup" :disabled="isDisabled">
<el-checkbox v-for="(item, index) in recommend" :key="index" :label="item.value">{{ item.name }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
</template>
</el-col>
<el-col :span="24">
<el-form-item>
<el-button type="primary" :loading="modal_loading" class="submission"
@click="handleSubmit('formValidate')">提交
<el-button type="primary" :loading="modal_loading" class="submission" @click="handleSubmit('formValidate')">提交
</el-button>
</el-form-item>
</el-col>
@@ -213,7 +237,10 @@
productCreateApi,
copyConfigApi
} from '@/api/store';
import { goodDesignList } from "@/api/systemGroup";
import Tinymce from '@/components/Tinymce/index'
import {shippingTemplatesList} from '@/api/logistics'
import {Debounce} from '@/utils/validate'
const defaultObj = [{
image: '',
price: null,
@@ -222,7 +249,7 @@
stock: null,
barCode: '',
weight: 0,
volume: 0
volume: 0,
}]
const objTitle = {
price: {
@@ -249,6 +276,7 @@
}
export default {
name: 'taoBao',
components: {Tinymce },
data() {
return {
loading: false,
@@ -264,6 +292,8 @@
multiple: true,
emitPath: false
},
checkboxGroup: [], //
recommend: [],
modal_loading: false,
ManyAttrValue: [Object.assign({}, defaultObj[0])], // 多规格
imgList: [],
@@ -277,6 +307,7 @@
url: '',
modalPic: false,
isChoice: '',
isDisabled:false,
ruleInline: {
storeName: [
{required: true, message: '请输入商品名称', trigger: 'blur'}
@@ -334,6 +365,7 @@
mounted() {
this.productGetTemplate();
this.getCopyConfig();
this.getGoodsType()
},
methods: {
// 删除表格中的属性
@@ -344,6 +376,13 @@
copyConfigApi().then(res => {
this.copyConfig = res
})
},
onChangeGroup() {
this.checkboxGroup.includes('isGood') ? this.formValidate.isGood = true : this.formValidate.isGood = false
this.checkboxGroup.includes('isBenefit') ? this.formValidate.isBenefit = true : this.formValidate.isBenefit = false
this.checkboxGroup.includes('isBest') ? this.formValidate.isBest = true : this.formValidate.isBest = false
this.checkboxGroup.includes('isNew') ? this.formValidate.isNew = true : this.formValidate.isNew = false
this.checkboxGroup.includes('isHot') ? this.formValidate.isHot = true : this.formValidate.isHot = false
},
// 批量添加
batchAdd() {
@@ -364,8 +403,10 @@
const tmp = {}
const tmpTab = {}
this.formValidate.attr.forEach((o, i) => {
tmp['value' + i] = {title: o.attrName}
tmpTab['value' + i] = ''
// tmp['value' + i] = {title: o.attrName}
// tmpTab['value' + i] = ''
tmp[o.attrName] = { title: o.attrName };
tmpTab[o.attrName] = '';
})
this.formValidate.attrValue = this.attrFormat(val)
this.manyTabTit = tmp
@@ -404,9 +445,12 @@
if (!rep4['attrValue']) rep4['attrValue'] = {}
rep4['attrValue'][rep3[0]] = rep3.length > 1 ? rep3[1] : ''
})
Object.values(rep4.attrValue).forEach((v, i) => {
rep4['value' + i] = v
})
// Object.values(rep4.attrValue).forEach((v, i) => {
// rep4['value' + i] = v
// })
for (let attrValueKey in rep4.attrValue) {
rep4[attrValueKey] = rep4.attrValue[attrValueKey];
}
res.push(rep4)
}
})
@@ -431,9 +475,9 @@
brokerage_two: 0,
attrValue: {[v['attrName']]: vv}
}
Object.values(res[kk].attrValue).forEach((v, i) => {
res[kk]['value' + i] = v
})
for (let attrValueKey in res[kk].attrValue) {
res[kk][attrValueKey] = res[kk].attrValue[attrValueKey];
}
})
})
data.push(dataArr.join('$&'))
@@ -450,6 +494,7 @@
// 删除图片
handleRemove(i) {
this.formValidate.sliderImages.splice(i, 1);
this.$forceUpdate();
},
// 选择主图
checked(item, index) {
@@ -498,7 +543,12 @@
giveIntegral: info.giveIntegral,
ficti: info.ficti
}
let imgs = JSON.parse(info.sliderImage)
if(info.isHot) this.checkboxGroup.push('isHot')
if(info.isGood) this.checkboxGroup.push('isGood')
if(info.isBenefit) this.checkboxGroup.push('isBenefit')
if(info.isBest) this.checkboxGroup.push('isBest')
if(info.isNew) this.checkboxGroup.push('isNew')
let imgs = JSON.parse(info.sliderImage)
let imgss = []
Object.keys(imgs).map(i => {
imgss.push(this.$selfUtil.setDomain(imgs[i]))
@@ -562,17 +612,21 @@
}
},
// 提交
handleSubmit(name) {
handleSubmit:Debounce(function(name) {
let pram = JSON.parse(JSON.stringify(this.formValidate));
// this.formValidate.attr.length ? this.formValidate.attrValue = this.ManyAttrValue : this.formValidate.attrValue = []
this.formValidate.cateId = this.formValidate.cateIds.join(',')
this.formValidate.sliderImage = JSON.stringify(this.formValidate.sliderImages)
for (var i = 0; i < this.formValidate.attr.length; i++) {
this.formValidate.attr[i].attrValues = JSON.stringify(this.formValidate.attr[i].attrValue)
}
pram.attr.forEach(item => {
item.attrValues = item.attrValue.join(",");
});
pram.cateId = pram.cateIds.join(',')
pram.sliderImage = JSON.stringify(pram.sliderImages);
pram.attrValue.forEach(itemData => {
itemData.attrValue = JSON.stringify(itemData.attrValue);
});
this.$refs[name].validate((valid) => {
if (valid) {
this.modal_loading = true
productCreateApi(this.formValidate).then(async res => {
productCreateApi(pram).then(async res => {
this.$message.success('新增成功');
this.$emit('handleCloseMod', false)
this.modal_loading = false
@@ -580,13 +634,13 @@
this.modal_loading = false
})
} else {
if (!this.formValidate.storeName || !this.formValidate.cateId || !this.formValidate.keyword
|| !this.formValidate.unitName || !this.formValidate.image) {
if (!pram.storeName || !pram.cateId || !pram.keyword
|| !pram.unitName || !pram.image) {
this.$message.warning("请填写完整商品信息!");
}
}
})
},
}),
// 点击商品图
modalPicTap(tit, num, i) {
const _this = this
@@ -606,7 +660,7 @@
_this.OneattrValue[0].image = img[0].sattDir
}
if (tit === '1' && num === 'duo') {
_this.this.formValidate.attrValue[i].image = img[0].sattDir
_this.formValidate.attrValue[i].image = img[0].sattDir
}
if (tit === '1' && num === 'pi') {
_this.oneFormBatch[0].image = img[0].sattDir
@@ -635,7 +689,48 @@
const dst = newItems.indexOf(item)
newItems.splice(dst, 0, ...newItems.splice(src, 1))
this.formValidate.slider_image = newItems
}
},
getGoodsType(){
/** 让商品推荐列表的name属性与页面设置tab的name匹配**/
goodDesignList({gid:70}).then((response)=>{
let list = response.list;
let arr = [];
let arr1 = [];
const listArr = [{ name: '是否热卖', value: 'isHot' }];
let typeLists = [
{ name: '', value: 'isGood',type:'2' }, //精品推荐1 热门榜单2 首发新品3 促销单品4
{ name: '', value: 'isBenefit' ,type:'4'},
{ name: '', value: 'isBest',type:'1' },
{ name: '', value: 'isNew',type:'3' }];
list.forEach((item)=>{
let obj = {};
obj.value = JSON.parse(item.value);
obj.id = item.id;
obj.gid = item.gid;
obj.status = item.status;
arr.push(obj);
})
arr.forEach((item1)=>{
let obj1 = {};
obj1.name = item1.value.fields[1].value;
obj1.status = item1.status;
obj1.type = item1.value.fields[3].value;
arr1.push(obj1);
})
typeLists.forEach((item)=>{
arr1.forEach((item1)=>{
if(item.type == item1.type){
listArr.push({
name:item1.name,
value:item.value,
type:item.type
})
}
})
})
this.recommend = listArr
})
},
}
}
</script>
@@ -650,6 +745,10 @@
width: 100%;
}
.line-ht{
line-height: 28px;
}
.lunBox {
display: flex;
flex-direction: column;