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.

592 lines
15 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.

<template>
<!-- 规格 -->
<view class="cu-modal bottom-modal" @touchmove.stop.prevent="" :class="{ show: showModal }"
@tap.stop="showModal = false" v-if="goodsInfo.sku_price">
<view class="cu-dialog" @tap.stop style="border-radius: 30rpx 30rpx 0 0;">
<view class="shop-modal page_box" :style="goodsInfo.is_sku == 0 ? 'height:700rpx' : ''">
<text class="u-iconfont uicon-close-circle-fill close-icon" @tap.stop="showModal = false"></text>
<!-- 商品卡片-->
<view class="top u-flex modal-head__box">
<image class="shop-img" :src="currentSkuPrice.image ? currentSkuPrice.image : goodsInfo.image"
mode="aspectFill"></image>
<view class=" goods-box u-flex-col u-row-between">
<view class="goods-title u-ellipsis-2">{{ goodsInfo.title }}</view>
<view class="u-flex u-row-between goods-bottom">
<view class="price-box u-flex">
<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>
<!-- 规格选项 -->
<scroll-view scroll-y class="content_box">
<view class="select-box u-flex-col u-row-left" v-for="(s, x) in skuList" :key="s.id">
<view class="type-title u-flex">{{ s.name }}</view>
<view class="tag-box u-flex u-flex-wrap">
<button class="tag u-reset-button" 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 u-flex u-row-between">
<view class="num-title">购买数量</view>
<u-number-box v-model="goodsNum" :min="1" :step="1" :max="maxStep" @plus="plus"
:long-press="false" @change="changeNum"></u-number-box>
</view>
</scroll-view>
<!-- 功能按钮 -->
<view class="btn-box foot_box u-flex u-row-between" v-if="buyType === 'cart' || buyType === 'buy'">
<button class="u-reset-button cu-btn save-btn"
v-if="(activityRules && activityRules.status === 'ing') || !goodsInfo.activity_type"
@tap="confirm">确认</button>
<button class="u-reset-button cu-btn cancel-btn"
v-if="activityRules && activityRules.status !== 'ing' && goodsInfo.activity_type"
@tap="confirm">确定</button>
</view>
<view class="btn-box foot_box u-flex u-row-between" v-else>
<button class="u-reset-button cu-btn cart-btn" @tap="confirmCart">加入购物车</button>
<button class="u-reset-button cu-btn buy-btn" @tap="confirmBuy"></button>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* 多规格组件
* @property {Object} goodsInfo - 商品数据
* @property {Boolean} value = showModal - 显隐
* @property {String} buyType - 购买方式
* @property {String} goodsType - 商品类别
* @property {String} grouponBuyType -拼团商品购买方式
* @property {Number} grouponId - 拼团ID,分享进入
* @property {Object} activityRules - 活动状态。
*/
import { mapMutations, mapActions, mapState } from 'vuex';
export default {
components: {},
data() {
return {
maxStep: 999,
skuList: [],
currentSkuPrice: {},
currentSkuArray: [],
goodsNum: 1,
confirmGoodsInfo: {},
type: this.buyType
};
},
props: {
goodsInfo: {},
activityRules: {},
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];
this.maxStep = this.skuPrice[0].stock > 999 ? 999 : this.skuPrice[0].stock;
}
},
watch: {
type(nweVal, oldVal) {
return newVal;
}
},
computed: {
skuPrice() {
return this.goodsInfo.sku_price;
},
showModal: {
get() {
return this.value;
},
set(val) {
val ? uni.hideTabBar() : uni.showTabBar();
this.$emit('input', val);
return 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(['addCartGoodsJson','addCartGoods', 'getCartList']),
jump(path, parmas) {
this.$Router.push({
path: path,
query: parmas
});
},
// 选择规格
chooseSku(pid, skuId) {
let that = this;
let isChecked = true; // 选中 or 取消选中
this.goodsNum = 1; //选择规格时数量重置为1.
this.maxStep = 999; //选择其他规格时,取消上个规格库存限制
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) {
this.changeDisabled(false);
},
// 增加
plus(e) {
if (e.value >= this.currentSkuPrice.stock) {
this.maxStep = this.currentSkuPrice.stock;
this.$u.toast('库存不足');
return;
}
if (this.goodsInfo.activity_type === 'seckill' || this.goodsInfo.activity_type === 'groupon') {
let rules = this.goodsInfo.activity.rules;
if (rules.limit_buy != 0 && e.value >= rules.limit_buy) {
this.maxStep = rules.limit_buy;
this.$u.toast('本次活动最多购买' + rules.limit_buy + '件');
return;
}
}
},
// 加入购物车确定
confirmCart() {
let that = this;
if (this.confirmSku()) {
let confirmGoodsList = {
list: [that.confirmGoodsInfo],
from: 'goods'
};
that.addCartGoodsJson(confirmGoodsList).then(res => {
console.log(res)
if (res.error.code === 200) {
that.showModal = false;
that.$u.toast(res.error.msg);
}
});
}
},
// 立即购买
confirmBuy() {
let that = this;
that.showModal = false;
if (this.confirmSku()) {
let confirmGoodsList = [];
confirmGoodsList.push(that.confirmGoodsInfo);
that.jump('/pages/order/confirm', {
goodsList: confirmGoodsList,
from: 'goods',
orderType: that.goodsType,
grouponBuyType: that.grouponBuyType,
grouponId: that.grouponId
});
}
},
// 确定
confirm() {
console.log("confirm")
if (this.confirmSku()) {
switch (this.buyType) {
case 'cart':
this.confirmCart();
break;
case 'buy':
this.confirmBuy();
break;
default:
}
}
},
// 确定规格
confirmSku() {
let that = this;
if (that.currentSkuPrice.stock == 0 || that.currentSkuPrice.stock < that.goodsNum) {
that.$u.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.$u.toast('请选择规格');
return false;
} else {
that.showModal = false;
return true;
}
}
}
}
};
</script>
<style lang="scss" scoped>
.size-box {
line-height: 82rpx;
background: #fff;
padding: 0 20rpx;
margin: 20rpx 0;
font-size: 28rpx;
.title {
color: #999;
margin-right: 20rpx;
}
}
// 规格
.shop-modal {
width: 750rpx;
height: 950rpx;
background: rgba(255, 255, 255, 1);
padding: 20rpx 20rpx 30rpx;
position: relative;
.close-icon {
font-size: 34rpx;
color: #e0e0e0;
position: absolute;
top: 20rpx;
right: 20rpx;
}
// 商品卡片
.top {
margin: 30rpx 0;
border-radius: 20rpx;
padding: 20rpx;
.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-weight: 500;
color: rgba(51, 51, 51, 1);
line-height: 42rpx;
text-align: left;
}
.goods-bottom {
width: 100%;
}
.price-box {
font-size: 36upx;
font-weight: bold;
color: #e1212b;
.unit {
font-size: 24upx;
font-weight: bold;
color: #e1212b;
}
}
.stock {
font-size: 26rpx;
color: #999;
}
}
}
// 规格选项
.select-box {
margin-bottom: 30rpx;
.type-title {
font-size: 26upx;
font-weight: 400;
margin-bottom: 20upx;
}
.tag-box {
flex-wrap: wrap;
}
.tag {
line-height: 62rpx;
background: #f4f4f4;
border-radius: 31rpx;
font-size: 28upx;
font-weight: 400;
color: #666666;
padding: 0 30upx;
margin-bottom: 20rpx;
margin-right: 10rpx;
}
.tag-active {
background: linear-gradient(90deg, #e9b461, #eecc89);
font-size: 28rpx;
font-weight: 400;
color: #ffffff;
}
.tag-disabled {
background: #f8f8f8;
color: #cacaca;
}
}
.buy-num-box {
.num-title {
font-size: 26upx;
font-weight: 400;
margin-bottom: 20upx;
}
}
}
.btn-box {
height: 100rpx;
.cu-btn {
width: 340rpx;
line-height: 70rpx;
border-radius: 35rpx;
font-size: 28rpx;
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));
}
.save-btn {
width: 710rpx;
height: 70rpx;
background: linear-gradient(90deg, rgba(233, 180, 97, 1), rgba(238, 204, 137, 1));
font-size: 28rpx;
font-weight: 500;
color: rgba(255, 255, 255, 1);
border-radius: 35rpx;
padding: 0;
}
.cancel-btn {
width: 710rpx;
height: 70rpx;
background: rgba(221, 221, 221, 1);
font-size: 28rpx;
font-weight: 500;
color: #999999;
border-radius: 35rpx;
padding: 0;
}
}
</style>