aslan-h5/src/views/Invitation/inviteNewUser.vue

1908 lines
57 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/Invitation/InviteToRegister.vue -->
<template>
<div class="fullPage">
<!-- 预加载状态 -->
<div v-if="isLoading" class="loading-container">
<!-- 页面背景 -->
<BackgroundLayer :backgroundImages="[imageUrl('bg1New'), imageUrl('bg2'), imageUrl('bg3')]" />
<!-- 加载动画 -->
<LoadingContent>{{ $t('loading') }}...</LoadingContent>
</div>
<!-- 主要内容 -->
<div v-else style="width: 100vw; min-height: 100vh; overflow: hidden; position: relative">
<!-- 页面背景 -->
<BackgroundLayer :backgroundImages="[imageUrl('bg1New'), imageUrl('bg2'), imageUrl('bg3')]" />
<!-- 头部导航组件 -->
<div style="position: absolute; top: 0; left: 0; width: 100%">
<GeneralHeader
:isHomePage="true"
:showHelp="true"
:backImg="imgUrl"
:title="t('invitation_to_register')"
@help="helpInfoShow = true"
/>
</div>
<!-- 确认邀请码 -->
<div class="leftBt">
<!-- 打开输入邀请码 -->
<itemCenter
v-if="leftBtType === 'enterCode'"
style="width: 40%; min-height: 15.63vw"
:imgUrl="imageUrl('BtBg')"
:contentStyle="`direction: ltr;justify-content: center;inset: 1vw 6vw 0 0.5vw;`"
@click="enterCodeShow = true"
>
<div :class="['enter', `enter_${currentLangType}`]">{{ t('enter_invitation_code') }}</div>
</itemCenter>
<!-- <itemCenter
style="width: 40%; min-height: 15.63vw"
:imgUrl="imageUrl('BtBg')"
:contentStyle="`direction: ltr;justify-content: center;inset: 1vw 6vw 0 0.5vw;`"
@click="enterCodeShow = true"
>
<div :class="['enter', `enter_${currentLangType}`]">{{ t('enter_invitation_code') }}</div>
</itemCenter> -->
<!-- 前往邀请人信息页 -->
<itemCenter
v-else-if="leftBtType === 'privateChat'"
style="width: 40%; min-height: 15.63vw"
:imgUrl="imageUrl('BtBg')"
:contentStyle="`direction: ltr;justify-content: center;inset: 1vw 6vw 0 0.5vw;`"
@click="gotoPrivateChat(myInviter.inviterInfo?.userId)"
>
<div :class="['contact', `contact_${currentLangType}`]">
{{ t('contact_your_inviter') }}
</div>
</itemCenter>
<!-- <itemCenter
style="width: 40%; min-height: 15.63vw"
:imgUrl="imageUrl('BtBg')"
:contentStyle="`direction: ltr;justify-content: center;inset: 1vw 6vw 0 0.5vw;`"
@click="gotoPrivateChat(myInviter.inviterInfo?.userId)"
>
<div :class="['contact', `contact_${currentLangType}`]">
{{ t('contact_your_inviter') }}
</div>
</itemCenter> -->
</div>
<!-- 主体内容 -->
<div
style="
padding-top: 130vw;
display: flex;
flex-direction: column;
gap: 2vw;
"
>
<!-- 我的邀请码 -->
<itemCenter
style="min-height: 141vw"
:imgUrl="imageUrl(getImgName('myCode'))"
:contentStyle="`padding: 111vw 10vw 17vw;flex-direction: column;justify-content: flex-start;gap: 0vw;`"
>
<!-- 邀请码 -->
<div
style="
width: 90%;
height: 12vw;
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
"
>
<div style="font-weight: 600; font-size: 0.9em">{{ t('my_invitation_code') }}</div>
<div style="font-weight: 590; font-size: 1.1em">
{{ myInviteInfo.inviteCode || '' }}
</div>
<img
v-if="myInviteInfo.inviteCode"
v-smart-img
:src="imageUrl('copy')"
alt=""
style="display: block; width: 1.5em; object-fit: cover"
@click="copyCode(myInviteInfo.inviteCode || '')"
/>
</div>
<!-- 提示 -->
<div
style="
flex: 1;
min-height: 0;
width: 95%;
display: flex;
justify-content: center;
align-items: center;
"
>
<div style="font-size: 0.7em; font-weight: 510; color: #e9e9e9">
{{ t('copy_invitation_code_tip') }}
</div>
</div>
</itemCenter>
<!-- 模块切换按钮 -->
<div
style="
min-height: 22.07vw;
display: flex;
justify-content: space-around;
align-items: center;
"
>
<!-- 收益模块按钮 -->
<div style="width: 40%; position: relative; min-height: max-content">
<img
v-smart-img.noFade
:src="imageUrl(getImgName('incomeBtActive'))"
alt=""
style="display: block; width: 100%"
:style="{ opacity: showModule === 'income' ? 1 : 0 }"
@click="showModule = 'income'"
/>
<img
v-smart-img.noFade
:src="imageUrl(getImgName('incomeBt'))"
alt=""
style="display: block; width: 100%; position: absolute; bottom: 0; left: 0"
:style="{ opacity: showModule === 'income' ? 0 : 1 }"
@click="showModule = 'income'"
/>
</div>
<!-- 排行榜模块按钮 -->
<div style="width: 40%; position: relative">
<img
v-smart-img.noFade
:src="imageUrl(getImgName('earningsRankingBtActive'))"
alt=""
style="display: block; width: 100%"
:style="{ opacity: showModule === 'ranking' ? 1 : 0 }"
@click="showModule = 'ranking'"
/>
<img
v-smart-img.noFade
:src="imageUrl(getImgName('earningsRankingBt'))"
alt=""
style="display: block; width: 100%; position: absolute; bottom: 0; left: 0"
:style="{ opacity: showModule === 'ranking' ? 0 : 1 }"
@click="showModule = 'ranking'"
/>
</div>
</div>
<!-- 收益模块 -->
<div
v-show="showModule == 'income'"
style="display: flex; flex-direction: column; gap: 2vw; padding-bottom: 37vw"
>
<!-- 收入展示 -->
<itemCenter
style="min-height: 100vw"
:imgUrl="imageUrl(getImgName('incomeBg'))"
:contentStyle="`padding: 44vw 8vw 18vw 7vw;display:grid;grid-template-columns: repeat(2, 1fr);gap: 4vw;`"
>
<!-- 更多按钮 -->
<div
style="
position: absolute;
z-index: 2;
width: 22vw;
height: 10vw;
top: 31vw;
right: 6vw;
"
@click="incomeShow = true"
></div>
<!-- 总邀请人数 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('total_invitations') }}</div>
<div style="font-weight: 600; font-size: 1.1em">
{{ myInviteIncome.validInviteCount || 0 }}
</div>
</div>
<!-- 今日邀请人数 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('todays_invitation') }}</div>
<div style="font-weight: 600; font-size: 1.1em">
{{ myInviteIncome.todayInviteCount || 0 }}
</div>
</div>
<!-- 总收入 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">
{{ t('invitation_total_income') }}
</div>
<div style="display: flex; align-items: center">
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em"
/>
<div style="font-weight: 600; font-size: 1.1em; padding-top: 1vw">
{{ myInviteIncome.totalIncome || 0 }}
</div>
</div>
</div>
<!-- 今日收入 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('todays_income') }}</div>
<div style="display: flex; align-items: center">
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em"
/>
<div style="font-weight: 600; font-size: 1.1em; padding-top: 1vw">
{{ myInviteIncome.todayIncome || 0 }}
</div>
</div>
</div>
</itemCenter>
<!-- 流程展示 -->
<img
v-smart-img
:src="imageUrl(getImgName('example'))"
alt=""
style="position: relative; z-index: 2; display: block; width: 100%; object-fit: cover"
/>
</div>
<!-- 排行榜模块 -->
<div v-show="showModule == 'ranking'" style="position: relative">
<!-- 标签页按钮 -->
<div
style="
width: 100vw;
min-height: 15vw;
display: flex;
justify-content: center;
align-items: center;
gap: 13vw;
"
>
<!-- 总榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rankAll')">
<img
v-smart-img
:src="imageUrl(getImgName('listBt'))"
alt=""
:class="{
'grayscale-container': !rankAllShow,
}"
style="width: 100%; display: block; object-fit: cover"
/>
</div>
<!-- 周榜栏目按钮 -->
<div style="width: 35vw; min-width: 0" @click="changeTag('rankWeek')">
<img
v-smart-img
:src="imageUrl(getImgName('rankBt'))"
alt=""
:class="{
'grayscale-container': !rankWeekShow,
}"
style="width: 100%; display: block; object-fit: cover"
/>
</div>
</div>
<!-- 总榜 -->
<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:2vw`"
>
<!-- 列表 -->
<div
style="
flex: 1;
min-height: 0;
width: 100%;
display: flex;
flex-direction: column;
gap: 4px;
"
>
<!-- 列表项 -->
<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 < 10"
:rootMargin="'100px'"
:show="rankAllShow"
@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/Azizi/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 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
style="
flex: 1;
min-height: 0;
width: 100%;
display: flex;
flex-direction: column;
gap: 4px;
"
>
<!-- 列表项 -->
<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 < 10"
:rootMargin="'100px'"
:show="rankWeekShow"
@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/Azizi/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 style="height: 30vw"></div>
</div>
</div>
</div>
<!-- 邀请按钮 -->
<div
style="
width: 100%;
position: fixed;
bottom: 5vw;
z-index: 3;
display: flex;
justify-content: center;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
touch-action: manipulation;
"
@click="handleInviteClick"
@touchend="handleInviteClick"
>
<img
v-show="showModule == 'income'"
v-smart-img
:src="imageUrl(getImgName('inviteFriendsBt'))"
alt=""
style="display: block; width: 90%; object-fit: cover; pointer-events: none"
/>
</div>
<!-- 我的排名 -->
<itemCenter
v-show="showModule == 'ranking' && rankWeekShow"
style="min-height: 25.33vw; position: fixed; bottom: 0; z-index: 3"
:imgUrl="imageUrl('rankItemBg')"
:contentStyle="`padding: 0 7vw`"
>
<!-- 基本信息 -->
<div
style="
flex: 1;
min-width: 0;
display: flex;
justify-content: space-around;
align-items: center;
gap: 8px;
"
>
<!-- 排名 -->
<div style="color: #ffe601; font-weight: 700">
{{ myRanking.rank || 999 }}
</div>
<!-- 头像 -->
<img
:src="myRanking.avatar || ''"
alt=""
style="
display: block;
width: 15vw;
aspect-ratio: 1/1;
border-radius: 50%;
object-fit: cover;
"
@error="handleAvatarImageError"
/>
<!-- 名称 -->
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column">
<div
style="
color: #fff;
font-weight: 860;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
class="UserNickname"
>
{{ myRanking.nickname }}
</div>
</div>
</div>
<!-- 贡献值 -->
<div
style="
width: auto;
min-width: 0;
display: flex;
align-items: center;
"
>
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em; aspect-ratio: 1/1; object-fit: cover"
/>
<div style="font-weight: 700">
{{ myRanking.quantity || 0 }}
</div>
</div>
</itemCenter>
<!-- 弹窗遮罩层 -->
<maskLayer :maskLayerShow="maskLayerShow" @click="closedPopup">
<!-- 帮助模块 -->
<div v-show="helpInfoShow" style="margin: 20% 0; position: relative" @click.stop>
<img
v-smart-img
:src="imageUrl(getImgName('helpInfo'))"
alt=""
width="100%"
style="display: block"
/>
</div>
<!-- 输入邀请码模块 -->
<div
v-show="enterCodeShow"
style="
width: 100vw;
padding: 30vw 0 10vw;
display: flex;
justify-content: center;
align-items: center;
"
@click="closedPopup"
>
<itemCenter
style="width: 100vw; min-height: 240.66vw"
:imgUrl="imageUrl(getImgName('enterCodeBg'))"
:contentStyle="`padding: 31.5vw 6vw 10vw;display: flex;flex-direction: column;justify-content: flex-start;`"
@click.stop
>
<!-- 邀请码 -->
<div class="bindingUserCode">
<!-- 输入框 -->
<input
v-model="invitationCode"
type="text"
style="
width: 60vw;
min-width: 0;
align-self: stretch;
color: white;
font-weight: 510;
padding: 4px 8px;
border: none;
outline: none;
background-color: transparent;
"
@keyup.enter="confirmInvitationCode"
/>
<!-- 按钮 -->
<img
:src="imageUrl(getImgName('confirmBt'))"
alt=""
style="display: block; width: 16vw; object-fit: contain"
@click="confirm"
/>
</div>
<!-- 邀请奖励 -->
<div
style="
width: 85vw;
height: 28vw;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.3vw;
"
:class="['inviteReward', `inviteReward_${currentLangType}`]"
>
<div
v-for="(reward, index) in bindingUserRewards"
style="align-self: stretch; display: flex; flex-direction: column"
>
<!-- 奖励图 -->
<div
style="
width: 100%;
min-width: 0;
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="
width: 100%;
min-width: 0;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
"
>
{{ showDetail(reward) }}
</div>
</div>
</div>
<!-- 充值奖励 -->
<div
style="
flex: 1;
min-height: 0;
width: 85vw;
display: flex;
flex-direction: column;
"
:class="['rechargeReward', `rechargeReward_${currentLangType}`]"
>
<div
v-for="(Rewards, top) in rechargeRewards"
style="width: 100%; display: flex; flex-direction: column; gap: 18vw"
>
<div style="width: 100%; height: 30vw; display: flex; gap: 12vw">
<div
v-for="reward in Rewards"
style="
flex: 1;
min-width: 0;
height: 100%;
display: flex;
flex-direction: column;
"
>
<!-- 奖励图 -->
<div
style="
width: 100%;
min-width: 0;
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="
width: 100%;
min-width: 0;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
"
>
{{ showDetail(reward) }}
</div>
</div>
</div>
</div>
</div>
</itemCenter>
</div>
<!-- 收益&列表 -->
<div
v-show="incomeShow"
style="
width: 100vw;
padding: 25vw 0 10vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
"
@click="closedPopup"
>
<!-- 收益&列表 -->
<itemCenter
style="min-height: 163.33vw"
:imgUrl="imageUrl(getImgName('incomeListBg'))"
:contentStyle="`padding: 37vw 6.5vw 10vw 5.5vw;flex-direction: column;gap: 4vw;justify-content: flex-start;`"
@click.stop
>
<!-- 收益 -->
<div
style="
width: 95%;
height: 37vw;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 5vw;
"
>
<!-- 总邀请人数 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('total_invitations') }}</div>
<div style="font-weight: 600; font-size: 1.1em">
{{ myInviteIncome.validInviteCount || 0 }}
</div>
</div>
<!-- 今日邀请人数 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('todays_invitation') }}</div>
<div style="font-weight: 600; font-size: 1.1em">
{{ myInviteIncome.todayInviteCount || 0 }}
</div>
</div>
<!-- 总收入 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">
{{ t('invitation_total_income') }}
</div>
<div style="display: flex; align-items: center">
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em"
/>
<div style="font-weight: 600; font-size: 1.1em; padding-top: 1vw">
{{ myInviteIncome.totalIncome || 0 }}
</div>
</div>
</div>
<!-- 今日收入 -->
<div
style="
align-self: stretch;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 2vw;
"
>
<div style="font-weight: 700; font-size: 0.9em">{{ t('todays_income') }}</div>
<div style="display: flex; align-items: center">
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1.5em"
/>
<div style="font-weight: 600; font-size: 1.1em; padding-top: 1vw">
{{ myInviteIncome.todayIncome || 0 }}
</div>
</div>
</div>
</div>
<!-- 列表 -->
<div
style="
flex: 1;
min-height: 0;
width: 100%;
border-radius: 8px;
background: rgba(194, 174, 232, 0.2);
backdrop-filter: blur(1px);
padding: 12px;
display: flex;
flex-direction: column;
gap: 4px;
"
>
<!-- 头部 -->
<div style="width: 100%; display: flex; align-items: center">
<!-- user项 -->
<div style="flex: 1; font-weight: 590; font-size: 0.8em; text-align: center">
{{ t('users') }}
</div>
<!-- 时间项 -->
<div
style="
flex: 1;
font-weight: 590;
display: flex;
justify-content: space-between;
align-items: center;
"
>
<!-- 分割线 -->
<div
style="
width: 1px;
height: 16px;
background: linear-gradient(
rgba(217, 217, 217, 0) 0%,
#d9d9d9 50%,
rgba(217, 217, 217, 0) 100%
);
"
></div>
<div style="font-weight: 590; font-size: 0.8em; text-align: center">
{{ t('unbinding_time') }}
</div>
<!-- 分割线 -->
<div
style="
width: 1px;
height: 16px;
background: linear-gradient(
rgba(217, 217, 217, 0) 0%,
#d9d9d9 50%,
rgba(217, 217, 217, 0) 100%
);
"
></div>
</div>
<!-- 收入项 -->
<div
style="
flex: 1;
font-weight: 590;
text-align: end;
font-size: 0.8em;
text-align: center;
"
>
{{ t('prowide_income') }}
</div>
</div>
<!-- 列表项 -->
<div class="overflow-y-auto" style="align-self: stretch; width: 100%">
<div
v-for="user in myInviteUsers"
style="width: 100%; display: flex; align-items: center"
>
<!-- ID -->
<div style="flex: 1; font-weight: 590; font-size: 0.8em; text-align: center">
{{ t('user_id_prefix') }}{{ user.invitedUserAccount || '-' }}
</div>
<!-- 时间项 -->
<div
style="
flex: 1;
font-weight: 590;
display: flex;
justify-content: space-between;
align-items: center;
"
>
<div
style="
width: 1px;
height: 16px;
background: linear-gradient(
rgba(217, 217, 217, 0) 0%,
#d9d9d9 50%,
rgba(217, 217, 217, 0) 100%
);
"
></div>
<div style="font-weight: 590; font-size: 0.8em">
{{ user.remainingDays || 0 }}{{ t('day_unit') }}
</div>
<div
style="
width: 1px;
height: 16px;
background: linear-gradient(
rgba(217, 217, 217, 0) 0%,
#d9d9d9 50%,
rgba(217, 217, 217, 0) 100%
);
"
></div>
</div>
<!-- 收入项 -->
<div
style="
flex: 1;
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
"
>
<img
v-smart-img
src="/src/assets/icon/Azizi/coin.png"
alt=""
style="display: block; width: 1em"
/>
<div style="color: #ffb627; font-size: 1em; font-weight: 590">
{{ user.provideIncome || 0 }}
</div>
</div>
</div>
</div>
</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>
<!-- 提示弹窗 -->
<div
v-show="tipShow"
style="position: fixed; top: 50vh; display: flex; justify-content: center; width: 100vw"
>
<div
style="
padding: 12px;
border-radius: 8px;
background: rgba(0, 0, 0, 0.4);
font-weight: 600;
"
>
{{ t('copied_successfully') }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useLangStore } from '@/stores/lang'
import { viewUserInfo, gotoPrivateChat, openAppComponent } from '@/utils/appBridge.js'
import { showError, showWarning, showSuccess } from '@/utils/toast.js'
import { useClipboard } from '@vueuse/core'
import { connectToApp } from '@/utils/appConnector.js'
import { getPngUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/image/imagePreloader.js'
import { handleAvatarImageError, handleRewardImageError } from '@/utils/image/imageHandler.js'
import { formatRewardDisplay } from '@/utils/rewardFormatter.js'
import {
getRankingListAndMyRanking, // 获取排行榜和当前用户排名
getThisWeekRewardsAndGifts, // 获取本周奖励和礼物
getOverallRanking, // 获取总榜
} from '@/api/activity.js'
import {
getMyInviteCode, // 获取我的邀请码
bindInviteCode, // 绑定邀请码
getMyInviteIncome, // 获取收益统计
getMyInviteUsers, // 有效邀请用户列表
apiGetBindingUserRewards, // 获取绑定用户奖励
getMyInviter, // 获取我的邀请人信息
} from '@/api/invitation.js'
import BackgroundLayer from '@/components/BackgroundLayer.vue'
import GeneralHeader from '@/components/GeneralHeader.vue'
import itemCenter from '@/components/itemCenter.vue'
import maskLayer from '@/components/MaskLayer.vue'
const imgUrl = new URL('/src/assets/icon/Azizi/arrowBack.png', import.meta.url).href
const { t } = useI18n()
const langStore = useLangStore()
// 当前语言类型
const currentLangType = computed(() => {
return langStore.selectedLang?.type || 'en'
})
// 根据语言获取图片名
const getImgName = (filename) => {
return currentLangType.value === 'en' ? filename : `${filename}_${currentLangType.value}`
}
// 获取OSS图片URL的函数
const imageUrl = (filename) => getPngUrl('invitation/inviteNewUser/', filename)
const { copy, isSupported } = useClipboard()
// 预加载状态
const isLoading = ref(true)
const invitationCode = ref('') //邀请码
const myInviteInfo = ref({}) //我的邀请信息
const myInviter = ref({}) //我的邀请人信息
const myInviteIncome = ref({}) //邀请用户收益统计
const myInviteUsers = ref([]) //邀请用户列表
const bindingUserRewards = ref([]) //绑定用户奖励
// 充值奖励
const rechargeRewards = ref(Array(3))
// 排行奖励
const rankingRewards = ref([])
const Ranking = ref([]) // 原始排行榜
const myRanking = ref({}) // 我的排名
const RankingLoadmore = ref(null) //触底模块
const rankingPageNo = ref(1) //分页页码
const rankingAdd = ref([]) //加载排行榜项
const OverallRanking = ref([]) // 总榜
// 完整排行榜
const rankingTotal = computed(() => {
if (rankAllShow.value) {
return OverallRanking.value
}
if (rankWeekShow.value) {
// return [...Ranking.value, ...rankingAdd.value]
return Ranking.value
}
})
const showModule = ref('income') //显示模块
const rankAllShow = ref(true) //总榜显示
const rankWeekShow = ref(false) //周榜显示
const rewardShow = ref(false) //前三奖励显示
// 栏目切换
const changeTag = (tag) => {
switch (tag) {
case 'rankWeek':
rankWeekShow.value = true
rankAllShow.value = false
break
case 'rankAll':
rankWeekShow.value = false
rankAllShow.value = true
break
}
}
// 弹窗展示
const helpInfoShow = ref(false) //帮助弹窗
const enterCodeShow = ref(false) //交易弹窗
const incomeShow = ref(false) //收益详情弹窗
const tipShow = ref(false) //提示弹窗
// 遮罩层展示
const maskLayerShow = computed(() => {
return helpInfoShow.value || enterCodeShow.value || incomeShow.value || rewardShow.value
})
// 关闭弹窗
const closedPopup = () => {
helpInfoShow.value = false
enterCodeShow.value = false
incomeShow.value = false
rewardShow.value = false
}
// 倒计时相关数据
const WDays = ref(0)
const WHours = ref(0)
const WMinutes = ref(0)
const WSeconds = ref(0)
let countdownTimer = null
// 按条件展示按钮
const leftBtType = computed(() => {
// 数据还未加载完成
if (!myInviter.value || Object.keys(myInviter.value).length === 0) {
return null
}
// 优先级1: 如果有邀请人信息且有userId则显示私聊按钮
if (myInviter.value.inviterInfo?.userId) {
return 'privateChat'
}
// 优先级2: 如果没有过期且没有邀请人,则显示输入邀请码按钮
if (!myInviter.value.myInfo?.expired && !myInviter.value.inviterInfo) {
return 'enterCode'
}
// 其他情况不显示按钮
return null
})
// 获取下周一对应的时间戳
const getNextWeekInBeijing = () => {
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(getNextWeekInBeijing()) // 闭包保存目标时间 (核心修正)
// 格式化时间
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)
WDays.value = Math.floor(totalSeconds / (24 * 3600))
WHours.value = formatTime(Math.floor((totalSeconds % (24 * 3600)) / 3600))
WMinutes.value = formatTime(Math.floor((totalSeconds % 3600) / 60))
WSeconds.value = formatTime(Math.floor(totalSeconds % 60))
}
// 启动倒计时
const startCountdown = () => {
getCountdown() // 立即执行一次周倒计时
countdownTimer = setInterval(getCountdown, 1000)
}
// 格式化奖励的展示信息
const showDetail = (reward) => {
let showamount = ['GOLD', 'DIAMOND', 'GIFT', 'FRAGMENTS']
if (showamount.includes(reward.type)) {
return reward.content
} else if (reward.type === 'DOLLARS') {
return `$${reward.content}`
} else {
return `${reward.quantity}${t('day_unit')}`
}
}
// 处理邀请按钮点击
const handleInviteClick = () => {
// 确保数据已加载
if (!myInviteInfo.value?.inviteCode) {
showError(t('please_wait_loading'))
return
}
openAppComponent(
'shareDrawer:' + t('share_invitation_message', { code: myInviteInfo.value?.inviteCode }),
)
}
// 复制到剪贴板(原生方法)
const copyCode = (text) => {
if (isSupported.value) {
copy(text)
} else {
// 降级方案
const textArea = document.createElement('textarea')
textArea.value = text
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
}
tipShow.value = true
setTimeout(() => {
tipShow.value = false
}, 2000)
}
// 更改邀请码
const confirmInvitationCode = () => {
if (!invitationCode.value.trim()) {
showWarning(t('please_enter_valid_invitation_code'))
return
}
}
// 获取我的邀请码
const apiGetMyInviteCode = async () => {
const resCode = await getMyInviteCode()
if (resCode.status && resCode.body) {
myInviteInfo.value = resCode.body
}
}
// 获取我的邀请人信息
const apiGetMyInviter = async () => {
const resInviter = await getMyInviter()
if (resInviter.status && resInviter.body) {
myInviter.value = resInviter.body || {}
}
}
// 绑定邀请码
const confirm = async () => {
if (!invitationCode.value.trim()) {
showWarning(t('please_enter_valid_invitation_code'))
return
}
let data = { inviteCode: invitationCode.value.trim(), inviteType: 'REGISTER' }
try {
const resBind = await bindInviteCode(data)
if (resBind.status) {
showSuccess(t('invitation_code_bound_successfully'))
apiGetMyInviter() //刷新我的邀请人信息
} else {
showError(t('invitation_code_binding_failed'))
}
invitationCode.value = ''
enterCodeShow.value = false
} catch (error) {
showError(error.errorMsg)
}
}
// 获取收益统计
const apiGetMyInviteIncome = async () => {
const resIncome = await getMyInviteIncome()
if (resIncome.status && resIncome.body) {
myInviteIncome.value = resIncome.body
}
}
// 有效邀请用户列表
const apiGetMyInviteUsers = async () => {
const resUserList = await getMyInviteUsers()
if (resUserList.status && resUserList.body) {
myInviteUsers.value = resUserList.body
// myInviteUsers.value = Array(2).fill(resUserList.body).flat()
// myInviteUsers.value = []
}
}
// 绑定用户奖励
const getBindingUserRewards = async () => {
let data = ['1983474358707736577']
const resAwardPool = await apiGetBindingUserRewards(data)
if (resAwardPool.status && resAwardPool.body) {
bindingUserRewards.value = resAwardPool.body['1983474358707736577']
}
}
// 获取排行榜
const getRanking = async () => {
let data = {
activityType: 14,
}
const resRanking = await getRankingListAndMyRanking(data)
if (resRanking.status && resRanking.body) {
myRanking.value = resRanking.body?.currentUserRank //我的排名信息
Ranking.value = resRanking.body?.rankingList
} else {
Ranking.value = []
myRanking.value = {}
}
}
// 获取总榜
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')
if (resRewardsAndGifts.status && resRewardsAndGifts.body) {
rankingRewards.value = resRewardsAndGifts.body.butOneRewards
}
}
// 获取充值奖励
const getRechargeRewards = async () => {
let RewardsId = [['2029448725407711234'], ['2029449081176965121'], ['2029449364032438273']]
RewardsId.forEach(async (id, index) => {
const resRechargeRewards = await apiGetBindingUserRewards(id)
if (resRechargeRewards.status && resRechargeRewards.body) {
console.log('resRechargeRewards.body.id', resRechargeRewards.body[`${id}`])
rechargeRewards.value[index] = resRechargeRewards.body[`${id}`]
}
})
}
// 预加载关键图片
const preloadCriticalImages = async () => {
const criticalImages = [
imageUrl('bg1New'),
imageUrl('bg2'),
imageUrl('bg3'),
imageUrl('BtBg'),
imageUrl(getImgName('myCode')),
imageUrl('copy'),
imageUrl(getImgName('incomeBtActive')),
imageUrl(getImgName('incomeBt')),
imageUrl(getImgName('earningsRankingBtActive')),
imageUrl(getImgName('earningsRankingBt')),
imageUrl(getImgName('incomeBg')),
imageUrl(getImgName('example')),
imageUrl(getImgName('listBt')),
imageUrl(getImgName('rankBt')),
imageUrl(getImgName('rewardBt')),
imageUrl('rankingBg'),
imageUrl('timeBg'),
imageUrl('rankItemBg'),
imageUrl(getImgName('inviteFriendsBt')),
imageUrl(getImgName('helpInfo')),
imageUrl(getImgName('enterCodeBg')),
imageUrl(getImgName('confirmBt')),
imageUrl(getImgName('incomeListBg')),
imageUrl(getImgName('weekRewardBg')),
]
await preloadImages(criticalImages)
}
// 页面初始化数据
const initData = async () => {
await Promise.all([
apiGetMyInviteCode(), // 获取我的邀请码
apiGetMyInviter(), // 获取我的邀请人信息
apiGetMyInviteIncome(), // 获取收益统计
apiGetMyInviteUsers(), // 有效邀请用户列表
getBindingUserRewards(), // 绑定用户奖励
getRanking(), //获取排行榜
getOverallList(), //获取总榜
getRewardsAndGifts(), //获取每周奖励列表
getRechargeRewards(), //获取充值奖励
])
}
// 完成预加载
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() // 完成预加载
})
}
onMounted(() => {
startCountdown() //开启倒计时
connectToAppHandler()
})
onUnmounted(() => {
// 销毁计时器
if (countdownTimer) {
clearInterval(countdownTimer)
countdownTimer = null
}
})
</script>
<style lang="scss" scoped>
* {
color: white;
}
.fullPage {
width: 100vw;
min-height: 100vh;
background-color: #c7432d;
position: relative;
}
.grayscale-container {
filter: grayscale(100%) brightness(90%);
}
.timeBox {
// margin-top: 1vw;
width: 80%;
display: flex;
justify-content: space-around;
}
.timeText {
color: #fff;
font-weight: 590;
font-size: 1.7em;
}
.timeGap {
width: 6px;
align-self: stretch;
display: flex;
justify-content: center;
align-items: center;
}
[dir='rtl'] .timeBox {
flex-direction: row-reverse;
}
.overflow-y-auto {
overflow-y: auto;
}
.overflow-y-auto::-webkit-scrollbar {
display: none;
}
.leftBt {
position: absolute;
top: 117vw;
left: 0;
width: 100vw;
direction: ltr;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.bindingUserCode {
width: 100%;
padding-left: 5vw;
padding-right: 5vw;
height: 14vw;
direction: ltr;
display: flex;
justify-content: space-between;
}
.enter {
font-weight: 590;
font-size: 0.7em;
}
.enter_ar {
font-size: 0.9em;
}
.enter_tr {
font-size: 0.8em;
}
.enter_bn {
font-size: 0.9em;
}
.contact {
font-weight: 590;
font-size: 0.6em;
}
.contact_en {
font-size: 0.8em;
}
.contact_tr {
font-size: 0.6em;
}
.inviteReward {
margin-top: 22vw;
}
.inviteReward_bn,
.inviteReward_tr {
margin-top: 19vw;
}
.rechargeReward {
padding: 23.5vw 0 5vw;
gap: 8.8vw;
}
.rechargeReward_bn,
.rechargeReward_tr {
padding: 24.5vw 0 5vw;
gap: 10vw;
}
/* 添加加载动画样式 */
.loading-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #666;
overflow: hidden;
position: relative;
}
@media screen and (max-width: 360px) {
* {
font-size: 12px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 14px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
}
@media screen and (min-width: 1024px) {
* {
font-size: 32px;
}
}
// [dir='rtl'] .leftBt {
// align-items: flex-end;
// }
// [dir='rtl'] .bindingUserCode {
// padding-left: 5vw;
// padding-right: 3.5vw;
// }
</style>