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>