feat: 公告弹窗组件 + 公告列表页 + 旅游卡功能区调整

- 新增 AnnouncementModal 公告弹窗组件(v-model 控制,居中白色面板+圆形关闭按钮+动画)
- 新增通知公告列表页(pages/notice-list),微信原生导航,卡片式布局
- 首页公告栏去掉类型标签(重要/景区/福利),公告条目可点击打开弹窗
- 首页'更多'按钮跳转公告列表页
- 旅游卡页面'我要入园'改为'我要绑定',icon 与首页绑卡一致
- 公告列表页极简风格:标题+摘要+日期+右箭头,无图标无分割线

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jacobxu666
2026-06-25 19:56:41 +08:00
co-authored by Claude
parent 5524d78229
commit ff524ac973
5 changed files with 426 additions and 24 deletions
+33 -23
View File
@@ -32,8 +32,7 @@
@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>
<view class="notice-item" @click="openNotice(item)">
<text class="notice-text">{{ item.content }}</text>
</view>
</swiper-item>
@@ -130,12 +129,20 @@
</view>
</view>
</scroll-view>
<!-- 公告弹窗 -->
<AnnouncementModal
v-model="showNoticeModal"
:title="noticeModalTitle"
:body="noticeModalBody"
/>
</view>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ScenicSpotItem } from '../../data/scenic-spots'
import AnnouncementModal from '../../components/AnnouncementModal.vue'
/** 金刚区 */
const quickActions = [
@@ -151,9 +158,9 @@ function onQuickAction(item: { label: string }) {
/** 公告数据(mock,后续接 API) */
const announcements = ref([
{ id: 1, type: 'important', typeLabel: '重要', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!' },
{ id: 2, type: 'scenic', typeLabel: '景区', content: '武功山金顶景区已开放,持卡可免费入园1次。' },
{ id: 3, type: 'promo', typeLabel: '福利', content: '超级玩家卡全新上线,40家景区免门票,仅¥198!' },
{ id: 1, type: 'important', typeLabel: '重要', title: '赣湘全域旅游年卡限时优惠', date: '2026-06-20', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!', body: '赣湘全域旅游年卡限时优惠活动现已开启,工会会员凭有效证件可享专享价¥300/套卡(原价¥580)。套卡包含武功山金顶景区、杨岐山孽龙洞景区、仙凤三宝景区等42家合作景区全年免首道门票权益,覆盖萍乡、长沙、株洲、湘潭等地区。活动期间购买还可额外获赠君澜温泉单次体验券一张。活动截止至2026年7月31日,数量有限,售完即止。' },
{ id: 2, type: 'scenic', typeLabel: '景区', title: '武功山金顶景区开放通知', date: '2026-06-18', content: '武功山金顶景区已开放,持卡可免费入园1次。', body: '武功山金顶景区即日起正常开放,营业时间08:00-18:00。赣湘全域旅游年卡持卡用户可免费入园1次(含首道门票,价值¥70)。温馨提示:山顶温差较大,建议携带防风保暖衣物;雷雨天气请勿登顶;需提前1天通过小程序预约,每日限流5000人。' },
{ id: 3, type: 'promo', typeLabel: '福利', title: '超级玩家卡全新上线', date: '2026-06-15', content: '超级玩家卡全新上线,40家景区免门票,仅¥198!', body: '超级玩家卡全新上线!仅需¥198即可享受40家合作景区免首道门票权益,单次最高可省¥228。覆盖景区包括武功山金顶(¥70)、君澜温泉(¥228)、杨岐山孽龙洞(¥68)、仙凤三宝(¥50)等热门景区。卡片有效期为购买之日起一年,法定节假日通用,不限购买次数。适合经常出游的家庭和户外爱好者。' },
])
/** 公告轮播状态 */
@@ -164,7 +171,21 @@ const currentNoticeType = computed(() => announcements.value[currentNoticeIndex.
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 showNoticeModal = ref(false)
const noticeModalTitle = ref('公告')
const noticeModalBody = ref('')
function openNotice(item: { typeLabel: string; content: string; body?: string }) {
noticeModalTitle.value = `${item.typeLabel}公告`
noticeModalBody.value = item.body || item.content
showNoticeModal.value = true
}
function goMoreNotice() {
uni.navigateTo({ url: '/pages/notice-list/notice-list' })
}
/** 热门景点数据 */
const hotSpots = [
@@ -297,25 +318,9 @@ function goMore() {
.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;
@@ -673,14 +678,19 @@ function goMore() {
}
.spot-benefit {
display: flex;
align-items: center;
justify-content: center;
background: $uv-primary;
border-radius: $radius-sm;
padding: 4rpx $spacing-1;
padding: 8rpx 12rpx;
line-height: 1;
text {
font-size: $font-size-xs;
color: #fff;
font-weight: $font-weight-medium;
line-height: 1;
}
}