3268 lines
106 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">
<!-- 页面背景 -->
<BackgroundLayer :backgroundImages="[imageUrl('bg1'), imageUrl('bg2')]" />
<div class="loading-spinner"></div>
<p>{{ $t('loading') }}...</p>
</div>
<!-- 主要内容 -->
<div
v-if="!isLoading"
style="width: 100vw; min-height: 100vh; overflow: hidden; position: relative"
>
<!-- 页面背景 -->
<BackgroundLayer :backgroundImages="[imageUrl('bg1'), imageUrl('bg2')]" />
<!-- 重复的背景图层 -->
<div class="background-overlay" :style="{ '--bg2-url': `url(${imageUrl('bg3')})` }"></div>
<!-- 页面内容 -->
<div style="position: relative; z-index: 2; margin-top: 115vw">
<!-- 弹幕 -->
<Barrage
style="display: block; width: 100vw; height: 30vw"
:barrageList="barrageList"
></Barrage>
<!-- 切换按钮 -->
<div>
<div style="display: flex; justify-content: space-around; margin-top: 2vw">
<!-- 排行榜按钮 -->
<div style="width: 30%; position: relative" @click="handleBt('ranking')">
<img
v-show="!rankingShow"
v-smart-img
:src="imageUrl(getImgName('rankBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="rankingShow"
v-smart-img
:src="imageUrl(getImgName('rankBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
<!-- 抽奖按钮 -->
<div style="width: 30%; position: relative" @click="handleBt('lottery')">
<img
v-show="!lotteryShow"
v-smart-img
:src="imageUrl(getImgName('lotteryBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="lotteryShow"
v-smart-img
:src="imageUrl(getImgName('lotteryBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
<!-- 收益按钮 -->
<div style="width: 30%; position: relative" @click="handleBt('withdrawal')">
<img
v-show="!incomeShow"
v-smart-img
:src="imageUrl(getImgName('withdrawalBt'))"
alt=""
style="display: block; width: 100%"
/>
<img
v-show="incomeShow"
v-smart-img
:src="imageUrl(getImgName('withdrawalBtActive'))"
alt=""
style="display: block; width: 100%"
/>
</div>
</div>
</div>
<!-- 展示内容 -->
<div>
<!-- 排行榜模块 -->
<div v-show="rankingShow">
<!-- 每周礼物 -->
<itemCenter :imgUrl="imageUrl('eventGiftsBg')">
<div
style="width: 80%; display: flex; justify-content: space-around; margin-top: 10%"
>
<div
v-for="(gift, index) in giftsList"
:key="index"
style="width: 30%; display: flex; flex-direction: column"
>
<itemCenter :imgUrl="imageUrl('giftBg')">
<img v-smart-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/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>
<!-- 总排行榜前三 -->
<itemCenter
:imgUrl="imageUrl('overallRankingBg')"
:contentStyle="`inset: 15vw 4vw 5vw;flex-direction: column;`"
>
<!-- 前三规则按钮 -->
<img
v-smart-img
:src="imageUrl('historyBt')"
alt=""
style="width: 6vw; position: absolute; z-index: 2; top: 4vw; right: 2vw"
@click="openPopup('top3Help')"
/>
<!-- 第一 -->
<div style="display: flex; justify-content: center">
<TopUser
ranking="1"
:BorderImgUrl="imageUrl('top1')"
:avatarUrl="OverallRanking[0].avatar"
:name="OverallRanking[0].nickname"
:distributionValue="OverallRanking[0].quantity"
style="width: 40%"
@click="viewUserInfo(OverallRanking[0].userId)"
/>
</div>
<!-- 第二三 -->
<div
style="
position: relative;
z-index: 3;
display: flex;
justify-content: space-between;
margin-top: -44%;
pointer-events: none;
"
>
<div
style="pointer-events: auto; width: 30%"
@click.stop="viewUserInfo(OverallRanking[1].userId)"
>
<TopUser
ranking="2"
:BorderImgUrl="imageUrl('top2')"
:avatarUrl="OverallRanking[1].avatar"
:name="OverallRanking[1].nickname"
:distributionValue="OverallRanking[1].quantity"
style="width: 100%"
/>
</div>
<div
style="pointer-events: auto; width: 30%"
@click.stop="viewUserInfo(OverallRanking[2].userId)"
>
<TopUser
ranking="3"
:BorderImgUrl="imageUrl('top3')"
:avatarUrl="OverallRanking[2].avatar"
:name="OverallRanking[2].nickname"
:distributionValue="OverallRanking[2].quantity"
style="width: 100%"
/>
</div>
</div>
</itemCenter>
<!-- 倒计时 -->
<div class="timeBox">
<div style="width: 30%">
<itemCenter
:imgUrl="imageUrl('timeDayBg')"
:contentStyle="`left:3vw;right: auto;top:1vw;bottom:auto;width: 10vw;height: 11vw;`"
>
<div class="timeText" style="">{{ Days }}</div>
</itemCenter>
</div>
<div class="timeText timeGap"></div>
<div style="width: 13%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Hours }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 13%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Minutes }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 13%">
<itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Second }}</div>
</itemCenter>
</div>
</div>
<!-- 排行榜 -->
<div
style="
padding: 30vw 5vw 10vw;
position: relative;
z-index: 0;
display: flex;
flex-direction: column;
gap: 2vw;
"
>
<!-- 背景图 -->
<div
style="
position: absolute;
z-index: 0;
inset: 0;
display: flex;
flex-direction: column;
"
>
<!-- 边框头部 -->
<img
v-smart-img
:src="imageUrl('RankingTopBorder')"
alt=""
style="display: block; width: 100%; min-width: 0"
/>
<!-- 边框中部占位 -->
<div style="flex: 1; min-width: 0"></div>
<!-- 边框尾部 -->
<img
v-smart-img
:src="imageUrl('RankingBottomBorder')"
alt=""
style="display: block; width: 100%; min-width: 0"
/>
<!-- 边框中部 -->
<div
style="
position: absolute;
z-index: -1;
inset: 11vw 0 2vw;
display: flex;
flex-direction: column;
"
>
<img
v-smart-img
:src="imageUrl('RankingBorder')"
alt=""
style="display: block; width: 100%; height: 100%; min-width: 0"
/>
</div>
</div>
<!-- 排行榜规则按钮 -->
<img
v-smart-img
:src="imageUrl('historyBt')"
alt=""
style="width: 6vw; position: absolute; z-index: 2; top: 19vw; right: 7vw"
@click="openPopup('rankingHelp')"
/>
<!-- 排行榜前10名(带奖励) -->
<div
v-for="(listItem, index) in RankingHasTop10"
:key="listItem.userId"
style="display: flex; flex-direction: column; gap: 1vw"
>
<!-- 基本信息 -->
<itemCenter
:imgUrl="imageUrl(index < 3 ? `itemTop${index + 1}Bg` : 'itemFrom4Bg')"
:contentStyle="`padding: 0 2vw`"
:lazy="true"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 4px;
"
>
<!-- 排名 -->
<div style="width: 9vw">
<div v-if="index < 3" style="width: 100%">
<img
v-smart-img
:src="imageUrl(`ranking${index + 1}`)"
alt=""
style="width: 100%; display: block; object-fit: cover"
/>
</div>
<div v-else style="width: 100%">
<itemCenter
:imgUrl="imageUrl('rankingFrom4')"
:contentStyle="``"
@click="viewUserInfo(listItem.userId)"
>
<div style="color: #ffe601; font-weight: 700">
{{ listItem?.rank }}
</div>
</itemCenter>
</div>
</div>
<!-- 头像 -->
<div style="width: 3.5em; margin: 0 1vw; position: relative; z-index: 0">
<!-- 前三名头像框 -->
<img
v-smart-img
v-if="index < 3"
:src="imageUrl(`ranking${index + 1}Frame`)"
alt=""
style="
display: block;
width: 120%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
"
/>
<!-- 头像 -->
<img
v-smart-img
:src="listItem?.avatar || ''"
alt=""
style="
display: block;
width: 100%;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
</div>
<!-- 名称id -->
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column">
<!-- 滚动名称 -->
<itemCenter
style="width: 30vw; height: 10vw; min-width: 0"
:imgUrl="imageUrl('userNameBorder')"
:contentStyle="`padding:0;`"
:lazy="true"
>
<div style="width: 100%; margin-top: 1vw">
<div
style="
height: 100%;
display: flex;
align-items: center;
/* justify-content: center; */
overflow: hidden;
"
>
<!-- 滚动容器 -->
<div
v-if="isTextOverflow(listItem?.userName || '')"
class="scroll-wrapper"
>
<!-- 2套内容 -->
<div class="scroll-content" v-for="value in 2">
<div
style="
color: #fff;
font-size: 1em;
font-weight: 860;
white-space: nowrap;
"
>
{{ listItem?.nickname }}
</div>
</div>
</div>
<div v-else style="width: 100%; text-align: center">
<div
style="
color: #fff;
font-size: 1em;
font-weight: 860;
white-space: nowrap;
"
>
{{ listItem?.nickname }}
</div>
</div>
</div>
</div>
</itemCenter>
<!-- ID -->
<div style="color: #fff; font-weight: 590" class="Textlittle">
{{ $t('user_id_prefix') }}
{{ listItem?.specialAccount || 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="Textlittle">
{{ listItem?.quantity || 0 }}
</div>
</div>
</itemCenter>
<!-- 前10名奖励 -->
<itemCenter
:imgUrl="imageUrl('itemTopRewardBg')"
:contentStyle="`padding:0 2vw 0 11vw`"
:lazy="true"
>
<div class="reward-wrapper">
<div style="height: 100%; display: flex; align-items: center; overflow: hidden">
<!-- 滚动容器 -->
<div class="scroll-wrapper">
<!-- 2套内容 -->
<div class="scroll-content" v-for="value in 2">
<div
v-for="(item, index) in showRewardsTop10[index]?.rewards"
:key="index"
style="
align-self: stretch;
display: flex;
align-items: center;
padding: 0 1vw;
"
@click="clickReward(item)"
>
<!-- 预览图 -->
<img
v-if="item.cover != ''"
:src="item.cover"
alt=""
style="min-width: 0; display: block; width: 8vw; object-fit: cover"
/>
<div style="min-width: 0; color: #fff; white-space: nowrap">
{{ formatRewardDisplay(item.type, item) }}
</div>
</div>
</div>
</div>
</div>
</div>
</itemCenter>
</div>
<!-- 排行榜10名后(无奖励) -->
<div
v-if="showRanking.length > 0"
v-for="(listItem, index) in showRanking"
:key="listItem.userId"
style="position: relative; z-index: 2"
>
<itemCenter
:imgUrl="imageUrl('itemFrom4Bg')"
:contentStyle="`padding: 0 2vw`"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 4px;
"
>
<!-- 排名 -->
<itemCenter
style="width: 9vw"
:imgUrl="imageUrl('rankingFrom4')"
:contentStyle="``"
@click="viewUserInfo(listItem.userId)"
>
<div style="color: #ffe601; font-weight: 700">
{{ listItem?.rank }}
</div>
</itemCenter>
<!-- 头像 -->
<img
v-smart-img
:src="listItem?.avatar || ''"
alt=""
style="
display: block;
width: 3.5em;
margin: 0 2%;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 名称id -->
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column">
<!-- 滚动名称 -->
<itemCenter
style="width: 30vw; height: 10vw; min-width: 0"
:imgUrl="imageUrl('userNameBorder')"
:contentStyle="`padding:0;`"
:lazy="true"
>
<div style="width: 100%; margin-top: 1vw">
<div
style="
height: 100%;
display: flex;
align-items: center;
/* justify-content: center; */
overflow: hidden;
"
>
<!-- 滚动容器 -->
<div
v-if="isTextOverflow(listItem?.userName || '')"
class="scroll-wrapper"
>
<!-- 2套内容 -->
<div class="scroll-content" v-for="value in 2">
<div
style="
color: #fff;
font-size: 1em;
font-weight: 860;
white-space: nowrap;
"
>
{{ listItem?.nickname }}
</div>
</div>
</div>
<div v-else style="width: 100%; text-align: center">
<div
style="
color: #fff;
font-size: 1em;
font-weight: 860;
white-space: nowrap;
"
>
{{ listItem?.nickname }}
</div>
</div>
</div>
</div>
</itemCenter>
<!-- ID -->
<div style="color: #fff; font-weight: 590" class="Textlittle">
{{ $t('user_id_prefix') }}
{{ listItem?.specialAccount || 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="Textlittle">
{{ listItem?.quantity || 0 }}
</div>
</div>
</itemCenter>
</div>
</div>
<!-- 触发加载功能 -->
<!-- <div ref="RankingLoadmore"></div> -->
</div>
<!-- 抽奖模块 -->
<div
v-show="lotteryShow"
style="
width: 100vw;
position: relative;
display: flex;
flex-direction: column;
gap: 4vw;
"
>
<!-- 中奖历史按钮 -->
<img
v-smart-img
:src="imageUrl('resultBt')"
alt=""
style="width: 7vw; position: absolute; z-index: 2; top: 11.3vw; right: 5vw"
@click="openPopup('history')"
/>
<!-- 奖池 -->
<itemCenter
style="margin-top: 6vw"
:imgUrl="imageUrl('lottery')"
:contentStyle="`
inset: 10vw;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 1vw;
direction: ltr;`"
>
<!-- 抽奖转盘 -->
<div
v-for="(prize, index) in activity.prizeList"
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
padding: 5vw;
"
:style="[getGridPosition(index)]"
>
<div
style="
width: 100%;
flex: 1;
min-width: 0;
min-height: 0;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
v-smart-img
:src="prize.prizeImage || ''"
:alt="prize.prizeName || ''"
width="70%"
style="display: block"
/>
</div>
<div
style="
width: 100%;
height: 20%;
min-width: 0;
min-height: 0;
display: flex;
justify-content: center;
align-items: center;
"
>
<div
style="
font-size: 0.9em;
font-weight: 700;
color: #fff;
text-shadow: 0 1px 0 #339370;
white-space: nowrap;
"
>
{{ prize.prizeName }}
</div>
</div>
<!-- 转到的奖品项 -->
<img
v-show="activeIndex === index"
v-smart-img
:src="imageUrl('prizeActiveFrame')"
alt=""
style="
display: block;
width: 100%;
position: absolute;
inset: 0;
"
/>
</div>
<!-- 奖池中心 -->
<div
style="
grid-area: 2 / 2;
display: flex;
justify-content: center;
align-items: center;
"
>
<div
style="
width: 80%;
text-align: center;
min-width: 0;
font-size: 1em;
font-weight: 700;
color: #fff;
text-shadow: 0 1px 0 #339370;
"
>
{{ t('ramadan_kareem') }}
</div>
</div>
</itemCenter>
<!-- 我的抽奖券数量 -->
<div style="padding: 0 4vw">
<div style="font-size: 1.3em; font-weight: 600">
{{ $t('remaining_lottery_tickets') }}: {{ rollTimes }}
</div>
</div>
<!-- 抽奖按钮 -->
<div style="display: flex; justify-content: center; gap: 4vw" class="drawBts">
<!-- 单抽 -->
<img
v-smart-img
:src="imageUrl(getImgName('draw1BtBg'))"
alt=""
style="width: 45vw; display: block; object-fit: cover"
@click="sweepstakes(1)"
/>
<!-- 10连抽 -->
<img
v-smart-img
:src="imageUrl(getImgName('draw10BtBg'))"
alt=""
style="width: 45vw; display: block; object-fit: cover"
@click="sweepstakes(10)"
/>
</div>
<!-- 总抽奖次数 -->
<div
style="
position: relative;
z-index: 2;
margin: 0 4vw 0;
display: flex;
flex-direction: column;
gap: 2vw;
padding: 12px;
border-radius: 12px;
background:
linear-gradient(
99deg,
rgba(211, 212, 213, 0.15) 12.86%,
rgba(139, 145, 147, 0.15) 15.34%,
rgba(87, 95, 99, 0.15) 17.82%,
rgba(55, 65, 69, 0.15) 18.64%,
rgba(43, 54, 58, 0.15) 19.47%,
rgba(52, 62, 66, 0.15) 22.77%,
rgba(77, 85, 89, 0.15) 26.9%,
rgba(117, 123, 126, 0.15) 32.68%,
rgba(173, 176, 177, 0.15) 38.46%,
rgba(205, 205, 206, 0.15) 41.76%,
rgba(198, 199, 200, 0.15) 43.41%,
rgba(180, 182, 184, 0.15) 45.06%,
rgba(151, 156, 158, 0.15) 46.71%,
rgba(111, 118, 122, 0.15) 49.19%,
rgba(72, 83, 87, 0.15) 50.84%,
rgba(76, 86, 90, 0.15) 52.49%,
rgba(89, 98, 102, 0.15) 54.97%,
rgba(112, 117, 120, 0.15) 57.45%,
rgba(143, 144, 146, 0.15) 59.1%,
rgba(152, 152, 154, 0.15) 59.92%,
rgba(165, 165, 166, 0.15) 63.23%,
rgba(199, 199, 200, 0.15) 70.66%,
rgba(255, 255, 255, 0.15) 78.91%,
rgba(209, 209, 210, 0.15) 81.39%,
rgba(79, 79, 83, 0.15) 87.17%,
rgba(27, 27, 32, 0.15) 90.47%,
rgba(49, 49, 54, 0.15) 91.3%,
rgba(77, 77, 81, 0.15) 92.12%,
rgba(116, 116, 118, 0.15) 92.95%,
rgba(165, 165, 167, 0.15) 94.6%,
rgba(233, 233, 233, 0.15) 95.43%
),
linear-gradient(0deg, #0f674c 0%, #0f674c 100%), #e8e8e8;
background-blend-mode: hard-light, normal, normal;
"
>
<div style="display: flex; justify-content: space-between; align-items: center">
<div style="font-size: 1.4em; font-weight: 700">
{{
t('Total Tickets:({ usedCount }/100)', { usedCount: totalDraw?.usedCount || 0 })
}}
</div>
<!-- 按钮 -->
<div style="width: 20%">
<!-- 未满足条件 -->
<itemCenter
v-if="RechargeBadgeInfo.claimStatus == -1"
:imgUrl="imageUrl('taskBtGo')"
>
<div style="font-size: 1em; font-weight: 600; white-space: nowrap">
{{ t('task_go') }}
</div>
</itemCenter>
<!-- 未领取 -->
<itemCenter
v-if="RechargeBadgeInfo.claimStatus == 0"
:imgUrl="imageUrl('taskBtReceive')"
@click="receiveRechargeBadge(RechargeBadgeInfo)"
>
<div style="font-size: 1em; font-weight: 600; white-space: nowrap">
{{ t('task_receive') }}
</div>
</itemCenter>
<!-- 已领取 -->
<itemCenter
v-if="RechargeBadgeInfo.claimStatus == 1"
:imgUrl="imageUrl('taskBtReceived')"
@click="receiveRechargeBadge(RechargeBadgeInfo)"
>
<div style="font-size: 0.9em; font-weight: 600; white-space: nowrap">
{{ t('task_received') }}
</div>
</itemCenter>
</div>
</div>
<!-- 100抽奖励 -->
<div style="display: flex; align-items: center; gap: 4vw">
<!-- 奖励图 -->
<img
v-for="Badge in RechargeBadgeInfo.rewardProps"
v-smart-img
:src="Badge.cover || ''"
alt=""
style="display: block; width: 18vw"
/>
<!-- 奖励说明 -->
<div style="font-size: 1.1em; font-weight: 700">
{{ t('Lucky Dollars Medal*permanent') }}
</div>
</div>
</div>
<!-- 任务列表 -->
<div
style="
position: relative;
z-index: 2;
margin: 0 4vw;
border-radius: 12px;
background:
linear-gradient(
99deg,
rgba(211, 212, 213, 0.15) 12.86%,
rgba(139, 145, 147, 0.15) 15.34%,
rgba(87, 95, 99, 0.15) 17.82%,
rgba(55, 65, 69, 0.15) 18.64%,
rgba(43, 54, 58, 0.15) 19.47%,
rgba(52, 62, 66, 0.15) 22.77%,
rgba(77, 85, 89, 0.15) 26.9%,
rgba(117, 123, 126, 0.15) 32.68%,
rgba(173, 176, 177, 0.15) 38.46%,
rgba(205, 205, 206, 0.15) 41.76%,
rgba(198, 199, 200, 0.15) 43.41%,
rgba(180, 182, 184, 0.15) 45.06%,
rgba(151, 156, 158, 0.15) 46.71%,
rgba(111, 118, 122, 0.15) 49.19%,
rgba(72, 83, 87, 0.15) 50.84%,
rgba(76, 86, 90, 0.15) 52.49%,
rgba(89, 98, 102, 0.15) 54.97%,
rgba(112, 117, 120, 0.15) 57.45%,
rgba(143, 144, 146, 0.15) 59.1%,
rgba(152, 152, 154, 0.15) 59.92%,
rgba(165, 165, 166, 0.15) 63.23%,
rgba(199, 199, 200, 0.15) 70.66%,
rgba(255, 255, 255, 0.15) 78.91%,
rgba(209, 209, 210, 0.15) 81.39%,
rgba(79, 79, 83, 0.15) 87.17%,
rgba(27, 27, 32, 0.15) 90.47%,
rgba(49, 49, 54, 0.15) 91.3%,
rgba(77, 77, 81, 0.15) 92.12%,
rgba(116, 116, 118, 0.15) 92.95%,
rgba(165, 165, 167, 0.15) 94.6%,
rgba(233, 233, 233, 0.15) 95.43%
),
linear-gradient(0deg, #0f674c 0%, #0f674c 100%), #e8e8e8;
background-blend-mode: hard-light, normal, normal;
padding: 12px;
display: flex;
flex-direction: column;
gap: 12px;
"
>
<div style="font-weight: 590">{{ t('Task for tickets') }}</div>
<div
v-for="task in taskList"
style="
border-radius: 8px;
border: 1px solid rgba(64, 64, 64, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(7.5px);
display: flex;
padding: 8px;
justify-content: space-between;
align-items: center;
"
>
<!-- 图标 -->
<div style="width: 20%">
<img
v-if="task.taskType == 1"
v-smart-img
:src="imageUrl('taskTalk')"
alt=""
width="100%"
style="display: block"
/>
<img
v-if="task.taskType == 2"
v-smart-img
:src="imageUrl('taskGift')"
alt=""
width="100%"
style="display: block"
/>
<img
v-if="task.taskType == 4"
v-smart-img
:src="imageUrl('taskGame')"
alt=""
width="100%"
style="display: block"
/>
<img
v-if="task.taskType == 5"
v-smart-img
:src="imageUrl('taskRecharge')"
alt=""
width="100%"
style="display: block"
/>
</div>
<!-- 内容 -->
<div style="width: 60%">
<!-- 任务进度 -->
<div style="color: #fff; font-weight: 590; font-size: 0.9em">
{{ showTarget(task) }}
</div>
<!-- 任务奖励 -->
<div style="display: flex; align-items: center; gap: 8px">
<div style="color: #fff; font-weight: 590">{{ t('Rewards:') }}</div>
<img
v-smart-img
:src="imageUrl('ticket')"
:alt="t('ticket')"
width="15%"
style="display: block"
/>
<div style="color: #fff; font-weight: 590">*{{ task.rewardValue }}</div>
</div>
</div>
<!-- 按钮 -->
<div style="width: 20%">
<!-- 前往任务 -->
<itemCenter v-if="task.taskStatus == 0" :imgUrl="imageUrl('taskBtGo')">
<div style="font-size: 1em; font-weight: 600; white-space: nowrap">
{{ t('task_go') }}
</div>
</itemCenter>
<!-- 领取抽奖券 -->
<itemCenter
v-else-if="task.taskStatus === 1"
:imgUrl="imageUrl('taskBtReceive')"
@click="receiveTaskReward(task.taskCode)"
>
<div style="font-size: 1em; font-weight: 600; white-space: nowrap">
{{ t('task_receive') }}
</div>
</itemCenter>
<!-- 已完成 -->
<itemCenter
v-else
:imgUrl="imageUrl('taskBtReceived')"
@click="receiveRechargeBadge(RechargeBadgeInfo)"
>
<div style="font-size: 0.9em; font-weight: 600; white-space: nowrap">
{{ t('task_received') }}
</div>
</itemCenter>
</div>
</div>
</div>
</div>
<!-- 收益模块 -->
<div
v-show="incomeShow"
style="width: 100%; padding: 4vw; display: flex; flex-direction: column; gap: 3vw"
>
<!-- 个人信息 -->
<div
style="
border-radius: 12px;
background:
linear-gradient(
99deg,
rgba(211, 212, 213, 0.15) 12.86%,
rgba(139, 145, 147, 0.15) 15.34%,
rgba(87, 95, 99, 0.15) 17.82%,
rgba(55, 65, 69, 0.15) 18.64%,
rgba(43, 54, 58, 0.15) 19.47%,
rgba(52, 62, 66, 0.15) 22.77%,
rgba(77, 85, 89, 0.15) 26.9%,
rgba(117, 123, 126, 0.15) 32.68%,
rgba(173, 176, 177, 0.15) 38.46%,
rgba(205, 205, 206, 0.15) 41.76%,
rgba(198, 199, 200, 0.15) 43.41%,
rgba(180, 182, 184, 0.15) 45.06%,
rgba(151, 156, 158, 0.15) 46.71%,
rgba(111, 118, 122, 0.15) 49.19%,
rgba(72, 83, 87, 0.15) 50.84%,
rgba(76, 86, 90, 0.15) 52.49%,
rgba(89, 98, 102, 0.15) 54.97%,
rgba(112, 117, 120, 0.15) 57.45%,
rgba(143, 144, 146, 0.15) 59.1%,
rgba(152, 152, 154, 0.15) 59.92%,
rgba(165, 165, 166, 0.15) 63.23%,
rgba(199, 199, 200, 0.15) 70.66%,
rgba(255, 255, 255, 0.15) 78.91%,
rgba(209, 209, 210, 0.15) 81.39%,
rgba(79, 79, 83, 0.15) 87.17%,
rgba(27, 27, 32, 0.15) 90.47%,
rgba(49, 49, 54, 0.15) 91.3%,
rgba(77, 77, 81, 0.15) 92.12%,
rgba(116, 116, 118, 0.15) 92.95%,
rgba(165, 165, 167, 0.15) 94.6%,
rgba(233, 233, 233, 0.15) 95.43%
),
linear-gradient(0deg, #0f674c 0%, #0f674c 100%), #e8e8e8;
background-blend-mode: hard-light, normal, normal;
padding: 16px 12px;
display: flex;
align-items: center;
gap: 8px;
position: relative;
"
>
<!-- 头像 -->
<img
v-smart-img
:src="userInfo.userAvatar || ''"
alt=""
style="
width: 12vw;
min-width: 0;
border-radius: 50%;
aspect-ratio: 1/1;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
gap: 4px;
"
>
<!-- 帮助按钮 -->
<img
v-smart-img
src="/src/assets/icon/helpWhite.png"
alt=""
class="ruleBt"
@click="openPopup('withdrawalHelp')"
/>
<!-- 名称 -->
<div
style="
max-width: 70%;
min-width: 0;
font-weight: 500;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ userInfo.userNickname || '' }}
</div>
<div style="display: flex; justify-content: space-between; align-items: center">
<div style="min-width: 0">
{{ $t('user_id_prefix') }} {{ userInfo.account || '' }}
</div>
<div style="width: auto; font-weight: 600">
{{ t('current_earnings', { amount: currentAmount.availableAmount }) }}
</div>
</div>
</div>
</div>
<!-- 操作抽屉 -->
<div
style="
border-radius: 12px;
background:
linear-gradient(
99deg,
rgba(211, 212, 213, 0.15) 12.86%,
rgba(139, 145, 147, 0.15) 15.34%,
rgba(87, 95, 99, 0.15) 17.82%,
rgba(55, 65, 69, 0.15) 18.64%,
rgba(43, 54, 58, 0.15) 19.47%,
rgba(52, 62, 66, 0.15) 22.77%,
rgba(77, 85, 89, 0.15) 26.9%,
rgba(117, 123, 126, 0.15) 32.68%,
rgba(173, 176, 177, 0.15) 38.46%,
rgba(205, 205, 206, 0.15) 41.76%,
rgba(198, 199, 200, 0.15) 43.41%,
rgba(180, 182, 184, 0.15) 45.06%,
rgba(151, 156, 158, 0.15) 46.71%,
rgba(111, 118, 122, 0.15) 49.19%,
rgba(72, 83, 87, 0.15) 50.84%,
rgba(76, 86, 90, 0.15) 52.49%,
rgba(89, 98, 102, 0.15) 54.97%,
rgba(112, 117, 120, 0.15) 57.45%,
rgba(143, 144, 146, 0.15) 59.1%,
rgba(152, 152, 154, 0.15) 59.92%,
rgba(165, 165, 166, 0.15) 63.23%,
rgba(199, 199, 200, 0.15) 70.66%,
rgba(255, 255, 255, 0.15) 78.91%,
rgba(209, 209, 210, 0.15) 81.39%,
rgba(79, 79, 83, 0.15) 87.17%,
rgba(27, 27, 32, 0.15) 90.47%,
rgba(49, 49, 54, 0.15) 91.3%,
rgba(77, 77, 81, 0.15) 92.12%,
rgba(116, 116, 118, 0.15) 92.95%,
rgba(165, 165, 167, 0.15) 94.6%,
rgba(233, 233, 233, 0.15) 95.43%
),
linear-gradient(0deg, #0f674c 0%, #0f674c 100%), #e8e8e8;
background-blend-mode: hard-light, normal, normal;
padding: 12px;
font-weight: 600;
display: flex;
flex-direction: column;
gap: 8px;
"
>
<!-- 转账功能 -->
<div
style="display: flex; justify-content: space-between; align-items: center"
@click="drawerShowBt('transfer')"
v-if="userIdentity.anchor"
>
<div>{{ t('transfer_to_recharge_agent') }}</div>
<img
v-smart-img
class="flipImg"
src="/src/assets/icon/arrowWhite.png"
alt=""
style="width: 1em; display: block; transition: all 0.2s ease"
:class="{ rotated: transferShow }"
/>
</div>
<!-- 转账抽屉 -->
<transition name="drawer">
<div
v-if="transferShow"
style="
background-color: transparent;
display: flex;
flex-direction: column;
gap: 12px;
"
>
<!-- 转账对象 -->
<div
v-if="selectedPayee.id"
style="
border-radius: 8px;
border: 1px solid rgba(64, 64, 64, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(7.5px);
padding: 12px;
"
>
<!-- 基本信息 -->
<div style="display: flex; align-items: center">
<!-- 头像 -->
<div style="position: relative; width: 50px; margin-right: 12px">
<img
v-smart-img
:src="selectedPayee.avatar || ''"
:alt="selectedPayee.name || ''"
style="width: 100%; object-fit: cover; border-radius: 50%"
@error="handleAvatarImageError"
/>
</div>
<!-- 个人信息 -->
<div style="flex: 1">
<div style="margin: 0 0 4px 0; font-weight: 700">
{{ selectedPayee.name || '' }}
</div>
<div style="margin: 0; font-size: 0.9em; font-weight: 500">
{{ $t('user_id_prefix') }} {{ selectedPayee.account || '' }}
</div>
</div>
<!-- 换人按钮 -->
<button
style="
border-radius: 12px;
background: linear-gradient(
152deg,
rgba(198, 112, 255, 0.6) 7.01%,
rgba(119, 38, 255, 0.6) 92.99%
);
border: none;
font-weight: 500;
padding: 2px 8px;
"
@click="searchPayee"
>
{{ t('change') }}
</button>
</div>
<!-- 身份图标 -->
<div style="margin-left: 50px; display: flex; gap: 5px">
<img
v-if="selectedPayee.isHost"
v-smart-img
src="/src/assets/icon/identity/host.png"
alt=""
width="30%"
/>
<img
v-if="selectedPayee.isAgency"
v-smart-img
src="/src/assets/icon/identity/agency.png"
alt=""
width="30%"
style="display: block"
/>
<img
v-if="selectedPayee.hasSalary"
v-smart-img
src="/src/assets/icon/identity/coinSeller.png"
alt=""
width="30%"
/>
</div>
</div>
<!-- 空状态 - 默认显示 -->
<div
v-else
style="
display: flex;
justify-content: center;
align-items: center;
border-radius: 8px;
border: 1px solid rgba(64, 64, 64, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(7.5px);
padding: 12px 0;
"
>
<div
style="
font-weight: 590;
padding: 16px 24px;
border-radius: 20px;
border: 1px solid rgba(156, 156, 156, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
0 -5px 4px 0 rgba(255, 255, 255, 0.25) inset,
0 4px 4px 0 rgba(255, 255, 255, 0.25) inset,
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(10px);
"
@click="searchPayee"
>
{{ t('select') }}
</div>
</div>
<!-- 转账金额选择 -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
<div
v-for="coin in coinOptions"
:key="coin.id"
@click="selectCoin(coin)"
:class="['coin-item', { selected: selectedCoin?.id === coin.id }]"
>
<img
v-smart-img
src="/src/assets/icon/dollar.png"
alt=""
style="width: 40%"
/>
<div style="font-weight: 500; color: #fff">${{ coin.price }}</div>
</div>
</div>
<!-- 转账按钮 -->
<div style="display: flex; justify-content: center; align-items: center">
<div
style="
width: 70%;
padding: 12px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 20px;
border: 1px solid rgba(156, 156, 156, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
0 -5px 4px 0 rgba(255, 255, 255, 0.25) inset,
0 4px 4px 0 rgba(255, 255, 255, 0.25) inset,
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(10px);
font-weight: 590;
"
@click="transfer"
:disabled="!selectedCoin || !selectedPayee.value?.id"
>
{{ t('transfer') }}
</div>
</div>
</div>
</transition>
<!-- 兑换金币 -->
<div
style="display: flex; justify-content: space-between; align-items: center"
@click="drawerShowBt('exchange')"
>
<div>{{ t('exchange_gold_coins') }}</div>
<img
v-smart-img
class="flipImg"
src="/src/assets/icon/arrowWhite.png"
alt=""
style="width: 1em; display: block; transition: all 0.2s ease"
:class="{ rotated: exchangeShow }"
/>
</div>
<!-- 兑换金币抽屉 -->
<transition name="drawer">
<div
v-if="exchangeShow"
style="
background-color: transparent;
display: flex;
flex-direction: column;
gap: 12px;
"
>
<!-- 转账金额选择 -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
<div
v-for="coin in coinOptions"
:key="coin.id"
@click="selectCoin(coin)"
:class="['coin-item', { selected: selectedCoin?.id == coin.id }]"
>
<img v-smart-img src="/src/assets/icon/coin.png" alt="" style="width: 40%" />
<div style="font-size: 0.7em">{{ coin.amount }} coins x1</div>
<div style="font-weight: 500; color: #fff">${{ coin.price }}</div>
</div>
</div>
<!-- 转账按钮 -->
<div style="display: flex; justify-content: center; align-items: center">
<div
style="
width: 70%;
padding: 12px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 20px;
border: 1px solid rgba(156, 156, 156, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
0 -5px 4px 0 rgba(255, 255, 255, 0.25) inset,
0 4px 4px 0 rgba(255, 255, 255, 0.25) inset,
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(10px);
font-weight: 590;
"
:disabled="!selectedCoin || !selectedPayee.value?.id"
@click="exchangeCoinBt"
>
{{ t('exchange') }}
</div>
</div>
</div>
</transition>
<!-- 提取现金 -->
<div
style="display: flex; justify-content: space-between; align-items: center"
@click="goToWithdraw"
v-if="currentAmount.availableAmount >= 10"
>
<div>{{ t('go_to_withdraw') }}</div>
<img
v-smart-img
class="flipImg"
src="/src/assets/icon/arrowWhite.png"
alt=""
style="width: 1em; display: block"
/>
</div>
</div>
</div>
</div>
<!-- 我的排名占位 -->
<div v-show="rankingShow" style="height: 25vw"></div>
<!-- 我的排名 -->
<itemCenter
v-show="rankingShow"
style="position: fixed; bottom: -1px; z-index: 3"
:imgUrl="imageUrl('myRankingBg')"
:contentStyle="`padding: 1vw 3vw 0`"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<itemCenter
style="width: 10vw"
:imgUrl="imageUrl('rankingFrom4')"
:contentStyle="``"
@click="viewUserInfo(listItem.userId)"
>
<div style="color: #ffe601; font-weight: 700">
{{ myRanking.rank || 999 }}
</div>
</itemCenter>
<!-- 头像 -->
<img
v-smart-img
:src="myRanking.avatar || ''"
alt=""
style="
display: block;
width: 4em;
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-size: 1em;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ 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="closedPopup">
<!-- 居中弹窗 -->
<div
style="
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
"
@click="closedPopup"
>
<!-- 前三名奖励展示 -->
<div v-show="topRewardShow" style="width: 90%; position: relative" @click.stop>
<itemCenter
:imgUrl="imageUrl('rewardBg')"
:contentStyle="`padding: 22vw 6vw 11vw;flex-direction: column;gap: 2vw;`"
>
<!-- 奖品展示 -->
<img
v-smart-img
:src="topReward.cover"
alt=""
style="width: 60%; display: block; object-fit: cover"
/>
<!-- 时长或数量 -->
<div
style="
font-size: 1.2em;
font-weight: 700;
background: linear-gradient(
180deg,
#ffdf6b 31.61%,
#ffe562 36.73%,
#fff 52.37%,
#ffe562 58.67%,
#ffa615 72.2%
);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
"
>
{{ formatRewardDisplay(topReward.type, topReward) }}
</div>
</itemCenter>
</div>
<!-- 抽奖结果 -->
<div v-show="resultShow" style="position: relative; width: 90%" @click.stop>
<itemCenter
:imgUrl="imageUrl('resultBg')"
:contentStyle="`inset: 20vw 7vw 8vw;
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
class="flipImg"
v-show="result.length > 1 && resultShowIndex > 0"
:src="imageUrl('resultBack')"
alt=""
style="display: block; width: 80%; object-fit: cover"
@click="resultShowIndex--"
/>
</div>
<!-- 奖品 -->
<img
v-smart-img
:src="result[resultShowIndex]?.prize?.prizeImage"
alt=""
width="50%"
style="display: block"
/>
<!-- 下一个奖品 -->
<div
style="
width: 8vw;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
v-smart-img
class="flipImg"
v-show="result.length > 1 && resultShowIndex + 1 < result.length"
:src="imageUrl('resultNext')"
alt=""
style="display: block; width: 80%; object-fit: cover"
@click="resultShowIndex++"
/>
</div>
</div>
<!-- 奖品说明 -->
<div
style="
width: 100%;
height: 5vw;
text-align: center;
font-size: 0.9em;
font-weight: 590;
position: relative;
color: #ff79a1;
"
>
{{ t('you_get') }} {{ result[resultShowIndex]?.prize?.prizeName }}
<div v-if="result.length > 1" class="resultNum">
{{ resultShowIndex + 1 }} / {{ result.length }}
</div>
</div>
<!-- 关闭弹窗按钮 -->
<div style="width: 30vw; height: 10vw" @click="closedPopup"></div>
</itemCenter>
</div>
<!-- 中奖历史 -->
<div v-show="historyShow" style="position: relative; width: 95%" @click.stop>
<itemCenter
:imgUrl="imageUrl(getImgName('historyBg'))"
:contentStyle="`padding: 22vw 6vw 11vw;`"
>
<div
style="
width: 100%;
height: 100%;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
"
class="scrollY"
>
<div
v-for="(record, index) in myRecords"
style="
border-radius: 8px;
border: 1px solid rgba(64, 64, 64, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(7.5px);
display: flex;
padding: 12px;
justify-content: space-between;
align-items: center;
"
>
<div style="display: flex; align-items: center; gap: 4px">
<img
v-smart-img
:src="record?.prize?.prizeImage || ''"
alt=""
style="width: 10vw; min-width: 0; object-fit: cover; display: block"
/>
<div
style="font-weight: 590; font-size: 0.9em; direction: ltr; text-align: left"
>
{{ record?.prize?.prizeName }}
</div>
</div>
<div
style="font-weight: 510; font-size: 0.8em; direction: ltr; text-align: left"
>
{{ formatUTCCustom(record.drawTime) }}
</div>
</div>
</div>
</itemCenter>
</div>
<!-- 排行榜帮助弹窗 -->
<div v-show="rankingHelpShow" @click.stop>
<itemCenter
:imgUrl="imageUrl('rankingHelpBg_ar')"
:contentStyle="`inset: 26vw 6vw 13vw;overflow-y: auto;display:block;`"
>
<img
v-smart-img
:src="imageUrl(getImgName('rankingHelpInfo'))"
alt=""
style="display: block; width: 100%; object-fit: cover; margin-bottom: 6vw"
/>
</itemCenter>
</div>
<!-- 总榜前三规则弹窗 -->
<div v-show="top3HelpShow" @click.stop>
<itemCenter
:imgUrl="imageUrl('top3HelpBg_ar')"
:contentStyle="`inset: 26vw 6vw 13vw;overflow-y: auto;display:block;`"
>
<img
v-smart-img
:src="imageUrl(getImgName('top3HelpInfo'))"
alt=""
style="display: block; width: 100%; object-fit: cover; margin-bottom: 6vw"
/>
</itemCenter>
</div>
<!-- 兑换规则弹窗 -->
<div v-show="withdrawalHelpShow" @click.stop>
<img
v-smart-img
:src="imageUrl(getImgName('withdrawalHelp'))"
alt=""
style="display: block; width: 100%; object-fit: cover; margin-bottom: 6vw"
/>
</div>
</div>
</maskLayer>
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { connectToApp } from '@/utils/appConnector.js'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { setDocumentDirection } from '@/locales/i18n'
import { viewUserInfo } from '@/utils/appBridge.js'
import { useLangStore } from '@/stores/lang'
import { getPngUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/imagePreloader.js'
import { setUserInfo } from '@/utils/userStore.js'
import { formatUTCCustom } from '@/utils/utcFormat.js'
import { showError, showSuccess } from '@/utils/toast.js'
import { handleAvatarImageError, handleRewardImageError } from '@/utils/imageHandler.js'
import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js'
import { useThrottle } from '@/utils/useDebounce'
import { formatRewardDisplay } from '@/utils/rewardFormatter.js'
import { getMemberProfile, getUserIdentity } from '@/api/wallet'
import {
getThisWeekRewardsAndGifts,
getRankingListAndMyRanking,
getOverallRankingTop3, // 获取总榜前三
} from '@/api/activity.js'
import {
ranklist, //获取排行榜
activityDetail, // 获取活动详情
myRecharge, // 获取充值记录
activityRewardConfigs, // 获取活动奖励配置列表
myTickets, // 获取剩余中奖券
myTotalDrawCount, // 获取我的累计抽奖次数
onceDraw, // 执行单次抽奖
multiDraw, // 执行连抽
drawRecords, // 获取中奖记录
ActTaskList, // 获取任务列表
rewardConfigsBadge, // 获取累计抽奖-徽章信息
receiveTickets, // 领取任务奖励
receiveRechargeReward, // 领取充值奖励
receiveRewardBadge, // 领取累计抽奖奖励-徽章
winnerHistory, //获取历史中奖用户
withdrawableAmount, //获取可提现金额
transferActivityDollar, // 转账活动美金
exchangeCoin, //兑换代币
} from '@/api/lottery'
import BackgroundLayer from '@/components/BackgroundLayer.vue'
import TopUser from './components/topUser.vue'
import Barrage from './components/Barrage.vue'
import itemCenter from '@/components/itemCenter.vue'
import maskLayer from '@/components/MaskLayer.vue'
const isLoading = ref(true) // 预加载状态
const timeoutId = ref(null) // 超时定时器 ID
const { t, locale } = useI18n()
const router = useRouter()
const route = useRoute()
const langStore = useLangStore()
// 当前语言类型
const currentLangType = computed(() => {
return langStore.selectedLang?.type || 'en'
})
// 获取OSS图片URL的函数
const imageUrl = (filename) => getPngUrl('Activities/LuckyDollars/Season3/', 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 rankingHelpShow = ref(false) // 排行榜帮助
const top3HelpShow = ref(false) // 总榜前三帮助
const withdrawalHelpShow = ref(false) // 帮助
const resultShow = ref(false) // 抽奖结果
const historyShow = ref(false) // 历史
const topRewardShow = ref(false) // 前三名奖励展示
const maskLayerShow = computed(() => {
return (
rankingHelpShow.value ||
top3HelpShow.value ||
withdrawalHelpShow.value ||
resultShow.value ||
historyShow.value ||
topRewardShow.value
)
})
// 模块切换展示
const rankingShow = ref(true) //排行榜标签页
const lotteryShow = ref(false) //抽奖标签页
const incomeShow = ref(false) //收益标签页
// 抽屉展示
const transferShow = ref(false) //转账
const exchangeShow = ref(false) //兑换
const withdrawShow = ref(false) //提现
const selectedCoin = ref(null) // 选择的币种
const barrageList = ref([]) // 弹幕数据
const OverallRanking = ref(
Array(3).fill({
userId: '',
avatar: '',
nickname: 'aaaaaaaa',
quantity: '111M',
}),
) // 总排行榜前三
const Ranking = ref([]) // 原始排行榜
const myRanking = ref({}) // 我的排名
const RankingLoadmore = ref(null) //触底模块
const rankingPageNo = ref(1) //分页页码
const rankingAdd = ref([]) //加载排行榜项
// 完整排行榜
const rankingTotal = computed(() => {
return [...Ranking.value, ...rankingAdd.value]
})
const rewardsTop10 = ref([]) // 原前10名奖励列表
const topReward = ref({}) // 前10名奖励项
// 处理后的前10名奖励列表
const showRewardsTop10 = computed(() => {
let newRewardsTop10 = JSON.parse(JSON.stringify(rewardsTop10.value)) // 对 rewardsTop10 进行深拷贝,避免引用问题
for (let index = 0; index < newRewardsTop10.length; index++) {
let topRewards = newRewardsTop10[index]
let topUser = RankingHasTop10.value[index]
// 第1名
if (index === 0) {
topRewards?.rewards.push(
{
cover: new URL('/src/assets/icon/coin.png', import.meta.url).href,
content: `${formatLargeNumber(Number(topUser?.quantityNumber || '0') * 0.1)}(10% Points Coins)`,
quantity: 0,
type: 'GIFT',
},
{
cover: '',
content: 'Homepage Ad* 7 days',
quantity: 0,
type: 'GIFT',
},
)
}
// 第2名
else if (index === 1) {
topRewards?.rewards.push({
cover: new URL('/src/assets/icon/coin.png', import.meta.url).href,
content: `${formatLargeNumber(Number(topUser?.quantityNumber || '0') * 0.08)}(8% Points Coins)`,
quantity: 0,
type: 'GIFT',
})
}
// 第3名
else if (index === 2) {
topRewards?.rewards.push({
cover: new URL('/src/assets/icon/coin.png', import.meta.url).href,
content: `${formatLargeNumber(Number(topUser?.quantityNumber || '0') * 0.06)}(6% Points Coins)`,
quantity: 0,
type: 'GIFT',
})
}
// 第4-10名
else {
topRewards?.rewards.push({
cover: new URL('/src/assets/icon/coin.png', import.meta.url).href,
content: `${formatLargeNumber(Number(topUser?.quantityNumber || '0') * 0.04)}(4% Points Coins)`,
quantity: 0,
type: 'GIFT',
})
}
}
return newRewardsTop10
})
// 计算前10名的奖励金币数量
const formatLargeNumber = (num) => {
if (typeof num !== 'number' || isNaN(num)) {
return '0'
}
const absNum = Math.abs(num)
if (absNum >= 1000000) {
const millionValue = num / 1000000
const roundedValue = Math.floor(millionValue * 100) / 100 // 向下取整
return roundedValue.toFixed(2) + 'M'
} else if (absNum >= 1000) {
const thousandValue = num / 1000
const roundedValue = Math.floor(thousandValue * 100) / 100 // 向下取整
return roundedValue.toFixed(2) + 'K'
} else {
return Math.floor(num).toString()
}
}
const giftsList = ref([]) // 礼物列表
const activity = ref({}) //活动详情和奖池
const activeIndex = ref(0) // 当前高亮格子
const isRolling = ref(false) // 抽奖状态
const rollTimes = ref(0) // 拥有抽奖券量
const totalDraw = ref({}) // 我的总抽奖次数
const currentAmount = ref({ availableAmount: 0 }) //可提现金额
const result = ref([]) // 抽奖结果
const resultShowIndex = ref(0)
const myRecords = ref([]) // 抽奖记录
const RechargeBadgeInfo = ref([]) //充值奖励-徽章信息
const userInfo = ref({}) //用户信息
const userIdentity = ref({}) //用户身份
const taskList = ref([]) //任务列表
// 排行榜前10名带奖励
const RankingHasTop10 = computed(() => {
let RankingTop10 = rankingTotal.value.filter((_, index) => index < 10)
if (RankingTop10.length < 10) {
let addNullUser = Array.from({ length: 10 - RankingTop10.length }, () => ({
avatar: '',
nickname: '',
account: '',
amount: '',
}))
RankingTop10.push(...addNullUser)
}
return RankingTop10
})
// 排行榜11名开始无奖励
const showRanking = computed(() => {
return rankingTotal.value.filter((_, index) => index >= 10)
// return []
})
// 沙特时间的3月19号早上0点的截止
// 获取每周一早上5点的时间戳沙特时间0点 = 北京时间5点
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))
Seconds.value = formatTime(Math.floor(totalSeconds % 60))
}
// 抽屉展示
const drawerShowBt = (type) => {
transferShow.value = type == 'transfer' ? !transferShow.value : false
exchangeShow.value = type == 'exchange' ? !exchangeShow.value : false
withdrawShow.value = type == 'withdraw' ? !withdrawShow.value : false
selectedCoin.value = null
}
// 点击展示主体内容
const handleBt = (type) => {
rankingShow.value = type == 'ranking' ? true : false
lotteryShow.value = type == 'lottery' ? true : false
incomeShow.value = type == 'withdrawal' ? true : false
drawerShowBt('') // 收起抽屉
selectedCoin.value = null // 清除选择币种
}
// 点击奖品
const clickReward = (item) => {
topReward.value = item // 展示奖品赋值
topRewardShow.value = true // 显示奖品
}
// 前往搜索代理页
const searchPayee = () => {
router.push({
path: '/search-payee',
query: { from: '/activities/lucky-dollars-season3', activeAction: 'incomeShow' },
})
}
// 前往提现页
const goToWithdraw = () => {
router.push({ path: '/cash-out', query: { activityId: '2006671533988298666' } })
}
// 判断文本是否溢出(需要滚动)
const isTextOverflow = (text) => {
// 创建临时元素来测量文本宽度
const tempDiv = document.createElement('div')
tempDiv.style.position = 'absolute'
tempDiv.style.fontSize = '1em'
tempDiv.style.fontWeight = '860'
tempDiv.textContent = text
document.body.appendChild(tempDiv) // 将临时元素添加到文档中
const containerWidth = window.innerWidth * 0.3 // 所在容器宽度
const textWidth = tempDiv.getBoundingClientRect().width // 文本宽度
document.body.removeChild(tempDiv) // 删除临时元素
// 如果文本宽度超过容器宽度,则需要滚动
return textWidth > containerWidth
}
// 转账金币选项
const coinOptions = ref([
{ id: 1, amount: 10500, price: 1 },
{ id: 2, amount: 52500, price: 5 },
{ id: 3, amount: 105000, price: 10 },
])
//选择金币
const selectCoin = (coin) => {
// 单选逻辑:如果已经选中相同的金币,则取消选择;否则选中新的金币
if (selectedCoin.value?.id == coin.id) {
selectedCoin.value = null
} else {
selectedCoin.value = coin
}
}
// 转账
const transfer = async () => {
if (!selectedCoin.value) {
showError(t('please_select_amount'))
return
}
if (!selectedPayee.value?.id) {
showError(t('please_select_payee'))
return
}
// 构造请求参数
const transferData = {
amount: selectedCoin.value.price,
acceptUserId: selectedPayee.value?.id,
activityId: '2006671533988298666',
}
try {
// 调用转账接口
const response = await transferActivityDollar(transferData)
if (response.status) {
showSuccess(
t('transfer_success', {
price: selectedCoin.value.price,
name: selectedPayee.value?.name,
}),
)
} else {
showError(t('transfer_failed', { price: selectedCoin.value.price }))
}
selectedCoin.value = null // 重置选择
getDrawableAmount() //刷新可提现金额
} catch (error) {
showError(error.errorMsg)
}
}
//兑换代币
const exchangeCoinBt = async () => {
if (!selectedCoin.value) {
showError(t('please_select_amount'))
return
}
// 构造请求参数
const transferData = {
amount: selectedCoin.value.price,
activityId: '2006671533988298666',
}
try {
// 调用转账接口
const response = await exchangeCoin(transferData)
if (response.status) {
showSuccess(t('exchange_success_coins', { amount: selectedCoin.value.amount }))
} else {
showError(t('exchange_failed_coins', { amount: selectedCoin.value.amount }))
}
// 重置选择
selectedCoin.value = null
getDrawableAmount() //刷新可提现金额
} catch (error) {
showError(error.errorMsg)
}
}
// 打开弹窗
const openPopup = (type) => {
closedPopup(false) //先关闭其他弹窗,不清除抽奖结果
switch (type) {
case 'rankingHelp':
rankingHelpShow.value = true
break
case 'top3Help':
top3HelpShow.value = true
break
case 'withdrawalHelp':
withdrawalHelpShow.value = true
break
case 'result':
resultShow.value = true
break
case 'history':
historyShow.value = true
break
case 'reward':
topRewardShow.value = true
break
default:
break
}
}
// 关闭弹窗
const closedPopup = (clear = true) => {
rankingHelpShow.value = false
top3HelpShow.value = false
withdrawalHelpShow.value = false
resultShow.value = false
historyShow.value = false
topRewardShow.value = false
if (clear) {
result.value = []
}
resultShowIndex.value = 0
}
//奖盘布局
const getGridPosition = (index) => {
//顺时针位置
const positions = [
{ gridArea: '1/1' }, //上左
{ gridArea: '1/2' }, //上中
{ gridArea: '1/3' }, //上右
{ gridArea: '2/3' }, //中右
{ gridArea: '3/3' }, //下右
{ gridArea: '3/2' }, //下中
{ gridArea: '3/1' }, //下左
{ gridArea: '2/1' }, //中左
]
return positions[index]
}
// 抽奖动画
const startLottery = (resultIndex) => {
console.log('开始抽奖动画')
return new Promise((resolve) => {
activeIndex.value = -1
let speed = 200 // 初始速度
let currentCycle = 0 // 当前圈数
let constantSpeedCycle = 0 // 当前匀速圈数
let totalCycles = 1 // 至少旋转2圈数
const roll = () => {
activeIndex.value = (activeIndex.value + 1) % activity.value.prizeList.length
console.log('当前索引:', activeIndex.value)
if (activeIndex.value === resultIndex && speed > 200) {
setTimeout(() => {
resolve() // 抽奖结束
}, 500)
} else {
if (activeIndex.value === activity.value.prizeList.length - 1) {
currentCycle++
}
// 加速旋转
if (currentCycle < totalCycles) {
speed -= 20
} else {
// 匀速旋转
if (activeIndex.value === activity.value.prizeList.length - 1) {
constantSpeedCycle++
}
if (constantSpeedCycle > 2) {
// 最后减速效果
speed += 20
}
}
setTimeout(roll, speed)
}
}
roll()
})
}
// 连抽
const sweepstakes = async (consecutive = 1) => {
if (isRolling.value) return // 防止重复点击
// 检查抽奖次数
if (rollTimes.value >= consecutive) {
isRolling.value = true
let data = {
activityId: '2006671533988298666',
drawCount: consecutive,
}
try {
// 单抽
if (consecutive == 1) {
const resOnceDraw = await onceDraw(data)
if (resOnceDraw.status && resOnceDraw.body) {
getTotalDrawCount() //刷新累计抽奖次数
getConfigsBadgeInfo() //刷新累计抽奖-徽章信息
getTickets() //重新获取拥有的抽奖券
result.value = [resOnceDraw.body] // 中奖结果赋值
const resItem = resOnceDraw.body //接口获取的抽奖结果(单抽为对象)
//取抽奖结果的位置
const index = activity.value.prizeList.findIndex(
(prize) => prize.prizeName == resItem?.prize.prizeName,
) //转盘第几位停下
console.log('index:', index)
await startLottery(index)
}
}
//连抽
else {
const resMultiDraw = await multiDraw(data)
if (resMultiDraw.status && resMultiDraw.body) {
getTotalDrawCount() //刷新累计抽奖次数
getConfigsBadgeInfo() //刷新累计抽奖-徽章信息
getTickets() //重新获取拥有的抽奖券
result.value = resMultiDraw.body.results // 中奖结果赋值
//取第一个抽奖结果的位置
let index = activity.value.prizeList.findIndex(
(prize) => prize.prizeName == result.value[0]?.prize.prizeName,
)
console.log('index:', index)
await startLottery(index)
}
}
getDrawRecords() // 获取中奖记录
openPopup('result') //打开中奖结果弹窗
isRolling.value = false
} catch (error) {
isRolling.value = false
if (error.response.errorCode == 3274) {
showError('Device has been used by another account')
}
}
}
}
// 展示任务目标
const showTarget = (task) => {
if (task.targetType == 'MIC_TIME') {
let timeType = task.targetValue < 60
let currentValue = timeType ? task.currentValue : task.currentValue / 60
let targetValue = timeType ? task.targetValue : task.targetValue / 60
// 直接去除小数部分(向下取整)
currentValue = Math.floor(currentValue * 10) / 10
targetValue = Math.floor(targetValue * 10) / 10
let timeUnit = timeType ? t('minutes_short') : t('hours_short')
return t('on_mic_progress', {
current: currentValue,
total: targetValue,
unit: timeUnit,
})
} else if (task.targetType == 'SEND_GIFT') {
if (task.taskCode == 'SPINS_SEND_GIFT_5') {
return t('Send 5 Ramadan gifts ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
}
} else if (task.targetType == 'SAVE_COINS') {
if (task.taskCode == 'SPINS_SAVE_50000') {
return t('Win 50,000 coins in total across any games ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
} else if (task.taskCode == 'SPINS_SAVE_100000') {
return t('Win 100,000 coins in total across any games ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
} else if (task.taskCode == 'SPINS_SAVE_500000') {
return t('Win 500,000 coins in total across any games ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
}
} else if (task.targetType == 'RECHARGE_AMOUNT') {
if (task.taskCode == 'SPINS_RECHARGE_1') {
return t('Daily total recharge amount: $1 ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
} else if (task.taskCode == 'SPINS_RECHARGE_10') {
return t('Daily total recharge amount: $10 ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
} else if (task.taskCode == 'SPINS_RECHARGE_50') {
return t('Daily total recharge amount: $50 ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
} else if (task.taskCode == 'SPINS_RECHARGE_100') {
return t('Daily total recharge amount: $100 ({currentValue}/{targetValue})', {
currentValue: task.currentValue,
targetValue: task.targetValue,
})
}
} else {
return `${task.taskName}(${task.currentValue}/${task.targetValue})`
}
}
// 选中的收款人
const selectedPayee = ref({})
// 初始化收款人信息
const initializePayee = () => {
const savedPayee = getSelectedPayee()
if (savedPayee) {
Object.assign(selectedPayee.value, savedPayee)
handleBt('withdrawal')
drawerShowBt('transfer')
}
}
// 清除当前选中的收款人
const clearPayee = () => {
Object.assign(selectedPayee.value, {
id: null,
account: '',
name: '',
avatar: '',
type: '',
isHost: false,
isAgency: false,
hasSalary: false,
})
clearSelectedPayee()
}
// 获取中奖用户列表
const getWinners = async () => {
const resWinners = await winnerHistory('2006671533988298666')
if (resWinners.status && resWinners.body) {
barrageList.value = resWinners.body
}
}
// 获取用户信息
const getUserInfo = async () => {
if (Object.keys(userInfo.value).length === 0) {
const resUserInfo = await getMemberProfile()
if (resUserInfo.status && resUserInfo.body) {
setUserInfo(resUserInfo.body, null)
userInfo.value = resUserInfo.body
}
}
const resIdentity = await getUserIdentity()
if (resIdentity.status && resIdentity.body) {
userIdentity.value = resIdentity.body
}
}
// 获取总榜前三
const getOverallRanking = async () => {
let data = {
activityType: 13,
}
const resRanking = await getOverallRankingTop3(data)
if (resRanking.status && resRanking.body) {
OverallRanking.value = resRanking.body || []
} else {
OverallRanking.value = []
}
}
// 获取排行榜
const getRanking = async () => {
let data = {
activityType: 13,
}
const resRanking = await getRankingListAndMyRanking(data)
if (resRanking.status && resRanking.body) {
myRanking.value = resRanking.body?.currentUserRank //我的排名信息
Ranking.value = resRanking.body?.rankingList
getRewardsAndGifts() // 获取前十名奖励列表
} else {
Ranking.value = []
myRanking.value = {}
}
}
// 获取前十名奖励列表
const getRewardsAndGifts = async () => {
const resRewardsAndGifts = await getThisWeekRewardsAndGifts('2020751672412921857')
if (resRewardsAndGifts.status && resRewardsAndGifts.body) {
giftsList.value = resRewardsAndGifts.body.gifts
let tempRewardsTop10 = resRewardsAndGifts.body.butOneRewards
let top4Rewards = JSON.parse(JSON.stringify(tempRewardsTop10[3])) // 获取第4名奖励项
if (tempRewardsTop10.length < 10) {
let addNullUser = Array.from({ length: 10 - tempRewardsTop10.length }, () => top4Rewards)
tempRewardsTop10.push(...addNullUser)
}
rewardsTop10.value = tempRewardsTop10
}
}
// 获取抽奖奖池
const getActivityDetail = async () => {
getDrawableAmount() //获取可提现金额
const resDetail = await activityDetail('98666')
if (resDetail.status && resDetail.body) {
activity.value = resDetail.body
} else {
activity.value = {}
}
}
// 格式化奖励的展示信息
const showDetail = (type, reward) => {
let showamount = ['GOLD', 'DIAMOND', 'GIFT', 'FRAGMENTS', 'TICKET']
if (showamount.includes(type)) {
return `*${reward.content}`
} else if (type === 'DOLLARS') {
return `$${reward.content}`
} else {
return `${reward.quantity}Days`
}
}
// 获取拥有的抽奖券
const getTickets = async () => {
const resTickets = await myTickets('2006671533988298666')
if (resTickets.status && resTickets.body) {
rollTimes.value = resTickets.body
} else {
rollTimes.value = 0
}
}
// 获取累计抽奖次数
const getTotalDrawCount = async () => {
const resTotalDrawCount = await myTotalDrawCount('2006671533988298666')
if (resTotalDrawCount.status && resTotalDrawCount.body) {
totalDraw.value = resTotalDrawCount.body
}
}
// 可提现金额
const getDrawableAmount = async () => {
const resDrawableAmount = await withdrawableAmount('2006671533988298666')
if (resDrawableAmount.status && resDrawableAmount.body) {
currentAmount.value = resDrawableAmount.body
}
}
// 获取任务列表
const getTaskList = async () => {
const resTaskList = await ActTaskList()
if (resTaskList.status && resTaskList.body) {
taskList.value = resTaskList.body
}
}
// 获取累计抽奖-徽章信息
const getConfigsBadgeInfo = async () => {
let data = {
activityType: 'USER_RECHARGE_DRAW',
activityId: '2006671533988298666',
}
const resConfigsBadge = await rewardConfigsBadge(data)
if (resConfigsBadge.status && resConfigsBadge.body) {
RechargeBadgeInfo.value = resConfigsBadge.body?.[0]
}
}
// 获取中奖记录
const getDrawRecords = async () => {
const resDrawRecords = await drawRecords('98666')
if (resDrawRecords.status && resDrawRecords.body) {
myRecords.value = resDrawRecords.body?.records || []
}
}
// 领取任务奖励
const receiveTaskReward = async (code) => {
let data = {
activityId: '2006671533988298666',
taskCode: code,
}
try {
const resReceive = await receiveTickets(data)
if (resReceive.status && resReceive.body) {
getTaskList() //获取任务列表
getTickets() //获取拥有的抽奖券
}
} catch (error) {
showError(error.errorMsg)
}
}
// 领取累计抽奖奖励-徽章
const receiveRechargeBadge = async (rewards) => {
let data = {
activityType: rewards.activityType,
activityId: '2006671533988298666',
ruleId: rewards.ruleId,
}
try {
const resReceive = await receiveRewardBadge(data)
if (resReceive.status && resReceive.body) {
getConfigsBadgeInfo() // 刷新累计抽奖-徽章信息
}
} catch (error) {
showError(error.errorMsg)
}
}
// 刷新页面数据
const initData = async () => {
await Promise.all([
getUserInfo(), //获取用户信息
initializePayee(), //获取收款人信息
getWinners(), //获取历史中奖用户
getRanking(), //获取排行榜
getOverallRanking(), //获取总榜前三
getActivityDetail(), //获取奖池
getTotalDrawCount(), //刷新累计抽奖次数
getTickets(), //重新获取拥有的抽奖券
getConfigsBadgeInfo(), // 刷新累计抽奖-徽章信息
getTaskList(), //获取任务列表
getDrawRecords(), // 获取中奖记录
])
}
// 预加载关键图片
const preloadCriticalImages = async () => {
const criticalImages = [
// 背景
imageUrl('bg1'),
imageUrl('bg2'),
// imageUrl('bg3'),
// 按钮
imageUrl(getImgName('rankBt')),
imageUrl(getImgName('rankBtActive')),
imageUrl(getImgName('lotteryBt')),
imageUrl(getImgName('lotteryBtActive')),
imageUrl(getImgName('withdrawalBt')),
imageUrl(getImgName('withdrawalBtActive')),
// 每周礼物
imageUrl('eventGiftsBg'),
imageUrl('giftBg'),
// 总排行榜前三
imageUrl('overallRankingBg'),
imageUrl('historyBt'),
imageUrl('top1'),
imageUrl('top2'),
imageUrl('top3'),
// 倒计时
imageUrl('timeDayBg'),
imageUrl('timeBg'),
// 排行榜
imageUrl('RankingTopBorder'),
imageUrl('RankingBottomBorder'),
imageUrl('RankingBorder'),
imageUrl('historyBt'),
imageUrl('itemTop1Bg'),
imageUrl('itemTop2Bg'),
imageUrl('itemTop3Bg'),
imageUrl('itemFrom4Bg'),
imageUrl('ranking1'),
imageUrl('ranking2'),
imageUrl('ranking3'),
imageUrl('rankingFrom4'),
imageUrl('ranking1Frame'),
imageUrl('ranking2Frame'),
imageUrl('ranking3Frame'),
imageUrl('userNameBorder'),
imageUrl('itemTopRewardBg'),
// 我的排名
imageUrl('myRankingBg'),
]
await preloadImages(criticalImages)
}
// 预加载其他图片
const preloadOtherImages = async () => {
// const criticalImages = [
// // 抽奖模块
// imageUrl('resultBt'),
// imageUrl('lottery'),
// imageUrl('prizeActiveFrame'),
// imageUrl(getImgName('draw1BtBg')),
// imageUrl(getImgName('draw10BtBg')),
// imageUrl('taskBtGo'),
// imageUrl('taskBtReceive'),
// imageUrl('taskBtReceived'),
// imageUrl('taskTalk'),
// imageUrl('taskGift'),
// imageUrl('taskGame'),
// imageUrl('taskRecharge'),
// imageUrl('ticket'),
// // 前三名奖励展示
// imageUrl('rewardBg'),
// // 抽奖结果展示
// imageUrl('resultBg'),
// imageUrl('resultBack'),
// imageUrl('resultNext'),
// // 中奖历史
// imageUrl(getImgName('historyBg')),
// // 排行榜帮助弹窗
// imageUrl('rankingHelpBg_ar'),
// imageUrl(getImgName('rankingHelpInfo')),
// // 总榜前三规则弹窗
// imageUrl('top3HelpBg_ar'),
// imageUrl(getImgName('top3HelpInfo')),
// // 兑换规则弹窗
// imageUrl(getImgName('withdrawalHelp')),
// ]
const criticalImages = []
await preloadImages(criticalImages)
}
// 完成预加载
const completePreloading = async () => {
try {
// 执行所有初始化操作
await Promise.all([
// initData(),
preloadCriticalImages(),
])
} catch (error) {
console.error('预加载过程中发生错误:', error)
} finally {
// 无论成功或失败都结束加载状态
isLoading.value = false
}
}
// 使用工具函数连接APP
const connectToAppHandler = async () => {
await connectToApp(() => {
// 连接成功回调
completePreloading() // 完成预加载
})
}
// 启动倒计时
const startCountdown = () => {
getCountdown() // 立即执行一次
timer = setInterval(getCountdown, 1000) //倒计时每秒更新
}
// // 触发节流获取排行榜
// const debouceGetRanking = useThrottle(() => {
// getRanking() //加载新的排行榜项
// }, 1000)
// // IntersectionObserver配置
// const observer = new IntersectionObserver((entries) => {
// entries.forEach((entry) => {
// if (entry.intersectionRatio > 0 && rankingTotal.value.length != 0) {
// console.log('触发RankingLoadmore加载')
// debouceGetRanking()
// }
// })
// })
// 设置超时刷新逻辑
const startTimeoutCheck = () => {
timeoutId.value = setTimeout(() => {
if (isLoading.value) {
console.warn('⏰ 预加载超时,正在刷新页面...')
window.location.reload() // 刷新页面
}
}, 20000) // 20 秒超时
}
// 清理定时器
const clearTimeoutCheck = () => {
if (timeoutId.value) {
clearTimeout(timeoutId.value)
timeoutId.value = null
}
}
// 组件挂载时检测环境
onMounted(async () => {
console.log('route.query.activeAction:', route.query.activeAction)
if (route.query.activeAction == 'incomeShow') {
handleBt('withdrawal')
} else {
handleBt('ranking')
}
// 启动超时检测
startTimeoutCheck()
await connectToAppHandler()
initData()
startCountdown() //开启倒计时
preloadOtherImages() // 预加载其他图片
// // 监听加载模块
// if (RankingLoadmore.value) {
// console.log('监控加载模块')
// observer.observe(RankingLoadmore.value)
// }
})
onUnmounted(() => {
clearTimeoutCheck() // 清理超时检测定时器
clearInterval(timer) //摧毁计时器
})
</script>
<style lang="scss" scoped>
* {
color: #fff;
}
.fullPage {
position: relative;
background: #142c24;
}
.bg {
width: 100vw;
min-height: 100vh;
position: relative;
z-index: 1;
}
.background-overlay {
position: absolute;
inset: 236vw 0 0;
background-image: var(--bg2-url);
background-repeat: repeat-y;
background-position: top center;
background-size: 100% auto;
z-index: 0; /* 确保在.bg之下 */
}
.ranking-bg {
background-color: #450b08;
background-image: var(--ranking-bg-url);
background-size: 100% auto;
background-repeat: no-repeat;
position: absolute;
inset: 15vw 2vw 4vw;
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;
}
.Textlittle {
font-size: 0.9em;
}
.timeBox {
display: flex;
justify-content: center;
align-items: center;
}
/* 添加加载动画样式 */
.loading-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #666;
overflow: hidden;
position: relative;
}
.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;
}
.reward-wrapper {
width: 100%;
overflow: hidden;
}
[dir='rtl'] .reward-wrapper {
left: 4vw;
right: 15vw;
}
@keyframes scroll-left {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
@keyframes scroll-right {
0% {
transform: translateX(0);
}
100% {
transform: translateX(50%);
}
}
.scroll-wrapper {
display: flex;
width: fit-content;
}
[dir='ltr'] .scroll-wrapper {
animation: scroll-left 8s linear infinite;
will-change: transform;
}
[dir='rtl'] .scroll-wrapper {
animation: scroll-right 8s linear infinite;
will-change: transform;
}
.scroll-content {
display: flex;
align-items: center;
}
[dir='ltr'] .scroll-content {
margin-left: 4vw;
}
[dir='rtl'] .scroll-content {
margin-left: auto;
margin-right: 4vw;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.ruleBt {
width: 5vw;
min-width: 0;
display: block;
position: absolute;
top: 5px;
right: 5px;
}
[dir='rtl'] .ruleBt {
left: 5px;
right: auto;
}
.scrollY::-webkit-scrollbar {
display: none;
}
/* 金币网格 */
.coin-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// transition: all 0.2s;
aspect-ratio: 1/1;
border-radius: 8px;
border: 1px solid rgba(64, 64, 64, 0.5);
background: rgba(240, 240, 240, 0.3);
box-shadow:
-42px 103px 31px 0 rgba(145, 145, 145, 0),
-27px 66px 29px 0 rgba(145, 145, 145, 0.01),
-15px 37px 24px 0 rgba(145, 145, 145, 0.03),
-7px 17px 18px 0 rgba(145, 145, 145, 0.04),
-2px 4px 10px 0 rgba(145, 145, 145, 0.05);
backdrop-filter: blur(7.5px);
}
.coin-item.selected {
border-radius: 11px;
border: 2px solid #5dffc9;
box-shadow:
-0.25px -0.25px 1px 0 #5dffbb,
0.25px 0.25px 1px 0 #5dffc6,
0 0 3px 0 rgba(93, 255, 198, 0.8),
0 0 5px 0 rgba(93, 255, 187, 0.6),
0 0 4px 0 rgba(0, 210, 161, 0.3);
}
.coin-item:active {
transform: scale(0.98);
}
.rotated {
transform: rotate(90deg);
}
[dir='rtl'] .flipImg {
transform: scaleX(-1);
}
[dir='rtl'] .flipImg.rotated {
transform: scaleX(-1) rotate(90deg);
}
@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;
}
}
[dir='rtl'] .timeBox {
flex-direction: row-reverse;
}
</style>