|
|
<!--
|
|
|
* @Author: ch
|
|
|
* @Date: 2022-03-24 11:30:55
|
|
|
* @LastEditors: ch
|
|
|
* @LastEditTime: 2022-04-08 15:34:00
|
|
|
* @Description: file content
|
|
|
-->
|
|
|
<template>
|
|
|
<u-popup :show="visible" round="24rpx" closeable @close="close">
|
|
|
<view class="sku-popup">
|
|
|
<view class="product-info">
|
|
|
<image class="product-info--img" src="https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/test/1.png"/>
|
|
|
<view>
|
|
|
<view class="product-info--price">¥{{curSku.sellPrice}}</view>
|
|
|
<view class="product-info--sku">{{curSku.name}}</view>
|
|
|
<!-- <view>库存:{{curSku.stock}}</view> -->
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="attr-group" v-for="(item, index) in attributeGroupList" :key="item.id">
|
|
|
<text class="attr-name">{{item.name}}</text>
|
|
|
<view class="attr-items">
|
|
|
<text class="attr-item" :class="{'attr-item__active' : i.active, 'attr-item__disabled' : i.disabled}"
|
|
|
v-for="i in item.attributes" :key="i.symbol"
|
|
|
@click="handleAttrItem(i, index)"
|
|
|
>{{i.name}}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="sku-num">
|
|
|
<view class="sku-num--single-box">
|
|
|
<template>
|
|
|
<text>数量</text>
|
|
|
<text class="sku-num--single">{{maxBuyNum}}</text>
|
|
|
</template>
|
|
|
</view>
|
|
|
<u-number-box :min="1" :max="maxBuyNum" button-size="40rpx" bgColor="#F5F6FA"
|
|
|
v-model="curBuyNum" >
|
|
|
<text slot="minus" class="cart-item--stepper-icon">-</text>
|
|
|
<text slot="plus" class="cart-item--stepper-icon">+</text>
|
|
|
</u-number-box>
|
|
|
</view>
|
|
|
<view class="footer">
|
|
|
<view class="btn-bg" v-if="mode == 1">
|
|
|
<UiButton class="btn" @click="addCart" size="max">加入购物车</UiButton>
|
|
|
<UiButton class="btn btn__buy" @click="buyNow" size="max">立即购买</UiButton>
|
|
|
</view>
|
|
|
<UiButton v-else class="btn__confirm" type="gradual" size="max" @click="confirm">确认</UiButton>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
</u-popup>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import UiButton from '@/components/UiButton.vue';
|
|
|
import {ApiPutAddCart} from '@/common/api/cart';
|
|
|
|
|
|
export default {
|
|
|
components: { UiButton },
|
|
|
props: {
|
|
|
// true 组件显示 false 组件隐藏
|
|
|
visible : {
|
|
|
type : Boolean,
|
|
|
default : false
|
|
|
},
|
|
|
// 模式 1:都显示 2:只显示购物车 3:只显示立即购买
|
|
|
mode: {
|
|
|
type: Number,
|
|
|
default: 1,
|
|
|
},
|
|
|
// 商品详情信息
|
|
|
goodsInfo: {
|
|
|
type: Object,
|
|
|
default: {},
|
|
|
},
|
|
|
// 商品sku信息
|
|
|
skuInfo : {
|
|
|
type : Array,
|
|
|
default : []
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
// 属性组数据,因为会修改数据,不能直接操作props中传入的数据
|
|
|
attributeGroupList : [],
|
|
|
// 数量
|
|
|
curBuyNum : 1,
|
|
|
};
|
|
|
},
|
|
|
watch : {
|
|
|
goodsInfo(newData){
|
|
|
if(newData.attributeGroupList){
|
|
|
this.attributeGroupList = newData.attributeGroupList;
|
|
|
// 请求数据返回后设置默认选中规格
|
|
|
if(this.skuInfo.length){
|
|
|
this.setDefaultAttr();
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
skuInfo(newData){
|
|
|
// 请求数据返回后设置默认选中规格
|
|
|
if(newData.length){
|
|
|
this.setDefaultAttr();
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
computed : {
|
|
|
/**
|
|
|
* 当前选中SKU,根据选中规格计算
|
|
|
*/
|
|
|
curSku(){
|
|
|
const skuSymbolList = this.attributeGroupList.map(item => {
|
|
|
const activeAttr = item.attributes.find(i => i.active);
|
|
|
return activeAttr ? activeAttr.symbol : ''
|
|
|
}).filter(i => i);
|
|
|
return this.skuInfo.find(i => i.attributeSymbolList === skuSymbolList.join(',')) || {};
|
|
|
},
|
|
|
/**
|
|
|
* 最大可购买数量
|
|
|
* 1、有限购则对比限购跟库存,取最小值
|
|
|
* 2、没限购取库存
|
|
|
*/
|
|
|
maxBuyNum(){
|
|
|
const singleBuyLimit = this.goodsInfo.singleBuyLimit;
|
|
|
const stock = this.curSku.stock;
|
|
|
return singleBuyLimit ? Math.min(singleBuyLimit, stock || 1) : stock;
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
/**
|
|
|
* 设置默认选中规格
|
|
|
*/
|
|
|
setDefaultAttr(){
|
|
|
const curSku = this.skuInfo.find(i => i.stock > 0);
|
|
|
this.attributeGroupList.forEach(item => {
|
|
|
for(let i of item.attributes){
|
|
|
if(curSku.attributeSymbolList.includes(i.symbol)){
|
|
|
this.$set(i,'active', true);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
this.$emit('input',this.curSku);
|
|
|
},
|
|
|
/**
|
|
|
* 点击属性项,设置选中和禁用项
|
|
|
*/
|
|
|
handleAttrItem(item, groupIndex){
|
|
|
// 禁用选项
|
|
|
if(item.disabled){
|
|
|
return false;
|
|
|
}
|
|
|
// 每次重选规格,购买数量都置为1
|
|
|
this.curBuyNum = 1;
|
|
|
|
|
|
// 把当前选项组的装先置为未选状态
|
|
|
this.attributeGroupList[groupIndex].attributes.forEach(item =>{
|
|
|
this.$set(item,'active', false);
|
|
|
});
|
|
|
// 设置当前点击选项选中
|
|
|
this.$set(item,'active', true);
|
|
|
// 找到有效SKU的symbol 有效定义:包含当前选项属性,且库存大于0的所有SKU,
|
|
|
const symbols = this.skuInfo.filter(i => i.attributeSymbolList.includes(item.symbol) && i.stock > 0)
|
|
|
.map(i => i.attributeSymbolList).join(',');
|
|
|
|
|
|
this.attributeGroupList.forEach((group, index) => {
|
|
|
if(groupIndex === index){
|
|
|
return false;
|
|
|
}
|
|
|
// 遍历其他选项组的所有属性项,对比是否在有效SKU的symbos中,在则启用,不再则禁用
|
|
|
group.attributes.forEach(item =>{
|
|
|
if(!symbols.includes(item.symbol)){
|
|
|
this.$set(item,'disabled', true);
|
|
|
}else{
|
|
|
this.$set(item,'disabled', false);
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
/**
|
|
|
* 加入购物车
|
|
|
*/
|
|
|
async addCart(){
|
|
|
const {error, result} = await ApiPutAddCart({
|
|
|
productSkuId : this.curSku.skuId,
|
|
|
productId : this.goodsInfo.id,
|
|
|
number : this.curBuyNum
|
|
|
});
|
|
|
if(error){
|
|
|
uni.$u.toast(error.message);
|
|
|
return false;
|
|
|
}
|
|
|
this.$Router.push('/cart');
|
|
|
},
|
|
|
/**
|
|
|
* 立即购买
|
|
|
*/
|
|
|
buyNow(){
|
|
|
console.log(this.curSku)
|
|
|
this.$Router.push({
|
|
|
path : '/orderSubmit',
|
|
|
query: {
|
|
|
mode : 'buyNow',
|
|
|
skuId : this.curSku.skuId,
|
|
|
num : this.curBuyNum
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
confirm(){
|
|
|
if(this.mode == 2){
|
|
|
this.addCart();
|
|
|
}
|
|
|
if(this.mode == 3){
|
|
|
this.buyNow();
|
|
|
}
|
|
|
},
|
|
|
close(){
|
|
|
this.$emit('update:visible', false)
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.sku-popup{
|
|
|
padding: 30rpx;
|
|
|
}
|
|
|
.product-info{
|
|
|
display: flex;
|
|
|
font-size: 28rpx;
|
|
|
color: #999;
|
|
|
line-height: 42rpx;
|
|
|
&--img{
|
|
|
width: 200rpx;
|
|
|
height: 200rpx;
|
|
|
margin-right: 40rpx;
|
|
|
}
|
|
|
&--price{
|
|
|
font-size: 40rpx;
|
|
|
color: #FF512B;
|
|
|
line-height: 48rpx;
|
|
|
margin-bottom: 20rpx;
|
|
|
}
|
|
|
}
|
|
|
.attr-group{
|
|
|
margin-top: 40rpx;
|
|
|
font-size: 30rpx;
|
|
|
}
|
|
|
.attr-items{
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
padding: 10rpx 0;
|
|
|
}
|
|
|
.attr-item{
|
|
|
background: #F8F8F8;
|
|
|
line-height: 70rpx;
|
|
|
border-radius: 100rpx;
|
|
|
border: 1px solid #F8F8F8;
|
|
|
color: #666;
|
|
|
display: block;
|
|
|
min-width: 158rpx;
|
|
|
max-width: 630rpx;
|
|
|
text-align: center;
|
|
|
margin: 20rpx 28rpx 0 0;
|
|
|
padding: 0 20rpx;
|
|
|
overflow: hidden;
|
|
|
text-overflow: ellipsis;
|
|
|
white-space: nowrap;
|
|
|
&__active{
|
|
|
background: #FFF3EE;
|
|
|
border-color: #FF512B;
|
|
|
color: #FF875B;
|
|
|
}
|
|
|
&__disabled{
|
|
|
color: #ccc;
|
|
|
}
|
|
|
}
|
|
|
.sku-num{
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
margin: 40rpx 0;
|
|
|
line-height: 40rpx;
|
|
|
&--single-box{
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
}
|
|
|
&--single{
|
|
|
color: #999;
|
|
|
margin-left: 10rpx;
|
|
|
font-size: 28rpx;
|
|
|
display: block;
|
|
|
height: 30rpx;
|
|
|
}
|
|
|
}
|
|
|
.footer{
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
.btn-bg{
|
|
|
background: #FFE6D9;
|
|
|
border-radius: 50rpx;
|
|
|
height: 80rpx;
|
|
|
}
|
|
|
.btn{
|
|
|
border: 0;
|
|
|
padding: 0;
|
|
|
border-radius: 0;
|
|
|
width: 340rpx;
|
|
|
font-size: 28rpx;
|
|
|
color: #FF875B;
|
|
|
&::after{
|
|
|
border: 0;
|
|
|
}
|
|
|
&__buy{
|
|
|
width: 350rpx;
|
|
|
background: url('@/static/goods/buy_max.png');
|
|
|
background-size: 350rpx;
|
|
|
color: #fff;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.btn__confirm{
|
|
|
margin: 0;
|
|
|
}
|
|
|
}
|
|
|
</style>
|