feat: 首页Hero改造Banner轮播 + 公告栏优化
- Hero: 替换为运营Banner图, swiper轮播结构, 移除文字遮罩, 点击跳转卡列表 - 公告栏: 卡片化圆角阴影, 分类标签(重要/景区/福利), 按类型变色脉冲圆点, 触摸暂停轮播, 右侧更多按钮, 修复橙色圆点被拉伸bug(.promo类名冲突) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+94
-60
@@ -1,31 +1,47 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- Hero: mountain landscape photo -->
|
||||
<view class="hero animate-fade-in-up">
|
||||
<!-- Hero: 运营Banner轮播 -->
|
||||
<view class="hero animate-fade-in-up" @click="goCardDetail()">
|
||||
<swiper class="hero-swiper" autoplay circular :interval="5000">
|
||||
<swiper-item>
|
||||
<image
|
||||
class="hero-bg"
|
||||
src="https://images.pexels.com/photos/28594448/pexels-photo-28594448.jpeg?auto=compress&cs=tinysrgb&w=750"
|
||||
src="https://aliyunoss.hntgov.net/image/2026/04/14/d2bf03167e484ba59f7c2d62879ad07f.jpg"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="hero-overlay" />
|
||||
<view class="hero-inner">
|
||||
<text class="hero-title">爱上萍乡</text>
|
||||
<text class="hero-sub">赣湘之间 · 发现旅途美好</text>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y class="main-scroll">
|
||||
<!-- 公告栏 -->
|
||||
<view v-if="announcements.length" class="notice animate-fade-in-up stagger-1">
|
||||
<view class="notice-tag">
|
||||
<view class="notice-pip animate-pulse" />
|
||||
<view class="notice-pip animate-pulse" :class="`type-${currentNoticeType}`" />
|
||||
<text class="notice-label">公告</text>
|
||||
</view>
|
||||
<swiper class="notice-swiper" vertical autoplay circular :interval="3000" :duration="500">
|
||||
<swiper
|
||||
class="notice-swiper"
|
||||
vertical
|
||||
:autoplay="swiperAutoplay"
|
||||
circular
|
||||
:interval="3000"
|
||||
:duration="500"
|
||||
@change="onNoticeChange"
|
||||
@touchstart="onNoticeTouchStart"
|
||||
@touchend="onNoticeTouchEnd"
|
||||
>
|
||||
<swiper-item v-for="item in announcements" :key="item.id">
|
||||
<view class="notice-item">
|
||||
<text class="notice-type-tag" :class="`type-${item.type}`">{{ item.typeLabel }}</text>
|
||||
<text class="notice-text">{{ item.content }}</text>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="notice-more" @click="goMoreNotice">
|
||||
<text class="notice-more-text">更多</text>
|
||||
<view class="chevron" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 旅游卡 — 大字报风格 -->
|
||||
@@ -102,17 +118,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { scenicSpots } from '../../data/scenic-spots'
|
||||
import type { ScenicSpotItem } from '../../data/scenic-spots'
|
||||
|
||||
/** 公告数据(mock,后续接 API) */
|
||||
const announcements = ref([
|
||||
{ id: 1, content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!' },
|
||||
{ id: 2, content: '超级玩家卡全新上线,40家景区免门票,仅¥198!' },
|
||||
{ id: 3, content: '武功山金顶景区已开放,持卡可免费入园1次。' },
|
||||
{ id: 1, type: 'important', typeLabel: '重要', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!' },
|
||||
{ id: 2, type: 'scenic', typeLabel: '景区', content: '武功山金顶景区已开放,持卡可免费入园1次。' },
|
||||
{ id: 3, type: 'promo', typeLabel: '福利', content: '超级玩家卡全新上线,40家景区免门票,仅¥198!' },
|
||||
])
|
||||
|
||||
/** 公告轮播状态 */
|
||||
const swiperAutoplay = ref(true)
|
||||
const currentNoticeIndex = ref(0)
|
||||
const currentNoticeType = computed(() => announcements.value[currentNoticeIndex.value]?.type || 'scenic')
|
||||
|
||||
function onNoticeChange(e: any) { currentNoticeIndex.value = e.detail.current }
|
||||
function onNoticeTouchStart() { swiperAutoplay.value = false }
|
||||
function onNoticeTouchEnd() { swiperAutoplay.value = true }
|
||||
function goMoreNotice() { uni.showToast({ title: '全部公告开发中', icon: 'none' }) }
|
||||
|
||||
/** 景点山水风景图 */
|
||||
const spotImages: Record<number, string> = {
|
||||
1: 'https://images.unsplash.com/photo-1513415564515-763d91423bdd?fm=jpg&q=80&w=400&h=250&fit=crop',
|
||||
@@ -152,7 +178,7 @@ function goMore() {
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
Hero — mountain landscape photo
|
||||
Hero — 运营Banner轮播
|
||||
============================================ */
|
||||
.hero {
|
||||
position: relative;
|
||||
@@ -160,51 +186,14 @@ function goMore() {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-swiper {
|
||||
width: 100%;
|
||||
height: 340rpx;
|
||||
}
|
||||
|
||||
.hero-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hero-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0.45) 0%,
|
||||
rgba(0, 0, 0, 0.3) 40%,
|
||||
rgba(0, 0, 0, 0.65) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.hero-inner {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: $spacing-16 $spacing-4 $spacing-4;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-family: $font-family-display;
|
||||
font-size: $font-size-3xl;
|
||||
font-weight: $font-weight-bold;
|
||||
color: #fff;
|
||||
line-height: $line-height-tight;
|
||||
margin-bottom: $spacing-1;
|
||||
text-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.hero-sub {
|
||||
font-size: $font-size-sm;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
letter-spacing: 4rpx;
|
||||
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
|
||||
height: 340rpx;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
@@ -213,9 +202,15 @@ function goMore() {
|
||||
.notice-pip {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
min-height: 12rpx;
|
||||
max-height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: $color-accent;
|
||||
flex-shrink: 0;
|
||||
background: $color-accent;
|
||||
|
||||
&.type-important { background: #EF4444; }
|
||||
&.type-scenic { background: #0052FF; }
|
||||
&.type-promo { background: #F59E0B; }
|
||||
}
|
||||
|
||||
.chevron {
|
||||
@@ -251,7 +246,9 @@ function goMore() {
|
||||
align-items: center;
|
||||
background: $color-card;
|
||||
padding: $spacing-2 $spacing-3;
|
||||
border-bottom: $border-width solid $color-border;
|
||||
margin: $spacing-2 $spacing-3 0;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.notice-tag {
|
||||
@@ -260,6 +257,7 @@ function goMore() {
|
||||
margin-right: $spacing-2;
|
||||
flex-shrink: 0;
|
||||
gap: $spacing-1;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.notice-label {
|
||||
@@ -273,6 +271,28 @@ function goMore() {
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.notice-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-1;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.notice-type-tag {
|
||||
font-size: 20rpx;
|
||||
font-weight: $font-weight-medium;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 6rpx;
|
||||
flex-shrink: 0;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.type-important { color: #EF4444; background: rgba(239, 68, 68, 0.08); }
|
||||
&.type-scenic { color: #0052FF; background: rgba(0, 82, 255, 0.08); }
|
||||
&.type-promo { color: #F59E0B; background: rgba(245, 158, 11, 0.08); }
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
font-size: $font-size-sm;
|
||||
color: $color-muted-foreground;
|
||||
@@ -281,6 +301,20 @@ function goMore() {
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.notice-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-1;
|
||||
flex-shrink: 0;
|
||||
margin-left: $spacing-2;
|
||||
}
|
||||
|
||||
.notice-more-text {
|
||||
font-size: $font-size-xs;
|
||||
color: $color-muted-foreground;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
|
||||
Reference in New Issue
Block a user