<template> <view class="pages"> <!-- head --> <sklineHeader title="购物车"></sklineHeader> <view class="cart-body"> <!-- 内容 --> <scroll-view scroll-y class="cart-list" type="custom" :bounces="false" @scrolltolower="onreachBottom"> <sticky-header> <!-- 头部 --> <view class="cart-head" v-if="total>0"> <view class="cart-head-left">共<text>{{total}}</text>款商品</view> <view class="cart-head-right"> <view class="cart-head-btton blue" @click="editAll"> <text>{{editFlag?'完成':'编辑'}}</text> </view> </view> </view> </sticky-header> <productItem v-for="(item, index) in list" :key="index" :list="item" @changeQty="changeQty" @check="chooseItem" @editQty="editQty" @remove="removeCart"> </productItem> <!-- loading --> <view class="loading-bar" v-if="total>0 && status!='loading'">{{noDataText}}</view> <view class="empty-bar" v-if="total==0 && status!='loading'" @click="goBack"> <image mode="aspectFit" :src="empty.imgUrl"></image> <view>{{empty.tip}}</view> </view> </scroll-view> <!-- 底部 --> <view class="cart-footer" v-if="total>0"> <view class="cart-footer-box"> <view class="cart-footer-left"> <view class="cart-footer-left-all" @click="chooseAll"> <view class="cart-footer-left-all-icon"> <uni-icons v-if="allDisabled&&!editFlag" type="circle-filled" size="24" color="#ccc"></uni-icons> <uni-icons v-else :type="allChecked?'checkbox-filled':'circle'" size="24" :color="allChecked?'#dd0000':'#666'"></uni-icons> </view> <view class="cart-footer-left-all-text"> <text>全选</text> </view> </view> </view> <view class="cart-footer-right"> <view class="cart-footer-left-price" v-if="!editFlag && totalAmount"> <view class="flex align_center"> <view class="cart-footer-left-price-text"> <text>合计:</text> </view> <view class="cart-footer-left-price-num"> ¥<text>{{Number(totalAmount).toFixed(2).toString().split('.')[0]}}</text>.{{Number(totalAmount).toFixed(2).toString().split('.')[1]}} </view> </view> <view class="flex align_center"> <view class="cart-footer-left-price-text1"> <text>优惠:¥{{totalDiscount}}</text> <text>代金券:¥{{totalCoupon}}</text> </view> </view> </view> <view v-else></view> <view class="cart-footer-right-button"> <button class="btns" :loading="loading" v-if="!editFlag" type="warn" size="mini" @click="settlement">去结算({{totalNum}})</button> <button v-else class="btns" type="warn" plain size="mini" @click="batchRemove">删除({{totalSel}})</button> </view> </view> </view> <view :style="{height:safeAreaBottom+'px'}"></view> </view> </view> <!-- 修改数量弹框 --> <uni-popup ref="showPopu" type="center" :maskClick="false"> <view class="popu-content"> <view class="popu-close" @click="closePopu"> <uni-icons size="26" type="closeempty"></uni-icons> </view> <view class="popu-content-title flex align_center justify_center"><text>修改商品数量</text></view> <view class="popu-content-num flex align_center justify_center"> <uni-number-box v-model="curEditRow.qty" :size="28" :input-width="280" :input-height="70" :min="1" :max="999"></uni-number-box> </view> <view class="popu-content-btn"> <view class="popu-content-btn-item cancelBtn" @click="closePopu">取消</view> <view class="popu-content-btn-item okbtn" @click="changeSingQty">确定</view> </view> </view> </uni-popup> </view> </template> <script> import { mapState, mapMutations, } from 'vuex' import productItem from '@/pagesB/cart/productitem.vue' import sklineHeader from '../../components/skline/sklineHeader.vue' import { getCartList, updateCart, deleteCart } from '@/api/cart.js' import { purchaseSave, purchaseCheck } from '@/api/purchase.js' export default { components:{ productItem, sklineHeader }, onLoad() { // 计算区域高度 this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight this.screenWidth = uni.getSystemInfoSync().windowWidth this.screenHeight = uni.getSystemInfoSync().windowHeight this.safeAreaBottom = uni.getSystemInfoSync().safeAreaInsets.bottom // 获取列表数据 this.pageInit() }, data() { return { loading: false, status: 'loading', noDataText: '暂无产品', empty: { tip: '购物车空空的,去挑选商品吧', imgUrl: '/static/kongCart.png' }, // 查询条件 pageNo: 1, // 页数 pageSize: 10000, // 每页数 list: [], // 列表数据 total: 0, // 总款数 totalAmount: 0, // 总金额 totalDiscount:0, // 总优惠 totalCoupon: 0, // 总代金券 totalNum: 0, // 总数量 totalSel: 0, // 已选数量 editFlag: false, // 是否编辑状态 allChecked: false, // 是否全选 screenWidth: 325, // 屏幕宽度 screenHeight: 0, // 屏幕高度 statusBarHeight: 44, // 状态栏高度 safeAreaBottom: 0, // 底部安全区域高度 curEditRow: null } }, computed: { ...mapState(['hasLogin']), userInfo(){ return this.$store.state.vuex_userInfo }, allDisabled(){ let ret = false if(!this.editFlag){ this.list.forEach(key => { ret = key.every(item => !item.status || item.status==0 || item.dealerScopeFlag==0) }) } return ret } }, methods: { goBack(){ uni.navigateBack() }, pageInit(){ this.pageNo = 1 this.list = [] this.getRow() }, // 关闭弹框 closePopu(){ this.$refs.showPopu.close() this.curEditRow = null }, // 打开编辑数量弹框 editQty(item){ this.curEditRow = JSON.parse(JSON.stringify(item)) this.$refs.showPopu.open() }, // 确定修改 changeSingQty(){ this.changeQty(this.curEditRow.qty,this.curEditRow.cartSn) }, // 查询列表 getRow (pageNo) { let _this = this if (pageNo) { this.pageNo = pageNo } let params = { pageNo: this.pageNo, pageSize: this.pageSize, queryWord: this.queryWord } this.status = "loading" getCartList(params).then(res => { if (res.status == 200) { _this.total = res.data.count || 0 const list = res.data.list for(let i=0;i<list.length;i=i+10){ _this.list.push(list.slice(i,(i+10)>list.length?list.length:(i+10)).map(key=>{ const a = key.shopPromoProduct key.orginPrice = key.price if(a){ key.promoType = a.promoType key.resultValue = a.resultValue key.conditionValue = a.conditionValue key.discountType = a.discountType key.promoProductSn = a.promoProductSn key.promoSn = a.promoSn // 特价 if(key.promoType=='PROMO_PROD'){ // 直降 if(key.discountType == 'STRAIGHT_DOWN'){ key.price = key.price - key.resultValue } // 折扣 if(key.discountType == 'DISCOUNT'){ key.price = Number(key.price * key.resultValue).toFixed(2) } } } delete key.shopPromoProduct return { id: key.id, edit: false, checked: _this.allChecked, cartSn: key.cartSn, price: key.price, orginPrice: key.orginPrice, qty: key.qty, productSn: key.productSn, productName: key.productEntity.productName, productImage: key.productEntity.images, productCode: key.productEntity.code, productOrigCode: key.productEntity.origCode, unit: key.productEntity.unit, status: key.status, dealerScopeFlag: key.dealerScopeFlag, resultValue: key.resultValue, conditionValue: key.conditionValue, discountType: key.discountType, promoType: key.promoType, promoProductSn: key.promoProductSn, promoSn: key.promoSn, giftQty: 0 } })) } // 默认全选 if(_this.pageNo == 1){ _this.$nextTick(()=>{ _this.chooseAll() }) } // 判断是否最后一页 const maxPages = Math.ceil(_this.total / _this.pageSize) if(this.pageNo >= maxPages){ _this.status = 'nomore' _this.noDataText = '没有更多了' }else{ _this.status = 'loadmore' _this.noDataText = '加载更多' } } else { _this.list = [] _this.total = 0 _this.status = 'loadmore' _this.noDataText = res.message } }) }, // scroll-view到底部加载更多 onreachBottom() { // 判断是否最后一页 const maxPages = Math.ceil(this.total / this.pageSize) if(this.pageNo >= maxPages){ this.status = "nomore" this.noDataText = '没有更多了' }else{ this.pageNo += 1 this.getRow() } }, // 根据cartSn查找 getItemById(cartSn){ const a = this.list.findIndex(k => k.find(s=> s.cartSn == cartSn)) const b = a>=0 ? this.list[a].findIndex(s=> s.cartSn == cartSn) : -1 return {p:a,s:b} }, // 已选产品变更数量 changeQty(val,cartSn){ uni.showLoading({ title: '加载中' }) updateCart({ cartSn: cartSn, qty: val }).then(res => { if(res.status == 200){ const crow = this.getItemById(cartSn) if(crow.p>=0&&crow.s>=0){ this.list[crow.p][crow.s].qty = val this.list[crow.p].splice() // 合计 this.getChooseHeji() uni.$emit('refashCart') } this.closePopu() }else{ uni.showToast({ title: res.message, icon: 'none' }) } uni.hideLoading() }) }, // 单选择 chooseItem(cartSn){ const crow = this.getItemById(cartSn) if(crow.p>=0&&crow.s>=0){ this.list[crow.p][crow.s].checked = !this.list[crow.p][crow.s].checked // 合计 this.getChooseHeji() // 判断是否全选 this.isAllChecked() } }, // 判断是否全选 isAllChecked(){ if(this.editFlag){ this.allChecked = this.list.every(key => key.every(item => item.checked)) }else{ this.allChecked = this.list.every(key => key.filter(item => item.status==1&&item.dealerScopeFlag==1 ).every(item => item.checked)) } }, // 编辑 editAll(){ this.editFlag = !this.editFlag this.list.forEach(key => { key.forEach(item => { item.edit = this.editFlag if(!item.status||item.status==0||item.dealerScopeFlag==0){ item.checked = false } }) }) // 合计 this.getChooseHeji() // 判断是否全选 this.isAllChecked() }, // 清空购物车 clearAll(){ const _this = this uni.showModal({ title: '提示', content: '确定清空购物车?', confirmText: '确定', success(res) { if(res.confirm){ uni.showLoading({ title: '正在清空...', mask: true }) } } }) }, // 全选 chooseAll(){ if(this.allDisabled){ return } this.allChecked = !this.allChecked this.list.forEach(key => { // 非编辑模式 if(!this.editFlag){ key.filter(item=>item.status == 1 && item.dealerScopeFlag == 1).forEach(item => { item.checked = this.allChecked }) }else{ // 编辑模式 key.forEach(item => { item.checked = this.allChecked }) } }) // 合计 this.getChooseHeji() }, //单个删除 removeChoose(cartSn,isBatch){ // 删除项 const crow = this.getItemById(cartSn) if(crow.p>=0&&crow.s>=0){ this.list[crow.p].splice(crow.s, 1); this.total = this.total - 1 // 合计 if(!isBatch){ this.getChooseHeji() uni.$emit('refashCart') // 判断是否全选 this.isAllChecked() } } }, // 批量删除 batchRemove(){ if(this.totalNum==0){ uni.showToast({ title: '请选择产品', icon: 'none' }) return false } const _this = this uni.showModal({ title: '提示', content: '确定删除商品吗?', confirmText: '确定', success(res) { if(res.confirm){ const snList = [] _this.list.forEach(item => { item.filter(k=>k.checked).forEach(s=>{ snList.push(s.cartSn) }) }) // 删除购物车 _this.removeCart(snList,true,true) } } }) }, // 删除商品 removeCart(snList,isBatch,isTip){ const _this = this if(isTip){ uni.showLoading({ title: '删除中' }) } deleteCart({cartSns:snList}).then(ret => { if(ret.status == 200){ snList.forEach(sn => { _this.removeChoose(sn,isBatch) }) // 合计,批量操作 if(isBatch){ _this.getChooseHeji() uni.$emit('refashCart') // 判断是否全选 _this.isAllChecked() } if(isTip){ uni.showToast({ title: '删除成功', icon: 'none' }) } } uni.hideLoading() }) }, // 去结算 settlement(){ if(this.totalAmount>0){ this.submitOrder() }else{ uni.showToast({ title: '请选择产品', icon: 'none' }) } }, // 去结算 submitOrder(){ const _this = this // 获取已选商品 const detailList = [] const cartSn = [] _this.list.forEach(key => { key.filter(item=>item.checked).forEach(item => { detailList.push({ productSn:item.productSn, productCode:item.productCode, qty: item.qty, price:item.orginPrice, }) cartSn.push({ cartSn: item.cartSn, productSn:item.productSn }) }) }) // 校验并提示信息 purchaseCheck({detailList:detailList}).then(res => { if(res.status == 200){ const successList = res.data.successList.map(item => { return { productSn:item.productSn, productCode: item.productCode, qty: item.qty, price:item.price } }) const delSn = cartSn.filter(item => successList.find(k => k.productSn == item.productSn)).map(item => item.cartSn) const removeList = res.data.removeList.map(item => item.productCode) const selloutList = res.data.selloutList.map(item => item.productCode) console.log(successList,delSn) console.log(removeList,selloutList) // 有已下架或已售罄产品提示 if(removeList.length || selloutList.length){ uni.showModal({ title: '提示', content: (removeList.length ? `产品${removeList.join(',')}已下架,`:'')+(selloutList.length?`产品${selloutList.join(',')}已售罄,`:'')+`不可采购。`+(successList.length?'是否继续采购其他产品?':''), showCancel: successList.length, confirmText: successList.length?'确定':'知道了', success(ret) { if(ret.confirm && successList.length){ _this.submitForm(successList,delSn) } } }) }else{ // 提交 _this.submitForm(successList,delSn) } }else{ uni.showToast({ title: res.message, icon: 'none' }) } }) }, // 确认提交 submitForm(detailList,cartSn){ uni.showLoading({ title: '提交中...', mask: true }) this.loading = true purchaseSave({ detailList: detailList }).then(res => { this.loading = false uni.hideLoading() if(res.status == 200){ // 删除已提交产品 this.removeCart(cartSn,true,false) res.data.detailList = [] this.$store.state.vuex_tempData = res.data uni.navigateTo({ url: "/pagesB/procureOrder" }) }else{ uni.showToast({ title: res.message, icon: 'none' }) } }) }, // 计算总款数、合计、数量 getChooseHeji(){ this.totalAmount = 0 this.totalDiscount = 0 this.totalCoupon = 0 this.totalNum = 0 this.totalSel = 0 this.list.forEach(key => { key.filter(item=>item.checked).forEach(item => { this.totalAmount += item.price * item.qty // 总金额 this.totalNum += item.qty // 总数量 this.totalSel += 1 // 已选数量 // 如果是返券类型 if(item.promoType=='BUY_PROD_GIVE_VALID'){ this.totalCoupon += item.resultValue * item.qty } // 特价 if(item.promoType=='PROMO_PROD'){ // 直降 if(item.discountType == 'STRAIGHT_DOWN'){ this.totalDiscount += item.resultValue * item.qty } // 折扣 if(item.discountType == 'DISCOUNT'){ this.totalDiscount += Number(item.price * (1-item.resultValue)) * item.qty } } // 满赠 item.giftQty = item.promoType=='BUY_PROD_GIVE_PROD' ? Math.floor(item.qty / item.conditionValue)*item.resultValue : 0 }) }) }, } } </script> <style lang="less"> .pages{ height: 100vh; display: flex; flex-direction: column; .popu-content{ background-color: #FFFFFF; border-radius: 10px; width: 300px; display: flex; flex-direction: column; align-items: center; padding: 10px 15px; .popu-close{ padding: 10px; position: absolute; right: 0; top: 0; } .popu-content-title{ padding: 10px; font-size: 16px; } .popu-content-num{ font-size: 14px; color: #999999; padding: 10px 0; > text{ margin-right: 10px; font-size: 10px; } } .popu-content-btn{ width: 100%; display: flex; align-items: center; justify-content: space-around; margin: 20px 0 10px; .popu-content-btn-item{ width: 40%; height: 36px; font-size: 14px; display: flex; align-items: center; justify-content: center; border-radius: 100px; } .cancelBtn{ background-color: #f8f8f8; color: #666; } .okbtn{ background-color: #f70000; color: #FFFFFF; } } } .cart-body{ position: relative; flex-grow: 1; display: flex; flex-direction: column; .cart-head{ display: flex; justify-content: space-between; align-items: center; padding: 0 20rpx; background-color: #FFFFFF; height: 40px; .cart-head-left{ display: flex; align-items: center; font-size: 28rpx; color: #333333; height: 100%; text{ color: #d81e06; margin: 0 10rpx; } } .cart-head-right{ display: flex; align-items: center; } .red{ color: #d81e06; } .blue{ color: #2196F3; } .cart-head-btton{ height: 100%; font-size: 28rpx; margin-right: 10px; } } .cart-list{ flex-grow: 1; background-color: #F5F5F5; width: 100%; .loading-bar{ text-align: center; padding: 10px 0; color: #999999; } .empty-bar{ display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px 0; margin-top: 20vh; image{ width: 100px; height: 100px; } view{ font-size: 14px; color: #999999; margin-top: 10px; } } } .cart-footer{ width: 100%; background-color: #FFFFFF; .cart-footer-box{ width: 100%; height: 100rpx; display: flex; justify-content: space-between; align-items: center; } .cart-footer-left{ display: flex; align-items: center; padding: 0 20rpx 0 36rpx; .cart-footer-left-all{ display: flex; align-items: center; .cart-footer-left-all-text{ margin-left: 10rpx; font-size: 28rpx; color: #333333; } } } .cart-footer-right{ padding: 0 20rpx; display: flex; align-items: center; justify-content: space-between; flex-grow:1; .cart-footer-left-price{ flex-grow:1; > view{ display: flex; align-items: baseline; justify-content: flex-end; } .cart-footer-left-price-text{ font-size: 24rpx; color: #333333; } .cart-footer-left-price-text1{ font-size: 20rpx; color: #666; display: flex; align-items: center; margin-top: 2px; text{ margin-right: 5px; } } .cart-footer-left-price-num{ display: flex; align-items: baseline; font-size: 24rpx; color: #d81e06; text{ font-size: 32rpx; } } } .red{ color: #d81e06; } .cart-head-btton{ height: 100%; font-size: 28rpx; color: #333333; } .cart-footer-right-button{ display: flex; align-items: center; margin-left: 20rpx; text-align: right; .btns{ border-radius: 100rpx; height: 36px; } } } } } } </style>