zhwl-miniapp/pages/shop/cart.vue
2025-06-26 12:38:35 +08:00

293 lines
14 KiB
Vue

<template>
<view class="waper">
<u-navbar :autoBack="true" :placeholder="true" bgColor="#FFF">
<view slot='center' class="navbar_title">购物车</view>
</u-navbar>
<view class="waper_box">
<view class="list" v-if="list.length" v-for="(i, index) in list" :key="index">
<view class="title">
{{i.name}}
<view class="check" :class="[i.checked ? '' : 'nocheck']" @click="tabParentCheck(index)">
<u-icon v-if="i.checked" name="checkmark-circle-fill" size="36rpx" color="#01BE69"></u-icon>
</view>
</view>
<view class="cont">
<view class="card_list" v-for="(item, itemIndex) in i.cartList" :key="itemIndex">
<cowain-slide-action :slide-width="132">
<template v-slot:card>
<view class="item">
<view class="check" :class="[item.checked ? '' : 'nocheck']" @click="tabChildCheck(index, itemIndex)">
<u-icon v-if="item.checked" name="checkmark-circle-fill" size="36rpx" color="#01BE69"></u-icon>
</view>
<view class="image">
<image :src="$utils.setImgUrl(item.goods.image)" mode=""></image>
</view>
<view class="info">
<view class="name">{{item.goods.title}}</view>
<view class="tag">
<view v-if="item.sku.goodsSkuText">{{item.sku.goodsSkuText}}</view>
</view>
<view class="option">
<view class="money">{{item.sku.price}}</view>
<view class="number">
<u-number-box :min="1" :max="10" :step="1" v-model="item.goodsNum" @input="updateShoppingCart(index, itemIndex)"></u-number-box>
</view>
</view>
</view>
</view>
</template>
<template v-slot:delete>
<view class="delete-wrap" @click="deleteCart(index, itemIndex)">
<view class="icon">
<u-icon name="trash" color="#fff" size="32rpx"></u-icon>
</view>
<view class="text">删除</view>
</view>
</template>
</cowain-slide-action>
</view>
</view>
</view>
<view class="noData" v-if="!list.length">
<image class="img" src="../../static/image/mine/empty.png" mode=""></image>
<view class="text">空空如也~</view>
<view class="btn" @click="goBrowse">去逛逛</view>
</view>
</view>
<view class="btn_box">
<view class="btn_waper">
<view class="checkAll" @click="tabAllCheck">
<view class="icon" :class="[checked ? '' : 'nocheck']">
<u-icon v-if="checked" name="checkmark-circle-fill" size="36rpx" color="#01BE69"></u-icon>
</view>
<veiw class="text">全选</veiw>
</view>
<view class="btn_cont">
<view class="info">
<view>已选{{buyNum}}件</view>
<view>
<text>合计:</text>
<text>{{money}}</text>
</view>
</view>
<view class="btn" @click="submitOrder">结算</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data () {
return {
checked: false,
list: [],
buyNum: 0,
money: '0.00'
}
},
onShow (options) {
this.getList();
},
methods: {
async submitOrder () {
let arr = [];
this.list.forEach((info) => {
info.cartList.forEach((item) => {
if (item.checked) {
let e = { goodsImage: item.goods.image, goodsTitle: item.goods.title, goodsSkuText: item.sku.goodsSkuText, buy_num: item.goodsNum, cartId: item.id, price: item.sku.price, skuPriceId: item.skuPriceId, expressAreaList: item.goods.expressAreaList };
let f = arr.find(m => m.name === info.name)
if (f) {
f.cartList.push(e)
} else {
arr.push({
name: info.name,
cartList: [e]
})
}
// arr.push({ goodsImage: item.goods.image, goodsTitle: item.goods.title, goodsSkuText: item.sku.goodsSkuText, buy_num: item.goodsNum, cartId: item.id, price: item.sku.price, skuPriceId: item.skuPriceId })
}
})
})
if (arr.length > 0) {
uni.navigateTo({
url: '/pages/shop/cartSubmit?list=' + encodeURIComponent(JSON.stringify(arr))
})
}
},
async getList () {
let info = await this.$shop.queryCartByUser();
this.list = info.data;
},
async deleteCart (parentIndex, index) {
let info = await this.$shop.deleteCart(this.list[parentIndex].cartList[index].id);
uni.showToast({ mask: true, title: info.msg, icon: 'success' });
this.getList();
},
tabParentCheck (index) {
this.list[index].checked = !this.list[index].checked;
this.list[index].cartList.forEach((item, itemIndex) => {
this.list[index].cartList[itemIndex].checked = this.list[index].checked;
})
let parent = this.list.filter((item) => {
return item.checked;
})
if (parent.length == this.list.length) {
this.checked = true;
} else this.checked = false;
this.getMoney()
},
tabChildCheck (parentIndex, index) {
this.list[parentIndex].cartList[index].checked = !this.list[parentIndex].cartList[index].checked;
let arr = this.list[parentIndex].cartList.filter((item) => {
return item.checked;
})
if (arr.length == this.list[parentIndex].cartList.length) {
this.list[parentIndex].checked = true;
} else this.list[parentIndex].checked = false;
let parent = this.list.filter((item) => {
return item.checked;
})
if (parent.length == this.list.length) {
this.checked = true;
} else this.checked = false;
this.getMoney()
},
tabAllCheck () {
this.checked = !this.checked;
this.list.forEach((item, index) => {
this.list[index].checked = this.checked;
this.list[index].cartList.forEach((info, infoIndex) => {
this.list[index].cartList[infoIndex].checked = this.checked;
})
})
this.getMoney()
},
async updateShoppingCart (parentIndex, index) {
let info = await this.$shop.updateShoppingCart({ id: this.list[parentIndex].cartList[index].id, goodsNum: this.list[parentIndex].cartList[index].goodsNum, skuPriceId: this.list[parentIndex].cartList[index].skuPriceId })
this.getMoney();
},
getMoney () {
let buyNum = 0, money = 0;
this.list.forEach((info) => {
info.cartList.forEach((item) => {
if (item.checked) {
buyNum += item.goodsNum;
money += item.goodsNum * item.sku.price
}
})
})
this.buyNum = buyNum;
this.money = money.toFixed(2);
},
goBrowse() {
uni.navigateTo({
url: '/pages/shop/list'
})
}
}
}
</script>
<style lang="scss">
page{ background: #F6F6F6; }
.waper_box{
width: 100%; box-sizing: border-box; padding: 24rpx; padding-bottom: 168rpx;
.check{ width: 36rpx; height: 36rpx; border-radius: 18rpx; position: absolute; left: 0; top: 50%; transform: translateY(-50%); box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.nocheck{
border: 1rpx solid #CCCED1;
}
.list{
width: 100%; border-radius: 10rpx; background: #fff; box-sizing: border-box; padding: 24rpx 0 0 24rpx; margin-bottom: 20rpx; overflow: hidden;
&:last-child{ margin-bottom: 0; }
.title{
height: 46rpx; position: relative; box-sizing: border-box; padding-left: 52rpx; line-height: 38rpx; color: rgba(0,0,0,0.85); font-size: 32rpx; font-weight: 500;
}
.delete-wrap{
width: 108rpx; height: 234rpx; background: #FF5833; display: flex; flex-direction: column; justify-content: center; align-items: center;
.text{ color: #fff; margin-top: 12rpx; font-size: 24rpx; }
}
.cont{
width: 100%;
.card_list{
overflow: hidden; border-bottom: 1rpx solid rgba(0,0,0,0.1); position: relative;
&:last-child{ border-bottom: 0; }
}
.item{
width: calc(100% - 132rpx); box-sizing: border-box; padding: 28rpx 0 28rpx 250rpx;
.image{
width: 170rpx; height: 170rpx; position: absolute; left: 60rpx; top: 28rpx;
image{ border-radius: 10rpx; }
}
.info{
width: 100%; min-height: 170rpx; padding-right: 24rpx; box-sizing: border-box;
.name{ line-height: 33rpx; color: rgba(0,0,0,0.85); font-size: 28rpx; font-weight: 500; }
.tag{
width: 100%; margin-top: 6rpx; display: flex; align-items: center; height: 48rpx;
view{ line-height: 48rpx; background: #F4F4F4; color: rgba(0,0,0,0.65); padding: 0 24rpx; border-radius: 2rpx; font-size: 24rpx; }
}
.option{
width: 100%; margin-top: 10rpx; height: 56rpx; display: flex; justify-content: space-between; align-items: center;
.money{
color: #FF5833; font-size: 36rpx; font-weight: bold; padding-left: 20rpx; position: relative; line-height: 42rpx;
&::after{ content: ""; color: #FF5833; line-height: 23rpx; font-size: 20rpx; position: absolute; left: 0; bottom: 0; }
}
.number{
width: 198rpx; height: 64rpx; border-radius: 50rpx; box-sizing: border-box; border: 2rpx solid #E1E1E1;
.u-number-box__input{ width: 66rpx; margin: 0; background: transparent !important; border: 2rpx solid #E1E1E1; box-sizing: border-box; border-top: 0; border-bottom: 0; }
.u-number-box__minus, .u-number-box__plus{
background: transparent !important; width: 64rpx; height: 100% !important; padding: 0 !important;
.u-icon__icon{ font-size: 20rpx !important; color: #03AE80 !important; }
}
.u-number-box__minus--disabled .u-icon__icon{ color: #c8c9cc !important; }
}
}
}
}
}
}
.noData {
margin-top: 274rpx;
.img { width: 438rpx; height: 387rpx; margin: 0 auto; display: block; }
.text { font-size: 28rpx; color: #666666; text-align: center; }
.btn { height: 96rpx; background: #03AE80; border-radius: 64rpx; line-height: 96rpx; text-align: center; font-size: 32rpx; color: #FFFFFF; margin-top: 100rpx; }
}
}
.btn_box{
width: 100%; background: #fff; position: fixed; left: 0; bottom: 0; box-shadow: 0rpx -1rpx 6rpx 0rpx rgba(0,0,0,0.05);
.btn_waper{
width: 100%; height: 120rpx; box-sizing: border-box; padding: 0 32rpx; position: relative; padding-left: 176rpx;
.checkAll{
display: flex; align-items: center; position: absolute; left: 24rpx; top: 50%; transform: translateY(-50%);
.icon{ width: 36rpx; height: 36rpx; border-radius: 18rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.nocheck{
border: 1rpx solid #CCCED1;
}
.text{ margin-left: 10rpx; color: rgba(0,0,0,0.45); font-size: 28rpx; }
}
.btn_cont{
width: 100%; height: 100%; display: flex; justify-content: space-between; align-items: center;
.info{
display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
view{
&:nth-child(1){ line-height: 28rpx; color: rgba(0,0,0,0.45); font-size: 24rpx; }
&:nth-child(2){
margin-top: 2rpx; display: flex; align-items: flex-end;
text{
&:nth-child(1){ padding-bottom: 4rpx; color: rgba(0,0,0,0.85); font-size: 28rpx; line-height: 33rpx; }
&:nth-child(2){
margin-left: 2rpx; padding-left: 24rpx; position: relative; line-height: 49rpx; color: #FF5833; font-size: 42rpx; font-weight: bold;
&::after{ content: ""; line-height: 28rpx; color: #FF5833; font-size: 24rpx; position: absolute; left: 0; bottom: 4rpx; }
}
}
}
}
}
.btn{ width: 228rpx; height: 80rpx; background: #03AE80; border-radius: 66rpx; text-align: center; line-height: 80rpx; color: #fff; font-size: 30rpx; font-weight: 500; }
}
}
}
</style>