qs_xinchun2026_h5/pages/end/end.vue

490 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="end-page-container">
<!-- 背景图 -->
<div class="background">
<img
v-lazy="backgroundImage"
alt="结束页背景"
@error="handleImageError"
/>
</div>
<!-- 标题 -->
<h1 class="title">🎉 恭喜完成全部场景游览 🎉</h1>
<!-- 福印收集展示 -->
<div class="seal-collection-section">
<h2 class="section-title">福印收集成果</h2>
<!-- 收集进度 -->
<div class="collection-progress">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: `${progressPercentage}%` }"
></div>
</div>
<p class="progress-text">
已收集 {{ collectedSeals.length }} / {{ totalSeals }} 个福印
</p>
</div>
<!-- 福印列表 -->
<div class="seal-grid">
<div
v-for="seal in allSeals"
:key="seal.id"
class="seal-item"
:class="{ 'collected': seal.collected }"
>
<div class="seal-image">
<img
v-lazy="seal.collected ? seal.image : uncollectedImage"
:alt="seal.name"
/>
</div>
<div class="seal-name">{{ seal.name }}</div>
<div class="seal-status" :class="{ 'collected-status': seal.collected }">
{{ seal.collected ? '已收集' : '未收集' }}
</div>
</div>
</div>
<!-- 全部收集奖励 -->
<div class="full-collection-reward" v-if="allCollected">
<div class="reward-content">
<div class="reward-icon">🏆</div>
<h3>恭喜集齐全部福印!</h3>
<p>您已完成所有商圈的探索,获得了完整的福印收集成就!</p>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="action-buttons">
<button @click="restartTour" class="btn restart-btn">
重新游览
</button>
<button @click="generateCouple" class="btn couple-btn">
生成AI春联
</button>
<button @click="participateLottery" class="btn lottery-btn">
参与抽奖
</button>
</div>
<!-- 分享按钮 -->
<div class="share-section">
<button @click="shareResult" class="share-btn">
📤 分享我的成果
</button>
</div>
<!-- 加载动画 -->
<div v-if="loading" class="loading-overlay">
<uni-spinner type="circle" size="48" color="#fff"></uni-spinner>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { useCollectionStore } from '../../src/store/collection';
import { share } from '../utils/share';
const router = useRouter();
const collectionStore = useCollectionStore();
// 响应式数据
const loading = ref(false);
const backgroundImage = ref('/static/bg/bg_finish.jpg');
const uncollectedImage = ref('https://placeholder.pics/svg/100x100/CCCCCC/999999/未收集');
// 计算属性
const allSeals = computed(() => {
return collectionStore.seals;
});
const collectedSeals = computed(() => {
return collectionStore.collectedSeals;
});
const totalSeals = computed(() => {
return allSeals.value.length;
});
const progressPercentage = computed(() => {
return collectionStore.getCollectionProgress;
});
const allCollected = computed(() => {
return collectionStore.isAllCollected;
});
// 组件挂载后初始化
onMounted(() => {
// 如果是全部收集,显示特殊效果
if (allCollected.value) {
uni.showToast({
title: '恭喜集齐全部福印!',
icon: 'success',
duration: 3000
});
}
});
// 重新游览
const restartTour = () => {
// 重置收集状态
collectionStore.resetCollection();
// 跳转到首页
router.push('/');
};
// 生成AI春联
const generateCouple = () => {
router.push('/ai-spring');
};
// 参与抽奖
const participateLottery = () => {
router.push('/');
uni.showToast({
title: '抽奖功能请在首页参与',
icon: 'none',
duration: 2000
});
};
// 分享成果
const shareResult = () => {
const shareText = `
我在2026新春东城商圈H5中完成了全部场景游览
已收集 ${collectedSeals.value.length} / ${totalSeals.value} 个福印
#2026新春东城商圈#
`;
// 调用分享工具函数
share(
'新春商圈游览成果',
shareText,
backgroundImage.value
);
};
// 处理图片加载错误
const handleImageError = (event) => {
event.target.src = 'https://placeholder.pics/svg/640x1136/FDF2E9/F39C12/结束页背景';
};
</script>
<style scoped>
.end-page-container {
position: relative;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
overflow: hidden;
}
.background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
}
.background img {
width: 100%;
height: 100%;
object-fit: cover;
}
.title {
font-size: 28px;
color: #f39c12;
text-align: center;
margin: 40px 0 30px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.seal-collection-section {
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 25px;
width: 100%;
max-width: 600px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
margin-bottom: 30px;
}
.section-title {
font-size: 24px;
color: #e67e22;
text-align: center;
margin-bottom: 20px;
font-weight: bold;
}
.collection-progress {
margin-bottom: 30px;
}
.progress-bar {
width: 100%;
height: 15px;
background: #e0e0e0;
border-radius: 10px;
overflow: hidden;
margin-bottom: 10px;
}
.progress-fill {
height: 100%;
background: linear-gradient(135deg, #f39c12, #e67e22);
border-radius: 10px;
transition: width 0.5s ease;
}
.progress-text {
text-align: center;
font-size: 16px;
color: #666;
margin: 0;
}
.seal-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-bottom: 30px;
}
.seal-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 15px;
background: #f9f9f9;
border-radius: 15px;
transition: all 0.3s ease;
border: 2px solid #ddd;
}
.seal-item.collected {
background: linear-gradient(135deg, #fff9c4, #fff59d);
border-color: #ffd740;
transform: scale(1.05);
}
.seal-image {
width: 80px;
height: 80px;
border-radius: 50%;
overflow: hidden;
margin-bottom: 10px;
background: #fff;
border: 3px solid #e67e22;
display: flex;
justify-content: center;
align-items: center;
}
.seal-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.seal-name {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 5px;
}
.seal-status {
font-size: 14px;
color: #999;
padding: 3px 8px;
border-radius: 10px;
background: #eee;
}
.seal-status.collected-status {
color: #4caf50;
background: #e8f5e9;
}
.full-collection-reward {
background: linear-gradient(135deg, #ffeb3b, #ffc107);
border-radius: 15px;
padding: 20px;
text-align: center;
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.3);
animation: glow 2s infinite;
}
@keyframes glow {
0%, 100% {
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.3);
}
50% {
box-shadow: 0 6px 18px rgba(255, 193, 7, 0.6);
}
}
.reward-content {
display: flex;
flex-direction: column;
align-items: center;
}
.reward-icon {
font-size: 64px;
margin-bottom: 10px;
}
.reward-content h3 {
font-size: 22px;
color: #e65100;
margin-bottom: 10px;
}
.reward-content p {
font-size: 16px;
color: #8d6e63;
margin: 0;
}
.action-buttons {
display: flex;
flex-direction: column;
gap: 15px;
width: 100%;
max-width: 400px;
margin-bottom: 20px;
}
.btn {
padding: 15px 25px;
border: none;
border-radius: 25px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
}
.restart-btn {
background: linear-gradient(135deg, #95a5a6, #7f8c8d);
color: white;
}
.restart-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(149, 165, 166, 0.4);
}
.couple-btn {
background: linear-gradient(135deg, #e67e22, #d35400);
color: white;
}
.couple-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(230, 126, 34, 0.4);
}
.lottery-btn {
background: linear-gradient(135deg, #e74c3c, #c0392b);
color: white;
}
.lottery-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(231, 76, 60, 0.4);
}
.share-section {
margin-bottom: 30px;
}
.share-btn {
padding: 15px 30px;
background: linear-gradient(135deg, #3498db, #2980b9);
color: white;
border: none;
border-radius: 25px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 8px;
}
.share-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4);
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
/* 响应式设计 */
@media (max-width: 480px) {
.title {
font-size: 24px;
}
.seal-collection-section {
padding: 20px;
}
.section-title {
font-size: 20px;
}
.seal-grid {
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.seal-image {
width: 70px;
height: 70px;
}
.seal-name {
font-size: 14px;
}
.btn {
font-size: 16px;
padding: 12px 20px;
}
}
</style>