/** * 系统账户报表Tab组件 * [2026-01-04] 新增:显示系统账户统计数据 * [2026-01-05] 更新:添加分类账明细显示 * [2026-01-06] 更新:添加收益类型汇总统计(手续费、省团队、市团队、分享引荐、社区) * 回滚方式:删除此文件及整个 system-account-report 目录 */ 'use client'; import { useState, useEffect, useCallback } from 'react'; import { systemAccountReportService } from '@/services/systemAccountReportService'; import type { SystemAccountReportResponse, RegionAccountsSummary, AllSystemAccountsLedgerResponse, FixedAccountLedger, RegionAccountLedger, LedgerEntryDTO, AllRewardTypeSummariesResponse, RewardTypeSummary, FeeAccountSummary, } from '@/types'; import { ENTRY_TYPE_LABELS, ACCOUNT_TYPE_LABELS, FEE_TYPE_LABELS } from '@/types'; import styles from './SystemAccountsTab.module.scss'; /** * 格式化金额显示 */ const formatAmount = (value: string | number | undefined): string => { if (value === undefined || value === null) return '0.00'; const num = typeof value === 'string' ? parseFloat(value) : value; if (isNaN(num)) return '0.00'; return num.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); }; /** * 权益类型显示名称 */ const getRightTypeName = (type: string): string => { const labels: Record = { SETTLEABLE: '可结算收益', SHARE: '分享权益', PROVINCE_TEAM: '省团队权益', CITY_TEAM: '市团队权益', PROVINCE_REGION: '省区域权益', CITY_REGION: '市区域权益', COMMUNITY: '社区权益', }; return labels[type] || type; }; /** * 系统账户报表Tab组件 */ // Tab类型定义 type TabType = 'fixed' | 'province' | 'city' | 'settlement' | 'expired' | 'ledger' | 'feeAccount' | 'provinceTeam' | 'cityTeam' | 'shareReferral' | 'community'; export default function SystemAccountsTab() { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [reportData, setReportData] = useState(null); const [ledgerData, setLedgerData] = useState(null); const [ledgerLoading, setLedgerLoading] = useState(false); // [2026-01-06] 新增:收益类型汇总数据 const [rewardTypeSummaries, setRewardTypeSummaries] = useState(null); const [rewardTypeSummariesLoading, setRewardTypeSummariesLoading] = useState(false); const [activeTab, setActiveTab] = useState('fixed'); // 加载报表数据 const loadReportData = useCallback(async () => { setLoading(true); setError(null); try { const response = await systemAccountReportService.getFullReport(); if (response.data) { setReportData(response.data); } } catch (err) { setError('加载系统账户报表失败'); console.error('Failed to load system account report:', err); } finally { setLoading(false); } }, []); // 加载分类账明细 const loadLedgerData = useCallback(async () => { setLedgerLoading(true); try { const response = await systemAccountReportService.getAllLedger({ pageSize: 50 }); if (response.data) { setLedgerData(response.data); } } catch (err) { console.error('Failed to load ledger data:', err); } finally { setLedgerLoading(false); } }, []); // [2026-01-06] 新增:加载收益类型汇总数据 const loadRewardTypeSummaries = useCallback(async () => { setRewardTypeSummariesLoading(true); try { const response = await systemAccountReportService.getRewardTypeSummaries(); if (response.data) { setRewardTypeSummaries(response.data); } } catch (err) { console.error('Failed to load reward type summaries:', err); } finally { setRewardTypeSummariesLoading(false); } }, []); useEffect(() => { loadReportData(); }, [loadReportData]); // 切换到分类账明细时加载数据 useEffect(() => { if (activeTab === 'ledger' && !ledgerData && !ledgerLoading) { loadLedgerData(); } }, [activeTab, ledgerData, ledgerLoading, loadLedgerData]); // [2026-01-06] 切换到收益类型汇总Tab时加载数据 const rewardTypeTabs: TabType[] = ['feeAccount', 'provinceTeam', 'cityTeam', 'shareReferral', 'community']; useEffect(() => { if (rewardTypeTabs.includes(activeTab) && !rewardTypeSummaries && !rewardTypeSummariesLoading) { loadRewardTypeSummaries(); } }, [activeTab, rewardTypeSummaries, rewardTypeSummariesLoading, loadRewardTypeSummaries]); if (loading) { return (
加载中...
); } if (error) { return (
{error}
); } if (!reportData) { return
暂无数据
; } return (
{/* Tab 切换 */}
{/* [2026-01-06] 新增:收益类型汇总Tab */}
{/* 内容区域 */}
{activeTab === 'fixed' && } {activeTab === 'province' && } {activeTab === 'city' && } {activeTab === 'settlement' && } {activeTab === 'expired' && } {activeTab === 'ledger' && } {/* [2026-01-06] 新增:收益类型汇总Tab内容 */} {activeTab === 'feeAccount' && ( )} {activeTab === 'provinceTeam' && ( )} {activeTab === 'cityTeam' && ( )} {activeTab === 'shareReferral' && ( )} {activeTab === 'community' && ( )}
{/* 报表生成时间 */}
报表生成时间: {new Date(reportData.generatedAt).toLocaleString('zh-CN')}
); } /** * 固定系统账户区域 * [2026-01-05] 更新:根据业务需求调整显示名称,USDT改为绿积分 */ function FixedAccountsSection({ data }: { data: SystemAccountReportResponse['fixedAccounts'] }) { const accounts = [ { key: 'costAccount', label: '总部储备', sequence: 'S0000000001', data: data.costAccount }, { key: 'operationAccount', label: '运营账户1', sequence: 'S0000000002', data: data.operationAccount }, { key: 'hqCommunity', label: '运营账户2', sequence: 'S0000000003', data: data.hqCommunity }, { key: 'rwadPoolPending', label: '积分股池', sequence: 'S0000000004', data: data.rwadPoolPending }, { key: 'platformFee', label: '平台手续费', sequence: 'S0000000005', data: data.platformFee }, ]; return (

固定系统账户

{accounts.map(({ key, label, sequence, data: accountData }) => (
{label} {sequence}
账户余额 {accountData ? formatAmount(accountData.usdtBalance) : '0.00'} 绿积分
累计收入 {accountData ? formatAmount(accountData.totalReceived) : '0.00'} 绿积分
累计转出 {accountData ? formatAmount(accountData.totalTransferred) : '0.00'} 绿积分
))}
); } /** * 区域账户汇总区域 * [2026-01-05] 更新:USDT改为绿积分 */ function RegionAccountsSection({ data, type }: { data: RegionAccountsSummary; type: 'province' | 'city' }) { const typeLabel = type === 'province' ? '省' : '市'; return (

{typeLabel}区域账户汇总

{/* 汇总卡片 */}
账户数量 {data.summary.count}
总余额 {formatAmount(data.summary.totalBalance)} 绿积分
累计收入 {formatAmount(data.summary.totalReceived)} 绿积分
{/* 账户列表 */} {data.accounts.length > 0 ? (
{data.accounts.map((account) => ( ))}
区域代码 区域名称 余额 (绿积分) 累计收入 (绿积分) 状态
{account.regionCode || '-'} {account.regionName || '-'} {formatAmount(account.usdtBalance)} {formatAmount(account.totalReceived)} {account.status === 'ACTIVE' ? '正常' : account.status}
) : (
暂无{typeLabel}区域账户数据
)}
); } /** * 面对面结算统计区域 * [2026-01-05] 更新:USDT改为绿积分,添加空值检查 */ function OfflineSettlementSection({ data }: { data: SystemAccountReportResponse['offlineSettlement'] | null | undefined }) { if (!data) { return (

面对面结算统计

暂无面对面结算数据
); } return (

面对面结算统计

{/* 汇总卡片 */}
总笔数 {data.totalCount ?? 0}
总金额 {formatAmount(data.totalAmount)} 绿积分
{/* 按月统计 */} {data.byMonth && data.byMonth.length > 0 && ( <>

按月统计

{data.byMonth.map((item) => ( ))}
月份 笔数 金额 (绿积分)
{item.month} {item.count} {formatAmount(item.amount)}
)} {(!data.byMonth || data.byMonth.length === 0) && (
暂无面对面结算数据
)}
); } /** * 过期收益统计区域 * [2026-01-05] 更新:USDT改为绿积分,添加空值检查 */ function ExpiredRewardsSection({ data }: { data: SystemAccountReportResponse['expiredRewards'] | null | undefined }) { if (!data) { return (

过期收益统计

暂无过期收益数据
); } return (

过期收益统计

{/* 汇总卡片 */}
总笔数 {data.totalCount ?? 0}
总金额 {formatAmount(data.totalAmount)} 绿积分
{/* 按权益类型统计 */} {data.byRightType && data.byRightType.length > 0 && ( <>

按权益类型统计

{data.byRightType.map((item) => ( ))}
权益类型 笔数 金额 (绿积分)
{getRightTypeName(item.rightType)} {item.count} {formatAmount(item.amount)}
)} {/* 按月统计 */} {data.byMonth && data.byMonth.length > 0 && ( <>

按月统计

{data.byMonth.map((item) => ( ))}
月份 笔数 金额 (绿积分)
{item.month} {item.count} {formatAmount(item.amount)}
)} {(!data.byRightType || data.byRightType.length === 0) && (!data.byMonth || data.byMonth.length === 0) && (
暂无过期收益数据
)}
); } // [2026-01-05] 新增:分类账明细组件 /** * 分类账明细区域 */ function LedgerSection({ data, loading, onRefresh, }: { data: AllSystemAccountsLedgerResponse | null; loading: boolean; onRefresh: () => void; }) { const [expandedAccounts, setExpandedAccounts] = useState>(new Set()); const toggleExpand = (accountKey: string) => { setExpandedAccounts((prev) => { const newSet = new Set(prev); if (newSet.has(accountKey)) { newSet.delete(accountKey); } else { newSet.add(accountKey); } return newSet; }); }; if (loading) { return (
加载分类账明细中...
); } if (!data) { return (
暂无分类账数据
); } const getEntryTypeLabel = (type: string): string => { return ENTRY_TYPE_LABELS[type] || type; }; const getAccountTypeLabel = (type: string): string => { return ACCOUNT_TYPE_LABELS[type] || type; }; return (

分类账明细

{/* 固定系统账户分类账 */} {data.fixedAccountsLedger && data.fixedAccountsLedger.length > 0 && (

固定系统账户

{data.fixedAccountsLedger.map((account) => ( toggleExpand(account.accountSequence)} getEntryTypeLabel={getEntryTypeLabel} /> ))}
)} {/* 省区域账户分类账 */} {data.provinceAccountsLedger && data.provinceAccountsLedger.length > 0 && (

省区域账户 ({data.provinceAccountsLedger.length}个)

{data.provinceAccountsLedger.map((account) => ( toggleExpand(account.accountSequence)} getEntryTypeLabel={getEntryTypeLabel} /> ))}
)} {/* 市区域账户分类账 */} {data.cityAccountsLedger && data.cityAccountsLedger.length > 0 && (

市区域账户 ({data.cityAccountsLedger.length}个)

{data.cityAccountsLedger.map((account) => ( toggleExpand(account.accountSequence)} getEntryTypeLabel={getEntryTypeLabel} /> ))}
)} {(!data.fixedAccountsLedger || data.fixedAccountsLedger.length === 0) && (!data.provinceAccountsLedger || data.provinceAccountsLedger.length === 0) && (!data.cityAccountsLedger || data.cityAccountsLedger.length === 0) && (
暂无分类账明细数据
)}
); } /** * 资产类型显示名称映射 * [2026-01-05] 新增:USDT改为绿积分 */ const getAssetTypeLabel = (assetType: string): string => { const labels: Record = { USDT: '绿积分', usdt: '绿积分', }; return labels[assetType] || assetType; }; /** * 单个账户的分类账卡片 * [2026-01-05] 更新:资产类型显示改用中文 */ function LedgerAccountCard({ title, subtitle, ledger, total, expanded, onToggle, getEntryTypeLabel, }: { title: string; subtitle: string; ledger: LedgerEntryDTO[]; total: number; expanded: boolean; onToggle: () => void; getEntryTypeLabel: (type: string) => string; }) { return (
{title} {subtitle}
{total} 条记录 {expanded ? '▼' : '▶'}
{expanded && (
{ledger.length > 0 ? (
{ledger.map((entry) => ( ))}
时间 类型 金额 余额 备注
{new Date(entry.createdAt).toLocaleString('zh-CN')} {getEntryTypeLabel(entry.entryType)} = 0 ? styles.amountPositive : styles.amountNegative}> {entry.amount >= 0 ? '+' : ''}{formatAmount(entry.amount)} {getAssetTypeLabel(entry.assetType)} {entry.balanceAfter !== null ? formatAmount(entry.balanceAfter) : '-'} {entry.memo || entry.allocationType || '-'}
) : (
暂无流水记录
)}
)}
); } // [2026-01-06] 新增:手续费账户汇总组件 /** * 手续费账户汇总区域 */ function FeeAccountSection({ data, loading, onRefresh, }: { data: FeeAccountSummary | undefined; loading: boolean; onRefresh: () => void; }) { if (loading) { return (
加载手续费账户汇总中...
); } if (!data) { return (
暂无手续费账户数据
); } return (

手续费账户汇总

{/* 汇总卡片 */}
总金额 {formatAmount(data.totalAmount)} 绿积分
总笔数 {data.totalCount}
{/* 按类型明细 */} {data.breakdown && data.breakdown.length > 0 ? ( <>

按类型明细

{data.breakdown.map((item) => ( ))}
费用类型 金额 (绿积分) 笔数
{FEE_TYPE_LABELS[item.rightType] || item.rightType} {formatAmount(item.amount)} {item.count}
) : (
暂无手续费数据
)}
); } // [2026-01-06] 新增:收益类型汇总组件 /** * 收益类型汇总区域(省团队、市团队、分享引荐、社区) */ function RewardTypeSummarySection({ title, data, loading, onRefresh, }: { title: string; data: RewardTypeSummary | undefined; loading: boolean; onRefresh: () => void; }) { if (loading) { return (
加载{title}中...
); } if (!data) { return (
暂无数据
); } return (

{title}

{/* 汇总卡片 */}
总金额 {formatAmount(data.totalAmount)} 绿积分
总笔数 {data.totalCount}
可结算金额 {formatAmount(data.totalSettleableAmount)} 绿积分
已结算金额 {formatAmount(data.totalSettledAmount)} 绿积分
{/* 按月统计 */} {data.byMonth && data.byMonth.length > 0 ? ( <>

按月统计

{data.byMonth.map((item) => ( ))}
月份 金额 (绿积分) 笔数
{item.month} {formatAmount(item.amount)} {item.count}
) : (
暂无月度数据
)}
); }