1167 lines
35 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.

<!-- src/views/Activities/Game/index.vue -->
<template>
<div class="fullPage">
<!-- 预加载状态 -->
<div v-if="isLoading" class="loading-container">
<div class="loading-spinner"></div>
<p>{{ $t('loading') }}...</p>
</div>
<!-- 主要内容 -->
<div v-else>
<!-- 新增的背景图层 -->
<img
v-smart-img
:src="imageUrl('bg2')"
alt=""
style="display: block; width: 100%; position: absolute; inset: 80vw 0 0; z-index: 0"
@click="maskLayerShow = true"
/>
<div class="bg">
<img
v-smart-img
:src="imageUrl('bg')"
alt=""
style="display: block; width: 100%; position: absolute; z-index: 0"
@click="maskLayerShow = true"
/>
<!-- 状态栏占位区域仅在APP中显示 -->
<div v-if="isInAppEnvironment" style="height: 30px"></div>
<!-- 第一名 -->
<div style="display: flex; justify-content: center; margin-top: 11vw">
<TopUser
ranking="1"
:BorderImgUrl="imageUrl('top1')"
:avatarUrl="RankingHasTop10[0].avatar"
:name="RankingHasTop10[0].nickname"
:distributionValue="RankingHasTop10[0].quantity || ''"
style="width: 55%"
@click="viewUserInfo(RankingHasTop10[0].userId)"
/>
</div>
<!-- 按钮 -->
<div style="margin-top: 6vw; display: flex; justify-content: flex-end; align-items: center">
<!-- 帮助按钮 -->
<img
v-smart-img
:src="imageUrl('helpBt')"
alt=""
style="display: block; position: relative; width: 8vw; margin-right: 4vw"
@click="maskLayerShow = true"
/>
</div>
<!-- 倒计时 -->
<div class="timeBox">
<div style="width: 20%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Days }}D</div>
</itemCenter>
</div>
<div class="timeText timeGap"></div>
<div style="width: 20%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Hours }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 20%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Minutes }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 20%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Second }}</div>
</itemCenter>
</div>
</div>
<!-- 切换按钮 -->
<div>
<div style="display: flex; justify-content: space-around; margin-top: 2vw">
<!-- 历史模块按钮 -->
<div style="width: 30%; position: relative" @click="changeModule('history')">
<img
v-show="!historyShow"
v-smart-img
:src="imageUrl(getImgName('historyBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="historyShow"
v-smart-img
:src="imageUrl(getImgName('historyBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
<!-- 排行榜模块按钮 -->
<div style="width: 30%; position: relative" @click="changeModule('ranking')">
<img
v-show="!rankingShow"
v-smart-img
:src="imageUrl(getImgName('rankingBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="rankingShow"
v-smart-img
:src="imageUrl(getImgName('rankingBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
<!-- 奖励模块按钮 -->
<div style="width: 30%; position: relative" @click="changeModule('rewards')">
<img
v-show="!rewardsShow"
v-smart-img
:src="imageUrl(getImgName('rewardsBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="rewardsShow"
v-smart-img
:src="imageUrl(getImgName('rewardBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
</div>
</div>
<!-- 模块 -->
<div>
<!-- history -->
<div
v-show="historyShow"
style="display: flex; flex-direction: column; align-items: center"
>
<!-- 历史榜首 -->
<itemCenter
:imgUrl="imageUrl(getImgName('historyTopBg'))"
:contentStyle="`inset: 31vw 5vw 4vw;
flex-direction: column;
justify-content: space-between;
gap:2vw`"
>
<div
style="
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
"
>
<!-- 上一周榜首按钮 -->
<div
style="
width: 8vw;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
v-smart-img
v-show="historyTopList.length > 1 && historyTopIndex > 0"
:src="imageUrl('topBackBt')"
alt=""
class="flipImg"
style="display: block; width: 100%; object-fit: cover"
@click="historyTopIndex--"
/>
</div>
<!-- 榜首 -->
<TopUser
:BorderImgUrl="imageUrl('historyTopFrame')"
:avatarUrl="historyTopList[historyTopIndex].topUser.avatar"
:name="historyTopList[historyTopIndex].topUser.nickname"
:distributionValue="historyTopList[historyTopIndex].topUser.quantity || ''"
style="width: 90%"
@click="viewUserInfo(historyTopList[historyTopIndex].topUser.userId)"
/>
<!-- 下一周榜首按钮 -->
<div
style="
width: 8vw;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
v-smart-img
v-show="
historyTopList.length > 1 && historyTopIndex + 1 < historyTopList.length
"
:src="imageUrl('topNextBt')"
alt=""
class="flipImg"
style="display: block; width: 100%; object-fit: cover"
@click="historyTopIndex++"
/>
</div>
</div>
</itemCenter>
<!-- 特殊奖励 -->
<itemCenter
:imgUrl="imageUrl(getImgName('specialRewardsBg'))"
:contentStyle="`inset: 50vw 3vw 5vw;`"
>
<img
:src="specialReward?.cover"
alt=""
style="display: block; width: 66%; object-fit: cover"
/>
</itemCenter>
</div>
<!-- Ranking -->
<div v-show="rankingShow" style="position: relative; width: 100%; margin: 10px 0">
<div style="position: relative; z-index: 1">
<!-- 第2-4名 -->
<itemCenter
:imgUrl="imageUrl(getImgName('RankingMain'))"
:contentStyle="`padding: 25% 4% 0;flex-direction: column;`"
>
<div>
<!-- 第2名 -->
<div style="display: flex; justify-content: center">
<TopUser
ranking="2"
:BorderImgUrl="imageUrl('top2')"
:avatarUrl="RankingHasTop10[1].avatar"
:name="RankingHasTop10[1].nickname"
:distributionValue="RankingHasTop10[1].quantity || ''"
style="width: 40%"
@click="viewUserInfo(RankingHasTop10[1].userId)"
/>
</div>
<!-- 第3-4名 -->
<div style="display: flex; justify-content: space-between; margin-top: -5vw">
<TopUser
ranking="3"
:BorderImgUrl="imageUrl('top3')"
:avatarUrl="RankingHasTop10[2].avatar"
:name="RankingHasTop10[2].nickname"
:distributionValue="RankingHasTop10[2].quantity || ''"
style="width: 38%"
@click="viewUserInfo(RankingHasTop10[2].userId)"
/>
<TopUser
ranking="4"
:BorderImgUrl="imageUrl('top4')"
:avatarUrl="RankingHasTop10[3].avatar"
:name="RankingHasTop10[3].nickname"
:distributionValue="RankingHasTop10[3].quantity || ''"
style="width: 38%"
@click="viewUserInfo(RankingHasTop10[3].userId)"
/>
</div>
</div>
</itemCenter>
<!-- 第5-10名 -->
<itemCenter
:imgUrl="imageUrl('RankingCenterBg')"
:contentStyle="`padding: 0 5%;flex-direction: column;justify-content: space-around;`"
>
<!-- 5-7 -->
<div style="width: 100%; display: flex; justify-content: space-between">
<TopUser
v-for="topUser in RankingHasTop10.slice(4, 7)"
:key="topUser.userId"
ranking="5-7"
:BorderImgUrl="imageUrl('top5_7')"
:avatarUrl="topUser.avatar"
:name="topUser.nickname"
:distributionValue="topUser.quantity || ''"
style="width: 30%"
@click="viewUserInfo(topUser.userId)"
/>
</div>
<!-- 8-10 -->
<div style="width: 100%; display: flex; justify-content: space-between">
<TopUser
v-for="topUser in RankingHasTop10.slice(7, 10)"
:key="topUser.userId"
ranking="8-10"
:BorderImgUrl="imageUrl('top8_10')"
:avatarUrl="topUser.avatar"
:name="topUser.nickname"
:distributionValue="topUser.quantity || ''"
style="width: 30%"
@click="viewUserInfo(topUser.userId)"
/>
</div>
</itemCenter>
<!-- 第11名开始 -->
<div v-if="showRanking.length > 0" style="position: relative; z-index: 2">
<itemCenter
v-for="(listItem, index) in showRanking"
:key="listItem.userId"
:imgUrl="imageUrl('RankingItem')"
:contentStyle="`padding: 0 10%`"
:lazy="true"
:immediate="index < 2"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div style="color: #ffe601; font-weight: 700">
{{ listItem?.rank }}
</div>
<!-- 头像 -->
<img
v-smart-img
:src="listItem?.avatar || ''"
alt=""
style="
display: block;
width: 13vw;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 名称、id -->
<div
style="
flex: 1;
min-width: 0;
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
"
>
<div
style="
color: #fff;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
class="UserNickname"
>
{{ listItem?.nickname }}
</div>
<div style="color: #fff; font-weight: 590" class="UserNickname">
{{ $t('user_id_prefix') }} {{ listItem?.account }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/coin.png"
alt=""
style="display: block; width: 1.5em; aspect-ratio: 1/1; object-fit: cover"
/>
<div style="color: #ffe601; font-weight: 700" class="UserNickname">
{{ listItem?.quantity }}
</div>
</div>
</itemCenter>
</div>
<!-- 底框 -->
<img
v-smart-img
:src="imageUrl('RankingBottomBorder')"
alt=""
width="100%"
style="display: block; margin-top: -6vw; position: relative; z-index: 2"
/>
</div>
</div>
<!-- Rewards -->
<div
v-show="rewardsShow"
style="display: flex; flex-direction: column; align-items: center"
>
<div
v-for="(rewardsTop, top) in rewardsList"
:key="top"
style="position: relative; width: 100%; margin: 10px 0"
>
<!-- 第一名奖励 -->
<itemCenter
v-if="top == 0"
:imgUrl="topImg[0]"
:contentStyle="`display: grid;grid-template-columns: repeat(2, 1fr);gap: 2vw;padding: 28vw 4vw 8vw 37vw;`"
>
<div
v-for="(reward, rewardIndex) in rewardsTop.rewards"
:key="rewardIndex"
style="
width: 100%;
min-width: 0;
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
"
>
<div
style="
width: 100%;
aspect-ratio: 1/1;
display: flex;
justify-content: center;
align-items: center;
"
>
<!-- 奖励图片 -->
<img
v-smart-img
:src="reward.cover || ''"
alt=""
style="display: block; width: 70%; object-fit: cover"
@error="(e) => handleRewardImageError(e, reward.type)"
/>
</div>
<!-- 数值 -->
<div
style="
width: 100%;
display: flex;
justify-content: center;
align-items: center;
"
>
<div
style="
min-width: 0;
color: #f9e447;
text-align: center;
font-size: 1.2em;
font-weight: 900;
font-family: Atma;
"
>
{{ showDetail(reward.type, reward) }}
</div>
</div>
</div>
<!-- 启动时间 -->
<div
style="
position: absolute;
left: 3.5vw;
bottom: 10vw;
width: 28vw;
display: flex;
justify-content: center;
align-items: center;
"
>
<div
style="color: #f9e447; text-align: center; font-size: 1.2em; font-weight: 900"
>
7Days
</div>
</div>
</itemCenter>
<!-- 第2-4、5-7、8-10名奖励 -->
<itemCenter
v-else
:imgUrl="topImg[Number(rewardsTop.rankRange) - 1]"
:contentStyle="`display: grid;grid-template-columns: repeat(3, 1fr);gap: 4vw;padding: 28vw 3vw 10vw;`"
>
<div
v-for="(reward, rewardIndex) in rewardsTop.rewards"
:key="rewardIndex"
style="width: 100%"
:style="rewardIndex == 3 ? `grid-row: 2;grid-column: 2;` : ''"
>
<div
style="
width: 100%;
aspect-ratio: 1/1;
display: flex;
justify-content: center;
align-items: center;
"
>
<!-- 奖励图片 -->
<img
v-smart-img
:src="reward.cover || ''"
alt=""
style="display: block; width: 70%; object-fit: cover"
@error="(e) => handleRewardImageError(e, reward.type)"
/>
</div>
<!-- 数值 -->
<div
style="
width: 100%;
display: flex;
justify-content: center;
align-items: center;
"
>
<div
style="
min-width: 0;
color: #f9e447;
text-align: center;
font-size: 1.2em;
font-weight: 900;
font-family: Atma;
"
>
{{ showDetail(reward.type, reward) }}
</div>
</div>
</div>
</itemCenter>
</div>
</div>
</div>
<!-- 我的排名占位 -->
<div v-if="rankingShow" style="height: 22vw"></div>
<!-- 我的排名 -->
<itemCenter
v-if="rankingShow"
style="position: fixed; bottom: 0; z-index: 3"
:imgUrl="imageUrl('myRankingBg')"
:contentStyle="`padding: 0 8%`"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div style="color: #ffe601; font-weight: 700">
{{ myRanking.rank || 999 }}
</div>
<!-- 头像 -->
<img
v-smart-img
:src="myRanking.avatar || ''"
alt=""
style="
display: block;
width: 15vw;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 名称 -->
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column">
<div
style="
color: #fff;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
class="UserNickname"
>
{{ myRanking.nickname }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/coin.png"
alt=""
style="display: block; width: 1.5em; aspect-ratio: 1/1; object-fit: cover"
/>
<div style="color: #ffe601; font-weight: 700">
{{ myRanking.quantity || 0 }}
</div>
</div>
</itemCenter>
<!-- 弹窗遮罩层 -->
<maskLayer :maskLayerShow="maskLayerShow" @click="maskLayerShow = false">
<!-- help弹窗 -->
<div style="margin: 10vh 0 5vh" @click.stop>
<itemCenter
:imgUrl="imageUrl(getImgName('helpBg'))"
:contentStyle="`inset: 15% 8% 3%;overflow-y: auto;display:block;`"
>
<img
v-smart-img
:src="imageUrl(getImgName('helpInfo'))"
alt=""
style="display: block; width: 100%; object-fit: cover; margin-bottom: 6vw"
/>
</itemCenter>
</div>
</maskLayer>
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { isInApp, viewUserInfo } from '@/utils/appBridge.js'
import { connectToApp } from '@/utils/appConnector.js'
import { useLangStore } from '@/stores/lang'
import { getPngUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/imagePreloader.js'
import { handleAvatarImageError, handleRewardImageError } from '@/utils/imageHandler.js'
import {
getThisWeekRewardsAndGifts, // 获取本周奖励和礼物
getRankingListAndMyRanking, // 获取排行榜和我的排名
getHistoryTopOne, // 获取历史榜首
activityResource, // 活动特定资源
} from '@/api/activity.js'
import itemCenter from '@/components/itemCenter.vue'
import TopUser from './components/topUser.vue'
import maskLayer from '@/components/MaskLayer.vue'
const isInAppEnvironment = ref(false) // 检测是否在APP环境中
const maskLayerShow = ref(false) //帮助模块
// 预加载状态
const isLoading = ref(true)
const langStore = useLangStore()
// 当前语言类型
const currentLangType = computed(() => {
return langStore.selectedLang?.type || 'en'
})
// 获取OSS图片URL的函数
const imageUrl = (filename) => getPngUrl('Ranking/GamesKing/', filename)
// 根据语言获取图片名
const getImgName = (filename) => {
return currentLangType.value === 'ar' ? `${filename}_ar` : filename
}
// 倒计时
const Days = ref(0)
const Hours = ref(0)
const Minutes = ref(0)
const Second = ref(0)
let timer = null
// 模块切换展示
const historyShow = ref(true) //历史榜首
const rankingShow = ref(false) //排行榜
const rewardsShow = ref(false) //奖励模块
const changeModule = (module) => {
switch (module) {
case 'history':
historyShow.value = true
rankingShow.value = false
rewardsShow.value = false
break
case 'ranking':
historyShow.value = false
rankingShow.value = true
rewardsShow.value = false
break
case 'rewards':
historyShow.value = false
rankingShow.value = false
rewardsShow.value = true
}
}
const historyTopList = ref([]) // 历史榜首
const historyTopIndex = ref(0)
const Ranking = ref([]) // 排行榜
const myRanking = ref({}) // 我的排名
const rewardsList = ref([]) // 奖励列表
const specialReward = ref({}) // 奖励列表
const topImg = ref([
imageUrl('top1RewardBg'),
imageUrl('top2_4RewardBg'),
imageUrl('top5_7RewardBg'),
imageUrl('top8_10RewardBg'),
]) // top奖励背景
// 处理排行榜小于10人时的情况
const RankingHasTop10 = computed(() => {
let RankingShow = [...Ranking.value]
if (Ranking.value.length < 10) {
let addNullUser = Array.from({ length: 10 - Ranking.value.length }, () => ({
avatar: '',
nickname: '',
quantity: '',
}))
RankingShow.push(...addNullUser)
}
return RankingShow
})
// 展示用的榜单
const showRanking = computed(() => {
return Ranking.value.filter((_, index) => index >= 10)
// return []
})
// 获取对应的时间戳
const getNextMondayInBeijing = () => {
const now = new Date()
const targetDate = new Date(now.getTime()) // 创建一个基于当前时间的新日期对象
// 转换为北京时间来判断星期几
const utcTime = now.getTime() + now.getTimezoneOffset() * 60000
const beijingTime = new Date(utcTime + 8 * 3600000) // UTC+8
const beijingDay = beijingTime.getDay() // 0=周日, 1=周一, ..., 6=周六
const beijingHour = beijingTime.getHours()
// 转换为 0=周一, 1=周二, ..., 6=周日
const normalizedDay = beijingDay === 0 ? 6 : beijingDay - 1
let daysToAdd
if (normalizedDay === 0) {
// 今天是周一
if (beijingHour >= 5) {
daysToAdd = 7 // 超过5点计算到下周一的所需时间
} else {
daysToAdd = 0 // 今天
}
} else {
daysToAdd = 7 - normalizedDay // 到下周一的天数
}
// 正确地添加天数
targetDate.setDate(targetDate.getDate() + daysToAdd) // 添加天数到下周一的当前时间
targetDate.setHours(5, 0, 0, 0) // 将时间重新设置为早上5点作为目标时间戳
return targetDate.getTime()
}
const targetTime = ref(getNextMondayInBeijing()) // 闭包保存目标时间 (核心修正)
// 格式化时间
const formatTime = (value) => {
return value < 10 ? `0${value}` : value
}
// 倒计时
const getCountdown = () => {
const now = Date.now()
let diff = targetTime.value - now
if (diff <= 0) {
// 初始化数据
initData()
targetTime.value += 7 * 86400000 // +7天 (更新闭包变量)
diff = targetTime.value - now
}
const totalSeconds = Math.floor(diff / 1000)
Days.value = Math.floor(totalSeconds / (24 * 3600))
Hours.value = formatTime(Math.floor((totalSeconds % (24 * 3600)) / 3600))
Minutes.value = formatTime(Math.floor((totalSeconds % 3600) / 60))
Second.value = formatTime(Math.floor(totalSeconds % 60))
}
// 格式化奖励的展示信息
const showDetail = (type, reward) => {
let showamount = ['GOLD', 'DIAMOND', 'GIFT', 'FRAGMENTS']
if (showamount.includes(type)) {
return reward.content
} else if (type === 'DOLLARS') {
return `$${reward.content}`
} else {
return `${reward.quantity}Days`
}
}
// 获取历史榜首
const getAllTopOne = async () => {
const resHistoryTopOne = await getHistoryTopOne('10')
if (resHistoryTopOne.status && resHistoryTopOne.body) {
historyTopList.value = resHistoryTopOne.body?.historicalList
}
}
// 获取排行榜和我的排名
const getListAndMy = async () => {
let data = {
activityType: 10,
}
const resMyWeekStarRanking = await getRankingListAndMyRanking(data)
console.log('resMyWeekStarRanking:', resMyWeekStarRanking)
if (resMyWeekStarRanking.status && resMyWeekStarRanking.body) {
myRanking.value = resMyWeekStarRanking.body.currentUserRank
Ranking.value = resMyWeekStarRanking.body.rankingList
}
}
// 获取每周奖励列表
const getRewardsAndGifts = async () => {
const resRewardsAndGifts = await getThisWeekRewardsAndGifts('2001207026499137537')
if (resRewardsAndGifts.status && resRewardsAndGifts.body) {
rewardsList.value = resRewardsAndGifts.body.butOneRewards
}
}
// 获取指定类型活动资源
const getActivityResource = async () => {
let data = {
sysOrigin: 'LIKEI',
activityType: 'GAME_KING',
}
const resActivityResource = await activityResource(data)
if (resActivityResource.status && resActivityResource.body) {
specialReward.value = resActivityResource.body?.[0]?.propsGroup?.activityRewardProps?.[0]
}
}
// 刷新页面数据
const initData = async () => {
await Promise.all([
getAllTopOne(), // 获取历史榜首
getListAndMy(), // 获取排行榜和我的排名
getRewardsAndGifts(), // 获取本周的礼物和奖励列表
getActivityResource(), // 获取指定类型活动资源
])
}
// 预加载关键图片
const preloadCriticalImages = async () => {
const criticalImages = [
imageUrl('bg'),
imageUrl('bg2'),
imageUrl('helpBt'),
imageUrl('helpInfo'),
imageUrl('historyBt'),
imageUrl('historyBtActive'),
imageUrl('historyTopBg'),
imageUrl('historyTopFrame'),
imageUrl('specialRewardsBg'),
imageUrl('myRankingBg'),
imageUrl('rankingBt'),
imageUrl('rankingBtActive'),
imageUrl('rewardBtActive'),
imageUrl('rewardsBt'),
imageUrl('timeBg'),
imageUrl('topBackBt'),
imageUrl('topNextBt'),
imageUrl('top1'),
]
const criticalImages_ar = [
imageUrl('bg'),
imageUrl('bg2'),
imageUrl('helpBt'),
imageUrl('helpInfo_ar'),
imageUrl('historyBt_ar'),
imageUrl('historyBtActive_ar'),
imageUrl('historyTopBg_ar'),
imageUrl('historyTopFrame'),
imageUrl('specialRewardsBg_ar'),
imageUrl('myRankingBg'),
imageUrl('rankingBt_ar'),
imageUrl('rankingBtActive_ar'),
imageUrl('rewardBtActive_ar'),
imageUrl('rewardsBt_ar'),
imageUrl('timeBg'),
imageUrl('topBackBt'),
imageUrl('topNextBt'),
imageUrl('top1'),
]
if (currentLangType.value == 'en') {
await preloadImages(criticalImages)
} else if (currentLangType.value == 'ar') {
await preloadImages(criticalImages_ar)
}
}
// 完成预加载
const completePreloading = async () => {
try {
// 执行所有初始化操作
await Promise.all([initData(), preloadCriticalImages()])
} catch (error) {
console.error('预加载过程中发生错误:', error)
} finally {
// 无论成功或失败都结束加载状态
isLoading.value = false
}
}
// 预加载其他图片
const preloadOtherImages = async () => {
const criticalImages = [
imageUrl('RankingBottomBorder'),
imageUrl('RankingCenterBg'),
imageUrl('RankingItem'),
imageUrl('RankingMain'),
imageUrl('top1RewardBg'),
imageUrl('top2_4RewardBg'),
imageUrl('top5_7RewardBg'),
imageUrl('top8_10RewardBg'),
imageUrl('top2'),
imageUrl('top3'),
imageUrl('top4'),
imageUrl('top5_7'),
imageUrl('top8_10'),
]
const criticalImages_ar = [
imageUrl('RankingBottomBorder'),
imageUrl('RankingCenterBg'),
imageUrl('RankingItem'),
imageUrl('RankingMain_ar'),
imageUrl('top1RewardBg'),
imageUrl('top2_4RewardBg'),
imageUrl('top5_7RewardBg'),
imageUrl('top8_10RewardBg'),
imageUrl('top2'),
imageUrl('top3'),
imageUrl('top4'),
imageUrl('top5_7'),
imageUrl('top8_10'),
]
if (currentLangType.value == 'en') {
await preloadImages(criticalImages)
} else if (currentLangType.value == 'ar') {
await preloadImages(criticalImages_ar)
}
}
// 使用工具函数连接APP
const connectToAppHandler = async () => {
await connectToApp(() => {
// 连接成功回调
completePreloading() // 完成预加载
})
}
// 组件挂载时检测环境
onMounted(() => {
connectToAppHandler()
preloadOtherImages() // 预加载其他图片
isInAppEnvironment.value = isInApp()
getCountdown()
timer = setInterval(getCountdown, 1000) //倒计时每秒更新
})
onUnmounted(() => {
clearInterval(timer) //摧毁计时器
})
</script>
<style lang="scss" scoped>
* {
color: #fff;
font-family: 'SF Pro';
}
.fullPage {
position: relative;
background: #5d0c00;
}
.bg {
width: 100vw;
min-height: 100vh;
position: relative;
z-index: 1;
}
.timeText {
color: #fff;
font-weight: 590;
font-size: 1.5em;
}
.timeGap {
width: 6px;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
}
.btTitle {
color: #fff;
font-weight: 700;
}
.topTitle {
font-size: 1.5em;
}
.history-name {
font-size: 0.8em;
}
.history-time {
font-size: 0.8em;
}
.UserNickname {
font-size: 0.8em;
}
.timeBox {
display: flex;
justify-content: center;
margin-top: 10vw;
}
/* 添加加载动画样式 */
.loading-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #666;
}
.loading-spinner {
width: 32px;
height: 32px;
border: 3px solid #f3f3f3;
border-top: 3px solid #f59e0b;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 12px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 14px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
}
@media screen and (min-width: 1024px) {
* {
font-size: 32px;
}
}
[dir='rtl'] .timeBox {
flex-direction: row-reverse;
}
[dir='rtl'] .flipImg {
transform: scaleX(-1);
}
</style>