You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

586 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<xy-dialog :width="66" ref="dialog" type="form" :is-show.sync="isShow" :title="type === 'add' ? '新增商品' : '编辑商品'"
:form="form" :rules="rules" @submit="submit">
<template v-slot:name>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>名称
</div>
<div class="xy-table-item-content">
<el-input v-model="form.name" placeholder="请输入商品名称" clearable style="width: 300px;"></el-input>
</div>
</div>
</template>
<template v-slot:poster>
<div class="xy-table-item">
<div class="xy-table-item-label">
海报图:
</div>
<div class="xy-table-item-content">
<div v-if="form.poster_url" style="position: relative;">
<img :src="form.poster_url" class="avatar">
<Button shape="circle" icon="md-close" type="error" size="small" class="img__delete"
@click="form.poster_url = ''"></Button>
</div>
<el-upload v-else accept="picture" :limit="1" class="avatar-uploader" list-type="picture-card"
:action="action" :show-file-list="true" :on-error="uploadFail" :on-success="uploadSuccess"
:before-upload="uploadBefore">
<i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</div>
</template>
<template v-slot:merchantId>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>所属商户:
</div>
<div class="xy-table-item-content">
<el-input suffix-icon="el-icon-arrow-down" readonly :value="form.merchantId.label" placeholder="请选择所属商户"
clearable style="width: 300px;" @focus="isShowMerchantSelect = true,getMerchants()"></el-input>
</div>
</div>
</template>
<template v-slot:shopIds>
<div class="xy-table-item">
<div class="xy-table-item-label">
限制门店:
</div>
<div class="xy-table-item-content">
<el-input v-model="form.shopIds" placeholder="请选择限制门店" clearable style="width: 300px;"></el-input>
</div>
</div>
</template>
<template v-slot:productTypePid>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>所属板块:
</div>
<div class="xy-table-item-content">
<el-select clearable placeholder="请选择所属板块" style="width: 300px" v-model="form.productTypePid"
@change="typeChange">
<el-option v-for="item in types" :key="item.id" :value="item.id" :label="item.name">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-slot:productTypeId>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>产品类别:
</div>
<div class="xy-table-item-content">
<el-select clearable placeholder="请选择产品类别" style="width: 300px" v-model="form.productTypeId">
<el-option v-for="item in products" :key="item.id" :value="item.id" :label="item.name">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-slot:originalPrice>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>原价:
</div>
<div class="xy-table-item-content number-input">
<el-input-number :precision="2" :controls="false" :min="0" placeholder="请输入原价" clearable
v-model="form.originalPrice" style="width: 300px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:price>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>价格:
</div>
<div class="xy-table-item-content number-input">
<el-input-number :precision="2" :controls="false" :min="0" placeholder="请输入价格" clearable
v-model="form.price" style="width: 300px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:fee>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>平台佣金:
</div>
<div class="xy-table-item-content number-input">
<el-input-number :precision="2" :controls="false" :min="0" placeholder="请输入平台佣金" clearable
v-model="form.fee" style="width: 300px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:sharing>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>分享金:
</div>
<div class="xy-table-item-content number-input">
<el-input-number :precision="2" :controls="false" :min="0" placeholder="请输入分享金" clearable
v-model="form.sharing" style="width: 300px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:maxQuantity>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>总份数:
</div>
<div class="xy-table-item-content">
<el-input-number :min="0" placeholder="请输入总份数" clearable v-model="form.maxQuantity" style="width: 200px;">
</el-input-number>
</div>
</div>
</template>
<template v-slot:limitQuantity>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>每用户限购:
</div>
<div class="xy-table-item-content">
<el-input-number :min="0" placeholder="请输入每用户限购数" clearable v-model="form.limitQuantity"
style="width: 200px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:pretendQuantity>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>虚拟购买次数:
</div>
<div class="xy-table-item-content">
<el-input-number :min="0" placeholder="请输入虚拟购买次数" clearable v-model="form.pretendQuantity"
style="width: 200px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:time>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>上架/下架时间:
</div>
<div class="xy-table-item-content">
<el-date-picker clearable style="width: 440px;" v-model="form.time" type="datetimerange"
:picker-options="pickerOptions" range-separator="至" start-placeholder="上架日期" end-placeholder="下架日期"
align="right" value-format="yyyy-MM-dd hh:mm:ss">
</el-date-picker>
</div>
</div>
</template>
<template v-slot:sortnumber>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>排序<span
style="font-size: 12px;padding-left: 2px;color: rgb(140,140,140)">(大到小)</span>
</div>
<div class="xy-table-item-content">
<el-input-number v-model="form.sortnumber" :controls="false" style="width: 200px;"></el-input-number>
</div>
</div>
</template>
<template v-slot:content>
<div class="xy-table-item">
<div class="xy-table-item-label">
内容:
</div>
<div class="xy-table-item-content" style="width:680px">
<xyTinymce v-if="isShow" v-model="form.content"></xyTinymce>
<!-- <tinymce ref="tinymce" :height="200" v-model="form.content" id='tinymce'></tinymce> -->
</div>
</div>
</template>
</xy-dialog>
<Modal v-model="isShowMerchantSelect" title="所属商户选择">
<div class="searchMerchants">
<el-input type="text" @keyup.enter.native="searchMerchants" v-model="merchantKeyword" placeholder="请输入关键词查找商户"></el-input>
<el-button type="primary" @click="searchMerchants">查询</el-button>
</div>
<Table size="small" highlight-row ref="currentRowTable" :columns="merchantTable" :data="merchants"
@on-current-change="merchantSelect" />
<Page :current="merchantIndex" :total="merchantTotal" simple
style="padding-top: 14px;display: flex;justify-content: center;" @on-change="merchantPageChange" />
</Modal>
</div>
</template>
<script>
import {
store,
show,
save
} from '@/api/product'
import {
index as merchantIndex
} from '@/api/merchant'
import {
Message
} from 'element-ui'
// import tinymce from "@/components/Tinymce"
import xyTinymce from "@/components/XyTinymce/index.vue";
import {replaceAll} from "@/utils/index"
export default {
components: {
xyTinymce
},
props: {
types: Array
},
data() {
return {
id: '',
isShow: false,
type: 'add',
action: `${process.env.VUE_APP_BASE_API}api/admin/upload-file`,
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}]
},
form: {
name: '',
poster: '',
merchantId: '',
shopIds: '',
productTypePid: '',
productTypeId: '',
originalPrice: '',
price: '',
fee: '',
sharing: '',
maxQuantity: '',
limitQuantity: '1',
pretendQuantity: 0,
time: [],
sortnumber: 0,
content: '',
poster_url: ""
},
rules: {
name: [{
required: true,
message: '请填写商品名称'
}],
merchantId: [{
required: true,
message: '请选择所属商家'
}],
productTypePid: [{
required: true,
message: '请选择所属模块'
}],
productTypeId: [{
required: true,
message: '请选择产品类别'
}],
originalPrice: [{
required: true,
message: '请输入原价'
}],
price: [{
required: true,
message: '请输入价格'
}],
fee: [{
required: true,
message: '请输入平台佣金'
}],
sharing: [{
required: true,
message: '请输入分享金'
}],
maxQuantity: [{
required: true,
message: '请输入总分数'
}],
limitQuantity: [{
required: true,
message: '请输入用户限购'
}],
time: [{
required: true,
message: '请选择上架/下架时间'
}]
},
products: [], //板块下商品
isShowMerchantSelect: false,
merchants: [],
merchantTable: [{
title: '简称',
key: 'username',
width: 130
},
{
title: '全称',
key: 'name',
align: 'left',
width: 220
},
{
title: '状态',
key: 'state',
sortable: true
}
],
merchantKeyword:"",
merchantIndex: 1,
merchantTotal: 0,
}
},
methods: {
async getDetail() {
const res = await show({
id: this.id
})
this.typeChange(res?.product_type_pid)
this.form = {
name: res?.name,
poster: res?.poster,
poster_url: res?.poster_url,
merchantId: {
label: res.merchant?.name,
value: res.merchant?.id
},
shopIds: res?.shop_ids,
productTypePid: res?.product_type_pid,
productTypeId: res?.product_type_id,
originalPrice: res?.original_price,
price: res?.price,
fee: res?.fee,
sharing: res?.sharing,
maxQuantity: res?.max_quantity,
limitQuantity: res?.limit_quantity,
pretendQuantity: res?.pretend_quantity,
time: [res?.start_time, res?.end_time],
sortnumber: res?.sortnumber,
content: res?.content
}
// this.$refs['tinymce'].setContent(this.form.content || ' ')
},
//上传
uploadFail(err) {
console.log(err)
},
uploadSuccess(response) {
console.log(response)
this.form.poster = "/" + response.folder + "/" + response.name
this.form.poster_url = response.url;
},
uploadBefore(file) {
if ((file.size / 1000) > 2024) {
Message({
type: 'warning',
message: '上传图片大小超过2M'
})
return false
}
},
typeChange(val) {
if (!val) {
this.products = []
return
}
let res = this.types.filter(item => {
return item.id === val
})
this.products = res[0].children
},
async getMerchants() {
const res = await merchantIndex({
page_size: 10,
page: this.merchantIndex,
keyword:this.merchantKeyword
})
this.merchantTotal = res.total
this.merchants = res.data
},
searchMerchants(){
this.getMerchants()
},
merchantPageChange(e) {
this.merchantIndex = e
this.getMerchants()
},
merchantSelect(row) {
this.form.merchantId = {
label: row.username,
value: row.id
}
},
// replaceAll(str,before,after){
// if(str.indexOf(before) != -1){
// return str.replace(new RegExp(before, 'g'),after)
// }else{
// return str
// }
// },
submit() {
if (this.type === 'add'||this.type === 'copy') {
store({
name: this.form.name,
poster: this.form.poster,
merchant_id: this.form.merchantId?.value,
shop_ids: this.form.shopIds,
product_type_pid: this.form.productTypePid,
product_type_id: this.form.productTypeId,
original_price: this.form.originalPrice.toString(),
price: this.form.price.toString(),
fee: this.form.fee.toString(),
sharing: this.form.sharing.toString(),
max_quantity: this.form.maxQuantity.toString(),
limit_quantity: this.form.limitQuantity.toString(),
pretend_quantity: this.form.pretendQuantity.toString(),
start_time: this.form.time[0],
sortnumber: this.form.sortnumber,
end_time: this.form.time[1],
content: replaceAll(this.form.content,'../storage/files',`${process.env.VUE_APP_BASE_API}storage/files`)
}).then(res => {
Message({
type: 'success',
message: '新增成功'
})
this.isShow = false
this.$emit('refresh')
})
return
}
if (this.type === 'editor') {
save({
id: this.id,
name: this.form.name,
poster: this.form.poster,
merchant_id: this.form.merchantId?.value,
shop_ids: this.form.shopIds,
product_type_pid: this.form.productTypePid,
product_type_id: this.form.productTypeId,
original_price: this.form.originalPrice.toString(),
price: this.form.price.toString(),
fee: this.form.fee.toString(),
sharing: this.form.sharing.toString(),
max_quantity: this.form.maxQuantity.toString(),
limit_quantity: this.form.limitQuantity.toString(),
pretend_quantity: this.form.pretendQuantity.toString(),
start_time: this.form.time[0],
sortnumber: this.form.sortnumber,
end_time: this.form.time[1],
content: replaceAll(this.form.content,'../storage/files',`${process.env.VUE_APP_BASE_API}storage/files`)
}).then(res => {
Message({
type: 'success',
message: '编辑商品成功'
})
this.isShow = false
this.$emit('refresh')
})
}
}
},
watch: {
isShow(newVal) {
if (newVal) {
if (this.type === 'editor'||this.type === 'copy') {
this.getDetail()
}
} else {
// this.$refs['tinymce'].setContent(' ')
this.$refs['dialog'].reset()
this.id = ''
this.type = ''
}
}
}
}
</script>
<style scoped lang="scss">
.xy-table-item-label {
width: 164px;
}
.number-input {
::v-deep .el-input-number .el-input__inner {
text-align: left !important;
}
}
.searchMerchants{
display: flex;
justify-content: space-between;
margin-bottom:16px;
.el-input{
width:80%
}
}
</style>
<style>
.avatar-uploader .el-upload {
width: 110px;
height: 110px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
.avatar-uploader .el-upload:hover {
border-color: #BF617C;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 110px;
height: 110px;
line-height: 110px;
text-align: center;
}
.avatar {
width: 110px;
display: block;
border-radius: 6px;
}
.img__delete {
transform: scale(0.7, 0.7);
position: absolute;
top: 1px;
left: 4%;
}
</style>