WechatOwnerService/components/vc-sku/vc-sku.vue
2020-10-28 19:07:57 +08:00

554 lines
13 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="">
<!-- 规格 -->
<view class="cu-modal sku-modal bottom-modal" style="z-index: 999;" :class="{ show: showModal }" @tap="hideModal" v-if="goodsInfo.sku_price">
<view class="cu-dialog" @tap.stop style="background: none;">
<view class="shop-modal page_box" :style="goodsInfo.is_sku == 0 ? 'height:500rpx' : ''">
<text class="cuIcon-roundclosefill" @tap="hideModal"></text>
<!-- 商品信息 -->
<view class="top x-f modal-head__box">
<image class="shop-img" :src="currentSkuPrice.image ? currentSkuPrice.image : goodsInfo.image" mode="aspectFill"></image>
<view class="y-bc goods-box">
<view class="goods-title more-t">{{ goodsInfo.title }}</view>
<view class="x-bc goods-bottom">
<view class="price-box x-f">
<view v-if="goodsType === 'score'">{{ currentSkuPrice.price_text || goodsInfo.price }}</view>
<view v-else-if="grouponBuyType === 'groupon'">
¥{{ currentSkuPrice.groupon_price || (goodsInfo.activity_type === 'groupon' ? goodsInfo.groupon_price : goodsInfo.price) }}
</view>
<view v-else>¥{{ currentSkuPrice.price || goodsInfo.price }}</view>
</view>
<text class="stock">库存{{ currentSkuPrice.stock || goodsInfo.stock }}件</text>
</view>
</view>
</view>
<!-- 选择规格 -->
<view class="content_box">
<view class="select-box y-start" v-for="(s, x) in skuList" :key="s.id">
<view class="type-title">{{ s.name }}</view>
<view class="tag-box x-f">
<button
class="tag cu-btn"
v-for="(sc, y) in s.content"
:key="sc.id"
:class="{ 'tag-active': currentSkuArray[sc.pid] == sc.id, 'tag-disabled': sc.disabled == true }"
:disabled="sc.disabled == true"
@tap="chooseSku(sc.pid, sc.id)"
>
{{ sc.name }}
</button>
</view>
</view>
<view class="buy-num-box x-bc">
<view class="num-title">购买数量</view>
<view class="num-step">
<uni-number-box
@change="changeNum"
:step="1"
:min="0"
:currentSkuPrice.sync="currentSkuPrice"
:goodsInfo="goodsInfo"
:value="goodsNum"
></uni-number-box>
</view>
</view>
</view>
<view class="btn-box foot_box x-bc" v-if="buyType === 'cart' || buyType === 'buy'"><button class="cu-btn seckill-btn" @tap="confirm">确认</button></view>
<view class="btn-box foot_box x-bc" v-else>
<button class="cu-btn cart-btn" @tap="confirmCart">加入购物车</button>
<button class="cu-btn buy-btn" @tap="confirmBuy">立即购买</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import uniNumberBox from '@/components/uni-number-box/uni-number-box.vue';
import { mapMutations, mapActions, mapState } from 'vuex';
export default {
name: 'shoproSku',
components: {
uniNumberBox
},
data() {
return {
skuList: [],
currentSkuPrice: {},
currentSkuArray: [],
goodsNum: 1,
confirmGoodsInfo: {},
type: this.buyType
};
},
props: {
goodsInfo: {},
value: {},
buyType: {
type: String,
default: 'sku'
},
goodsType: {
type: String,
default: 'goods'
},
grouponBuyType: {
type: String,
default: 'alone'
},
grouponId: {
//参加拼团的时候传入当前团id;
type: Number,
default: 0
}
},
created() {
this.skuList = this.goodsInfo.sku;
this.changeDisabled(false);
},
mounted() {
// 单规格选项
if (!this.goodsInfo.is_sku) {
this.currentSkuPrice = this.skuPrice[0];
}
},
watch: {
type(nweVal, oldVal) {
return newVal;
}
},
computed: {
skuPrice() {
return this.goodsInfo.sku_price;
},
showModal: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
},
currentSkuText() {
let that = this;
let str = '';
let currentSkuArray = this.currentSkuArray;
currentSkuArray.forEach(v => {
that.skuList.forEach(s => {
s.content.forEach(u => {
if (u.id === v) {
str += ' ' + u.name;
}
});
});
});
that.$emit('getSkuText', str);
return str;
}
},
methods: {
...mapActions(['addCartGoods', 'getCartList']),
jump(path, parmas) {
this.$Router.push({
path: path,
query: parmas
});
},
// 选择规格
chooseSku(pid, skuId) {
let that = this;
let isChecked = true; // 选中 or 取消选中
if (that.currentSkuArray[pid] != undefined && that.currentSkuArray[pid] == skuId) {
// 点击已被选中的,删除并填充 ''
isChecked = false;
that.currentSkuArray.splice(pid, 1, '');
} else {
// 选中
that.$set(that.currentSkuArray, pid, skuId);
}
let chooseSkuId = []; // 选中的规格大类
that.currentSkuArray.forEach(sku => {
if (sku != '') {
// sku 为空是反选 填充的
chooseSkuId.push(sku);
}
});
// 当前所选规格下,所有可以选择的 skuPric
let newPrice = this.getCanUseSkuPrice();
// 判断所有规格大类是否选择完成
if (chooseSkuId.length == that.skuList.length && newPrice.length) {
that.currentSkuPrice = newPrice[0];
} else {
that.currentSkuPrice = {};
}
// 改变规格项禁用状态
this.changeDisabled(isChecked, pid, skuId);
},
// 改变禁用状态
changeDisabled(isChecked = false, pid = 0, skuId = 0) {
let newPrice = []; // 所有可以选择的 skuPrice
if (isChecked) {
// 选中规格
// 当前点击选中规格下的 所有可用 skuPrice
for (let price of this.skuPrice) {
if (price.stock <= 0) {
// this.goodsNum 不判断是否大于当前选择数量,在 uni-number-box 判断,并且 取 stock 和 goods_num 的小值
continue;
}
if (price.goods_sku_id_arr.indexOf(skuId.toString()) >= 0) {
newPrice.push(price);
}
}
} else {
// 取消选择规格
// 当前所选规格下,所有可以选择的 skuPric
newPrice = this.getCanUseSkuPrice();
}
// 所有存在并且有库存未选择的规格项 的 子项 id
let noChooseSkuIds = [];
for (let price of newPrice) {
noChooseSkuIds = noChooseSkuIds.concat(price.goods_sku_id_arr);
}
// 去重
noChooseSkuIds = Array.from(new Set(noChooseSkuIds));
if (isChecked) {
// 去除当前选中的规格项
let index = noChooseSkuIds.indexOf(skuId.toString());
noChooseSkuIds.splice(index, 1);
} else {
// 循环去除当前已选择的规格项
this.currentSkuArray.forEach(sku => {
if (sku.toString() != '') {
// sku 为空是反选 填充的
let index = noChooseSkuIds.indexOf(sku.toString());
if (index >= 0) {
// sku 存在于 noChooseSkuIds
noChooseSkuIds.splice(index, 1);
}
}
});
}
// 当前已选择的规格大类
let chooseSkuKey = [];
if (!isChecked) {
// 当前已选择的规格大类
this.currentSkuArray.forEach((sku, key) => {
if (sku != '') {
// sku 为空是反选 填充的
chooseSkuKey.push(key);
}
});
} else {
// 当前点击选择的规格大类
chooseSkuKey = [pid];
}
for (let i in this.skuList) {
// 当前点击的规格,或者取消选择时候 已选中的规格 不进行处理
if (chooseSkuKey.indexOf(this.skuList[i]['id']) >= 0) {
continue;
}
for (let j in this.skuList[i]['content']) {
// 如果当前规格项 id 不存在于有库存的规格项中,则禁用
if (noChooseSkuIds.indexOf(this.skuList[i]['content'][j]['id'].toString()) >= 0) {
this.skuList[i]['content'][j]['disabled'] = false;
} else {
this.skuList[i]['content'][j]['disabled'] = true;
}
}
}
},
// 当前所选规格下,获取所有有库存的 skuPrice
getCanUseSkuPrice() {
let newPrice = [];
for (let price of this.skuPrice) {
if (price.stock <= 0) {
// || price.stock < this.goodsNum 不判断是否大于当前选择数量,在 uni-number-box 判断,并且 取 stock 和 goods_num 的小值
continue;
}
var isOk = true;
this.currentSkuArray.forEach(sku => {
// sku 不为空,并且,这个 条 skuPrice 没有被选中,则排除
if (sku.toString() != '' && price.goods_sku_id_arr.indexOf(sku.toString()) < 0) {
isOk = false;
}
});
if (isOk) {
newPrice.push(price);
}
}
return newPrice;
},
// 数量
changeNum(e) {
let that = this;
this.goodsNum = +e;
this.changeDisabled(false);
},
// 弹窗显示隐藏
showSkuModal() {
this.$emit('changeType', 'sku');
this.showModal = true;
},
hideModal() {
this.showModal = false;
},
// 加入购物车确定
confirmCart() {
let that = this;
if (this.confirmSku()) {
let confirmGoodsList = {
list: [that.confirmGoodsInfo],
from: 'goods'
};
that.addCartGoods(confirmGoodsList).then(res => {
if (res.code === 1) {
that.$tools.toast(res.msg);
}
});
}
},
// 立即购买
confirmBuy() {
let that = this;
if (this.confirmSku()) {
let confirmGoodsList = [];
confirmGoodsList.push(that.confirmGoodsInfo);
that.jump('/pages/order/confirm', {
goodsList: JSON.stringify(confirmGoodsList),
from: 'goods',
orderType: that.goodsType,
grouponBuyType: that.grouponBuyType,
grouponId: that.grouponId
});
}
},
// 确定
confirm() {
this.confirmSku();
switch (this.buyType) {
case 'cart':
this.confirmCart();
break;
case 'buy':
this.confirmBuy();
break;
default:
}
},
// 确定规格
confirmSku() {
let that = this;
console.log(that.currentSkuPrice.stock, that.goodsNum);
if (that.currentSkuPrice.stock == 0 || that.currentSkuPrice.stock < that.goodsNum) {
that.$tools.toast('库存不足');
that.showModal = false;
return false;
} else {
that.currentSkuPrice.goods_num = that.goodsNum;
that.confirmGoodsInfo = {
goods_id: that.currentSkuPrice.goods_id,
goods_num: that.currentSkuPrice.goods_num,
sku_price_id: that.currentSkuPrice.id,
goods_price: that.currentSkuPrice.price
};
if (!that.confirmGoodsInfo.sku_price_id) {
that.$tools.toast('请选择规格');
return false;
} else {
that.showModal = false;
return true;
}
}
}
}
};
</script>
<style lang="scss">
.size-box {
line-height: 82rpx;
background: #fff;
padding: 0 20rpx;
margin: 20rpx 0;
font-size: 28rpx;
.title {
color: #999;
margin-right: 20rpx;
}
.cuIcon-right {
color: #bfbfbf;
font-size: 36rpx;
}
}
// 规格
.shop-modal {
width: 750upx;
height: 950rpx;
background: rgba(255, 255, 255, 1);
border-radius: 30rpx 30rpx 0 0 !important;
padding: 60upx 20upx 30rpx;
.cuIcon-roundclosefill {
font-size: 34rpx;
color: #e0e0e0;
position: absolute;
top: 20rpx;
right: 20rpx;
}
.top {
margin-bottom: 50upx;
.shop-img {
width: 160upx;
height: 160upx;
border-radius: 6upx;
margin-right: 30upx;
background: #ccc;
}
.goods-box {
height: 160upx;
width: 490rpx;
align-items: flex-start;
.goods-title {
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(51, 51, 51, 1);
line-height: 42rpx;
text-align: left;
}
.goods-bottom {
width: 100%;
}
.price-box {
font-size: 36upx;
font-family: PingFang SC;
font-weight: bold;
color: #e1212b;
.unit {
font-size: 24upx;
font-family: PingFang SC;
font-weight: bold;
color: #e1212b;
}
}
.stock {
font-size: 26rpx;
color: #999;
}
}
}
.select-box {
margin-bottom: 25upx;
.type-title {
font-size: 26upx;
font-family: PingFang SC;
font-weight: 400;
margin-bottom: 20upx;
}
.tag-box {
flex-wrap: wrap;
}
.tag {
line-height: 62rpx;
background: rgba(#ddd, 0.8);
border-radius: 31rpx;
font-size: 28upx;
font-family: PingFang SC;
font-weight: 400;
color: #999;
padding: 0 30upx;
margin-bottom: 20rpx;
margin-right: 10rpx;
}
.tag-active {
background: linear-gradient(90deg, rgba(233, 180, 97, 1), rgba(238, 204, 137, 1));
color: rgba(#fff, 0.9);
}
.tag-disabled {
background: #f5f5f5;
}
}
.buy-num-box {
.num-title {
font-size: 26upx;
font-family: PingFang SC;
font-weight: 400;
margin-bottom: 20upx;
}
}
}
.btn-box {
height: 100rpx;
.cu-btn {
width: 340rpx;
height: 70rpx;
border-radius: 35rpx;
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
padding: 0;
}
.cart-btn {
background: linear-gradient(90deg, rgba(103, 104, 105, 1), rgba(82, 82, 82, 1));
box-shadow: 0px 2rpx 5rpx 0px rgba(102, 103, 104, 0.46);
}
.buy-btn {
background: linear-gradient(90deg, rgba(233, 180, 97, 1), rgba(238, 204, 137, 1));
box-shadow: 0px 7rpx 6rpx 0px rgba(229, 138, 0, 0.22);
}
.seckill-btn {
width: 710rpx;
height: 70rpx;
background: linear-gradient(90deg, rgba(233, 180, 97, 1), rgba(238, 204, 137, 1));
box-shadow: 0px 7rpx 6rpx 0px rgba(229, 138, 0, 0.22);
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
border-radius: 35rpx;
padding: 0;
}
}
</style>