feat(邀请新用户活动): 对接总榜接口并展示

This commit is contained in:
hzj 2026-03-10 19:08:40 +08:00
parent 8710e0abd2
commit 0bcc04817e

View File

@ -16,6 +16,7 @@
<!-- 页面背景 -->
<BackgroundLayer :backgroundImages="[imageUrl('bg1'), imageUrl('bg2'), imageUrl('bg3')]" />
<!-- 头部导航组件 -->
<div style="position: absolute; top: 0; left: 0; width: 100%">
<GeneralHeader
:isHomePage="true"
@ -187,7 +188,7 @@
<!-- 收入展示 -->
<itemCenter
style="min-height: 100vw"
:imgUrl="imageUrl('incomeBg')"
:imgUrl="imageUrl(getImgName('incomeBg'))"
:contentStyle="`padding: 44vw 8vw 18vw 7vw;display:grid;grid-template-columns: repeat(2, 1fr);gap: 4vw;`"
>
<!-- 更多按钮 -->
@ -308,56 +309,193 @@
gap: 13vw;
"
>
<!-- 排行榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rank')">
<!-- 榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rankAll')">
<img
v-smart-img
:src="imageUrl(getImgName('rankBt'))"
:src="imageUrl(getImgName('listBt'))"
alt=""
:class="{
'grayscale-container': !rankShow,
'grayscale-container': !rankAllShow,
}"
style="width: 100%; display: block; object-fit: cover"
/>
</div>
<!-- 奖励栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('reward')">
<!-- 周榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rankWeek')">
<img
v-smart-img
:src="imageUrl(getImgName('rewardBt'))"
:src="imageUrl(getImgName('rankBt'))"
alt=""
:class="{
'grayscale-container': !rewardShow,
'grayscale-container': !rankWeekShow,
}"
style="width: 100%; display: block; object-fit: cover"
/>
</div>
</div>
<!-- 排行-->
<div v-show="rankShow">
<!-- -->
<div v-show="rankAllShow">
<itemCenter
style="min-height: 205.33vw"
:imgUrl="imageUrl('rankingBg')"
:contentStyle="`padding: 10vw 6vw 10vw;flex-direction: column;justify-content: flex-start;gap:4vw`"
:contentStyle="`padding: 10vw 6vw 10vw;flex-direction: column;justify-content: flex-start;gap:2vw`"
>
<!-- 倒计时 -->
<itemCenter
style="width: 85%; min-height: 11.33vw"
:imgUrl="imageUrl('timeBg')"
:contentStyle="``"
<!-- 列表 -->
<div
style="
flex: 1;
min-height: 0;
width: 100%;
display: flex;
flex-direction: column;
gap: 4px;
"
>
<div class="timeBox">
<div class="timeText" style="">{{ WDays }}Day</div>
<div class="timeText timeGap"></div>
<div class="timeText" style="">{{ WHours }}</div>
<div class="timeText timeGap">:</div>
<div class="timeText" style="">{{ WMinutes }}</div>
<div class="timeText timeGap">:</div>
<div class="timeText" style="">{{ WSeconds }}</div>
<!-- 列表项 -->
<div
class="overflow-y-auto"
style="display: flex; flex-direction: column; width: 100%; gap: 2vw"
>
<itemCenter
style="min-height: 22.33vw"
v-for="(listItem, index) in rankingTotal"
:key="listItem.userId"
:imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 5vw`"
:lazy="true"
:immediate="index < 8"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div style="color: #ffe601; font-weight: 700">
{{ listItem?.rank }}
</div>
<!-- 头像 -->
<img
:src="listItem?.avatar || ''"
alt=""
style="
display: block;
width: 13vw;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 名称id -->
<div
style="
flex: 1;
min-width: 0;
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
"
>
<div
style="
color: #fff;
font-size: 0.9em;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ listItem?.nickname }}
</div>
<div style="font-size: 0.8em; color: #fff; font-weight: 590">
{{ $t('user_id_prefix') }} {{ listItem?.account }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/coin.png"
alt=""
style="display: block; width: 1.5em; aspect-ratio: 1/1; object-fit: cover"
/>
<div style="font-size: 0.9em; font-weight: 700">
{{ listItem?.quantity }}
</div>
</div>
</itemCenter>
</div>
</itemCenter>
</div>
</itemCenter>
<!-- 我的排名占位 -->
<div style="height: 20vw"></div>
</div>
<!-- 周榜 -->
<div v-show="rankWeekShow">
<itemCenter
style="min-height: 205.33vw"
:imgUrl="imageUrl('rankingBg')"
:contentStyle="`padding: 13vw 6vw 10vw;flex-direction: column;justify-content: flex-start;gap:2vw`"
>
<!-- 头部 -->
<div style="width: 100%; min-width: 0; display: flex; align-items: center; gap: 2vw">
<!-- 倒计时 -->
<itemCenter
style="width: 70%; min-width: 0; min-height: 9.87vw"
:imgUrl="imageUrl('timeBg')"
:contentStyle="``"
>
<div class="timeBox">
<div class="timeText" style="">{{ WDays }}Day</div>
<div class="timeText timeGap"></div>
<div class="timeText" style="">{{ WHours }}</div>
<div class="timeText timeGap">:</div>
<div class="timeText" style="">{{ WMinutes }}</div>
<div class="timeText timeGap">:</div>
<div class="timeText" style="">{{ WSeconds }}</div>
</div>
</itemCenter>
<!-- 奖励按钮 -->
<img
v-smart-img
:src="imageUrl(getImgName('rewardBt'))"
alt=""
style="flex: 1; min-width: 0; display: block; object-fit: cover"
@click="rewardShow = true"
/>
</div>
<!-- 列表 -->
<div
@ -383,7 +521,7 @@
:imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 5vw`"
:lazy="true"
:immediate="index < 2"
:immediate="index < 8"
@click="viewUserInfo(listItem.userId)"
>
<!-- 基本信息 -->
@ -476,47 +614,6 @@
<!-- 我的排名占位 -->
<div style="height: 30vw"></div>
</div>
<!-- 奖励展示 -->
<div
v-show="rewardShow"
style="display: flex; flex-direction: column; gap: 2vw; padding-bottom: 10vw"
>
<itemCenter
v-for="(rewardsTop, index) in rankingRewards"
style="min-height: 100vw"
:imgUrl="imageUrl(`rewardTop${index + 1}Bg`)"
:contentStyle="`padding: 36.5vw 9vw 18vw;align-items: flex-start;gap: 11vw;`"
>
<div
v-for="(reward, index) in rewardsTop.rewards"
style="flex: 1; align-self: stretch; display: flex; flex-direction: column"
>
<div
style="
width: 100%;
aspect-ratio: 1/1;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
:src="reward.cover || ''"
alt=""
width="70%"
style="display: block; object-fit: cover"
@error="(e) => handleRewardImageError(e, reward.type)"
/>
</div>
<div style="flex: 1; display: flex; justify-content: center; align-items: center">
<div style="font-size: 1.3em; color: #fff; font-weight: 600">
{{ formatRewardDisplay(reward.type, reward) }}
</div>
</div>
</div>
</itemCenter>
</div>
</div>
</div>
@ -548,7 +645,7 @@
<!-- 我的排名 -->
<itemCenter
v-show="showModule == 'ranking' && rankShow"
v-show="showModule == 'ranking' && rankWeekShow"
style="min-height: 25.33vw; position: fixed; bottom: 0; z-index: 3"
:imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 7vw`"
@ -1076,6 +1173,72 @@
</div>
</itemCenter>
</div>
<!-- 周榜奖励模块 -->
<div
v-show="rewardShow"
style="
width: 100vw;
padding: 25vw 0 10vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
"
@click="closedPopup"
>
<!-- 收益&列表 -->
<itemCenter
style="min-height: 286.13vw"
:imgUrl="imageUrl(getImgName('weekRewardBg'))"
:contentStyle="`padding: 57vw 15vw 20vw 15vw;flex-direction: column;gap: 40vw;justify-content: flex-start;`"
@click.stop
>
<div
v-for="(rewardsTop, index) in rankingRewards"
style="flex: 1; min-height: 0; display: flex; gap: 11vw"
>
<div
v-for="(reward, index) in rewardsTop.rewards"
style="
flex: 1;
align-self: stretch;
display: flex;
flex-direction: column;
gap: 2vw;
"
>
<!-- 奖励图 -->
<div
style="
width: 100%;
aspect-ratio: 1/1;
display: flex;
justify-content: center;
align-items: center;
"
>
<img
:src="reward.cover || ''"
alt=""
width="70%"
style="display: block; object-fit: cover"
@error="(e) => handleRewardImageError(e, reward.type)"
/>
</div>
<!-- 奖励信息 -->
<div style="flex: 1; display: flex; justify-content: center; align-items: center">
<div style="font-size: 1.3em; color: #fff; font-weight: 600">
{{ formatRewardDisplay(reward.type, reward) }}
</div>
</div>
</div>
</div>
</itemCenter>
</div>
</maskLayer>
<!-- 提示弹窗 -->
@ -1114,6 +1277,7 @@ import { formatRewardDisplay } from '@/utils/rewardFormatter.js'
import {
getRankingListAndMyRanking, //
getThisWeekRewardsAndGifts, //
getOverallRanking, //
} from '@/api/activity.js'
import {
getMyInviteCode, //
@ -1144,7 +1308,7 @@ const getImgName = (filename) => {
}
// OSSURL
const imageUrl = (filename) => getPngUrl('invitation/inviteNewUser/', filename)
const imageUrl = (filename) => getPngUrl('invitation/inviteNewUserNew/', filename)
const { copy, isSupported } = useClipboard()
@ -1168,25 +1332,34 @@ const myRanking = ref({}) // 我的排名
const RankingLoadmore = ref(null) //
const rankingPageNo = ref(1) //
const rankingAdd = ref([]) //
const OverallRanking = ref([]) //
//
const rankingTotal = computed(() => {
return [...Ranking.value, ...rankingAdd.value]
if (rankAllShow.value) {
return OverallRanking.value
}
if (rankWeekShow.value) {
return [...Ranking.value, ...rankingAdd.value]
}
})
const showModule = ref('income') //
const rankShow = ref(true) //
const rankAllShow = ref(true) //
const rankWeekShow = ref(false) //
const rewardShow = ref(false) //
//
const changeTag = (tag) => {
switch (tag) {
case 'rank':
rankShow.value = true
rewardShow.value = false
case 'rankWeek':
rankWeekShow.value = true
rankAllShow.value = false
break
case 'reward':
rankShow.value = false
rewardShow.value = true
case 'rankAll':
rankWeekShow.value = false
rankAllShow.value = true
break
}
}
@ -1198,7 +1371,7 @@ const incomeShow = ref(false) //收益详情弹窗
const tipShow = ref(false) //
//
const maskLayerShow = computed(() => {
return helpInfoShow.value || enterCodeShow.value || incomeShow.value
return helpInfoShow.value || enterCodeShow.value || incomeShow.value || rewardShow.value
})
//
@ -1206,6 +1379,7 @@ const closedPopup = () => {
helpInfoShow.value = false
enterCodeShow.value = false
incomeShow.value = false
rewardShow.value = false
}
//
@ -1423,6 +1597,19 @@ const getRanking = async () => {
}
}
//
const getOverallList = async () => {
let data = {
activityType: 14,
}
const resRanking = await getOverallRanking(100, data)
if (resRanking.status && resRanking.body) {
OverallRanking.value = resRanking.body || []
} else {
OverallRanking.value = []
}
}
//
const getRewardsAndGifts = async () => {
const resRewardsAndGifts = await getThisWeekRewardsAndGifts('2029443922744954881')
@ -1450,27 +1637,27 @@ const preloadCriticalImages = async () => {
imageUrl('bg2'),
imageUrl('bg3'),
imageUrl('BtBg'),
imageUrl('copy'),
imageUrl(getImgName('myCode')),
imageUrl('copy'),
imageUrl(getImgName('incomeBtActive')),
imageUrl(getImgName('incomeBt')),
imageUrl(getImgName('earningsRankingBtActive')),
imageUrl(getImgName('earningsRankingBt')),
imageUrl('incomeBg'),
imageUrl(getImgName('incomeBg')),
imageUrl(getImgName('example')),
imageUrl(getImgName('listBt')),
imageUrl(getImgName('rankBt')),
imageUrl(getImgName('rewardBt')),
imageUrl('rankingBg'),
imageUrl('timeBg'),
imageUrl('rankItemBg'),
imageUrl('rewardTop1Bg'),
imageUrl('rewardTop2Bg'),
imageUrl('rewardTop3Bg'),
imageUrl(getImgName('inviteFriendsBt')),
imageUrl('rankItemBg'),
imageUrl(getImgName('helpInfo')),
imageUrl(getImgName('enterCodeBg')),
imageUrl(getImgName('confirmBt')),
imageUrl(getImgName('incomeListBg')),
imageUrl(getImgName('weekRewardBg')),
]
await preloadImages(criticalImages)
@ -1486,6 +1673,7 @@ const initData = async () => {
getBindingUserRewards(), //
getRanking(), //
getOverallList(), //
getRewardsAndGifts(), //
getRechargeRewards(), //
])
@ -1543,7 +1731,7 @@ onUnmounted(() => {
}
.timeBox {
margin-top: 1vw;
// margin-top: 1vw;
width: 80%;
display: flex;
justify-content: space-around;
@ -1552,7 +1740,7 @@ onUnmounted(() => {
.timeText {
color: #fff;
font-weight: 590;
font-size: 2em;
font-size: 1.7em;
}
.timeGap {