diff --git a/frontend/mining-admin-web/src/app/(dashboard)/market-maker/page.tsx b/frontend/mining-admin-web/src/app/(dashboard)/market-maker/page.tsx index cf6cdf90..d8a602f3 100644 --- a/frontend/mining-admin-web/src/app/(dashboard)/market-maker/page.tsx +++ b/frontend/mining-admin-web/src/app/(dashboard)/market-maker/page.tsx @@ -23,7 +23,9 @@ import { useDepth, useDepthEnabled, useSetDepthEnabled, + useCashDepositLedgers, } from '@/features/market-maker'; +import type { LedgerEntry } from '@/features/market-maker'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Button } from '@/components/ui/button'; @@ -57,6 +59,9 @@ import { MinusCircle, Copy, Check, + History, + ChevronLeft, + ChevronRight, } from 'lucide-react'; export default function MarketMakerPage() { @@ -95,6 +100,11 @@ export default function MarketMakerPage() { const [blockchainWithdrawCashAmount, setBlockchainWithdrawCashAmount] = useState(''); const [blockchainWithdrawSharesAddress, setBlockchainWithdrawSharesAddress] = useState(''); const [blockchainWithdrawSharesAmount, setBlockchainWithdrawSharesAmount] = useState(''); + // 充值记录 + const [ledgerDialogOpen, setLedgerDialogOpen] = useState(false); + const [ledgerFilter, setLedgerFilter] = useState<'all' | 'centralized' | 'blockchain'>('all'); + const [ledgerPage, setLedgerPage] = useState(1); + const ledgerPageSize = 20; const handleCopyAddress = async (address: string) => { await navigator.clipboard.writeText(address); @@ -102,6 +112,21 @@ export default function MarketMakerPage() { setTimeout(() => setCopiedAddress(false), 2000); }; + const { data: ledgerData, isLoading: ledgerLoading } = useCashDepositLedgers(ledgerPage, ledgerPageSize); + + const filteredLedgers = (ledgerData?.data ?? []).filter((entry: LedgerEntry) => { + if (ledgerFilter === 'centralized') return !entry.memo?.includes('区块链'); + if (ledgerFilter === 'blockchain') return entry.memo?.includes('区块链'); + return true; + }); + + const ledgerTotalPages = Math.max(1, Math.ceil((ledgerData?.total ?? 0) / ledgerPageSize)); + + const formatDateTime = (dateStr: string) => { + const d = new Date(dateStr); + return d.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); + }; + const config = configData?.config; const formatNumber = (value: string | undefined, decimals: number = 2) => { @@ -284,6 +309,21 @@ export default function MarketMakerPage() { )} +
+ +
@@ -372,6 +412,109 @@ export default function MarketMakerPage() { + + {/* 充值记录 Dialog */} + + + + 现金(积分值)充值记录 + 查看做市商账户的充值流水明细 + + { setLedgerFilter(v as typeof ledgerFilter); setLedgerPage(1); }}> + + 全部 + 中心化充值 + 区块链充值 + + + + {ledgerLoading ? ( +
+ + + +
+ ) : filteredLedgers.length === 0 ? ( +
+ 暂无充值记录 +
+ ) : ( + + + + 时间 + 充值方式 + 金额 + 变动前余额 + 变动后余额 + 备注 + + + + {filteredLedgers.map((entry: LedgerEntry) => { + const isBlockchain = entry.memo?.includes('区块链'); + return ( + + + {formatDateTime(entry.createdAt)} + + + {isBlockchain ? ( + 链上 + ) : ( + 中心化 + )} + + + +{formatNumber(entry.amount, 2)} + + + {formatNumber(entry.balanceBefore, 2)} + + + {formatNumber(entry.balanceAfter, 2)} + + + {entry.memo ?? '-'} + + + ); + })} + +
+ )} + + {/* 分页 */} + {(ledgerData?.total ?? 0) > 0 && ( +
+ + 共 {ledgerData?.total ?? 0} 条记录 + +
+ + + {ledgerPage} / {ledgerTotalPages} + + +
+
+ )} +
+
diff --git a/frontend/mining-admin-web/src/features/market-maker/api/market-maker.api.ts b/frontend/mining-admin-web/src/features/market-maker/api/market-maker.api.ts index 1900e3a1..6910280d 100644 --- a/frontend/mining-admin-web/src/features/market-maker/api/market-maker.api.ts +++ b/frontend/mining-admin-web/src/features/market-maker/api/market-maker.api.ts @@ -106,6 +106,22 @@ export interface DepthData { timestamp: number; } +export interface LedgerEntry { + id: string; + type: string; + assetType: string; + amount: string; + balanceBefore: string; + balanceAfter: string; + tradeNo: string | null; + orderNo: string | null; + counterpartySeq: string | null; + price: string | null; + quantity: string | null; + memo: string | null; + createdAt: string; +} + export const marketMakerApi = { // 获取做市商配置(包含运行状态) getConfig: async (name: string = 'MAIN_MARKET_MAKER'): Promise<{ @@ -320,4 +336,23 @@ export const marketMakerApi = { const response = await tradingClient.post('/admin/trading/depth-enabled', { enabled }); return response.data; }, + + // 获取做市商分类账流水 + getLedgers: async ( + name: string, + params?: { + type?: string; + assetType?: string; + page?: number; + pageSize?: number; + }, + ): Promise<{ success: boolean; data: LedgerEntry[]; total: number }> => { + const searchParams = new URLSearchParams(); + if (params?.type) searchParams.append('type', params.type); + if (params?.assetType) searchParams.append('assetType', params.assetType); + if (params?.page) searchParams.append('page', params.page.toString()); + if (params?.pageSize) searchParams.append('pageSize', params.pageSize.toString()); + const response = await tradingClient.get(`/admin/market-maker/${name}/ledgers?${searchParams.toString()}`); + return response.data; + }, }; diff --git a/frontend/mining-admin-web/src/features/market-maker/hooks/use-market-maker.ts b/frontend/mining-admin-web/src/features/market-maker/hooks/use-market-maker.ts index 2ae727de..bb536ac7 100644 --- a/frontend/mining-admin-web/src/features/market-maker/hooks/use-market-maker.ts +++ b/frontend/mining-admin-web/src/features/market-maker/hooks/use-market-maker.ts @@ -324,6 +324,19 @@ export function useMarketMakerStats() { }); } +export function useCashDepositLedgers(page: number = 1, pageSize: number = 20) { + return useQuery({ + queryKey: ['marketMaker', 'ledgers', 'cash-deposit', MARKET_MAKER_NAME, page, pageSize], + queryFn: () => + marketMakerApi.getLedgers(MARKET_MAKER_NAME, { + type: 'DEPOSIT', + assetType: 'CASH', + page, + pageSize, + }), + }); +} + export function useDepthEnabled() { return useQuery({ queryKey: ['trading', 'depthEnabled'],