aslan-h5/src/views/InformationDetailsView.vue

387 lines
8.1 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="information-details gradient-background-circles">
<!-- 使用 GeneralHeader 替换 MobileHeader -->
<GeneralHeader
:showLanguageList="true"
:title="t('information_details')"
color="black"
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
/>
<div class="content">
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<div class="loading-spinner"></div>
<p>{{ t('loading') }}...</p>
</div>
<!-- 错误状态 -->
<div v-else-if="error" class="error-state">
<div class="error-icon"></div>
<p>{{ error }}</p>
<button @click="fetchData" class="retry-btn">{{ t('retry') }}</button>
</div>
<!-- 交易记录列表 -->
<div v-else class="transaction-list">
<div v-for="transaction in transactions" :key="transaction.id" class="transaction-item">
<div class="transaction-content">
<!-- 交易信息 -->
<div class="transaction-info">
<div style="margin-bottom: 4px; font-weight: 700">
{{ transaction.eventDescribe }}
</div>
<!-- 用户信息 -->
<!-- <div v-if="transaction.userNickname || transaction.account" class="user-info">
<span v-if="transaction.userNickname" class="user-nickname">{{
transaction.userNickname
}}</span>
<span v-if="transaction.account" class="user-account"
>ID: {{ transaction.account }}</span
>
</div> -->
<p class="transaction-time" style="font-weight: 500; color: rgba(0, 0, 0, 0.4)">
{{ transaction.createTime }}
</p>
</div>
<!-- 交易金额 -->
<div class="transaction-amount" style="font-weight: 500; margin: 0 8px">
{{ transaction.amount > 0 ? '+' : '-' }}{{ Math.abs(transaction.amount) }}
</div>
</div>
</div>
</div>
<!-- 空状态 -->
<div v-if="!loading && !error && transactions.length === 0" class="empty-state">
<div class="empty-icon">📄</div>
<p>{{ t('no_transaction_records') }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import GeneralHeader from '@/components/GeneralHeader.vue'
import { getWalletDetails } from '../api/wallet.js'
import { formatUTCTimeClean } from '@/utils/utcFormat.js'
import { setDocumentDirection } from '@/locales/i18n'
const { t, locale } = useI18n()
// 监听语言变化并设置文档方向
locale.value && setDocumentDirection(locale.value)
const transactions = ref([])
const loading = ref(false)
const error = ref(null)
// 获取数据
const fetchData = async () => {
loading.value = true
error.value = null
try {
const response = await getWalletDetails()
// 处理API返回的数据
if (response.body && Array.isArray(response.body)) {
transactions.value = response.body.map((item) => {
// 根据 event 字段判断是加还是减
let amount = item.amount
let isPositive = false
// 根据事件类型判断显示
switch (item.event) {
case 'RECEIVE_TRANSFER':
// 接收转账 - 显示为正数(绿色)
amount = Math.abs(item.amount)
isPositive = true
break
case 'TRANSFER':
// 转账支出 - 显示为负数(红色)
amount = -Math.abs(item.amount)
isPositive = false
break
default:
// 其他情况根据 type 字段处理
// type: 0 表示收入1 表示支出
if (item.type === 0) {
amount = Math.abs(item.amount)
isPositive = true
} else {
amount = -Math.abs(item.amount)
isPositive = false
}
}
return {
id: item.id,
eventDescribe: item.eventDescribe,
createTime: formatUTCTimeClean(item.createTime),
amount: amount,
balance: item.balance,
event: item.event,
isPositive: isPositive,
// 添加用户信息字段
userAvatar: item.details?.userAvatar || null,
userNickname: item.details?.userNickname || null,
account: item.details?.account || null,
}
})
} else {
transactions.value = []
}
} catch (err) {
console.error('Failed to fetch wallet details:', err)
error.value = err.message || t('failed_to_load_data')
} finally {
loading.value = false
}
}
// 头像占位符
const getAvatarPlaceholder = (nickname) => {
if (!nickname) return 'U'
return nickname.charAt(0).toUpperCase()
}
// 页面加载时获取数据
onMounted(() => {
fetchData()
})
</script>
<style scoped>
* {
color: rgba(0, 0, 0, 0.8);
font-family: 'SF Pro Text';
}
.information-details {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
}
.content {
padding: 16px;
position: relative;
z-index: 2;
}
/* 交易记录列表 */
.transaction-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.transaction-item {
background-color: white;
padding: 12px;
border-radius: 12px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
}
.transaction-content {
display: flex;
align-items: center;
gap: 12px;
}
/* 用户头像 */
.user-avatar-container {
flex-shrink: 0;
}
.user-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
object-fit: cover;
}
.avatar-placeholder {
width: 48px;
height: 48px;
border-radius: 50%;
background-color: #8b5cf6;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 18px;
font-weight: 600;
}
.transaction-info {
flex: 1;
min-width: 0; /* 为了支持text overflow */
}
/* 用户信息 */
.user-info {
display: flex;
flex-direction: column;
gap: 2px;
margin-bottom: 4px;
}
.user-nickname {
font-size: 14px;
font-weight: 500;
color: #333;
}
/* 加载状态 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #666;
}
.loading-spinner {
width: 32px;
height: 32px;
border: 3px solid #f3f3f3;
border-top: 3px solid #8b5cf6;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 16px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-state p {
margin: 0;
font-size: 14px;
}
/* 错误状态 */
.error-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #666;
text-align: center;
}
.error-icon {
font-size: 48px;
margin-bottom: 16px;
}
.error-state p {
margin: 0 0 20px 0;
font-size: 14px;
line-height: 1.5;
}
.retry-btn {
padding: 10px 24px;
background-color: #8b5cf6;
color: white;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
}
.retry-btn:active {
background-color: #7c3aed;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #666;
text-align: center;
}
.empty-icon {
font-size: 48px;
margin-bottom: 16px;
}
.empty-state p {
margin: 0;
font-size: 16px;
}
/* 响应式设计 */
@media (max-width: 480px) {
.transaction-content {
gap: 10px;
}
.user-avatar,
.avatar-placeholder {
width: 40px;
height: 40px;
font-size: 16px;
}
.user-nickname {
font-size: 13px;
}
}
.user-account {
font-size: 0.9em;
}
.transaction-time {
font-size: 1em;
}
.transaction-amount {
font-size: 1.2em;
}
@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;
}
}
/* RTL支持 */
[dir='rtl'] .transaction-content {
flex-direction: row-reverse;
}
[dir='rtl'] .transaction-info {
text-align: right;
}
</style>