consumerm模块完成度90%,完善消费者和商家端数据库表,商品、聊天、订单数据对接好了supabase,和商家端对接了聊天功能,安卓端编译通过了css样式,剩余几个页面在处理函数规范问题
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
<text v-else class="unselected-icon"></text>
|
||||
</view>
|
||||
<text class="shop-icon" @click="navigateToShop(group.shopId, group.merchantId)">🏪</text>
|
||||
<text class="shop-name" @click="navigateToShop(group.shopId, group.merchantId)">{{ group.shopName }}</text>
|
||||
<text class="shop-name" :lines="1" @click="navigateToShop(group.shopId, group.merchantId)">{{ group.shopName }}</text>
|
||||
<text class="shop-arrow" @click="navigateToShop(group.shopId, group.merchantId)">></text>
|
||||
</view>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<view class="item-info">
|
||||
<view class="info-top">
|
||||
<text class="item-name">{{ item.name }}</text>
|
||||
<text class="item-name" :lines="1">{{ item.name }}</text>
|
||||
<text class="item-spec">{{ item.spec }}</text>
|
||||
</view>
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
:src="product.image"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<text class="recommend-name">{{ product.name }}</text>
|
||||
<text class="recommend-name" :lines="2">{{ product.name }}</text>
|
||||
<view class="recommend-bottom">
|
||||
<text class="recommend-price">¥{{ product.price }}</text>
|
||||
<view class="recommend-add-btn" @click.stop="addToCart(product)">
|
||||
@@ -170,55 +170,93 @@ import { ref, computed, onMounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { supabaseService, type CartItem as SupabaseCartItem, type Product } from '@/utils/supabaseService.uts'
|
||||
|
||||
type LocalCartItem = {
|
||||
id: string
|
||||
shopId: string
|
||||
shopName: string
|
||||
name: string
|
||||
price: number
|
||||
image: string
|
||||
spec: string
|
||||
quantity: number
|
||||
selected: boolean
|
||||
productId: string
|
||||
skuId: string
|
||||
merchantId: string
|
||||
}
|
||||
|
||||
type CartGroup = {
|
||||
shopId: string
|
||||
shopName: string
|
||||
merchantId: string
|
||||
items: LocalCartItem[]
|
||||
}
|
||||
|
||||
type RecommendProduct = {
|
||||
id: string
|
||||
shopId: string
|
||||
shopName: string
|
||||
name: string
|
||||
price: number
|
||||
image: string
|
||||
skuId: string
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const cartItems = ref<any[]>([])
|
||||
const recommendProducts = ref<any[]>([])
|
||||
const cartItems = ref<LocalCartItem[]>([])
|
||||
const recommendProducts = ref<RecommendProduct[]>([])
|
||||
const loading = ref<boolean>(false)
|
||||
const statusBarHeight = ref(0)
|
||||
const isManageMode = ref(false)
|
||||
const updatingItems = ref<Set<string>>(new Set()) // Track items being updated to prevent race conditions
|
||||
|
||||
// 计算属性
|
||||
const cartGroups = computed(() => {
|
||||
const groups = new Map<string, any>()
|
||||
cartItems.value.forEach(item => {
|
||||
// Build a unique key for the shop
|
||||
const shopKey = item.shopId || 'unknown'
|
||||
const cartGroups = computed<CartGroup[]>(() => {
|
||||
const groups = new Map<string, CartGroup>()
|
||||
|
||||
cartItems.value.forEach((item: LocalCartItem) => {
|
||||
const shopKey = item.shopId
|
||||
if (!groups.has(shopKey)) {
|
||||
groups.set(shopKey, {
|
||||
shopId: item.shopId,
|
||||
shopName: item.shopName || '商城优选', // Better default name
|
||||
merchantId: item.merchantId, // Add merchantId for navigation
|
||||
items: [] as any[]
|
||||
shopName: item.shopName,
|
||||
merchantId: item.merchantId,
|
||||
items: []
|
||||
})
|
||||
}
|
||||
|
||||
const group = groups.get(shopKey)
|
||||
if (group) {
|
||||
if (group != null) {
|
||||
group.items.push(item)
|
||||
}
|
||||
})
|
||||
return Array.from(groups.values())
|
||||
|
||||
const groupArray: CartGroup[] = []
|
||||
groups.forEach((value: CartGroup) => {
|
||||
groupArray.push(value)
|
||||
})
|
||||
return groupArray
|
||||
})
|
||||
|
||||
const allSelected = computed(() => {
|
||||
return cartItems.value.length > 0 && cartItems.value.every(item => item.selected)
|
||||
return cartItems.value.length > 0 && cartItems.value.every((item: LocalCartItem) => item.selected)
|
||||
})
|
||||
|
||||
const selectedCount = computed(() => {
|
||||
return cartItems.value.filter(item => item.selected).reduce((sum, item) => sum + item.quantity, 0)
|
||||
return cartItems.value.filter((item: LocalCartItem) => item.selected).reduce((sum: number, item: LocalCartItem) => sum + item.quantity, 0)
|
||||
})
|
||||
|
||||
const totalPrice = computed(() => {
|
||||
return cartItems.value
|
||||
.filter(item => item.selected)
|
||||
.reduce((sum, item) => sum + item.price * item.quantity, 0)
|
||||
.filter((item: LocalCartItem) => item.selected)
|
||||
.reduce((sum: number, item: LocalCartItem) => sum + item.price * item.quantity, 0)
|
||||
.toFixed(2)
|
||||
})
|
||||
|
||||
// 检查店铺是否全选
|
||||
const isShopSelected = (shopId: string) => {
|
||||
const group = cartGroups.value.find(g => g.shopId === shopId)
|
||||
return group ? group.items.every(item => item.selected) : false
|
||||
const isShopSelected = (shopId: string): boolean => {
|
||||
const shopItems = cartItems.value.filter((item: LocalCartItem): boolean => item.shopId === shopId)
|
||||
return shopItems.length > 0 && shopItems.every((item: LocalCartItem): boolean => item.selected)
|
||||
}
|
||||
|
||||
const toggleManageMode = () => {
|
||||
@@ -228,7 +266,7 @@ const toggleManageMode = () => {
|
||||
// 初始化页面数据
|
||||
const initPage = () => {
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
statusBarHeight.value = systemInfo.statusBarHeight || 0
|
||||
statusBarHeight.value = systemInfo.statusBarHeight ?? 0
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
@@ -236,10 +274,6 @@ onMounted(() => {
|
||||
initPage()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
loadCartData()
|
||||
})
|
||||
|
||||
// 加载数据
|
||||
const loadCartData = async () => {
|
||||
loading.value = true
|
||||
@@ -249,26 +283,28 @@ const loadCartData = async () => {
|
||||
const supabaseCartItems = await supabaseService.getCartItems()
|
||||
|
||||
// 转换数据格式以匹配前端界面
|
||||
const transformedItems = supabaseCartItems.map((item: SupabaseCartItem) => {
|
||||
const transformedItems = supabaseCartItems.map((item: SupabaseCartItem): LocalCartItem => {
|
||||
// 调试日志:打印每条商品数据的关键字段
|
||||
console.log(`CartItem raw: id=${item.id}, shop_id=${item.shop_id}, shop_name=${item.shop_name}, name=${item.product_name}, price=${item.product_price}`);
|
||||
|
||||
// 关键修复:确保shopId有值,如果后端返回null/undefined,使用'default_shop'作为分组键
|
||||
const shopId = (item.shop_id != null && item.shop_id !== '') ? item.shop_id : 'default_shop'
|
||||
const shopName = (item.shop_name != null && item.shop_name !== '') ? item.shop_name : '商城优选'
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
// 关键修复:确保shopId有值,如果后端返回null/undefined,使用'default_shop'作为分组键
|
||||
shopId: (item.shop_id != null && item.shop_id !== '') ? item.shop_id : 'default_shop',
|
||||
// 关键修复:确保shopName有值
|
||||
shopName: (item.shop_name != null && item.shop_name !== '') ? item.shop_name : '商城优选',
|
||||
name: item.product_name || '未知商品',
|
||||
shopId: shopId,
|
||||
shopName: shopName,
|
||||
name: item.product_name ?? '未知商品',
|
||||
price: item.product_price != null ? item.product_price : 0,
|
||||
image: item.product_image || '/static/images/default-product.png',
|
||||
spec: item.product_specification || '标准规格',
|
||||
quantity: item.quantity || 1,
|
||||
selected: item.selected || false,
|
||||
productId: item.product_id,
|
||||
skuId: item.sku_id,
|
||||
merchantId: item.merchant_id
|
||||
}
|
||||
image: item.product_image ?? '/static/images/default-product.png',
|
||||
spec: item.product_specification ?? '标准规格',
|
||||
quantity: item.quantity ?? 1,
|
||||
selected: item.selected ?? false,
|
||||
productId: item.product_id ?? '',
|
||||
skuId: item.sku_id ?? '',
|
||||
merchantId: item.merchant_id ?? ''
|
||||
} as LocalCartItem
|
||||
})
|
||||
|
||||
console.log('Transformed items count:', transformedItems.length);
|
||||
@@ -284,18 +320,17 @@ const loadCartData = async () => {
|
||||
}
|
||||
|
||||
if (recommends.length > 0) {
|
||||
recommendProducts.value = recommends.map((p: Product) => {
|
||||
return {
|
||||
id: p.id,
|
||||
shopId: p.merchant_id || 'unknown',
|
||||
shopName: p.shop_name || '商城推荐',
|
||||
name: p.name,
|
||||
price: p.base_price,
|
||||
image: p.main_image_url || '/static/images/default-product.png',
|
||||
specification: '', // 推荐列表不显示详细规格
|
||||
specDetails: {}
|
||||
}
|
||||
})
|
||||
recommendProducts.value = recommends.map((p: Product): RecommendProduct => {
|
||||
return {
|
||||
id: p.id,
|
||||
shopId: p.merchant_id ?? 'unknown',
|
||||
shopName: p.shop_name ?? '商城推荐',
|
||||
name: p.name,
|
||||
price: p.base_price,
|
||||
image: p.main_image_url ?? '/static/images/default-product.png',
|
||||
skuId: ''
|
||||
}
|
||||
})
|
||||
} else {
|
||||
recommendProducts.value = []
|
||||
}
|
||||
@@ -307,6 +342,10 @@ const loadCartData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
loadCartData()
|
||||
})
|
||||
|
||||
// 商品操作 - 更新选中状态到Supabase
|
||||
const toggleSelect = async (itemId: string) => {
|
||||
// 乐观更新
|
||||
@@ -329,18 +368,14 @@ const toggleSelect = async (itemId: string) => {
|
||||
}
|
||||
|
||||
const toggleShopSelect = async (shopId: string) => {
|
||||
// 查找该组是否已存在,并判断目标状态
|
||||
const group = cartGroups.value.find((g: any) => g.shopId === shopId)
|
||||
if (!group) return
|
||||
// 获取该店铺下所有商品的ID
|
||||
const shopItems = cartItems.value.filter((item: LocalCartItem): boolean => item.shopId === shopId)
|
||||
if (shopItems.length === 0) return
|
||||
|
||||
// 检查当前是否全选: 如果所有都选中,则目标是全不选(false);否则全选(true)
|
||||
const isAllShopSelected = (group.items as any[]).every((item: any) => item.selected)
|
||||
const isAllShopSelected = shopItems.every((item: LocalCartItem): boolean => item.selected)
|
||||
const newState = !isAllShopSelected
|
||||
|
||||
// 获取该店铺下所有商品的ID
|
||||
const shopItemIds = cartItems.value
|
||||
.filter(item => item.shopId === shopId)
|
||||
.map(item => item.id)
|
||||
const shopItemIds = shopItems.map((item: LocalCartItem): string => item.id)
|
||||
|
||||
// 乐观更新本地状态
|
||||
const oldStates = new Map<string, boolean>()
|
||||
@@ -376,11 +411,11 @@ const toggleSelectAll = async () => {
|
||||
const newSelectedState = !allSelected.value
|
||||
|
||||
// 乐观更新
|
||||
const oldItems = JSON.parse(JSON.stringify(cartItems.value))
|
||||
const selectedItems = cartItems.value.map(item => ({
|
||||
...item,
|
||||
selected: newSelectedState
|
||||
}))
|
||||
const oldItems = JSON.parse(JSON.stringify(cartItems.value)) as LocalCartItem[]
|
||||
const selectedItems = cartItems.value.map((item): LocalCartItem => {
|
||||
item.selected = newSelectedState
|
||||
return item
|
||||
})
|
||||
cartItems.value = selectedItems
|
||||
|
||||
// 更新到Supabase
|
||||
@@ -391,7 +426,7 @@ const toggleSelectAll = async () => {
|
||||
|
||||
if (!success) {
|
||||
console.error('批量更新选中状态失败')
|
||||
cartItems.value = oldItems
|
||||
cartItems.value = oldItems
|
||||
uni.showToast({
|
||||
title: '操作失败',
|
||||
icon: 'none'
|
||||
@@ -450,24 +485,25 @@ const decreaseQuantity = async (itemId: string) => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要从购物车移除该商品吗?',
|
||||
success: async (res) => {
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 从Supabase删除
|
||||
const success = await supabaseService.deleteCartItem(itemId)
|
||||
if (success) {
|
||||
cartItems.value.splice(index, 1)
|
||||
cartItems.value = [...cartItems.value]
|
||||
uni.showToast({
|
||||
title: '已移除',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
console.error('删除商品失败')
|
||||
uni.showToast({
|
||||
title: '删除失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
supabaseService.deleteCartItem(itemId).then((success) => {
|
||||
if (success) {
|
||||
cartItems.value.splice(index, 1)
|
||||
cartItems.value = [...cartItems.value]
|
||||
uni.showToast({
|
||||
title: '已移除',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
console.error('删除商品失败')
|
||||
uni.showToast({
|
||||
title: '删除失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -488,7 +524,7 @@ const deleteSelectedItems = async () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: `确定要删除选中的 ${selectedCount.value} 件商品吗?`,
|
||||
success: async (res) => {
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 获取选中的商品ID
|
||||
const selectedItemIds = cartItems.value
|
||||
@@ -496,27 +532,27 @@ const deleteSelectedItems = async () => {
|
||||
.map(item => item.id)
|
||||
|
||||
// 批量删除到Supabase
|
||||
const success = await supabaseService.batchDeleteCartItems(selectedItemIds)
|
||||
|
||||
if (success) {
|
||||
// 从本地列表移除
|
||||
cartItems.value = cartItems.value.filter(item => !item.selected)
|
||||
|
||||
// 如果购物车删空了,退出管理模式
|
||||
if (cartItems.value.length === 0) {
|
||||
isManageMode.value = false
|
||||
supabaseService.batchDeleteCartItems(selectedItemIds).then((success) => {
|
||||
if (success) {
|
||||
// 从本地列表移除
|
||||
cartItems.value = cartItems.value.filter(item => !item.selected)
|
||||
|
||||
// 如果购物车删空了,退出管理模式
|
||||
if (cartItems.value.length === 0) {
|
||||
isManageMode.value = false
|
||||
}
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
console.error('批量删除商品失败')
|
||||
uni.showToast({
|
||||
title: '删除失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
console.error('批量删除商品失败')
|
||||
uni.showToast({
|
||||
title: '删除失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -525,7 +561,11 @@ const deleteSelectedItems = async () => {
|
||||
const addToCart = async (product: any) => {
|
||||
try {
|
||||
// 调用SupabaseService添加商品到购物车
|
||||
const success = await supabaseService.addToCart(product.id, 1, product.skuId)
|
||||
// 显式访问属性,避免any类型导致的编译错误
|
||||
const target = product as UTSJSONObject
|
||||
const productId = target.getString('id') ?? ''
|
||||
const skuId = target.getString('skuId') ?? ''
|
||||
const success = await supabaseService.addToCart(productId, 1, skuId)
|
||||
if (success) {
|
||||
uni.showToast({
|
||||
title: '已添加到购物车',
|
||||
@@ -553,13 +593,16 @@ const addToCart = async (product: any) => {
|
||||
// 导航函数
|
||||
const navigateToShop = (shopId: string, merchantId: any) => {
|
||||
// Prevent navigation for invalid shops
|
||||
if (!shopId || shopId === 'default_shop' || shopId === 'unknown') return
|
||||
if (shopId == '' || shopId === 'default_shop' || shopId === 'unknown') return
|
||||
|
||||
let url = `/pages/mall/consumer/shop-detail?id=${shopId}`
|
||||
if (merchantId) {
|
||||
url += `&merchantId=${merchantId}`
|
||||
}
|
||||
uni.navigateTo({ url })
|
||||
let url = `/pages/mall/consumer/shop-detail?id=${shopId}`
|
||||
if (merchantId != null) {
|
||||
const mId = `${merchantId}`
|
||||
if (mId !== '' && mId !== 'null' && mId !== 'undefined' && mId !== 'false') {
|
||||
url += `&merchantId=${mId}`
|
||||
}
|
||||
}
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
|
||||
const goShopping = () => {
|
||||
@@ -567,20 +610,50 @@ const goShopping = () => {
|
||||
}
|
||||
|
||||
const navigateToProduct = (product: any) => {
|
||||
console.log('navigateToProduct', product)
|
||||
|
||||
// 使用 JSON 转换确保可以作为 JSONObject 处理,兼容 LocalCartItem 类型和普通对象
|
||||
const productJson = JSON.parse(JSON.stringify(product)) as UTSJSONObject
|
||||
|
||||
// 使用productId(如果存在)作为跳转的商品ID,否则使用id
|
||||
const productId = product.productId || product.id
|
||||
let productId = productJson.getString('productId')
|
||||
if (productId == null || productId == '') {
|
||||
productId = productJson.getString('id')
|
||||
}
|
||||
|
||||
if (productId == null || productId == '') {
|
||||
console.error('无法获取商品ID', product)
|
||||
return
|
||||
}
|
||||
|
||||
// 传递完整的参数,确保商品详情页能正确加载
|
||||
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'))
|
||||
let paramsArr: string[] = []
|
||||
paramsArr.push('id=' + encodeURIComponent(productId))
|
||||
paramsArr.push('productId=' + encodeURIComponent(productId))
|
||||
|
||||
const price = productJson.getNumber('price') ?? 0
|
||||
paramsArr.push('price=' + price)
|
||||
|
||||
let originalPrice = productJson.getNumber('original_price')
|
||||
if (originalPrice == null) {
|
||||
originalPrice = productJson.getNumber('originalPrice')
|
||||
}
|
||||
if (originalPrice == null) {
|
||||
originalPrice = parseFloat((price * 1.2).toFixed(2))
|
||||
}
|
||||
paramsArr.push('originalPrice=' + originalPrice)
|
||||
|
||||
const name = productJson.getString('name') ?? ''
|
||||
paramsArr.push('name=' + encodeURIComponent(name))
|
||||
|
||||
const image = productJson.getString('image') ?? '/static/product1.jpg'
|
||||
paramsArr.push('image=' + encodeURIComponent(image))
|
||||
|
||||
const url = `/pages/mall/consumer/product-detail?${paramsArr.join('&')}`
|
||||
console.log('Navigate to:', url)
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/product-detail?${params.toString()}`
|
||||
url: url
|
||||
})
|
||||
}
|
||||
|
||||
@@ -598,16 +671,16 @@ const goToCheckout = () => {
|
||||
.filter(item => item.selected)
|
||||
.map(item => ({
|
||||
id: item.id,
|
||||
product_id: item.productId || item.id,
|
||||
sku_id: item.skuId || item.id,
|
||||
product_id: item.productId ?? item.id,
|
||||
sku_id: item.skuId ?? item.id,
|
||||
product_name: item.name,
|
||||
shop_id: item.shopId, // 关键:保留shopId用于分组
|
||||
shop_name: item.shopName, // 关键:保留shopName
|
||||
merchant_id: item.merchantId,
|
||||
product_image: item.image,
|
||||
sku_specifications: item.spec,
|
||||
price: Number(item.price), // 确保是数字
|
||||
quantity: Number(item.quantity) // 确保是数字
|
||||
price: item.price, // 确保是数字
|
||||
quantity: item.quantity // 确保是数字
|
||||
}))
|
||||
|
||||
// 关键修复:将结算数据写入 Storage,确保 checkout 页面能稳定获取
|
||||
@@ -623,13 +696,7 @@ const goToCheckout = () => {
|
||||
|
||||
// 跳转到结算页面并传递数据
|
||||
uni.navigateTo({
|
||||
url: '/pages/mall/consumer/checkout',
|
||||
success: (res) => {
|
||||
// 通过eventChannel传递数据 (作为备份)
|
||||
res.eventChannel.emit('acceptData', {
|
||||
selectedItems: selectedItems
|
||||
})
|
||||
}
|
||||
url: '/pages/mall/consumer/checkout'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -637,7 +704,7 @@ const goToCheckout = () => {
|
||||
<style>
|
||||
.cart-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -690,7 +757,7 @@ const goToCheckout = () => {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 4px 12px;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
/* cursor: pointer; REMOVED */
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -707,7 +774,7 @@ const goToCheckout = () => {
|
||||
.action-text {
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 导航栏占位符 */
|
||||
@@ -802,7 +869,7 @@ const goToCheckout = () => {
|
||||
|
||||
.shop-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin-right: 4px;
|
||||
/* 自适应宽度,但不超过剩余空间 */
|
||||
@@ -844,7 +911,7 @@ const goToCheckout = () => {
|
||||
height: 18px;
|
||||
background-color: #ff5000;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
border-radius: 9px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -855,7 +922,7 @@ const goToCheckout = () => {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 50%;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.item-image {
|
||||
@@ -884,11 +951,12 @@ const goToCheckout = () => {
|
||||
font-size: 14px; /* 稍微减小字体 */
|
||||
color: #333;
|
||||
margin-bottom: 2px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1; /* 单行显示 */
|
||||
-webkit-box-orient: vertical;
|
||||
/* display: -webkit-box; REMOVED */
|
||||
/* -webkit-line-clamp: 1; REMOVED */
|
||||
/* -webkit-box-orient: vertical; REMOVED */
|
||||
overflow: hidden;
|
||||
font-weight: 500;
|
||||
font-weight: bold;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.item-spec {
|
||||
@@ -957,9 +1025,12 @@ const goToCheckout = () => {
|
||||
}
|
||||
|
||||
.recommend-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr); /* 手机端默认双列 */
|
||||
gap: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
/* grid-template-columns: repeat(2, 1fr); REMOVED */
|
||||
/* gap: 12px; REMOVED */
|
||||
}
|
||||
|
||||
.recommend-item {
|
||||
@@ -968,13 +1039,15 @@ const goToCheckout = () => {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
width: 48%; /* 替换 grid 1fr auto fit */
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.recommend-image {
|
||||
width: 100%;
|
||||
aspect-ratio: 1; /* 保持正方形比例 */
|
||||
height: auto; /* 自动高度 */
|
||||
object-fit: cover;
|
||||
height: 170px; /* 显式高度 */
|
||||
/* aspect-ratio: 1; REMOVED */
|
||||
/* object-fit: cover; REMOVED */
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
background: #f5f5f5;
|
||||
@@ -987,9 +1060,10 @@ const goToCheckout = () => {
|
||||
line-height: 1.4;
|
||||
height: 36px;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
/* display: -webkit-box; REMOVED */
|
||||
/* -webkit-line-clamp: 2; REMOVED */
|
||||
/* -webkit-box-orient: vertical; REMOVED */
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.recommend-bottom {
|
||||
@@ -1010,7 +1084,7 @@ const goToCheckout = () => {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #ff5000;
|
||||
border-radius: 50%;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -1028,12 +1102,17 @@ const goToCheckout = () => {
|
||||
.cart-list,
|
||||
.recommend-section {
|
||||
margin: 20px auto;
|
||||
max-width: 95%;
|
||||
width: 95%; /* max-width -> width */
|
||||
}
|
||||
|
||||
.recommend-list {
|
||||
grid-template-columns: repeat(4, 1fr); /* 平板显示4列 */
|
||||
gap: 16px;
|
||||
/* grid-template-columns: repeat(4, 1fr); REMOVED */
|
||||
/* gap: 16px; REMOVED */
|
||||
/* Flex 布局参数调整在下方 update */
|
||||
}
|
||||
.recommend-item {
|
||||
width: 23%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,12 +1126,14 @@ const goToCheckout = () => {
|
||||
.cart-list,
|
||||
.recommend-section {
|
||||
margin: 20px auto;
|
||||
max-width: 1200px; /* 限制最大宽度 */
|
||||
width: 96%; /* max-width -> width: percentage is safer */
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
/* 店铺分组在桌面端显示为网格布局 */
|
||||
.shop-group {
|
||||
display: block;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
@@ -1063,14 +1144,14 @@ const goToCheckout = () => {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 12px;
|
||||
padding: 16px 24px;
|
||||
padding: 16px 80px 16px 24px; /* 同步增加右侧内边距 */
|
||||
}
|
||||
|
||||
/* 购物车商品列表转为列表布局 */
|
||||
.cart-item {
|
||||
background: white;
|
||||
border-radius: 0;
|
||||
padding: 15px 30px;
|
||||
padding: 15px 80px 15px 30px; /* 进一步增加右侧内边距 */
|
||||
height: 80px; /* 固定高度 */
|
||||
border-bottom: 1px solid #eee;
|
||||
box-shadow: none;
|
||||
@@ -1137,14 +1218,15 @@ const goToCheckout = () => {
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
/* gap: 40px; REMOVED */
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.item-price {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
margin-bottom: 0;
|
||||
margin-right: 40px; /* Replace gap */
|
||||
}
|
||||
|
||||
.quantity-control {
|
||||
@@ -1155,8 +1237,12 @@ const goToCheckout = () => {
|
||||
|
||||
/* 推荐商品优化 */
|
||||
.recommend-list {
|
||||
grid-template-columns: repeat(5, 1fr); /* 桌面端显示5列 */
|
||||
gap: 20px;
|
||||
/* grid-template-columns: repeat(5, 1fr); REMOVED */
|
||||
/* gap: 20px; REMOVED */
|
||||
}
|
||||
.recommend-item {
|
||||
width: 18%; /* 5列 */
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.recommend-image {
|
||||
@@ -1166,7 +1252,7 @@ const goToCheckout = () => {
|
||||
/* 底部结算栏优化 */
|
||||
.cart-footer {
|
||||
padding: 0 40px;
|
||||
max-width: 100%;
|
||||
width: 100%; /* max-width -> width */
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
|
||||
}
|
||||
@@ -1184,7 +1270,7 @@ const goToCheckout = () => {
|
||||
@media screen and (min-width: 1400px) {
|
||||
.cart-list,
|
||||
.recommend-section {
|
||||
max-width: 1400px;
|
||||
width: 1400px;
|
||||
}
|
||||
|
||||
/* 大屏下购物车商品显示3列 - 移除,保持单列列表 */
|
||||
@@ -1193,11 +1279,14 @@ const goToCheckout = () => {
|
||||
} */
|
||||
|
||||
.recommend-list {
|
||||
grid-template-columns: repeat(6, 1fr); /* 大屏幕显示6列 */
|
||||
/* grid-template-columns: repeat(6, 1fr); REMOVED */
|
||||
}
|
||||
.recommend-item {
|
||||
width: 15%; /* 6 columns approx */
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
max-width: 1400px;
|
||||
width: 1400px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1216,6 +1305,7 @@ const goToCheckout = () => {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
/* gap: 20px; REMOVED from .action-bar-content usually in desktop */
|
||||
}
|
||||
|
||||
.action-left {
|
||||
@@ -1324,12 +1414,12 @@ const goToCheckout = () => {
|
||||
@media screen and (min-width: 768px) {
|
||||
.cart-action-bar {
|
||||
margin: 20px auto;
|
||||
max-width: 95%;
|
||||
width: 95%; /* max-width -> width */
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.action-bar-content {
|
||||
gap: 20px;
|
||||
/* gap: 20px; REMOVED */
|
||||
}
|
||||
|
||||
.total-price {
|
||||
@@ -1339,13 +1429,14 @@ const goToCheckout = () => {
|
||||
.checkout-btn, .delete-btn {
|
||||
padding: 10px 30px;
|
||||
font-size: 16px;
|
||||
margin-left: 20px; /* Replace gap */
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面端优化 */
|
||||
@media screen and (min-width: 1024px) {
|
||||
.cart-action-bar {
|
||||
max-width: 1200px;
|
||||
width: 1200px; /* max-width -> width */
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
@@ -1378,7 +1469,7 @@ const goToCheckout = () => {
|
||||
/* 大屏幕优化 */
|
||||
@media screen and (min-width: 1400px) {
|
||||
.cart-action-bar {
|
||||
max-width: 1400px;
|
||||
width: 1400px; /* max-width -> width */
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user