396 lines
9.0 KiB
Vue
396 lines
9.0 KiB
Vue
<template>
|
|
<view>
|
|
<up-popup :show="show" :round="10" mode="bottom" @close="handleClose" closeable catchtouchmove="preventD" :z-index="200">
|
|
<view class="skuBox">
|
|
<view class="oneBox">
|
|
<image :src="info.face_img" mode="aspectFill"></image>
|
|
<view class="box">
|
|
<view class="tit">{{info.title}}</view>
|
|
<view class="pricebox">
|
|
<view class="text1" v-if="vipOn && info.vip_price > 0 && (is_vip || (!is_vip && vip_price_show))">
|
|
<text class="icon1">¥</text>
|
|
<text>{{info.price}}</text>
|
|
</view>
|
|
<view>
|
|
<!-- 显示会员价 -->
|
|
<view v-if="vipOn && info.vip_price > 0 && (is_vip || (!is_vip && vip_price_show))" class="vip">
|
|
<view class="vip-tag"><text>会员价 ¥</text>{{info.vip_price}}</view>
|
|
</view>
|
|
<!-- 显示普通价格 -->
|
|
<view v-else class="vip">
|
|
<text class="icon1">¥</text>
|
|
<text>{{info.price}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="text" v-if="show_stock === 1">剩余{{info.stock <= 0 ? 0 : info.stock}}件</view>
|
|
</view>
|
|
</view>
|
|
<scroll-view class="scrollbox" scroll-y="true" enhanced="true">
|
|
<view class="twoBox">
|
|
<text>数量</text>
|
|
<view class="stepper">
|
|
<view class="minus flex" @click="minusNum()"><up-icon name="minus" size="12" :color="Color" /></view>
|
|
<view class="num">{{num}}</view>
|
|
<view class="plus flex" @click="plusNum()"><up-icon name="plus" size="12" color="#fff" /></view>
|
|
</view>
|
|
</view>
|
|
<view class="sku-buy" v-if="sales > 0">
|
|
<view class="img" v-for="img in info.avatars" :key="img">
|
|
<image :src="img"></image>
|
|
</view>
|
|
<view class="text">已有<text class="num">{{sales}}</text>个社群好友购买</view>
|
|
</view>
|
|
<view class="edition">
|
|
<view v-for="(item, index) in info.text_modules" :key="item.id">
|
|
<view v-if="item.type == 1" class="edition_box" @click="viewImg(item.imgs[0])">
|
|
<view v-for="(imgs, index) in item.imgs" :key="index">
|
|
<image :src="imgs" mode="widthFix" style="width: 100%;"></image>
|
|
</view>
|
|
</view>
|
|
<view class="edition_box" v-if="item.type == 2">
|
|
<view class="small_img">
|
|
<view v-for="(list, index) in item.img" :key="index" class="imgs" @click="viewImg(list)">
|
|
<image :src="list" mode="aspectFill"></image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 文字 -->
|
|
<view class="edition_box text1_box" v-if="item.type == 4">
|
|
<text user-select="true" class="text">{{item.text}}</text>
|
|
</view>
|
|
</view>
|
|
<view class="imgbox">
|
|
<image v-for="(img, idx) in info.gallery" :key="idx" :src="img" class="img" mode="widthFix" @click="viewImg(img)"></image>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="btn" :class="info.stock <= 0 || !canBuy ? 'dis' : ''" @click="(info.stock > 0 && canBuy) ? addCart():''">加入购物车</view>
|
|
</view>
|
|
</up-popup>
|
|
</view>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, reactive, toRefs, watch } from 'vue'
|
|
import { get, post } from '@/api/request.js'
|
|
import { showToast } from '../common.js'
|
|
export default {
|
|
props: {
|
|
show: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
id: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
show_stock: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
canBuy: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
shortStatus: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
groupId: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
sales: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
setup(props, context) {
|
|
const data = reactive({
|
|
id: 0,
|
|
show: false,
|
|
info: {},
|
|
vipOn: uni.getStorageSync('vip_on') === 1,
|
|
is_vip: uni.getStorageSync('is_vip'),
|
|
vip_price_show: uni.getStorageSync('vip_price_show') || false,
|
|
Color: uni.getStorageSync('theme_color'),
|
|
show_stock: 0,
|
|
canBuy: true,
|
|
num: 1,
|
|
groupId: 0,
|
|
shortStatus: 1
|
|
})
|
|
|
|
function getSpecInfo(val) {
|
|
get(`/api/v1/goods/spec/${data.id}`).then((res) => {
|
|
data.info = res.data
|
|
data.info.avatars = res.data.avatars || []
|
|
data.info.text_modules = res.data.text_modules || []
|
|
data.info.gallery = res.data.gallery || []
|
|
// 如果商品设置了起购
|
|
data.num = 1
|
|
if(res.data.limit_type == 1) {
|
|
data.num = parseInt(res.data.start_sale_num)
|
|
}
|
|
if(data.shortStatus == 0) {
|
|
data.info.stock = 0
|
|
}
|
|
})
|
|
}
|
|
|
|
// 数量-减
|
|
function minusNum() {
|
|
// 如果设置了起购&&起购数量与现有数量相等、现有数量为1 不可减
|
|
if((data.info.limit_type == 1 && data.num == parseInt(data.info.start_sale_num)) || data.num == 1) {
|
|
|
|
} else {
|
|
data.num -= 1
|
|
}
|
|
}
|
|
|
|
// 数量-加
|
|
function plusNum() {
|
|
// 如果设置了限购&&起购数量与现有数量相等、现有数量大于等于库存 不可加
|
|
if((data.info.limit_type == 2 && data.num == parseInt(data.info.limit)) || (data.num >= data.info.stock)) {
|
|
|
|
} else {
|
|
data.num += 1
|
|
}
|
|
}
|
|
|
|
const viewImg = (img) => {
|
|
uni.previewImage({
|
|
current: 0,
|
|
urls: [img]
|
|
})
|
|
}
|
|
|
|
function handleClose() {
|
|
context.emit('close')
|
|
}
|
|
|
|
const preventD = () => {
|
|
return
|
|
}
|
|
|
|
function addCart() {
|
|
let params = {
|
|
num: data.num,
|
|
shop_goods_id: data.id,
|
|
shop_goods_sku_id: 0,
|
|
shop_group_goods_id: data.groupId,
|
|
source_id: 0,
|
|
source_type: 'normal'
|
|
}
|
|
post('/api/v1/carts', params).then((res) => {
|
|
context.emit('refresh')
|
|
})
|
|
}
|
|
|
|
watch(props, async (newProps) => {
|
|
if (newProps.show) {
|
|
data.show = true
|
|
data.id = newProps.id
|
|
data.groupId = newProps.groupId
|
|
data.canBuy = newProps.canBuy
|
|
data.shortStatus = newProps.shortStatus
|
|
data.show_stock = newProps.show_stock
|
|
getSpecInfo()
|
|
} else {
|
|
data.show = false
|
|
}
|
|
})
|
|
|
|
return {
|
|
...toRefs(data),
|
|
getSpecInfo,
|
|
handleClose,
|
|
viewImg,
|
|
preventD,
|
|
minusNum,
|
|
plusNum,
|
|
addCart
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.skuBox{
|
|
background: #fff;
|
|
height: 78vh;
|
|
overflow: hidden;
|
|
.oneBox{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 24rpx;
|
|
box-sizing: border-box;
|
|
image{
|
|
width: 200rpx;
|
|
height: 200rpx;
|
|
}
|
|
.box{
|
|
width: calc(100% - 220rpx);
|
|
.tit{
|
|
font-size: 30rpx;
|
|
}
|
|
.pricebox{
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
margin: 8rpx 0 20rpx;
|
|
.text1{
|
|
font-size: 34rpx;
|
|
color: #f66d2d;
|
|
font-weight: 600;
|
|
margin-right: 12rpx;
|
|
}
|
|
.icon1{
|
|
font-size: 24rpx;
|
|
}
|
|
.vip{
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 34rpx;
|
|
color: #f66d2d;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
.text{
|
|
font-size: 24rpx;
|
|
color: #999999;
|
|
}
|
|
.vip-tag {
|
|
font-size: 32rpx;
|
|
color: #fbe6c3;
|
|
background: #353648;
|
|
border-radius: 20rpx 0 0 0;
|
|
padding: 8rpx 10rpx;
|
|
line-height: 1;
|
|
text{
|
|
font-size: 22rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.scrollbox{
|
|
width: 100%;
|
|
height: calc(78vh - 358rpx);
|
|
}
|
|
.twoBox{
|
|
font-size: 28rpx;
|
|
padding: 30rpx 24rpx;
|
|
box-sizing: border-box;
|
|
border-top: 1rpx solid #eee;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
.stepper{
|
|
display: flex;
|
|
align-items: center;
|
|
.flex{
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
box-sizing: border-box;
|
|
border-radius: 4rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.num{
|
|
width: 80rpx;
|
|
font-size: 28rpx;
|
|
text-align: center;
|
|
}
|
|
.minus{
|
|
border: 1px solid v-bind('Color');
|
|
}
|
|
.plus{
|
|
background-color: v-bind('Color');
|
|
}
|
|
}
|
|
}
|
|
.sku-buy{
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 30rpx;
|
|
border-top: 1rpx solid #eee;
|
|
border-bottom: 1rpx solid #eee;
|
|
.img{
|
|
width: 50rpx;
|
|
height: 50rpx;
|
|
margin-left: -10rpx;
|
|
border: 4rpx solid #fff;
|
|
box-sizing: border-box;
|
|
image{
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 10rpx;
|
|
}
|
|
}
|
|
.text {
|
|
margin-left: 20rpx;
|
|
font-size: 28rpx;
|
|
.num{
|
|
color: v-bind('Color');
|
|
}
|
|
}
|
|
}
|
|
.edition{
|
|
padding-bottom: 50rpx;
|
|
.edition_box{
|
|
margin: 8rpx 0;
|
|
position: relative;
|
|
padding: 0 20rpx;
|
|
.img{
|
|
width: 100%;
|
|
}
|
|
.small_img{
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: flex-start;
|
|
.imgs{
|
|
width: calc(33% - 11rpx);
|
|
height: 220rpx;
|
|
margin: 16rpx 16rpx 0 0;
|
|
image{
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
}
|
|
.imgs:nth-child(3n+3){
|
|
margin: 16rpx 0 0 0;
|
|
}
|
|
}
|
|
.text{
|
|
line-height: 55rpx;
|
|
font-size: 30rpx;
|
|
color: #222;
|
|
}
|
|
}
|
|
.imgbox{
|
|
padding: 20rpx 0;
|
|
.img{
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
.btn{
|
|
height: 110rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
background-color: v-bind('Color');
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
&.dis{
|
|
opacity: 0.65;
|
|
}
|
|
}
|
|
}
|
|
</style> |