You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
7.4 KiB
Vue

<script setup lang="ts">
import { useCartStore } from '@/store/cart'
import CartStoreGroup from './components/CartStoreGroup.vue'
import EmptyCart from './components/EmptyCart.vue'
definePage({
style: {
navigationBarTitleText: '进货车',
},
})
// 初始化购物车状态
const cartStore = useCartStore()
// 管理模式状态
const isManageMode = ref(false)
// 计算属性
const storeGroups = computed(() => cartStore.groupedByStore)
const totalPrice = computed(() => cartStore.totalPrice)
const selectedCount = computed(() => cartStore.selectedCount)
const isAllSelected = computed(() => cartStore.isAllSelected)
const isEmpty = computed(() => cartStore.isEmpty)
// 全选/取消全选
function handleAllSelect() {
cartStore.toggleAllSelection()
}
// 结算
function handleCheckout() {
if (selectedCount.value === 0) {
uni.showToast({
title: '请选择要结算的商品',
icon: 'none',
})
return
}
// 跳转到结算页面
console.log('跳转到结算页面', cartStore.selectedCartItems)
}
// 切换管理模式
function toggleManageMode() {
isManageMode.value = !isManageMode.value
// 退出管理模式时清空选择
if (!isManageMode.value) {
cartStore.clearSelection()
}
}
// 批量删除
function handleBatchDelete() {
if (selectedCount.value === 0) {
uni.showToast({
title: '请选择要删除的商品',
icon: 'none',
})
return
}
uni.showModal({
title: '确认删除',
content: `确定要删除选中的${selectedCount.value}个商品吗?`,
success: (res) => {
if (res.confirm) {
cartStore.removeSelectedItems()
uni.showToast({
title: '删除成功',
icon: 'success',
})
// 如果删除后购物车为空,退出管理模式
if (cartStore.isEmpty) {
isManageMode.value = false
}
}
},
})
}
// 模拟数据 - 用于开发测试
onMounted(() => {
// 如果购物车为空,添加一些模拟数据
if (cartStore.isEmpty) {
// 添加模拟商品数据
const mockItems = [
{
productId: 1,
productName: 'Apple iPhone 15 Pro Max 256GB 钛金属',
price: 9999,
originalPrice: 10999,
quantity: 1,
image: 'https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=Apple%20iPhone%2015%20Pro%20Max%20product%20image%2C%20titanium%20color%2C%20clean%20background%2C%20professional%20photography&image_size=portrait_4_3',
storeId: 1,
storeName: 'Apple官方旗舰店',
},
{
productId: 2,
productName: 'Apple AirPods Pro 2 主动降噪无线蓝牙耳机',
price: 1899,
originalPrice: 1999,
quantity: 2,
image: 'https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=Apple%20AirPods%20Pro%202%20wireless%20earbuds%2C%20white%20color%2C%20clean%20background%2C%20professional%20photography&image_size=portrait_4_3',
storeId: 1,
storeName: 'Apple官方旗舰店',
},
{
productId: 3,
productName: 'Sony WH-1000XM5 头戴式无线降噪耳机',
price: 2999,
originalPrice: 3299,
quantity: 1,
image: 'https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=Sony%20WH-1000XM5%20over-ear%20wireless%20headphones%2C%20black%20color%2C%20clean%20background%2C%20professional%20photography&image_size=portrait_4_3',
storeId: 2,
storeName: 'Sony官方旗舰店',
},
]
// 添加到购物车
mockItems.forEach((item) => {
cartStore.addItem(item)
})
// 默认全选
cartStore.toggleAllSelection()
}
})
</script>
<template>
<view class="cart-page">
<!-- 页面头部 -->
<view class="cart-header">
<text class="cart-title">购物车</text>
<!-- 管理按钮 -->
<view v-if="!isEmpty" class="header-actions">
<text class="manage-btn" @click="toggleManageMode">
{{ isManageMode ? '完成' : '管理' }}
</text>
</view>
</view>
<!-- 购物车内容 -->
<view class="cart-content">
<!-- 空购物车状态 -->
<EmptyCart v-if="isEmpty" />
<!-- 购物车商品列表 -->
<view v-else class="cart-list">
<!-- 店铺分组 -->
<CartStoreGroup
v-for="group in storeGroups"
:key="group.storeId"
:group="group"
/>
</view>
</view>
<!-- 底部操作栏 -->
<view v-if="!isEmpty" class="cart-footer">
<!-- 全选 -->
<view class="select-all-section">
<wd-checkbox
v-model="isAllSelected"
size="large"
shape="circle"
@change="handleAllSelect"
/>
<text class="select-all-text">全选</text>
</view>
<!-- 操作区域 -->
<view class="action-section">
<!-- 管理模式 -->
<template v-if="isManageMode">
<view class="selected-info">
<text class="selected-text">已选择{{ selectedCount }}项</text>
</view>
<wd-button
type="error"
size="large"
class="batch-delete-btn"
@click="handleBatchDelete"
>
删除
</wd-button>
</template>
<!-- 普通模式 -->
<template v-else>
<view class="price-section">
<text class="price-label">合计:</text>
<text class="price-value">¥{{ totalPrice.toFixed(2) }}</text>
</view>
<wd-button
type="primary"
size="large"
class="checkout-btn"
@click="handleCheckout"
>
结算({{ selectedCount }})
</wd-button>
</template>
</view>
</view>
</view>
</template>
<style scoped lang="scss">
.cart-page {
@apply flex flex-col min-h-screen bg-gray-50;
}
/* */
.cart-header {
@apply bg-white py-[30rpx] px-[32rpx] border-b border-gray-100 flex items-center justify-between;
}
.cart-title {
@apply text-[32rpx] font-bold text-gray-800;
}
/* */
.header-actions {
@apply flex items-center;
}
.manage-btn {
@apply text-[28rpx] text-gray-600;
}
/* */
.cart-content {
@apply flex-1 overflow-y-auto;
}
/* */
.cart-list {
@apply py-[16rpx];
}
/* */
.cart-footer {
@apply fixed left-0 right-0 bg-white border-t border-gray-200 py-[20rpx] px-[32rpx] flex items-center justify-between;
bottom: calc(50px + env(safe-area-inset-bottom));
}
/* */
.select-all-section {
@apply flex items-center;
}
.select-all-text {
@apply ml-[12rpx] text-[28rpx] text-gray-700;
}
/* */
.action-section {
@apply flex items-center;
}
/* */
.checkout-section {
@apply flex items-center;
}
/* */
.price-section {
@apply mr-[24rpx];
}
.price-label {
@apply text-[26rpx] text-gray-600;
}
.price-value {
@apply text-[32rpx] font-bold text-red-500;
}
/* */
.checkout-btn {
@apply min-w-[200rpx];
}
/* - */
.selected-info {
@apply mr-[24rpx];
}
.selected-text {
@apply text-[26rpx] text-gray-600;
}
/* */
.batch-delete-btn {
@apply min-w-[200rpx];
}
/* */
@media screen and (max-width: 750rpx) {
.cart-footer {
@apply py-[16rpx] px-[24rpx];
}
.checkout-btn,
.batch-delete-btn {
@apply min-w-[180rpx];
}
.price-section,
.selected-info {
@apply mr-[16rpx];
}
}
</style>