1303 lines
39 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/Ranking/KingAndQueen/TopList.vue -->
<template>
<div class="fullPage">
<!-- 预加载状态 -->
<div v-if="isLoading" class="loading-container">
<LoadingContent :text-style="{ color: '#fff' }">{{ $t('loading') }}...</LoadingContent>
</div>
<!-- 主要内容 -->
<div v-else style="width: 100vw; min-height: 100vh; overflow: hidden; position: relative">
<!-- 页面背景 -->
<BackgroundLayer :useCanvas="true" :backgroundImages="[webpUrl('bg')]" />
<div class="bg">
<!-- 状态栏占位区域仅在APP中显示 -->
<div style="height: 30px"></div>
<button v-show="!maskLayerShow" class="ranking-back-btn" @click="handlePageBack">
<img v-smart-img class="flipImg" :src="backIcon" alt="" />
</button>
<!-- 帮助按钮 -->
<img
v-smart-img
:src="webpUrl('help')"
alt=""
style="
width: 10%;
position: absolute;
top: calc(env(safe-area-inset-top, 0px) + 30px + 14vw);
right: 8px;
z-index: 4;
"
@click="helpInfoShow = true"
/>
<!-- history按钮 -->
<img
v-smart-img
:src="webpUrl('history')"
alt=""
style="min-height: 17.22vw; width: 20%; margin-top: 14vw"
@click="historyShow = true"
/>
<!-- 每周榜首 -->
<div style="display: flex; flex-direction: column; align-items: center; gap: 16px">
<!-- 主标题 -->
<img
v-smart-img
:src="webpUrl('listTitle')"
alt=""
style="min-height: 11.55vw; width: 90%"
/>
<!-- 榜首 -->
<div style="min-height: 40vw; width: 100%; display: flex; justify-content: space-around">
<div
style="width: 40%"
v-for="(topUser, index) in listTop"
:key="index"
@click="viewUserInfo(topUser.userInfo.userId)"
>
<div
style="
min-height: 40vw;
position: relative;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
"
>
<!-- 头像框 -->
<img v-smart-img :src="topUser.Frame" alt="" style="width: 100%; z-index: 1" />
<!-- 头像 -->
<div
style="
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 0;
"
>
<img
v-if="topUser.userInfo.userAvatar"
:src="topUser.userInfo.userAvatar || ''"
alt=""
width="70%"
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
@error="handleAvatarImageError"
@click="viewUserInfo(topUser.userInfo.userId)"
/>
</div>
<div
style="
height: 10%;
width: 50%;
position: absolute;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
"
:style="{ bottom: topUser.type == 'topKing' ? '9.3%' : '7%' }"
>
<div
style="
color: #fff;
font-size: 0.8em;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ topUser.userInfo.userNickname }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 刷新倒计时 -->
<div style="min-height: 9vw; display: flex; justify-content: center; margin-top: 20px">
<!-- 天数 -->
<itemCenter :imgUrl="webpUrl('dayBg')" style="width: 12vw; margin-right: 10px">
<div class="time">{{ Days }}D</div>
</itemCenter>
<!-- 当天时间倒计时 -->
<itemCenter :imgUrl="webpUrl('timeBg')" style="width: 28.5%">
<div class="time">{{ Hours }} : {{ Minutes }} : {{ Second }}</div>
</itemCenter>
</div>
<!-- rewards按钮 -->
<div style="min-height: 17.46vw; display: flex; justify-content: flex-end; margin-top: -8%">
<img
v-smart-img
:src="webpUrl('rewards')"
alt=""
style="width: 20%"
@click="rewardsShow = true"
/>
</div>
<!-- 每周礼物 -->
<div
style="
display: flex;
justify-content: center;
width: 108vw;
position: relative;
left: -4vw;
"
>
<itemCenter style="min-height: 74.91vw" :imgUrl="webpUrl('eventGifts')">
<div style="width: 80%; display: flex; justify-content: space-around; margin-top: 10%">
<div
v-for="(gift, index) in gifts"
:key="index"
style="width: 30%; display: flex; flex-direction: column"
>
<itemCenter style="min-height: 25.91vw" :imgUrl="webpUrl('gift')">
<img :src="gift.giftPhoto" alt="" width="50%" />
</itemCenter>
<div style="display: flex; justify-content: center; align-items: center; gap: 2px">
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.3em; aspect-ratio: 1/1"
/>
<div style="color: rgba(255, 255, 255, 1); font-weight: 590">
{{ gift.giftCandy }}
</div>
</div>
</div>
</div>
</itemCenter>
</div>
<!-- 排行榜模块 -->
<div style="width: 100vw">
<!-- 排行榜切换按钮 -->
<div style="min-height: 21.46vw; width: 100%">
<div
v-show="visibleKingList"
style="width: 100%; display: flex; justify-content: space-around"
>
<img v-smart-img :src="webpUrl('kingBtActive')" alt="" style="width: 40%" />
<img
v-smart-img
:src="webpUrl('queenBt')"
alt=""
style="width: 40%"
@click="visibleKingList = false"
/>
</div>
<div
v-show="!visibleKingList"
style="width: 100%; display: flex; justify-content: space-around"
>
<img
v-smart-img
:src="webpUrl('kingBt')"
alt=""
style="width: 40%"
@click="visibleKingList = true"
/>
<img v-smart-img :src="webpUrl('queenBtActive')" alt="" style="width: 40%" />
</div>
</div>
<!-- 排行榜 -->
<div style="width: 100%; width: 108vw; position: relative; left: -4vw">
<borderImg title="Ranking">
<itemCenter
:imgUrl="webpUrl('border-item-user')"
style="min-height: 27.66vw; margin: -2px 0"
:contentStyle="`justify-content: flex-start;padding: 0 15%;gap: 8px;`"
v-for="(listItem, index) in topList"
:key="index"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
align-self: stretch;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div
style="
width: auto;
min-width: 0;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
"
>
<div style="color: #edb247; font-weight: 700">{{ listItem.rank }}</div>
</div>
<!-- 头像 -->
<div
style="
width: 25%;
aspect-ratio: 1/1;
border-radius: 50%;
background: linear-gradient(
to bottom,
rgba(255, 224, 60, 1),
rgba(255, 189, 19, 1)
);
display: flex;
justify-content: center;
align-items: center;
"
>
<img
:src="listItem.userAvatar || ''"
alt=""
style="
display: block;
width: 90%;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
</div>
<!-- 名称 -->
<div
style="
flex: 1;
min-width: 0;
padding: 0 2px;
display: flex;
flex-direction: column;
"
>
<div
style="
width: 100%;
color: #fff;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ listItem.userNickname }}
</div>
<div style="color: #fff; font-weight: 590">
{{ $t('user_id_prefix') }} {{ listItem.account }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
align-self: stretch;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.3em; aspect-ratio: 1/1"
/>
<div style="color: #edb247; font-weight: 700">
{{ listItem.quantity }}
</div>
</div>
</itemCenter>
<!-- 触发加载功能 -->
<div ref="kingListLoadmore" v-show="showKingLoading && visibleKingList"></div>
<!-- 触发加载功能 -->
<div ref="queenListloadmore" v-show="showQueenLoading && !visibleKingList"></div>
</borderImg>
</div>
</div>
</div>
<!-- 弹窗遮罩层 -->
<maskLayer class="ranking-popup-mask" :maskLayerShow="maskLayerShow" @click="closedPopup">
<!-- help弹窗 -->
<div
v-show="helpInfoShow"
style="width: 100vw; margin: 20% 0; overflow: hidden"
@click.stop
>
<img
v-smart-img
:src="webpUrl(getImgName('helpInfo'))"
alt=""
style="width: 108vw; position: relative; left: -4vw; display: block"
/>
</div>
<!-- history弹窗 -->
<div v-show="historyShow" style="width: 100vw; margin: 20% 0; overflow: hidden" @click.stop>
<div style="width: 108vw; position: relative; left: -4vw">
<borderImg title="History">
<div
style="
background-size: 100% 100%;
min-height: 20px;
margin: -10px 0;
padding: 10px 10%;
"
:style="{ backgroundImage: toCssBackgroundImage(webpUrl('border-item')) }"
>
<!-- 国王皇后榜首 -->
<div
style="
width: 100%;
display: flex;
justify-content: space-around;
margin-top: 16px;
"
>
<div
style="width: 40%"
v-for="(topOne, topIndex) in showTopOne.top"
:key="topIndex"
>
<div
style="
min-height: 34.56vw;
position: relative;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
"
>
<!-- 头像框 -->
<img v-smart-img :src="topOne.Frame" alt="" style="width: 100%; z-index: 1" />
<!-- 头像 -->
<div
style="
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 0;
"
>
<img
:src="topOne.userInfo.userAvatar"
alt=""
width="70%"
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
/>
</div>
<div
style="
height: 10%;
width: 50%;
color: #fff;
position: absolute;
z-index: 2;
font-weight: 860;
font-size: 12px;
display: flex;
justify-content: center;
align-items: center;
"
:style="{ bottom: topOne.type == 'topKing' ? '9.3%' : '7%' }"
>
<div
style="
color: #fff;
font-size: 0.7em;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ topOne.userInfo.userNickname }}
</div>
</div>
</div>
<div style="color: #fff; font-weight: 590; text-align: center">
{{ $t('user_id_prefix') }} {{ topOne.userInfo.account }}
</div>
</div>
</div>
<!-- 时间 -->
<div
style="
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
"
>
<img
v-smart-img
:src="webpUrl('timeBack')"
alt=""
width="18px"
height="18px"
@click="changeHistoryIndex(1)"
/>
<div
style="
width: 40%;
text-align: center;
font-size: 14px;
font-weight: 590;
background-image: -webkit-linear-gradient(
top,
rgba(243, 183, 0, 1),
rgba(255, 238, 198, 1)
);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
"
>
{{ showTopOne.group }}
</div>
<img
v-smart-img
:src="webpUrl('timeNext')"
alt=""
width="18px"
height="18px"
@click="changeHistoryIndex(-1)"
/>
</div>
</div>
</borderImg>
</div>
</div>
<!-- rewards弹窗 -->
<div
v-show="rewardsShow"
style="width: 100vw; padding: 20% 0; overflow: hidden"
@click.stop
>
<div style="width: 108vw; position: relative; left: -4vw">
<!-- 取消按钮 -->
<img
v-smart-img
:src="webpUrl('cancel')"
alt=""
style="width: 7%; position: absolute; top: 0; right: 6%; z-index: 99"
@click="closedPopup"
/>
<div style="width: 100%">
<borderImg title="Rewards">
<div
style="
background-size: 100% 100%;
min-height: 20px;
margin: -20px 0;
padding: 20px 10%;
"
:style="{ backgroundImage: toCssBackgroundImage(webpUrl('border-item')) }"
>
<!-- 奖励榜切换按钮 -->
<div style="width: 100%; min-height: 18.54vw">
<div
v-show="visibleKingRewards"
style="width: 100%; display: flex; justify-content: space-around"
>
<img v-smart-img :src="webpUrl('kingBtActive')" alt="" style="width: 40%" />
<img
v-smart-img
:src="webpUrl('queenBt')"
alt=""
style="width: 40%"
@click="visibleKingRewards = false"
/>
</div>
<div
v-show="!visibleKingRewards"
style="width: 100%; display: flex; justify-content: space-around"
>
<img
v-smart-img
:src="webpUrl('kingBt')"
alt=""
style="width: 40%"
@click="visibleKingRewards = true"
/>
<img v-smart-img :src="webpUrl('queenBtActive')" alt="" style="width: 40%" />
</div>
</div>
<!-- 奖励榜 -->
<div v-for="(rewardsTop, top) in rewardsList" :key="top">
<div
style="display: flex; flex-direction: column; align-items: center"
v-if="rewardsTop.rewards.length > 0"
>
<img
v-smart-img
:src="topImg[Number(rewardsTop.rankRange) - 1]"
alt=""
style="min-height: 19.13vw; width: 40%; margin: 24px 0"
/>
<div
style="
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3%;
margin-bottom: 3%;
"
>
<div
v-for="(reward, rewardIndex) in rewardsTop.rewards"
:key="rewardIndex"
style="width: 100%"
>
<itemCenter style="min-height: 27.07vw" :imgUrl="webpUrl('gift')">
<img
v-smart-img
:src="reward.cover || ''"
alt=""
width="50%"
style="aspect-ratio: 1/1"
@error="(e) => handleRewardImageError(e, reward.type)"
/>
</itemCenter>
<div
style="
color: rgba(255, 255, 255, 1);
font-weight: 590;
text-align: center;
"
>
{{ showDetail(reward.type, reward) }}
</div>
</div>
</div>
</div>
</div>
</div>
</borderImg>
</div>
</div>
</div>
</maskLayer>
<!-- 我的排名占位 -->
<div style="height: 25vw"></div>
<!-- 我的排名 -->
<div
style="
position: fixed;
bottom: 0;
width: 100vw;
background-color: rgba(77, 30, 22, 1);
display: flex;
justify-content: center;
margin-top: 10px;
"
>
<img
v-smart-img
:src="webpUrl('myRankingBg')"
alt=""
style="width: calc(100% - 1px); display: block"
/>
<div
style="
position: absolute;
inset: 0;
padding: 2vw 4vw 0;
display: flex;
align-items: center;
justify-content: space-around;
gap: 4px;
"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
align-self: stretch;
display: flex;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div
style="
width: auto;
min-width: 0;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
"
>
<div style="color: #edb247; font-size: 1.1em; font-weight: 700">
{{ (myRanking.userSex == 1 ? myRanking.wealthRank : myRanking.charmRank) || 999 }}
</div>
</div>
<!-- 头像 -->
<div
style="
width: 22%;
aspect-ratio: 1/1;
border-radius: 50%;
background: linear-gradient(
to bottom,
rgba(255, 224, 60, 1),
rgba(255, 189, 19, 1)
);
display: flex;
justify-content: center;
align-items: center;
"
>
<img
:src="myRanking.userAvatar || ''"
alt=""
style="
display: block;
width: 90%;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
</div>
<!-- 名称 -->
<div
style="
flex: 1;
min-width: 0;
font-weight: 700;
padding: 0 4px;
display: flex;
flex-direction: column;
"
>
<div
style="
color: #fff;
font-size: 1.1em;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ myRanking.userNickname }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
align-self: stretch;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em; aspect-ratio: 1/1"
/>
<!-- 1:,0: -->
<div
v-if="myRanking.userSex == 1"
style="color: #edb247; font-size: 1.1em; font-weight: 700"
>
{{ myRanking.wealthQuantity }}
</div>
<div v-else style="color: #edb247; font-size: 1.1em; font-weight: 700">
{{ myRanking.charmQuantity }}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { closePage, viewUserInfo } from '@/utils/appBridge.js'
import { useLangStore } from '@/stores/lang'
import { useThrottle } from '@/utils/useDebounce'
import { connectToApp } from '@/utils/appConnector.js'
import { getWebpUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/image/imagePreloader.js'
import { toCssBackgroundImage } from '@/utils/protectedAssets.js'
import { handleAvatarImageError, handleRewardImageError } from '@/utils/image/imageHandler.js'
import {
getWeekTopList,
getWeekMyContribution,
getThisWeekRewardsAndGifts,
getHistoryTopOne,
} from '@/api/topList.js'
import { getMemberProfile } from '@/api/wallet'
import BackgroundLayer from '@/components/BackgroundLayer.vue'
import borderImg from './components/borderImg.vue'
import itemCenter from '@/components/itemCenter.vue'
import maskLayer from '@/components/MaskLayer.vue'
const langStore = useLangStore()
const backIcon = new URL('../../../assets/icon/Azizi/arrowBack.png', import.meta.url).href
// 当前语言类型
const currentLangType = computed(() => {
return langStore.selectedLang?.type || 'en'
})
// 预加载状态
const isLoading = ref(true)
// 获取OSS图片URL的函数
const webpUrl = (filename) => getWebpUrl('Ranking/KingQueenWebp/', filename)
// 根据语言获取图片名
const getImgName = (filename) => {
return currentLangType.value === 'ar' ? `${filename}_ar` : filename
}
// 使用工具函数连接APP
const handlePageBack = () => {
if (maskLayerShow.value) return
console.log('home back')
closePage()
}
const connectToAppHandler = async () => {
await connectToApp(() => {
// 连接成功回调
completePreloading() // 完成预加载
})
}
const userInfo = ref({})
const visibleKingList = ref(true)
const historyList = ref([]) // 榜首历史记录
const showTopOne = computed(() => {
let topNew = []
if (historyList.value[historyIndex.value]?.wealth)
topNew.push({
type: 'topKing',
Frame: webpUrl('kingFrame'),
userInfo: historyList.value[historyIndex.value].wealth || {},
})
if (historyList.value[historyIndex.value]?.charm) {
topNew.push({
type: 'topQueen',
Frame: webpUrl('queenFrame'),
userInfo: historyList.value[historyIndex.value].charm || {},
})
}
return {
group: historyList.value[historyIndex.value]?.group,
top: topNew,
}
})
const historyIndex = ref(0)
const changeHistoryIndex = (num) => {
let index = historyIndex.value + num
let length = historyList.value.length
console.log('index:', index)
console.log('length:', length)
if (index >= 0 && index < length) {
historyIndex.value = index
}
}
const myRanking = ref({}) // 我的排名
const kingListCurrent = ref(1) //国王榜第几页
const kingListParams = computed(() => ({
type: 'THIS_WEEK',
kingQueenType: 'WEALTH',
current: kingListCurrent.value,
size: 10,
}))
const kingList = ref([]) // 国王榜
const queenListCurrent = ref(1) //女王榜第几页
const queenListParams = computed(() => ({
type: 'THIS_WEEK',
kingQueenType: 'CHARM',
current: queenListCurrent.value,
size: 10,
}))
const queenList = ref([]) // 女王榜
const listTop = ref([
{
type: 'topKing',
Frame: webpUrl('kingFrame'),
userInfo: {},
},
{
type: 'topQueen',
Frame: webpUrl('queenFrame'),
userInfo: {},
},
]) //本周的top1国王和女王
// 展示用排行榜
const topList = computed(() => {
return visibleKingList.value ? kingList.value : queenList.value
})
const showKingLoading = ref(true) //触底加载功能
const showQueenLoading = ref(true) //触底加载功能
const topImg = ref([webpUrl('top1'), webpUrl('top2'), webpUrl('top3')]) // top图片
const visibleKingRewards = ref(true) // 展示奖励榜标签
const kingRewards = ref([]) //国王奖励列表
const queenRewards = ref([]) //女王奖励列表
const rewardsList = computed(() => {
return visibleKingRewards.value ? kingRewards.value : queenRewards.value
}) //展示奖励列表
const maskLayerShow = computed(() => {
return helpInfoShow.value || historyShow.value || rewardsShow.value
})
const helpInfoShow = ref(false)
const historyShow = ref(false)
const rewardsShow = ref(false)
// 获取底部加载div
const kingListLoadmore = ref(null)
const queenListloadmore = ref(null)
const debouceGetKingList = useThrottle(() => {
getTopList(kingListParams.value)
}, 1000)
const debouceGetQueenList = useThrottle(() => {
getTopList(queenListParams.value)
}, 1000)
const gifts = ref([])
// 倒计时
const Days = ref(0)
const Hours = ref(0)
const Minutes = ref(0)
const Second = ref(0)
let timer = null
// 获取对应的时间戳
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) {
getUserInfo()
updatePageData() // 刷新页面数据
targetTime.value += 7 * 86400000 // +7天 (更新闭包变量)
diff = targetTime.value - now
}
// 计算时间单位
const totalSeconds = Math.floor(diff / 1000)
Days.value = Math.floor(totalSeconds / (3600 * 24)) //totalSeconds / (3600 * 24)取余留天数并用Math.floor取整
Hours.value = formatTime(Math.floor((totalSeconds % (3600 * 24)) / 3600)) //(totalSeconds % (3600 * 24)取余留秒数,除一小时并取整
Minutes.value = formatTime(Math.floor((totalSeconds % 3600) / 60)) //(totalSeconds % 3600)每个小时的余留秒数,除一分钟并取整
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 {
return `${reward.quantity}Days`
}
}
// 获取俩榜单
const getTopList = async (params) => {
const resWeekTopList = await getWeekTopList(params)
if (resWeekTopList.status && resWeekTopList.body) {
if (params.kingQueenType == 'WEALTH') {
if (kingList.value.length == 0) listTop.value[0].userInfo = resWeekTopList.body.records[0] //首次加载获取king榜首
kingList.value.push(...resWeekTopList.body.records)
if (params.current * params.size >= resWeekTopList.body.total) showKingLoading.value = false
} else {
if (queenList.value.length == 0) listTop.value[1].userInfo = resWeekTopList.body.records[0] //首次加载获取king榜首
queenList.value.push(...resWeekTopList.body.records)
if (params.current * params.size >= resWeekTopList.body.total) showQueenLoading.value = false
}
}
}
// 获取我的贡献
const getMyContribution = async () => {
console.log('userInfo.value.id:', userInfo.value)
let userId = userInfo.value.id
console.log('userId:', userId)
const resWeekMyContribution = await getWeekMyContribution(userId)
console.log('resWeekMyContribution:', resWeekMyContribution)
if (resWeekMyContribution.status && resWeekMyContribution.body) {
myRanking.value = resWeekMyContribution.body
}
}
// 获取每周奖励列表和礼物
const getRewardsAndGifts = async () => {
const resRewardsAndGifts = await getThisWeekRewardsAndGifts('1966020557831610370')
if (resRewardsAndGifts.status && resRewardsAndGifts.body) {
gifts.value = resRewardsAndGifts.body.gifts
kingRewards.value = resRewardsAndGifts.body.butOneRewards
queenRewards.value = resRewardsAndGifts.body.butTwoRewards
console.log('kingRewards:', kingRewards.value)
console.log('queenRewards:', queenRewards.value)
}
}
const getAllTopOne = async () => {
const resHistoryTopOne = await getHistoryTopOne()
if (resHistoryTopOne.status && resHistoryTopOne.body) {
historyList.value = resHistoryTopOne.body
}
}
//获取用户信息
const getUserInfo = async () => {
if (Object.keys(userInfo.value).length === 0) {
const resUserInfo = await getMemberProfile()
if (resUserInfo.status && resUserInfo.body) {
userInfo.value = resUserInfo.body
}
}
getMyContribution() // 获取我的贡献
}
// 关闭弹窗
const closedPopup = () => {
helpInfoShow.value = false
historyShow.value = false
rewardsShow.value = false
}
// IntersectionObserver配置
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
console.log('监控到底部')
if (entry.target == kingListLoadmore.value && kingList.value.length != 0) {
console.log('kingListLoadmore')
kingListCurrent.value++
debouceGetKingList()
}
if (entry.target == queenListloadmore.value && queenList.value.length != 0) {
console.log('queenListloadmore')
queenListCurrent.value++
debouceGetQueenList()
}
}
})
})
// 刷新页面数据
const updatePageData = async () => {
// 重置数据
kingList.value = []
queenList.value = []
kingListCurrent.value = 1
queenListCurrent.value = 1
showKingLoading.value = true
showQueenLoading.value = true
await Promise.all([
getTopList(kingListParams.value), // 获取国王榜单
getTopList(queenListParams.value), // 获取女王榜单
getRewardsAndGifts(), //获取本周的礼物和国王和皇后top奖励列表
getAllTopOne(), //获取近几个月的榜首国王女王
])
}
// 预加载关键图片
const preloadCriticalImages = async () => {
const criticalImages = [
webpUrl('bg'),
webpUrl('border-item'),
webpUrl('border-item-user'),
webpUrl('help'),
webpUrl('history'),
webpUrl('listTitle'),
webpUrl('dayBg'),
webpUrl('timeBg'),
webpUrl('rewards'),
webpUrl('eventGifts'),
webpUrl('gift'),
webpUrl('kingBtActive'),
webpUrl('queenBt'),
webpUrl('kingBt'),
webpUrl('queenBtActive'),
webpUrl(getImgName('helpInfo')),
webpUrl('timeBack'),
webpUrl('timeNext'),
webpUrl('cancel'),
webpUrl('myRankingBg'),
webpUrl('kingFrame'),
webpUrl('queenFrame'),
webpUrl('top1'),
webpUrl('top2'),
webpUrl('top3'),
]
await preloadImages(criticalImages)
}
// 完成预加载
const completePreloading = async () => {
try {
// 执行所有初始化操作
await Promise.all([getUserInfo(), updatePageData(), preloadCriticalImages()])
} catch (error) {
console.error('预加载过程中发生错误:', error)
} finally {
// 无论成功或失败都结束加载状态
isLoading.value = false
}
}
// 组件挂载时检测环境
onMounted(() => {
connectToAppHandler()
getCountdown()
timer = setInterval(getCountdown, 1000) //每秒更新
if (kingListLoadmore.value) {
observer.observe(kingListLoadmore.value)
} //监控国王加载标志
if (queenListloadmore.value) {
observer.observe(queenListloadmore.value)
} //监控女王加载标志
})
onUnmounted(() => {
clearInterval(timer)
})
</script>
<style scoped>
* {
color: black;
}
.fullPage {
background-color: rgba(77, 30, 22, 1);
min-height: 100vh;
position: relative;
direction: ltr;
}
.bg {
width: 100vw;
position: relative;
}
.ranking-back-btn {
position: fixed;
z-index: 9999;
top: calc(env(safe-area-inset-top, 0px) + 30px);
left: 4vw;
width: 12vw;
height: 12vw;
padding: 1.8vw;
border: none;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.2s ease;
}
.ranking-back-btn:active {
transform: scale(0.9);
}
.ranking-back-btn img {
width: 100%;
aspect-ratio: 1 / 1;
display: block;
}
.ranking-popup-mask {
z-index: 10000 !important;
}
[dir='rtl'] .ranking-back-btn {
left: auto;
right: 4vw;
}
[dir='rtl'] .flipImg {
transform: scaleX(-1);
}
.time {
font-size: 1.3em;
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-weight: 860;
}
/* 添加加载动画样式 */
.loading-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #666;
overflow: hidden;
position: relative;
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 12px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
}
@media screen and (min-width: 1024px) {
* {
font-size: 32px;
}
}
</style>