258 lines
6.1 KiB
Vue
258 lines
6.1 KiB
Vue
<template>
|
|
<view class="cart-page">
|
|
<!-- 购物车列表 -->
|
|
<view v-if="cartStore.items.length > 0" class="cart-list">
|
|
<view v-for="item in cartStore.items" :key="item.id" class="cart-item">
|
|
<view class="cart-item__check" @click="cartStore.toggleCheck(item.id)">
|
|
<view class="checkbox" :class="{ 'checkbox--checked': item.checked }">✓</view>
|
|
</view>
|
|
<image class="cart-item__img" :src="item.product.bannerImages?.[0] || '/static/logo.png'" mode="aspectFill" />
|
|
<view class="cart-item__info">
|
|
<text class="cart-item__name">{{ item.product.name }}</text>
|
|
<text class="cart-item__spec">{{ item.specData.fineness }} / {{ item.specData.mainStone }} / {{ item.specData.ringSize }}</text>
|
|
<view class="cart-item__bottom">
|
|
<text class="cart-item__price">¥{{ item.specData.totalPrice }}</text>
|
|
<view class="quantity-ctrl">
|
|
<view class="quantity-btn" @click="handleMinus(item)">-</view>
|
|
<text class="quantity-num">{{ item.quantity }}</text>
|
|
<view class="quantity-btn" @click="cartStore.updateQuantity(item.id, item.quantity + 1)">+</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="cart-item__delete" @click="cartStore.removeFromCart(item.id)">删除</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 空状态 -->
|
|
<view v-else class="empty-cart">
|
|
<text class="empty-cart__text">购物车是空的</text>
|
|
<view class="empty-cart__btn" @click="goHome">去逛逛</view>
|
|
</view>
|
|
|
|
<!-- 底部结算栏 -->
|
|
<view v-if="cartStore.items.length > 0" class="settle-bar">
|
|
<view class="settle-bar__left">
|
|
<view class="checkbox" :class="{ 'checkbox--checked': isAllChecked }" @click="cartStore.toggleCheckAll()">✓</view>
|
|
<text class="settle-bar__all-text">全选</text>
|
|
</view>
|
|
<view class="settle-bar__right">
|
|
<text class="settle-bar__total">合计:<text class="settle-bar__price">¥{{ cartStore.totalAmount.toFixed(2) }}</text></text>
|
|
<view
|
|
class="settle-bar__btn"
|
|
:class="{ 'settle-bar__btn--disabled': cartStore.checkedItems.length === 0 }"
|
|
@click="handleSettle"
|
|
>
|
|
下单({{ cartStore.checkedItems.length }})
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 客服入口 -->
|
|
<CustomerServiceBtn v-if="showQrcode" mode="qrcode" @close="showQrcode = false" />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { useCartStore } from '../../store/cart'
|
|
import CustomerServiceBtn from '../../components/CustomerServiceBtn.vue'
|
|
import type { CartItem } from '../../types'
|
|
|
|
const cartStore = useCartStore()
|
|
const showQrcode = ref(false)
|
|
|
|
const isAllChecked = computed(() =>
|
|
cartStore.items.length > 0 && cartStore.items.every((item) => item.checked),
|
|
)
|
|
|
|
function handleMinus(item: CartItem) {
|
|
if (item.quantity > 1) {
|
|
cartStore.updateQuantity(item.id, item.quantity - 1)
|
|
}
|
|
}
|
|
|
|
function handleSettle() {
|
|
if (cartStore.checkedItems.length === 0) {
|
|
uni.showToast({ title: '请先选择商品', icon: 'none' })
|
|
return
|
|
}
|
|
const token = uni.getStorageSync('token')
|
|
if (!token) {
|
|
uni.navigateTo({ url: '/pages/login/index' })
|
|
return
|
|
}
|
|
uni.navigateTo({ url: '/pages/order/submit' })
|
|
}
|
|
|
|
function goHome() {
|
|
uni.switchTab({ url: '/pages/index/index' })
|
|
}
|
|
|
|
onMounted(() => {
|
|
cartStore.fetchCart()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.cart-page {
|
|
min-height: 100vh;
|
|
background: #f5f5f5;
|
|
padding-bottom: 120rpx;
|
|
}
|
|
.cart-list {
|
|
padding: 16rpx;
|
|
}
|
|
.cart-item {
|
|
display: flex;
|
|
align-items: center;
|
|
background: #fff;
|
|
border-radius: 12rpx;
|
|
padding: 20rpx;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
.cart-item__check {
|
|
margin-right: 16rpx;
|
|
}
|
|
.checkbox {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
border: 2rpx solid #ccc;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 24rpx;
|
|
color: transparent;
|
|
}
|
|
.checkbox--checked {
|
|
background: #e4393c;
|
|
border-color: #e4393c;
|
|
color: #fff;
|
|
}
|
|
.cart-item__img {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
border-radius: 8rpx;
|
|
margin-right: 20rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
.cart-item__info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
.cart-item__name {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 1;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
.cart-item__spec {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-top: 8rpx;
|
|
}
|
|
.cart-item__bottom {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 16rpx;
|
|
}
|
|
.cart-item__price {
|
|
font-size: 30rpx;
|
|
color: #e4393c;
|
|
font-weight: bold;
|
|
}
|
|
.quantity-ctrl {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.quantity-btn {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
border: 1rpx solid #ddd;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
border-radius: 8rpx;
|
|
}
|
|
.quantity-num {
|
|
min-width: 60rpx;
|
|
text-align: center;
|
|
font-size: 26rpx;
|
|
}
|
|
.cart-item__delete {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-left: 12rpx;
|
|
padding: 8rpx;
|
|
}
|
|
.empty-cart {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding-top: 300rpx;
|
|
}
|
|
.empty-cart__text {
|
|
font-size: 30rpx;
|
|
color: #999;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
.empty-cart__btn {
|
|
background: #e4393c;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
padding: 16rpx 60rpx;
|
|
border-radius: 44rpx;
|
|
}
|
|
.settle-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 100rpx;
|
|
background: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 24rpx;
|
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
.settle-bar__left {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.settle-bar__all-text {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
margin-left: 12rpx;
|
|
}
|
|
.settle-bar__right {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.settle-bar__total {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
margin-right: 20rpx;
|
|
}
|
|
.settle-bar__price {
|
|
color: #e4393c;
|
|
font-weight: bold;
|
|
font-size: 32rpx;
|
|
}
|
|
.settle-bar__btn {
|
|
background: #e4393c;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
padding: 16rpx 40rpx;
|
|
border-radius: 44rpx;
|
|
}
|
|
.settle-bar__btn--disabled {
|
|
background: #ccc;
|
|
}
|
|
</style>
|