674 lines
18 KiB
Vue
674 lines
18 KiB
Vue
<template>
|
|
<div class="fullPage">
|
|
<GeneralHeader
|
|
:showLanguageList="true"
|
|
:title="t('bank_card')"
|
|
:backQuery="backQuery"
|
|
style="width: 100%"
|
|
color="black"
|
|
/>
|
|
<div style="padding: 16px; display: flex; flex-direction: column; gap: 8px">
|
|
<!-- 当前使用的银行卡 -->
|
|
<div style="font-weight: 600">{{ t('currently_in_use') }}</div>
|
|
<div
|
|
style="
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
"
|
|
:style="
|
|
usedBankCard.cardNo
|
|
? `border-radius: 11.75px;border: 0.5px solid rgba(255, 255, 255, 0.08);`
|
|
: ''
|
|
"
|
|
>
|
|
<div v-if="!usedBankCard.cardNo" style="font-weight: 510; color: rgba(0, 0, 0, 0.4)">
|
|
{{ t('no_bank_cards_in_use') }}
|
|
</div>
|
|
<div v-else style="display: flex; align-items: center; gap: 2vw">
|
|
<div style="width: 4.5em">
|
|
<img
|
|
v-smart-img
|
|
v-if="usedBankCard.cardType == 'BANK'"
|
|
src="@/assets/icon/bank/BANK.png"
|
|
alt=""
|
|
style="width: 100%; display: block"
|
|
/>
|
|
<img
|
|
v-smart-img
|
|
v-if="usedBankCard.cardType == 'USDT'"
|
|
src="@/assets/icon/bank/USDT.png"
|
|
alt=""
|
|
style="width: 100%; display: block"
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
style="
|
|
flex: 1;
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-around;
|
|
"
|
|
>
|
|
<div
|
|
style="
|
|
font-weight: 510;
|
|
color: rgba(0, 0, 0, 0.8);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
"
|
|
>
|
|
{{ t('payee') }}: {{ usedBankCard.payee }}
|
|
</div>
|
|
<div style="font-weight: 510; color: rgba(0, 0, 0, 0.4)">
|
|
{{ t('card_number') }}: {{ usedBankCard.cardNo }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 所拥有的银行卡 -->
|
|
<div style="font-weight: 600">{{ t('all_bank_cards') }}</div>
|
|
<!-- 列表为空 -->
|
|
<div
|
|
v-if="bankCardList.length === 0"
|
|
style="
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
"
|
|
>
|
|
<div style="font-weight: 510; color: rgba(0, 0, 0, 0.4)">
|
|
{{ t('no_bank_cards_added') }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 列表不为空 -->
|
|
<div
|
|
v-else
|
|
v-for="card in bankCardList"
|
|
:key="card.id"
|
|
style="
|
|
border-radius: 8px;
|
|
background: #fff;
|
|
padding: 12px;
|
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2vw;
|
|
"
|
|
>
|
|
<!-- 银行卡信息 -->
|
|
<div style="display: flex; align-items: center; gap: 2vw">
|
|
<!-- 银行图 -->
|
|
<div style="width: 4.5em">
|
|
<img
|
|
v-smart-img
|
|
v-if="card.cardType == 'BANK'"
|
|
src="@/assets/icon/bank/BANK.png"
|
|
alt=""
|
|
style="width: 100%; display: block"
|
|
/>
|
|
<img
|
|
v-smart-img
|
|
v-if="card.cardType == 'USDT'"
|
|
src="@/assets/icon/bank/USDT.png"
|
|
alt=""
|
|
style="width: 100%; display: block"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 信息 -->
|
|
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px">
|
|
<div
|
|
style="
|
|
font-weight: 510;
|
|
color: rgba(0, 0, 0, 0.8);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
"
|
|
>
|
|
{{ t('payee') }}: {{ card.payee }}
|
|
</div>
|
|
<div style="font-weight: 510; color: rgba(0, 0, 0, 0.4)">
|
|
{{ t('card_number') }}: {{ card.cardNo }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 按钮 -->
|
|
<div style="display: flex; justify-content: space-between; gap: 4vw">
|
|
<!-- 删除按钮 -->
|
|
<div
|
|
style="
|
|
flex: 1;
|
|
min-width: 0;
|
|
|
|
font-size: 1em;
|
|
font-weight: 700;
|
|
padding: 12px 12px;
|
|
color: #fff;
|
|
border-radius: 8px;
|
|
background: linear-gradient(135deg, #ff9294 2.82%, #ff4548 99.15%);
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
@click="removeBankCard(card.id)"
|
|
>
|
|
{{ t('delete') }}
|
|
</div>
|
|
|
|
<!-- 使用按钮 -->
|
|
<div
|
|
v-if="!card.use"
|
|
style="
|
|
flex: 1;
|
|
min-width: 0;
|
|
|
|
font-size: 1em;
|
|
font-weight: 700;
|
|
padding: 12px 12px;
|
|
color: #fff;
|
|
border-radius: 8px;
|
|
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
@click="setDefaultBankCard(card.id)"
|
|
>
|
|
{{ t('use') }}
|
|
</div>
|
|
|
|
<!-- 使用中按钮 -->
|
|
<div
|
|
v-else
|
|
style="
|
|
flex: 1;
|
|
min-width: 0;
|
|
|
|
font-size: 1em;
|
|
font-weight: 700;
|
|
padding: 12px 12px;
|
|
color: #fff;
|
|
border-radius: 8px;
|
|
background: linear-gradient(135deg, #d0d0d0 2.82%, #5b5b5b 99.15%);
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
>
|
|
{{ t('using') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="height: 50px"></div>
|
|
|
|
<!-- 添加按钮 -->
|
|
<div
|
|
style="
|
|
position: fixed;
|
|
width: 100%;
|
|
bottom: 10px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
>
|
|
<div
|
|
style="
|
|
padding: 8px 12px;
|
|
border-radius: 8px;
|
|
background: linear-gradient(135deg, #a6f1b2 2.82%, #2fff3d 99.15%);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
"
|
|
@click="maskLayerShow = true"
|
|
>
|
|
<div style="width: 5vw; display: flex; justify-content: center; align-items: center">
|
|
<img
|
|
v-smart-img
|
|
src="/src/assets/icon/addWhite.png"
|
|
alt=""
|
|
style="display: block; width: 100%; object-fit: cover"
|
|
/>
|
|
</div>
|
|
|
|
<div style="color: #fff; font-size: 1.1em; font-weight: 500">
|
|
{{ t('add_new_payment_method') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 弹窗遮罩层 -->
|
|
<maskLayer :maskLayerShow="maskLayerShow" @click="closedPopup">
|
|
<!-- 选择提现方式抽屉 -->
|
|
<div 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="font-size: 1.1em; font-weight: 600; color: #333">
|
|
{{ t('add_new_payment_method') }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 添加付款方式 -->
|
|
<div style="font-size: 0.9em; font-weight: 600; margin-bottom: 4px">
|
|
{{ t('withdrawal_method') }}:
|
|
</div>
|
|
<div>
|
|
<div
|
|
style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px"
|
|
>
|
|
<div
|
|
style="display: flex; justify-content: space-between; align-items: center"
|
|
@click="withdrawelMethodShow = !withdrawelMethodShow"
|
|
>
|
|
<div v-if="selectedMethod.cardType" style="font-size: 0.9em; font-weight: 500">
|
|
{{ selectedMethod.cardType }}
|
|
</div>
|
|
<div v-else style="font-size: 0.9em; font-weight: 500; color: rgba(0, 0, 0, 0.4)">
|
|
{{ t('choose_withdrawal_method') }}
|
|
</div>
|
|
<img
|
|
v-smart-img
|
|
src="../../../assets/icon/arrow.png"
|
|
alt=""
|
|
style="display: block; width: 6vw; transition: transform 0.5s"
|
|
class="flipImg"
|
|
:class="{ rotated: withdrawelMethodShow }"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div v-show="withdrawelMethodShow" style="position: relative; top: -15px">
|
|
<div
|
|
style="
|
|
position: absolute;
|
|
width: 100%;
|
|
left: 0;
|
|
top: 0;
|
|
max-height: 50vw;
|
|
background-color: #fff;
|
|
|
|
border-radius: 0 0 16px 16px;
|
|
box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.25);
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
"
|
|
class="overflow-y-auto"
|
|
>
|
|
<div
|
|
v-for="way in withdrawalWaysList"
|
|
:key="way"
|
|
style="font-size: 0.8em"
|
|
@click="selectMethod(way)"
|
|
>
|
|
{{ way }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 输入银行卡号 -->
|
|
<div v-if="cardNameShow" style="font-size: 0.9em; font-weight: 600; margin-bottom: 4px">
|
|
{{ t('card_name') }}:
|
|
</div>
|
|
<div
|
|
v-if="cardNameShow"
|
|
style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px"
|
|
>
|
|
<input
|
|
type="text"
|
|
name=""
|
|
id=""
|
|
:placeholder="t('enter_card_name')"
|
|
style="
|
|
width: 100%;
|
|
outline: none;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: black;
|
|
"
|
|
v-model="selectedMethod.cardName"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 输入银行卡号 -->
|
|
<div style="font-size: 0.9em; font-weight: 600; margin-bottom: 4px">
|
|
{{ t('card_number') }}:
|
|
</div>
|
|
<div style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px">
|
|
<input
|
|
type="text"
|
|
name=""
|
|
id=""
|
|
:placeholder="t('enter_card_number')"
|
|
style="
|
|
width: 100%;
|
|
outline: none;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: black;
|
|
"
|
|
v-model="selectedMethod.cardNo"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 输入收款人 -->
|
|
<div style="font-size: 0.9em; font-weight: 600; margin-bottom: 4px">{{ t('payee') }}</div>
|
|
<div style="box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); border-radius: 8px; padding: 12px">
|
|
<input
|
|
type="text"
|
|
name=""
|
|
id=""
|
|
:placeholder="t('enter_payee')"
|
|
style="
|
|
width: 100%;
|
|
outline: none;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: black;
|
|
"
|
|
v-model="selectedMethod.payee"
|
|
/>
|
|
</div>
|
|
|
|
<div style="display: flex; justify-content: center; align-items: center">
|
|
<div
|
|
style="
|
|
margin-top: 10px;
|
|
|
|
border-radius: 32px;
|
|
padding: 12px 20px;
|
|
color: #fff;
|
|
font-weight: 590;
|
|
text-align: center;
|
|
"
|
|
:style="{
|
|
background: checkpassed
|
|
? '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="Confirm"
|
|
>
|
|
{{ t('confirm') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</maskLayer>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { useI18n } from 'vue-i18n'
|
|
import { ref, onMounted, computed } from 'vue'
|
|
import GeneralHeader from '@/components/GeneralHeader.vue'
|
|
import { showError, showWarning, showInfo, showSuccess } from '@/utils/toast.js'
|
|
import { getUserId } from '@/utils/userStore'
|
|
import {
|
|
getWithdrawalWays,
|
|
getBankCardList,
|
|
addBankCard,
|
|
deleteBankCard,
|
|
useBankCard,
|
|
} from '@/api/wallet'
|
|
import maskLayer from '@/components/MaskLayer.vue'
|
|
import { useRoute } from 'vue-router'
|
|
import { setDocumentDirection } from '@/locales/i18n'
|
|
|
|
const route = useRoute()
|
|
const backQuery = ref(route.query || null)
|
|
|
|
const { t, locale } = useI18n()
|
|
|
|
// 监听语言变化并设置文档方向
|
|
locale.value && setDocumentDirection(locale.value)
|
|
|
|
const maskLayerShow = ref(false)
|
|
const withdrawelMethodShow = ref(false)
|
|
const cardNameShow = ref(false)
|
|
|
|
const withdrawalWaysList = ref([]) // 提现方式列表
|
|
const bankCardList = ref([]) // 银行卡列表
|
|
|
|
// 正在使用的银行卡
|
|
const usedBankCard = ref({
|
|
cardType: '',
|
|
cardName: '',
|
|
cardNo: '',
|
|
payee: '',
|
|
})
|
|
|
|
// 需要添加的银行卡信息
|
|
const selectedMethod = ref({
|
|
userId: getUserId(),
|
|
cardType: '',
|
|
cardName: '',
|
|
cardNo: '',
|
|
payee: '',
|
|
})
|
|
|
|
// 检查需要添加的银行卡信息是否填写完整
|
|
const checkpassed = computed(() => {
|
|
return (
|
|
selectedMethod.value.cardType &&
|
|
selectedMethod.value.cardName &&
|
|
selectedMethod.value.cardNo &&
|
|
selectedMethod.value.payee
|
|
)
|
|
})
|
|
|
|
// 关闭弹窗
|
|
const closedPopup = () => {
|
|
maskLayerShow.value = false
|
|
withdrawelMethodShow.value = false
|
|
cardNameShow.value = false
|
|
}
|
|
|
|
// 选择充值方式
|
|
const selectMethod = (way) => {
|
|
selectedMethod.value.cardType = way
|
|
if (way === 'USDT') {
|
|
selectedMethod.value.cardName = way
|
|
cardNameShow.value = false
|
|
} else if (way === 'BANK') {
|
|
selectedMethod.value.cardName = ''
|
|
cardNameShow.value = true
|
|
}
|
|
|
|
withdrawelMethodShow.value = !withdrawelMethodShow.value
|
|
}
|
|
|
|
// 确定添加
|
|
const Confirm = async () => {
|
|
if (checkpassed.value) {
|
|
// 添加银行卡
|
|
const resAddCard = await addBankCard(selectedMethod.value)
|
|
if (resAddCard.status) {
|
|
// 添加成功
|
|
closedPopup() //关闭弹窗
|
|
selectedMethod.value = {
|
|
...selectedMethod.value,
|
|
cardType: '',
|
|
cardName: '',
|
|
cardNo: '',
|
|
payee: '',
|
|
}
|
|
getBankCards()
|
|
} else {
|
|
// 添加失败
|
|
console.log('添加银行卡失败:', resAddCard.message)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 获取提现方式列表
|
|
const getWithdrawalWaysList = async () => {
|
|
try {
|
|
const resWithdrawalWays = await getWithdrawalWays()
|
|
console.log('提现方式列表:', resWithdrawalWays)
|
|
if (resWithdrawalWays.status && resWithdrawalWays.body) {
|
|
// 处理提现方式列表数据
|
|
withdrawalWaysList.value = resWithdrawalWays.body
|
|
}
|
|
} catch (error) {
|
|
console.error('获取提现方式列表失败:', error)
|
|
}
|
|
}
|
|
|
|
// 获取银行卡列表
|
|
const getBankCards = async () => {
|
|
try {
|
|
const resBankCards = await getBankCardList()
|
|
console.log('银行卡列表:', resBankCards)
|
|
if (resBankCards.status && resBankCards.body) {
|
|
// 处理银行卡列表数据
|
|
bankCardList.value = resBankCards.body
|
|
|
|
const usedCard = bankCardList.value.find((card) => card.use)
|
|
if (usedCard) {
|
|
usedBankCard.value = usedCard
|
|
} else {
|
|
// 没有使用中的银行卡
|
|
usedBankCard.value = {
|
|
cardType: '',
|
|
cardName: '',
|
|
cardNo: '',
|
|
payee: '',
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('获取银行卡列表失败:', error)
|
|
}
|
|
}
|
|
|
|
// 删除银行卡
|
|
const removeBankCard = async (cardId) => {
|
|
try {
|
|
const resDeleteCard = await deleteBankCard({ id: cardId })
|
|
if (resDeleteCard.status) {
|
|
getBankCards() // 重新获取银行卡列表
|
|
}
|
|
} catch (error) {
|
|
showError(error.response?.errorMsg || '')
|
|
}
|
|
}
|
|
|
|
// 设置默认银行卡
|
|
const setDefaultBankCard = async (cardId) => {
|
|
try {
|
|
const resUseCard = await useBankCard({ id: cardId })
|
|
if (resUseCard.status) {
|
|
getBankCards() // 重新获取银行卡列表
|
|
}
|
|
} catch (error) {
|
|
showError(error.response?.errorMsg || '')
|
|
}
|
|
}
|
|
|
|
// 初始化数据
|
|
const initData = () => {
|
|
getWithdrawalWaysList() // 获取提现方式列表
|
|
getBankCards() // 获取银行卡列表
|
|
}
|
|
|
|
onMounted(() => {
|
|
initData()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
* {
|
|
color: rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
.fullPage {
|
|
width: 100vw;
|
|
min-height: 100vh;
|
|
background-color: #fff;
|
|
background-image: url(/src/assets/images/secondBg.png);
|
|
background-size: 100% auto;
|
|
background-repeat: no-repeat;
|
|
position: relative;
|
|
}
|
|
|
|
.overflow-y-auto {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.overflow-y-auto::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.rotated {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
input::placeholder {
|
|
color: rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
@media screen and (max-width: 360px) {
|
|
* {
|
|
font-size: 10px;
|
|
}
|
|
}
|
|
|
|
@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;
|
|
}
|
|
}
|
|
|
|
/* RTL支持 */
|
|
[dir='rtl'] .flipImg {
|
|
transform: scaleX(-1);
|
|
}
|
|
|
|
[dir='rtl'] .rotated {
|
|
transform: scaleX(-1) rotate(90deg);
|
|
}
|
|
</style>
|