feat(兑换金币页): 使用新的头部组件,对接语言切换功能并调整布局

This commit is contained in:
hzj 2025-10-30 11:21:52 +08:00
parent bb1db52774
commit 3e5fd32bea
4 changed files with 94 additions and 24 deletions

View File

@ -137,6 +137,17 @@
"tips": "نصائح",
"leave_agent_tips": "يمكن للمضيف مغادرة الوكيل الحالي فقط في اليوم الأول والـ16 من كل شهر",
"loading": "جار التحميل",
"details": "تفاصيل",
"failed_to_load_balance": "فشل تحميل الرصيد. يرجى المحاولة مرة أخرى.",
"failed_to_load_user_info": "فشل تحميل معلومات المستخدم",
"please_select_coin_amount": "يرجى اختيار كمية العملات أولاً",
"insufficient_balance": "رصيد غير كافٍ. رصيدك الحالي هو ${balance} دولارًا، لكنك تحتاج إلى ${price} دولارًا للتبادل.",
"confirm_exchange_coins": "هل تريد تبادل العملات مقابل ${price} دولارًا؟",
"exchange_success": "تم تبادل العملات مقابل ${price} دولارًا بنجاح",
"exchange_failed": "فشل التبادل، يرجى المحاولة لاحقًا.",
"exchange_error_occurred": "حدث خطأ أثناء عملية التبادل. يرجى المحاولة لاحقًا.",
"application_record_not_found": "Application record not found",
"application_processed_cannot_cancel": "Application has been processed and cannot be canceled",
"cancellation_failed_try_again": "Cancellation failed, please try again",

View File

@ -137,6 +137,17 @@
"tips": "Tips",
"leave_agent_tips": "The host can only leave the current agent on the 1st and 16th of each month",
"loading": "Loading",
"details": "Details",
"failed_to_load_balance": "Failed to load balance. Please try again.",
"failed_to_load_user_info": "Failed to load user information",
"please_select_coin_amount": "Please select a coin amount first",
"insufficient_balance": "Insufficient balance. Your current balance is ${balance}, but you need $${price} to exchange.",
"confirm_exchange_coins": "Do you want to exchange coins for $${price}?",
"exchange_success": "Successfully exchanged coins for $${price}",
"exchange_failed": "Exchange failed, please try again later.",
"exchange_error_occurred": "An error occurred during the exchange process. Please try again later.",
"application_record_not_found": "Application record not found",
"application_processed_cannot_cancel": "Application has been processed and cannot be canceled",
"cancellation_failed_try_again": "Cancellation failed, please try again",

View File

@ -137,6 +137,17 @@
"tips": "提示",
"leave_agent_tips": "主播只能在每月1日和16日离开当前代理",
"loading": "加载中",
"details": "详情",
"failed_to_load_balance": "加载余额失败,请重试。",
"failed_to_load_user_info": "加载用户信息失败",
"please_select_coin_amount": "请先选择金币数量",
"insufficient_balance": "余额不足。您当前余额为${balance}美元,但兑换需要${price}美元。",
"confirm_exchange_coins": "您确定要兑换${price}美元的金币吗?",
"exchange_success": "成功兑换${price}美元的金币",
"exchange_failed": "兑换失败,请稍后重试。",
"exchange_error_occurred": "兑换过程中发生错误,请稍后重试。",
"application_record_not_found": "申请记录未找到",
"application_processed_cannot_cancel": "申请已被处理,无法取消",
"cancellation_failed_try_again": "取消失败,请重试",

View File

