qs_xinchun2026_h5/components/ChongwenScene.vue

332 lines
7.1 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.

<script setup>
import { ref, onMounted, computed } from 'vue'
import VideoPlayButton from './VideoPlayButton.vue'
import VideoPlayerModal from './VideoPlayerModal.vue'
import { recordInteraction } from '../api/api.js'
// 组件属性
const props = defineProps({
// 是否为活动状态
active: {
type: Boolean,
default: false
},
// 滚动位置,用于实现视差效果
scrollPosition: {
type: Number,
default: 0
},
// 视频地址
videoUrl: {
type: String,
default: ''
},
// 全局BGM播放状态
isMusicPlaying: {
type: Boolean,
default: false
},
// 页面访问UUID
pageVisitUuid: {
type: String,
default: ''
}
})
// 组件事件
const emit = defineEmits(['collect-seal', 'video-open', 'video-close', 'pause-bgm', 'resume-bgm', 'webview-open', 'webview-close'])
// 是否收集福印
const sealCollected = ref(false)
// 福字点击区域状态
const sq2ImageVisible = ref(false)
// 视频播放状态
const showVideoPlayer = ref(false)
// 视频播放完成状态
const hasVideoPlayed = ref(false)
// 互动点击完成状态
const hasInteractiveClicked = ref(false)
// 计算视差效果的偏移量
const parallaxOffset = computed(() => {
// 滚动位置的1/10作为视差偏移
return props.scrollPosition * 0.1
})
// 保存BGM状态
const wasBgPlayingBeforeWebview = ref(false)
// 打开webview页面
const openWebview = () => {
// 标记互动点击已完成
hasInteractiveClicked.value = true
// 记录点击交互
if (props.pageVisitUuid) {
recordInteraction({
page_visit_uuid: props.pageVisitUuid,
scene_id: 'chongwenmen',
interaction_type: 'click'
}).catch(err => {
console.log('记录点击交互失败:', err)
})
}
// 检查是否满足收集福印的条件
checkSealCollection()
// 保存BGM状态
wasBgPlayingBeforeWebview.value = props.isMusicPlaying
// 通知父组件webview即将打开
emit('webview-open')
// 暂停全局BGM播放
if (props.isMusicPlaying) {
emit('pause-bgm', 'webview')
}
// 标记即将打开webview
uni.setStorageSync('isOpeningWebview', true)
uni.setStorageSync('wasMusicPlayingBeforeWebview', props.isMusicPlaying)
uni.navigateTo({
url: '/pages/webview/webview',
success: () => {
console.log('Webview opened successfully')
},
fail: (err) => {
console.error('Failed to open webview:', err)
uni.showToast({
title: '页面打开失败',
icon: 'none',
duration: 1500
})
// 如果打开失败恢复BGM状态
if (wasBgPlayingBeforeWebview.value) {
emit('resume-bgm')
}
// 通知父组件webview打开失败
emit('webview-close')
}
})
}
// 检查是否满足收集福印的条件
const checkSealCollection = () => {
if (!sealCollected.value && hasVideoPlayed.value && hasInteractiveClicked.value) {
sealCollected.value = true
sq2ImageVisible.value = true
emit('collect-seal')
}
}
// 打开视频播放器
const openVideoPlayer = () => {
showVideoPlayer.value = true
emit('video-open')
}
// 关闭视频播放器
const closeVideoPlayer = () => {
showVideoPlayer.value = false
emit('video-close')
}
// 处理视频播放事件
const handleVideoPlayed = () => {
hasVideoPlayed.value = true
// 记录视频播放交互
if (props.pageVisitUuid) {
recordInteraction({
page_visit_uuid: props.pageVisitUuid,
scene_id: 'chongwenmen',
interaction_type: 'video_play'
}).catch(err => {
console.log('记录视频播放交互失败:', err)
})
}
// 检查是否满足收集福印的条件
checkSealCollection()
}
// 页面挂载时的初始化
onMounted(() => {
// 添加动画类,触发入场动画
const container = document.querySelector('.chongwen-scene-container')
if (container) {
container.classList.add('animate-in')
}
})
</script>
<template>
<section class="chongwen-scene-container" :class="{ 'active': active }">
<!-- 背景图片层 -->
<div class="background-layer" :style="{ transform: `translateY(${parallaxOffset}px)` }">
<!-- 使用崇文门商圈背景图片 -->
<img src="/static/bg/bg2.jpg" alt="崇文门商圈" class="background-image" />
</div>
<!-- sq2图片 -->
<img
v-if="sq2ImageVisible"
src="/static/images/sq2.png"
alt="新春祝福"
class="sq2-image"
/>
<!-- 查看按钮 -->
<img
src="/static/images/btn_view.png"
alt="查看详情"
class="btn-view"
@click="openWebview"
/>
<!-- 热点点击区域 -->
<div class="hotspot-area">
<div class="pulse-indicator">
<div class="pulse-circle"></div>
</div>
</div>
<!-- 视频播放按钮 -->
<VideoPlayButton @play="openVideoPlayer" />
<!-- 视频播放器弹窗 -->
<VideoPlayerModal
:video-url="props.videoUrl"
:visible="showVideoPlayer"
@close="closeVideoPlayer"
@video-played="handleVideoPlayed"
/>
</section>
</template>
<style scoped>
.chongwen-scene-container {
position: relative;
width: 100%;
height: auto; /* 高度由内容决定 */
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
background-color: #ff6b35;
}
/* 背景图片层 */
.background-layer {
position: relative;
width: 100%;
transition: transform 0.1s ease;
/* 背景图片决定容器高度 */
height: auto;
}
.background-image {
width: 100%;
height: auto;
display: block;
/* 确保图片完整显示,决定容器高度 */
object-fit: contain;
}
/* 入场动画 */
.chongwen-scene-container.animate-in {
animation: sceneFadeIn 1s ease-out;
}
@keyframes sceneFadeIn {
from { opacity: 0; transform: translateY(50px); }
to { opacity: 1; transform: translateY(0); }
}
/* sq2图片 */
.sq2-image {
position: absolute;
top: 200rpx;
right: -6rpx;
width: auto;
height: auto;
max-width: 300rpx;
z-index: 20;
animation: fadeIn 0.5s ease;
}
/* 查看按钮 */
.btn-view {
position: absolute;
left: 156rpx;
top: 597rpx;
width: 479rpx;
height: 84rpx;
cursor: pointer;
z-index: 26;
transition: all 0.3s ease;
}
.btn-view:active {
transform: scale(0.95);
}
/* 动画效果 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 热点点击区域 */
.hotspot-area {
position: absolute;
left: 321rpx;
top: 570rpx;
width: 150rpx;
height: 150rpx;
cursor: pointer;
z-index: 25;
display: flex;
align-items: center;
justify-content: center;
}
/* 脉冲动效 */
.pulse-indicator {
position: relative;
width: 100rpx;
height: 100rpx;
}
.pulse-circle {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
border-radius: 50%;
background-color: rgba(255, 215, 0, 0.4);
border: 3rpx solid rgba(255, 215, 0, 0.8);
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% {
transform: translate(-50%, -50%) scale(0.8);
opacity: 0.8;
}
100% {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
</style>