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.

811 lines
17 KiB

<template>
<view class="cart" :class="['theme', themeObj.name]" style="background-color: #5f6f7;min-height: 100vh;">
<!-- #ifdef APP-PLUS -->
<div class="status-bar" :style="{height:statusBarHeight+'px'}"></div>
<!-- #endif -->
<block v-if="cartList.length > 0 ">
<view class="clearCart" :style="{top:showHeader==true?statusBarHeight+'px':'0upx'}"
@click="clearInvalid">购物车</view>
<!-- <view class="clearCart" :style="{color:colors,top:showHeader==true?statusBarHeight+'px':'0upx'}" @click="clearInvalid">清空失效商品</view> -->
<view class="cart_box">
<view v-for="(item, index) in cartList" :key="index" class="cart_list"
@longpress.stop="onshowDel(item,index)"
@touchend="ontouchend">
<view class="checkbox-box" @tap="setCurrent(item,index)">
<view class="checkbox text-xxl" style="border: 0px;" v-if="item.status !== 1 ">
<text class="cuIcon-roundcheckfill "
:class="item.current == true ? 'text-green':'text-gray'" ></text>
</view>
<view class="checkbox" style="border-color:#ccc" v-else>
<view></view>
</view>
</view>
<view class="cover" @tap="jumpDetails(item,index)">
<image :src="item.selectSku.url" mode="aspectFill" v-if="item.selectSku"></image>
<image :src="item.url" mode="aspectFill" v-else></image>
<text class="masks"></text>
<text class="mask" v-if="item.status == 1">已失效</text>
</view>
<view class="right">
<view class="goods_name" @tap="jumpDetails(item,index)">
{{item.goodsName}}
</view>
<view class="sku">
<block v-if="item._selectedSku.length">
<text style="margin-left: 10upx;" v-for="_it in item._selectedSku" key="it">{{
_it.tagname
}}</text>
</block>
<block v-else>
<text>暂无规格</text>
</block>
</view>
<view class="numbers">
<text class="price" v-if="item.selectSku">
¥{{ item.selectSku.money }}
</text>
<text class="price" v-else>
¥{{(Number(item.price) * item.number).toFixed(4)}}
</text>
<view class="right_btn">
<view class="sub" @tap="onChangeNum(item,index, 'sub')" :style="'color:' + (item.num == 1?'#ccc':'')">-</view>
<view class="input">
<input
v-model="item.number"
type="number"
@blur="handlerChangeNum(item, index,'blur')"
@input="handlerChangeNum(item, index, 'input')"
max="99999"></input>
</view>
<view class="add" @tap="onChangeNum(item,index, 'add')">+</view>
</view>
</view>
</view>
<!-- 删除的遮罩层 长按触发 -->
<view class="del_mask" v-if="current == index" :style="'z-index:' + (current == index ?'99':'-21')" @tap="oncencal">
</view>
<view class="dask_del" :style="'opacity:' + (current == index ?'1':'0') + ';z-index:' + (current == index ?'100':'-20')+';left:'+(current == index?'0':'-100%')">
<text class="del" @tap="delItem(item,index)">删除</text>
<text class="cencal" @tap="oncencal">取消</text>
</view>
</view>
<view class="daodi" v-if="cartList.length >= 5">—— 到底啦 ——</view>
</view>
<!-- 全选 -->
<view class="bottom_all" :style="{marginBottom: bottomShow}">
<view class="left">
<view class="checkbox-box" @tap="setAllCurrent">
<view class="checkbox text-xxl" :style="'border-color:' + colors">
<view class="cuIcon-roundcheckfill "
:class="allCurrent ? 'text-green':'text-gray'" ></view>
</view>
<view class="text" style="margin-left: 8upx;">全选</view>
</view>
<view class="delAll" @click="delectAll" v-if="allCurrent == true">删除</view>
</view>
<view class="rights">
<view class="jiesuan" @click="settlement">结算({{sum}})</view>
<view class="sum">合计:<text>¥{{sumPrice || 0}}</text></view>
</view>
</view>
</block>
<!-- 如果购物车没有数据 -->
<view class="nocart" v-if="cartList.length == 0">
<text class="iconfont icon-gouwuche1" ></text>
<view>空空如也,<text class="empty" @tap="onStroll">便 ></text></view>
</view>
</view>
</template>
<script>
var app = getApp();
import {
setGoodsDetails,getCartNumber,
getCartDetails_goods_id,
getCart,
setGoodsData,
resetCart,
removeCart,
getToken
} from '@/utils/auth.js'
import {resetNum, setTabBarBadge, debounce} from '@/utils/util.js'
export default {
data() {
return {
colors: '',
statusBarHeight:20,
cartList: [],
current: 99999,
allCurrent: false,
sum: 0,
sumPrice: 0,
lock: false,
bottomShow: '',
showHeader: false,
stock: 99999,
themeObj: app.globalData.themeObj
};
},
components: {},
props: {},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
// #ifdef MP
this.bottomShow = 0
// #endif
// #ifdef H5
this.bottomShow = '50px'
// #endif
// #ifdef APP-PLUS
this.showHeader = true //在APP端对样式进行调整
// #endif
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
if (!getToken()) {
uni.navigateTo({
url: '/pages/login/index1'
})
return
}
const cartList = getCart() || []
this.themeObj = app.globalData.themeObj
this.setData({
colors: app.globalData.newColor,
current: '99999',
cartList,
allCurrent: false,
sum: 0,
sumPrice: 0
});
setTabBarBadge(cartList.length)
this.setAllCurrent(false)
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {},
methods: {
setCurrent(item, index) {
if (item.status == 1) { //如果商品的status 状态为1 说明已经失效
return
}
//单选
let cartList = this.cartList;
let dataList = this.cartList[index];
dataList.current = !dataList.current;
let datas = 'cartList[' + index + ']';
let currentAll = false;
let count = [];
cartList.forEach(e => {
if (e.current == true) {
count.push(e);
}
});
if (count.length == cartList.length) { //判断是否全选
currentAll = true;
}
this.setData({
[datas]: dataList,
allCurrent: currentAll,
});
resetCart(cartList)
this.getSumprice()
},
onshowDel(item, index) {
//显示删除
this.setData({
current: index,
lock: true
});
return;
},
delItem(item, index) {
//点击删除 模拟删除本地数据
this.cartList.splice(index, 1)
this.setData({
current: '9999',
lock: false
})
uni.showToast({
title: '删除成功',
icon: 'none'
})
this.getSumprice() //计算总价
resetCart(this.cartList)
setTabBarBadge(this.cartList.length)
},
oncencal() {
//点击取消
this.setData({
current: '99999'
});
},
handlerChangeNum(item, index, type = 'input') {
const total = Math.floor(Number(item.number))
item.number = total < 1 ? 1 : total > this.stock ? this.stock : total
if (type === 'blur') {
if (!item.number) {
item.number = 1
}
resetCart(this.cartList)
this.getSumprice()
return
}
debounce(() => {
if (item.number >= this.stock) {
item.number = this.stock
}
if (item.number != '' && item.number < 1) {
item.number = 1
}
}, 1)
},
onChangeNum(item, index, type = 'add') {
if (item.status == 1) { //已失效商品不做操作
return
}
const total = Math.floor(Number(item.number))
let num = total < 1 ? 1 : total > this.stock ? this.stock : total
if (type === 'add') {
//增加
if (num >= this.stock) {
item.number = this.stock
return
}
item.number = num + 1
} else {
if (num <= 1) {
return
}
item.number = num - 1
}
resetCart(this.cartList)
this.getSumprice() //计算总价
},
setAllCurrent(isClick = true) {
//设置全选
let dataList = this.cartList;
let allCurrent = this.allCurrent;
let sumPrice = 0;
// 先判断是否存在失效商品 必须清楚失效商品之后才能继续全选
const isOff = dataList.some(v => v.status == 1)
if (isOff) {
uni.showToast({
title: '存在失效商品',
icon: 'none'
})
return
}
if (isClick) {
dataList.forEach(element => { //反选
element.current = !allCurrent;
});
allCurrent = !allCurrent;
} else {
allCurrent = dataList.every(v => v.current)
}
this.cartList = dataList
this.allCurrent = allCurrent
this.getSumprice()
},
getSumprice() { //计算总价
let sumPrice = 0;
const list = this.cartList.filter(v => v.current)
list.forEach(v => {
if (v.selectSku) {
sumPrice += resetNum(v.price * v.number)
} else {
sumPrice += resetNum(v.price * v.number)
}
})
this.sum = list.length
this.sumPrice = resetNum(sumPrice, 'end')
},
ontouchend() { //隐藏删除弹窗
console.log('触发了touch');
if (this.lock) {
setTimeout(() => {
this.setData({
lock: false
});
}, 100);
}
},
clearInvalid() { //模拟清空失效商品 根据商品的status值来判断商品状态
this.cartList.forEach((e, index) => {
if (e.status == 1) {
this.cartList.splice(index, 1)
}
e.current = false
})
uni.showToast({
title: '清空成功~',
icon: 'none'
})
setTabBarBadge(this.cartList.length)
},
delectAll() { //模拟删除所有商品
this.cartList = []
removeCart()
setTabBarBadge(this.cartList.length)
},
jumpDetails(item, index) {
uni.navigateTo({
url: '/pages/views/goods/goodsDetails?id=' + item.id
});
},
settlement() { //结算
if (this.sum == 0) {
this.$toast('您还没选择商品')
return
}
// 计算出被选中的数据
uni.showLoading({
title: '提交中...'
})
let arr = []
this.cartList.forEach(e => {
if (e.current == true) {
arr.push(e)
}
})
setGoodsData(arr) //存储商品信息去支付
setTimeout(() => {
uni.hideLoading()
uni.navigateTo({
url: '/pages/views/order/confirmOrder'
})
}, 1000)
},
onStroll() { //随便逛逛
uni.switchTab({
url: '/pages/views/tabBar/category'
});
}
}
};
</script>
<style lang="scss" scoped>
.cart {
padding: 10rpx 4%;
background-color: #F5F6F7;
}
.clearCart {
height: 80rpx;
font-size: 40rpx;
text-align: left;
line-height: 80rpx;
position: fixed;
left: 0;
width: 100vw;
padding: 0 4%;
background-color: #FFFFFF;
z-index: 100;
letter-spacing: 1px;
}
.cart_box {
margin-top: 80rpx;
padding-bottom: 100rpx;
}
.cart_list {
width: 92vw;
height: calc(22vw + 34rpx);
border-radius: 12rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, .1);
overflow: hidden;
border: 0;
display: flex;
align-items: center;
position: relative;
margin-bottom: 20rpx;
background-color: #FFFFFF;
}
.cart_list .checkbox-box {
padding-left: 16rpx;
flex-shrink: 0;
height: 22vw;
margin-right: 16rpx;
align-items: center;
position: relative;
width: 50rpx;
}
.cart_list .checkbox-box .checkbox {
width: 28rpx;
height: 28rpx;
border-radius: 100%;
border: solid 1rpx;
position: absolute;
top: 50%;
left: 20rpx;
display: flex;
align-items: center;
justify-content: center;
transform: translateY(-50%);
}
.cart_list .checkbox-box .checkbox .on {
width: 20rpx;
height: 20rpx;
border-radius: 100%;
align-items: center;
}
.cart_list .cover {
width: 22vw;
height: 22vw;
flex-shrink: 0;
margin-left: 10rpx;
border-radius: 8rpx;
overflow: hidden;
margin-right: 10rpx;
position: relative;
}
.cart_list .cover .mask {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .6);
position: absolute;
top: 0;
left: 0;
text-align: center;
color: #ddd;
font-size: 24upx;
line-height: 22vw;
}
.cart_list .cover .masks {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.cart_list .cover image {
width: 100%;
height: 100%;
display: block;
}
.daodi {
text-align: center;
font-size: 24rpx;
color: #ccc;
margin-top: 30rpx;
}
.right {
height: 22vw;
width: 100%;
/* overflow: hidden; */
display: flex;
flex-wrap: wrap;
padding-right: 15rpx;
position: relative;
}
.right .goods_name {
width: 100%;
font-size: 24rpx;
line-height: 34rpx;
max-height: 68rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.sku {
font-size: 22rpx;
background-color: #f3f3f3;
border-radius: 10rpx;
height: 40rpx;
line-height: 40rpx;
padding: 0 10rpx;
color: #a7a7a7;
margin-bottom: 40rpx;
}
.numbers {
position: absolute;
width: 100%;
overflow: hidden;
display: flex;
justify-content: space-between;
align-items: flex-end;
height: 50rpx;
bottom: -5rpx;
}
.numbers .price {
font-size: 30rpx;
line-height: 50rpx;
color: $mycolor;
}
.numbers .right_btn {
display: flex;
justify-content: center;
align-items: flex-end;
margin-right: 20rpx;
}
.right_btn .sub {
width: 40rpx;
height: 40rpx;
font-size: 40rpx;
background-color: #f3f3f3;
border-radius: 4rpx;
text-align: center;
line-height: 40rpx;
}
.right_btn .sub:active {
background-color: #f8f8f8;
}
.right_btn .input {
width: 100upx;
height: 50rpx;
margin: 0 8rpx;
background-color: #f3f3f3;
}
.right_btn .input input {
width: 100%;
height: 50rpx;
text-align: center;
// display: flex;
// font-size: 22rpx;
// text-align: center;
// align-items: center;
// justify-content: center;
color: $mycolor;
}
.right_btn .add {
width: 40rpx;
height: 40rpx;
font-size: 40rpx;
background-color: #f3f3f3;
border-radius: 4rpx;
text-align: center;
line-height: 40rpx;
}
.right_btn .add:active {
background-color: #f8f8f8;
}
.del_mask {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: -21;
}
.dask_del {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, .5);
z-index: -20;
display: flex;
align-items: center;
opacity: 0;
transition: all 0.3s;
}
.dask_del .del,
.cencal {
width: 100rpx;
height: 100rpx;
display: flex;
justify-content: center;
line-height: 100rpx;
border-radius: 100%;
text-align: center;
font-size: 24rpx;
background: linear-gradient(#FF5D39, #FFAF48);
color: #ffffff;
font-weight: 500;
margin: 0 auto;
}
.dask_del text:active {
opacity: 0.9;
}
.cencal {
background: linear-gradient(#FFE846, #FFCD43);
}
.bottom_all {
height: 100rpx;
width: 100%;
padding: 0 2%;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
bottom: 0;
left: 0;
background-color: #fdfdfd;
z-index: 11;
border-top: 1upx solid #F8F8F8;
}
.bottom_all .left {
// float: left;
width: 40vw;
font-size: 24rpx;
position: relative;
}
.bottom_all .left .delAll {
height: 40rpx;
border-radius: 20rpx;
font-size: 22rpx;
line-height: 38rpx;
border: solid 1rpx;
text-align: center;
width: 92rpx;
position: absolute;
right: 50rpx;
top: 50%;
transform: translateY(-50%);
}
.bottom_all .left .text {
position: absolute;
left: 60rpx;
top: 50%;
transform: translateY(-52%);
}
.bottom_all .checkbox-box {
padding-left: 16rpx;
flex-shrink: 0;
height: 100rpx;
margin-right: 16rpx;
align-items: center;
position: relative;
}
.bottom_all .checkbox-box .checkbox {
width: 40rpx;
height: 40rpx;
border-radius: 100%;
border: solid 1rpx;
position: absolute;
top: 50%;
left: 20rpx;
display: flex;
align-items: center;
justify-content: center;
transform: translateY(-50%);
}
.bottom_all .checkbox-box .checkbox .on {
// width: 20rpx;
// height: 20rpx;
border-radius: 100%;
align-items: center;
}
.bottom_all .rights {
// float: right;
width: 56vw;
// line-height: 100rpx;
font-size: 24rpx;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.bottom_all .rights view {
// float: right;
}
.bottom_all .rights .sum {
font-weight: bold;
// margin-right: 20rpx;
font-size: 20upx;
}
.bottom_all .rights .jiesuan {
padding: 0 22rpx;
border-radius: 24rpx;
background-color: pink;
height: 50rpx;
line-height: 50rpx;
color: #ffffff;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
width: 150upx;
// margin-top: 28rpx;
// margin-left: 40rpx;
}
/* 购物车为空的样式} */
.nocart {
text-align: center;
margin-top: 30vh;
}
.nocart .iconfont {
font-size: 80rpx;
text-align: center;
}
.nocart view {
height: 40rpx;
line-height: 40rpx;
font-size: 24rpx;
color: #999;
margin-top: 20rpx;
}
</style>