1173 lines
34 KiB
Vue
1173 lines
34 KiB
Vue
<template>
|
|
<div class="transfer gradient-background-circles">
|
|
<GeneralHeader
|
|
:title="t('available_salaries')"
|
|
:showLanguageList="true"
|
|
color="black"
|
|
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
|
|
/>
|
|
|
|
<div class="content">
|
|
<!-- 信息部分 -->
|
|
<div>
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
"
|
|
>
|
|
<div style="font-weight: 600">{{ t('available_salaries') }}</div>
|
|
<div style="display: flex; align-items: center" @click="showDetails">
|
|
<div style="color: rgba(0, 0, 0, 0.4)">{{ t('details') }}</div>
|
|
<img src="../../assets/icon/arrow.png" alt="" width="16px" class="flipImg" />
|
|
</div>
|
|
</div>
|
|
<div
|
|
style="
|
|
background-color: white;
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
"
|
|
>
|
|
<span v-if="loading" class="loading-text">{{ t('loading') }}...</span>
|
|
<span v-else style="font-weight: 700; color: #333; font-size: 1.1em"
|
|
>${{ availableIncome?.availableBalance }}</span
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 切换按钮 -->
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
margin-bottom: 12px;
|
|
"
|
|
>
|
|
<button
|
|
v-for="action in actions"
|
|
:key="action.name"
|
|
@click="handleAction(action.name)"
|
|
:style="{
|
|
padding: '8px 12px',
|
|
borderRadius: '8px',
|
|
background:
|
|
activeAction === action.name
|
|
? 'linear-gradient(135deg, #BB92FF 2.82%, #8B45FF 99.15%)'
|
|
: 'linear-gradient(135deg, #A2A2A2 2.82%, #646464 99.15%)',
|
|
border: 'none',
|
|
color: 'white',
|
|
fontWeight: '600',
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s',
|
|
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
|
|
}"
|
|
>
|
|
{{ t(action.lang) }}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Exchange -->
|
|
<div v-if="activeAction === 'Exchange'">
|
|
<div
|
|
style="
|
|
background-color: white;
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
margin-bottom: 20px;
|
|
"
|
|
>
|
|
<!-- 兑换金额选择 -->
|
|
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
|
|
<div
|
|
v-for="option in exchangeOptions"
|
|
:key="option.id"
|
|
@click="selectExchangeOption(option)"
|
|
:style="{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
border:
|
|
selectedExchangeOption === option.id ? '2px solid #8b5cf6' : '2px solid #e5e7eb',
|
|
borderRadius: '12px',
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s',
|
|
backgroundColor: selectedExchangeOption === option.id ? '#f3f4f6' : 'white',
|
|
aspectRatio: '1/1',
|
|
}"
|
|
>
|
|
<img src="../../assets/icon/coin.png" alt="" style="width: 40%" />
|
|
<div style="font-weight: 500; color: #373232">
|
|
<!-- {{ option.coins }} -->
|
|
</div>
|
|
<div style="font-weight: 500; color: #131111">${{ option.cash }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 兑换按钮 -->
|
|
<div style="display: flex; justify-content: center; margin-top: 10px">
|
|
<button
|
|
style="
|
|
width: 70%;
|
|
padding: 12px;
|
|
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 32px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
"
|
|
@click="exchangeTipShow = true"
|
|
:disabled="!selectedExchangeOption"
|
|
:style="{
|
|
background: !selectedExchangeOption
|
|
? '#ccc'
|
|
: 'linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%)',
|
|
opacity: !selectedExchangeOption ? 0.6 : 1,
|
|
}"
|
|
>
|
|
{{ t('exchange') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Transfer转账对象 -->
|
|
<div v-if="activeAction === 'Transfer'">
|
|
<div style="font-weight: 600; margin-bottom: 10px">{{ t('transfer_to_others') }}</div>
|
|
<div
|
|
style="
|
|
background-color: white;
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
"
|
|
>
|
|
<!-- 用户信息 -->
|
|
<div v-if="selectedPayee.id" style="width: 100%">
|
|
<!-- 头像信息 -->
|
|
<div style="display: flex; align-items: center; margin-bottom: 12px">
|
|
<!-- 头像 -->
|
|
<div
|
|
style="
|
|
width: 50px;
|
|
height: 50px;
|
|
margin-right: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
"
|
|
>
|
|
<img
|
|
:src="selectedPayee.avatar || ''"
|
|
:alt="selectedPayee.name"
|
|
style="
|
|
display: block;
|
|
object-fit: cover;
|
|
width: 100%;
|
|
aspect-ratio: 1/1;
|
|
border-radius: 50%;
|
|
"
|
|
@error="defaultAvatarUrl"
|
|
/>
|
|
</div>
|
|
<!-- 个人信息 -->
|
|
<div style="flex: 1; min-width: 0">
|
|
<div
|
|
style="
|
|
margin: 0 0 4px 0;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
"
|
|
>
|
|
{{ selectedPayee.name }}
|
|
</div>
|
|
<div style="margin: 0; font-size: 14px; color: #666">
|
|
ID: {{ selectedPayee.account || selectedPayee.id }}
|
|
</div>
|
|
</div>
|
|
<!-- 换人按钮 -->
|
|
<button
|
|
style="
|
|
border-radius: 12px;
|
|
border: 1px solid #e6e6e6;
|
|
color: rgba(0, 0, 0, 0.4);
|
|
font-weight: 500;
|
|
padding: 2px 8px;
|
|
background: none;
|
|
"
|
|
@click="searchPayee"
|
|
>
|
|
{{ t('change') }}
|
|
</button>
|
|
</div>
|
|
<!-- 身份 -->
|
|
<div style="margin-left: 62px; height: 20px; display: flex; gap: 5px">
|
|
<img
|
|
v-if="selectedPayee.isHost"
|
|
src="../../assets/icon/identity/host.png"
|
|
alt=""
|
|
height="100%"
|
|
/>
|
|
<img
|
|
v-if="selectedPayee.isAgency"
|
|
src="../../assets/icon/identity/agency.png"
|
|
alt=""
|
|
height="100%"
|
|
/>
|
|
<img
|
|
v-if="selectedPayee.hasSalary"
|
|
src="../../assets/icon/identity/coinSeller.png"
|
|
alt=""
|
|
height="100%"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 空状态 - 默认显示 -->
|
|
<div v-else style="display: flex; justify-content: center; align-items: center">
|
|
<div
|
|
style="
|
|
font-weight: 590;
|
|
color: rgba(0, 0, 0, 0.4);
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
"
|
|
@click="searchPayee"
|
|
>
|
|
{{ t('search') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Transfer -->
|
|
<div v-if="activeAction === 'Transfer'">
|
|
<div
|
|
style="
|
|
background-color: white;
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
"
|
|
>
|
|
<!-- 转账金额选择 -->
|
|
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px">
|
|
<div
|
|
v-for="coin in coinOptions"
|
|
:key="coin.id"
|
|
@click="selectCoin(coin)"
|
|
:style="{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
border: selectedCoin === coin.id ? '2px solid #8b5cf6' : '2px solid #e5e7eb',
|
|
borderRadius: '12px',
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s',
|
|
backgroundColor: selectedCoin === coin.id ? '#f3f4f6' : 'white',
|
|
aspectRatio: '1/1',
|
|
}"
|
|
>
|
|
<img src="../../assets/icon/coin.png" alt="" style="width: 40%" />
|
|
<div style="font-weight: 500; color: #373232">
|
|
<!-- {{ coin.amount }} -->
|
|
</div>
|
|
<div style="font-weight: 500; color: #131111">${{ coin.price }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 转账按钮 -->
|
|
<div style="display: flex; justify-content: center; margin-top: 10px">
|
|
<button
|
|
style="
|
|
width: 70%;
|
|
padding: 12px;
|
|
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 32px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
"
|
|
@click="transfer"
|
|
:disabled="!selectedCoin || !selectedPayee.id"
|
|
:style="{
|
|
background:
|
|
!selectedCoin || !selectedPayee.id
|
|
? '#ccc'
|
|
: 'linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%)',
|
|
opacity: !selectedCoin || !selectedPayee.id ? 0.6 : 1,
|
|
}"
|
|
>
|
|
{{ t('transfer') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Cash out -->
|
|
<div v-if="activeAction === 'Cash out'">
|
|
<!-- KYC验证资料 -->
|
|
<div>
|
|
<!-- 标题 -->
|
|
<div style="display: flex; align-items: flex-end; margin-bottom: 10px">
|
|
<div style="font-weight: 600">{{ t('kyc') }}</div>
|
|
|
|
<!-- 申请状态 -->
|
|
<div v-if="hasKYC" style="font-weight: 600; margin: 0 4px">:</div>
|
|
<!-- 通过 -->
|
|
<div
|
|
v-if="bankCardInfo?.status === 'PASS'"
|
|
style="
|
|
font-weight: 510;
|
|
font-size: 0.9em;
|
|
background: linear-gradient(248deg, #75ff98 5.66%, #3dff54 42.49%);
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
"
|
|
>
|
|
{{ t('review_passed') }}
|
|
</div>
|
|
|
|
<!-- 未通过 -->
|
|
<div
|
|
v-if="bankCardInfo?.status === 'NOT_PASS'"
|
|
style="
|
|
font-weight: 510;
|
|
font-size: 0.9em;
|
|
background: linear-gradient(248deg, #ff7578 5.66%, #ff3d40 42.49%);
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
"
|
|
>
|
|
{{ t('review_failed') }}
|
|
</div>
|
|
|
|
<!-- 审核中 -->
|
|
<div
|
|
v-if="bankCardInfo?.status === 'PENDING'"
|
|
style="
|
|
font-weight: 510;
|
|
font-size: 0.9em;
|
|
background: linear-gradient(248deg, #ffe675 5.66%, #ffc53d 42.49%);
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
"
|
|
>
|
|
{{ t('awaiting_review') }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 资料内容 -->
|
|
<div
|
|
style="
|
|
background-color: white;
|
|
padding: 16px;
|
|
border-radius: 12px;
|
|
margin-bottom: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
"
|
|
>
|
|
<!-- 未上传 -->
|
|
<div
|
|
v-if="!hasKYC"
|
|
style="display: flex; justify-content: space-between; align-items: center"
|
|
@click="gotoKYC"
|
|
>
|
|
<span style="font-weight: 510; font-size: 1em">{{ t('complete_information') }}</span>
|
|
<img src="../../assets/icon/arrow.png" alt="" style="width: 6vw" class="flipImg" />
|
|
</div>
|
|
|
|
<!-- 获取到上传的资料 -->
|
|
<div v-else style="width: 100%; display: flex; flex-direction: column; gap: 8px">
|
|
<!-- 图片 -->
|
|
<div style="display: flex; justify-content: space-between; align-items: center">
|
|
<span style="font-weight: 510; font-size: 1em">{{
|
|
t('passport_id_card', { current: bankCardInfo.previewUrls.length })
|
|
}}</span>
|
|
<img
|
|
src="../../assets/icon/arrow.png"
|
|
alt=""
|
|
style="width: 6vw"
|
|
@click="gotoKYC"
|
|
class="flipImg"
|
|
/>
|
|
</div>
|
|
<div style="display: flex; align-items: center; gap: 4px">
|
|
<img
|
|
:src="imgUrl"
|
|
alt=""
|
|
v-for="imgUrl in bankCardInfo.previewUrls"
|
|
style="width: 10vw; aspect-ratio: 1/1; border-radius: 4px"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 卡号 -->
|
|
<div style="font-weight: 500">{{ t('contact_number') }}:</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.8em">
|
|
{{ bankCardInfo.contactNumber }}
|
|
</div>
|
|
|
|
<!-- 备注信息 -->
|
|
<div style="font-weight: 500">{{ t('other_description') }}:</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.8em">
|
|
{{ bankCardInfo.otherDescription }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 展示金额填写弹窗按钮 -->
|
|
<div style="display: flex; justify-content: center; align-items: center">
|
|
<div
|
|
style="
|
|
margin-top: 10px;
|
|
width: 80%;
|
|
border-radius: 32px;
|
|
padding: 12px;
|
|
color: #fff;
|
|
font-weight: 590;
|
|
text-align: center;
|
|
"
|
|
:style="{
|
|
background:
|
|
bankCardInfo?.status === 'PASS'
|
|
? 'linear-gradient(135deg, #BB92FF 2.82%, #8B45FF 99.15%), linear-gradient(135deg, #D1CED6 2.82%, #7C7882 99.15%)'
|
|
: 'linear-gradient(135deg, #D1CED6 2.82%, #7C7882 99.15%)',
|
|
}"
|
|
@click="CashOut"
|
|
>
|
|
{{ t('cash_out') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 弹窗遮罩层 -->
|
|
<maskLayer :maskLayerShow="maskLayerShow" @click="closedPopup">
|
|
<!-- 兑换弹窗 -->
|
|
<div
|
|
v-if="exchangeTipShow"
|
|
style="
|
|
width: 100vw;
|
|
height: 100vh;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
@click="closedPopup"
|
|
>
|
|
<div
|
|
style="
|
|
width: 80%;
|
|
border-radius: 12px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
"
|
|
@click.stop
|
|
>
|
|
<div style="color: rgba(0, 0, 0, 0.8); font-weight: 800">{{ t('tips') }}</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.7em">
|
|
Are you sure you want to exchangecoins?
|
|
</div>
|
|
<div
|
|
style="width: 80%; display: flex; justify-content: space-between; align-items: center"
|
|
>
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 12px;
|
|
background: #fff;
|
|
border: 1px solid #e6e6e6;
|
|
|
|
color: rgba(0, 0, 0, 0.4);
|
|
font-weight: 800;
|
|
padding: 8px 12px;
|
|
width: 40%;
|
|
"
|
|
@click="closedPopup"
|
|
>
|
|
Cancel
|
|
</div>
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 12px;
|
|
background: linear-gradient(
|
|
152deg,
|
|
rgba(198, 112, 255, 0.8) 7.01%,
|
|
rgba(119, 38, 255, 0.8) 92.99%
|
|
);
|
|
|
|
color: #fff;
|
|
font-weight: 800;
|
|
padding: 8px 12px;
|
|
width: 40%;
|
|
"
|
|
@click="handleExchange"
|
|
>
|
|
Confirm
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 资料不足提示弹窗 -->
|
|
<div
|
|
v-if="cashOutTipShow"
|
|
style="
|
|
width: 100vw;
|
|
height: 100vh;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
@click="closedPopup"
|
|
>
|
|
<div
|
|
style="
|
|
width: 80%;
|
|
border-radius: 12px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
"
|
|
@click.stop
|
|
>
|
|
<div style="color: rgba(0, 0, 0, 0.8); font-weight: 800">{{ t('tips') }}</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.8em">
|
|
Please fill in the information carefully. You can only withdraw cash after the
|
|
information is completed.
|
|
</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.6em">
|
|
*lf there is a problem with the card number and the transfer cannot be made, it will
|
|
result in the review being.
|
|
</div>
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 12px;
|
|
background: linear-gradient(
|
|
152deg,
|
|
rgba(198, 112, 255, 0.8) 7.01%,
|
|
rgba(119, 38, 255, 0.8) 92.99%
|
|
);
|
|
|
|
color: #fff;
|
|
font-weight: 800;
|
|
padding: 8px 12px;
|
|
width: 50%;
|
|
"
|
|
@click="gotoKYC"
|
|
>
|
|
{{ t('receive') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 选择提现方式抽屉 -->
|
|
<div
|
|
v-if="cashOutTypeShow"
|
|
style="position: fixed; bottom: 0; width: 100%"
|
|
@click="closedPopup"
|
|
>
|
|
<div
|
|
style="
|
|
background: white;
|
|
border-radius: 16px 16px 0 0;
|
|
max-height: 80vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
padding: 20px;
|
|
"
|
|
@click.stop
|
|
>
|
|
<div style="display: flex; justify-content: center; align-items: center">
|
|
<div style="margin: 0; font-size: 18px; font-weight: 600; color: #333">
|
|
{{ t('cash_out') }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 选择支付方式 -->
|
|
<div style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px">
|
|
<div style="font-size: 0.9em; font-weight: 600; margin-bottom: 4px">
|
|
{{ t('withdrawal_method') }}: {{ usedBankCard?.cardType || '' }}
|
|
</div>
|
|
<div
|
|
style="display: flex; justify-content: space-between; align-items: center"
|
|
@click="gotoselectBank"
|
|
>
|
|
<div style="font-size: 0.9em; font-weight: 600">
|
|
{{ t('please_select_bank_card') }}
|
|
</div>
|
|
<img src="../../assets/icon/arrow.png" alt="" style="width: 6vw" class="flipImg" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 输入提现金额 -->
|
|
<div style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px">
|
|
<input
|
|
type="number"
|
|
min="50"
|
|
name=""
|
|
id=""
|
|
:placeholder="t('enter_cash_out_amount')"
|
|
style="
|
|
width: 100%;
|
|
outline: none;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: black;
|
|
"
|
|
v-model="cashOutAmount"
|
|
/>
|
|
</div>
|
|
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.9em">
|
|
{{ t('cash_out_minimum') }}
|
|
</div>
|
|
|
|
<div style="display: flex; justify-content: center; align-items: center">
|
|
<div
|
|
style="
|
|
margin-top: 10px;
|
|
width: 80%;
|
|
border-radius: 32px;
|
|
padding: 12px;
|
|
color: #fff;
|
|
font-weight: 590;
|
|
text-align: center;
|
|
"
|
|
:style="{
|
|
background: checkStatus
|
|
? 'linear-gradient(135deg, #BB92FF 2.82%, #8B45FF 99.15%), linear-gradient(135deg, #D1CED6 2.82%, #7C7882 99.15%)'
|
|
: 'linear-gradient(135deg, #D1CED6 2.82%, #7C7882 99.15%)',
|
|
}"
|
|
@click="Receive"
|
|
>
|
|
{{ t('cash_out') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 等待审核提示弹窗 -->
|
|
<div
|
|
v-if="cashOutShow"
|
|
style="
|
|
width: 100vw;
|
|
height: 100vh;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
@click="closedPopup"
|
|
>
|
|
<div
|
|
style="
|
|
width: 80%;
|
|
border-radius: 12px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
"
|
|
@click.stop
|
|
>
|
|
<div style="color: rgba(0, 0, 0, 0.8); font-weight: 800">{{ t('tips') }}</div>
|
|
<div style="color: rgba(0, 0, 0, 0.4); font-weight: 600; font-size: 0.8em">
|
|
{{ t('cash_withdrawal_tips') }}
|
|
</div>
|
|
<div
|
|
style="
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 12px;
|
|
background: linear-gradient(
|
|
152deg,
|
|
rgba(198, 112, 255, 0.8) 7.01%,
|
|
rgba(119, 38, 255, 0.8) 92.99%
|
|
);
|
|
|
|
color: #fff;
|
|
font-weight: 800;
|
|
padding: 8px 12px;
|
|
width: 50%;
|
|
"
|
|
@click="closedPopup"
|
|
>
|
|
{{ t('receive') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</maskLayer>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js'
|
|
import { showError, showSuccess } from '@/utils/toast.js'
|
|
import { getUserId } from '@/utils/userStore.js'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { setDocumentDirection } from '@/locales/i18n'
|
|
import { useIdentityStore } from '@/stores/identity.js'
|
|
|
|
import {
|
|
apiGetBankBalance, //获取当前余额
|
|
getBankBalance,
|
|
apiExchange, //兑换
|
|
apiTransfer, //转账
|
|
getBankCardList, //获取正在使用的银行卡
|
|
getWithdrawInfoList, //获取申请提现信息
|
|
withdrawApply, //提现
|
|
} from '@/api/wallet.js'
|
|
|
|
import GeneralHeader from '@/components/GeneralHeader.vue'
|
|
import maskLayer from '@/components/MaskLayer.vue'
|
|
|
|
const { t, locale } = useI18n()
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
|
|
const identityStore = useIdentityStore()
|
|
|
|
// 监听语言变化并设置文档方向
|
|
locale.value && setDocumentDirection(locale.value)
|
|
|
|
const availableIncome = ref({})
|
|
const selectedCoin = ref(null)
|
|
const selectedExchangeOption = ref(null)
|
|
const activeAction = ref(route.query.activeAction || 'Exchange')
|
|
const loading = ref(false)
|
|
|
|
const exchangeTipShow = ref(false)
|
|
const cashOutTipShow = ref(false)
|
|
const cashOutTypeShow = ref(false)
|
|
const cashOutShow = ref(false)
|
|
|
|
const cashOutAmount = ref(null)
|
|
|
|
const maskLayerShow = computed(() => {
|
|
return exchangeTipShow.value || cashOutTipShow.value || cashOutShow.value || cashOutTypeShow.value
|
|
})
|
|
|
|
const usedBankCard = ref(null) //正在使用的银行卡
|
|
|
|
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 closedPopup = () => {
|
|
exchangeTipShow.value = false
|
|
cashOutTipShow.value = false
|
|
cashOutShow.value = false
|
|
cashOutTypeShow.value = false
|
|
}
|
|
|
|
// 操作按钮
|
|
const actions = ref([
|
|
{ name: 'Exchange', lang: 'exchange' },
|
|
{ name: 'Transfer', lang: 'transfer' },
|
|
{ name: 'Cash out', lang: 'cash_out' },
|
|
])
|
|
|
|
// 提现按钮
|
|
const CashOut = () => {
|
|
if (hasKYC.value && bankCardInfo.value?.status === 'PASS') {
|
|
cashOutTypeShow.value = true
|
|
} else if (!hasKYC.value) {
|
|
cashOutTipShow.value = true
|
|
}
|
|
}
|
|
|
|
// 选中的收款人
|
|
const selectedPayee = reactive({
|
|
id: null,
|
|
account: '',
|
|
name: '',
|
|
avatar: '',
|
|
type: '',
|
|
isHost: false,
|
|
isAgency: false,
|
|
hasSalary: false,
|
|
})
|
|
|
|
// 转账金币选项
|
|
const coinOptions = reactive([
|
|
{ id: 1, amount: 10500, price: 1 },
|
|
{ id: 2, amount: 52500, price: 5 },
|
|
{ id: 3, amount: 105000, price: 10 },
|
|
{ id: 4, amount: 525000, price: 50 },
|
|
{ id: 5, amount: 1050000, price: 100 },
|
|
{ id: 6, amount: 2100000, price: 200 },
|
|
])
|
|
|
|
// 兑换选项
|
|
const exchangeOptions = reactive([
|
|
{ id: 1, coins: 10500, cash: 1 },
|
|
{ id: 2, coins: 52500, cash: 5 },
|
|
{ id: 3, coins: 105000, cash: 10 },
|
|
{ id: 4, coins: 525000, cash: 50 },
|
|
{ id: 5, coins: 1050000, cash: 100 },
|
|
{ id: 6, coins: 2100000, cash: 200 },
|
|
])
|
|
|
|
const bankCardInfo = ref(null)
|
|
const hasKYC = computed(() => {
|
|
return bankCardInfo.value != null
|
|
})
|
|
|
|
// 获取提现信息列表
|
|
const getWithdrawInfoListData = async () => {
|
|
try {
|
|
const resWithdrawInfoList = await getWithdrawInfoList()
|
|
console.log('提现信息列表:', resWithdrawInfoList)
|
|
if (resWithdrawInfoList.status && resWithdrawInfoList.body?.length > 0) {
|
|
let imgList = JSON.parse(resWithdrawInfoList.body[0].passportFrontUrl)
|
|
let previewUrls = imgList.map((item) => item)
|
|
bankCardInfo.value = { previewUrls, ...resWithdrawInfoList.body[0] }
|
|
}
|
|
} catch (error) {
|
|
console.error('获取提现信息列表失败:', error)
|
|
showError(error.response?.errorMsg)
|
|
}
|
|
}
|
|
|
|
// 获取银行卡列表
|
|
const getBankCards = async () => {
|
|
try {
|
|
const resBankCards = await getBankCardList()
|
|
console.log('银行卡列表:', resBankCards)
|
|
if (resBankCards.status && resBankCards.body) {
|
|
// 处理银行卡列表数据
|
|
resBankCards.body.forEach((card) => {
|
|
if (card.use) {
|
|
usedBankCard.value = card
|
|
}
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('获取银行卡列表失败:', error)
|
|
}
|
|
}
|
|
|
|
// 初始化收款人信息
|
|
const initializePayee = () => {
|
|
const savedPayee = getSelectedPayee()
|
|
if (savedPayee) {
|
|
Object.assign(selectedPayee, savedPayee)
|
|
}
|
|
}
|
|
|
|
// 获取银行余额
|
|
const fetchBankBalance = async () => {
|
|
loading.value = true
|
|
|
|
let salaryType = ['BD_LEADER', 'BD'].includes(identityStore.identity) ? 'BD_SALARY' : ''
|
|
|
|
try {
|
|
const response = await apiGetBankBalance(salaryType)
|
|
|
|
if (response.status && response.body) {
|
|
availableIncome.value = response.body || {}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch bank balance:', error)
|
|
showError(t('failed_to_load_balance'))
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 前往提交个人资料
|
|
const gotoKYC = () => {
|
|
router.push({ path: '/KYC', query: { from: '/available-income', activeAction: 'Cash out' } })
|
|
}
|
|
|
|
// 前往选择提交方式
|
|
const gotoselectBank = () => {
|
|
router.push({
|
|
path: '/bank-card',
|
|
query: { from: '/available-income', activeAction: 'Cash out' },
|
|
})
|
|
}
|
|
|
|
// 跳转详情
|
|
const showDetails = () => {
|
|
router.push('/income-details')
|
|
}
|
|
|
|
// 跳转搜索收款人
|
|
const searchPayee = () => {
|
|
router.push({
|
|
path: '/search-payee',
|
|
query: { from: '/available-income', activeAction: 'Transfer' },
|
|
})
|
|
}
|
|
|
|
// 处理操作按钮点击
|
|
const handleAction = (actionName) => {
|
|
activeAction.value = actionName
|
|
// 重置所有选择
|
|
selectedCoin.value = null
|
|
selectedExchangeOption.value = null
|
|
}
|
|
|
|
// 清除当前选中的收款人
|
|
const clearPayee = () => {
|
|
Object.assign(selectedPayee, {
|
|
id: null,
|
|
account: '',
|
|
name: '',
|
|
avatar: '',
|
|
type: '',
|
|
isHost: false,
|
|
isAgency: false,
|
|
hasSalary: false,
|
|
})
|
|
clearSelectedPayee()
|
|
}
|
|
|
|
// 选择转账金币
|
|
const selectCoin = (coin) => {
|
|
if (selectedCoin.value === coin.id) {
|
|
selectedCoin.value = null
|
|
} else {
|
|
selectedCoin.value = coin.id
|
|
}
|
|
}
|
|
|
|
// 选择兑换金币
|
|
const selectExchangeOption = (option) => {
|
|
if (selectedExchangeOption.value === option.id) {
|
|
selectedExchangeOption.value = null
|
|
} else {
|
|
selectedExchangeOption.value = option.id
|
|
}
|
|
}
|
|
|
|
// 转账操作
|
|
const transfer = async () => {
|
|
if (!selectedCoin.value) {
|
|
showError(t('please_select_amount'))
|
|
return
|
|
}
|
|
|
|
if (!selectedPayee.id) {
|
|
showError(t('please_select_payee'))
|
|
return
|
|
}
|
|
|
|
const selectedCoinData = coinOptions.find((coin) => coin.id === selectedCoin.value)
|
|
|
|
console.log('当前身份:', identityStore.identity)
|
|
|
|
const transferData = {
|
|
amount: selectedCoinData.price,
|
|
acceptUserId: selectedPayee.id,
|
|
salaryType: ['BD_LEADER', 'BD'].includes(identityStore.identity) ? 'BD_SALARY' : '',
|
|
}
|
|
|
|
try {
|
|
const response = await apiTransfer(transferData)
|
|
if (response.status) {
|
|
showSuccess(
|
|
t('transfer_success', { price: selectedCoinData.price, name: selectedPayee.name })
|
|
)
|
|
selectedCoin.value = null
|
|
await fetchBankBalance() // 刷新银行余额
|
|
} else {
|
|
showError(t('transfer_failed', { price: selectedCoinData.price }))
|
|
}
|
|
} catch (error) {
|
|
console.error('Transfer failed:', error)
|
|
showError(error.response?.errorMsg || t('transfer_error'))
|
|
}
|
|
}
|
|
|
|
// 兑换操作
|
|
const handleExchange = async () => {
|
|
if (!selectedExchangeOption.value) {
|
|
showError(t('please_select_coin_amount'))
|
|
return
|
|
}
|
|
|
|
const selectedOption = exchangeOptions.find(
|
|
(option) => option.id === selectedExchangeOption.value
|
|
)
|
|
|
|
console.log('当前身份:', identityStore.identity)
|
|
|
|
try {
|
|
// 调用接口进行兑换
|
|
const response = await apiExchange({
|
|
amount: selectedOption.cash,
|
|
salaryType: ['BD_LEADER', 'BD'].includes(identityStore.identity) ? 'BD_SALARY' : '',
|
|
})
|
|
|
|
if (response.status === true || response.errorCode === 0) {
|
|
showSuccess(t('exchange_success', { price: selectedOption.cash }))
|
|
|
|
closedPopup()
|
|
await fetchBankBalance() // 刷新银行余额
|
|
}
|
|
|
|
selectedExchangeOption.value = null
|
|
} catch (error) {
|
|
closedPopup()
|
|
console.error('Exchange failed:', error)
|
|
showError(error.response?.errorMsg || t('exchange_error_occurred'))
|
|
}
|
|
}
|
|
|
|
// 是否可以提现
|
|
const checkStatus = computed(() => {
|
|
return bankCardInfo.value?.status == 'PASS' && usedBankCard.value?.id && cashOutAmount.value >= 50
|
|
})
|
|
|
|
// 确认提现
|
|
const Receive = async () => {
|
|
if (checkStatus.value) {
|
|
try {
|
|
const resApply = await withdrawApply({
|
|
amount: cashOutAmount.value,
|
|
acceptBankCardId: usedBankCard.value.id,
|
|
})
|
|
if (resApply.status) {
|
|
closedPopup()
|
|
await fetchBankBalance() // 刷新银行余额
|
|
cashOutShow.value = true
|
|
}
|
|
} catch (error) {
|
|
closedPopup()
|
|
console.log('提现失败:', error.response?.errorMsg)
|
|
showError(t('something_went_wrong'))
|
|
}
|
|
}
|
|
}
|
|
|
|
// 页面加载时获取银行余额和初始化收款人
|
|
onMounted(() => {
|
|
fetchBankBalance() // 获取银行余额
|
|
initializePayee() // 初始化收款人信息
|
|
getWithdrawInfoListData() // 获取提现信息列表
|
|
getBankCards() // 获取正在使用的银行卡
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
clearPayee()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
* {
|
|
color: rgba(0, 0, 0, 0.8);
|
|
font-family: 'SF Pro Text';
|
|
}
|
|
|
|
input::placeholder {
|
|
font-weight: 510;
|
|
color: rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
.transfer {
|
|
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
|
width: 100vw;
|
|
min-height: 100vh;
|
|
background-color: #ffffff;
|
|
background-image: url(../../assets/images/secondBg.png);
|
|
background-size: 100% auto;
|
|
background-repeat: no-repeat;
|
|
position: relative;
|
|
}
|
|
|
|
.content {
|
|
padding: 16px;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.loading-text {
|
|
font-weight: 500;
|
|
color: #8b5cf6;
|
|
font-style: italic;
|
|
}
|
|
|
|
@media screen and (max-width: 360px) {
|
|
* {
|
|
font-size: 10px;
|
|
}
|
|
}
|
|
|
|
@media screen and (min-width: 360px) {
|
|
* {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
@media screen and (min-width: 768px) {
|
|
* {
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
|
|
/* RTL支持 */
|
|
[dir='rtl'] .avatar {
|
|
margin-right: 0;
|
|
margin-left: 12px;
|
|
}
|
|
|
|
[dir='rtl'] .user-info {
|
|
text-align: right;
|
|
}
|
|
|
|
[dir='rtl'] .flipImg {
|
|
transform: scaleX(-1);
|
|
}
|
|
</style>
|