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

293 lines
14 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>