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": "نصائح", "tips": "نصائح",
"leave_agent_tips": "يمكن للمضيف مغادرة الوكيل الحالي فقط في اليوم الأول والـ16 من كل شهر", "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_record_not_found": "Application record not found",
"application_processed_cannot_cancel": "Application has been processed and cannot be canceled", "application_processed_cannot_cancel": "Application has been processed and cannot be canceled",
"cancellation_failed_try_again": "Cancellation failed, please try again", "cancellation_failed_try_again": "Cancellation failed, please try again",

View File

@ -137,6 +137,17 @@
"tips": "Tips", "tips": "Tips",
"leave_agent_tips": "The host can only leave the current agent on the 1st and 16th of each month", "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_record_not_found": "Application record not found",
"application_processed_cannot_cancel": "Application has been processed and cannot be canceled", "application_processed_cannot_cancel": "Application has been processed and cannot be canceled",
"cancellation_failed_try_again": "Cancellation failed, please try again", "cancellation_failed_try_again": "Cancellation failed, please try again",

View File

@ -137,6 +137,17 @@
"tips": "提示", "tips": "提示",
"leave_agent_tips": "主播只能在每月1日和16日离开当前代理", "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_record_not_found": "申请记录未找到",
"application_processed_cannot_cancel": "申请已被处理,无法取消", "application_processed_cannot_cancel": "申请已被处理,无法取消",
"cancellation_failed_try_again": "取消失败,请重试", "cancellation_failed_try_again": "取消失败,请重试",

View File

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