Files
medical-mall/pages/mall/consumer/cart copy.uvue
2026-02-02 17:34:31 +08:00

1436 lines
32 KiB
Plaintext
Raw 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.
<!-- pages/mall/consumer/cart.uvue -->
<template>
<view class="cart-page">
<!-- 智能顶部导航栏 - 与消息页保持一致 -->
<view class="smart-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-container">
<text class="nav-title">购物车</text>
<view class="nav-actions">
<view class="action-btn" @click="toggleManageMode">
<text class="action-icon">{{ isManageMode ? '✓' : '⚙️' }}</text>
<text class="action-text">{{ isManageMode ? '完成' : '管理' }}</text>
</view>
</view>
</view>
</view>
<!-- 导航栏占位符 - 已移除 -->
<!-- <view class="navbar-placeholder" :style="{ height: (statusBarHeight + 44) + 'px' }"></view> -->
<!-- 购物车内容 -->
<scroll-view scroll-y class="cart-content" :style="{ paddingTop: (statusBarHeight + 10) + 'px' }">
<!-- 空购物车 -->
<view v-if="!loading && cartItems.length === 0" class="empty-cart">
<text class="empty-icon">🛒</text>
<text class="empty-title">购物车是空的</text>
<text class="empty-desc">快去挑选喜欢的商品吧</text>
<button class="go-shopping-btn" @click="goShopping">去逛逛</button>
</view>
<!-- 购物车商品列表 -->
<view v-else class="cart-list">
<view
v-for="group in cartGroups"
:key="group.shopId"
class="shop-group"
>
<!-- 店铺头部 -->
<view class="shop-header">
<view class="shop-select" @click="toggleShopSelect(group.shopId)">
<text v-if="isShopSelected(group.shopId)" class="selected-icon">✓</text>
<text v-else class="unselected-icon"></text>
</view>
<text class="shop-icon">🏪</text>
<text class="shop-name">{{ group.shopName }}</text>
<text class="shop-arrow">></text>
</view>
<!-- 店铺商品 -->
<view
v-for="item in group.items"
:key="item.id"
class="cart-item"
>
<view class="item-select" @click="toggleSelect(item.id)">
<text v-if="item.selected" class="selected-icon">✓</text>
<text v-else class="unselected-icon"></text>
</view>
<image
class="item-image"
:src="item.image"
mode="aspectFill"
@click="navigateToProduct(item)"
/>
<view class="item-info">
<view class="info-top">
<text class="item-name">{{ item.name }}</text>
<text class="item-spec">{{ item.spec }}</text>
</view>
<view class="item-footer">
<text class="item-price">¥{{ item.price }}</text>
<view class="quantity-control">
<text class="quantity-btn" @click="decreaseQuantity(item.id)">-</text>
<text class="quantity-value">{{ item.quantity }}</text>
<text class="quantity-btn" @click="increaseQuantity(item.id)">+</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 购物车操作栏 (移至推荐商品上方) -->
<view v-if="cartItems.length > 0" class="cart-action-bar">
<view class="action-bar-content">
<view class="action-left">
<view class="select-all" @click="toggleSelectAll">
<text v-if="allSelected" class="selected-icon">✓</text>
<text v-else class="unselected-icon"></text>
<text class="select-all-text">全选</text>
</view>
</view>
<view class="action-right">
<view v-if="!isManageMode" class="total-info">
<text class="total-text">合计:</text>
<text class="total-price">¥{{ totalPrice }}</text>
</view>
<button v-if="!isManageMode" class="checkout-btn" @click="goToCheckout">
去结算({{ selectedCount }})
</button>
<button v-else class="delete-btn" @click="deleteSelectedItems">
删除({{ selectedCount }})
</button>
</view>
</view>
</view>
<!-- 推荐商品 -->
<view v-if="recommendProducts.length > 0" class="recommend-section">
<view class="section-header">
<text class="section-title">猜你喜欢</text>
</view>
<view class="recommend-list">
<view
v-for="product in recommendProducts"
:key="product.id"
class="recommend-item"
@click="navigateToProduct(product)"
>
<image
class="recommend-image"
:src="product.image"
mode="aspectFill"
/>
<text class="recommend-name">{{ product.name }}</text>
<view class="recommend-bottom">
<text class="recommend-price">¥{{ product.price }}</text>
<view class="recommend-add-btn" @click.stop="addToCart(product)">
<text class="recommend-add-icon">+</text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<!-- 底部结算栏 - 已移除,移动到内容区域 -->
<!-- <view v-if="cartItems.length > 0" class="cart-footer">
<view class="footer-content">
<view class="footer-left">
<view class="select-all" @click="toggleSelectAll">
<text v-if="allSelected" class="selected-icon">✓</text>
<text v-else class="unselected-icon"></text>
<text class="select-all-text">全选</text>
</view>
</view>
<view class="footer-right">
<view v-if="!isManageMode" class="total-info">
<text class="total-text">合计:</text>
<text class="total-price">¥{{ totalPrice }}</text>
</view>
<button v-if="!isManageMode" class="checkout-btn" @click="goToCheckout">
去结算({{ selectedCount }})
</button>
<button v-else class="delete-btn" @click="deleteSelectedItems">
删除({{ selectedCount }})
</button>
</view>
</view>
</view> -->
</view>
</template>
<script setup lang="uts">
import { ref, computed, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import supabaseService from '@/utils/supabaseService.uts'
import type { CartItem } from '@/utils/supabaseService.uts'
// 响应式数据
const cartItems = ref<any[]>([])
const recommendProducts = ref<any[]>([])
const loading = ref<boolean>(false)
const statusBarHeight = ref(0)
const isManageMode = ref(false)
const mockRecommendProducts = [
{
id: 'rec_001',
shopId: 'shop_rec_1',
shopName: '潮流运动旗舰店',
name: '运动保温杯',
price: 59,
image: 'https://picsum.photos/100/100?random=11',
specification: '颜色:星空黑 | 容量500ml | 材质304不锈钢',
specDetails: {
color: '星空黑',
capacity: '500ml',
material: '304不锈钢'
}
},
{
id: 'rec_002',
shopId: 'shop_rec_2',
shopName: '智能家居生活馆',
name: '声波电动牙刷',
price: 129,
image: 'https://picsum.photos/100/100?random=12',
specification: '颜色:珍珠白 | 刷头敏感型×2 | 续航30天',
specDetails: {
color: '珍珠白',
brushHead: '敏感型×2',
batteryLife: '30天'
}
},
{
id: 'rec_003',
shopId: 'shop_rec_3',
shopName: '健康防护专家店',
name: '医用护理口罩',
price: 29.9,
image: 'https://picsum.photos/100/100?random=13',
specification: '规格:三层防护 | 数量50只独立装 | 执行标准YY0469',
specDetails: {
layers: '三层防护',
quantity: '50只',
standard: 'YY0469'
}
},
{
id: 'rec_004',
shopId: 'shop_rec_4',
shopName: '户外运动装备店',
name: '专业护膝',
price: 45,
image: 'https://picsum.photos/100/100?random=14',
specification: '尺码L码 | 材质:记忆棉+弹力布 | 适用:篮球/跑步',
specDetails: {
size: 'L码',
material: '记忆棉+弹力布',
suitableFor: '篮球/跑步'
}
}
]
// 计算属性
const cartGroups = computed(() => {
const groups = new Map<string, any>()
cartItems.value.forEach(item => {
if (!groups.has(item.shopId)) {
groups.set(item.shopId, {
shopId: item.shopId,
shopName: item.shopName,
items: [] as any[]
})
}
const group = groups.get(item.shopId)
if (group) {
group.items.push(item)
}
})
return Array.from(groups.values())
})
const allSelected = computed(() => {
return cartItems.value.length > 0 && cartItems.value.every(item => item.selected)
})
const selectedCount = computed(() => {
return cartItems.value.filter(item => item.selected).reduce((sum, item) => sum + item.quantity, 0)
})
const totalPrice = computed(() => {
return cartItems.value
.filter(item => item.selected)
.reduce((sum, item) => sum + item.price * item.quantity, 0)
.toFixed(2)
})
const toggleManageMode = () => {
isManageMode.value = !isManageMode.value
}
// 初始化页面数据
const initPage = () => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight || 0
}
// 生命周期
onMounted(() => {
initPage()
})
onShow(() => {
loadCartData()
})
// 加载数据
const loadCartData = async () => {
loading.value = true
try {
// 从Supabase获取购物车数据
const dbCartItems = await supabaseService.getCartItems()
console.log('从Supabase获取购物车数据:', dbCartItems)
// 将数据库CartItem映射为页面CartItem格式
cartItems.value = dbCartItems.map((item: CartItem) => ({
id: item.id, // 购物车项ID
productId: item.product_id, // 商品ID
shopId: item.shop_id || 'shop_default', // 店铺ID
shopName: item.shop_name || '自营店铺', // 店铺名称
name: item.product_name || '商品名称', // 商品名称
price: item.product_price || 0, // 商品价格
image: item.product_image || '/static/images/default-product.png', // 商品图片
spec: item.product_specification || '默认规格', // 商品规格
quantity: item.quantity, // 数量
selected: item.selected // 是否选中
}))
// 同时更新本地存储作为缓存
uni.setStorageSync('cart', JSON.stringify(cartItems.value))
console.log('购物车数据已从数据库加载,数量:', cartItems.value.length)
} catch (error) {
console.error('从Supabase加载购物车数据失败:', error)
// 如果数据库加载失败,尝试从本地存储恢复
const cartData = uni.getStorageSync('cart')
if (cartData) {
try {
cartItems.value = JSON.parse(cartData as string) as any[]
console.log('使用本地存储购物车数据,数量:', cartItems.value.length)
} catch (e) {
console.error('解析购物车数据失败', e)
cartItems.value = []
}
} else {
cartItems.value = []
}
}
setTimeout(() => {
// 模拟推荐商品加载
recommendProducts.value = [...mockRecommendProducts]
loading.value = false
}, 500)
}
// 保存购物车数据到本地存储(作为缓存)
const saveCartData = () => {
uni.setStorageSync('cart', JSON.stringify(cartItems.value))
}
// 商品操作 - 切换选择状态
const toggleSelect = async (itemId: string) => {
const index = cartItems.value.findIndex(item => item.id === itemId)
if (index !== -1) {
const newSelected = !cartItems.value[index].selected
try {
// 更新数据库中的选择状态
const success = await supabaseService.updateCartItemSelection(itemId, newSelected)
if (success) {
cartItems.value[index].selected = newSelected
cartItems.value = [...cartItems.value] // 触发响应式更新
saveCartData()
} else {
console.error('更新购物车项选择状态失败')
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} catch (error) {
console.error('更新购物车项选择状态异常:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
}
}
const toggleShopSelect = async (shopId: string) => {
const group = cartGroups.value.find((g: any) => g.shopId === shopId)
if (!group) return
// 检查当前是否全选
const isAllShopSelected = (group.items as any[]).every((item: any) => item.selected)
const newState = !isAllShopSelected
// 获取该店铺下所有购物车项的ID
const cartItemIds = cartItems.value
.filter(item => item.shopId === shopId)
.map(item => item.id)
if (cartItemIds.length === 0) return
try {
// 批量更新数据库中的选择状态
const success = await supabaseService.batchUpdateCartItemSelection(cartItemIds, newState)
if (success) {
// 更新本地状态
cartItems.value.forEach(item => {
if (item.shopId === shopId) {
item.selected = newState
}
})
cartItems.value = [...cartItems.value]
saveCartData()
} else {
console.error('批量更新购物车项选择状态失败')
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} catch (error) {
console.error('批量更新购物车项选择状态异常:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
}
const toggleSelectAll = async () => {
const newSelectedState = !allSelected.value
// 获取所有购物车项的ID
const cartItemIds = cartItems.value.map(item => item.id)
if (cartItemIds.length === 0) return
try {
// 批量更新数据库中的选择状态
const success = await supabaseService.batchUpdateCartItemSelection(cartItemIds, newSelectedState)
if (success) {
// 更新本地状态
cartItems.value = cartItems.value.map(item => ({
...item,
selected: newSelectedState
}))
saveCartData()
} else {
console.error('批量更新全选状态失败')
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} catch (error) {
console.error('批量更新全选状态异常:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
}
const increaseQuantity = async (itemId: string) => {
const index = cartItems.value.findIndex(item => item.id === itemId)
if (index !== -1) {
const newQuantity = cartItems.value[index].quantity + 1
try {
// 更新数据库中的数量
const success = await supabaseService.updateCartItemQuantity(itemId, newQuantity)
if (success) {
cartItems.value[index].quantity = newQuantity
cartItems.value = [...cartItems.value]
saveCartData()
} else {
console.error('更新购物车项数量失败')
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} catch (error) {
console.error('更新购物车项数量异常:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
}
}
const decreaseQuantity = async (itemId: string) => {
const index = cartItems.value.findIndex(item => item.id === itemId)
if (index !== -1) {
if (cartItems.value[index].quantity > 1) {
const newQuantity = cartItems.value[index].quantity - 1
try {
// 更新数据库中的数量
const success = await supabaseService.updateCartItemQuantity(itemId, newQuantity)
if (success) {
cartItems.value[index].quantity = newQuantity
cartItems.value = [...cartItems.value]
saveCartData()
} else {
console.error('更新购物车项数量失败')
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} catch (error) {
console.error('更新购物车项数量异常:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
} else {
// 数量为1时询问是否删除
uni.showModal({
title: '提示',
content: '确定要从购物车移除该商品吗?',
success: async (res) => {
if (res.confirm) {
try {
// 从数据库删除购物车项
const success = await supabaseService.deleteCartItem(itemId)
if (success) {
cartItems.value.splice(index, 1)
cartItems.value = [...cartItems.value]
saveCartData()
uni.showToast({
title: '已移除',
icon: 'success'
})
} else {
console.error('删除购物车项失败')
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
} catch (error) {
console.error('删除购物车项异常:', error)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
}
}
})
}
}
}
// 删除商品 - 批量删除选中的商品
const deleteSelectedItems = async () => {
if (selectedCount.value === 0) {
uni.showToast({
title: '请选择要删除的商品',
icon: 'none'
})
return
}
uni.showModal({
title: '提示',
content: `确定要删除选中的 ${selectedCount.value} 件商品吗?`,
success: async (res) => {
if (res.confirm) {
// 获取选中的购物车项ID
const selectedCartItemIds = cartItems.value
.filter(item => item.selected)
.map(item => item.id)
try {
// 批量从数据库删除购物车项
const success = await supabaseService.batchDeleteCartItems(selectedCartItemIds)
if (success) {
// 更新本地状态
cartItems.value = cartItems.value.filter(item => !item.selected)
saveCartData()
// 如果购物车删空了,退出管理模式
if (cartItems.value.length === 0) {
isManageMode.value = false
}
uni.showToast({
title: '删除成功',
icon: 'success'
})
} else {
console.error('批量删除购物车项失败')
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
} catch (error) {
console.error('批量删除购物车项异常:', error)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
}
}
})
}
const addToCart = async (product: any) => {
try {
// 调用SupabaseService添加商品到购物车
const success = await supabaseService.addToCart(product.id, 1, product.skuId)
if (success) {
uni.showToast({
title: '已添加到购物车',
icon: 'success'
})
// 重新加载购物车数据
loadCartData()
} else {
console.error('添加商品到购物车失败')
uni.showToast({
title: '添加失败',
icon: 'none'
})
}
} catch (error) {
console.error('添加商品到购物车异常:', error)
uni.showToast({
title: '添加失败',
icon: 'none'
})
}
}
// 导航函数
const goShopping = () => {
uni.switchTab({ url: '/pages/mall/consumer/index' })
}
const navigateToProduct = (product: any) => {
// 使用productId如果存在作为跳转的商品ID否则使用id
const productId = product.productId || product.id
// 传递完整的参数,确保商品详情页能正确加载
const params = new URLSearchParams()
params.append('id', productId)
params.append('productId', productId)
params.append('price', product.price?.toString() || '0')
// 商品详情页期望的参数名是originalPrice
params.append('originalPrice', (product.original_price || product.originalPrice || (product.price * 1.2).toFixed(2))?.toString())
params.append('name', encodeURIComponent(product.name || ''))
params.append('image', encodeURIComponent(product.image || '/static/product1.jpg'))
uni.navigateTo({
url: `/pages/mall/consumer/product-detail?${params.toString()}`
})
}
const goToCheckout = () => {
if (selectedCount.value === 0) {
uni.showToast({
title: '请选择商品',
icon: 'none'
})
return
}
// 确保最新状态已保存到本地存储
saveCartData()
// 获取选中的商品 (直接过滤cartItems不依赖cartGroups)
const selectedItems = cartItems.value
.filter(item => item.selected)
.map(item => ({
id: item.id,
product_id: item.id, // 使用商品ID作为product_id
sku_id: item.id, // 使用商品ID作为sku_id
product_name: item.name,
product_image: item.image,
sku_specifications: item.spec,
price: Number(item.price), // 确保是数字
quantity: Number(item.quantity) // 确保是数字
}))
// 关键修复:将结算数据写入 Storage确保 checkout 页面能稳定获取
uni.setStorageSync('checkout_type', 'cart')
uni.setStorageSync('checkout_items', JSON.stringify(selectedItems))
// 跳转到结算页面并传递数据
uni.navigateTo({
url: '/pages/mall/consumer/checkout',
success: (res) => {
// 通过eventChannel传递数据
res.eventChannel.emit('acceptData', {
selectedItems: selectedItems
})
}
})
}
</script>
<style>
.cart-page {
width: 100%;
height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
}
/* 智能导航栏 */
.smart-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
z-index: 1000;
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.15);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.nav-container {
padding: 0 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
max-width: 1400px;
margin: 0 auto;
height: 44px; /* 统一高度 44px */
}
.nav-title {
font-size: 18px;
font-weight: bold;
color: white;
}
.nav-actions {
display: flex;
flex-direction: row;
align-items: center;
}
.action-btn {
display: flex;
flex-direction: row;
align-items: center;
background: rgba(255, 255, 255, 0.2);
padding: 4px 12px;
border-radius: 20px;
cursor: pointer;
transition: all 0.2s ease;
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.action-icon {
font-size: 14px;
margin-right: 4px;
color: white;
}
.action-text {
font-size: 12px;
color: white;
font-weight: 500;
}
/* 导航栏占位符 */
.navbar-placeholder {
width: 100%;
flex-shrink: 0;
}
/* 内容区 */
.cart-content {
flex: 1;
height: 0; /* 配合 flex: 1 实现自适应滚动 */
padding-bottom: 60px; /* 为底部结算栏留出空间 */
}
/* 空购物车 */
.empty-cart {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
}
.empty-icon {
font-size: 80px;
color: #ddd;
margin-bottom: 20px;
}
.empty-title {
font-size: 18px;
color: #666;
margin-bottom: 10px;
}
.empty-desc {
font-size: 14px;
color: #999;
margin-bottom: 30px;
}
.go-shopping-btn {
background-color: #ff5000;
color: white;
border: none;
border-radius: 25px;
padding: 10px 40px;
font-size: 16px;
}
/* 购物车商品列表 */
.cart-list {
background-color: transparent; /* 背景透明,因为每个店铺有自己的卡片 */
margin: 10px;
border-radius: 0;
overflow: visible;
}
.shop-group {
background-color: white;
border-radius: 12px;
margin-bottom: 12px;
overflow: hidden;
}
.shop-header {
display: flex;
flex-direction: row; /* 强制横向排列 */
align-items: center;
justify-content: flex-start; /* 靠左对齐 */
padding: 12px;
border-bottom: 1px solid #f5f5f5;
}
.shop-select {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 8px;
flex-shrink: 0; /* 防止被压缩 */
}
.shop-icon {
font-size: 16px;
margin-right: 6px;
flex-shrink: 0;
}
.shop-name {
font-size: 14px;
font-weight: 600;
color: #333;
margin-right: 4px;
/* 自适应宽度,但不超过剩余空间 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.shop-arrow {
font-size: 12px;
color: #999;
flex-shrink: 0;
}
.cart-item {
display: flex;
flex-direction: row; /* 显式横向排列 */
padding: 12px; /* 减小内边距 */
border-bottom: 1px solid #f5f5f5;
align-items: center;
height: 100px; /* 固定高度节省空间 */
}
.cart-item:last-child {
border-bottom: none;
}
.item-select {
width: 30px; /* 减小选择框区域 */
height: 100%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 5px;
}
.selected-icon {
width: 18px;
height: 18px;
background-color: #ff5000;
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
}
.unselected-icon {
width: 18px;
height: 18px;
border: 1px solid #ddd;
border-radius: 50%;
}
.item-image {
width: 70px; /* 减小图片尺寸 */
height: 70px;
border-radius: 6px;
margin-right: 10px;
flex-shrink: 0;
}
.item-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 70px; /* 与图片高度一致 */
overflow: hidden;
}
.info-top {
display: flex;
flex-direction: column;
}
.item-name {
font-size: 14px; /* 稍微减小字体 */
color: #333;
margin-bottom: 2px;
display: -webkit-box;
-webkit-line-clamp: 1; /* 单行显示 */
-webkit-box-orient: vertical;
overflow: hidden;
font-weight: 500;
}
.item-spec {
font-size: 12px;
color: #999;
margin-bottom: auto; /* 自动占据中间空间 */
}
.item-footer {
display: flex;
flex-direction: row; /* 显式设置横向排列 */
justify-content: space-between;
align-items: center;
width: 100%; /* 确保占满宽度 */
}
.item-price {
font-size: 16px;
color: #ff5000;
font-weight: bold;
}
.quantity-control {
display: flex;
flex-direction: row; /* 显式设置横向排列 */
align-items: center;
background-color: #f5f5f5;
border-radius: 12px;
overflow: hidden;
height: 24px;
}
.quantity-btn {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: #666;
}
.quantity-value {
width: 30px;
text-align: center;
font-size: 13px;
line-height: 24px;
}
/* 推荐商品 */
.recommend-section {
margin: 20px 10px;
background-color: white;
border-radius: 10px;
padding: 15px;
}
.section-header {
margin-bottom: 15px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
}
.recommend-list {
display: grid;
grid-template-columns: repeat(2, 1fr); /* 手机端默认双列 */
gap: 12px;
}
.recommend-item {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 8px;
overflow: hidden;
}
.recommend-image {
width: 100%;
aspect-ratio: 1; /* 保持正方形比例 */
height: auto; /* 自动高度 */
object-fit: cover;
border-radius: 8px;
margin-bottom: 8px;
background: #f5f5f5;
}
.recommend-name {
font-size: 13px;
color: #333;
margin-bottom: 5px;
line-height: 1.4;
height: 36px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.recommend-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-right: 8px;
}
.recommend-price {
font-size: 15px;
color: #ff5000;
font-weight: bold;
}
.recommend-add-btn {
width: 24px;
height: 24px;
background-color: #ff5000;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.recommend-add-icon {
color: white;
font-size: 16px;
line-height: 1;
font-weight: bold;
}
/* 响应式布局优化 */
@media screen and (min-width: 768px) {
.cart-list,
.recommend-section {
margin: 20px auto;
max-width: 95%;
}
.recommend-list {
grid-template-columns: repeat(4, 1fr); /* 平板显示4列 */
gap: 16px;
}
}
@media screen and (min-width: 1024px) {
/* 桌面端整体布局调整 */
.cart-content {
padding: 20px 40px;
background-color: #f5f5f5;
}
.cart-list,
.recommend-section {
margin: 20px auto;
max-width: 1200px; /* 限制最大宽度 */
}
/* 店铺分组在桌面端显示为网格布局 */
.shop-group {
display: block;
background: transparent;
box-shadow: none;
border-radius: 0;
overflow: visible;
}
.shop-header {
background: white;
border-radius: 12px;
margin-bottom: 12px;
padding: 16px 24px;
}
/* 购物车商品列表转为列表布局 */
.cart-item {
background: white;
border-radius: 0;
padding: 15px 30px;
height: 80px; /* 固定高度 */
border-bottom: 1px solid #eee;
box-shadow: none;
display: flex;
flex-direction: row; /* 显式设置横向排列 */
align-items: center; /* 垂直居中 */
width: 100%;
}
.cart-item:hover {
background-color: #f9f9f9;
transform: none;
box-shadow: none;
}
.item-image {
width: 50px;
height: 50px;
margin-right: 20px;
flex-shrink: 0;
}
.item-info {
flex: 1;
height: 100%;
display: flex;
flex-direction: row; /* 信息区域横向排列 */
align-items: center;
justify-content: space-between;
overflow: visible;
}
.info-top {
flex: 1;
display: flex;
flex-direction: row; /* 名称和规格横向排列 */
align-items: center;
margin-right: 20px;
height: 100%;
}
.item-name {
font-size: 14px;
width: 250px; /* 固定名称宽度 */
margin-right: 20px;
/* 限制行数 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 0;
}
.item-spec {
width: 150px;
margin-bottom: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-footer {
width: auto;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
gap: 40px;
height: 100%;
}
.item-price {
width: 100px;
text-align: right;
margin-bottom: 0;
}
.quantity-control {
margin-left: 0;
display: flex;
flex-direction: row;
}
/* 推荐商品优化 */
.recommend-list {
grid-template-columns: repeat(5, 1fr); /* 桌面端显示5列 */
gap: 20px;
}
.recommend-image {
height: 200px; /* 强制高度 */
}
/* 底部结算栏优化 */
.cart-footer {
padding: 0 40px;
max-width: 100%;
margin: 0 auto;
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
}
@media screen and (min-width: 1400px) {
.cart-list,
.recommend-section {
max-width: 1400px;
}
/* 大屏下购物车商品显示3列 - 移除,保持单列列表 */
/* .cart-list .shop-group > view:not(.shop-header) {
grid-template-columns: repeat(3, 1fr);
} */
.recommend-list {
grid-template-columns: repeat(6, 1fr); /* 大屏幕显示6列 */
}
.footer-content {
max-width: 1400px;
}
}
/* 购物车操作栏样式 - 自适应横向排列 */
.cart-action-bar {
background-color: white;
margin: 10px;
border-radius: 12px;
padding: 15px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.action-bar-content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.action-left, .action-right {
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.action-right {
justify-content: flex-end;
flex: 1;
min-width: 0; /* 防止溢出 */
}
/* 合计信息区域 - 自适应横向排列 */
.total-info {
display: flex;
align-items: center;
margin-right: 12px;
flex-shrink: 0;
}
.total-text {
font-size: 14px;
color: #333;
margin-right: 5px;
white-space: nowrap;
}
.total-price {
font-size: 18px;
color: #ff5000;
font-weight: bold;
white-space: nowrap;
}
/* 结算按钮 */
.checkout-btn, .delete-btn {
background-color: #ff5000;
color: white;
border: none;
border-radius: 25px;
padding: 8px 20px;
font-size: 14px;
white-space: nowrap;
flex-shrink: 0;
}
.delete-btn {
background-color: #ff3b30; /* 红色删除按钮 */
padding: 8px 25px;
}
/* 全选区域 */
.select-all {
display: flex;
align-items: center;
}
.select-all-text {
margin-left: 8px;
font-size: 14px;
color: #333;
white-space: nowrap;
}
/* 响应式调整 */
/* 手机端小屏幕优化 */
@media screen and (max-width: 375px) {
.action-bar-content {
gap: 8px;
}
.total-text {
font-size: 13px;
}
.total-price {
font-size: 16px;
}
.checkout-btn, .delete-btn {
padding: 8px 15px;
font-size: 13px;
}
.select-all-text {
font-size: 13px;
}
}
/* 平板端优化 */
@media screen and (min-width: 768px) {
.cart-action-bar {
margin: 20px auto;
max-width: 95%;
padding: 20px;
}
.action-bar-content {
gap: 20px;
}
.total-price {
font-size: 20px;
}
.checkout-btn, .delete-btn {
padding: 10px 30px;
font-size: 16px;
}
}
/* 桌面端优化 */
@media screen and (min-width: 1024px) {
.cart-action-bar {
max-width: 1200px;
padding: 20px 30px;
}
.action-bar-content {
justify-content: space-between;
}
.total-info {
margin-right: 30px;
}
.total-text {
font-size: 16px;
}
.total-price {
font-size: 22px;
}
.checkout-btn, .delete-btn {
padding: 12px 40px;
font-size: 16px;
}
.select-all-text {
font-size: 16px;
}
}
/* 大屏幕优化 */
@media screen and (min-width: 1400px) {
.cart-action-bar {
max-width: 1400px;
}
}
</style>