1569 lines
45 KiB
Vue
1569 lines
45 KiB
Vue
<template>
|
||
<div class="fullPage">
|
||
<!-- 状态栏占位区域(仅在APP中显示) -->
|
||
<div v-if="isInAppEnvironment" style="height: 30px"></div>
|
||
<div style="padding: 10px 10px 10px">
|
||
<!-- 页面标题 -->
|
||
<img :src="images.pageTitle" alt="" width="100%" style="display: block" />
|
||
|
||
<!-- 弹幕 -->
|
||
<Barrage class="barrage-container" style="width: 100vw" :barrageList="barrageList"></Barrage>
|
||
|
||
<!-- 模块切换按钮 -->
|
||
<div style="display: flex; justify-content: space-around">
|
||
<div style="width: 30%" @click="handleBt('Rank')">
|
||
<img :src="rankShow ? images.rankingBtActive : images.rankingBt" alt="" width="100%" />
|
||
</div>
|
||
<div style="width: 30%" @click="handleBt('Income')">
|
||
<img :src="incomeShow ? images.incomeBtActive : images.incomeBt" alt="" width="100%" />
|
||
</div>
|
||
<div style="width: 30%" @click="handleBt('Lottery')">
|
||
<img :src="lotteryShow ? images.lotteryBtActive : images.lotteryBt" alt="" width="100%" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 排行榜模块 -->
|
||
<div
|
||
v-if="rankShow"
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
|
||
display: flex;
|
||
padding: 12px;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
margin-bottom: 18vw;
|
||
"
|
||
>
|
||
<div style="font-weight: 590">{{ t('ranking') }}</div>
|
||
<div
|
||
v-for="user in ranking"
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
backdrop-filter: blur(32px);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px;
|
||
"
|
||
>
|
||
<div style="display: flex; align-items: center; gap: 4px; width: 80%">
|
||
<div style="font-weight: 700">{{ user.rank }}</div>
|
||
<img
|
||
:src="user.avatar || ''"
|
||
:alt="user.nickname || ''"
|
||
style="
|
||
display: block;
|
||
width: 11vw;
|
||
border-radius: 50%;
|
||
aspect-ratio: 1/1;
|
||
object-fit: cover;
|
||
"
|
||
@error="defaultAvatarUrl"
|
||
/>
|
||
<div style="width: 60%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
|
||
{{ user.nickname || '' }}
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 4px">
|
||
<img
|
||
src="/src/assets/icon/dollar.png"
|
||
alt=""
|
||
style="display: block; object-fit: cover; width: 6vw; aspect-ratio: 1/1"
|
||
/>
|
||
<div style="color: #2df860; font-weight: 500">{{ user.totalAmount }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 提现模块 -->
|
||
<div v-if="incomeShow" style="width: 100%; display: flex; flex-direction: column; gap: 3vw">
|
||
<!-- 个人信息 -->
|
||
<div
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
backdrop-filter: blur(32px);
|
||
|
||
padding: 12px 12px 12px;
|
||
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
|
||
position: relative;
|
||
"
|
||
>
|
||
<img
|
||
src="/src/assets/icon/helpWhite.png"
|
||
class="help-btn"
|
||
alt=""
|
||
@click="helpShow = true"
|
||
/>
|
||
<img
|
||
:src="userInfo.userAvatar || ''"
|
||
:alt="userInfo.userNickname || ''"
|
||
width="15%"
|
||
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
|
||
@error="defaultAvatarUrl"
|
||
/>
|
||
<div
|
||
style="
|
||
width: 85%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
gap: 4px;
|
||
"
|
||
>
|
||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||
<div
|
||
style="
|
||
max-width: 40%;
|
||
font-weight: 500;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
"
|
||
>
|
||
{{ userInfo.userNickname || '' }}
|
||
</div>
|
||
<div style="font-weight: 600">
|
||
{{ t('current_earnings', { amount: currentAmount.availableAmount }) }}
|
||
</div>
|
||
</div>
|
||
<!-- <div style="text-align: end; font-weight: 400; font-size: 0.8em">
|
||
Only $9 left to withdraw $10.00
|
||
</div> -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 抽屉 -->
|
||
<div
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
backdrop-filter: blur(32px);
|
||
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
|
||
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: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
padding: 12px;
|
||
"
|
||
>
|
||
<!-- 基本信息 -->
|
||
<div style="display: flex; align-items: center">
|
||
<!-- 头像 -->
|
||
<div style="position: relative; width: 50px; margin-right: 12px">
|
||
<img
|
||
:src="selectedPayee.avatar || ''"
|
||
:alt="selectedPayee.name || ''"
|
||
style="width: 100%; object-fit: cover; border-radius: 50%"
|
||
@error="defaultAvatarUrl"
|
||
/>
|
||
</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">
|
||
ID: {{ 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"
|
||
src="/src/assets/icon/host.png"
|
||
alt=""
|
||
width="30%"
|
||
/>
|
||
<img
|
||
v-if="selectedPayee.isAgency"
|
||
src="/src/assets/icon/agency.png"
|
||
alt=""
|
||
width="30%"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
v-if="selectedPayee.hasSalary"
|
||
src="/src/assets/icon/RA.png"
|
||
alt=""
|
||
width="30%"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 - 默认显示 -->
|
||
<div
|
||
v-else
|
||
style="
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
padding: 12px 0;
|
||
"
|
||
>
|
||
<div
|
||
style="
|
||
font-weight: 590;
|
||
padding: 16px;
|
||
|
||
border-radius: 8px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
"
|
||
@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 src="/src/assets/icon/dollar.png" alt="" style="width: 40%" />
|
||
<div style="font-weight: 500; color: #131111">${{ 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: 32px;
|
||
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
|
||
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
|
||
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 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: #131111">${{ 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: 32px;
|
||
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
|
||
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
|
||
class="flipImg"
|
||
src="/src/assets/icon/arrowWhite.png"
|
||
alt=""
|
||
style="width: 1em; display: block"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 抽奖模块 -->
|
||
<div v-if="lotteryShow" style="width: 100%; display: flex; flex-direction: column; gap: 3vw">
|
||
<!-- 抽奖转盘 -->
|
||
<div style="position: relative">
|
||
<img :src="images.turnTable" alt="" width="100%" style="display: block" />
|
||
<div
|
||
style="
|
||
position: absolute;
|
||
inset: 0;
|
||
margin: 11% 0 10.5%;
|
||
padding: 0 8%;
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
grid-template-rows: repeat(3, 1fr);
|
||
gap: 4.5%;
|
||
"
|
||
>
|
||
<div
|
||
v-for="(prize, index) in activity.prizeList"
|
||
style="
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
box-sizing: border-box;
|
||
border-width: 2px;
|
||
border-style: solid;
|
||
"
|
||
:style="[
|
||
getGridPosition(index),
|
||
{ borderColor: activeIndex === index ? '#00ffa3' : 'transparent' },
|
||
]"
|
||
:class="{ 'active-prize': activeIndex === index }"
|
||
>
|
||
<img
|
||
:src="prize.prizeImage || ''"
|
||
:alt="prize.prizeName || ''"
|
||
width="50%"
|
||
style="display: block"
|
||
/>
|
||
<div style="font-size: 0.8em">{{ prize.prizeName }}</div>
|
||
</div>
|
||
|
||
<!-- 按钮 -->
|
||
<div
|
||
style="grid-area: 2 / 2; display: flex; justify-content: center; align-items: center"
|
||
:disabled="isRolling"
|
||
@click="sweepstakes(1)"
|
||
></div>
|
||
</div>
|
||
<!-- 底部饰品 -->
|
||
<div
|
||
style="
|
||
position: absolute;
|
||
bottom: -2vw;
|
||
left: 0;
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
"
|
||
>
|
||
<img
|
||
:src="images.giftLeft"
|
||
alt=""
|
||
width="20%"
|
||
style="display: block; margin-left: -10px"
|
||
/>
|
||
<img
|
||
:src="images.giftRight"
|
||
alt=""
|
||
width="20%"
|
||
style="display: block; margin-right: -5px"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 抽奖按钮 -->
|
||
<div style="display: flex; justify-content: space-around">
|
||
<img
|
||
:src="images.spin1"
|
||
alt=""
|
||
width="40%"
|
||
@click="sweepstakes(1)"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
:src="images.spin10"
|
||
alt=""
|
||
width="40%"
|
||
@click="sweepstakes(10)"
|
||
style="display: block"
|
||
/>
|
||
</div>
|
||
|
||
<!-- 抽奖次数 -->
|
||
<div
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
padding: 12px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
"
|
||
>
|
||
<div style="font-weight: 590">
|
||
{{ t('current_raffle_tickets', { count: rollTimes }) }}
|
||
</div>
|
||
<div style="font-weight: 590; font-size: 0.9em" @click="historyShow = true">
|
||
{{ t('history') }}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 任务列表 -->
|
||
<div
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
|
||
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: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(1, 255, 39, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
display: flex;
|
||
padding: 8px;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<!-- 图标 -->
|
||
<div style="width: 20%">
|
||
<img
|
||
v-if="task.taskType == 1"
|
||
:src="images.talking"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
v-if="task.taskType == 2"
|
||
:src="images.gift"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
v-if="task.taskType == 3"
|
||
:src="images.invite"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block"
|
||
/>
|
||
</div>
|
||
<!-- 内容 -->
|
||
<div style="width: 60%">
|
||
<div>
|
||
<div v-if="task.taskType == 1" style="color: rgba(0, 0, 0, 0.8); font-weight: 590">
|
||
{{ showTarget(task) }}
|
||
</div>
|
||
<div v-else style="color: rgba(0, 0, 0, 0.8); font-weight: 590">
|
||
{{ task.taskName }}
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; align-items: center; gap: 8px">
|
||
<img :src="images.ticket" :alt="t('ticket')" width="15%" style="display: block" />
|
||
<div style="color: #2f0; font-weight: 590">*{{ task.rewardValue }}</div>
|
||
</div>
|
||
</div>
|
||
<!-- 按钮 -->
|
||
<div style="width: 20%">
|
||
<!-- 前往任务 -->
|
||
<img
|
||
v-if="task.taskStatus == 0"
|
||
:src="images.goToTask"
|
||
width="100%"
|
||
style="display: block"
|
||
/>
|
||
<!-- 领取抽奖券 -->
|
||
<img
|
||
v-else-if="task.taskStatus === 1"
|
||
:src="images.receive"
|
||
:alt="t('receive')"
|
||
width="100%"
|
||
style="display: block"
|
||
@click="receiveTaskReward(task.taskCode)"
|
||
/>
|
||
<!-- 已完成 -->
|
||
<img :src="images.done" :alt="t('done')" width="100%" style="display: block" v-else />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 我的排名 -->
|
||
<div
|
||
v-if="rankShow"
|
||
style="
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
z-index: 999;
|
||
width: 100vw;
|
||
padding: 12px;
|
||
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
border-radius: 12px 12px 0 0;
|
||
border-top: 1px solid #77ff87;
|
||
border-right: 1px solid #77ff87;
|
||
border-left: 1px solid #77ff87;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
backdrop-filter: blur(32px);
|
||
"
|
||
>
|
||
<div style="display: flex; align-items: center; gap: 4px; width: 80%">
|
||
<div style="font-weight: 700">{{ userInfo.rank || 999 }}</div>
|
||
<img
|
||
:src="userInfo.userAvatar || ''"
|
||
:alt="userInfo.userNickname || ''"
|
||
style="border-radius: 50%; width: 11vw; aspect-ratio: 1/1; object-fit: cover"
|
||
@error="defaultAvatarUrl"
|
||
/>
|
||
<div style="width: 70%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
|
||
{{ userInfo.userNickname || '' }}
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 4px">
|
||
<img
|
||
src="/src/assets/icon/dollar.png"
|
||
alt=""
|
||
style="display: block; object-fit: cover; width: 6vw"
|
||
/>
|
||
<div style="color: #2df860; font-weight: 500">
|
||
{{ userInfo.totalAmount || 0 }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 弹窗遮罩层 -->
|
||
<maskLayer :maskLayerShow="maskLayerShow">
|
||
<div
|
||
style="
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
"
|
||
@click="closedPopup"
|
||
>
|
||
<!-- 抽奖结果 -->
|
||
<div v-if="resultShow" style="position: relative; width: 90%" @click.stop>
|
||
<img :src="images.rewardBg" alt="" width="100%" style="display: block" />
|
||
<div
|
||
style="
|
||
position: absolute;
|
||
inset: 23% 10% 10%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<div
|
||
style="width: 100%; display: flex; justify-content: space-around; align-items: center"
|
||
>
|
||
<!-- 上一个奖品 -->
|
||
<div style="width: 8%">
|
||
<img
|
||
v-if="result.length > 1 && resultShowIndex > 0"
|
||
:src="images.backGift"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block; object-fit: cover"
|
||
@click="resultShowIndex--"
|
||
/>
|
||
</div>
|
||
<!-- 奖品 -->
|
||
<img
|
||
:src="result[resultShowIndex]?.prize?.prizeImage"
|
||
:alt="result[resultShowIndex]?.prize?.prizeName || ''"
|
||
width="50%"
|
||
style="display: block"
|
||
/>
|
||
<!-- 下一个奖品 -->
|
||
<div style="width: 8%">
|
||
<img
|
||
v-if="result.length > 1 && resultShowIndex + 1 < result.length"
|
||
:src="images.nextGift"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block; object-fit: cover"
|
||
@click="resultShowIndex++"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
style="
|
||
width: 100%;
|
||
text-align: center;
|
||
font-size: 0.9em;
|
||
font-weight: 590;
|
||
background: linear-gradient(0deg, #f3b700 0%, #ffeec6 100%);
|
||
background-clip: text;
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
position: relative;
|
||
"
|
||
>
|
||
{{ t('you_get', { prize: result[resultShowIndex]?.prize?.prizeName }) }}
|
||
<div
|
||
v-if="result.length > 1"
|
||
style="
|
||
position: absolute;
|
||
z-index: 9999;
|
||
inset: 0;
|
||
|
||
padding-right: 8%;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
|
||
font-size: 0.8em;
|
||
font-weight: 590;
|
||
background: linear-gradient(0deg, #f3b700 0%, #ffeec6 100%);
|
||
background-clip: text;
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
"
|
||
>
|
||
{{ resultShowIndex + 1 }} / {{ result.length }}
|
||
</div>
|
||
</div>
|
||
<img
|
||
:src="images.rewardConfirm"
|
||
:alt="t('confirm')"
|
||
width="40%"
|
||
@click="closedPopup"
|
||
style="display: block"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 中奖历史 -->
|
||
<div v-if="historyShow" style="position: relative; width: 90%" @click.stop>
|
||
<img
|
||
src="/src/assets/images/Lottery/historyBg.png"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
src="/src/assets/images/Lottery/cancel.png"
|
||
:alt="t('cancel')"
|
||
class="cancel-bt"
|
||
@click="closedPopup"
|
||
/>
|
||
<div style="position: absolute; inset: 0; padding: 20% 3% 3%">
|
||
<div
|
||
style="
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow-y: auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
"
|
||
class="scrollbar"
|
||
>
|
||
<div
|
||
v-for="(record, index) in myRecords"
|
||
style="
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
|
||
display: flex;
|
||
padding: 12px;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<div style="display: flex; align-items: center; gap: 4px">
|
||
<img
|
||
:src="record.prize.prizeImage || ''"
|
||
:alt="record.prize.prizeName || ''"
|
||
style="width: 10vw; object-fit: cover; display: block; aspect-ratio: 1/1"
|
||
/>
|
||
<div style="font-weight: 590; font-size: 0.9em">
|
||
{{ record.prize.prizeName }}
|
||
</div>
|
||
</div>
|
||
<div style="font-weight: 510; font-size: 0.8em">
|
||
{{ formatUTCCustom(record.drawTime) }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 帮助弹窗 -->
|
||
<div v-if="helpShow" style="position: relative; width: 90%" @click.stop>
|
||
<img :src="images.helpInfo" alt="" width="100%" style="display: block" />
|
||
<div class="close-btn" @click="closedPopup"></div>
|
||
</div>
|
||
</div>
|
||
</maskLayer>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { isInApp } from '@/utils/appBridge.js'
|
||
import { connectToApp } from '@/utils/appConnector.js'
|
||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||
import maskLayer from '@/components/MaskLayer.vue'
|
||
import { formatUTCCustom } from '@/utils/utcFormat.js'
|
||
import { getMemberProfile, getUserIdentity } from '@/api/wallet'
|
||
import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js'
|
||
import { useRouter } from 'vue-router'
|
||
import {
|
||
ranklist, //获取排行榜
|
||
validActivity, // 获取有效活动
|
||
activityDetail, // 获取活动详情
|
||
myTickets, // 获取剩余中奖券
|
||
onceDraw, // 执行单次抽奖
|
||
multiDraw, // 执行连抽
|
||
drawRecords, // 获取中奖记录
|
||
ActTaskList, // 获取任务列表
|
||
receiveTickets, // 领取任务奖励
|
||
winnerHistory, //获取历史中奖用户
|
||
withdrawableAmount, //获取可提现金额
|
||
transferActivityDollar, // 转账活动美金
|
||
exchangeCoin, //兑换代币
|
||
} from '@/api/lottery'
|
||
import Barrage from '@/components/Lottery/Barrage.vue'
|
||
import { setUserInfo } from '@/utils/userStore.js'
|
||
import { showError, showWarning, showInfo, showSuccess } from '@/utils/toast.js'
|
||
import { useI18n } from 'vue-i18n'
|
||
import { setDocumentDirection } from '@/locales/i18n'
|
||
|
||
const { t, locale } = useI18n()
|
||
const router = useRouter()
|
||
|
||
// 监听语言变化并设置文档方向
|
||
locale.value && setDocumentDirection(locale.value)
|
||
|
||
// vite动态导入图片
|
||
const imageModules = import.meta.glob('@/assets/images/Lottery/*.{jpg,png,svg}', {
|
||
eager: true,
|
||
})
|
||
|
||
// 生成文件名映射对象(自动移除路径和扩展名)
|
||
const images = computed(() => {
|
||
const imageMap = {}
|
||
const rtlImageMap = {}
|
||
|
||
// 构建基础映射和RTL映射
|
||
Object.entries(imageModules).forEach(([path, module]) => {
|
||
const fileName = path.split('/').pop().split('.')[0]
|
||
imageMap[fileName] = module.default
|
||
|
||
// 如果是_ar后缀的图片,建立RTL映射
|
||
if (fileName.endsWith('_ar')) {
|
||
const baseName = fileName.slice(0, -3)
|
||
rtlImageMap[baseName] = module.default
|
||
}
|
||
})
|
||
|
||
// 如果是RTL语言(阿拉伯语),优先使用_ar后缀的图片
|
||
if (locale.value === 'ar') {
|
||
// 合并基础图片和_ar图片,_ar图片优先
|
||
return { ...imageMap, ...rtlImageMap }
|
||
}
|
||
|
||
return imageMap
|
||
})
|
||
|
||
// 弹幕数据(示例)
|
||
const barrageList = ref([])
|
||
|
||
// 活动详情
|
||
const activity = ref({}) //活动详情和奖池
|
||
const activityId = ref('') //活动码
|
||
|
||
const userInfo = ref({}) //用户信息
|
||
const userIdentity = ref({}) //用户身份
|
||
|
||
const ranking = ref([]) //奖品排名
|
||
|
||
const activeIndex = ref(-1) // 当前高亮格子
|
||
const isRolling = ref(false) // 抽奖状态
|
||
const rollTimes = ref(0) // 拥有抽奖券量
|
||
const currentAmount = ref({ availableAmount: 0 }) //可提现金额
|
||
const result = ref([]) // 抽奖结果
|
||
const resultShowIndex = ref(0)
|
||
const myRecords = ref([]) // 抽奖结果
|
||
|
||
const isInAppEnvironment = ref(false) // 检测是否在APP环境中
|
||
|
||
const resultShow = ref(false)
|
||
const helpShow = ref(false)
|
||
const historyShow = ref(false)
|
||
const maskLayerShow = computed(() => {
|
||
return helpShow.value || resultShow.value || historyShow.value
|
||
})
|
||
|
||
const rankShow = ref(true)
|
||
const incomeShow = ref(false)
|
||
const lotteryShow = ref(false)
|
||
|
||
const transferShow = ref(false)
|
||
const exchangeShow = ref(false)
|
||
const withdrawShow = ref(false)
|
||
|
||
const selectedCoin = ref(null)
|
||
|
||
const appConnected = ref(false)
|
||
const headerInfo = ref({})
|
||
|
||
// 抽屉展示
|
||
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) => {
|
||
rankShow.value = type == 'Rank' ? true : false
|
||
incomeShow.value = type == 'Income' ? true : false
|
||
lotteryShow.value = type == 'Lottery' ? true : false
|
||
drawerShowBt('') // 收起抽屉
|
||
selectedCoin.value = null // 清除选择币种
|
||
}
|
||
|
||
const taskList = ref([])
|
||
|
||
// 展示任务目标
|
||
const showTarget = (task) => {
|
||
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)
|
||
targetValue = Math.floor(targetValue)
|
||
let timeUnit = timeType ? t('minutes_short') : t('hours_short')
|
||
|
||
return t('on_mic_progress', {
|
||
current: currentValue,
|
||
total: targetValue,
|
||
unit: timeUnit,
|
||
})
|
||
}
|
||
|
||
// 选中的收款人
|
||
const selectedPayee = ref({})
|
||
|
||
// 初始化收款人信息
|
||
const initializePayee = () => {
|
||
const savedPayee = getSelectedPayee()
|
||
if (savedPayee) {
|
||
Object.assign(selectedPayee.value, savedPayee)
|
||
handleBt('Income')
|
||
drawerShowBt('transfer')
|
||
}
|
||
}
|
||
|
||
// 清除当前选中的收款人
|
||
const clearPayee = () => {
|
||
Object.assign(selectedPayee.value, {
|
||
id: null,
|
||
account: '',
|
||
name: '',
|
||
avatar: '',
|
||
type: '',
|
||
isHost: false,
|
||
isAgency: false,
|
||
hasSalary: false,
|
||
})
|
||
clearSelectedPayee()
|
||
}
|
||
|
||
// 前往搜索代理页
|
||
const searchPayee = () => {
|
||
router.push({ path: '/search-payee', query: { from: 'lottery' } })
|
||
}
|
||
|
||
// 前往提现页
|
||
const goToWithdraw = () => {
|
||
router.push({ path: '/cash-out', query: { activityId: activityId.value } })
|
||
}
|
||
|
||
// 转账金币选项
|
||
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: activityId.value,
|
||
}
|
||
|
||
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: activityId.value,
|
||
}
|
||
|
||
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 closedPopup = () => {
|
||
resultShow.value = false
|
||
helpShow.value = false
|
||
historyShow.value = false
|
||
result.value = []
|
||
resultShowIndex.value = 0
|
||
}
|
||
|
||
// 出错头像
|
||
const defaultAvatarUrl = (e) => {
|
||
console.log('头像资源出错')
|
||
e.target.onerror = null //防止循环
|
||
e.target.src = new URL('/src/assets/images/WeeklyStar/defaultAvatar.png', import.meta.url).href
|
||
}
|
||
|
||
//奖盘布局
|
||
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) => {
|
||
if (isRolling.value) return // 防止重复点击
|
||
// 检查抽奖次数
|
||
if (rollTimes.value >= consecutive) {
|
||
isRolling.value = true
|
||
let data = {
|
||
activityId: activity.value.activity.id,
|
||
drawCount: consecutive,
|
||
}
|
||
try {
|
||
// 单抽
|
||
if (consecutive == 1) {
|
||
const resOnceDraw = await onceDraw(data)
|
||
if (resOnceDraw.status && resOnceDraw.body) {
|
||
result.value.push(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) {
|
||
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)
|
||
}
|
||
}
|
||
getTickets() //重新获取拥有的抽奖券
|
||
getDrawRecords() // 获取中奖记录
|
||
resultShow.value = true
|
||
isRolling.value = false
|
||
} catch (error) {
|
||
isRolling.value = false
|
||
}
|
||
}
|
||
}
|
||
|
||
//获取用户信息
|
||
const getUserInfo = async () => {
|
||
if (Object.keys(userInfo.value).length === 0) {
|
||
const resUserInfo = await getMemberProfile()
|
||
if (resUserInfo.status && resUserInfo.body) {
|
||
// 缓存用户信息
|
||
console.debug('✅ User info cached successfully')
|
||
setUserInfo(resUserInfo.body, null)
|
||
if (ranking.value.length == 0) {
|
||
userInfo.value = resUserInfo.body
|
||
} else {
|
||
// 在排行榜中查我的信息
|
||
const myInfo = ranking.value.find((item) => item.account == resUserInfo.body.account)
|
||
console.log('myInfo:', myInfo)
|
||
userInfo.value = Object.assign(resUserInfo.body, myInfo)
|
||
}
|
||
}
|
||
}
|
||
const resIdentity = await getUserIdentity()
|
||
if (resIdentity.status && resIdentity.body) {
|
||
userIdentity.value = resIdentity.body
|
||
}
|
||
}
|
||
|
||
//获取排行榜
|
||
const getRanking = async () => {
|
||
const resRanking = await ranklist()
|
||
if (resRanking.status && resRanking.body) {
|
||
ranking.value = resRanking.body
|
||
if (Object.keys(userInfo.value).length != 0) {
|
||
// 在排行榜中查我的信息
|
||
const myInfo = resRanking.body.find((item) => item.account == userInfo.value.account)
|
||
console.log('myInfo:', myInfo)
|
||
|
||
if (myInfo) {
|
||
Object.assign(userInfo.value, myInfo)
|
||
}
|
||
}
|
||
} else {
|
||
ranking.value = {}
|
||
}
|
||
}
|
||
|
||
//获取奖池
|
||
const getActivityDetail = async () => {
|
||
const resvalidActivity = await validActivity() //活动是否有效
|
||
|
||
if (resvalidActivity.body?.id) {
|
||
activityId.value = resvalidActivity.body.id || ''
|
||
|
||
getDrawableAmount() //获取可提现金额
|
||
const resDetail = await activityDetail(resvalidActivity.body.activityCode)
|
||
if (resDetail.status && resDetail.body) {
|
||
activity.value = resDetail.body
|
||
} else {
|
||
activity.value = {}
|
||
}
|
||
}
|
||
}
|
||
|
||
//获取拥有的抽奖券
|
||
const getTickets = async () => {
|
||
const resTickets = await myTickets()
|
||
if (resTickets.status && resTickets.body) {
|
||
rollTimes.value = resTickets.body
|
||
} else {
|
||
rollTimes.value = 0
|
||
}
|
||
}
|
||
|
||
//可提现金额
|
||
const getDrawableAmount = async () => {
|
||
const resDrawableAmount = await withdrawableAmount(activityId.value)
|
||
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 getDrawRecords = async () => {
|
||
const resDrawRecords = await drawRecords()
|
||
if (resDrawRecords.status && resDrawRecords.body) {
|
||
myRecords.value = resDrawRecords.body?.records || []
|
||
}
|
||
}
|
||
|
||
//获取中奖用户列表
|
||
const getWinners = async () => {
|
||
const resWinners = await winnerHistory()
|
||
if (resWinners.status && resWinners.body) {
|
||
barrageList.value = resWinners.body
|
||
}
|
||
}
|
||
|
||
//领取任务奖励
|
||
const receiveTaskReward = async (code) => {
|
||
let data = {
|
||
taskCode: code,
|
||
}
|
||
try {
|
||
const resReceive = await receiveTickets(data)
|
||
if (resReceive.status && resReceive.body) {
|
||
getTaskList() //获取任务列表
|
||
getTickets() //获取拥有的抽奖券
|
||
}
|
||
} catch (error) {
|
||
showError(error.errorMsg)
|
||
}
|
||
}
|
||
|
||
// 页面初始化数据
|
||
const initData = () => {
|
||
getUserInfo() //获取用户信息
|
||
initializePayee() //获取收款人信息
|
||
getRanking() //获取排行榜
|
||
getActivityDetail() //获取奖池
|
||
getDrawRecords() // 获取中奖记录
|
||
getTickets() //获取拥有的抽奖券
|
||
getTaskList() //获取任务列表
|
||
getWinners() //获取历史中奖用户
|
||
}
|
||
// 使用工具函数连接APP
|
||
const connectToAppHandler = async () => {
|
||
await connectToApp(() => {
|
||
// 连接成功回调
|
||
initData()
|
||
})
|
||
}
|
||
|
||
onMounted(() => {
|
||
connectToAppHandler()
|
||
isInAppEnvironment.value = isInApp()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
clearPayee() //清空收款人信息
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
* {
|
||
color: #fff;
|
||
font-family: 'SF Pro Text';
|
||
}
|
||
|
||
.fullPage {
|
||
width: 100vw;
|
||
min-height: 100vh;
|
||
background: #1f5631;
|
||
background-image: url(@/assets/images/Lottery/bg.png);
|
||
background-size: 100% auto;
|
||
background-repeat: no-repeat;
|
||
position: relative;
|
||
}
|
||
|
||
.scrollbar::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
.active-prize {
|
||
border-radius: 8px;
|
||
box-shadow: 0 51px 80px 0 rgba(56, 253, 182, 0.49), 0 21.307px 33.422px 0 rgba(56, 253, 182, 0.35),
|
||
0 11.392px 17.869px 0 rgba(56, 253, 182, 0.29), 0 6.386px 10.017px 0 rgba(56, 253, 182, 0.25),
|
||
0 3.392px 5.32px 0 rgba(56, 253, 182, 0.2), 0 1.411px 2.214px 0 rgba(56, 253, 182, 0.14);
|
||
}
|
||
|
||
/* 金币网格 */
|
||
|
||
.coin-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border: 2px solid transparent;
|
||
|
||
transition: all 0.2s;
|
||
aspect-ratio: 1/1;
|
||
|
||
border-radius: 12px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
backdrop-filter: blur(32px);
|
||
}
|
||
|
||
.coin-item.selected {
|
||
border-color: #8b5cf6;
|
||
}
|
||
|
||
.coin-item:active {
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.rotated {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
.drawer-enter-active,
|
||
.drawer-leave-active {
|
||
transition: all 0.2s ease-out;
|
||
}
|
||
|
||
.drawer-enter-from,
|
||
.drawer-leave-to {
|
||
transform: translateY(-5px);
|
||
opacity: 0;
|
||
}
|
||
|
||
.help-btn {
|
||
display: block;
|
||
width: 16px;
|
||
position: absolute;
|
||
top: 4px;
|
||
right: 8px;
|
||
}
|
||
|
||
.close-btn {
|
||
position: absolute;
|
||
width: 8%;
|
||
aspect-ratio: 1/1;
|
||
top: 7%;
|
||
right: 7%;
|
||
}
|
||
|
||
.cancel-bt {
|
||
display: block;
|
||
width: 10vw;
|
||
position: absolute;
|
||
top: 4vw;
|
||
right: 4vw;
|
||
z-index: 99999;
|
||
}
|
||
|
||
.barrage-container {
|
||
position: relative;
|
||
left: -10px;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
@media screen and (max-width: 360px) {
|
||
* {
|
||
font-size: 10px;
|
||
}
|
||
}
|
||
|
||
@media screen and (min-width: 360px) {
|
||
* {
|
||
font-size: 16px;
|
||
}
|
||
}
|
||
|
||
@media screen and (min-width: 768px) {
|
||
* {
|
||
font-size: 24px;
|
||
}
|
||
}
|
||
|
||
@media screen and (min-width: 1024px) {
|
||
* {
|
||
font-size: 32px;
|
||
}
|
||
}
|
||
|
||
/* RTL支持 */
|
||
[dir='rtl'] .section-title {
|
||
text-align: right;
|
||
}
|
||
|
||
[dir='rtl'] .avatar {
|
||
margin-right: 0;
|
||
margin-left: 12px;
|
||
}
|
||
|
||
[dir='rtl'] .barrage-container {
|
||
right: -10px;
|
||
left: auto;
|
||
}
|
||
|
||
[dir='rtl'] .flipImg {
|
||
transform: scaleX(-1);
|
||
}
|
||
|
||
[dir='rtl'] .help-btn {
|
||
left: 8px;
|
||
right: auto;
|
||
}
|
||
|
||
[dir='rtl'] .cancel-bt {
|
||
left: 4vw;
|
||
right: auto;
|
||
}
|
||
|
||
[dir='rtl'] .close-btn {
|
||
left: 7%;
|
||
right: auto;
|
||
}
|
||
|
||
[dir='rtl'] .flipImg.rotated {
|
||
transform: scaleX(-1) rotate(90deg);
|
||
}
|
||
|
||
[dir='rtl'] .title-icon {
|
||
margin-left: 0;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
[dir='rtl'] .user-header {
|
||
/* flex-direction: row-reverse; */
|
||
}
|
||
|
||
[dir='rtl'] .user-info {
|
||
text-align: right;
|
||
}
|
||
|
||
[dir='rtl'] .salary-header {
|
||
/* flex-direction: row-reverse; */
|
||
}
|
||
|
||
[dir='rtl'] .task-header {
|
||
/* flex-direction: row-reverse; */
|
||
}
|
||
|
||
[dir='rtl'] .task-content {
|
||
/* flex-direction: row-reverse; */
|
||
}
|
||
|
||
[dir='rtl'] .action-buttons {
|
||
grid-template-columns: 1fr 1fr;
|
||
}
|
||
</style>
|