Files
medical-mall/pages/mall/consumer/indexback.uvue
2026-01-23 16:47:05 +08:00

1540 lines
31 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/index.uvue -->
<template>
<view class="consumer-home">
<!-- 自定义顶部导航栏(简化版) -->
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-content">
<view class="location" @click="showCityPicker">
<text class="location-icon">📍</text>
<text class="location-text">{{ currentCity }}</text>
<text class="location-arrow">▼</text>
</view>
<view class="nav-icons">
<view class="icon-item" @click="navigateToMessages">
<text class="icon">💬</text>
<text v-if="unreadMessageCount > 0" class="message-badge">{{ unreadMessageCount }}</text>
</view>
<view class="icon-item" @click="navigateToCart">
<text class="icon">🛒</text>
<text v-if="cartCount > 0" class="cart-badge">{{ cartCount }}</text>
</view>
</view>
</view>
</view>
<!-- 主内容区 -->
<scroll-view
scroll-y
class="main-content"
:style="{ height: scrollViewHeight + 'px' }"
refresher-enabled
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
@scrolltolower="loadMore"
:show-scrollbar="false"
>
<!-- 商品分类区域 - 修复横向滚动 -->
<view class="category-section">
<scroll-view
scroll-x
class="category-scroll"
:show-scrollbar="false"
:scroll-left="scrollLeft"
@scroll="onScroll"
>
<view class="category-container">
<view
v-for="(category, index) in categoryList"
:key="category.id"
:class="['category-item', { active: activeCategory === category.id }]"
@click="switchCategory(category.id, index)"
>
<view class="category-icon-wrapper">
<text class="category-icon">{{ category.icon }}</text>
</view>
<text class="category-name">{{ category.name }}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 搜索栏 -->
<view class="search-section" @click="navigateToSearch">
<view class="search-container">
<view class="search-box">
<text class="search-icon">🔍</text>
<text class="search-placeholder">搜索商品/品牌/店铺</text>
</view>
</view>
</view>
<!-- 轮播图 -->
<view class="banner-section">
<swiper
class="banner-swiper"
:autoplay="true"
:interval="4000"
:duration="500"
:circular="true"
:indicator-dots="true"
indicator-color="rgba(255,255,255,0.6)"
indicator-active-color="#ff5000"
>
<swiper-item v-for="(banner, index) in bannerList" :key="banner.id">
<image
class="banner-image"
:src="banner.image_url"
mode="aspectFill"
/>
</swiper-item>
</swiper>
</view>
<!-- 快捷入口 -->
<view class="quick-actions">
<view class="action-item" @click="navigateToFlashSale">
<view class="action-icon flash">⚡</view>
<text class="action-text">限时秒杀</text>
</view>
<view class="action-item" @click="navigateToCoupons">
<view class="action-icon coupon">🎫</view>
<text class="action-text">领券中心</text>
</view>
<view class="action-item" @click="navigateToDailyDeals">
<view class="action-icon daily">🔥</view>
<text class="action-text">每日特价</text>
</view>
<view class="action-item" @click="navigateToBrand">
<view class="action-icon brand">🏷️</view>
<text class="action-text">品牌特卖</text>
</view>
</view>
<!-- 限时秒杀 -->
<view class="flash-sale-section">
<view class="section-header">
</view>
<!-- 限时秒杀商品网格 -->
<view class="flash-grid">
<view
v-for="(product, index) in flashSaleProducts"
:key="index"
class="flash-product"
@click="navigateToProduct(product)"
>
<view class="product-image-wrapper">
<image
class="product-image"
:src="product.image"
mode="aspectFill"
/>
<view v-if="product.tag" class="product-tag">{{ product.tag }}</view>
</view>
<view class="price-info">
<text class="flash-price">¥{{ product.price }}</text>
<text class="original-price">¥{{ product.original_price }}</text>
<view class="progress-container">
<view class="progress-bar">
<view class="progress-inner" :style="{ width: product.soldPercent + '%' }"></view>
</view>
<text class="sold-text">已抢{{ product.soldPercent }}%</text>
</view>
</view>
</view>
</view>
</view>
<!-- 为你推荐 - 瀑布流布局 -->
<view class="recommend-section">
<view class="section-header">
<view class="title-with-icon">
<text class="recommend-icon">❤️</text>
<text class="section-title">为你推荐</text>
</view>
</view>
<!-- 瀑布流容器 -->
<view class="waterfall-container">
<!-- 左列 -->
<view class="waterfall-column left-column">
<view
v-for="(product, index) in leftColumnProducts"
:key="product.id"
class="product-card"
@click="navigateToProduct(product)"
>
<view class="product-image-wrapper">
<image
class="product-image"
:src="product.image"
mode="widthFix"
lazy-load="true"
/>
<view v-if="product.tag" class="product-tag">{{ product.tag }}</view>
</view>
<view class="product-info">
<text class="product-title">{{ product.name }}</text>
<view class="price-section">
<view class="current-price">
<text class="price-symbol">¥</text>
<text class="price-value">{{ product.price }}</text>
</view>
<text v-if="product.original_price > product.price" class="original-price">
¥{{ product.original_price }}
</text>
</view>
<view class="product-meta">
<text class="sales-count">{{ product.sales }}人已买</text>
<view class="shop-info" v-if="product.shop">
<text class="shop-name">{{ product.shop }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 右列 -->
<view class="waterfall-column right-column">
<view
v-for="(product, index) in rightColumnProducts"
:key="product.id"
class="product-card"
@click="navigateToProduct(product)"
>
<view class="product-image-wrapper">
<image
class="product-image"
:src="product.image"
mode="widthFix"
lazy-load="true"
/>
<view v-if="product.tag" class="product-tag">{{ product.tag }}</view>
</view>
<view class="product-info">
<text class="product-title">{{ product.name }}</text>
<view class="price-section">
<view class="current-price">
<text class="price-symbol">¥</text>
<text class="price-value">{{ product.price }}</text>
</view>
<text v-if="product.original_price > product.price" class="original-price">
¥{{ product.original_price }}
</text>
</view>
<view class="product-meta">
<text class="sales-count">{{ product.sales }}人已买</text>
<view class="shop-info" v-if="product.shop">
<text class="shop-name">{{ product.shop }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<view v-if="!hasMore && productList.length > 0" class="no-more">
<text>--- 我是有底线的 ---</text>
</view>
</view>
<!-- 底部安全区域 -->
<view class="safe-area"></view>
</scroll-view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
// 响应式数据
const bannerList = ref<any[]>([])
const categoryList = ref<any[]>([])
const productList = ref<any[]>([])
const flashSaleProducts = ref<any[]>([])
const currentCity = ref<string>('北京市')
const refreshing = ref<boolean>(false)
const loading = ref<boolean>(false)
const hasMore = ref<boolean>(true)
const page = ref<number>(1)
const activeCategory = ref<string>('1')
const activeSort = ref<string>('recommend')
const statusBarHeight = ref<number>(0)
const scrollViewHeight = ref<number>(0)
const scrollLeft = ref<number>(0)
const cartCount = ref<number>(0)
const unreadMessageCount = ref<number>(3)
// 倒计时数据
const countdown = reactive({
hours: '02',
minutes: '30',
seconds: '15'
})
// 排序选项
const sortOptions = [
{ id: 'recommend', name: '推荐' },
{ id: 'new', name: '新品' },
{ id: 'hot', name: '热销' },
{ id: 'priceAsc', name: '价格↑' },
{ id: 'priceDesc', name: '价格↓' }
]
// 计算瀑布流列数据
const leftColumnProducts = computed(() => {
return productList.value.filter((_, index) => index % 2 === 0)
})
const rightColumnProducts = computed(() => {
return productList.value.filter((_, index) => index % 2 === 1)
})
// Mock 数据
const mockData = {
banners: [
{
id: '1',
title: '双11狂欢购',
image_url: 'https://picsum.photos/750/350?random=1'
},
{
id: '2',
title: '品牌品质日',
image_url: 'https://picsum.photos/750/350?random=2'
},
{
id: '3',
title: '新人专享礼',
image_url: 'https://picsum.photos/750/350?random=3'
}
],
categories: [
{ id: '1', name: '推荐', icon: '⭐' },
{ id: '2', name: '女装', icon: '👗' },
{ id: '3', name: '男装', icon: '👔' },
{ id: '4', name: '鞋靴', icon: '👠' },
{ id: '5', name: '箱包', icon: '👜' },
{ id: '6', name: '美妆', icon: '💄' },
{ id: '7', name: '数码', icon: '📱' },
{ id: '8', name: '家电', icon: '📺' },
{ id: '9', name: '家居', icon: '🏠' },
{ id: '10', name: '母婴', icon: '👶' },
{ id: '11', name: '食品', icon: '🍎' },
{ id: '12', name: '运动', icon: '⚽' },
{ id: '13', name: '汽车', icon: '🚗' },
{ id: '14', name: '百货', icon: '🛒' },
{ id: '15', name: '图书', icon: '📚' },
{ id: '16', name: '玩具', icon: '🧸' },
{ id: '17', name: '珠宝', icon: '💎' },
{ id: '18', name: '手表', icon: '⌚' },
{ id: '19', name: '宠物', icon: '🐶' },
{ id: '20', name: '文具', icon: '✏️' }
],
flashSaleProducts: [
{
id: '1001',
name: '无线蓝牙耳机',
price: 299,
original_price: 599,
image: 'https://picsum.photos/200/200?random=1',
sales: 150,
soldPercent: 75,
tag: '秒杀'
},
{
id: '1002',
name: '运动T恤',
price: 79,
original_price: 159,
image: 'https://picsum.photos/200/200?random=2',
sales: 200,
soldPercent: 80,
tag: '爆款'
},
{
id: '1003',
name: '智能手环',
price: 199,
original_price: 299,
image: 'https://picsum.photos/200/200?random=3',
sales: 180,
soldPercent: 60,
tag: '新品'
},
{
id: '1004',
name: '电动牙刷',
price: 89,
original_price: 159,
image: 'https://picsum.photos/200/200?random=4',
sales: 250,
soldPercent: 90,
tag: '热卖'
},
{
id: '1005',
name: '保温杯',
price: 49,
original_price: 99,
image: 'https://picsum.photos/200/200?random=5',
sales: 300,
soldPercent: 85,
tag: '秒杀'
},
{
id: '1006',
name: '智能手表',
price: 399,
original_price: 599,
image: 'https://picsum.photos/200/200?random=6',
sales: 180,
soldPercent: 70,
tag: '爆款'
},
{
id: '1007',
name: '运动鞋',
price: 199,
original_price: 299,
image: 'https://picsum.photos/200/200?random=7',
sales: 220,
soldPercent: 80,
tag: '热卖'
},
{
id: '1008',
name: '保温饭盒',
price: 89,
original_price: 129,
image: 'https://picsum.photos/200/200?random=8',
sales: 190,
soldPercent: 75,
tag: '新品'
}
],
products: [
{
id: '2001',
name: '智能手机 5G全网通 大内存',
price: 3999,
original_price: 4999,
image: 'https://picsum.photos/300/400?random=6',
sales: 500,
shop: '官方旗舰店',
tag: '官方'
},
{
id: '2002',
name: '笔记本电脑 轻薄本 学生办公',
price: 5999,
original_price: 6999,
image: 'https://picsum.photos/300/300?random=7',
sales: 300,
shop: '品牌专卖店',
tag: '折扣'
},
{
id: '2003',
name: '运动鞋 透气舒适跑步鞋',
price: 299,
original_price: 499,
image: 'https://picsum.photos/300/500?random=8',
sales: 800,
shop: '运动专营店'
},
{
id: '2004',
name: '电饭煲 智能预约多功能',
price: 399,
original_price: 599,
image: 'https://picsum.photos/300/350?random=9',
sales: 450,
shop: '家电旗舰店',
tag: '热卖'
},
{
id: '2005',
name: '护肤品套装 保湿补水',
price: 299,
original_price: 399,
image: 'https://picsum.photos/300/450?random=10',
sales: 600,
shop: '美妆官方店'
},
{
id: '2006',
name: '儿童玩具积木益智',
price: 199,
original_price: 299,
image: 'https://picsum.photos/300/320?random=11',
sales: 350,
shop: '母婴专营店',
tag: '新品'
},
{
id: '2007',
name: '智能手表 心率监测',
price: 899,
original_price: 1299,
image: 'https://picsum.photos/300/380?random=12',
sales: 280,
shop: '数码旗舰店'
},
{
id: '2008',
name: '羽绒服 冬季保暖',
price: 499,
original_price: 899,
image: 'https://picsum.photos/300/420?random=13',
sales: 420,
shop: '服装旗舰店',
tag: '爆款'
}
]
}
// 生命周期
onMounted(() => {
// 获取状态栏高度
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight || 0
// 计算滚动区域高度
const windowHeight = systemInfo.windowHeight
const tabBarHeight = 50 // 假设tabBar高度为50px
scrollViewHeight.value = windowHeight - statusBarHeight.value - tabBarHeight
// 加载数据
loadMockData()
setupCountdown()
// 模拟获取购物车数量和未读消息数
cartCount.value = Math.floor(Math.random() * 5) + 1
})
onUnmounted(() => {
// 清理定时器
if (countdownTimer.value !== null) {
clearInterval(countdownTimer.value)
}
})
// 加载Mock数据
const loadMockData = () => {
bannerList.value = mockData.banners || []
categoryList.value = mockData.categories || []
flashSaleProducts.value = mockData.flashSaleProducts || []
productList.value = mockData.products || []
}
// 倒计时定时器
const countdownTimer = ref<any>(null)
const setupCountdown = () => {
countdownTimer.value = setInterval(() => {
let hours = parseInt(countdown.hours)
let minutes = parseInt(countdown.minutes)
let seconds = parseInt(countdown.seconds)
seconds--
if (seconds < 0) {
seconds = 59
minutes--
if (minutes < 0) {
minutes = 59
hours--
if (hours < 0) {
// 重置倒计时
hours = 2
minutes = 30
seconds = 15
}
}
}
countdown.hours = hours.toString().padStart(2, '0')
countdown.minutes = minutes.toString().padStart(2, '0')
countdown.seconds = seconds.toString().padStart(2, '0')
}, 1000)
}
// 事件处理函数
const showCityPicker = () => {
uni.showActionSheet({
itemList: ['北京市', '上海市', '广州市', '深圳市', '其他城市'],
success: (res) => {
const cities = ['北京市', '上海市', '广州市', '深圳市', '其他城市']
currentCity.value = cities[res.tapIndex]
}
})
}
// 切换商品分类
const switchCategory = (categoryId: string, index: number) => {
activeCategory.value = categoryId
// 这里可以添加根据分类筛选商品的逻辑
console.log('切换到分类:', categoryId)
// 滚动到选中的分类
const itemWidth = 80 // 每个分类项的宽度包括margin
scrollLeft.value = index * itemWidth
}
const switchSort = (sortId: string) => {
activeSort.value = sortId
// 这里可以添加根据排序方式筛选商品的逻辑
}
// 滚动事件
const onScroll = (e: any) => {
scrollLeft.value = e.detail.scrollLeft
}
// 下拉刷新
const onRefresh = () => {
refreshing.value = true
setTimeout(() => {
loadMockData()
refreshing.value = false
uni.showToast({
title: '刷新成功',
icon: 'success'
})
}, 1000)
}
// 上拉加载更多
const loadMore = () => {
if (!loading.value && hasMore.value) {
loading.value = true
setTimeout(() => {
// 模拟加载更多数据
const newProducts = [...mockData.products].map((item, index) => ({
...item,
id: `300${index}`,
price: item.price + Math.floor(Math.random() * 100)
}))
productList.value = [...productList.value, ...newProducts]
loading.value = false
hasMore.value = productList.value.length < 20 // 假设最多显示20个商品
}, 1500)
}
}
// 导航函数 - 修改消息为跳转到消息tab页
const navigateToSearch = () => uni.navigateTo({ url: '/pages/mall/consumer/search' })
const navigateToCategory = (category?: any) => {
if (category) {
uni.navigateTo({ url: `/pages/mall/consumer/category?id=${category.id}&name=${category.name}` })
} else {
uni.switchTab({ url: '/pages/mall/consumer/category' })
}
}
const navigateToProduct = (product: any) => {
uni.navigateTo({ url: `/pages/mall/consumer/product-detail?id=${product.id}` })
}
const navigateToCoupons = () => uni.navigateTo({ url: '/pages/mall/consumer/coupons' })
const navigateToMessages = () => uni.switchTab({ url: '/pages/mall/consumer/messages' })
const navigateToFlashSale = () => uni.navigateTo({ url: '/pages/mall/consumer/flash-sale' })
const navigateToBrand = () => uni.navigateTo({ url: '/pages/mall/consumer/brand' })
const navigateToCart = () => uni.switchTab({ url: '/pages/mall/consumer/cart' })
const navigateToDailyDeals = () => uni.navigateTo({ url: '/pages/mall/consumer/daily-deals' })
const navigateToGroupBuy = () => uni.navigateTo({ url: '/pages/mall/consumer/group-buy' })
</script>
<style>
/* 重置默认样式 - 确保不受全局样式影响 */
.consumer-home * {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.consumer-home {
width: 100%;
min-height: 100vh;
background: #f5f5f5;
display: flex;
flex-direction: column;
position: relative;
}
/* 自定义导航栏 - 简化版 */
.custom-navbar {
background: #ff5000;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
}
.nav-content {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
color: white;
}
.location {
display: flex;
align-items: center;
flex-shrink: 0;
padding: 5px 10px;
background: rgba(255, 255, 255, 0.2);
border-radius: 15px;
}
.location-icon {
font-size: 14px;
margin-right: 4px;
}
.location-text {
font-size: 14px;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 60px;
}
.location-arrow {
font-size: 10px;
margin-left: 4px;
color: rgba(255, 255, 255, 0.8);
}
.nav-icons {
display: flex;
align-items: center;
gap: 15px;
}
.icon-item {
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
position: relative;
}
.icon {
font-size: 20px;
}
.message-badge, .cart-badge {
position: absolute;
top: -5px;
right: -5px;
background: #ff3b30;
color: white;
font-size: 10px;
width: 16px;
height: 16px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
/* 主内容区 */
.main-content {
background: #f5f5f5;
margin-top: 44px;
width: 100%;
}
/* 商品分类区域 - 修复横向滚动 */
.category-section {
background: white;
width: 100%;
padding: 15px 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
margin-bottom: 5px;
position: relative;
overflow: hidden;
}
/* 商品分类横向滚动区域 */
.category-scroll {
white-space: nowrap;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
height: 90px;
}
.category-container {
display: flex;
flex-direction: row;
padding: 10px 15px;
}
.category-item {
flex-shrink: 0;
margin-right: 15px;
width: 70px;
height: 70px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
position: relative;
}
.category-item.active .category-icon-wrapper {
background: #ff5000;
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
}
.category-item.active .category-icon {
color: white;
}
.category-item.active .category-name {
color: #ff5000;
font-weight: bold;
}
/* 添加活动指示器 */
.category-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 3px;
background: #ff5000;
border-radius: 2px;
}
.category-icon-wrapper {
width: 48px;
height: 48px;
border-radius: 24px;
background: linear-gradient(135deg, #f5f5f5, #e8e8e8);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 6px;
transition: all 0.3s ease;
}
.category-icon {
font-size: 24px;
color: #666;
transition: all 0.3s ease;
}
.category-name {
font-size: 12px;
color: #333;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
line-height: 1.2;
transition: all 0.3s ease;
}
/* 搜索栏 */
.search-section {
background: white;
padding: 12px 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.search-container {
width: 100%;
}
.search-box {
background: #f5f5f5;
border-radius: 25px;
padding: 12px 20px;
display: flex;
align-items: center;
width: 100%;
height: 45px;
border: 1px solid #eee;
}
.search-icon {
color: #999;
margin-right: 10px;
font-size: 18px;
}
.search-placeholder {
color: #999;
font-size: 15px;
flex: 1;
}
/* 轮播图区域 */
.banner-section {
background: white;
width: 100%;
overflow: hidden;
margin-top: 5px;
}
.banner-swiper {
height: 200px;
width: 100%;
}
.banner-image {
width: 100%;
height: 100%;
display: block;
}
/* 快捷入口 - 横向排列 */
.quick-actions {
background: white;
padding: 20px 0;
margin: 10px;
border-radius: 12px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
width: calc(100% - 20px);
}
.action-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 20%;
flex-shrink: 0;
}
.action-icon {
width: 48px;
height: 48px;
border-radius: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
margin-bottom: 8px;
}
.action-icon.flash {
background: linear-gradient(135deg, #ff3b30, #ff9500);
color: white;
}
.action-icon.coupon {
background: linear-gradient(135deg, #34c759, #30d158);
color: white;
}
.action-icon.daily {
background: linear-gradient(135deg, #ff9500, #ffcc00);
color: white;
}
.action-icon.brand {
background: linear-gradient(135deg, #af52de, #ff2d55);
color: white;
}
.action-icon.group {
background: linear-gradient(135deg, #007aff, #5856d6);
color: white;
}
.action-text {
font-size: 13px;
color: #333;
font-weight: 500;
text-align: center;
width: 100%;
}
/* 限时秒杀 - 新版横向布局 */
.flash-sale-section {
background: linear-gradient(135deg, #fff0e8, #ffece6);
margin: 10px;
border-radius: 12px;
padding: 18px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #ffddd1;
width: calc(100% - 20px);
}
/* 限时秒杀头部 - 横向排列 */
.section-header {
margin-bottom: 18px;
width: 100%;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
gap: 15px;
}
.title-with-icon {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.flash-icon, .recommend-icon {
color: #ff5000;
font-size: 20px;
}
.section-title {
font-size: 18px;
font-weight: bold;
color: #ff5000;
white-space: nowrap;
}
/* 倒计时样式调整 - 横向排列 */
.countdown-wrapper {
display: flex;
align-items: center;
gap: 8px;
background: #ff5000;
padding: 6px 12px;
border-radius: 6px;
white-space: nowrap;
flex-shrink: 0;
}
.countdown-label {
font-size: 13px;
color: white;
font-weight: 500;
}
.time-box {
display: flex;
align-items: center;
gap: 3px;
}
.time {
background: white;
color: #ff5000;
padding: 4px 8px;
border-radius: 4px;
font-size: 14px;
min-width: 26px;
text-align: center;
font-weight: bold;
}
.colon {
color: white;
font-size: 14px;
font-weight: bold;
}
.more-link {
display: flex;
align-items: center;
color: #999;
font-size: 14px;
white-space: nowrap;
flex-shrink: 0;
}
.more-link .arrow {
margin-left: 5px;
font-size: 18px;
}
/* 限时秒杀商品网格布局 */
.flash-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
width: 100%;
}
.flash-product {
background: white;
border-radius: 10px;
overflow: hidden;
border: 1px solid #ffddd1;
box-shadow: 0 3px 10px rgba(255, 80, 0, 0.12);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.flash-product:active {
transform: scale(0.98);
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.2);
}
.product-image-wrapper {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%; /* 保持正方形 */
overflow: hidden;
}
.product-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
}
.product-tag {
position: absolute;
top: 8px;
left: 8px;
background: #ff5000;
color: white;
font-size: 11px;
padding: 3px 10px;
border-radius: 12px;
font-weight: bold;
z-index: 1;
}
.price-info {
padding: 12px;
display: flex;
flex-direction: column;
align-items: center;
}
.flash-price {
color: #ff5000;
font-size: 18px;
font-weight: bold;
text-align: center;
width: 100%;
}
.original-price {
color: #999;
font-size: 13px;
text-decoration: line-through;
margin: 6px 0;
text-align: center;
width: 100%;
}
.progress-container {
width: 100%;
margin-top: 8px;
}
.progress-bar {
width: 100%;
height: 8px;
background: #ffece6;
border-radius: 4px;
overflow: hidden;
}
.progress-inner {
height: 100%;
background: linear-gradient(90deg, #ff9500, #ff5000);
border-radius: 4px;
}
.sold-text {
font-size: 11px;
color: #ff5000;
text-align: center;
width: 100%;
margin-top: 4px;
}
/* 为你推荐 - 瀑布流布局 */
.recommend-section {
background: white;
margin: 10px;
border-radius: 12px;
padding: 18px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
width: calc(100% - 20px);
}
/* 为你推荐头部 */
.recommend-section .section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 18px;
}
/* 排序选项 - 横向排列 */
.sort-options {
display: flex;
gap: 15px;
align-items: center;
flex-wrap: nowrap;
overflow-x: auto;
padding-bottom: 5px;
}
.sort-option {
font-size: 14px;
color: #666;
padding: 5px 0;
position: relative;
white-space: nowrap;
flex-shrink: 0;
}
.sort-option.active {
color: #ff5000;
font-weight: bold;
}
.sort-option.active::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
background: #ff5000;
border-radius: 1px;
}
/* 瀑布流布局 */
.waterfall-container {
display: flex;
justify-content: space-between;
gap: 12px;
width: 100%;
margin-top: 18px;
}
.waterfall-column {
flex: 1;
display: flex;
flex-direction: column;
gap: 12px;
}
.left-column {
margin-right: 6px;
}
.right-column {
margin-left: 6px;
}
.product-card {
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
width: 100%;
}
.product-image-wrapper {
position: relative;
width: 100%;
background: #f8f8f8;
}
.product-image {
width: 100%;
display: block;
}
.product-info {
padding: 15px;
}
.product-title {
font-size: 15px;
color: #333;
line-height: 1.4;
height: 42px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 12px;
font-weight: 500;
}
.price-section {
display: flex;
align-items: baseline;
margin-bottom: 10px;
}
.current-price {
color: #ff5000;
}
.price-symbol {
font-size: 13px;
}
.price-value {
font-size: 20px;
font-weight: bold;
}
.original-price {
color: #999;
font-size: 13px;
text-decoration: line-through;
margin-left: 10px;
}
.product-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
}
.sales-count {
color: #999;
}
.shop-info {
display: flex;
align-items: center;
}
.shop-name {
color: #666;
}
/* 加载状态 */
.loading-container {
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.loading-spinner {
width: 30px;
height: 30px;
border: 3px solid #f0f5ff;
border-top-color: #ff5000;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
color: #999;
font-size: 14px;
}
.no-more {
text-align: center;
color: #999;
font-size: 13px;
padding: 30px 0;
border-top: 1px solid #f0f0f0;
margin-top: 10px;
width: 100%;
}
/* 安全区域 */
.safe-area {
height: 20px;
width: 100%;
}
/* 为分类项添加点击反馈 */
.category-item:active {
opacity: 0.7;
transform: scale(0.98);
}
/* 确保分类图标在点击时有更好的视觉效果 */
.category-icon-wrapper:active {
transform: scale(0.95);
}
/* 响应式适配 */
@media screen and (max-width: 320px) {
.category-item {
width: 65px;
margin-right: 12px;
}
.flash-grid {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
/* 限时秒杀头部适配小屏幕 */
.header-content {
flex-wrap: wrap;
gap: 10px;
}
.countdown-wrapper {
order: 3;
width: 100%;
justify-content: center;
margin-top: 5px;
}
.more-link {
order: 2;
}
.sort-options {
gap: 12px;
font-size: 13px;
}
}
@media screen and (min-width: 321px) and (max-width: 375px) {
.category-item {
width: 68px;
margin-right: 14px;
}
.flash-grid {
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.header-content {
flex-wrap: wrap;
gap: 10px;
}
.countdown-wrapper {
order: 3;
width: 100%;
justify-content: center;
margin-top: 5px;
}
.more-link {
order: 2;
}
.sort-options {
gap: 15px;
font-size: 14px;
}
}
@media screen and (min-width: 376px) and (max-width: 414px) {
.category-item {
width: 72px;
margin-right: 15px;
}
.flash-grid {
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.header-content {
flex-wrap: nowrap;
gap: 15px;
}
.countdown-wrapper {
order: unset;
width: auto;
justify-content: flex-start;
margin-top: 0;
}
.more-link {
order: unset;
}
.sort-options {
gap: 18px;
font-size: 14px;
}
}
@media screen and (min-width: 415px) {
.category-item {
width: 75px;
margin-right: 18px;
}
.flash-grid {
grid-template-columns: repeat(4, 1fr);
gap: 15px;
}
.header-content {
flex-wrap: nowrap;
gap: 20px;
}
.sort-options {
gap: 20px;
font-size: 14px;
}
}
/* 针对平板设备的适配 */
@media screen and (min-width: 768px) {
.flash-grid {
grid-template-columns: repeat(5, 1fr);
gap: 16px;
}
.flash-product {
border-radius: 12px;
}
.product-image-wrapper {
padding-bottom: 100%;
}
.sort-options {
gap: 25px;
font-size: 15px;
}
}
</style>