feat: 旅游卡页面功能入口改为SVG图标 + 图标资源优化
- 旅游卡页面(qrcode/index)功能入口:我要入园/我要预约/使用记录/景区权益 - 卡片详情页(detail)新增4宫格功能入口 - SVG图标(4.3MB)转为PNG(99KB)解决主包4MB限制 - tabBar图标从1024x1024缩至81x81修复模拟器启动失败 - 统一各页面区域间距为24rpx Co-Authored-By: Claude <noreply@anthropic.com>
@@ -11,6 +11,18 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="card-desc">{{ card.description }}</text>
|
<text class="card-desc">{{ card.description }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 功能入口 -->
|
||||||
|
<view class="quick-grid">
|
||||||
|
<view
|
||||||
|
v-for="item in quickActions"
|
||||||
|
:key="item.label"
|
||||||
|
class="quick-item"
|
||||||
|
@click="onQuickAction(item)"
|
||||||
|
>
|
||||||
|
<image class="quick-icon-img" :src="item.icon" mode="aspectFit" />
|
||||||
|
<text class="quick-label">{{ item.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<!-- 权益说明 -->
|
<!-- 权益说明 -->
|
||||||
<view class="section" v-if="card.benefits?.length">
|
<view class="section" v-if="card.benefits?.length">
|
||||||
<text class="section-title">权益说明</text>
|
<text class="section-title">权益说明</text>
|
||||||
@@ -59,6 +71,17 @@ import type { CardDetail } from '../../../../api/types'
|
|||||||
|
|
||||||
const card = ref<CardDetail | null>(null)
|
const card = ref<CardDetail | null>(null)
|
||||||
|
|
||||||
|
const quickActions = [
|
||||||
|
{ label: '我要入园', icon: '/static/icon/check.png' },
|
||||||
|
{ label: '我要预约', icon: '/static/icon/reserve.png' },
|
||||||
|
{ label: '使用记录', icon: '/static/icon/record.png' },
|
||||||
|
{ label: '景区权益', icon: '/static/icon/scenic.png' },
|
||||||
|
]
|
||||||
|
|
||||||
|
function onQuickAction(item: { label: string }) {
|
||||||
|
uni.showToast({ title: `${item.label}功能开发中`, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
/** 页面加载时获取年卡详情 */
|
/** 页面加载时获取年卡详情 */
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
if (options?.id) {
|
if (options?.id) {
|
||||||
@@ -84,8 +107,8 @@ function handleBuy() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.page { min-height: 100vh; background: #f5f5f5; padding-bottom: 120rpx; }
|
.page { min-height: 100vh; background: $uv-bg-color; padding-bottom: 120rpx; }
|
||||||
.cover { width: 100%; height: 400rpx; background: #ddd; }
|
.cover { width: 100%; height: 400rpx; background: #ddd; }
|
||||||
.info-card { background: #fff; padding: 24rpx 30rpx; margin-bottom: 16rpx; }
|
.info-card { background: #fff; padding: 24rpx 30rpx; margin-bottom: 16rpx; }
|
||||||
.card-name { font-size: 36rpx; font-weight: bold; color: #333; display: block; }
|
.card-name { font-size: 36rpx; font-weight: bold; color: #333; display: block; }
|
||||||
@@ -110,4 +133,34 @@ function handleBuy() {
|
|||||||
.bottom-price .value { font-size: 36rpx; color: #E74C3C; font-weight: bold; }
|
.bottom-price .value { font-size: 36rpx; color: #E74C3C; font-weight: bold; }
|
||||||
.btn-buy { background: #E74C3C; color: #fff; font-size: 30rpx; padding: 20rpx 60rpx; border-radius: 44rpx; border: none; }
|
.btn-buy { background: #E74C3C; color: #fff; font-size: 30rpx; padding: 20rpx 60rpx; border-radius: 44rpx; border: none; }
|
||||||
.loading-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; color: #999; }
|
.loading-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; color: #999; }
|
||||||
|
|
||||||
|
/* Quick actions — 功能入口 */
|
||||||
|
.quick-grid {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
padding: $spacing-3 0;
|
||||||
|
background: $color-card;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
box-shadow: $shadow-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
transition: transform $transition-fast;
|
||||||
|
|
||||||
|
&:active { transform: scale(0.92); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-icon-img { width: 88rpx; height: 88rpx; }
|
||||||
|
|
||||||
|
.quick-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: $uv-main-color;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -140,10 +140,10 @@ import type { ScenicSpotItem } from '../../data/scenic-spots'
|
|||||||
|
|
||||||
/** 金刚区 */
|
/** 金刚区 */
|
||||||
const quickActions = [
|
const quickActions = [
|
||||||
{ label: '我要绑卡', icon: '/static/icon/card.svg' },
|
{ label: '我要绑卡', icon: '/static/icon/card.png' },
|
||||||
{ label: '我要预约', icon: '/static/icon/reserve.svg' },
|
{ label: '我要预约', icon: '/static/icon/reserve.png' },
|
||||||
{ label: '我要入园', icon: '/static/icon/check.svg' },
|
{ label: '我要入园', icon: '/static/icon/check.png' },
|
||||||
{ label: '常见问题', icon: '/static/icon/faq.svg' },
|
{ label: '常见问题', icon: '/static/icon/faq.png' },
|
||||||
]
|
]
|
||||||
|
|
||||||
function onQuickAction(item: { label: string }) {
|
function onQuickAction(item: { label: string }) {
|
||||||
|
|||||||
@@ -51,29 +51,9 @@
|
|||||||
<!-- 功能入口 -->
|
<!-- 功能入口 -->
|
||||||
<view class="feature-panel">
|
<view class="feature-panel">
|
||||||
<view class="feature-grid">
|
<view class="feature-grid">
|
||||||
<view class="feature-item" @click="goBindCard">
|
<view class="feature-item" v-for="item in featureActions" :key="item.label" @click="onFeatureClick(item)">
|
||||||
<view class="feature-icon-wrap">
|
<image class="feature-icon-img" :src="item.icon" mode="aspectFit" />
|
||||||
<view class="fi-link" />
|
<text class="feature-label">{{ item.label }}</text>
|
||||||
</view>
|
|
||||||
<text class="feature-label">绑定旅游卡</text>
|
|
||||||
</view>
|
|
||||||
<view class="feature-item" @click="onFeature('reserve')">
|
|
||||||
<view class="feature-icon-wrap">
|
|
||||||
<view class="fi-calendar" />
|
|
||||||
</view>
|
|
||||||
<text class="feature-label">景区预约</text>
|
|
||||||
</view>
|
|
||||||
<view class="feature-item" @click="onFeature('history')">
|
|
||||||
<view class="feature-icon-wrap">
|
|
||||||
<view class="fi-list" />
|
|
||||||
</view>
|
|
||||||
<text class="feature-label">使用记录</text>
|
|
||||||
</view>
|
|
||||||
<view class="feature-item" @click="onFeature('spots')">
|
|
||||||
<view class="feature-icon-wrap">
|
|
||||||
<view class="fi-mountain" />
|
|
||||||
</view>
|
|
||||||
<text class="feature-label">权益景区</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -234,8 +214,15 @@ function goBindCard() {
|
|||||||
uni.navigateTo({ url: '/packages/user/pages/card/bind' })
|
uni.navigateTo({ url: '/packages/user/pages/card/bind' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFeature(type: string) {
|
const featureActions = [
|
||||||
uni.showToast({ title: '功能开发中', icon: 'none' })
|
{ label: '我要入园', icon: '/static/icon/check.png' },
|
||||||
|
{ label: '我要预约', icon: '/static/icon/reserve.png' },
|
||||||
|
{ label: '使用记录', icon: '/static/icon/record.png' },
|
||||||
|
{ label: '景区权益', icon: '/static/icon/scenic.png' },
|
||||||
|
]
|
||||||
|
|
||||||
|
function onFeatureClick(item: { label: string }) {
|
||||||
|
uni.showToast({ title: `${item.label}功能开发中`, icon: 'none' })
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => { startTimer() })
|
onMounted(() => { startTimer() })
|
||||||
@@ -388,65 +375,9 @@ onUnmounted(() => { if (timer) clearInterval(timer) })
|
|||||||
min-width: 110rpx; transition: opacity 150ms;
|
min-width: 110rpx; transition: opacity 150ms;
|
||||||
}
|
}
|
||||||
.feature-item:active { opacity: 0.6; }
|
.feature-item:active { opacity: 0.6; }
|
||||||
.feature-icon-wrap {
|
.feature-icon-img {
|
||||||
width: 88rpx; height: 88rpx; border-radius: 20rpx;
|
width: 88rpx; height: 88rpx;
|
||||||
background: #F1F5F9;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
margin-bottom: 10rpx;
|
margin-bottom: 10rpx;
|
||||||
transition: background 150ms;
|
|
||||||
}
|
}
|
||||||
.feature-item:active .feature-icon-wrap { background: #E2E8F0; }
|
|
||||||
.feature-label { font-size: 24rpx; color: #475569; }
|
.feature-label { font-size: 24rpx; color: #475569; }
|
||||||
|
|
||||||
/* CSS 图标 — 统一使用页面主色 #0052FF */
|
|
||||||
.fi-link {
|
|
||||||
width: 24rpx; height: 24rpx;
|
|
||||||
border: 3rpx solid #0052FF; border-radius: 50%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.fi-link::before {
|
|
||||||
content: ''; position: absolute;
|
|
||||||
top: 50%; left: 50%;
|
|
||||||
width: 10rpx; height: 10rpx;
|
|
||||||
background: #0052FF; border-radius: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
.fi-calendar {
|
|
||||||
width: 28rpx; height: 28rpx;
|
|
||||||
border: 3rpx solid #0052FF; border-radius: 4rpx;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.fi-calendar::before {
|
|
||||||
content: ''; position: absolute;
|
|
||||||
top: 10rpx; left: 4rpx; right: 4rpx;
|
|
||||||
height: 3rpx; background: #0052FF;
|
|
||||||
}
|
|
||||||
.fi-calendar::after {
|
|
||||||
content: ''; position: absolute;
|
|
||||||
top: -6rpx; left: 6rpx;
|
|
||||||
width: 3rpx; height: 10rpx; background: #0052FF;
|
|
||||||
border-radius: 1rpx;
|
|
||||||
box-shadow: 10rpx 0 0 #0052FF;
|
|
||||||
}
|
|
||||||
.fi-list { width: 28rpx; display: flex; flex-direction: column; gap: 6rpx; }
|
|
||||||
.fi-list::before, .fi-list::after {
|
|
||||||
content: ''; height: 3rpx; background: #0052FF; border-radius: 1rpx;
|
|
||||||
}
|
|
||||||
.fi-list::before { width: 100%; }
|
|
||||||
.fi-list::after { width: 70%; }
|
|
||||||
.fi-mountain {
|
|
||||||
width: 0; height: 0;
|
|
||||||
border-left: 16rpx solid transparent;
|
|
||||||
border-right: 16rpx solid transparent;
|
|
||||||
border-bottom: 24rpx solid #0052FF;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.fi-mountain::after {
|
|
||||||
content: ''; position: absolute;
|
|
||||||
top: 12rpx; left: -6rpx;
|
|
||||||
width: 0; height: 0;
|
|
||||||
border-left: 10rpx solid transparent;
|
|
||||||
border-right: 10rpx solid transparent;
|
|
||||||
border-bottom: 16rpx solid #4D7CFF;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 658 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 612 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 677 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 814 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 608 KiB |
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 7.4 KiB |