aslan-h5/src/views/ExchangeGoldCoinsView.vue
2025-09-25 14:46:02 +08:00

377 lines
9.4 KiB
Vue
Raw 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>
<div class="exchange-gold-coins gradient-background-circles">
<MobileHeader title="Exchange Gold Coins" />
<div class="content">
<!-- 信息部分 -->
<div>
<div
style="
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
"
>
<div style="font-weight: 600">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>
</div>
<div
style="
background-color: white;
padding: 16px;
border-radius: 12px;
margin-bottom: 12px;
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 v-else style="font-weight: 700; color: #333; font-size: 1.1em">{{
availableSalary
}}</span>
</div>
</div>
<!-- 兑换部分 -->
<div>
<div style="font-weight: 600; margin-bottom: 10px">Exchange Gold Coins</div>
<div
style="
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
"
>
<!-- 金币选择 -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
<div
v-for="coin in coinOptions"
:key="coin.id"
@click="selectCoin(coin)"
:class="['coin-item', { selected: selectedCoin === coin.id }]"
>
<img src="../assets/icon/coin.png" alt="" style="width: 40%" />
<div style="font-weight: 500; color: #373232">{{ coin.amount }}</div>
<div style="font-weight: 500; color: #131111">${{ coin.price }}</div>
</div>
</div>
</div>
<!-- 兑换按钮 -->
<div style="display: flex; justify-content: center; margin-top: 10px">
<button class="exchange-btn" @click="exchangeCoins" :disabled="!selectedCoin">
Exchange
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import { getBankBalance, userSalaryCheckExchange, userBankExchangeGold } from '../api/wallet.js'
import { showError, showSuccess, showWarning } from '@/utils/toast.js'
const router = useRouter()
const availableSalary = ref('0')
const selectedCoin = ref(null)
const loading = ref(false)
const isLoadingRole = ref(false)
const userRole = ref('')
const selectedUserType = ref('')
// 金币选项
const coinOptions = reactive([
{ id: 1, amount: 10000, price: 1 },
{ id: 2, amount: 50000, price: 5 },
{ id: 3, amount: 100000, price: 10 },
{ id: 4, amount: 500000, price: 50 },
{ id: 5, amount: 1000000, price: 100 },
{ id: 6, amount: 2000000, price: 200 },
])
// 获取银行余额
const fetchBankBalance = async () => {
loading.value = true
try {
const response = await getBankBalance()
if (response.status && typeof response.body === 'number') {
// 格式化余额显示保留2位小数
availableSalary.value = response.body.toFixed(2)
} else {
availableSalary.value = '0.00'
}
} catch (error) {
console.error('Failed to fetch bank balance:', error)
availableSalary.value = '0.00'
// 可以显示错误提示
showError('Failed to load balance. Please try again.')
} finally {
loading.value = false
}
}
// 检查用户exchange角色
// 检查用户exchange角色
const checkUserRole = async () => {
isLoadingRole.value = true
try {
const response = await userSalaryCheckExchange()
if (response.status && response.body) {
// 根据接口返回的role设置用户角色
userRole.value = response.body.role || ''
console.debug('用户角色:', userRole.value)
// 设置默认的用户类型
if (userRole.value === 'TEAM_OWN') {
selectedUserType.value = 'ANCHOR' // TEAM_OWN 默认选择 ANCHOR
} else {
selectedUserType.value = 'AGENT' // 其他角色默认选择 AGENT
}
} else {
// 接口返回成功但没有有效数据的情况
userRole.value = ''
selectedUserType.value = 'USER'
router.back() // 对于其他严重错误,也建议退出页面
}
} catch (error) {
// 处理特定错误情况
if (error.errorCode === 1083) {
// NOT_OPEN_ERROR
showWarning('Exchange NOT_OPEN_ERROR')
} 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'
)
} else {
// 其他错误情况
showError('Failed to load user information')
}
router.back() // 对于其他严重错误,也建议退出页面
// 清理状态
userRole.value = ''
selectedUserType.value = 'USER'
} finally {
isLoadingRole.value = false
}
}
const exchangeCoins = async () => {
if (!selectedCoin.value) {
showError('Please select a coin amount first')
return
}
const selectedCoinData = coinOptions.find((coin) => coin.id === selectedCoin.value)
// 检查余额是否足够
const coinPrice = selectedCoinData.price
const availableBalance = parseFloat(availableSalary.value)
if (isNaN(availableBalance) || availableBalance < coinPrice) {
showError(
`Insufficient balance. Your current balance is $${availableBalance.toFixed(
2
)}, but you need $${coinPrice} to exchange.`
)
return
}
// 显示确认对话框
const confirmExchange = confirm(
`Do you want to exchange ${selectedCoinData.amount} coins for $${selectedCoinData.price}?`
)
if (confirmExchange) {
try {
// 调用接口进行兑换
const response = await userBankExchangeGold({
coinId: selectedCoinData.id,
amount: selectedCoinData.price,
price: selectedCoinData.price,
})
if (response.status === true || response.errorCode === 0) {
showSuccess(
`Successfully exchanged ${selectedCoinData.amount} coins for $${selectedCoinData.price}`
)
// 刷新银行余额
await fetchBankBalance()
// 重置选择
selectedCoin.value = null
} else {
// 接口调用失败
const errorMessage = response.message || 'Exchange failed, please try again later.'
showError(errorMessage)
}
} catch (error) {
console.error('Exchange error:', error)
showError('An error occurred during the exchange process. Please try again later.')
}
}
// 如果用户取消,则什么都不做
}
// 方法
const showDetails = () => {
router.push('/information-details')
}
const selectCoin = (coin) => {
// 单选逻辑:如果已经选中相同的金币,则取消选择;否则选中新的金币
if (selectedCoin.value === coin.id) {
selectedCoin.value = null
} else {
selectedCoin.value = coin.id
}
}
// 页面加载时获取银行余额
onMounted(() => {
checkUserRole()
fetchBankBalance()
})
</script>
<style scoped>
* {
color: rgba(0, 0, 0, 0.8);
font-family: 'SF Pro Text';
}
.exchange-gold-coins {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
}
.content {
padding: 16px;
position: relative;
z-index: 2;
}
/* 信息部分 */
.info-section {
background-color: white;
padding: 16px;
border-radius: 12px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.info-header {
display: flex;
justify-content: flex-end;
margin-bottom: 12px;
}
.details-btn {
background: none;
border: none;
color: #8b5cf6;
font-size: 14px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
border-radius: 4px;
transition: all 0.2s;
}
.details-btn:hover {
background-color: #f3f4f6;
}
.details-btn:active {
background-color: #e5e7eb;
color: #7c3aed;
}
.available-salary {
font-size: 16px;
color: #333;
}
.available-salary .amount {
font-weight: 600;
color: #333;
}
.available-salary .loading-text {
font-weight: 500;
color: #8b5cf6;
font-style: italic;
}
.coin-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 2px solid #e5e7eb;
border-radius: 12px;
cursor: pointer;
transition: all 0.2s;
background-color: white;
aspect-ratio: 1/1;
}
.coin-item.selected {
border-color: #8b5cf6;
background-color: #f3f4f6;
}
.coin-item:active {
transform: scale(0.98);
}
/* 兑换按钮 */
.exchange-btn {
width: 70%;
border-radius: 32px;
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
border: none;
padding: 12px;
color: white;
}
.exchange-btn:disabled {
background: #ccc;
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 12px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
}
</style>