<template> <view class="container"> <!-- 空白页 --> <view v-if="!hasLogin || empty === true" class="empty"> <image src="/static/error/emptyCart.png" class="emptyImg" mode="aspectFit"></image> <view v-if="hasLogin" class="empty-tips"> 空空如也 <navigator class="navigator" v-if="hasLogin" url="../index/index" open-type="switchTab">随便逛逛> </navigator> </view> <view v-else class="empty-tips"> 空空如也 <view class="navigator" @click="navToLogin">去登陆></view> </view> </view> <view v-else> <!-- 列表 --> <view class="cart-list"> <block v-for="(item, index) in cartList" :key="item.id"> <view class="cart-item" :class="{ 'b-b': index !== cartList.length - 1 }"> <view class="flex padding-r-20" @click="item.checked=!item.checked"> <image v-if='item.checked' class="checkedGoods" src="../../static/icon/addressIconXz.png" mode="scaleToFill"> </image> <view v-else class="icon-checked-box"> </view> </view> <image class="image-wrapper" :src="item.productInfo.image" :class="[item.loaded]" mode="aspectFill" lazy-load @load="onImageLoad('cartList', index)" @error="onImageError('cartList', index)"></image> <view class="item-right"> <view class="clamp title">{{ item.productInfo.store_name }}</view> <view class="attr">{{ item.productInfo.attrInfo.suk }}</view> <view class="flex"> <text class="price">¥{{ item.productInfo.price }}</text> <uni-number-box class="step" :min="1" :max="item.productInfo.stock" :value="item.cart_num > item.productInfo.stock ? item.productInfo.stock : item.cart_num" :isMax="item.cart_num >= item.productInfo.stock ? true : false" :isMin="item.cart_num === 1" :index="index" @eventChange="numberChange"> </uni-number-box> </view> <view class="server" v-if="item.day>0"> (服务费:{{item.day_deducted}} 服务天数:{{item.day}}) </view> </view> <image class="del-btn" src="../../static/icon/goodsExit.png" @click="deleteCartItem(index)" mode="scaleToFill"></image> </view> </block> </view> <!-- 底部菜单栏 --> <view class="action-section"> <view class="flex leftBox"> <view class="checkbox" @click="check('all')"> <image class="icon-checked-box icon-checked" v-if='allChecked' src="../../static/icon/addressIconXz.png" mode="scaleToFill"></image> <view v-else class="icon-checked-box"></view> </view> <view class="margin-l-20"> 全选 </view> </view> <view class="total-box"> <view class="font-size-base"> <text>合计:</text> <text class="price">¥{{ total }}</text> </view> <view class="coupon"> 共{{checkedNum}}件商品 </view> </view> <button type="primary" class="no-border confirm-btn" @click="createOrder">立即购买</button> </view> </view> </view> </template> <script> import { getCartList, getCartNum, cartDel } from '@/api/user.js'; import { mapState } from 'vuex'; import { saveUrl, interceptor } from '@/utils/loginUtils.js'; export default { data() { return { total: 0, //总价格 allChecked: false, //全选状态 true|false empty: false, //空白页现实 true|false cartList: [] }; }, onShow() { uni.setTabBarStyle({ backgroundColor: '#FFFFFF' }) // 只有登录时才加载数据 if (this.hasLogin) { this.loadData(); } }, watch: { //显示空白页 cartList(e) { let empty = e.length === 0 ? true : false; if (this.empty !== empty) { this.empty = empty; } } }, computed: { ...mapState('user', ['hasLogin']), ...mapState('shop', ['shopDetail']), checkedNum() { let num = 0; for (var i = 0; i < this.cartList.length; i++) { if (this.cartList[i].checked) { num++ } } return num }, }, methods: { //请求数据 async loadData() { let obj = this; getCartList({ store_id:obj.shopDetail.id }) .then(function(e) { // 获取当前购物车物品增加数量 let nub = obj.cartList.length; // 获取之前对象数组 let aArray = obj.cartList.reverse(); // 获取返回数据对象数组 let bArray = e.data.valid.reverse(); obj.cartList = bArray .map((item, ind) => { // 设置返回数据默认为勾选状态 item.checked = true; // 获取相同数组之前对象的数据 let carlist = aArray[ind]; // 判断之前是否已经加载完毕 if (carlist && carlist.loaded == 'loaded') { item.loaded = 'loaded'; } return item; }) .reverse(); obj.calcTotal(); //计算总价 }) .catch(function(e) { console.log(e); }); }, //监听image加载完成 onImageLoad(key, index) { // 修改载入完成后图片class样式 this.$set(this[key][index], 'loaded', 'loaded'); }, //监听image加载失败 onImageError(key, index) { this[key][index].image = '/static/error/errorImage.jpg'; }, // 跳转到登录页 navToLogin() { // 保存地址 saveUrl(); // 登录拦截 interceptor(); }, //选中状态处理 check(type, index) { if (type === 'item') { this.cartList[index].checked = !this.cartList[index].checked; } else { const checked = !this.allChecked; const list = this.cartList; list.forEach(item => { item.checked = checked; }); this.allChecked = checked; } this.calcTotal(type); }, //数量 numberChange(data) { let arr = this.cartList[data.index]; arr.cart_num = data.number; getCartNum({ id: arr.id, number: data.number }) .then(e => { console.log(e); }) .catch(function(e) { console.log(e); }); this.calcTotal(); }, //删除 deleteCartItem(index) { let list = this.cartList; let row = list[index]; let id = row.id; uni.showModal({ title: '提示', content: '是否删除'+row.productInfo.store_name, success: res => { if(res.confirm){ cartDel({ ids: id }); this.cartList.splice(index, 1); uni.hideLoading(); this.calcTotal(); } } }); }, //清空 // clearCart() { // uni.showModal({ // content: '清空购物车?', // success: e => { // if (e.confirm) { // let st = this.cartList.map(e => { // return e.id; // }); // cartDel({ // ids: st.join(',') // }).then(e => { // console.log(e); // }); // this.cartList = []; // } // } // }); // }, //计算总价 calcTotal() { let list = this.cartList; if (list.length === 0) { this.empty = true; return; } let total = 0; let checked = true; list.forEach(item => { if (item.checked === true) { total += item.productInfo.price * item.cart_num; } else if (checked === true) { checked = false; } }); this.allChecked = checked; this.total = Number(total.toFixed(2)); }, //创建订单 createOrder() { let list = this.cartList; let goodsData = []; list.forEach(item => { if (item.checked) { goodsData.push(item.id); } }); uni.navigateTo({ url: '/pages/order/createOrder?id=' + goodsData.join(',') }); } } }; </script> <style lang="scss"> .container { padding-bottom: 134rpx; background-color: $page-color-base; /* #ifdef MP-WEIXIN || H5 */ padding-top: 30rpx; /* #endif */ /* #ifdef APP */ padding-top: var(--status-bar-height); /* #endif */ /* 空白页 */ .empty { position: fixed; left: 0; top: 0; width: 100%; height: 100vh; padding-bottom: 100rpx; display: flex; justify-content: center; flex-direction: column; align-items: center; background: #fff; .emptyImg { width: 300rpx; height: 250rpx; margin-bottom: 30rpx; } .empty-tips { display: flex; font-size: $font-sm + 2rpx; color: $font-color-disabled; .navigator { color: $uni-color-primary; margin-left: 16rpx; } } } } /* 购物车列表项 */ .cart-list { padding: 0 30rpx; } .cart-item { display: flex; position: relative; padding: 20rpx; background-color: #FFFFFF; margin-bottom: 20rpx; border-radius: 20rpx; .icon-checked-box { width: 37rpx; height: 37rpx; z-index: 5; border: 1px solid $font-color-light; border-radius: 99rpx; } .checkedGoods { width: 37rpx; height: 37rpx; } .image-wrapper { width: 170rpx; height: 170rpx; flex-shrink: 0; position: relative; border-radius: 20rpx; } .checkbox { position: absolute; left: -16rpx; top: -16rpx; z-index: 8; font-size: 44rpx; line-height: 1; padding: 4rpx; color: $font-color-disabled; background: #fff; border-radius: 50px; } .item-right { overflow: hidden; position: relative; padding-left: 30rpx; flex-grow: 1; .title, .price { font-size: $font-base; color: $font-color-dark; } .attr { font-size: 24rpx; color: $font-color-light; height: 40rpx; line-height: 40rpx; } .server { font-size: 24rpx; color: $font-color-light; margin-top: 10rpx; } .price { font-size: 30rpx; color: $color-green; } } .del-btn { flex-shrink: 0; height: 40rpx; width: 40rpx; } } /* 底部栏 */ .action-section { /* #ifdef H5 */ margin-bottom: 100rpx; /* #endif */ position: fixed; left: 0rpx; bottom: 0rpx; z-index: 95; display: flex; align-items: center; width: 750rpx; height: 100rpx; padding: 0 30rpx; background: rgba(255, 255, 255, 0.9); .leftBox { padding-right: 30rpx; border-right: 1px solid $font-color-disabled; } .checkbox { line-height: 1; font-size: 30rpx; .icon-checked-box { width: 37rpx; height: 37rpx; z-index: 5; border: 1px solid $font-color-light; border-radius: 99rpx; } .icon-checked { border: none; color: $base-color; } } .clear-btn { position: absolute; left: 26rpx; top: 0; z-index: 4; width: 0; height: 52rpx; line-height: 52rpx; padding-left: 38rpx; font-size: $font-base; color: #fff; background: $font-color-disabled; border-radius: 0 50px 50px 0; opacity: 0; transition: 0.2s; &.show { opacity: 1; width: 120rpx; } } .total-box { flex-grow: 1; padding-left: 30rpx; font-size: 30rpx; .price { color: $color-green; } .coupon { font-size: 24rpx; color: $font-color-light; } } .confirm-btn { padding: 0 70rpx; margin: 0; border-radius: 100px; height: 70rpx; line-height: 70rpx; font-size: 24rpx; background: $color-yellow; color: #714D01; } } /* 复选框选中状态 */ .action-section .checkbox.checked, .cart-item .checkbox.checked { color: $base-color; } </style>