@ -1,6 +1,13 @@
<template>
<div class="exchange-gold-coins gradient-background-circles">
<MobileHeader title="Exchange Gold Coins" />
<!-- 使用 GeneralHeader 替换 MobileHeader -->
<GeneralHeader
:title="t('exchange_gold_coins')"
:showBack="true"
:showLanguageList="true"
color="black"
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
/>
<div class="content">
<!-- 信息部分 -->
@ -13,10 +20,10 @@
margin-bottom: 10px;
"
>
<div style="font-weight: 600">Information</div>
<div style="font-weight: 600">{{ t('information') }}</div>
<div style="display: flex; align-items: center" @click="showDetails">
<div style="color: rgba(0, 0, 0, 0.4)">Details</div>
<img src="../assets/icon/arrow.png" alt="" width="16px" />
<div style="color: rgba(0, 0, 0, 0.4)">{{ t('details') }}</div>
<img src="../assets/icon/arrow.png" alt="" class="flipImg" />
</div>
</div>
<div
@ -28,8 +35,8 @@
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
"
>
<span style="font-weight: 510; font-size: 1em">Available salary: </span>
<span v-if="loading" class="loading-text">Loading...</span>
<span style="font-weight: 510; font-size: 1em">{{ t('available_salaries') }} </span>
<span v-if="loading" class="loading-text">{{ t('loading') }}...</span>
<span v-else style="font-weight: 700; color: #333; font-size: 1.1em">{{
availableSalary
}}</span>
@ -38,7 +45,7 @@
<!-- 兑换部分 -->
<div>
<div style="font-weight: 600; margin-bottom: 10px">Exchange Gold Coins</div>
<div style="font-weight: 600; margin-bottom: 10px">{{ t('exchange_gold_coins') }}</div>
<div
style="
background-color: white;
@ -64,7 +71,7 @@
<!-- 兑换按钮 -->
<div style="display: flex; justify-content: center; margin-top: 10px">
<button class="exchange-btn" @click="exchangeCoins" :disabled="!selectedCoin">
Exchange
{{ t('exchange') }}
</button>
</div>
</div>
@ -73,14 +80,20 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import GeneralHeader from '@/components/GeneralHeader.vue'
import { getBankBalance, userSalaryCheckExchange, userBankExchangeGold } from '../api/wallet.js'
import { showError, showSuccess, showWarning } from '@/utils/toast.js'
import { setDocumentDirection } from '@/locales/i18n'
const { t, locale } = useI18n()
const router = useRouter()
//
locale.value && setDocumentDirection(locale.value)
const availableSalary = ref('0')
const selectedCoin = ref(null)
const loading = ref(false)
@ -114,7 +127,7 @@ const fetchBankBalance = async () => {
console.error('Failed to fetch bank balance:', error)
availableSalary.value = '0.00'
//
showError('Failed to load balance. Please try again.')
showError(t('failed_to_load_balance'))
} finally {
loading.value = false
}
@ -139,15 +152,13 @@ const checkUserRole = async () => {
//
if (error.errorCode === 1083) {
// NOT_OPEN_ERROR
showWarning('Exchange NOT_OPEN_ERROR')
showWarning(t('exchange_not_available'))
} else if (error.message && error.message.includes('HTTP Error: 406')) {
// 406 Not Acceptable
showError(
'The server cannot produce a response matching the list of acceptable values defined in the request headers'
)
showError(t('request_not_acceptable'))
} else {
//
showError('Failed to load user information')
showError(t('failed_to_load_user_info'))
}
router.back() // 退
@ -160,7 +171,7 @@ const checkUserRole = async () => {
const exchangeCoins = async () => {
if (!selectedCoin.value) {
showError('Please select a coin amount first')
showError(t('please_select_coin_amount'))
return
}
@ -172,15 +183,16 @@ const exchangeCoins = async () => {
if (isNaN(availableBalance) || availableBalance < coinPrice) {
showError(
`Insufficient balance. Your current balance is $${availableBalance.toFixed(
2
)}, but you need $${coinPrice} to exchange.`
t('insufficient_balance', {
balance: availableBalance.toFixed(2),
price: coinPrice,
})
)
return
}
//
const confirmExchange = confirm(`Do you want to exchange coins for $${selectedCoinData.price}?`)
const confirmExchange = confirm(t('confirm_exchange_coins', { price: selectedCoinData.price }))
if (confirmExchange) {
try {
@ -192,7 +204,7 @@ const exchangeCoins = async () => {
})
if (response.status === true || response.errorCode === 0) {
showSuccess(`Successfully exchanged coins for $${selectedCoinData.price}`)
showSuccess(t('exchange_success', { price: selectedCoinData.price }))
//
await fetchBankBalance()
@ -201,12 +213,12 @@ const exchangeCoins = async () => {
selectedCoin.value = null
} else {
//
const errorMessage = response.message || 'Exchange failed, please try again later.'
const errorMessage = response.message || t('exchange_failed')
showError(errorMessage)
}
} catch (error) {
console.error('Exchange error:', error)
showError('An error occurred during the exchange process. Please try again later.')
showError(t('exchange_error_occurred'))
}
}
//
@ -230,6 +242,10 @@ const selectCoin = (coin) => {
onMounted(() => {
checkUserRole()
fetchBankBalance()
console.log(
"document.documentElement.getAttribute('dir') === 'rtl'",
document.documentElement.getAttribute('dir') === 'rtl'
)
})
</script>
@ -334,10 +350,19 @@ onMounted(() => {
border: none;
padding: 12px;
color: white;
font-weight: 600;
cursor: pointer;
}
.exchange-btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.flipImg {
display: block;
width: 16px;
margin-left: 4px;
}
@media screen and (max-width: 360px) {
@ -357,4 +382,16 @@ onMounted(() => {
font-size: 24px;
}
}
/* RTL支持 */
[dir='rtl'] .details-btn {
flex-direction: row-reverse;
}
[dir='rtl'] .flipImg {
margin-left: auto;
margin-right: 4px;
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
</style>