Files
BlockChainH5/pages/goods/add.vue

718 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content">
<!-- 商品图片 -->
<view class="form-block">
<view class="form-upd">
<view class="form-title">商品轮播图<text>首图封面图点击预览长按删除</text></view>
<view class="form-imgs">
<view
class="item"
v-for="(item, index) in pictures"
:key="index"
@click="openImg(index, 'pictures')"
@longpress="removeImg(index, 'pictures')"
>
<image class="item-cover" :src="item.showpath" mode="aspectFill"></image>
</view>
<view class="item item-add" @click="updCover('pictures')">
<image class="item-cover" src="@/static/icons/add-icon.png" mode="aspectFill"></image>
</view>
</view>
</view>
</view>
<!-- 商品基本信息 -->
<view class="form-block">
<view class="form-box inputs-flex">
<label class="form-label">商品标题</label>
<input type="text" v-model="name" placeholder="输入商品标题"/>
</view>
<view class="form-box inputs-flex">
<label class="form-label">商品描述</label>
<input type="text" v-model="description" placeholder="输入商品描述"/>
</view>
<view class="form-box inputs-flex">
<label class="form-label">规格单位</label>
<input type="text" v-model="skus_unit" placeholder="输入规格单位 如:件"/>
</view>
<view class="form-upd">
<view class="form-title">商品详情点击预览长按删除</view>
<view class="form-imgs">
<view
class="item"
v-for="(item, index) in content"
:key="index"
@click="openImg(index, 'content')"
@longpress="removeImg(index, 'content')"
>
<image class="item-cover" :src="item.showpath" mode="aspectFill"></image>
</view>
<view class="item item-add" @click="updCover('content')">
<image class="item-cover" src="@/static/icons/add-icon.png" mode="aspectFill"></image>
</view>
</view>
</view>
</view>
<!-- 商品价格 -->
<view class="form-block">
<view class="form-box inputs-flex input-unit">
<label class="form-label">市场价格</label>
<input type="digit" v-model="skus_cost" placeholder="0.00"/>
<text class="units">{{skus_unit != '' ? '/' + skus_unit : ''}}</text>
</view>
<view class="form-box inputs-flex input-unit">
<label class="form-label">销售价格</label>
<input type="digit" v-model="skus_price" placeholder="0.00"/>
<text class="units">{{skus_unit != '' ? '/' + skus_unit : ''}}</text>
</view>
<view class="form-box inputs-flex input-unit " style="background-color: #eee9fd;" v-if="skus_price>0">
<label class="form-label">可结算货款 </label>
<input type="digit" :value="percentTotal" :disabled="true" /> <span class='des'>(扣除分佣后预计到账金额)</span>
<text class="units">{{skus_unit != '' ? '/' + skus_unit : ''}}</text>
</view>
</view>
<!-- 商品详情介绍 -->
<view class="form-block">
<!-- <view class="form-box picker-flex">
<label class="form-label">支持易货</label>
<view class="picker-switch">
<switch :checked="isChange" color="#e93340" @change="pickerChange($event, 'isChange')"/>
</view>
</view> -->
<!-- <view class="form-box inputs-flex" v-if="isChange">
<label class="form-label">最低易货量</label>
<input type="number" v-model="skus_number" placeholder="输入最低易货量"/>
</view> -->
<view class="form-box inputs-flex">
<label class="form-label">发行权证数</label>
<input type="number" v-model="skus_stock" placeholder="输入商品发行权证数"/>
</view>
</view>
<!-- 售后服务 -->
<view class="form-block">
<view class="form-box picker-flex">
<label class="form-label">配送方式</label>
<picker :range="logisticArr" range-key="text" :value="logisticType" @change="pickerChange($event, 'logisticType')">
<view class="picker-text">
{{logisticArr[logisticType].text}}
<uni-icons class="picker-icon" type="arrowright" color="#999"></uni-icons>
</view>
</picker>
</view>
<view class="form-box picker-flex" v-if="logisticType === 1">
<label class="form-label">关联店铺</label>
<view class="picker-text" @click="opnePopup('storePopup')">
已关联{{stores.length}}家店铺<uni-icons class="picker-icon" type="arrowright" color="#999"></uni-icons>
</view>
</view>
<view class="form-box picker-flex">
<label class="form-label">允许售后</label>
<view class="picker-switch">
<switch :checked="isPostSale" color="#8b64fd" @change="pickerChange($event, 'isPostSale')"/>
</view>
</view>
<view class="form-box picker-flex">
<label class="form-label">可选服务</label>
<view class="picker-text" @click="opnePopup('categoryPopup')">
已选{{services.length}}项服务<uni-icons class="picker-icon" type="arrowright" color="#999"></uni-icons>
</view>
</view>
</view>
<!-- 售后服务 -->
<view class="form-block" v-if="type == 2">
<view class="form-box picker-flex">
<label class="form-label">到期时间</label>
<picker mode="date" :value="expiriedAt" @change="pickerChange($event, 'expiriedAt')">
<view class="picker-text">
{{expiriedAt || '选择服务到期时间'}}
<uni-icons class="picker-icon" type="arrowright" color="#999"></uni-icons>
</view>
</picker>
</view>
</view>
<!-- 可选服务 -->
<uni-popup ref="categoryPopup">
<view class="category-popup">
<view class="header">
<view class="title">选择商品服务</view>
</view>
<view class="category-flex">
<view class="category-flex-item" :class="{'show' : item.check}" v-for="(item, index) in servicesArr" :key="index" @click="item.check = !item.check">
<view class="category-name">{{item.name}}</view>
<view class="category-content">{{item.content}}</view>
</view>
</view>
<view class="btns">
<button type="default" size="default" @click="affirmCategory('services', 'categoryPopup')">确定</button>
</view>
</view>
</uni-popup>
<!-- 选择店铺 -->
<uni-popup ref="storePopup">
<view class="category-popup">
<block v-if="storesArr.length>0">
<view class="header">
<view class="title">选择店铺</view>
</view>
<scroll-view class="category-flex" scroll-y="true">
<view class="category-flex-item" :class="{'show' : item.check}" v-for="(item, index) in storesArr" :key="index" @click="item.check = !item.check">
<view class="category-name">{{item.name}}</view>
<view class="category-content">{{item.address}}</view>
</view>
</scroll-view>
<view class="btns">
<button type="default" size="default" @click="affirmCategory('stores', 'storePopup')">确定</button>
</view>
</block>
<block v-else>
<no-list name="no-shop" txt='您还没有创建店铺~' />
<view class="btns" v-if="storePer">
<button type="default" size="default" @click="$Router.push({name:'shopCreate'})">新建店铺</button>
</view>
<view v-else>
<view class="btns">
<button type="default" size="default">当前没有创建店铺的权限</button>
</view>
</view>
</block>
</view>
</uni-popup>
<!-- 安全区 -->
<view class="ios-bottom"></view>
<!-- footer -->
<view class="footer">
<button class="footer-btn" type="default" @click="submitAdd">{{type == 2 ? '发布': '发布并认证'}}</button>
<view class="ios-bottom"></view>
</view>
</view>
</template>
<script>
import { managesGoodsCreate, managesCreate, managesGoodsEdit, managesGoodsPut } from '@/apis/interfaces/goods'
import { uploads } from '@/apis/interfaces/uploading'
export default {
data() {
return {
categoryId : '', // 一级分类
categoryCid : '', // 二级分类
name : '', // 标题
pictures : [], // 轮播图
content : [], // 详情图
description : '', // 商品描述
isPostSale : false, // 是否允许售后
services : [], // 商品服务
skus_cost : '', // 市场价格
skus_price : '', // 销售价格
skus_number : 1, // 易货起购数量
skus_unit : '件', // 规格文字
skus_stock : '', // 库存
isChange : false, // 是否支持易货
stores : [], // 关联店铺
expiriedAt : '', // 活动到期时间
logisticType: 0, // 配送方式
logisticArr : [
{text: '快递', type: 1},
{text: '自提', type: 2}
],
percent:0,// 预结算货款比例
// 配置信息
storesArr : [], // 可选店铺
tags : [], // 可选商品标签
tagsIndex : 0, // 选择标签的下标
servicesArr : [], // 可选服务
type : 1, // 1为商品2为服务
storePer : true,// 默认可以创建门店
shopRefresh: false
};
},
computed:{
percentTotal(){
return (this.percent * this.skus_price).toFixed(2)
}
},
beforeRouteLeave(to, from, next){
if(to.name === 'shopCreate'){
this.shopRefresh = true
}
next()
},
onShow(){
if(this.shopRefresh){
// 编辑状态信息
if(this.$Route.query.type && this.$Route.query.type === 'edit'){
managesGoodsEdit(this.$Route.query.id).then(res => {
let storesArr = res.stores.map(val => {
let check = (res.data.stores.findIndex(obj => obj.store_id === val.store_id)) >= 0
if(check){
stores.push(val.store_id)
}
return {
check,
...val
}
})
this.storesArr = storesArr
this.stores = stores
this.storePer = res.storePer
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
return
}
// 添加配置信息
managesCreate({
category_cid: this.$Route.query.cid
}).then(res => {
res.stores = res.stores.map(val => {
return {
check: false,
...val
}
})
this.storesArr = res.stores
this.storePer = res.storePer
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
}
},
created() {
// 编辑状态信息
if(this.$Route.query.type && this.$Route.query.type === 'edit'){
managesGoodsEdit(this.$Route.query.id).then(res => {
let services = [], stores = []
let servicesArr = res.services.map(val => {
let check = (res.data.services.findIndex(obj => obj.service_id === val.service_id)) >= 0
if(check){
services.push(val.service_id)
}
return{
check,
...val
}
})
let storesArr = res.stores.map(val => {
let check = (res.data.stores.findIndex(obj => obj.store_id === val.store_id)) >= 0
if(check){
stores.push(val.store_id)
}
return {
check,
...val
}
})
this.categoryId = res.data.category.category_id
this.categoryCid = res.data.category_sub.category_id
this.name = res.data.name
this.content = res.data.content
this.description = res.data.description
this.pictures = res.data.pictures
this.skus_cost = res.data.skus[0].cost
this.skus_price = res.data.skus[0].price
this.skus_number = res.data.skus[0].number
this.skus_unit = res.data.skus[0].unit
this.skus_stock = res.data.skus[0].stock
this.isPostSale = res.data.is_post_sale == 0
this.isChange = res.data.is_change == 0
this.logisticType= this.logisticArr.findIndex(val => val.type === res.data.logistic_type)
this.servicesArr = servicesArr
this.storesArr = storesArr
this.services = services
this.stores = stores
this.percent = Number(res.percent)
this.storePer = res.storePer
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
return
}
// 添加配置信息
managesCreate({
category_cid: this.$Route.query.cid
}).then(res => {
res.services = res.services.map(val => {
return {
check: false,
...val
}
})
res.stores = res.stores.map(val => {
return {
check: false,
...val
}
})
this.storesArr = res.stores
this.tags = res.tags
this.servicesArr= res.services
this.type = res.type
this.categoryId = this.$Route.query.id
this.categoryCid= this.$Route.query.cid
this.percent = Number(res.percent)
this.storePer = res.storePer
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
},
methods: {
// 选择商品服务
opnePopup(key){
this.$refs[key].open('bottom')
},
// 确认选择商品服务
affirmCategory(key, popupKey){
let keyArr = key == 'services' ? 'servicesArr' : 'storesArr'
this[key] = []
for(let val of this[keyArr]){
if(val.check){
this[key].push(val.service_id || val.store_id)
}
}
this.$refs[popupKey].close()
},
// picker选择
pickerChange(e, key){
this[key] = e.detail.value
},
// 图片预览
openImg(index, key){
let paths = this[key].map(val => {
return val.showpath
})
uni.previewImage({
urls : paths,
current : index,
indicator: 'number'
})
},
// 删除图片
removeImg(index, key){
this[key].splice(index, 1)
},
// 上传图片
updCover(key){
uni.chooseImage({
success : res => {
let path = res.tempFiles.map((val, index) => {
return {
name: 'uploads' + index,
uri : val.path
}
})
uploads(path).then(updRes => {
for(let i in updRes.path){
this[key].push({
path : updRes.path[i],
showpath: updRes.url[i]
})
}
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
}
})
},
// 发布产品
submitAdd(){
let pictures = this.pictures.map(val => {return val.path}),
content = this.content.map(val => {return val.path})
if(this.pictures.length <= 0) {
uni.showToast({
title: '商品轮播图不能为空',
icon : 'none'
})
return
}
let submitData = {
name : this.name,
cover : this.pictures[0].path,
category_id : this.categoryId,
category_cid : this.categoryCid,
pictures : pictures,
content : content,
description : this.description,
is_post_sale : this.isPostSale ? 0 : 1,
services : this.services,
skus_cost : this.skus_cost,
skus_price : this.skus_price,
skus_number : this.skus_number,
skus_unit : this.skus_unit,
skus_stock : this.skus_stock,
is_change : this.isChange ? 0 : 1,
logistic_type: this.logisticArr[this.logisticType].type,
stores : this.stores,
expiried_at : this.expiriedAt
}
let submitFund = this.$Route.query.type === 'edit' ? managesGoodsPut(this.$Route.query.id, submitData) : managesGoodsCreate(submitData)
submitFund.then(res => {
uni.setStorageSync('refresh',true)
if(this.type === 2){
uni.showModal({
title : '提示',
content : '商品权证已发布,请耐心等待平台审核',
showCancel : false,
success : res => {
if(res.confirm){
this.$Router.back(this.$Route.query.type === 'edit' ? 1 : 2)
}
}
})
return
}
uni.showModal({
title : '提示',
content : this.$Route.query.type === 'edit' ? '商品权证已更新,是否立即补充产品附加信息认证?' : '商品权证已发布,是否立即补充产品附加信息认证?',
cancelText : '稍后认证',
confirmText : '立即认证',
success : authRes => {
if(authRes.cancel){
this.$Router.back(this.$Route.query.type === 'edit' ? 1 : 2)
}
if(authRes.confirm){
let goodsId = this.$Route.query.type === 'edit' ? this.$Route.query.id : res
this.$Router.push({name: 'goodsAddAuth', params: { id: goodsId , type: 'goodsAdd', edit: this.$Route.query.type === 'edit'}})
}
}
})
}).catch(err => {
uni.showToast({
title: err.message,
icon : 'none'
})
})
}
}
}
</script>
<style lang="scss" scoped>
.content{
padding-bottom: 150rpx;
}
// 表单
.form-block{
background: white;
margin-top: $margin - 10;
.form-box{
position: relative;
padding-left: 240rpx;
padding-right: $padding;
font-size: $title-size-lg;
min-height: 80rpx;
&::after{
position: absolute;
bottom: 0;
left: $margin;
right: 0;
height: 1rpx;
content: " ";
background: $border-color;
}
&:last-child::after{
display: none;
}
.form-label{
position: absolute;
left: $margin;
line-height: 80rpx;
top: 0;
width: calc(240rpx - #{$margin});
}
}
.inputs-flex{
input{
height: 80rpx;
line-height: 80rpx;
}
}
.input-unit{
padding-right: 200rpx;
.des{
font-size: 26rpx;padding-bottom: 20rpx;display: inline-block;
color: #999;
position: relative;
right: -200rpx;
}
.units{
position: absolute;
right: 0;
top: 0;
line-height: 80rpx;
height: 80rpx;
width: 200rpx;
padding-right: $padding;
text-align: right;
box-sizing: border-box;
}
}
.picker-flex{
.picker-text{
position: relative;
line-height: 80rpx;
min-height: 80rpx;
padding-right: 80rpx;
@extend .nowrap;
.picker-icon{
right: 0;
position: absolute;
}
}
.picker-switch{
line-height: 80rpx;
min-height: 80rpx;
text-align: right;
margin-right: -15rpx;
switch{
transform:scale(0.7)
}
}
}
.form-upd{
.form-title{
font-size: $title-size-lg;
line-height: 80rpx;
padding: 0 $padding;
text{
font-size: 80%;
color: $text-gray;
}
}
.form-imgs{
margin-top: -($margin/3);
padding: 0 20rpx 20rpx;
display: flex;
flex-wrap: wrap;
.item{
width: calc(20% - 14rpx);
padding-top: calc(20% - 14rpx);
margin: 7rpx;
position: relative;
.item-cover{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
.item-add{
border: dashed 2rpx $border-color;
box-sizing: border-box;
.item-cover{
top: calc(15% - 2rpx);
left: calc(15% - 2rpx);
width: 70%;
height: 70%;
}
}
}
}
}
// 发布
.footer{
background: white;
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx $padding;
box-shadow: 0 0 4rpx 4rpx rgba($color: #000000, $alpha: .02);
z-index: 9;
.footer-btn{
border: none;
border-radius: 0;
background: $mian-color;
height: 90rpx;
line-height: 90rpx;
font-weight: bold;
font-size: $title-size;
color: white;
&::after{
border: none;
}
}
}
// 可选服务
.category-popup{
background: #F5F5F5;
padding: 0 $padding * 2 $padding * 2 $padding * 2;
.header{
padding: $padding*2 0;
box-sizing: border-box;
@extend .vertical;
.title{
text-align: center;
font-size: $title-size + 14;
font-weight: bold;
line-height: 90rpx;
}
.subtitle{
font-size: $title-size-m;
color: $text-gray;
text-align: center;
}
}
.category-flex{
max-height: 50vh;
overflow-y: scroll;
.category-flex-item{
margin-bottom: $margin;
padding: $padding;
background: white;
border:solid 1rpx white;
box-sizing: border-box;
.category-name{
padding-bottom: $padding/2;
font-weight: bold;
font-size: $title-size-lg;
}
.category-content{
font-size: $title-size-sm;
color: $text-gray;
@extend .ellipsis;
}
&.show{
color: $text-price;
border:solid 1rpx $text-price;
}
&:last-child{
margin-bottom: 0;
}
}
}
.btns{
padding-top: $padding * 2;
button{
background: $mian-color;
border-radius: 0;
height: 90rpx;
line-height: 90rpx;
font-size: $title-size;
color: white;
font-weight: bold;
&::after{
border: none;
}
}
}
}
</style>