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.
shop-app/pages/goods/detail/components/SkuPopup.vue

336 lines
7.7 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.

<!--
* @Author: ch
* @Date: 2022-03-24 11:30:55
* @LastEditors: ch
* @LastEditTime: 2022-04-19 10:51:46
* @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 : []
},
// 活动状态
activityStatus : {
type : String,
default : 'noActivity'
}
},
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, index) => {
for(let i of item.attributes){
if(curSku.attributeSymbolList.includes(i.symbol)){
this.$set(i,'active', true);
this.setDisabledItem(i, index);
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);
this.setDisabledItem(item, groupIndex);
},
setDisabledItem(item, groupIndex){
// 找到有效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(){
this.$Router.push({
path : '/orderSubmit',
query: {
mode : 'buyNow',
skuId : this.curSku.skuId,
num : this.curBuyNum,
activityType : this.activityStatus === 'startActivity' ? 2 : 1
}
})
},
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: $font-size-base;
color: $color-grey4;
line-height: 42rpx;
&--img{
width: 200rpx;
height: 200rpx;
margin-right: 40rpx;
}
&--price{
font-size: 40rpx;
color: $color-yellow4;
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: $color-grey1;
line-height: 70rpx;
border-radius: 100rpx;
border: 1px solid $color-grey1;
color: $color-grey5;
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: $color-yellow4;
color: $color-yellow3;
}
&__disabled{
color: $color-grey3;
}
}
.sku-num{
display: flex;
justify-content: space-between;
margin: 40rpx 0;
line-height: 40rpx;
&--single-box{
display: flex;
align-items: center;
}
&--single{
color: $color-grey4;
margin-left: 10rpx;
font-size: $font-size-base;
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: $font-size-base;
color: $color-yellow3;
&::after{
border: 0;
}
&__buy{
width: 350rpx;
background: url('@/static/goods/buy_max.png');
background-size: 350rpx;
color: $color-grey0;
}
}
.btn__confirm{
margin: 0;
}
}
</style>