feat: 新增vm支付
This commit is contained in:
parent
4ee2c02daf
commit
28b5702c56
|
|
@ -73,11 +73,140 @@
|
|||
</mf-button>
|
||||
</div>
|
||||
</mf-dialog>
|
||||
|
||||
<!-- VM支付信用卡信息对话框 -->
|
||||
<mf-dialog
|
||||
:visible="vmCardVisible"
|
||||
modal-class="vm-card-dialog"
|
||||
class="vm-card-dialog-wrapper"
|
||||
:title="$t('common.vmCardInfo')"
|
||||
hideTitle
|
||||
:footer="false"
|
||||
unmountOnClose
|
||||
@cancel="cancelVmCard">
|
||||
<div class="vm-card-close">
|
||||
<mf-icon
|
||||
value="icon-close"
|
||||
@click="cancelVmCard" />
|
||||
</div>
|
||||
<div class="vm-card-title">
|
||||
{{ $t('common.vmCardInfo') }}
|
||||
</div>
|
||||
<a-form
|
||||
ref="vmCardFormRef"
|
||||
:model="vmCardForm"
|
||||
:rules="vmCardRules"
|
||||
layout="vertical"
|
||||
class="vm-card-form">
|
||||
<a-form-item
|
||||
:label="$t('common.cardNumber')"
|
||||
field="number">
|
||||
<a-input
|
||||
v-model="vmCardForm.number"
|
||||
:placeholder="$t('common.cardNumberPlaceholder')"
|
||||
:max-length="50" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('common.cvc')"
|
||||
field="cvc">
|
||||
<a-input
|
||||
v-model="vmCardForm.cvc"
|
||||
:placeholder="$t('common.cvcPlaceholder')"
|
||||
:max-length="3"
|
||||
type="password" />
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
:label="$t('common.expYear')"
|
||||
field="expYear">
|
||||
<a-input
|
||||
v-model="vmCardForm.expYear"
|
||||
:placeholder="$t('common.expYearPlaceholder')"
|
||||
:max-length="4" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
:label="$t('common.expMonth')"
|
||||
field="expMonth">
|
||||
<a-select
|
||||
v-model="vmCardForm.expMonth"
|
||||
:placeholder="$t('common.expMonthPlaceholder')">
|
||||
<a-option
|
||||
v-for="month in monthOptions"
|
||||
:key="month.value"
|
||||
:value="month.value">
|
||||
{{ month.label }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
:label="$t('common.email')"
|
||||
field="email">
|
||||
<a-input
|
||||
v-model="vmCardForm.email"
|
||||
:placeholder="$t('common.emailPlaceholder')"
|
||||
:max-length="30" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('common.firstName')"
|
||||
field="firstName">
|
||||
<a-input
|
||||
v-model="vmCardForm.firstName"
|
||||
:placeholder="$t('common.firstNamePlaceholder')"
|
||||
:max-length="30" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('common.lastName')"
|
||||
field="lastName">
|
||||
<a-input
|
||||
v-model="vmCardForm.lastName"
|
||||
:placeholder="$t('common.lastNamePlaceholder')"
|
||||
:max-length="30" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="$t('common.country')"
|
||||
field="country">
|
||||
<a-select
|
||||
v-model="vmCardForm.country"
|
||||
:placeholder="$t('common.countryPlaceholder')"
|
||||
show-search
|
||||
:filter-option="filterCountry">
|
||||
<a-option
|
||||
v-for="country in countryList"
|
||||
:key="country.code"
|
||||
:value="country.code">
|
||||
{{ getCountryName(country) }} ({{ country.code }})
|
||||
</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<div class="vm-card-submit">
|
||||
<mf-button
|
||||
size="large"
|
||||
type="primary"
|
||||
:loading="vmCardLoading"
|
||||
@click="submitVmCard">
|
||||
{{ $t('common.submit') }}
|
||||
</mf-button>
|
||||
<mf-button
|
||||
size="large"
|
||||
@click="cancelVmCard">
|
||||
{{ $t('common.cancel') }}
|
||||
</mf-button>
|
||||
</div>
|
||||
</mf-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { v4 } from 'uuid'
|
||||
import { countryList } from '@/utils/countryCodes'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'mf-recharge-pc',
|
||||
data() {
|
||||
|
|
@ -90,20 +219,100 @@ export default {
|
|||
rechargeRemark: '',
|
||||
payVisible: false,
|
||||
orderNo: null,
|
||||
showPay: import.meta.env.VITE_SHOW_PAY == "SUCCESS"
|
||||
showPay: import.meta.env.VITE_SHOW_PAY == "SUCCESS",
|
||||
// VM支付相关
|
||||
vmCardVisible: false,
|
||||
vmCardLoading: false,
|
||||
currentGearId: null,
|
||||
vmCardForm: {
|
||||
number: '',
|
||||
cvc: '',
|
||||
expYear: '',
|
||||
expMonth: '',
|
||||
email: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
country: ''
|
||||
},
|
||||
vmCardRules: {},
|
||||
monthOptions: [
|
||||
{ value: '01', label: '01' },
|
||||
{ value: '02', label: '02' },
|
||||
{ value: '03', label: '03' },
|
||||
{ value: '04', label: '04' },
|
||||
{ value: '05', label: '05' },
|
||||
{ value: '06', label: '06' },
|
||||
{ value: '07', label: '07' },
|
||||
{ value: '08', label: '08' },
|
||||
{ value: '09', label: '09' },
|
||||
{ value: '10', label: '10' },
|
||||
{ value: '11', label: '11' },
|
||||
{ value: '12', label: '12' }
|
||||
],
|
||||
countryList: countryList
|
||||
}
|
||||
},
|
||||
props: {
|
||||
rechargeId: [String, Number],
|
||||
apiUrl: String
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['lang']),
|
||||
isVmPay() {
|
||||
// 判断是否是VM支付,根据apiUrl判断
|
||||
return this.apiUrl && (this.apiUrl.includes('vm') || this.apiUrl.includes('vm-pay'))
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
rechargeId(val) {
|
||||
if (!val) return
|
||||
this.getGiftInfo()
|
||||
},
|
||||
lang() {
|
||||
// 语言切换时更新验证规则
|
||||
this.initVmCardRules()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initVmCardRules()
|
||||
},
|
||||
methods: {
|
||||
// 初始化VM卡表单验证规则
|
||||
initVmCardRules() {
|
||||
this.vmCardRules = {
|
||||
number: [
|
||||
{ required: true, message: this.$t('common.cardNumberRequired') || '请输入信用卡卡号', trigger: 'blur' },
|
||||
{ pattern: /^\d{13,19}$/, message: this.$t('common.cardNumberInvalid') || '信用卡卡号格式不正确', trigger: 'blur' }
|
||||
],
|
||||
cvc: [
|
||||
{ required: true, message: this.$t('common.cvcRequired') || '请输入CVC', trigger: 'blur' },
|
||||
{ pattern: /^\d{3}$/, message: this.$t('common.cvcInvalid') || 'CVC必须是3位数字', trigger: 'blur' }
|
||||
],
|
||||
expYear: [
|
||||
{ required: true, message: this.$t('common.expYearRequired') || '请输入过期年份', trigger: 'blur' },
|
||||
{ pattern: /^\d{4}$/, message: this.$t('common.expYearInvalid') || '年份必须是4位数字', trigger: 'blur' }
|
||||
],
|
||||
expMonth: [
|
||||
{ required: true, message: this.$t('common.expMonthRequired') || '请选择过期月份', trigger: 'change' }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: this.$t('common.emailRequired') || '请输入邮箱', trigger: 'blur' },
|
||||
{ type: 'email', message: this.$t('common.emailInvalid') || '邮箱格式不正确', trigger: 'blur' },
|
||||
{ max: 30, message: this.$t('common.emailMaxLength') || '邮箱不能超过30个字符', trigger: 'blur' }
|
||||
],
|
||||
firstName: [
|
||||
{ required: true, message: this.$t('common.firstNameRequired') || '请输入持卡人名字', trigger: 'blur' },
|
||||
{ max: 30, message: this.$t('common.firstNameMaxLength') || '名字不能超过30个字符', trigger: 'blur' }
|
||||
],
|
||||
lastName: [
|
||||
{ required: true, message: this.$t('common.lastNameRequired') || '请输入持卡人姓氏', trigger: 'blur' },
|
||||
{ max: 30, message: this.$t('common.lastNameMaxLength') || '姓氏不能超过30个字符', trigger: 'blur' }
|
||||
],
|
||||
country: [
|
||||
{ required: true, message: this.$t('common.countryRequired') || '请选择国家', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
},
|
||||
cancelPay() {
|
||||
this.orderNo = null
|
||||
this.payVisible = false
|
||||
|
|
@ -167,7 +376,107 @@ export default {
|
|||
},
|
||||
ok() {
|
||||
let selectedItem = this.dataList[this.selectedIndex]
|
||||
// 如果是VM支付,弹出信用卡信息对话框
|
||||
if (this.isVmPay) {
|
||||
this.currentGearId = selectedItem.id
|
||||
this.vmCardVisible = true
|
||||
this.resetVmCardForm()
|
||||
} else {
|
||||
this.doRecharge(selectedItem.id)
|
||||
}
|
||||
},
|
||||
// 重置VM卡表单
|
||||
resetVmCardForm() {
|
||||
this.vmCardForm = {
|
||||
number: '',
|
||||
cvc: '',
|
||||
expYear: '',
|
||||
expMonth: '',
|
||||
email: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
country: ''
|
||||
}
|
||||
if (this.$refs.vmCardFormRef) {
|
||||
this.$refs.vmCardFormRef.resetFields()
|
||||
}
|
||||
},
|
||||
// 取消VM卡对话框
|
||||
cancelVmCard() {
|
||||
this.vmCardVisible = false
|
||||
this.resetVmCardForm()
|
||||
},
|
||||
// 提交VM卡信息
|
||||
async submitVmCard() {
|
||||
if (!this.$refs.vmCardFormRef) return
|
||||
|
||||
try {
|
||||
await this.$refs.vmCardFormRef.validate()
|
||||
this.vmCardLoading = true
|
||||
|
||||
// 调用VM支付接口
|
||||
this.$axios({
|
||||
url: '/api/pay/vm-pay',
|
||||
method: 'POST',
|
||||
data: {
|
||||
gearId: this.currentGearId,
|
||||
vmCardInfo: {
|
||||
number: this.vmCardForm.number,
|
||||
cvc: this.vmCardForm.cvc,
|
||||
expYear: this.vmCardForm.expYear,
|
||||
expMonth: this.vmCardForm.expMonth,
|
||||
email: this.vmCardForm.email,
|
||||
firstName: this.vmCardForm.firstName,
|
||||
lastName: this.vmCardForm.lastName,
|
||||
country: this.vmCardForm.country
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
this.vmCardLoading = false
|
||||
if (res.code == 200) {
|
||||
this.$message.success(this.$t('common.rechargeSuccessfully') || '支付请求提交成功')
|
||||
this.vmCardVisible = false
|
||||
this.resetVmCardForm()
|
||||
// 获取支付URL并跳转
|
||||
if (res.data?.payUrl) {
|
||||
window.open(res.data.payUrl)
|
||||
}
|
||||
} else {
|
||||
this.$message.error(res.msg || this.$t('common.rechargeFailed') || '支付请求失败')
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.vmCardLoading = false
|
||||
if (err.response && err.response.data && err.response.data.msg) {
|
||||
this.$message.error(err.response.data.msg)
|
||||
} else {
|
||||
this.$message.error(this.$t('common.rechargeFailed') || '支付请求失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
// 表单验证失败
|
||||
console.error('表单验证失败:', error)
|
||||
}
|
||||
},
|
||||
// 获取国家名称(根据当前语言)
|
||||
getCountryName(country) {
|
||||
if (!country) return ''
|
||||
// 如果是英文,显示英文名称
|
||||
if (this.lang === 'en_US') {
|
||||
return country.nameEn || country.name
|
||||
}
|
||||
// 默认显示中文名称
|
||||
return country.name
|
||||
},
|
||||
// 国家下拉框搜索过滤
|
||||
filterCountry(inputValue, option) {
|
||||
const country = this.countryList.find(c => c.code === option.value)
|
||||
if (!country) return false
|
||||
const name = this.getCountryName(country).toLowerCase()
|
||||
const code = country.code.toLowerCase()
|
||||
const searchValue = inputValue.toLowerCase()
|
||||
return name.includes(searchValue) || code.includes(searchValue)
|
||||
},
|
||||
doRecharge(gearId) {
|
||||
this.loading = true
|
||||
|
|
@ -311,9 +620,121 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vm-card-dialog {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(39, 20, 51, 0.7) 0%,
|
||||
rgba(230, 33, 122, 0.7) 49%
|
||||
);
|
||||
border-radius: 20px;
|
||||
border: 2px solid #e6217a;
|
||||
width: 600px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
top: 50% !important;
|
||||
transform: translateY(-50%) !important;
|
||||
&-wrapper {
|
||||
.arco-modal-mask {
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.arco-modal-body {
|
||||
padding: 24px 30px 30px 30px;
|
||||
}
|
||||
|
||||
.vm-card-close {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 6px;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
z-index: 10;
|
||||
|
||||
.mf-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.vm-card-title {
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.vm-card-form {
|
||||
:deep(.arco-form-item-label) {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.arco-input-wrapper),
|
||||
:deep(.arco-select-view-single) {
|
||||
background-color: transparent;
|
||||
border: 1px solid rgba(#ffffff, 0.3);
|
||||
color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
&.arco-input-focus,
|
||||
&.arco-select-view-focus {
|
||||
border-color: rgb(var(--primary-6));
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-input),
|
||||
:deep(.arco-select-view-value) {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.arco-input::placeholder),
|
||||
:deep(.arco-select-placeholder) {
|
||||
color: rgba(#fff, 0.5);
|
||||
}
|
||||
|
||||
:deep(.arco-select-dropdown) {
|
||||
background-color: rgba(39, 20, 51, 0.95);
|
||||
border: 1px solid #e6217a;
|
||||
}
|
||||
|
||||
:deep(.arco-select-option) {
|
||||
color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(230, 33, 122, 0.3);
|
||||
}
|
||||
|
||||
&.arco-select-option-selected {
|
||||
background-color: rgba(230, 33, 122, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vm-card-submit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-top: 30px;
|
||||
.mf-button {
|
||||
width: 160px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mf-recharge-pc {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
gap: 10px;
|
||||
|
||||
&-tips {
|
||||
color: #999;
|
||||
|
|
@ -328,52 +749,106 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
flex-wrap: wrap;
|
||||
gap: 14px;
|
||||
.mf-button {
|
||||
width: 160px;
|
||||
border-radius: 10px;
|
||||
margin: 0 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
width: calc(25% - 20px);
|
||||
flex: 1 1 calc(25% - 10px);
|
||||
min-width: 200px;
|
||||
max-width: 100%;
|
||||
color: #fff;
|
||||
margin: 0 10px 10px 10px;
|
||||
background-color: #1f1f1f;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
padding: clamp(12px, 2vw, 20px);
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
background-color: rgb(var(--primary-6));
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 30px;
|
||||
font-size: clamp(16px, 2.5vw, 30px);
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
overflow-wrap: break-word;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.arco-divider {
|
||||
border-color: rgba(#fff, 0.3);
|
||||
margin: clamp(8px, 1.5vw, 12px) 0;
|
||||
}
|
||||
|
||||
&-value {
|
||||
color: 14px;
|
||||
font-size: clamp(12px, 1.5vw, 14px);
|
||||
line-height: 1.5;
|
||||
span {
|
||||
color: rgb(var(--primary));
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
|
||||
// 大屏幕 (≥1400px)
|
||||
@media (min-width: 1400px) {
|
||||
.mf-recharge-pc {
|
||||
&-item {
|
||||
width: calc(50% - 20px);
|
||||
&-title {
|
||||
font-size: 20px;
|
||||
flex: 1 1 calc(20% - 10px);
|
||||
min-width: 220px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 中等屏幕 (768px - 1199px)
|
||||
@media (min-width: 768px) and (max-width: 1199px) {
|
||||
.mf-recharge-pc {
|
||||
&-item {
|
||||
flex: 1 1 calc(33.333% - 10px);
|
||||
min-width: 180px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 小屏幕 (576px - 767px)
|
||||
@media (min-width: 576px) and (max-width: 767px) {
|
||||
.mf-recharge-pc {
|
||||
&-item {
|
||||
flex: 1 1 calc(50% - 10px);
|
||||
min-width: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端 (≤576px)
|
||||
@media (max-width: 576px) {
|
||||
.mf-recharge-pc {
|
||||
gap: 8px;
|
||||
|
||||
&-item {
|
||||
flex: 1 1 calc(50% - 8px);
|
||||
min-width: 140px;
|
||||
padding: 12px;
|
||||
|
||||
&-title {
|
||||
font-size: clamp(14px, 4vw, 18px);
|
||||
}
|
||||
|
||||
.arco-divider {
|
||||
margin: 10px 0;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
&-value {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -381,6 +856,24 @@ export default {
|
|||
margin-top: 16px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&-submit {
|
||||
flex-direction: column;
|
||||
.mf-button {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 超小屏幕 (≤400px)
|
||||
@media (max-width: 400px) {
|
||||
.mf-recharge-pc {
|
||||
&-item {
|
||||
flex: 1 1 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ export default {
|
|||
forgotPassword: 'Forgot password',
|
||||
registerAccount: 'Register Account',
|
||||
usernamePlaceholder: 'Enter username',
|
||||
emailPlaceholder: 'Enter email',
|
||||
codePlaceholder: 'Enter verification code',
|
||||
confirmPasswordPlaceholder: 'Confirm password',
|
||||
backToLogin: 'Back to Login',
|
||||
|
|
@ -142,5 +141,38 @@ export default {
|
|||
cardName: 'Cardholder Name',
|
||||
cardNoRequired: 'Please enter card number',
|
||||
cardNameRequired: 'Please enter cardholder name',
|
||||
rechargeFailed: 'Recharge failed'
|
||||
rechargeFailed: 'Recharge failed',
|
||||
// VM支付相关
|
||||
vmCardInfo: 'Credit Card Information',
|
||||
cardNumber: 'Card Number',
|
||||
cardNumberPlaceholder: 'Enter card number',
|
||||
cardNumberRequired: 'Please enter card number',
|
||||
cardNumberInvalid: 'Card number must be 13-19 digits',
|
||||
cvc: 'CVC',
|
||||
cvcPlaceholder: 'Enter CVC',
|
||||
cvcRequired: 'Please enter CVC',
|
||||
cvcInvalid: 'CVC must be 3 digits',
|
||||
expYear: 'Expiration Year',
|
||||
expYearPlaceholder: 'Enter expiration year (e.g., 2027)',
|
||||
expYearRequired: 'Please enter expiration year',
|
||||
expYearInvalid: 'Year must be 4 digits',
|
||||
expMonth: 'Expiration Month',
|
||||
expMonthPlaceholder: 'Select expiration month',
|
||||
expMonthRequired: 'Please select expiration month',
|
||||
emailPlaceholder: 'Enter email address',
|
||||
emailRequired: 'Please enter email',
|
||||
emailInvalid: 'Invalid email format',
|
||||
emailMaxLength: 'Email cannot exceed 30 characters',
|
||||
firstName: 'First Name',
|
||||
firstNamePlaceholder: 'Enter first name',
|
||||
firstNameRequired: 'Please enter first name',
|
||||
firstNameMaxLength: 'First name cannot exceed 30 characters',
|
||||
lastName: 'Last Name',
|
||||
lastNamePlaceholder: 'Enter last name',
|
||||
lastNameRequired: 'Please enter last name',
|
||||
lastNameMaxLength: 'Last name cannot exceed 30 characters',
|
||||
country: 'Country',
|
||||
countryPlaceholder: 'Select country',
|
||||
countryRequired: 'Please select country',
|
||||
submit: 'Submit'
|
||||
}
|
||||
|
|
@ -52,7 +52,6 @@ export default {
|
|||
forgotPassword: '忘記密碼',
|
||||
registerAccount: '註冊帳號',
|
||||
usernamePlaceholder: '請輸入帳號',
|
||||
emailPlaceholder: '請輸入郵箱',
|
||||
codePlaceholder: '請輸入驗證碼',
|
||||
confirmPasswordPlaceholder: '請再次輸入密碼',
|
||||
backToLogin: '返回登入',
|
||||
|
|
@ -96,7 +95,6 @@ export default {
|
|||
passwordResetSuccessfully: '密碼重置成功',
|
||||
rechargeSuccessfully: '充值成功',
|
||||
avatar: '頭像',
|
||||
email: '郵箱',
|
||||
input: '請輸入',
|
||||
save: '保存',
|
||||
editEmail: '修改郵箱',
|
||||
|
|
@ -104,7 +102,6 @@ export default {
|
|||
updateAvatarSuccessfully: '頭像更新成功',
|
||||
balenceLow: '您的餘額不足,請充值',
|
||||
confirm: '確定',
|
||||
cancel: '取消',
|
||||
createFailed: '生成失敗,餘額已退回',
|
||||
notice: '提示',
|
||||
oldPasswordPlaceholder: '請輸入舊的密碼',
|
||||
|
|
@ -146,5 +143,40 @@ export default {
|
|||
cardName: '銀行卡姓名',
|
||||
cardNoRequired: '請輸入銀行卡號',
|
||||
cardNameRequired: '請輸入銀行卡姓名',
|
||||
rechargeFailed: '充值失敗'
|
||||
rechargeFailed: '充值失敗',
|
||||
// VM支付相關
|
||||
vmCardInfo: '信用卡信息',
|
||||
cardNumber: '信用卡卡號',
|
||||
cardNumberPlaceholder: '請輸入信用卡卡號',
|
||||
cardNumberRequired: '請輸入信用卡卡號',
|
||||
cardNumberInvalid: '信用卡卡號必須是13-19位數字',
|
||||
cvc: 'CVC',
|
||||
cvcPlaceholder: '請輸入CVC',
|
||||
cvcRequired: '請輸入CVC',
|
||||
cvcInvalid: 'CVC必須是3位數字',
|
||||
expYear: '過期年',
|
||||
expYearPlaceholder: '請輸入過期年份(例如:2027)',
|
||||
expYearRequired: '請輸入過期年份',
|
||||
expYearInvalid: '年份必須是4位數字',
|
||||
expMonth: '過期月',
|
||||
expMonthPlaceholder: '請選擇過期月份',
|
||||
expMonthRequired: '請選擇過期月份',
|
||||
email: '郵箱',
|
||||
emailPlaceholder: '請輸入郵箱地址',
|
||||
emailRequired: '請輸入郵箱',
|
||||
emailInvalid: '郵箱格式不正確',
|
||||
emailMaxLength: '郵箱不能超過30個字符',
|
||||
firstName: '持卡人名字',
|
||||
firstNamePlaceholder: '請輸入持卡人名字',
|
||||
firstNameRequired: '請輸入持卡人名字',
|
||||
firstNameMaxLength: '名字不能超過30個字符',
|
||||
lastName: '持卡人姓氏',
|
||||
lastNamePlaceholder: '請輸入持卡人姓氏',
|
||||
lastNameRequired: '請輸入持卡人姓氏',
|
||||
lastNameMaxLength: '姓氏不能超過30個字符',
|
||||
country: '國家',
|
||||
countryPlaceholder: '請選擇國家',
|
||||
countryRequired: '請選擇國家',
|
||||
submit: '提交',
|
||||
cancel: '取消'
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* ISO 3166-1 alpha-2 国家代码列表
|
||||
* 用于VM支付的国家选择下拉框
|
||||
*/
|
||||
export const countryList = [
|
||||
{ code: 'US', name: '美国', nameEn: 'United States' },
|
||||
{ code: 'GB', name: '英国', nameEn: 'United Kingdom' },
|
||||
{ code: 'CA', name: '加拿大', nameEn: 'Canada' },
|
||||
{ code: 'AU', name: '澳大利亚', nameEn: 'Australia' },
|
||||
{ code: 'DE', name: '德国', nameEn: 'Germany' },
|
||||
{ code: 'FR', name: '法国', nameEn: 'France' },
|
||||
{ code: 'IT', name: '意大利', nameEn: 'Italy' },
|
||||
{ code: 'ES', name: '西班牙', nameEn: 'Spain' },
|
||||
{ code: 'NL', name: '荷兰', nameEn: 'Netherlands' },
|
||||
{ code: 'BE', name: '比利时', nameEn: 'Belgium' },
|
||||
{ code: 'CH', name: '瑞士', nameEn: 'Switzerland' },
|
||||
{ code: 'AT', name: '奥地利', nameEn: 'Austria' },
|
||||
{ code: 'SE', name: '瑞典', nameEn: 'Sweden' },
|
||||
{ code: 'NO', name: '挪威', nameEn: 'Norway' },
|
||||
{ code: 'DK', name: '丹麦', nameEn: 'Denmark' },
|
||||
{ code: 'FI', name: '芬兰', nameEn: 'Finland' },
|
||||
{ code: 'PL', name: '波兰', nameEn: 'Poland' },
|
||||
{ code: 'CZ', name: '捷克', nameEn: 'Czech Republic' },
|
||||
{ code: 'IE', name: '爱尔兰', nameEn: 'Ireland' },
|
||||
{ code: 'PT', name: '葡萄牙', nameEn: 'Portugal' },
|
||||
{ code: 'GR', name: '希腊', nameEn: 'Greece' },
|
||||
{ code: 'JP', name: '日本', nameEn: 'Japan' },
|
||||
{ code: 'KR', name: '韩国', nameEn: 'South Korea' },
|
||||
{ code: 'CN', name: '中国', nameEn: 'China' },
|
||||
{ code: 'HK', name: '香港', nameEn: 'Hong Kong' },
|
||||
{ code: 'SG', name: '新加坡', nameEn: 'Singapore' },
|
||||
{ code: 'MY', name: '马来西亚', nameEn: 'Malaysia' },
|
||||
{ code: 'TH', name: '泰国', nameEn: 'Thailand' },
|
||||
{ code: 'PH', name: '菲律宾', nameEn: 'Philippines' },
|
||||
{ code: 'ID', name: '印度尼西亚', nameEn: 'Indonesia' },
|
||||
{ code: 'IN', name: '印度', nameEn: 'India' },
|
||||
{ code: 'BR', name: '巴西', nameEn: 'Brazil' },
|
||||
{ code: 'MX', name: '墨西哥', nameEn: 'Mexico' },
|
||||
{ code: 'AR', name: '阿根廷', nameEn: 'Argentina' },
|
||||
{ code: 'CL', name: '智利', nameEn: 'Chile' },
|
||||
{ code: 'CO', name: '哥伦比亚', nameEn: 'Colombia' },
|
||||
{ code: 'PE', name: '秘鲁', nameEn: 'Peru' },
|
||||
{ code: 'ZA', name: '南非', nameEn: 'South Africa' },
|
||||
{ code: 'NZ', name: '新西兰', nameEn: 'New Zealand' },
|
||||
{ code: 'AE', name: '阿联酋', nameEn: 'United Arab Emirates' },
|
||||
{ code: 'SA', name: '沙特阿拉伯', nameEn: 'Saudi Arabia' },
|
||||
{ code: 'IL', name: '以色列', nameEn: 'Israel' },
|
||||
{ code: 'TR', name: '土耳其', nameEn: 'Turkey' },
|
||||
{ code: 'RU', name: '俄罗斯', nameEn: 'Russia' },
|
||||
{ code: 'UA', name: '乌克兰', nameEn: 'Ukraine' },
|
||||
{ code: 'RO', name: '罗马尼亚', nameEn: 'Romania' },
|
||||
{ code: 'HU', name: '匈牙利', nameEn: 'Hungary' },
|
||||
{ code: 'BG', name: '保加利亚', nameEn: 'Bulgaria' },
|
||||
{ code: 'HR', name: '克罗地亚', nameEn: 'Croatia' },
|
||||
{ code: 'SK', name: '斯洛伐克', nameEn: 'Slovakia' },
|
||||
{ code: 'SI', name: '斯洛文尼亚', nameEn: 'Slovenia' },
|
||||
{ code: 'EE', name: '爱沙尼亚', nameEn: 'Estonia' },
|
||||
{ code: 'LV', name: '拉脱维亚', nameEn: 'Latvia' },
|
||||
{ code: 'LT', name: '立陶宛', nameEn: 'Lithuania' },
|
||||
{ code: 'IS', name: '冰岛', nameEn: 'Iceland' },
|
||||
{ code: 'LU', name: '卢森堡', nameEn: 'Luxembourg' },
|
||||
{ code: 'MT', name: '马耳他', nameEn: 'Malta' },
|
||||
{ code: 'CY', name: '塞浦路斯', nameEn: 'Cyprus' },
|
||||
{ code: 'TW', name: '台湾', nameEn: 'Taiwan' },
|
||||
{ code: 'MO', name: '澳门', nameEn: 'Macau' },
|
||||
{ code: 'VN', name: '越南', nameEn: 'Vietnam' },
|
||||
{ code: 'MM', name: '缅甸', nameEn: 'Myanmar' },
|
||||
{ code: 'KH', name: '柬埔寨', nameEn: 'Cambodia' },
|
||||
{ code: 'LA', name: '老挝', nameEn: 'Laos' },
|
||||
{ code: 'BN', name: '文莱', nameEn: 'Brunei' },
|
||||
{ code: 'BD', name: '孟加拉国', nameEn: 'Bangladesh' },
|
||||
{ code: 'PK', name: '巴基斯坦', nameEn: 'Pakistan' },
|
||||
{ code: 'LK', name: '斯里兰卡', nameEn: 'Sri Lanka' },
|
||||
{ code: 'NP', name: '尼泊尔', nameEn: 'Nepal' }
|
||||
]
|
||||
|
|
@ -180,7 +180,7 @@ const showRecharge = () => {
|
|||
|
||||
&-left {
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
width: clamp(160px, 12vw, 200px);
|
||||
overflow-y: auto;
|
||||
flex-shrink: 0;
|
||||
|
||||
|
|
@ -200,13 +200,14 @@ const showRecharge = () => {
|
|||
|
||||
&-right {
|
||||
flex-grow: 1;
|
||||
padding: 0 60px 60px 20px;
|
||||
padding: 0 clamp(12px, 4vw, 60px) clamp(20px, 4vw, 60px) clamp(12px, 2vw, 20px);
|
||||
overflow-y: auto;
|
||||
min-width: 0; // 防止 flex 子元素溢出
|
||||
|
||||
&-banner {
|
||||
width: 100%;
|
||||
aspect-ratio: 6 / 1;
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: clamp(20px, 3vw, 40px);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
|
@ -303,6 +304,20 @@ const showRecharge = () => {
|
|||
}
|
||||
}
|
||||
|
||||
// 平板和中等屏幕 (768px - 1024px)
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.recharge {
|
||||
&-left {
|
||||
width: clamp(140px, 15vw, 180px);
|
||||
}
|
||||
|
||||
&-right {
|
||||
padding: 0 clamp(16px, 3vw, 40px) clamp(20px, 3vw, 40px) clamp(12px, 2vw, 20px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端 (≤576px)
|
||||
@media (max-width: 576px) {
|
||||
.recharge {
|
||||
flex-direction: column;
|
||||
|
|
@ -350,18 +365,6 @@ const showRecharge = () => {
|
|||
height: 160px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
:deep(.mf-recharge-pc) {
|
||||
&-item {
|
||||
width: calc(50% - 20px);
|
||||
&-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
.arco-divider {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue