aslan-h5/src/views/ExchangeGoldCoinsView.vue
2025-08-20 19:37:43 +08:00

374 lines
8.7 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 class="info-section">
<div class="info-header">
<button class="details-btn" @click="showDetails">
Details
</button>
</div>
<div class="available-salary">
<span>Available salary: </span>
<span v-if="loading" class="loading-text">Loading...</span>
<span v-else class="amount">{{ availableSalary }}</span>
</div>
</div>
<!-- 兑换部分 -->
<div class="exchange-section">
<h3>Exchange Gold Coins</h3>
<!-- 金币选择 -->
<div class="coins-grid">
<div
v-for="coin in coinOptions"
:key="coin.id"
@click="selectCoin(coin)"
:class="['coin-item', { selected: selectedCoin === coin.id }]"
>
<div class="coin-icon">🪙</div>
<div class="coin-amount">{{ coin.amount }}</div>
<div class="coin-price">${{ coin.price }}</div>
</div>
</div>
<!-- 兑换按钮 -->
<button
class="exchange-btn"
@click="exchangeCoins"
:disabled="!selectedCoin"
>
Exchange
</button>
</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 } 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
showError('Exchange function is 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')
} 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) {
showError(`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(() => {
fetchBankBalance()
checkUserRole()
})
</script>
<style scoped>
.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;
}
/* 兑换部分 */
.exchange-section {
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.exchange-section h3 {
margin: 0 0 16px 0;
font-size: 18px;
font-weight: 600;
color: #333;
}
/* 金币网格 */
.coins-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
margin-bottom: 20px;
}
.coin-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px 8px;
border: 2px solid #e5e7eb;
border-radius: 12px;
cursor: pointer;
transition: all 0.2s;
background-color: white;
}
.coin-item:hover {
border-color: #8B5CF6;
}
.coin-item.selected {
border-color: #8B5CF6;
background-color: #F3F4F6;
}
.coin-item:active {
transform: scale(0.98);
}
.coin-icon {
font-size: 24px;
margin-bottom: 8px;
}
.coin-amount {
font-size: 14px;
font-weight: 600;
color: #333;
margin-bottom: 4px;
}
.coin-price {
font-size: 12px;
color: #666;
}
/* 兑换按钮 */
.exchange-btn {
width: 100%;
padding: 14px;
background-color: #FCD34D;
color: #92400E;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
}
.exchange-btn:disabled {
background-color: #ccc;
color: #666;
cursor: not-allowed;
}
.exchange-btn:not(:disabled):active {
background-color: #F59E0B;
}
</style>