feat(admin-web): 固定系统账户卡片添加查看分类账明细按钮
在固定系统账户卡片下方添加"查看明细"按钮,点击后展开显示 该账户的分类账流水记录,包括时间、类型、金额、余额和备注。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d53b1c7499
commit
d6b3f04612
|
|
@ -592,3 +592,49 @@
|
|||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* [2026-01-07] 新增:固定账户卡片底部样式 */
|
||||
.cardFooter {
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.viewLedgerButton {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
background-color: #f3f4f6;
|
||||
color: #374151;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background-color: #e5e7eb;
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.accountLedgerSection {
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
|
||||
.table {
|
||||
font-size: 12px;
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ export default function SystemAccountsTab() {
|
|||
/**
|
||||
* 固定系统账户区域
|
||||
* [2026-01-05] 更新:根据业务需求调整显示名称,USDT改为绿积分
|
||||
* [2026-01-07] 更新:添加查看分类账明细按钮
|
||||
*/
|
||||
function FixedAccountsSection({ data }: { data: SystemAccountReportResponse['fixedAccounts'] }) {
|
||||
// [2026-01-07] 更新:使用 SYSTEM_ACCOUNT_NAMES 映射获取正式名称
|
||||
|
|
@ -307,37 +308,136 @@ function FixedAccountsSection({ data }: { data: SystemAccountReportResponse['fix
|
|||
{ key: 'platformFee', sequence: 'S0000000005', data: data.platformFee },
|
||||
];
|
||||
|
||||
// [2026-01-07] 新增:展开状态管理和分类账数据
|
||||
const [expandedAccount, setExpandedAccount] = useState<string | null>(null);
|
||||
const [allLedgerData, setAllLedgerData] = useState<AllSystemAccountsLedgerResponse | null>(null);
|
||||
const [ledgerLoading, setLedgerLoading] = useState(false);
|
||||
|
||||
// 加载所有固定账户的分类账明细
|
||||
const loadAllLedger = useCallback(async () => {
|
||||
if (allLedgerData) return; // 已加载过,不重复加载
|
||||
|
||||
setLedgerLoading(true);
|
||||
try {
|
||||
const response = await systemAccountReportService.getAllLedger({ pageSize: 50 });
|
||||
if (response.data) {
|
||||
setAllLedgerData(response.data);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load ledger data:', err);
|
||||
} finally {
|
||||
setLedgerLoading(false);
|
||||
}
|
||||
}, [allLedgerData]);
|
||||
|
||||
// 切换显示某个账户的明细
|
||||
const handleToggleLedger = async (accountSequence: string) => {
|
||||
if (expandedAccount === accountSequence) {
|
||||
setExpandedAccount(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果还没有加载数据,先加载
|
||||
if (!allLedgerData) {
|
||||
await loadAllLedger();
|
||||
}
|
||||
setExpandedAccount(accountSequence);
|
||||
};
|
||||
|
||||
// 获取指定账户的分类账数据
|
||||
const getAccountLedger = (accountSequence: string): LedgerEntryDTO[] => {
|
||||
if (!allLedgerData?.fixedAccountsLedger) return [];
|
||||
const accountLedger = allLedgerData.fixedAccountsLedger.find(
|
||||
(item) => item.accountSequence === accountSequence
|
||||
);
|
||||
return accountLedger?.ledger || [];
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.section}>
|
||||
<h3 className={styles.sectionTitle}>固定系统账户</h3>
|
||||
<div className={styles.cardGrid}>
|
||||
{accounts.map(({ key, sequence, data: accountData }) => (
|
||||
<div key={key} className={styles.accountCard}>
|
||||
<div className={styles.cardHeader}>
|
||||
<span className={styles.accountLabel}>{getAccountDisplayName(sequence)}</span>
|
||||
{accounts.map(({ key, sequence, data: accountData }) => {
|
||||
const isExpanded = expandedAccount === sequence;
|
||||
const ledger = isExpanded ? getAccountLedger(sequence) : [];
|
||||
|
||||
return (
|
||||
<div key={key} className={styles.accountCard}>
|
||||
<div className={styles.cardHeader}>
|
||||
<span className={styles.accountLabel}>{getAccountDisplayName(sequence)}</span>
|
||||
</div>
|
||||
<div className={styles.cardBody}>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>账户余额</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.usdtBalance) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>累计收入</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.totalReceived) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>累计转出</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.totalTransferred) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* [2026-01-07] 新增:查看明细按钮 */}
|
||||
<div className={styles.cardFooter}>
|
||||
<button
|
||||
className={styles.viewLedgerButton}
|
||||
onClick={() => handleToggleLedger(sequence)}
|
||||
disabled={ledgerLoading}
|
||||
>
|
||||
{ledgerLoading && !allLedgerData ? '加载中...' : isExpanded ? '收起明细' : '查看明细'}
|
||||
</button>
|
||||
</div>
|
||||
{/* [2026-01-07] 新增:展开的分类账明细 */}
|
||||
{isExpanded && (
|
||||
<div className={styles.accountLedgerSection}>
|
||||
{ledger.length > 0 ? (
|
||||
<div className={styles.tableWrapper}>
|
||||
<table className={styles.table}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>时间</th>
|
||||
<th>类型</th>
|
||||
<th>金额</th>
|
||||
<th>余额</th>
|
||||
<th>备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ledger.map((entry) => (
|
||||
<tr key={entry.id}>
|
||||
<td>{new Date(entry.createdAt).toLocaleString('zh-CN')}</td>
|
||||
<td>
|
||||
<span className={styles.entryTypeBadge}>
|
||||
{ENTRY_TYPE_LABELS[entry.entryType] || entry.entryType}
|
||||
</span>
|
||||
</td>
|
||||
<td className={entry.amount >= 0 ? styles.amountPositive : styles.amountNegative}>
|
||||
{entry.amount >= 0 ? '+' : ''}{formatAmount(entry.amount)} {getAssetTypeLabel(entry.assetType)}
|
||||
</td>
|
||||
<td>{entry.balanceAfter !== null ? formatAmount(entry.balanceAfter) : '-'}</td>
|
||||
<td className={styles.memo}>{entry.memo || entry.allocationType || '-'}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.emptyLedger}>暂无流水记录</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.cardBody}>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>账户余额</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.usdtBalance) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>累计收入</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.totalReceived) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.statRow}>
|
||||
<span className={styles.statLabel}>累计转出</span>
|
||||
<span className={styles.statValue}>
|
||||
{accountData ? formatAmount(accountData.totalTransferred) : '0.00'} 绿积分
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue