update
BIN
src/assets/images/new/complete-icon.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
BIN
src/assets/images/new/game1.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
src/assets/images/new/game2.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
src/assets/images/new/game3.png
Normal file
|
After Width: | Height: | Size: 3.7 MiB |
BIN
src/assets/images/new/game4.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
src/assets/images/new/game5.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 716 KiB After Width: | Height: | Size: 1.4 MiB |
BIN
src/assets/images/new/slider2.png
Normal file
|
After Width: | Height: | Size: 758 KiB |
BIN
src/assets/images/new/slider3.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
src/assets/images/new/slider4.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
src/assets/images/new/slider5.png
Normal file
|
After Width: | Height: | Size: 684 KiB |
BIN
src/assets/images/new/touch-btn.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
@@ -3,9 +3,6 @@
|
||||
<div class="scene-item item-1" @click="handleGoBack">
|
||||
<img src="../assets/images/new/back.png" alt="后退">
|
||||
</div>
|
||||
<div class="scene-item item-2">
|
||||
<img src="../assets/images/new/music.png" alt="音乐">
|
||||
</div>
|
||||
|
||||
<!-- 隐藏的圆形点击区域 -->
|
||||
<div
|
||||
@@ -18,35 +15,75 @@
|
||||
height: circularArea.size
|
||||
}"
|
||||
></div>
|
||||
<div class="game-page">
|
||||
|
||||
</div>
|
||||
<div class="game-page" :style="gameBackgroundImg"></div>
|
||||
</ModalTransition>
|
||||
<Lottery :show="lotteryShow" @close="lotteryShow = false" :type="lotteryType" :data="lotteryNoticeData" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
||||
import ModalTransition from "./ModalTransition.vue"
|
||||
import Lottery from './Lottery.vue'
|
||||
import globalToastEvent, { ToastType } from '../globalToastEvent';
|
||||
import game1 from '../assets/images/new/game1.png';
|
||||
import game2 from '../assets/images/new/game2.png';
|
||||
import game3 from '../assets/images/new/game3.png';
|
||||
import game4 from '../assets/images/new/game4.png';
|
||||
import game5 from '../assets/images/new/game5.png';
|
||||
import { globalStore } from "../globalstore.js";
|
||||
import { Request } from "../libs/utils"
|
||||
|
||||
const props = defineProps({
|
||||
show: false,
|
||||
gameSlideId: 1
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
// Lottery 相关状态
|
||||
const lotteryShow = ref(false)
|
||||
const lotteryType = ref('draw')
|
||||
const lotteryNoticeData = ref(null)
|
||||
const gameImgMap = {
|
||||
1: game1,
|
||||
2: game2,
|
||||
3: game3,
|
||||
4: game4,
|
||||
5: game5
|
||||
}
|
||||
|
||||
const gameBackgroundImg = computed(() => {
|
||||
const id = Number(props.gameSlideId) || 1;
|
||||
const img = gameImgMap[id] || game1;
|
||||
return { backgroundImage: `url(${img})` };
|
||||
})
|
||||
|
||||
const circularAreaList = {
|
||||
1: {
|
||||
top: '62vw',
|
||||
left: '55vw',
|
||||
size: '35vw'
|
||||
},
|
||||
2: {
|
||||
top: '62vw',
|
||||
left: '80vw',
|
||||
size: '35vw'
|
||||
},
|
||||
3: {
|
||||
top: '88vw',
|
||||
left: '48vw',
|
||||
size: '35vw'
|
||||
},
|
||||
4: {
|
||||
top: '96vw',
|
||||
left: '36vw',
|
||||
size: '35vw'
|
||||
},
|
||||
5: {
|
||||
top: '96vw',
|
||||
left: '40vw',
|
||||
size: '35vw'
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏圆形点击区域的配置(可调整坐标和大小)
|
||||
const circularArea = ref({
|
||||
top: '78vw', // 可配置:距离顶部的位置
|
||||
left: '50vw', // 可配置:距离左边的位置
|
||||
size: '25vw' // 可配置:圆形区域的大小
|
||||
const circularArea = computed(() => {
|
||||
const id = Number(props.gameSlideId) || 1;
|
||||
return circularAreaList[id] || circularAreaList[1];
|
||||
})
|
||||
|
||||
const handleGoBack = () => {
|
||||
@@ -54,8 +91,20 @@ const handleGoBack = () => {
|
||||
}
|
||||
|
||||
// 点击隐藏区域显示抽奖弹窗
|
||||
const handleShowLottery = () => {
|
||||
globalToastEvent.emit(ToastType.SHOW_LOTTERY)
|
||||
const handleShowLottery = async () => {
|
||||
const loading = weui.loading()
|
||||
globalToastEvent.emit(ToastType.SHOW_LOTTERY);
|
||||
|
||||
// 点击隐藏区域后,游戏结束,再次调用game log接口
|
||||
const logId = globalStore.current_game_log_id;
|
||||
let gameLogRes = await Request("game/log", { source: globalStore.game_id, log_id: logId }, "POST");
|
||||
if (!gameLogRes || !gameLogRes.res || (gameLogRes.res.status !== 200 && gameLogRes.res.status !== 201)) {
|
||||
emit('close')
|
||||
loading.hide()
|
||||
return
|
||||
} else {
|
||||
console.log(gameLogRes)
|
||||
}
|
||||
}
|
||||
|
||||
// 轮播图数据
|
||||
@@ -236,7 +285,6 @@ onUnmounted(() => {
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
background-image: url('../assets/images/new/game-1-bg.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
<div class="scene-item item-1" @click="handleGoHome">
|
||||
<img src="../assets/images/new/go-home.png" alt="回到首页">
|
||||
</div>
|
||||
<div class="scene-item item-2">
|
||||
<img src="../assets/images/new/music.png" alt="音乐">
|
||||
</div>
|
||||
<div class="confirm-layout">
|
||||
|
||||
<div class="confirm-layout" v-if="isConfirmBtnDisplay">
|
||||
<div class="scene-item item-3" @click="handleConfirmClick">
|
||||
<img src="../assets/images/new/confirm-btn.png" alt="确定">
|
||||
</div>
|
||||
@@ -22,13 +20,15 @@
|
||||
>
|
||||
<div
|
||||
class="carousel-track"
|
||||
:style="{ transform: `translateX(calc(-${currentIndex * 100}% + ${currentIndex * 60}px))`, transition: isTransitioning ? 'transform 0.3s ease' : 'none' }"
|
||||
:style="{ transform: `translateX(calc(-${currentIndex * 104}% + ${currentIndex * 60}px))`, transition: isTransitioning ? 'transform 0.3s ease' : 'none' }"
|
||||
>
|
||||
|
||||
<div
|
||||
v-for="(slide, index) in slides"
|
||||
:key="index"
|
||||
:class="['carousel-slide', { active: currentIndex === index }]"
|
||||
>
|
||||
<img v-show="slide.show" class="complete-icon" src="../assets/images/new/complete-icon.png" alt="">
|
||||
<img :src="slide.image" :alt="slide.title" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,38 +49,91 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
|
||||
import ModalTransition from "./ModalTransition.vue"
|
||||
import globalToastEvent, { ToastType } from '../globalToastEvent';
|
||||
import { Request } from "../libs/utils"
|
||||
import slider1 from '../assets/images/new/slider1.png';
|
||||
import slider2 from '../assets/images/new/slider2.png';
|
||||
import slider3 from '../assets/images/new/slider3.png';
|
||||
import slider4 from '../assets/images/new/slider4.png';
|
||||
import slider5 from '../assets/images/new/slider5.png';
|
||||
import { globalStore } from "../globalstore.js";
|
||||
|
||||
const props = defineProps({
|
||||
show: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:show'])
|
||||
const handleGoHome = () => {
|
||||
emit('close')
|
||||
}
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
// 轮播图数据
|
||||
const slides = ref([
|
||||
{
|
||||
image: new URL('../assets/images/new/slider1.png', import.meta.url).href,
|
||||
image: slider1,
|
||||
title: '轮播图1',
|
||||
link: '/home' // 点击跳转的路由
|
||||
id: 1,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
image: new URL('../assets/images/new/slider1.png', import.meta.url).href,
|
||||
image: slider2,
|
||||
title: '轮播图2',
|
||||
link: '/lottery'
|
||||
id: 2,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
image: new URL('../assets/images/new/slider1.png', import.meta.url).href,
|
||||
image: slider3,
|
||||
title: '轮播图3',
|
||||
link: '/address'
|
||||
id: 3,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
image: slider4,
|
||||
title: '轮播图4',
|
||||
id: 4,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
image: slider5,
|
||||
title: '轮播图5',
|
||||
id: 5,
|
||||
show: true,
|
||||
}
|
||||
])
|
||||
|
||||
const isConfirmBtnDisplay = computed(() => {
|
||||
const slide = slides.value?.[currentIndex.value];
|
||||
return !globalStore.completed_games_today.includes(`game${slide.id}`);
|
||||
})
|
||||
|
||||
const getGameInfo = async () => {
|
||||
const result = await Request('game/info', { refresh_official: true, refresh_cap_scan: true }, "GET")
|
||||
if (result?.res?.status === 200) {
|
||||
console.log(result)
|
||||
// globalStore.completed_games_today = result.json.completed_games_today || [];
|
||||
globalStore.completed_games_today = ['game1', 'game3']; // 测试数据
|
||||
slides.value = slides.value.map(slide => ({
|
||||
...slide,
|
||||
show: globalStore.completed_games_today.includes(`game${slide.id}`)
|
||||
}));
|
||||
} else {
|
||||
weui.alert("获取游戏数据失败,请刷新页面重试");
|
||||
emit('close');
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.show, async (newVal) => {
|
||||
if (!newVal) {
|
||||
return
|
||||
}
|
||||
getGameInfo();
|
||||
}, { immediate: true })
|
||||
|
||||
const handleGoHome = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
|
||||
const currentIndex = ref(0)
|
||||
const startX = ref(0)
|
||||
const moveX = ref(0)
|
||||
@@ -141,24 +194,37 @@ const goToSlide = (index) => {
|
||||
isTransitioning.value = true
|
||||
currentIndex.value = index
|
||||
stopAutoPlay()
|
||||
startAutoPlay()
|
||||
// startAutoPlay()
|
||||
}
|
||||
|
||||
const hasVisitedBefore = localStorage.getItem('hasVisitedGameSwiper');
|
||||
|
||||
const handleConfirmClick = () => {
|
||||
const handleConfirmClick = async () => {
|
||||
const loading = weui.loading()
|
||||
const slide = slides.value?.[currentIndex.value]
|
||||
if (!slide) return
|
||||
handleSlideClick(slide)
|
||||
|
||||
// 点击确定按钮开始游戏,调用一次game log接口
|
||||
const gameSource = `game${slide.id}`;
|
||||
globalStore.game_id = gameSource;
|
||||
let gameLogRes = await Request("game/log", { source: globalStore.game_id }, "POST");
|
||||
if (!gameLogRes || !gameLogRes.res || (gameLogRes.res.status !== 200 && gameLogRes.res.status !== 201)) {
|
||||
emit('close')
|
||||
loading.hide()
|
||||
return
|
||||
} else {
|
||||
globalStore.current_game_log_id = gameLogRes.json.log_id;
|
||||
}
|
||||
}
|
||||
|
||||
const handleSlideClick = (slide) => {
|
||||
|
||||
if (!hasVisitedBefore) {
|
||||
localStorage.setItem('hasVisitedGameSwiper', 'true');
|
||||
globalToastEvent.emit(ToastType.SHOW_GAMEDEMO)
|
||||
globalToastEvent.emit(ToastType.SHOW_GAMEPAGE)
|
||||
globalToastEvent.emit(ToastType.SHOW_GAMEPAGE, slide)
|
||||
} else {
|
||||
globalToastEvent.emit(ToastType.SHOW_GAMEPAGE)
|
||||
globalToastEvent.emit(ToastType.SHOW_GAMEPAGE, slide)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +254,12 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.complete-icon {
|
||||
width: 14vw !important;
|
||||
position: absolute;
|
||||
left: 2vw;
|
||||
top: -2vw;
|
||||
}
|
||||
.scene-item {
|
||||
position: fixed;
|
||||
cursor: pointer;
|
||||
@@ -207,8 +279,8 @@ onUnmounted(() => {
|
||||
.item-1 {
|
||||
width: 14vw;
|
||||
height: 14vw;
|
||||
top: 8vw;
|
||||
left: 2vw;
|
||||
top: 6.8vw;
|
||||
left: 3vw;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.item-2 {
|
||||
|
||||
@@ -301,7 +301,7 @@ const handleLoginSuccess = async () => {
|
||||
console.log("已登录")
|
||||
loginShow.value = false
|
||||
|
||||
await initUserGameInfos(true, true)
|
||||
// await initUserGameInfos(true, true)
|
||||
await getNotice()
|
||||
}
|
||||
|
||||
@@ -397,7 +397,10 @@ globalToastEvent.on(ToastType.SHOW_POPUPMORE, () => {
|
||||
})
|
||||
|
||||
const gamePageShow = ref(false)
|
||||
globalToastEvent.on(ToastType.SHOW_GAMEPAGE, () => {
|
||||
const gameSlideId = ref('')
|
||||
globalToastEvent.on(ToastType.SHOW_GAMEPAGE, (slide) => {
|
||||
console.log("slide in home page:", slide.id);
|
||||
gameSlideId.value = slide.id;
|
||||
gamePageShow.value = true
|
||||
})
|
||||
|
||||
@@ -474,7 +477,7 @@ const handleAddress = (id) => {
|
||||
<Login :show="loginShow" @login-success="handleLoginSuccess" />
|
||||
<GameSwiper v-model:show="gameSwiperShow" @close="gameSwiperShow = false" />
|
||||
<Todolist :show="todolistShow" @close="todolistShow = false"></Todolist>
|
||||
<GamePage :show="gamePageShow" @close="gamePageShow = false" />
|
||||
<GamePage :show="gamePageShow" @close="gamePageShow = false" :gameSlideId="gameSlideId" />
|
||||
<GameDemo :show="gameDemoShow" @close="gameDemoShow = false" />
|
||||
<Lottery :show="lotteryShow" @close="lotteryShow = false" :type="lotteryType" :data="lotteryNoticeData"></Lottery>
|
||||
<SharePage :show="sharePageShow" @close="sharePageShow = false"></SharePage>
|
||||
@@ -618,9 +621,10 @@ const handleAddress = (id) => {
|
||||
|
||||
.item-4 {
|
||||
width: 11vw;
|
||||
top: 1.5%;
|
||||
right: 7%;
|
||||
top: 8vw;
|
||||
right: 4vw;
|
||||
animation-delay: 0s;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.item-5 {
|
||||
|
||||
@@ -7,29 +7,12 @@
|
||||
<div class="lottery-card" ref="cardRef">
|
||||
<div class="lottery-prize">
|
||||
<div class="lottery-layer" ref="layerRef">
|
||||
<!-- 底层:中奖图片(被遮罩层盖住,主要用于语义与对齐) -->
|
||||
<div class="lottery-image" :class="'USER_' + activePrizeData.prize_code" />
|
||||
|
||||
<!-- 中层:遮罩层背景(默认完全遮住中奖图) -->
|
||||
<div class="lottery-mask-image" ref="maskBgRef" />
|
||||
|
||||
<!-- 顶层:通过 mask-img.png 显示中奖图片的一小块,并自动放大揭晓 -->
|
||||
<div
|
||||
class="lottery-reveal lottery-image"
|
||||
:class="[
|
||||
'USER_' + activePrizeData.prize_code,
|
||||
revealDone ? 'reveal-done' : ''
|
||||
]"
|
||||
ref="revealRef"
|
||||
v-show="activePrizeData.prize_code !== 'NO'"
|
||||
/>
|
||||
|
||||
<!-- 可视化的 mask(否则用户看不到 mask-img.png 本身) -->
|
||||
<div
|
||||
class="lottery-mask-visual"
|
||||
:class="revealDone ? 'reveal-done' : ''"
|
||||
v-show="activePrizeData.prize_code !== 'NO'"
|
||||
/>
|
||||
<div class="lottery-mask-image" ref="maskBgRef">
|
||||
<div class="lottery-reveal lottery-image" v-show="activePrizeData.prize_code !== 'NO'">
|
||||
<div class="lottery-image" :class="'USER_' + activePrizeData.prize_code"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 标题(保持原逻辑) -->
|
||||
@@ -137,7 +120,7 @@ const initAnimateStyle = () => {
|
||||
keyframes.push({
|
||||
x: gsap.utils.random(-strength, strength),
|
||||
y: gsap.utils.random(-strength, strength),
|
||||
duration: 0.05 // 每帧的持续时间
|
||||
duration: 0.01 // 每帧的持续时间
|
||||
});
|
||||
}
|
||||
|
||||
@@ -245,9 +228,8 @@ watch(() => props.show, async (newVal) => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
prizeshowTime.to([sceneRef.value], {
|
||||
duration: 2.5,
|
||||
duration: 1.5,
|
||||
scale: 1,
|
||||
opacity: 1,
|
||||
ease: "power4.inOut"
|
||||
@@ -269,7 +251,7 @@ watch(() => props.show, async (newVal) => {
|
||||
onComplete: () => {
|
||||
revealDone.value = true
|
||||
// 动画结束后把遮罩背景淡出,让中奖图完全可见
|
||||
maskBgRef.value && gsap.to(maskBgRef.value, { duration: 0.3, opacity: 0 })
|
||||
maskBgRef.value && gsap.to(maskBgRef.value, { duration: 0.3 })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -353,7 +335,6 @@ onUnmounted(() => {
|
||||
.lottery-image {
|
||||
height: 110vw;
|
||||
width: 82vw;
|
||||
margin-top: -30vw;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-position: center;
|
||||
@@ -368,7 +349,7 @@ onUnmounted(() => {
|
||||
z-index: 3;
|
||||
|
||||
/* CSS Mask(WebKit + 标准) */
|
||||
/* -webkit-mask-image: url("../assets/images/new/mask-img.png");
|
||||
-webkit-mask-image: url("../assets/images/new/mask-img.png");
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-size: var(--maskSize) var(--maskSize);
|
||||
@@ -376,9 +357,9 @@ onUnmounted(() => {
|
||||
mask-image: url("../assets/images/new/mask-img.png");
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: var(--maskSize) var(--maskSize); */
|
||||
-webkit-clip-path: circle(calc(var(--maskSize) * 0.5) at 50% 50%);
|
||||
clip-path: circle(calc(var(--maskSize) * 0.5) at 50% 50%);
|
||||
mask-size: var(--maskSize) var(--maskSize);
|
||||
/* -webkit-clip-path: circle(calc(var(--maskSize) * 0.5) at 50% 50%);
|
||||
clip-path: circle(calc(var(--maskSize) * 0.5) at 50% 50%); */
|
||||
}
|
||||
|
||||
/* 可视化的 mask-img.png:让用户能看到“遮罩在放大”的过程 */
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { reactive } from "vue"
|
||||
|
||||
export const globalStore = reactive({
|
||||
completed_games_today: [],
|
||||
current_game_log_id: '',
|
||||
game_id: '',
|
||||
first_share_today:false,
|
||||
globalAudio: null,
|
||||
userMutedMusic: false, // 用户是否手动静音了音乐
|
||||
|
||||