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')]" /> <BackgroundLayer :backgroundImages="[imageUrl('bg1'), imageUrl('bg2'), imageUrl('bg3')]" />
<!-- 头部导航组件 -->
<div style="position: absolute; top: 0; left: 0; width: 100%"> <div style="position: absolute; top: 0; left: 0; width: 100%">
<GeneralHeader <GeneralHeader
:isHomePage="true" :isHomePage="true"
@ -187,7 +188,7 @@
<!-- 收入展示 --> <!-- 收入展示 -->
<itemCenter <itemCenter
style="min-height: 100vw" 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;`" :contentStyle="`padding: 44vw 8vw 18vw 7vw;display:grid;grid-template-columns: repeat(2, 1fr);gap: 4vw;`"
> >
<!-- 更多按钮 --> <!-- 更多按钮 -->
@ -308,56 +309,193 @@
gap: 13vw; gap: 13vw;
" "
> >
<!-- 排行榜栏目按钮 --> <!-- 榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rank')"> <div style="width: 35vw; min-width: 0" @click="changeTag('rankAll')">
<img <img
v-smart-img v-smart-img
:src="imageUrl(getImgName('rankBt'))" :src="imageUrl(getImgName('listBt'))"
alt="" alt=""
:class="{ :class="{
'grayscale-container': !rankShow, 'grayscale-container': !rankAllShow,
}" }"
style="width: 100%; display: block; object-fit: cover" style="width: 100%; display: block; object-fit: cover"
/> />
</div> </div>
<!-- 奖励栏目按钮 --> <!-- 周榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('reward')"> <div style="width: 35vw; min-width: 0" @click="changeTag('rankWeek')">
<img <img
v-smart-img v-smart-img
:src="imageUrl(getImgName('rewardBt'))" :src="imageUrl(getImgName('rankBt'))"
alt="" alt=""
:class="{ :class="{
'grayscale-container': !rewardShow, 'grayscale-container': !rankWeekShow,
}" }"
style="width: 100%; display: block; object-fit: cover" style="width: 100%; display: block; object-fit: cover"
/> />
</div> </div>
</div> </div>
<!-- 排行--> <!-- -->
<div v-show="rankShow"> <div v-show="rankAllShow">
<itemCenter <itemCenter
style="min-height: 205.33vw" style="min-height: 205.33vw"
:imgUrl="imageUrl('rankingBg')" :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 <div
style="width: 85%; min-height: 11.33vw" style="
:imgUrl="imageUrl('timeBg')" flex: 1;
:contentStyle="``" min-height: 0;
width: 100%;
display: flex;
flex-direction: column;
gap: 4px;
"
> >
<div class="timeBox"> <!-- 列表项 -->
<div class="timeText" style="">{{ WDays }}Day</div> <div
<div class="timeText timeGap"></div> class="overflow-y-auto"
<div class="timeText" style="">{{ WHours }}</div> style="display: flex; flex-direction: column; width: 100%; gap: 2vw"
<div class="timeText timeGap">:</div> >
<div class="timeText" style="">{{ WMinutes }}</div> <itemCenter
<div class="timeText timeGap">:</div> style="min-height: 22.33vw"
<div class="timeText" style="">{{ WSeconds }}</div> 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> </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 <div
@ -383,7 +521,7 @@
:imgUrl="imageUrl('rankItemBg')" :imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 5vw`" :contentStyle="`padding: 0 5vw`"
:lazy="true" :lazy="true"
:immediate="index < 2" :immediate="index < 8"
@click="viewUserInfo(listItem.userId)" @click="viewUserInfo(listItem.userId)"
> >
<!-- 基本信息 --> <!-- 基本信息 -->
@ -476,47 +614,6 @@
<!-- 我的排名占位 --> <!-- 我的排名占位 -->
<div style="height: 30vw"></div> <div style="height: 30vw"></div>
</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>
</div> </div>
@ -548,7 +645,7 @@
<!-- 我的排名 --> <!-- 我的排名 -->
<itemCenter <itemCenter
v-show="showModule == 'ranking' && rankShow" v-show="showModule == 'ranking' && rankWeekShow"
style="min-height: 25.33vw; position: fixed; bottom: 0; z-index: 3" style="min-height: 25.33vw; position: fixed; bottom: 0; z-index: 3"
:imgUrl="imageUrl('rankItemBg')" :imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 7vw`" :contentStyle="`padding: 0 7vw`"
@ -1076,6 +1173,72 @@
</div> </div>
</itemCenter> </itemCenter>
</div> </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> </maskLayer>
<!-- 提示弹窗 --> <!-- 提示弹窗 -->
@ -1114,6 +1277,7 @@ import { formatRewardDisplay } from '@/utils/rewardFormatter.js'
import { import {
getRankingListAndMyRanking, // getRankingListAndMyRanking, //
getThisWeekRewardsAndGifts, // getThisWeekRewardsAndGifts, //
getOverallRanking, //
} from '@/api/activity.js' } from '@/api/activity.js'
import { import {
getMyInviteCode, // getMyInviteCode, //
@ -1144,7 +1308,7 @@ const getImgName = (filename) => {
} }
// OSSURL // OSSURL
const imageUrl = (filename) => getPngUrl('invitation/inviteNewUser/', filename) const imageUrl = (filename) => getPngUrl('invitation/inviteNewUserNew/', filename)
const { copy, isSupported } = useClipboard() const { copy, isSupported } = useClipboard()
@ -1168,25 +1332,34 @@ const myRanking = ref({}) // 我的排名
const RankingLoadmore = ref(null) // const RankingLoadmore = ref(null) //
const rankingPageNo = ref(1) // const rankingPageNo = ref(1) //
const rankingAdd = ref([]) // const rankingAdd = ref([]) //
const OverallRanking = ref([]) //
// //
const rankingTotal = computed(() => { 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 showModule = ref('income') //
const rankShow = ref(true) // const rankAllShow = ref(true) //
const rankWeekShow = ref(false) //
const rewardShow = ref(false) // const rewardShow = ref(false) //
// //
const changeTag = (tag) => { const changeTag = (tag) => {
switch (tag) { switch (tag) {
case 'rank': case 'rankWeek':
rankShow.value = true rankWeekShow.value = true
rewardShow.value = false rankAllShow.value = false
break break
case 'reward': case 'rankAll':
rankShow.value = false rankWeekShow.value = false
rewardShow.value = true rankAllShow.value = true
break break
} }
} }
@ -1198,7 +1371,7 @@ const incomeShow = ref(false) //收益详情弹窗
const tipShow = ref(false) // const tipShow = ref(false) //
// //
const maskLayerShow = computed(() => { 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 helpInfoShow.value = false
enterCodeShow.value = false enterCodeShow.value = false
incomeShow.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 getRewardsAndGifts = async () => {
const resRewardsAndGifts = await getThisWeekRewardsAndGifts('2029443922744954881') const resRewardsAndGifts = await getThisWeekRewardsAndGifts('2029443922744954881')
@ -1450,27 +1637,27 @@ const preloadCriticalImages = async () => {
imageUrl('bg2'), imageUrl('bg2'),
imageUrl('bg3'), imageUrl('bg3'),
imageUrl('BtBg'), imageUrl('BtBg'),
imageUrl('copy'),
imageUrl(getImgName('myCode')), imageUrl(getImgName('myCode')),
imageUrl('copy'),
imageUrl(getImgName('incomeBtActive')), imageUrl(getImgName('incomeBtActive')),
imageUrl(getImgName('incomeBt')), imageUrl(getImgName('incomeBt')),
imageUrl(getImgName('earningsRankingBtActive')), imageUrl(getImgName('earningsRankingBtActive')),
imageUrl(getImgName('earningsRankingBt')), imageUrl(getImgName('earningsRankingBt')),
imageUrl('incomeBg'), imageUrl(getImgName('incomeBg')),
imageUrl(getImgName('example')), imageUrl(getImgName('example')),
imageUrl(getImgName('listBt')),
imageUrl(getImgName('rankBt')), imageUrl(getImgName('rankBt')),
imageUrl(getImgName('rewardBt')), imageUrl(getImgName('rewardBt')),
imageUrl('rankingBg'), imageUrl('rankingBg'),
imageUrl('timeBg'), imageUrl('timeBg'),
imageUrl('rankItemBg'), imageUrl('rankItemBg'),
imageUrl('rewardTop1Bg'),
imageUrl('rewardTop2Bg'),
imageUrl('rewardTop3Bg'),
imageUrl(getImgName('inviteFriendsBt')), imageUrl(getImgName('inviteFriendsBt')),
imageUrl('rankItemBg'),
imageUrl(getImgName('helpInfo')), imageUrl(getImgName('helpInfo')),
imageUrl(getImgName('enterCodeBg')), imageUrl(getImgName('enterCodeBg')),
imageUrl(getImgName('confirmBt')),
imageUrl(getImgName('incomeListBg')), imageUrl(getImgName('incomeListBg')),
imageUrl(getImgName('weekRewardBg')),
] ]
await preloadImages(criticalImages) await preloadImages(criticalImages)
@ -1486,6 +1673,7 @@ const initData = async () => {
getBindingUserRewards(), // getBindingUserRewards(), //
getRanking(), // getRanking(), //
getOverallList(), //
getRewardsAndGifts(), // getRewardsAndGifts(), //
getRechargeRewards(), // getRechargeRewards(), //
]) ])
@ -1543,7 +1731,7 @@ onUnmounted(() => {
} }
.timeBox { .timeBox {
margin-top: 1vw; // margin-top: 1vw;
width: 80%; width: 80%;
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
@ -1552,7 +1740,7 @@ onUnmounted(() => {
.timeText { .timeText {
color: #fff; color: #fff;
font-weight: 590; font-weight: 590;
font-size: 2em; font-size: 1.7em;
} }
.timeGap { .timeGap {