feat: 年卡相关页面(列表/详情/购买/激活/入园码/绑定)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2293e67f8c
commit
b4981587a2
@@ -1,3 +1,89 @@
|
||||
<template>
|
||||
<view><text>页面占位 - 后续任务实现</text></view>
|
||||
<view class="page">
|
||||
<!-- 年卡信息头部 -->
|
||||
<view class="card-top">
|
||||
<text class="card-label">{{ qrInfo?.cardName || '年卡' }}</text>
|
||||
<text class="user-name">{{ qrInfo?.userName || '---' }}</text>
|
||||
<text class="expire-date">有效期至 {{ qrInfo?.expireDate || '---' }}</text>
|
||||
</view>
|
||||
<!-- 二维码区域 -->
|
||||
<view class="qr-card">
|
||||
<view class="qr-area">
|
||||
<image v-if="qrInfo?.qrCode" class="qr-image" :src="qrInfo.qrCode" mode="aspectFit" />
|
||||
<view v-else class="qr-placeholder"><text>加载中...</text></view>
|
||||
</view>
|
||||
<text class="qr-tip">扫码入园 · 每60秒自动刷新</text>
|
||||
</view>
|
||||
<!-- 操作按钮 -->
|
||||
<view class="actions">
|
||||
<button class="btn-secondary" @click="showComingSoon">预约景区</button>
|
||||
<button class="btn-primary" @click="refreshQrCode">刷新二维码</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUnmount } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useCardStore } from '../../../../store/card'
|
||||
import { showToast } from '../../../../utils'
|
||||
import type { QrCodeInfo } from '../../../../api/types'
|
||||
|
||||
const cardStore = useCardStore()
|
||||
const cardId = ref('')
|
||||
const qrInfo = ref<QrCodeInfo | null>(null)
|
||||
let refreshTimer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
/** 页面加载时获取入园码并启动定时刷新 */
|
||||
onLoad((options) => {
|
||||
cardId.value = options?.cardId || ''
|
||||
if (cardId.value) {
|
||||
loadQrCode()
|
||||
// 每60秒自动刷新二维码
|
||||
refreshTimer = setInterval(() => {
|
||||
loadQrCode()
|
||||
}, 60000)
|
||||
}
|
||||
})
|
||||
|
||||
/** 页面销毁时清除定时器 */
|
||||
onBeforeUnmount(() => {
|
||||
if (refreshTimer) clearInterval(refreshTimer)
|
||||
})
|
||||
|
||||
/** 加载入园码 */
|
||||
async function loadQrCode() {
|
||||
try {
|
||||
qrInfo.value = await cardStore.getEntryQrCode(cardId.value)
|
||||
} catch (err: any) {
|
||||
showToast(err.message || '获取入园码失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 手动刷新二维码 */
|
||||
function refreshQrCode() {
|
||||
loadQrCode()
|
||||
showToast('已刷新', 'success')
|
||||
}
|
||||
|
||||
/** 预约景区(暂未开放) */
|
||||
function showComingSoon() {
|
||||
showToast('即将上线,敬请期待')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page { min-height: 100vh; background: #f5f5f5; padding: 20rpx; box-sizing: border-box; }
|
||||
.card-top { background: linear-gradient(135deg, #4A90D9, #357ABD); border-radius: 20rpx; padding: 30rpx; color: #fff; margin-bottom: -20rpx; }
|
||||
.card-label { font-size: 24rpx; opacity: 0.8; display: block; }
|
||||
.user-name { font-size: 36rpx; font-weight: bold; display: block; margin: 12rpx 0 8rpx; }
|
||||
.expire-date { font-size: 22rpx; opacity: 0.7; display: block; }
|
||||
.qr-card { background: #fff; border-radius: 16rpx; padding: 30rpx; margin-top: 30rpx; box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08); text-align: center; }
|
||||
.qr-area { width: 360rpx; height: 360rpx; margin: 20rpx auto; display: flex; align-items: center; justify-content: center; background: #f8f8f8; border-radius: 12rpx; }
|
||||
.qr-image { width: 320rpx; height: 320rpx; }
|
||||
.qr-placeholder { color: #999; font-size: 28rpx; }
|
||||
.qr-tip { font-size: 24rpx; color: #999; display: block; margin-top: 16rpx; }
|
||||
.actions { display: flex; gap: 20rpx; padding: 40rpx 20rpx; }
|
||||
.btn-secondary { flex: 1; height: 88rpx; line-height: 88rpx; background: #fff; color: #4A90D9; border: 2rpx solid #4A90D9; border-radius: 44rpx; font-size: 28rpx; }
|
||||
.btn-primary { flex: 1; height: 88rpx; line-height: 88rpx; background: #4A90D9; color: #fff; border-radius: 44rpx; font-size: 28rpx; border: none; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user