Files

1207 lines
33 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="recharge">
<u-navbar
title=""
bgColor="transparent"
:placeholder="true"
:fixed="true"
leftIcon=""
height="60"
>
<view slot="left">
<text class="navbar-lab">{{ $lang.recharge }}</text>
</view>
</u-navbar>
<view class="content">
<template v-if="userInfo.pay_channel == 'BC' && userInfo.area_id != 3">
<view class="picker-view" @click="show = true">
<u-input
readonly
:placeholder="$lang.pleaseChoose"
color="#f7ecd0"
v-model="type"
border="none"
>
<u--text
:text="$lang.chooseRecharge"
slot="prefix"
margin="0 3px 0 0"
type="tips"
></u--text>
<u-icon
slot="suffix"
name="arrow-down-fill"
color="#b9aa84"
size="16"
></u-icon>
</u-input>
</view>
<u-picker
:title="$lang.chooseRecharge"
closeOnClickOverlay
:show="show"
:columns="columns"
:cancelText="$lang.cancel"
:confirmText="$lang.confirm"
@cancel="close"
@close="close"
@confirm="confirm"
></u-picker>
<view class="list">
<view class="lab">{{ $lang.rechargeWithdrawNetwork }}</view>
<view class="type">TRC20</view>
</view>
<view class="list">
<view class="lab">{{ $lang.walletAddress }}</view>
<view class="box">
<u-input
readonly
:placeholder="$lang.walletAddress"
fontSize="12px"
color="#f7ecd0"
:value="address"
>
<template slot="suffix">
<u-button
class="btn"
:text="$lang.copy"
@click="copyCode"
color="#e5b932"
></u-button>
</template>
</u-input>
</view>
</view>
<view class="list qrcode">
<u--image
radius="5px"
:showLoading="true"
:src="qrcode"
width="200px"
height="200px"
mode="scaleToFill"
></u--image>
</view>
<view class="list">
<view class="tip">
{{ $lang.rechargeTip }}
</view>
</view>
</template>
<template v-if="userInfo.pay_channel == 'YBF' && userInfo.area_id != 3">
<view
class="picker-view"
@click="fnPicker('currency')"
v-if="currency_list.length"
>
<u-input
readonly
:placeholder="$lang.chooseCoin"
color="#f7ecd0"
v-model="currency.name"
border="none"
>
<u--text
:text="$lang.chooseCoin"
slot="prefix"
margin="0 3px 0 0"
type="tips"
></u--text>
<u-icon
slot="suffix"
name="arrow-down-fill"
color="#b9aa84"
size="16"
></u-icon>
</u-input>
</view>
<view
class="picker-view"
@click="fnPicker('coin_type')"
v-if="coin_type_list.length"
>
<u-input
readonly
:placeholder="$lang.chooseLine"
color="#f7ecd0"
v-model="coin_type.name"
border="none"
>
<u--text
:text="$lang.chooseLine"
slot="prefix"
margin="0 3px 0 0"
type="tips"
></u--text>
<u-icon
slot="suffix"
name="arrow-down-fill"
color="#b9aa84"
size="16"
></u-icon>
</u-input>
</view>
<view class="picker-view">
<u-input
:placeholder="$lang.enterMoney"
color="#f7ecd0"
v-model="amount"
border="none"
>
<u--text
:text="$lang.rechargeAmount"
slot="prefix"
margin="0 3px 0 0"
type="tips"
></u--text>
</u-input>
</view>
<view class="list mb60">
<u-button
class="button"
color="#e5b932"
:text="$lang.submit"
@click="submit"
></u-button>
</view>
<view class="list">
<view class="tip">
{{ $lang.rechargeTip }}
</view>
</view>
<u-picker
:title="$lang.chooseRecharge"
closeOnClickOverlay
:show="showPicker"
:columns="columnsPicker"
keyName="name"
:cancelText="$lang.cancel"
:confirmText="$lang.confirm"
@cancel="closePicker"
@close="closePicker"
@confirm="confirmPicker"
></u-picker>
</template>
<!-- 越南地区银行卡 (AlinPay) / USDT (Epay) 双通道 PC 同步按 area_id 判断 -->
<template v-if="userInfo.area_id == 3">
<view class="pay-tabs">
<view
class="pay-tab"
:class="{ active: payChannel === 'alin' }"
@click="payChannel = 'alin'"
>Thẻ ngân hàng</view>
<view
class="pay-tab"
:class="{ active: payChannel === 'epay' }"
@click="payChannel = 'epay'"
>USDT (TRC20)</view>
<view
class="pay-tab"
:class="{ active: payChannel === 'ccpay' }"
@click="payChannel = 'ccpay'"
>Ngân hàng QR</view>
</view>
<view class="picker-view">
<u-input
:placeholder="payChannel === 'epay' ? 'Nhập số tiền VND (vd: 1,000,000)' : 'Tối thiểu 1,000,000'"
color="#f7ecd0"
v-model="amount"
type="number"
border="none"
>
<u--text
:text="payChannel === 'epay' ? ($lang.rechargeAmount || '充值金额') + ' (VND)' : ($lang.rechargeAmount || '充值金额')"
slot="prefix"
margin="0 3px 0 0"
type="tips"
></u--text>
</u-input>
</view>
<view class="list mb60">
<u-button
class="button"
color="#e5b932"
:text="$lang.submit"
@click="payChannel === 'ccpay' ? submitCcpay() : (payChannel === 'epay' ? submitEpay() : submitAlin())"
></u-button>
</view>
<view class="list">
<view class="tip">
{{ payChannel === 'epay' ? 'Nhập số tiền theo VND — hệ thống tự động quy đổi sang USDT theo tỷ giá 1 USDT ≈ 27,100 VND. Thanh toán qua mạng TRC20.' : (payChannel === 'ccpay' ? 'Nhập số tiền VND — hệ thống tạo mã QR ngân hàng. Quét mã thanh toán qua ứng dụng ngân hàng.' : $lang.rechargeTip) }}
</view>
</view>
</template>
</view>
<view class="mb60"></view>
<!-- AlinPay 内嵌支付弹窗 -->
<view class="alin-overlay" v-if="alinPay.visible" @click.self="closeAlinPay">
<view class="alin-pay-box">
<view class="alin-pay-header">
<text class="alin-pay-title">Thanh toán ngân hàng</text>
<view class="epay-qr-close" @click="closeAlinPay">×</view>
</view>
<iframe v-if="alinPay.url" :src="alinPay.url" class="alin-iframe" frameborder="0" allow="payment"></iframe>
</view>
</view>
<!-- USDT 内嵌二维码弹窗 -->
<u-popup :show="epayQr.visible" mode="center" round="10" :closeOnClickOverlay="false" @close="closeEpayQr">
<view class="epay-qr-box">
<view class="epay-qr-close" @click="closeEpayQr">×</view>
<view class="epay-qr-title">USDT (TRC20)</view>
<view class="epay-qr-status" :class="epayQr.statusClass">{{ epayQr.statusText }}</view>
<view class="epay-qr-img-wrap">
<u--image v-if="epayQr.qrDataUrl" :src="epayQr.qrDataUrl" width="340rpx" height="340rpx" mode="scaleToFill"></u--image>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Số tiền USDT (chính xác)</view>
<view class="epay-qr-value amount">
<text>{{ epayQr.data.usdt_amount }} USDT</text>
<view class="epay-qr-btn" @click="copyEpayText(epayQr.data.usdt_amount, 'amount')">
{{ epayQr.copied === 'amount' ? '✓' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Địa chỉ (TRC20)</view>
<view class="epay-qr-value addr">
<text>{{ epayQr.data.usdt_address }}</text>
<view class="epay-qr-btn" @click="copyEpayText(epayQr.data.usdt_address, 'addr')">
{{ epayQr.copied === 'addr' ? '✓' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-meta">
<text> {{ epayQr.data.vnd_amount }} VND</text>
<text class="epay-qr-countdown"> {{ epayQr.countdownText }}</text>
</view>
<view class="epay-qr-tip">
Vui lòng chuyển chính xác số tiền. Sai số sẽ không thể xác định đơn hàng!
</view>
</view>
</u-popup>
<!-- CCpay 银行QR弹窗 -->
<u-popup :show="bankQr.visible" mode="center" round="10" :closeOnClickOverlay="false" @close="closeBankQr">
<view class="epay-qr-box">
<view class="epay-qr-close" @click="closeBankQr">×</view>
<view class="epay-qr-title">Ngân hàng QR</view>
<view class="epay-qr-status" :class="bankQr.statusClass">{{ bankQr.statusText }}</view>
<view class="epay-qr-img-wrap" v-if="bankQr.qrDataUrl">
<u--image :src="bankQr.qrDataUrl" width="340rpx" height="340rpx" mode="scaleToFill"></u--image>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Số tài khoản</view>
<view class="epay-qr-value amount">
<text>{{ bankQr.data.bank_account }}</text>
<view class="epay-qr-btn" @click="copyEpayText(bankQr.data.bank_account, 'bank_acc')">
{{ epayQr.copied === 'bank_acc' ? '✓' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Tên tài khoản Ngân hàng</view>
<view class="epay-qr-value addr">
<text>{{ bankQr.data.bank_name }} {{ bankQr.data.bank_short }}</text>
</view>
</view>
<view class="epay-qr-meta">
<text>{{ Number(bankQr.data.amount).toLocaleString() }} VND</text>
<text class="epay-qr-countdown"> {{ bankQr.countdownText }}</text>
</view>
<view class="epay-qr-tip">
Vui lòng chuyển khoản chính xác số tiền. Sai thông tin sẽ không thể xác nhận đơn hàng!
</view>
</view>
</u-popup>
</view>
</template>
<script>
import { mapState } from "vuex";
import qr from "qr-image";
export default {
data() {
return {
address: "",
qrcode: "",
// 币种选择
type: "USDT",
show: false,
columns: [["USDT"]],
// 支付方式
showPicker: false,
columnsPicker: [],
pickerType: "",
amount: "",
currency: { name: "", key: "" },
coin_type: { name: "", key: "" },
// 越南地区在线支付通道:'alin'(银行卡) | 'epay'(USDT)
payChannel: "alin",
// 内嵌 USDT 二维码弹窗状态
epayQr: {
visible: false,
data: { usdt_address: "", usdt_amount: "", vnd_amount: "", expires_at: 0, order_sn: "" },
qrDataUrl: "",
countdownText: "",
statusText: "",
statusClass: "waiting",
copied: "",
},
_epayPollTimer: null,
_epayCountdownTimer: null,
bankQr: {
visible: false,
data: { bank_account: "", bank_name: "", bank_short: "", qr_data: "", amount: 0, order_sn: "", expires_at: 0, timeout_sec: 600 },
qrDataUrl: "",
countdownText: "",
statusText: "",
statusClass: "waiting",
},
_bankPollTimer: null,
_bankCountdownTimer: null,
alinPay: {
visible: false,
url: "",
},
};
},
computed: {
...mapState({
userInfo: (state) => state.app.userInfo,
$lang: (state) => state.app.lang[state.app.language],
coin_type_list: (state) => {
return state.app?.userInfo?.pay_channel_coin_chain || [];
},
currency_list: (state) => {
return state.app?.userInfo?.pay_channel_currency || [];
},
}),
},
onLoad() {
if (this.userInfo && this.userInfo.wallet) {
this.address = this.userInfo.wallet.address;
this.setQrCode();
}
if (
this.userInfo &&
this.userInfo.pay_channel_coin_chain &&
this.userInfo.pay_channel_coin_chain.length
) {
this.coin_type = this.userInfo.pay_channel_coin_chain[0];
}
if (
this.userInfo &&
this.userInfo.pay_channel_currency &&
this.userInfo.pay_channel_currency.length
) {
this.currency = this.userInfo.pay_channel_currency[0];
}
},
methods: {
confirm(chose) {
this.type = chose.value[0];
this.close();
},
close() {
this.show = false;
},
setQrCode() {
const qrcode =
"data:image/png;base64," +
uni.arrayBufferToBase64(
qr.imageSync(this.address, {
margin: 2,
})
);
this.qrcode = qrcode;
},
// 复制链接
copyCode() {
uni.setClipboardData({
data: this.address,
success: () => {
this.$toast({
message: this.$lang.copySuccessfully,
duration: 2000,
});
},
});
},
fnPicker(type) {
this.pickerType = type;
this.columnsPicker = [this[`${type}_list`]];
this.showPicker = true;
},
confirmPicker(chose) {
this[this.pickerType] = chose.value[0];
this.closePicker();
},
closePicker() {
this.showPicker = false;
},
submit() {
if (!this.amount) {
this.$toast({
message: this.$lang.enterWithdrawalamount,
duration: 2000,
});
} else {
const params = {
user_id: this.userInfo.id,
pay_channel: this.userInfo.pay_channel,
amount: this.amount,
currency: this.currency.key,
coin_type: this.coin_type.key,
};
this.$toast({
type: "loading",
message: `${this.$lang.submit}...`,
duration: 200000,
});
this.$api
.ybfDeposit(params)
.then((res) => {
if (res.Success == 1) {
const o = navigator.userAgent;
const isiOS = !!o.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if (isiOS) {
window.location.href = res.data.payUrl;
} else {
window.open(res.data.payUrl, "_blank");
}
}
})
.catch((err) => {
console.log(err);
})
.finally(() => {
this.$toastHide();
});
}
},
// 越南 AlinPay 充值
submitAlin() {
if (!this.amount || this.amount <= 0) {
this.$toast({
message: 'Vui lòng nhập số tiền',
duration: 2000,
});
return;
}
if (this.amount < 1000000) {
this.$toast({
message: 'Số tiền tối thiểu là 1,000,000',
duration: 2000,
});
return;
}
const params = {
user_id: this.userInfo.id,
price: this.amount,
client: 3,
username: this.userInfo.username,
};
this.$toast({
type: "loading",
message: `${this.$lang.submit}...`,
duration: 200000,
});
this.$api
.alinDeposit(params)
.then((res) => {
const d = res.Data || {};
if (d.status == 1 && d.url) {
this.alinPay.url = d.url;
this.alinPay.visible = true;
} else {
this.$toast({
message: d.message || '充值失败',
duration: 2000,
});
}
})
.catch((err) => {
console.log(err);
})
.finally(() => {
this.$toastHide();
});
},
submitEpay() {
if (!this.amount || this.amount <= 0) {
this.$toast({ message: 'Vui lòng nhập số tiền', duration: 2000 });
return;
}
if (this.amount < 1000000) {
this.$toast({ message: 'Số tiền tối thiểu là 1,000,000', duration: 2000 });
return;
}
const params = {
user_id: this.userInfo.id,
price: this.amount,
client: 3,
username: this.userInfo.username,
pay_type: 'usdt',
};
this.$toast({
type: "loading",
message: `${this.$lang.submit}...`,
duration: 200000,
});
this.$api
.epayDeposit(params)
.then((res) => {
const d = res.Data || {};
if (d.status == 1 && d.qrcode) {
this.openEpayQr(d.qrcode);
} else if (d.status == 1 && d.url) {
// 后端未升级时兼容跳转
const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS) window.location.href = d.url; else window.open(d.url, "_blank");
} else {
this.$toast({ message: d.message || 'Nạp thất bại', duration: 2000 });
}
})
.catch((err) => {
console.log(err);
})
.finally(() => {
this.$toastHide();
});
},
openEpayQr(qrcode) {
this.epayQr.data = qrcode;
this.epayQr.statusText = "Đang chờ thanh toán...";
this.epayQr.statusClass = "waiting";
this.epayQr.copied = "";
// 生成二维码图片(复用现有 qr-image 库)
try {
this.epayQr.qrDataUrl =
"data:image/png;base64," +
uni.arrayBufferToBase64(qr.imageSync(qrcode.usdt_address, { margin: 2 }));
} catch (e) {
this.epayQr.qrDataUrl = "";
}
this.epayQr.visible = true;
this.startEpayCountdown();
this.startEpayPolling();
},
startEpayCountdown() {
const tick = () => {
const left = Math.max(0, this.epayQr.data.expires_at - Math.floor(Date.now() / 1000));
const m = Math.floor(left / 60);
const s = left % 60;
this.epayQr.countdownText = (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
if (left <= 0) {
this.epayQr.statusText = "Đơn hàng đã hết hạn";
this.epayQr.statusClass = "expired";
this.stopEpayTimers();
}
};
tick();
this._epayCountdownTimer = setInterval(tick, 1000);
},
startEpayPolling() {
const poll = () => {
if (!this.epayQr.visible || !this.epayQr.data.order_sn) return;
this.$api
.epayOrderStatus({
user_id: this.userInfo.id,
order_sn: this.epayQr.data.order_sn,
})
.then((res) => {
const d = res.Data || {};
if (d.status == 1) {
this.epayQr.statusText = "Thanh toán thành công!";
this.epayQr.statusClass = "success";
this.stopEpayTimers();
this.$store.dispatch("app/getUserInfo");
setTimeout(() => this.closeEpayQr(), 2500);
} else if (d.status == 2) {
this.epayQr.statusText = "Đơn hàng đã hết hạn";
this.epayQr.statusClass = "expired";
this.stopEpayTimers();
}
})
.catch(() => {});
};
this._epayPollTimer = setInterval(poll, 3000);
setTimeout(poll, 1000);
},
copyEpayText(text, tag) {
uni.setClipboardData({
data: String(text),
success: () => {
this.epayQr.copied = tag;
setTimeout(() => {
if (this.epayQr.copied === tag) this.epayQr.copied = "";
}, 1500);
},
});
},
closeAlinPay() {
this.alinPay.visible = false;
this.alinPay.url = "";
},
closeEpayQr() {
this.epayQr.visible = false;
this.stopEpayTimers();
},
stopEpayTimers() {
if (this._epayPollTimer) {
clearInterval(this._epayPollTimer);
this._epayPollTimer = null;
}
if (this._epayCountdownTimer) {
clearInterval(this._epayCountdownTimer);
this._epayCountdownTimer = null;
}
},
submitCcpay() {
if (!this.amount || this.amount <= 0) {
this.$toast({ message: 'Vui lòng nhập số tiền', duration: 2000 });
return;
}
if (this.amount < 1000000) {
this.$toast({ message: 'Số tiền tối thiểu là 1,000,000', duration: 2000 });
return;
}
const params = {
user_id: this.userInfo.id,
price: this.amount,
client: 3,
username: this.userInfo.username,
};
this.$toast({ type: "loading", message: `${this.$lang.submit}...`, duration: 200000 });
this.$api
.ccpayDeposit(params)
.then((res) => {
const d = res.Data || {};
if (d.status == 1 && d.qrcode) {
this.openBankQr(d.qrcode);
} else if (d.status == 1 && d.url) {
const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS) window.location.href = d.url; else window.open(d.url, "_blank");
} else {
this.$toast({ message: d.message || 'Nạp thất bại', duration: 2000 });
}
})
.catch((err) => { console.log(err); })
.finally(() => { this.$toastHide(); });
},
openBankQr(qrcode) {
this.bankQr.data = qrcode;
this.bankQr.statusText = "Đang chờ thanh toán...";
this.bankQr.statusClass = "waiting";
try {
this.bankQr.qrDataUrl = qrcode.qr_data
? "data:image/png;base64," + uni.arrayBufferToBase64(qr.imageSync(qrcode.qr_data, { margin: 2 }))
: "";
} catch (e) { this.bankQr.qrDataUrl = ""; }
this.bankQr.visible = true;
this.startBankCountdown();
this.startBankPolling();
},
startBankCountdown() {
const tick = () => {
const left = Math.max(0, this.bankQr.data.expires_at - Math.floor(Date.now() / 1000));
const m = Math.floor(left / 60);
const s = left % 60;
this.bankQr.countdownText = (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
if (left <= 0) {
this.bankQr.statusText = "Đơn hàng đã hết hạn";
this.bankQr.statusClass = "expired";
this.stopBankTimers();
}
};
tick();
this._bankCountdownTimer = setInterval(tick, 1000);
},
startBankPolling() {
const poll = () => {
if (!this.bankQr.visible || !this.bankQr.data.order_sn) return;
this.$api
.ccpayOrderStatus({ user_id: this.userInfo.id, order_sn: this.bankQr.data.order_sn })
.then((res) => {
const d = res.Data || {};
if (d.status == 1) {
this.bankQr.statusText = "Thanh toán thành công!";
this.bankQr.statusClass = "success";
this.stopBankTimers();
this.$store.dispatch("app/getUserInfo");
setTimeout(() => this.closeBankQr(), 2500);
} else if (d.status == 2) {
this.bankQr.statusText = "Đơn hàng đã hết hạn";
this.bankQr.statusClass = "expired";
this.stopBankTimers();
}
})
.catch(() => {});
};
this._bankPollTimer = setInterval(poll, 3000);
setTimeout(poll, 1000);
},
closeBankQr() {
this.bankQr.visible = false;
this.stopBankTimers();
},
stopBankTimers() {
if (this._bankPollTimer) { clearInterval(this._bankPollTimer); this._bankPollTimer = null; }
if (this._bankCountdownTimer) { clearInterval(this._bankCountdownTimer); this._bankCountdownTimer = null; }
},
},
beforeDestroy() {
this.stopEpayTimers();
this.stopBankTimers();
},
};
</script>
<style lang="scss" scoped>
.pay-tabs {
display: flex;
gap: 12rpx;
margin-bottom: 16px;
}
.pay-tab {
flex: 1;
min-height: 44px;
padding: 0 10rpx;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: #b9aa84;
background: linear-gradient(
180deg,
rgba(21, 18, 15, 0.96) 0%,
rgba(13, 11, 9, 0.96) 100%
);
border: 1rpx solid rgba(223, 189, 120, 0.14);
border-radius: 16px;
font-size: 24rpx;
line-height: 1.3;
transition: all 0.2s;
&.active {
color: #231705;
font-weight: 700;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-color: rgba(242, 223, 182, 0.5);
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
}
}
.recharge {
width: 100%;
min-height: 100vh;
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #f7ecd0;
::v-deep .u-navbar {
background: rgba(0, 0, 0, 0.72) !important;
}
::v-deep .u-navbar__content {
background: transparent !important;
}
::v-deep .u-picker__view__column__item {
color: #f3e3b8 !important;
}
::v-deep .u-toolbar {
background: #15120f !important;
border-bottom-color: rgba(223, 189, 120, 0.12) !important;
}
::v-deep .u-toolbar__title {
color: #f4dfae !important;
}
.navbar-lab {
color: #fbf2de;
font-weight: 700;
font-size: 19px;
letter-spacing: 0.3px;
}
.content {
width: calc(100% - 24px);
max-width: 760px;
margin: 10px auto 0;
padding: 18px 16px 22px;
box-sizing: border-box;
border-radius: 24px;
background: linear-gradient(
180deg,
rgba(16, 13, 11, 0.96) 0%,
rgba(10, 8, 7, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.18);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 245, 223, 0.03);
.picker-view {
min-height: 56px;
margin-bottom: 14px;
padding: 0 14px;
display: flex;
align-items: center;
background: linear-gradient(
180deg,
rgba(25, 21, 18, 0.96) 0%,
rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 16px;
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03),
inset 0 -1px 0 rgba(0, 0, 0, 0.12);
::v-deep .u-input {
flex: 1;
}
::v-deep .u-input__content {
min-height: 54px;
padding: 0;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd0 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.4) !important;
}
::v-deep .u-text__value {
color: #baa67f !important;
font-size: 13px !important;
}
}
.list {
margin-bottom: 14px;
padding: 14px;
border-radius: 16px;
background: linear-gradient(
180deg,
rgba(23, 19, 16, 0.92) 0%,
rgba(14, 12, 10, 0.92) 100%
);
border: 1px solid rgba(223, 189, 120, 0.1);
font-size: 14px;
text-align: center;
&.qrcode {
display: flex;
width: 100%;
align-items: center;
justify-content: center;
padding: 20px 14px;
::v-deep .u-image {
border-radius: 18px !important;
overflow: hidden;
border: 1px solid rgba(223, 189, 120, 0.12);
background: #fff;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16);
}
}
.lab {
color: #b9aa84;
margin: 0 0 10px;
text-align: left;
font-size: 13px;
}
.box {
::v-deep .u-input {
min-height: 48px;
padding: 0 12px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(223, 189, 120, 0.12);
border-radius: 14px;
}
::v-deep .u-input__content {
min-height: 48px;
}
::v-deep input {
color: #f7ecd0 !important;
}
}
.btn {
min-width: 76px;
height: 34px;
font-weight: 700;
border: none !important;
border-radius: 12px !important;
color: #231705 !important;
box-shadow: 0 8px 18px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.type {
min-width: 86px;
height: 36px;
padding: 0 16px;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-radius: 999px;
text-align: center;
line-height: 36px;
font-weight: 700;
color: #231705;
box-shadow: 0 8px 18px rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
margin: 0 auto;
}
.button {
height: 50px !important;
margin-top: 8px;
margin-bottom: 2px;
border: none !important;
border-radius: 16px !important;
color: #231705 !important;
font-weight: 700;
letter-spacing: 0.3px;
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
}
.tip {
color: #bca47a;
font-size: 13px;
text-align: justify;
line-height: 1.6;
}
}
.mb60 {
margin-bottom: 0 !important;
}
}
}
/* ============ 内嵌 USDT / 银行二维码弹窗 ============ */
.epay-qr-box {
width: 620rpx;
padding: 34rpx 34rpx 28rpx;
background: linear-gradient(
180deg,
rgba(20, 16, 12, 0.98) 0%,
rgba(11, 9, 7, 0.98) 100%
);
border: 1rpx solid rgba(223, 189, 120, 0.18);
border-radius: 20rpx;
color: #f0dbab;
box-sizing: border-box;
position: relative;
box-shadow: 0 24rpx 60rpx rgba(0, 0, 0, 0.3);
}
.epay-qr-close {
position: absolute;
top: 12rpx;
right: 16rpx;
color: #b7a37d;
font-size: 38rpx;
line-height: 1;
padding: 10rpx 16rpx;
}
.epay-qr-title {
text-align: center;
font-size: 30rpx;
font-weight: 700;
margin-bottom: 10rpx;
color: #f7e6bd;
}
.epay-qr-status {
width: fit-content;
min-width: 180rpx;
margin: 0 auto 20rpx;
padding: 8rpx 18rpx;
text-align: center;
font-size: 22rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.03);
&.waiting {
color: #e5b932;
}
&.success {
color: #7cd992;
}
&.expired {
color: #e67e72;
}
}
.epay-qr-img-wrap {
width: 340rpx;
height: 340rpx;
margin: 0 auto 24rpx;
background: #fff;
padding: 16rpx;
border-radius: 20rpx;
box-sizing: content-box;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 10rpx 26rpx rgba(0, 0, 0, 0.18);
}
.epay-qr-field {
margin-bottom: 16rpx;
}
.epay-qr-label {
color: #ab9770;
font-size: 22rpx;
margin-bottom: 8rpx;
}
.epay-qr-value {
display: flex;
align-items: center;
gap: 12rpx;
background: rgba(255, 255, 255, 0.03);
border: 1rpx solid rgba(223, 189, 120, 0.12);
border-radius: 14rpx;
padding: 14rpx 16rpx;
font-size: 24rpx;
word-break: break-all;
&.amount {
color: #fff8e6;
font-weight: 700;
font-size: 28rpx;
}
&.addr {
color: #f0dbab;
font-family: "Courier New", monospace;
font-size: 20rpx;
}
text {
flex: 1;
}
}
.epay-qr-btn {
flex-shrink: 0;
min-width: 90rpx;
text-align: center;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
color: #231705;
font-size: 22rpx;
padding: 8rpx 18rpx;
border-radius: 10rpx;
font-weight: 700;
}
.epay-qr-meta {
display: flex;
justify-content: space-between;
color: #b7a37d;
font-size: 24rpx;
margin: 20rpx 0 12rpx;
}
.epay-qr-countdown {
color: #e5b932;
font-weight: 700;
}
.epay-qr-tip {
color: #d58c65;
font-size: 22rpx;
text-align: center;
line-height: 1.6;
margin-top: 14rpx;
opacity: 0.92;
}
.alin-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
background: rgba(0, 0, 0, 0.68);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(4px);
}
.alin-pay-box {
width: 92vw;
height: 85vh;
background: linear-gradient(180deg, #17130f 0%, #0d0b09 100%);
border: 1px solid rgba(223, 189, 120, 0.16);
border-radius: 20px;
overflow: hidden;
display: flex;
flex-direction: column;
box-shadow: 0 20px 46px rgba(0, 0, 0, 0.26);
}
.alin-pay-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: rgba(20, 17, 14, 0.96);
border-bottom: 1px solid rgba(223, 189, 120, 0.12);
}
.alin-pay-title {
color: #f4dca3;
font-size: 16px;
font-weight: 700;
}
.alin-iframe {
flex: 1;
width: 100%;
border: none;
background: #fff;
}
</style>