|
|
<template> <div class="choujiang-main"> <Lottery3D ref="lottery3DRef" /> <PrizePanel :prizes="dataManager.state.basicData.prizes" /> <ControlBar :lottery-state="lotteryState" :is-disabled="isDisabled" @lottery-click="handleLotteryClick" @reset="handleReset" @export="handleExport" /> <!-- <MusicPlayer ref="musicPlayerRef" /> --> <Mascot />
<!-- 透明弹窗 --> <div v-if="showPrizeExhaustedModal" class="prize-exhausted-modal"> <div class="modal-content"> <p class="modal-text">该礼品已抽取完毕,请揭秘下一个礼品</p> </div> </div>
<div v-if="showPrizeExhaustedModal1" class="prize-exhausted-modal"> <div class="modal-content"> <p class="modal-text">请先揭秘一个礼品</p> </div> </div>
<div v-if="showPrizeExhaustedModal2" class="prize-exhausted-modal"> <div class="modal-content"> <p class="modal-text">该礼品已抽取完毕</p> </div> </div>
<!-- <UserList :lucky-users=" dataManager.state.basicData.luckyUsers[ dataManager.state.currentPrize?.type ] || [] " :left-users="dataManager.state.basicData.leftUsers" /> --> <!-- <Qipao :text="qipaoText" :show="showQipao" /> --> </div> <audio ref="audioRef" :src="musicSrc" loop preload="auto"></audio> <audio ref="audioRef1" :src="musicSrc1" preload="auto"></audio> </template>
<script setup> import Lottery3D from "./lottery/Lottery3D.vue"; import PrizePanel from "./lottery/PrizePanel.vue"; import ControlBar from "./lottery/ControlBar.vue"; // import MusicPlayer from "./lottery/MusicPlayer.vue";
import Qipao from "./lottery/Qipao.vue"; import UserList from "./lottery/UserList.vue"; import Mascot from "./lottery/Mascot.vue"; import { ref, onMounted, nextTick, computed, watch } from "vue"; import { useDataManager } from "./lottery/dataManager.js"; import { useLotteryEngine } from "./lottery/lotteryEngine.js";
import { useLotteryStore } from "../../store/lottery"; // 路径根据实际情况调整
import { drawLottery } from "../../api/API";
const qipaoText = ref(""); const showQipao = ref(false); const showPrizeExhaustedModal = ref(false); const showPrizeExhaustedModal1 = ref(false); const showPrizeExhaustedModal2 = ref(false);
// const lotteryState = ref('idle'); // idle, ready, rotating, result
// 新增
const lotteryStore = useLotteryStore(); const lotteryState = computed({ get: () => lotteryStore.lotteryState, set: (val) => lotteryStore.setLotteryState(val), });
const lastRevealed = computed({ get: () => lotteryStore.lastRevealedIdx, set: (val) => lotteryStore.setLastRevealedIdx(val), });
const waitingForNextReveal = computed({ get: () => lotteryStore.waitingForNextReveal, set: (val) => lotteryStore.setWaitingForNextReveal(val), });
const winnerList = computed({ get: () => lotteryStore.winnerList, set: (val) => lotteryStore.setWinnerList(val), });
const isDisabled = ref(false);
watch(isDisabled, (newVal, oldVal) => { console.log("isDisabled 变化:", oldVal, "->", newVal); });
// 数据与抽奖主流程
const dataManager = useDataManager(); let lottery3DRef = ref(null); let musicPlayerRef = ref(null); const lotteryEngine = useLotteryEngine(dataManager, { resetCard: (...args) => lottery3DRef.value?.resetCard?.(...args), addHighlight: (...args) => lottery3DRef.value?.addHighlight?.(...args), switchScreen: (...args) => lottery3DRef.value?.switchScreen?.(...args), rotateBallStart: (...args) => lottery3DRef.value?.rotateBallStart?.(...args), rotateBallStop: (...args) => lottery3DRef.value?.rotateBallStop?.(...args), selectCard: (...args) => lottery3DRef.value?.selectCard?.(...args), });
onMounted(async () => { isDisabled.value = true;
await dataManager.getBasicData();
await dataManager.getUsers(); setTimeout(() => { isDisabled.value = false; }, 3800);
// 将 dataManager 挂载到 window 对象,供子组件使用
window.dataManager = dataManager;
// 预加载音频文件以减少播放延迟
preloadAudio(); });
// 预加载音频文件
function preloadAudio() { if (audioRef.value) { audioRef.value.load(); // 设置音频缓冲
audioRef.value.addEventListener('canplaythrough', () => { console.log('背景音乐预加载完成'); }); } if (audioRef1.value) { audioRef1.value.load(); audioRef1.value.addEventListener('canplaythrough', () => { console.log('音效预加载完成'); }); } }
function showLotteryQipao() { const luckys = dataManager.state.currentLuckys; const prize = dataManager.state.currentPrize; if (!luckys || luckys.length === 0) return; // 适配新的数据格式,支持 jwcode 和 username
const names = luckys .map((item) => item.username || item[1] || item.jwcode || "") .join("、"); qipaoText.value = `恭喜${names}获得${prize?.title || ""}!`; showQipao.value = true; setTimeout(() => { showQipao.value = false; }, 3000); }
import musicFile from "/src/assets/worldcup.mp3"; import musicFile1 from "/src/assets/dong.mp3"; const musicSrc = musicFile; const audioRef = ref(null); const playing = ref(false); const musicSrc1 = musicFile1; const audioRef1 = ref(null); const playing1 = ref(false);
async function toggleMusic() { if (!audioRef.value) return; try { if (audioRef.value.paused) { // 确保音频已经准备好播放
if (audioRef.value.readyState < 2) { await new Promise((resolve) => { audioRef.value.addEventListener('canplay', resolve, { once: true }); audioRef.value.load(); }); } await audioRef.value.play(); playing.value = true; } else { audioRef.value.pause(); playing.value = false; } } catch (error) { console.error('播放音乐失败:', error); } }
async function playMusic1() { if (!audioRef1.value) return; try { // 重置音频到开始位置
audioRef1.value.currentTime = 0; // 确保音频已经准备好播放
if (audioRef1.value.readyState < 2) { await new Promise((resolve) => { audioRef1.value.addEventListener('canplay', resolve, { once: true }); audioRef1.value.load(); }); } await audioRef1.value.play(); playing1.value = true; // 监听音频播放结束事件
audioRef1.value.addEventListener('ended', () => { playing1.value = false; }, { once: true }); } catch (error) { console.error('播放音效失败:', error); } }
function isPlaying1() { return playing1.value; } // 检查是否正在播放
function isPlaying() { return playing.value; }
async function handleLotteryClick() { if (isDisabled.value) return; // 2秒内不能重复点击
isDisabled.value = true; // setTimeout(() => {
// isDisabled.value = false;
// }, 2000);
switch (lotteryState.value) { case "idle": setTimeout(() => { isDisabled.value = false; }, 2000); // 先切换到球体布局
await lottery3DRef.value?.switchScreen?.("lottery");
console.log("lotteryState 变更前:", lotteryState.value, "-> ready"); // await new Promise((resolve) => setTimeout(resolve, 2000));
lotteryState.value = "ready"; console.log("lotteryState 变更后:", lotteryState.value);
break; case "ready": if (waitingForNextReveal.value) { console.log("waitingForNextReveal.value", waitingForNextReveal.value); // 显示弹窗提示
showPrizeExhaustedModal.value = true; setTimeout(() => { showPrizeExhaustedModal.value = false; }, 1000); isDisabled.value = false;
break; }
if (lastRevealed.value === -1) { console.log("lastRevealed.value", lastRevealed.value); showPrizeExhaustedModal1.value = true; setTimeout(() => { showPrizeExhaustedModal1.value = false; }, 1000); isDisabled.value = false;
break; }
if ( lastRevealed.value === 0 && dataManager.state.basicData.prizes[lastRevealed.value].remainNum === 0 ) { // 如果是最后一个奖品且剩余数量为0,则跳出
// const currentPrize = dataManager.state.basicData.prizes[lastRevealed.value];
// if (currentPrize && currentPrize.remainNum === 0) {
showPrizeExhaustedModal2.value = true; setTimeout(() => { showPrizeExhaustedModal2.value = false; }, 1000); isDisabled.value = false; break;
// }
}
toggleMusic();
console.log("lotteryState 变更前:", lotteryState.value, "-> rotating"); lotteryState.value = "rotating"; console.log("lotteryState 变更后:", lotteryState.value);
const prize = dataManager.state.basicData.prizes[lastRevealed.value]; console.log("准备调用 drawLottery,prize:", prize); console.log("lastRevealed.value:", lastRevealed.value); // 先让球转起来,不等它结束
const rotatePromise = lottery3DRef.value?.rotateBallStart?.();
// 同时请求接口
try { winnerList.value = await drawLottery({ perWin: prize.perWin, remainNum: prize.remainNum, gradeId: prize.gradeId, prizeId: prize.prizeId, }); setTimeout(() => { isDisabled.value = false; }, 2000);
console.log("drawLottery 调用成功,结果:", winnerList.value);
// 开奖成功后更新获奖名单数据
// if (window.dataManager && window.dataManager.updatePrizeList) {
// try {
// await window.dataManager.updatePrizeList();
// console.log("开奖后获奖名单数据已更新");
// } catch (error) {
// console.error("更新获奖名单数据失败:", error);
// }
// }
} catch (error) { console.error("drawLottery 调用失败:", error); }
// 如果你还需要等球转完再做别的,可以 await rotatePromise
break; case "rotating": setTimeout(() => { isDisabled.value = false; }, 2000);
// toggleMusic();
// toggleMusic();
await lottery3DRef.value?.rotateBallStop?.(); toggleMusic(); playMusic1();
await lotteryEngine.executeLottery();
await nextTick(); showLotteryQipao(); console.log("lotteryState 变更前:", lotteryState.value, "-> idle"); lotteryState.value = "result";
console.log("lotteryState 变更后:", lotteryState.value);
break; case "result": setTimeout(() => { isDisabled.value = false; }, 2800); // result 状态下点击不做任何事,或者你可以加提示
await lottery3DRef.value?.switchScreen?.("lottery");
await new Promise((resolve) => setTimeout(resolve, 2500));
// 去除高光
lottery3DRef.value?.changeCard1?.();
//延迟2秒
lotteryState.value = "ready";
break; default: break; } }
function handleReset() { lotteryEngine.resetLottery(); } function handleExport() { dataManager.exportData(); }
function handlePrevPrize() { if (dataManager.state.currentPrizeIndex > 0) { dataManager.state.currentPrizeIndex--; dataManager.state.currentPrize = dataManager.state.basicData.prizes[dataManager.state.currentPrizeIndex]; } } function handleNextPrize() { if ( dataManager.state.currentPrizeIndex < dataManager.state.basicData.prizes.length - 1 ) { dataManager.state.currentPrizeIndex++; dataManager.state.currentPrize = dataManager.state.basicData.prizes[dataManager.state.currentPrizeIndex]; } } </script>
<style scoped> .choujiang-main { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; overflow: hidden; /* 添加背景图片 */ background: url("../../assets/bg@2x.png") ; background-size: 100% 100%; }
/* 透明弹窗样式 */ .prize-exhausted-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: flex-start; padding-top: 20vh; z-index: 9999; pointer-events: none; }
.modal-content { background: transparent; padding: 20px 30px; border-radius: 10px; animation: fadeInOut 1s ease-in-out; }
.modal-text { position: fixed !important; top: 300px; left: 50% !important; transform: translate(-50%, -50%) !important; color: #ff0000; font-size: 50px; font-weight: bold; margin: 0; white-space: nowrap; }
@keyframes fadeInOut { 0% { opacity: 0; } 20% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } } </style>
|