feat: 公告弹窗组件 + 公告列表页 + 旅游卡功能区调整
- 新增 AnnouncementModal 公告弹窗组件(v-model 控制,居中白色面板+圆形关闭按钮+动画) - 新增通知公告列表页(pages/notice-list),微信原生导航,卡片式布局 - 首页公告栏去掉类型标签(重要/景区/福利),公告条目可点击打开弹窗 - 首页'更多'按钮跳转公告列表页 - 旅游卡页面'我要入园'改为'我要绑定',icon 与首页绑卡一致 - 公告列表页极简风格:标题+摘要+日期+右箭头,无图标无分割线 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,185 @@
|
|||||||
|
<template>
|
||||||
|
<view
|
||||||
|
v-if="modelValue"
|
||||||
|
class="modal-overlay"
|
||||||
|
:class="{ visible: show }"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<view class="modal-panel" @click.stop>
|
||||||
|
<!-- 标题 -->
|
||||||
|
<text class="modal-title">{{ title }}</text>
|
||||||
|
|
||||||
|
<!-- 分隔线 -->
|
||||||
|
<view class="modal-divider" />
|
||||||
|
|
||||||
|
<!-- 正文(可滚动) -->
|
||||||
|
<scroll-view scroll-y class="modal-scroll">
|
||||||
|
<text class="modal-body">{{ body }}</text>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 关闭按钮 -->
|
||||||
|
<view class="modal-close" @click.stop="close">
|
||||||
|
<view class="close-x">
|
||||||
|
<view class="close-line line-a" />
|
||||||
|
<view class="close-line line-b" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch, nextTick } from 'vue'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
modelValue: boolean
|
||||||
|
title?: string
|
||||||
|
body?: string
|
||||||
|
}>(), {
|
||||||
|
title: '公告',
|
||||||
|
body: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: boolean]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const show = ref(false)
|
||||||
|
|
||||||
|
watch(() => props.modelValue, (val) => {
|
||||||
|
if (val) {
|
||||||
|
nextTick(() => { show.value = true })
|
||||||
|
} else {
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
show.value = false
|
||||||
|
setTimeout(() => { emit('update:modelValue', false) }, 280)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* ====== 遮罩层 ====== */
|
||||||
|
.modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: $z-modal;
|
||||||
|
background: rgba(0, 0, 0, 0.45);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 280ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
|
||||||
|
&.visible {
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
.modal-panel {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 面板 ====== */
|
||||||
|
.modal-panel {
|
||||||
|
width: calc(100vw - 96rpx);
|
||||||
|
max-height: 65vh;
|
||||||
|
background: $color-card;
|
||||||
|
border-radius: $radius-2xl;
|
||||||
|
padding: $spacing-5 $spacing-4 $spacing-4;
|
||||||
|
box-shadow: $shadow-xl;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transform: scale(0.88);
|
||||||
|
opacity: 0;
|
||||||
|
transition: transform 320ms cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
|
opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 标题 ====== */
|
||||||
|
.modal-title {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: $font-size-xl;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $color-foreground;
|
||||||
|
line-height: $line-height-tight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 分隔线 ====== */
|
||||||
|
.modal-divider {
|
||||||
|
height: $border-width;
|
||||||
|
background: $uv-border-color;
|
||||||
|
opacity: 0.4;
|
||||||
|
margin: $spacing-3 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 正文滚动区 ====== */
|
||||||
|
.modal-scroll {
|
||||||
|
flex: 1;
|
||||||
|
max-height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
font-size: $font-size-base;
|
||||||
|
color: $uv-content-color;
|
||||||
|
line-height: $line-height-relaxed;
|
||||||
|
display: block;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 关闭按钮 ====== */
|
||||||
|
.modal-close {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
border: 2rpx solid rgba(255, 255, 255, 0.35);
|
||||||
|
background: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: $spacing-4;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.8);
|
||||||
|
transition: opacity 320ms cubic-bezier(0.16, 1, 0.3, 1) 120ms,
|
||||||
|
transform 320ms cubic-bezier(0.16, 1, 0.3, 1) 120ms;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-x {
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-line {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 28rpx;
|
||||||
|
height: 2rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
|
||||||
|
&.line-a {
|
||||||
|
transform: translate(-50%, -50%) rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.line-b {
|
||||||
|
transform: translate(-50%, -50%) rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -42,6 +42,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "景区详情"
|
"navigationBarTitleText": "景区详情"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/notice-list/notice-list",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "通知公告"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"subPackages": [
|
"subPackages": [
|
||||||
|
|||||||
+33
-23
@@ -32,8 +32,7 @@
|
|||||||
@touchend="onNoticeTouchEnd"
|
@touchend="onNoticeTouchEnd"
|
||||||
>
|
>
|
||||||
<swiper-item v-for="item in announcements" :key="item.id">
|
<swiper-item v-for="item in announcements" :key="item.id">
|
||||||
<view class="notice-item">
|
<view class="notice-item" @click="openNotice(item)">
|
||||||
<text class="notice-type-tag" :class="`type-${item.type}`">{{ item.typeLabel }}</text>
|
|
||||||
<text class="notice-text">{{ item.content }}</text>
|
<text class="notice-text">{{ item.content }}</text>
|
||||||
</view>
|
</view>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
@@ -130,12 +129,20 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 公告弹窗 -->
|
||||||
|
<AnnouncementModal
|
||||||
|
v-model="showNoticeModal"
|
||||||
|
:title="noticeModalTitle"
|
||||||
|
:body="noticeModalBody"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import type { ScenicSpotItem } from '../../data/scenic-spots'
|
import type { ScenicSpotItem } from '../../data/scenic-spots'
|
||||||
|
import AnnouncementModal from '../../components/AnnouncementModal.vue'
|
||||||
|
|
||||||
/** 金刚区 */
|
/** 金刚区 */
|
||||||
const quickActions = [
|
const quickActions = [
|
||||||
@@ -151,9 +158,9 @@ function onQuickAction(item: { label: string }) {
|
|||||||
|
|
||||||
/** 公告数据(mock,后续接 API) */
|
/** 公告数据(mock,后续接 API) */
|
||||||
const announcements = ref([
|
const announcements = ref([
|
||||||
{ id: 1, type: 'important', typeLabel: '重要', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!' },
|
{ id: 1, type: 'important', typeLabel: '重要', title: '赣湘全域旅游年卡限时优惠', date: '2026-06-20', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!', body: '赣湘全域旅游年卡限时优惠活动现已开启,工会会员凭有效证件可享专享价¥300/套卡(原价¥580)。套卡包含武功山金顶景区、杨岐山孽龙洞景区、仙凤三宝景区等42家合作景区全年免首道门票权益,覆盖萍乡、长沙、株洲、湘潭等地区。活动期间购买还可额外获赠君澜温泉单次体验券一张。活动截止至2026年7月31日,数量有限,售完即止。' },
|
||||||
{ id: 2, type: 'scenic', typeLabel: '景区', content: '武功山金顶景区已开放,持卡可免费入园1次。' },
|
{ 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: '福利', content: '超级玩家卡全新上线,40家景区免门票,仅¥198!' },
|
{ 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 onNoticeChange(e: any) { currentNoticeIndex.value = e.detail.current }
|
||||||
function onNoticeTouchStart() { swiperAutoplay.value = false }
|
function onNoticeTouchStart() { swiperAutoplay.value = false }
|
||||||
function onNoticeTouchEnd() { swiperAutoplay.value = true }
|
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 = [
|
const hotSpots = [
|
||||||
@@ -297,25 +318,9 @@ function goMore() {
|
|||||||
.notice-item {
|
.notice-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: $spacing-1;
|
|
||||||
height: 40rpx;
|
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 {
|
.notice-text {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-muted-foreground;
|
color: $color-muted-foreground;
|
||||||
@@ -673,14 +678,19 @@ function goMore() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.spot-benefit {
|
.spot-benefit {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
background: $uv-primary;
|
background: $uv-primary;
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
padding: 4rpx $spacing-1;
|
padding: 8rpx 12rpx;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
text {
|
text {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<view class="list-container">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in notices"
|
||||||
|
:key="item.id"
|
||||||
|
class="notice-card fade-in"
|
||||||
|
:style="{ animationDelay: index * 60 + 'ms' }"
|
||||||
|
@click="openDetail(item)"
|
||||||
|
>
|
||||||
|
<!-- 第一行:标题 + 日期 + 箭头 -->
|
||||||
|
<view class="card-header">
|
||||||
|
<view class="header-text">
|
||||||
|
<text class="card-title">{{ item.title }}</text>
|
||||||
|
<text class="card-summary">{{ item.content }}</text>
|
||||||
|
</view>
|
||||||
|
<text class="card-date">{{ item.date }}</text>
|
||||||
|
<view class="card-arrow" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 公告详情弹窗 -->
|
||||||
|
<AnnouncementModal
|
||||||
|
v-model="showModal"
|
||||||
|
:title="modalTitle"
|
||||||
|
:body="modalBody"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 底部安全区 -->
|
||||||
|
<view class="safe-bottom" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import AnnouncementModal from '../../components/AnnouncementModal.vue'
|
||||||
|
|
||||||
|
interface NoticeItem {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
date: string
|
||||||
|
content: string
|
||||||
|
body: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const notices = ref<NoticeItem[]>([
|
||||||
|
{ id: 1, title: '赣湘全域旅游年卡限时优惠', date: '2026-06-20', content: '赣湘全域旅游年卡限时优惠,工会会员专享¥300/套卡!', body: '赣湘全域旅游年卡限时优惠活动现已开启,工会会员凭有效证件可享专享价¥300/套卡(原价¥580)。套卡包含武功山金顶景区、杨岐山孽龙洞景区、仙凤三宝景区等42家合作景区全年免首道门票权益,覆盖萍乡、长沙、株洲、湘潭等地区。活动期间购买还可额外获赠君澜温泉单次体验券一张。活动截止至2026年7月31日,数量有限,售完即止。' },
|
||||||
|
{ id: 2, title: '武功山金顶景区开放通知', date: '2026-06-18', content: '武功山金顶景区已开放,持卡可免费入园1次。', body: '武功山金顶景区即日起正常开放,营业时间08:00-18:00。赣湘全域旅游年卡持卡用户可免费入园1次(含首道门票,价值¥70)。温馨提示:山顶温差较大,建议携带防风保暖衣物;雷雨天气请勿登顶;需提前1天通过小程序预约,每日限流5000人。' },
|
||||||
|
{ id: 3, title: '超级玩家卡全新上线', date: '2026-06-15', content: '超级玩家卡全新上线,40家景区免门票,仅¥198!', body: '超级玩家卡全新上线!仅需¥198即可享受40家合作景区免首道门票权益,单次最高可省¥228。覆盖景区包括武功山金顶(¥70)、君澜温泉(¥228)、杨岐山孽龙洞(¥68)、仙凤三宝(¥50)等热门景区。卡片有效期为购买之日起一年,法定节假日通用,不限购买次数。适合经常出游的家庭和户外爱好者。' },
|
||||||
|
{ id: 4, title: '端午节假期景区预约提醒', date: '2026-06-10', content: '端午假期热门景区需提前预约,请合理安排出行。', body: '端午节假期(6月14日至16日)期间,武功山金顶景区、君澜温泉等热门景区将实行限流措施,每日限流5000人。请持卡用户提前通过小程序预约,未预约将无法入园。建议错峰出行,关注景区实时客流信息。' },
|
||||||
|
{ id: 5, title: '新增合作景区:莲花荷博园', date: '2026-06-05', content: '莲花荷博园正式加入合作景区,持卡免门票6次。', body: '莲花荷博园于2026年6月起正式加入赣湘全域旅游年卡合作景区。持卡用户全年可免首道门票入园6次(门票原价¥35)。莲花荷博园位于萍乡市莲花县,夏季荷花盛开时景色最佳,是休闲观光的好去处。' },
|
||||||
|
])
|
||||||
|
|
||||||
|
/** 弹窗状态 */
|
||||||
|
const showModal = ref(false)
|
||||||
|
const modalTitle = ref('公告')
|
||||||
|
const modalBody = ref('')
|
||||||
|
|
||||||
|
function openDetail(item: NoticeItem) {
|
||||||
|
modalTitle.value = item.title
|
||||||
|
modalBody.value = item.body
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* ================================================================
|
||||||
|
通知公告列表页 — Premium Utilitarian Minimalism
|
||||||
|
|
||||||
|
Typography:
|
||||||
|
Body/UI: PingFang SC (system)
|
||||||
|
Title: 28rpx / 600 weight / #1A1A1A / tracking -0.3rpx
|
||||||
|
Summary: 26rpx / 400 weight / #888888 / line-height 1.6
|
||||||
|
Date: 22rpx / 400 weight / #BBBBBB
|
||||||
|
Action: 26rpx / 500 weight / #3C9CFF
|
||||||
|
|
||||||
|
Color palette:
|
||||||
|
Canvas: #F7F8FA
|
||||||
|
Surface: #FFFFFF
|
||||||
|
Title: #1A1A1A (off-black, never pure #000)
|
||||||
|
Body: #888888
|
||||||
|
Muted: #BBBBBB
|
||||||
|
Primary: #3C9CFF
|
||||||
|
Icon bg: #ECF5FF ($uv-primary-light)
|
||||||
|
|
||||||
|
Spacing (rpx):
|
||||||
|
Card radius: 16
|
||||||
|
Card gap: 24
|
||||||
|
Side margin: 30
|
||||||
|
Card padding: 32 / 28
|
||||||
|
Icon: 56 × 56, radius 14
|
||||||
|
Icon→title: 16
|
||||||
|
Title→summary: 16
|
||||||
|
Summary→action: 24
|
||||||
|
================================================================ */
|
||||||
|
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #F7F8FA;
|
||||||
|
font-family: $font-family-body;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-container {
|
||||||
|
padding: 24rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 入场动画 ====== */
|
||||||
|
@keyframes cardFadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(16rpx);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
animation: cardFadeIn 500ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 卡片 ====== */
|
||||||
|
.notice-card {
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 32rpx 28rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
border: 1rpx solid rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.88;
|
||||||
|
transition: opacity 100ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 卡片内容行 ====== */
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 左侧文字区(标题 + 摘要) */
|
||||||
|
.header-text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标题 */
|
||||||
|
.card-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: #1A1A1A;
|
||||||
|
line-height: 1.3;
|
||||||
|
letter-spacing: -0.3rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 摘要 */
|
||||||
|
.card-summary {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
color: #888888;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 日期 */
|
||||||
|
.card-date {
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
|
color: #BBBBBB;
|
||||||
|
flex-shrink: 0;
|
||||||
|
letter-spacing: 0.5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 右箭头 */
|
||||||
|
.card-arrow {
|
||||||
|
width: 14rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
border-right: 3rpx solid #CCCCCC;
|
||||||
|
border-bottom: 3rpx solid #CCCCCC;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== 底部安全区 ====== */
|
||||||
|
.safe-bottom {
|
||||||
|
height: calc(40rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -215,7 +215,7 @@ function goBindCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const featureActions = [
|
const featureActions = [
|
||||||
{ label: '我要入园', icon: '/static/icon/check.png' },
|
{ label: '我要绑定', icon: '/static/icon/card.png' },
|
||||||
{ label: '我要预约', icon: '/static/icon/reserve.png' },
|
{ label: '我要预约', icon: '/static/icon/reserve.png' },
|
||||||
{ label: '使用记录', icon: '/static/icon/record.png' },
|
{ label: '使用记录', icon: '/static/icon/record.png' },
|
||||||
{ label: '景区权益', icon: '/static/icon/scenic.png' },
|
{ label: '景区权益', icon: '/static/icon/scenic.png' },
|
||||||
|
|||||||
Reference in New Issue
Block a user