955 lines
25 KiB
Vue
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.

<template>
<view class="page">
<!-- 背景装饰 -->
<view class="bg-decoration"></view>
<!-- 顶部导航栏 (搜索) -->
<view class="nav-header">
<view class="brand-logo">
<text class="brand-text">柯大鸭潮玩</text>
<view class="brand-star"></view>
</view>
<view class="search-bar">
<text class="search-icon">🔍</text>
<text class="search-placeholder">搜索商品</text>
</view>
</view>
<!-- 滚动区域 -->
<scroll-view class="main-content" scroll-y>
<!-- Banner 区域 -->
<view class="banner-box">
<swiper class="banner-swiper" circular autoplay interval="4000" duration="500">
<swiper-item v-for="b in displayBanners" :key="b.id">
<image v-if="b.image" class="banner-image" :src="b.image" mode="aspectFill" @tap="onBannerTap(b)" />
<view v-else class="banner-fallback">
<text class="banner-fallback-text">{{ b.title || '柯大鸭潮玩 V6.0' }}</text>
<text class="banner-tag">功能更新UI优化全面来袭</text>
</view>
</swiper-item>
</swiper>
</view>
<!-- 通知栏 -->
<view class="notice-bar" @tap="onNoticeTap">
<view class="notice-tag">通知</view>
<swiper class="notice-swiper" vertical circular autoplay interval="3000" duration="300">
<swiper-item v-for="n in displayNotices" :key="n.id">
<view class="notice-item">{{ n.text }}</view>
</swiper-item>
</swiper>
<view class="notice-more">查看详情</view>
</view>
<!-- 玩法分类专区 -->
<view class="gameplay-section">
<view class="section-header">
<text class="section-title">玩法分类</text>
</view>
<view class="gameplay-grid-v2">
<!-- 上排两大核心 -->
<view class="grid-row-top">
<view class="game-card-large card-yifan" @tap="navigateTo('/pages/activity/list/index?category=一番赏')">
<view class="card-bg-decoration"></view>
<view class="card-content-large">
<text class="card-title-large">一番赏</text>
<view class="card-tag-large">欧皇擂台</view>
<image class="card-mascot-large" src="https://via.placeholder.com/150/90EE90/000000?text=YI" mode="aspectFit" />
</view>
</view>
<view class="game-card-large card-wuxian" @tap="navigateTo('/pages/activity/list/index?category=无限赏')">
<view class="card-content-large">
<text class="card-title-large">无限赏</text>
<view class="card-tag-large yellow">一发入魂</view>
<image class="card-mascot-large" src="https://via.placeholder.com/150/FFD700/000000?text=WU" mode="aspectFit" />
</view>
</view>
</view>
<!-- 下排三小功能 -->
<view class="grid-row-bottom">
<view class="game-card-small card-match" @tap="navigateTo('/pages/activity/list/index?category=对对碰')">
<text class="card-title-small">对对碰</text>
<text class="card-subtitle-small">碰一碰消除</text>
<image class="card-icon-small" src="https://via.placeholder.com/80/FFB6C1/000000?text=Match" mode="aspectFit" />
</view>
<view class="game-card-small card-tower" @tap="navigateTo('/pages/activity/list/index?category=爬塔')">
<text class="card-title-small">爬塔</text>
<text class="card-subtitle-small">层层挑战</text>
<image class="card-icon-small" src="https://via.placeholder.com/80/9370DB/000000?text=Tower" mode="aspectFit" />
</view>
<view class="game-card-small card-more" @tap="navigateTo('#')">
<text class="card-title-small">更多</text>
<text class="card-subtitle-small">敬请期待</text>
<image class="card-icon-small" src="https://via.placeholder.com/80/E0E0E0/000000?text=More" mode="aspectFit" />
</view>
</view>
</view>
</view>
<!-- 推荐活动列表 -->
<view class="activity-section">
<view class="section-header">
<text class="section-title">推荐活动</text>
</view>
<view v-if="activeGroupItems.length" class="activity-grid-list">
<view class="activity-item" v-for="a in activeGroupItems" :key="a.id" @tap="onActivityTap(a)">
<view class="activity-thumb-box">
<image v-if="a.image" class="activity-thumb" :src="a.image" mode="aspectFill" />
<view v-else class="banner-fallback mini">
<text class="banner-fallback-text mini">{{ a.title }}</text>
</view>
<!-- 热门标签 -->
<view class="activity-tag-hot">HOT</view>
</view>
<view class="activity-info">
<text class="activity-name">{{ a.title }}</text>
<view class="activity-row">
<text class="activity-desc" v-if="a.subtitle">{{ a.subtitle }}</text>
<view class="activity-btn-go">GO</view>
</view>
</view>
</view>
</view>
<view v-else class="activity-empty">暂无更多活动</view>
</view>
<!-- 底部垫高 -->
<view style="height: 40rpx"></view>
</scroll-view>
</view>
</template>
<script>
import { authRequest, request } from '../../utils/request.js'
export default {
data() {
return {
notices: [],
banners: [],
activities: [],
selectedGroupName: ''
}
},
computed: {
displayNotices() {
if (Array.isArray(this.notices) && this.notices.length) return this.notices
return [
{ id: 'n1', text: '欢迎光临' },
{ id: 'n2', text: '最新活动敬请期待' }
]
},
displayBanners() {
if (Array.isArray(this.banners) && this.banners.length) return this.banners
return [
{ id: 'ph-1', title: '精彩内容即将上线', image: '' },
{ id: 'ph-2', title: '敬请期待', image: '' },
{ id: 'ph-3', title: '更多活动请关注', image: '' }
]
},
activityGroups() {
const list = Array.isArray(this.activities) ? this.activities : []
const map = new Map()
list.forEach(a => {
const key = (a.category_name || '').trim() || '其他'
if (!map.has(key)) map.set(key, [])
map.get(key).push(a)
})
return Array.from(map.entries()).map(([name, items]) => ({ name, items }))
},
activeGroupItems() {
// Return ALL activities without filtering by group
return Array.isArray(this.activities) ? this.activities : []
}
},
onShow() {
const token = uni.getStorageSync('token')
const phoneBound = !!uni.getStorageSync('phone_bound')
if (!token || !phoneBound) {
uni.showModal({
title: '提示',
content: '请先登录并绑定手机号',
confirmText: '去登录',
success: (res) => {
if (res.confirm) {
uni.navigateTo({ url: '/pages/login/index' })
}
}
})
}
try { console.log('home onShow', { token: !!token, phoneBound }) } catch (_) {}
this.loadHomeData()
},
methods: {
onSelectGroup(name) {
this.selectedGroupName = String(name || '')
},
updateSelectedGroup() {
// No-op as we now show all
},
toArray(x) { return Array.isArray(x) ? x : [] },
unwrap(list) {
if (Array.isArray(list)) return list
const obj = list || {}
const arr = obj.list || obj.items || obj.data || []
return Array.isArray(arr) ? arr : []
},
cleanUrl(u) {
const s = String(u || '').trim()
const m = s.match(/https?:\/\/[^\s'"`]+/)
if (m && m[0]) return m[0]
return s.replace(/[`'\"]/g, '').trim()
},
apiGet(url) {
const token = uni.getStorageSync('token')
const fn = token ? authRequest : request
return fn({ url })
},
normalizeNotices(list) {
const arr = this.unwrap(list)
return arr.map((i, idx) => ({
id: i.id ?? String(idx),
text: i.content ?? i.text ?? i.title ?? ''
})).filter(i => i.text)
},
normalizeBanners(list) {
const arr = this.unwrap(list)
const mapped = arr.map((i, idx) => ({
id: i.id ?? String(idx),
title: i.title ?? '',
image: this.cleanUrl(i.imageUrl ?? i.image_url ?? i.image ?? i.img ?? i.pic ?? ''),
link: this.cleanUrl(i.linkUrl ?? i.link_url ?? i.link ?? i.url ?? ''),
sort: typeof i.sort === 'number' ? i.sort : 0
})).filter(i => i.image)
mapped.sort((a, b) => a.sort - b.sort)
return mapped
},
normalizeActivities(list) {
const arr = this.unwrap(list)
const mapped = arr.map((i, idx) => ({
id: i.id ?? String(idx),
image: this.cleanUrl(i.image ?? i.banner ?? i.coverUrl ?? i.cover_url ?? i.img ?? i.pic ?? ''),
title: i.title ?? i.name ?? '',
subtitle: this.buildActivitySubtitle(i),
link: this.cleanUrl(i.linkUrl ?? i.link_url ?? i.link ?? i.url ?? ''),
category_name: (i.category_name ?? i.categoryName ?? '').trim(),
category_id: i.activity_category_id ?? i.category_id ?? i.categoryId ?? null
})).filter(i => i.image || i.title)
return mapped
},
buildActivitySubtitle(i) {
const base = i.subTitle ?? i.sub_title ?? i.subtitle ?? i.desc ?? i.description ?? ''
if (base) return base
const cat = i.category_name ?? i.categoryName ?? ''
const price = (i.price_draw !== undefined && i.price_draw !== null) ? `${(Number(i.price_draw || 0) / 100).toFixed(2)}` : ''
const parts = [cat, price].filter(Boolean)
return parts.join(' · ')
},
async loadHomeData() {
// Notices
try {
const nData = await this.apiGet('/api/app/notices')
this.notices = this.normalizeNotices(nData)
} catch (e) {
this.notices = []
}
// Banners
try {
const bData = await this.apiGet('/api/app/banners')
this.banners = this.normalizeBanners(bData)
} catch (e) {
this.banners = []
}
// Activities
try {
const acData = await this.apiGet('/api/app/activities')
this.activities = this.normalizeActivities(acData)
} catch (e) {
this.activities = []
}
},
onBannerTap(b) {
const imgs = (Array.isArray(this.banners) ? this.banners : []).map(x => x.image).filter(Boolean)
const current = b && b.image
if (current) {
uni.previewImage({ urls: imgs.length ? imgs : [current], current })
return
}
if (b.link && /^\/.+/.test(b.link)) {
uni.navigateTo({ url: b.link })
}
},
onActivityTap(a) {
const name = (a.category_name || a.categoryName || '').trim()
const id = a.id
let path = ''
if (name.includes('一番赏')) path = '/pages/activity/yifanshang/index'
else if (name.includes('无限赏')) path = '/pages/activity/wuxianshang/index'
else if (name.includes('对对碰')) path = '/pages/activity/duiduipeng/index'
else if (name.includes('爬塔')) path = '/pages/activity/pata/index'
if (path && id) {
uni.navigateTo({ url: `${path}?id=${id}` })
return
}
if (a.link && /^\/.+/.test(a.link)) {
uni.navigateTo({ url: a.link })
}
},
navigateTo(url) {
if(url === '#') return
uni.navigateTo({ url })
},
onNoticeTap() {
const content = this.displayNotices.map(n => n.text).join('\n')
uni.showModal({
title: '系统通知',
content: content || '暂无通知',
showCancel: false,
confirmText: '知道了'
})
}
},
// 分享给好友
onShareAppMessage() {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '柯大鸭潮玩 - 开箱惊喜等你来',
path: `/pages/index/index?invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
},
// 分享到朋友圈
onShareTimeline() {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '柯大鸭潮玩 - 开箱惊喜等你来',
query: `invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
}
}
</script>
<style lang="scss">
/* ============================================
柯大鸭潮玩 - 首页样式 (V6.0 Pro Refined)
============================================ */
.page {
padding: 0;
background-color: $bg-page;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* ========== 顶部导航栏 ========== */
.nav-header {
display: flex;
align-items: center;
padding: $spacing-md $spacing-lg;
background: transparent; /* 透明背景,依靠内容区的渐变 */
padding-top: calc($spacing-md + env(safe-area-inset-top));
gap: $spacing-lg;
z-index: 10;
}
.brand-logo {
display: flex;
align-items: center;
}
.brand-text {
font-size: 40rpx;
font-weight: 900;
color: $text-main;
font-style: italic;
letter-spacing: -1rpx;
text-shadow: 0 2rpx 4rpx rgba(255, 255, 255, 0.5);
}
.brand-star {
font-size: 24rpx;
margin-left: 4rpx;
margin-top: -16rpx;
animation: pulse 2s infinite;
}
.search-bar {
flex: 1;
height: 72rpx;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
border-radius: $radius-round;
display: flex;
align-items: center;
padding: 0 $spacing-lg;
border: 1rpx solid rgba(255, 255, 255, 0.6);
box-shadow: $shadow-sm;
transition: all 0.3s ease;
}
.search-bar:active {
background: #fff;
transform: scale(0.98);
}
.search-icon { margin-right: 12rpx; font-size: 32rpx; }
.search-placeholder { color: $text-tertiary; font-size: 28rpx; font-weight: 500; }
/* ========== 滚动主内容区 ========== */
.main-content {
flex: 1;
/* background: linear-gradient(180deg, $bg-secondary 0%, $bg-page 400rpx); */ /* 移除原有背景,使用全局背景装饰 */
position: relative;
z-index: 1; /* 确保内容在背景装饰之上 */
padding-top: $spacing-sm;
}
/* Logo Banner */
.banner-box {
margin: 0 $spacing-lg $spacing-lg;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: $shadow-float;
transform: translateZ(0); /* 开启硬件加速 */
animation: fadeInUp 0.6s ease-out;
}
.banner-swiper, .banner-image, .banner-fallback {
width: 100%;
height: 340rpx; /* 略微增高 */
}
.banner-fallback {
background: linear-gradient(135deg, $bg-secondary, #FFF0D6);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 4rpx dashed $brand-primary-light;
}
.banner-fallback-text {
font-size: 48rpx;
font-weight: 900;
color: $brand-primary;
font-style: italic;
margin-bottom: 12rpx;
text-shadow: 0 2rpx 0 rgba(255,255,255,1);
}
.banner-tag {
background: #1A1A1A;
color: $accent-gold;
padding: 6rpx 20rpx;
border-radius: $radius-round;
font-size: 24rpx;
font-weight: 700;
}
/* 通知栏 */
.notice-bar {
margin: 0 $spacing-lg $spacing-xl;
background: #FFFFFF;
border-radius: $radius-round;
padding: 16rpx 24rpx;
display: flex;
align-items: center;
gap: 16rpx;
box-shadow: $shadow-sm;
animation: fadeInUp 0.6s ease-out 0.1s backwards;
}
.notice-tag {
background: $gradient-brand;
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
font-weight: 700;
box-shadow: 0 2rpx 6rpx rgba($brand-primary, 0.3);
}
.notice-swiper { flex: 1; height: 36rpx; }
.notice-item {
font-size: 26rpx;
color: $text-main;
line-height: 36rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: 500;
}
.notice-more { font-size: 24rpx; color: $text-sub; display: flex; align-items: center; }
.notice-more::after { content: ''; margin-left: 4rpx; font-size: 32rpx; line-height: 24rpx; }
/* 玩法专区 - 方案B2+3 杂志风布局 */
.gameplay-section {
padding: 0 $spacing-lg;
margin-bottom: $spacing-xl;
animation: fadeInUp 0.6s ease-out 0.2s backwards;
}
.section-header {
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.section-title {
font-size: 36rpx;
font-weight: 900;
color: $text-main;
position: relative;
z-index: 1;
padding-left: 12rpx;
font-style: italic;
}
/* 标题装饰竖线 */
.section-title::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%) skewX(-10deg);
width: 8rpx;
height: 32rpx;
background: $brand-primary;
border-radius: 2rpx;
}
.gameplay-grid-v2 {
display: flex;
flex-direction: column;
gap: 20rpx;
}
/* 上排 */
.grid-row-top {
display: flex;
gap: 20rpx;
height: 220rpx; /* 增加高度,展示更多细节 */
}
.game-card-large {
flex: 1;
border-radius: $radius-lg;
position: relative;
overflow: hidden;
padding: 28rpx;
box-shadow: $shadow-card;
transition: transform 0.2s;
}
.game-card-large:active {
transform: scale(0.98);
}
/* 下排 */
.grid-row-bottom {
display: flex;
gap: 20rpx;
height: 160rpx;
}
.game-card-small {
flex: 1;
border-radius: $radius-md;
position: relative;
overflow: hidden;
padding: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
box-shadow: $shadow-sm;
background: white;
transition: all 0.2s;
}
.game-card-small:active {
transform: scale(0.96);
box-shadow: none;
}
/* 内容样式 - 大卡片 */
.card-content-large {
position: relative;
z-index: 2;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.card-title-large {
font-size: 40rpx;
font-weight: 900;
color: #FFF;
font-style: italic;
margin-bottom: 16rpx;
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.1);
}
.card-tag-large {
font-size: 22rpx;
background: rgba(255, 255, 255, 0.9);
color: $text-main;
padding: 6rpx 16rpx;
border-radius: $radius-round;
font-weight: 800;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
backdrop-filter: blur(4px);
}
.card-tag-large.yellow { color: #D97706; }
.card-mascot-large {
position: absolute;
right: -20rpx;
bottom: -30rpx;
width: 180rpx;
height: 180rpx;
transform: rotate(10deg);
filter: drop-shadow(0 8rpx 16rpx rgba(0,0,0,0.2));
}
/* 内容样式 - 小卡片 */
.card-title-small {
font-size: 30rpx;
font-weight: 800;
color: $text-main;
margin-bottom: 6rpx;
z-index: 2;
}
.card-subtitle-small {
font-size: 22rpx;
color: $text-sub;
z-index: 2;
}
.card-icon-small {
position: absolute;
right: -10rpx;
bottom: -10rpx;
width: 100rpx;
height: 100rpx;
opacity: 0.9;
transform: rotate(-10deg);
}
/* 背景配色 - 优化后的渐变 */
.card-yifan {
background: linear-gradient(135deg, $brand-primary 0%, $brand-secondary 100%); /* 品牌橙渐变 */
}
.card-wuxian {
background: $gradient-gold; /* 质感金渐变 */
}
.card-match {
background: linear-gradient(135deg, #FF9A9E 0%, #FECFEF 100%); /* 柔和粉 */
}
.card-match .card-title-small { color: $accent-pink; }
.card-tower {
background: linear-gradient(135deg, #E0C3FC 0%, #8EC5FC 100%); /* 梦幻紫蓝 */
}
.card-tower .card-title-small { color: $accent-purple; }
.card-more {
background: linear-gradient(135deg, $bg-secondary 0%, #E5E7EB 100%); /* 金属灰 */
}
.card-more .card-title-small { color: $text-sub; }
/* 推荐活动列表 */
.activity-section {
padding: 0 $spacing-lg;
animation: fadeInUp 0.6s ease-out 0.3s backwards;
}
.activity-grid-list {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24rpx;
}
.activity-item {
background: #FFFFFF;
border-radius: $radius-lg;
overflow: hidden;
box-shadow: $shadow-card;
display: flex;
flex-direction: column;
transition: transform 0.2s;
}
.activity-item:active {
transform: scale(0.98);
}
.activity-thumb-box {
position: relative;
width: 100%;
padding-bottom: 100%; /* 1:1 正方形 */
}
.activity-thumb {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
background: #EEE;
}
.activity-tag-hot {
position: absolute;
top: 16rpx;
left: 16rpx;
background: $gradient-brand;
color: #fff;
font-size: 20rpx;
padding: 6rpx 14rpx;
border-radius: 8rpx;
font-weight: 800;
box-shadow: 0 4rpx 10rpx rgba($brand-primary, 0.3);
animation: pulse 2s infinite;
}
.activity-info {
padding: 24rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.activity-name {
font-size: 28rpx;
font-weight: 700;
color: $text-main;
margin-bottom: 20rpx;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.activity-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.activity-desc {
font-size: 26rpx;
color: $accent-red; /* 价格/热度颜色 */
font-weight: 800;
}
.activity-btn-go {
background: $text-main;
color: #FFD700;
font-size: 20rpx;
font-weight: 900;
padding: 8rpx 24rpx;
border-radius: $radius-round;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.2);
}
/* 空状态 */
.activity-empty {
text-align: center;
padding: 80rpx 0;
color: $text-tertiary;
font-size: 28rpx;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.05); opacity: 0.9; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8rpx); }
}
/* Banner 入场动画 */
.banner-box {
animation: scaleIn 0.5s ease-out;
}
/* 通知栏滑入 */
.notice-bar {
animation: fadeInUp 0.4s ease-out 0.1s both;
}
/* 玩法卡片交错入场 */
.game-card-large:first-child {
animation: fadeInUp 0.4s ease-out 0.2s both;
}
.game-card-large:last-child {
animation: fadeInUp 0.4s ease-out 0.3s both;
}
.game-card-small:nth-child(1) {
animation: fadeInUp 0.4s ease-out 0.35s both;
}
.game-card-small:nth-child(2) {
animation: fadeInUp 0.4s ease-out 0.4s both;
}
.game-card-small:nth-child(3) {
animation: fadeInUp 0.4s ease-out 0.45s both;
}
/* 活动卡片交错入场 */
.activity-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.activity-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.activity-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.3s both; }
.activity-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.35s both; }
.activity-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.4s both; }
/* 玻璃态搜索栏 */
.search-bar {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
-webkit-backdrop-filter: blur(20rpx);
border: 1rpx solid rgba(255, 255, 255, 0.6);
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
}
.search-bar:active {
transform: scale(0.98);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
}
/* 卡片点击效果 */
.game-card-large,
.game-card-small {
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
cursor: pointer;
}
.game-card-large:active {
transform: scale(0.97);
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
}
.game-card-small:active {
transform: scale(0.95);
box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.08);
}
/* 活动卡片悬浮效果 */
.activity-item {
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.activity-item:active {
transform: scale(0.97) translateY(4rpx);
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
}
/* GO 按钮脉冲动画 */
.activity-btn-go {
animation: pulse 2s infinite;
transition: all 0.2s ease;
}
.activity-btn-go:active {
animation: none;
transform: scale(0.9);
}
/* 图片加载动画 */
.activity-thumb {
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* 热门标签浮动效果 */
.activity-tag-hot {
animation: float 3s ease-in-out infinite;
}
/* Banner 图片悬浮效果 */
.banner-image {
transition: transform 0.4s ease;
}
.banner-box:active .banner-image {
transform: scale(1.02);
}
/* 通知栏点击效果 */
.notice-bar {
transition: all 0.2s ease;
}
.notice-bar:active {
background: #F0F0F0;
transform: scale(0.99);
}
/* 品牌标志动画 */
.brand-star {
animation: float 2s ease-in-out infinite;
}
/* Section 标题增强 */
.section-header {
animation: fadeInUp 0.4s ease-out 0.15s both;
}
/* 增强阴影效果 */
.banner-box {
box-shadow: 0 12rpx 40rpx rgba(0,0,0,0.08);
}
.activity-item {
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.06);
}
/* 热门标签增强 */
.activity-tag-hot {
background: linear-gradient(135deg, rgba(255,77,79,0.9), rgba(255,107,53,0.9));
color: #fff;
text-shadow: 0 1rpx 2rpx rgba(0,0,0,0.2);
}
</style>