rwadurian/frontend/admin-web/src/app/(dashboard)/users/[id]/page.tsx

803 lines
36 KiB
TypeScript
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.

'use client';
import { useState, useCallback } from 'react';
import { useParams, useRouter } from 'next/navigation';
import Image from 'next/image';
import Link from 'next/link';
import { Button, toast } from '@/components/common';
import { PageContainer } from '@/components/layout';
import { cn } from '@/utils/helpers';
import { formatNumber, formatRanking } from '@/utils/formatters';
import {
useUserFullDetail,
useReferralTree,
usePlantingLedger,
useWalletLedger,
useAuthorizationDetail,
} from '@/hooks/useUserDetailPage';
import type {
ReferralNode,
PlantingLedgerItem,
WalletLedgerItem,
WALLET_ENTRY_TYPE_LABELS,
ASSET_TYPE_LABELS,
PLANTING_STATUS_LABELS,
AUTHORIZATION_ROLE_LABELS,
AUTHORIZATION_STATUS_LABELS,
ASSESSMENT_RESULT_LABELS,
} from '@/types/userDetail.types';
import { PROVINCE_CODE_NAMES, CITY_CODE_NAMES } from '@/types';
import styles from './user-detail.module.scss';
// Tab 类型
type TabType = 'referral' | 'planting' | 'wallet' | 'authorization';
const tabs: { key: TabType; label: string }[] = [
{ key: 'referral', label: '引荐关系' },
{ key: 'planting', label: '认种信息' },
{ key: 'wallet', label: '钱包信息' },
{ key: 'authorization', label: '授权信息' },
];
// 流水类型标签
const entryTypeLabels: Record<string, string> = {
DEPOSIT: '充值',
DEPOSIT_USDT: 'USDT充值',
DEPOSIT_BNB: 'BNB充值',
WITHDRAW: '提现',
WITHDRAW_FROZEN: '提现冻结',
WITHDRAW_CONFIRMED: '提现确认',
WITHDRAW_CANCELLED: '提现取消',
PLANTING_PAYMENT: '认种支付',
PLANTING_FROZEN: '认种冻结',
PLANTING_DEDUCT: '认种扣款',
REWARD_PENDING: '收益待领取',
REWARD_SETTLED: '收益结算',
REWARD_EXPIRED: '收益过期',
TRANSFER_OUT: '转出',
TRANSFER_IN: '转入',
INTERNAL_TRANSFER: '内部转账',
ADMIN_ADJUSTMENT: '管理员调整',
SYSTEM_DEDUCT: '系统扣款',
FEE: '手续费',
};
const assetTypeLabels: Record<string, string> = {
USDT: '绿积分',
DST: 'DST',
BNB: 'BNB',
OG: 'OG',
RWAD: 'RWAD',
HASHPOWER: '算力',
};
const plantingStatusLabels: Record<string, string> = {
CREATED: '已创建',
PAID: '已支付',
FUND_ALLOCATED: '资金已分配',
MINING_ENABLED: '已开始挖矿',
CANCELLED: '已取消',
EXPIRED: '已过期',
};
const roleTypeLabels: Record<string, string> = {
COMMUNITY_PARTNER: '社区合伙人',
PROVINCE_COMPANY: '省公司',
CITY_COMPANY: '市公司',
AUTH_PROVINCE_COMPANY: '授权省公司',
AUTH_CITY_COMPANY: '授权市公司',
};
const authStatusLabels: Record<string, string> = {
PENDING: '待授权',
AUTHORIZED: '已授权',
REVOKED: '已撤销',
EXPIRED: '已过期',
};
const assessmentResultLabels: Record<string, string> = {
NOT_ASSESSED: '未考核',
PASSED: '通过',
FAILED: '未通过',
BYPASSED: '豁免',
};
/**
* 将区域代码转换为名称
* @param code 区域代码,如 450000或 451200
* @returns 区域名称
*/
const getRegionName = (code: string | null | undefined): string => {
if (!code) return '-';
// 先尝试查找城市
if (CITY_CODE_NAMES[code]) {
return CITY_CODE_NAMES[code];
}
// 再尝试查找省份
if (PROVINCE_CODE_NAMES[code]) {
return PROVINCE_CODE_NAMES[code];
}
// 尝试去掉后4位的0如 450000 -> 45查找省份
if (code.length === 6 && code.endsWith('0000')) {
const shortCode = code.substring(0, 2);
if (PROVINCE_CODE_NAMES[shortCode]) {
return PROVINCE_CODE_NAMES[shortCode];
}
}
return code;
};
/**
* 用户详情页面
*/
export default function UserDetailPage() {
const params = useParams();
const router = useRouter();
const accountSequence = params.id as string;
const [activeTab, setActiveTab] = useState<TabType>('referral');
const [treeRootUser, setTreeRootUser] = useState<string>(accountSequence);
const [plantingPage, setPlantingPage] = useState(1);
const [walletPage, setWalletPage] = useState(1);
// 获取用户完整信息
const { data: userDetail, isLoading: detailLoading, error: detailError } = useUserFullDetail(accountSequence);
// 获取推荐关系树(以当前选中的用户为根)
const { data: referralTree, isLoading: treeLoading } = useReferralTree(treeRootUser, 'both', 1);
// 获取认种分类账
const { data: plantingData, isLoading: plantingLoading } = usePlantingLedger(accountSequence, {
page: plantingPage,
pageSize: 10,
});
// 获取钱包分类账
const { data: walletData, isLoading: walletLoading } = useWalletLedger(accountSequence, {
page: walletPage,
pageSize: 10,
});
// 获取授权信息
const { data: authData, isLoading: authLoading } = useAuthorizationDetail(accountSequence);
// 切换推荐关系树的根节点
const handleTreeNodeClick = useCallback((node: ReferralNode) => {
setTreeRootUser(node.accountSequence);
}, []);
// 返回列表
const handleBack = useCallback(() => {
router.push('/users');
}, [router]);
// 格式化日期
const formatDate = (dateStr: string | null) => {
if (!dateStr) return '-';
return new Date(dateStr).toLocaleString('zh-CN');
};
// 格式化金额
const formatAmount = (amount: string | null) => {
if (!amount) return '-';
const num = parseFloat(amount);
return num.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 8 });
};
if (detailLoading) {
return (
<PageContainer title="用户详情">
<div className={styles.loading}>...</div>
</PageContainer>
);
}
if (detailError || !userDetail) {
return (
<PageContainer title="用户详情">
<div className={styles.error}>
<p>: {(detailError as Error)?.message || '用户不存在'}</p>
<Button onClick={handleBack}></Button>
</div>
</PageContainer>
);
}
return (
<PageContainer title={`用户详情 - ${userDetail.accountSequence}`}>
<div className={styles.userDetail}>
{/* 返回按钮 */}
<div className={styles.userDetail__backBar}>
<button className={styles.userDetail__backBtn} onClick={handleBack}>
<span className={styles.userDetail__backIcon}></span>
</button>
</div>
{/* 用户基本信息卡片 */}
<div className={styles.userDetail__basicCard}>
<div className={styles.userDetail__basicHeader}>
<div
className={styles.userDetail__avatar}
style={{ backgroundImage: `url(${userDetail.avatar || '/images/Data@2x.png'})` }}
>
<div
className={cn(
styles.userDetail__status,
userDetail.isOnline ? styles['userDetail__status--online'] : styles['userDetail__status--offline']
)}
/>
</div>
<div className={styles.userDetail__basicInfo}>
<h1 className={styles.userDetail__nickname}>
{userDetail.nickname || '未设置昵称'}
<span className={cn(
styles.userDetail__statusBadge,
styles[`userDetail__statusBadge--${userDetail.status}`]
)}>
{userDetail.status === 'active' ? '正常' : userDetail.status === 'frozen' ? '冻结' : '停用'}
</span>
</h1>
<div className={styles.userDetail__basicMeta}>
<span>: <strong>{userDetail.accountSequence}</strong></span>
<span>: {userDetail.phoneNumberMasked || '未绑定'}</span>
<span>KYC: {userDetail.kycStatus}</span>
</div>
<div className={styles.userDetail__basicMeta}>
<span>: {formatDate(userDetail.registeredAt)}</span>
<span>: {formatDate(userDetail.lastActiveAt)}</span>
</div>
</div>
</div>
{/* 统计卡片 */}
<div className={styles.userDetail__statsGrid}>
<div className={styles.userDetail__statCard}>
<span className={styles.userDetail__statLabel}></span>
<span className={styles.userDetail__statValue}>{formatNumber(userDetail.personalAdoptions)}</span>
</div>
<div className={styles.userDetail__statCard}>
<span className={styles.userDetail__statLabel}></span>
<span className={styles.userDetail__statValue}>{formatNumber(userDetail.teamAdoptions)}</span>
</div>
<div className={styles.userDetail__statCard}>
<span className={styles.userDetail__statLabel}></span>
<span className={styles.userDetail__statValue}>{formatNumber(userDetail.teamAddresses)}</span>
</div>
<div className={styles.userDetail__statCard}>
<span className={styles.userDetail__statLabel}></span>
<span className={cn(
styles.userDetail__statValue,
userDetail.ranking && userDetail.ranking <= 10 && styles['userDetail__statValue--gold']
)}>
{userDetail.ranking ? formatRanking(userDetail.ranking) : '-'}
</span>
</div>
<div className={styles.userDetail__statCard}>
<span className={styles.userDetail__statLabel}></span>
<span className={styles.userDetail__statValue}>
{formatNumber(userDetail.referralInfo.directReferralCount)}
</span>
</div>
</div>
{/* 引荐人信息 */}
{userDetail.referralInfo.referrerSequence && (
<div className={styles.userDetail__referrerInfo}>
<span className={styles.userDetail__referrerLabel}>:</span>
<Link
href={`/users/${userDetail.referralInfo.referrerSequence}`}
className={styles.userDetail__referrerLink}
>
{userDetail.referralInfo.referrerSequence}
{userDetail.referralInfo.referrerNickname && ` (${userDetail.referralInfo.referrerNickname})`}
</Link>
<span className={styles.userDetail__referrerMeta}>
: {userDetail.referralInfo.usedReferralCode || '-'}
</span>
<span className={styles.userDetail__referrerMeta}>
: {userDetail.referralInfo.depth}
</span>
</div>
)}
</div>
{/* Tab 切换 */}
<div className={styles.userDetail__tabs}>
{tabs.map((tab) => (
<button
key={tab.key}
className={cn(
styles.userDetail__tab,
activeTab === tab.key && styles['userDetail__tab--active']
)}
onClick={() => setActiveTab(tab.key)}
>
{tab.label}
</button>
))}
</div>
{/* Tab 内容 */}
<div className={styles.userDetail__tabContent}>
{/* 引荐关系 Tab */}
{activeTab === 'referral' && (
<div className={styles.referralTab}>
<div className={styles.referralTab__header}>
<h3></h3>
{treeRootUser !== accountSequence && (
<Button
variant="outline"
size="sm"
onClick={() => setTreeRootUser(accountSequence)}
>
</Button>
)}
</div>
{treeLoading ? (
<div className={styles.referralTab__loading}>...</div>
) : referralTree ? (
<div className={styles.referralTree}>
{/* 向上的引荐人链 */}
{referralTree.ancestors.length > 0 && (
<div className={styles.referralTree__ancestors}>
<div className={styles.referralTree__label}> ()</div>
<div className={styles.referralTree__nodeList}>
{referralTree.ancestors.map((ancestor, index) => (
<div key={ancestor.accountSequence} className={styles.referralTree__nodeWrapper}>
<button
className={styles.referralTree__node}
onClick={() => handleTreeNodeClick(ancestor)}
>
<span className={styles.referralTree__nodeSeq}>{ancestor.accountSequence}</span>
<span className={styles.referralTree__nodeNickname}>
{ancestor.nickname || '未设置'}
</span>
<span className={styles.referralTree__nodeAdoptions}>
: {formatNumber(ancestor.personalAdoptions)}
</span>
</button>
{index < referralTree.ancestors.length - 1 && (
<div className={styles.referralTree__connector}></div>
)}
</div>
))}
</div>
<div className={styles.referralTree__connector}></div>
</div>
)}
{/* 当前用户 */}
<div className={styles.referralTree__current}>
<div
className={cn(
styles.referralTree__node,
styles['referralTree__node--current'],
referralTree.currentUser.accountSequence === accountSequence &&
styles['referralTree__node--highlight']
)}
>
<span className={styles.referralTree__nodeSeq}>
{referralTree.currentUser.accountSequence}
</span>
<span className={styles.referralTree__nodeNickname}>
{referralTree.currentUser.nickname || '未设置'}
</span>
<span className={styles.referralTree__nodeAdoptions}>
: {formatNumber(referralTree.currentUser.personalAdoptions)}
</span>
<span className={styles.referralTree__nodeCount}>
: {formatNumber(referralTree.currentUser.directReferralCount)}
</span>
</div>
</div>
{/* 引荐用户 */}
{referralTree.directReferrals.length > 0 && (
<div className={styles.referralTree__directReferrals}>
<div className={styles.referralTree__connector}></div>
<div className={styles.referralTree__label}>
({referralTree.directReferrals.length})
</div>
<div className={styles.referralTree__nodeGrid}>
{referralTree.directReferrals.map((referral) => (
<button
key={referral.accountSequence}
className={styles.referralTree__node}
onClick={() => handleTreeNodeClick(referral)}
>
<span className={styles.referralTree__nodeSeq}>{referral.accountSequence}</span>
<span className={styles.referralTree__nodeNickname}>
{referral.nickname || '未设置'}
</span>
<span className={styles.referralTree__nodeAdoptions}>
: {formatNumber(referral.personalAdoptions)}
</span>
{referral.directReferralCount > 0 && (
<span className={styles.referralTree__nodeCount}>
: {formatNumber(referral.directReferralCount)}
</span>
)}
</button>
))}
</div>
</div>
)}
{referralTree.directReferrals.length === 0 && referralTree.ancestors.length === 0 && (
<div className={styles.referralTree__empty}></div>
)}
</div>
) : (
<div className={styles.referralTab__empty}></div>
)}
</div>
)}
{/* 认种信息 Tab */}
{activeTab === 'planting' && (
<div className={styles.plantingTab}>
{plantingLoading ? (
<div className={styles.plantingTab__loading}>...</div>
) : plantingData ? (
<>
{/* 认种汇总 */}
<div className={styles.plantingTab__summary}>
<h3></h3>
<div className={styles.plantingTab__summaryGrid}>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}></span>
<span className={styles.plantingTab__summaryValue}>
{formatNumber(plantingData.summary.totalOrders)}
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}></span>
<span className={styles.plantingTab__summaryValue}>
{formatNumber(plantingData.summary.totalTreeCount)}
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}> (绿)</span>
<span className={styles.plantingTab__summaryValue}>
{formatAmount(plantingData.summary.totalAmount)}
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}></span>
<span className={styles.plantingTab__summaryValue}>
{formatNumber(plantingData.summary.effectiveTreeCount)}
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}></span>
<span className={styles.plantingTab__summaryValue}>
{formatDate(plantingData.summary.firstPlantingAt)}
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}></span>
<span className={styles.plantingTab__summaryValue}>
{formatDate(plantingData.summary.lastPlantingAt)}
</span>
</div>
</div>
</div>
{/* 认种分类账 */}
<div className={styles.plantingTab__ledger}>
<h3></h3>
<div className={styles.ledgerTable}>
<div className={styles.ledgerTable__header}>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
</div>
{plantingData.items.length === 0 ? (
<div className={styles.ledgerTable__empty}></div>
) : (
plantingData.items.map((item) => (
<div key={item.orderId} className={styles.ledgerTable__row}>
<div className={styles.ledgerTable__cell}>{item.orderNo}</div>
<div className={styles.ledgerTable__cell}>{formatNumber(item.treeCount)}</div>
<div className={styles.ledgerTable__cell}>{formatAmount(item.totalAmount)}</div>
<div className={styles.ledgerTable__cell}>
{getRegionName(item.selectedProvince)} / {getRegionName(item.selectedCity)}
</div>
<div className={styles.ledgerTable__cell}>{formatDate(item.createdAt)}</div>
<div className={styles.ledgerTable__cell}>{formatDate(item.paidAt)}</div>
</div>
))
)}
</div>
{/* 分页 */}
{plantingData.totalPages > 1 && (
<div className={styles.pagination}>
<button
disabled={plantingPage === 1}
onClick={() => setPlantingPage((p) => p - 1)}
>
</button>
<span> {plantingPage} / {plantingData.totalPages} </span>
<button
disabled={plantingPage === plantingData.totalPages}
onClick={() => setPlantingPage((p) => p + 1)}
>
</button>
</div>
)}
</div>
</>
) : (
<div className={styles.plantingTab__empty}></div>
)}
</div>
)}
{/* 钱包信息 Tab */}
{activeTab === 'wallet' && (
<div className={styles.walletTab}>
{walletLoading ? (
<div className={styles.walletTab__loading}>...</div>
) : walletData ? (
<>
{/* 钱包汇总 */}
<div className={styles.walletTab__summary}>
<h3></h3>
<div className={styles.walletTab__summaryGrid}>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}>绿 </span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.usdtAvailable)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}>绿 </span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.usdtFrozen)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}></span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.pendingUsdt)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}></span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.settleableUsdt)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}></span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.settledTotalUsdt)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}></span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.expiredTotalUsdt)}
</span>
</div>
</div>
</div>
{/* 钱包分类账 */}
<div className={styles.walletTab__ledger}>
<h3></h3>
<div className={styles.ledgerTable}>
<div className={styles.ledgerTable__header}>
<div className={styles.ledgerTable__cell}>ID</div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
</div>
{walletData.items.length === 0 ? (
<div className={styles.ledgerTable__empty}></div>
) : (
walletData.items.map((item) => (
<div key={item.entryId} className={styles.ledgerTable__row}>
<div className={styles.ledgerTable__cell}>{item.entryId}</div>
<div className={styles.ledgerTable__cell}>
{entryTypeLabels[item.entryType] || item.entryType}
</div>
<div className={styles.ledgerTable__cell}>
{assetTypeLabels[item.assetType] || item.assetType}
</div>
<div className={cn(
styles.ledgerTable__cell,
parseFloat(item.amount) >= 0
? styles['ledgerTable__cell--positive']
: styles['ledgerTable__cell--negative']
)}>
{parseFloat(item.amount) >= 0 ? '+' : ''}{formatAmount(item.amount)}
</div>
<div className={styles.ledgerTable__cell}>
{formatAmount(item.balanceAfter)}
</div>
<div className={styles.ledgerTable__cell}>
{item.refOrderId || item.refTxHash || '-'}
</div>
<div className={styles.ledgerTable__cell}>{formatDate(item.createdAt)}</div>
</div>
))
)}
</div>
{/* 分页 */}
{walletData.totalPages > 1 && (
<div className={styles.pagination}>
<button
disabled={walletPage === 1}
onClick={() => setWalletPage((p) => p - 1)}
>
</button>
<span> {walletPage} / {walletData.totalPages} </span>
<button
disabled={walletPage === walletData.totalPages}
onClick={() => setWalletPage((p) => p + 1)}
>
</button>
</div>
)}
</div>
</>
) : (
<div className={styles.walletTab__empty}></div>
)}
</div>
)}
{/* 授权信息 Tab */}
{activeTab === 'authorization' && (
<div className={styles.authTab}>
{authLoading ? (
<div className={styles.authTab__loading}>...</div>
) : authData ? (
<>
{/* 授权角色列表 */}
<div className={styles.authTab__roles}>
<h3></h3>
{authData.roles.length === 0 ? (
<div className={styles.authTab__empty}></div>
) : (
<div className={styles.authTab__roleGrid}>
{authData.roles.map((role) => (
<div key={role.id} className={styles.authTab__roleCard}>
<div className={styles.authTab__roleHeader}>
<span className={styles.authTab__roleType}>
{roleTypeLabels[role.roleType] || role.roleType}
</span>
<span className={cn(
styles.authTab__roleStatus,
styles[`authTab__roleStatus--${role.status.toLowerCase()}`]
)}>
{authStatusLabels[role.status] || role.status}
</span>
</div>
<div className={styles.authTab__roleInfo}>
<p><strong>:</strong> {role.regionName} ({role.regionCode})</p>
<p><strong>:</strong> {role.displayTitle}</p>
<p>
<strong>:</strong>
{role.benefitActive ? (
<span className={styles.authTab__benefitActive}></span>
) : (
<span className={styles.authTab__benefitInactive}></span>
)}
</p>
<p><strong>:</strong> {formatNumber(role.initialTargetTreeCount)} </p>
<p><strong>:</strong> {role.monthlyTargetType}</p>
<p><strong>:</strong> {formatDate(role.authorizedAt)}</p>
</div>
</div>
))}
</div>
)}
</div>
{/* 月度考核记录 */}
<div className={styles.authTab__assessments}>
<h3></h3>
{authData.assessments.length === 0 ? (
<div className={styles.authTab__empty}></div>
) : (
<div className={styles.ledgerTable}>
<div className={styles.ledgerTable__header}>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}>/</div>
<div className={styles.ledgerTable__cell}>/</div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
</div>
{authData.assessments.map((assessment) => (
<div key={assessment.id} className={styles.ledgerTable__row}>
<div className={styles.ledgerTable__cell}>{assessment.assessmentMonth}</div>
<div className={styles.ledgerTable__cell}>
{roleTypeLabels[assessment.roleType] || assessment.roleType}
</div>
<div className={styles.ledgerTable__cell}>
{formatNumber(assessment.monthlyCompleted)} / {formatNumber(assessment.monthlyTarget)}
</div>
<div className={styles.ledgerTable__cell}>
{formatNumber(assessment.cumulativeCompleted)} / {formatNumber(assessment.cumulativeTarget)}
</div>
<div className={styles.ledgerTable__cell}>
<span className={cn(
styles.ledgerTable__result,
styles[`ledgerTable__result--${assessment.result.toLowerCase()}`]
)}>
{assessmentResultLabels[assessment.result] || assessment.result}
</span>
</div>
<div className={styles.ledgerTable__cell}>
{assessment.rankingInRegion || '-'}
{assessment.isFirstPlace && ' 🥇'}
</div>
</div>
))}
</div>
)}
</div>
{/* 系统账户流水(如果有) */}
{authData.systemAccountLedger.length > 0 && (
<div className={styles.authTab__systemLedger}>
<h3></h3>
<div className={styles.ledgerTable}>
<div className={styles.ledgerTable__header}>
<div className={styles.ledgerTable__cell}>ID</div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
<div className={styles.ledgerTable__cell}></div>
</div>
{authData.systemAccountLedger.map((ledger) => (
<div key={ledger.ledgerId} className={styles.ledgerTable__row}>
<div className={styles.ledgerTable__cell}>{ledger.ledgerId}</div>
<div className={styles.ledgerTable__cell}>{ledger.accountType}</div>
<div className={styles.ledgerTable__cell}>{ledger.entryType}</div>
<div className={cn(
styles.ledgerTable__cell,
parseFloat(ledger.amount) >= 0
? styles['ledgerTable__cell--positive']
: styles['ledgerTable__cell--negative']
)}>
{parseFloat(ledger.amount) >= 0 ? '+' : ''}{formatAmount(ledger.amount)}
</div>
<div className={styles.ledgerTable__cell}>{formatAmount(ledger.balanceAfter)}</div>
<div className={styles.ledgerTable__cell}>{formatDate(ledger.createdAt)}</div>
</div>
))}
</div>
</div>
)}
</>
) : (
<div className={styles.authTab__empty}></div>
)}
</div>
)}
</div>
</div>
</PageContainer>
);
}