import { useEffect, useState } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { Card, Table, Button, Input, message, Divider, Spin } from 'antd' import { LeftOutlined } from '@ant-design/icons' import { apiService } from '../services/api' import { formatUSDC } from '../utils' import { useMediaQuery } from 'react-responsive' import { useTranslation } from 'react-i18next' import type { MatchedOrderInfo, OrderTrackingRequest, OrderTrackingListResponse } from '../types' const CopyTradingMatchedOrdersPage: React.FC = () => { const { t } = useTranslation() const { copyTradingId } = useParams<{ copyTradingId: string }>() const navigate = useNavigate() const isMobile = useMediaQuery({ maxWidth: 768 }) const [loading, setLoading] = useState(false) const [orders, setOrders] = useState([]) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const [limit, setLimit] = useState(20) const [filters, setFilters] = useState<{ sellOrderId?: string buyOrderId?: string }>({}) useEffect(() => { if (copyTradingId) { fetchOrders() } }, [copyTradingId, page, limit, filters]) const fetchOrders = async () => { if (!copyTradingId) return setLoading(true) try { const request: OrderTrackingRequest = { copyTradingId: parseInt(copyTradingId), type: 'matched', page, limit, ...filters } const response = await apiService.orderTracking.list(request) if (response.data.code === 0 && response.data.data) { const data = response.data.data as OrderTrackingListResponse setOrders((data.list || []) as MatchedOrderInfo[]) setTotal(data.total || 0) } else { message.error(response.data.msg || '获取匹配关系列表失败') } } catch (error: any) { message.error(error.message || '获取匹配关系列表失败') } finally { setLoading(false) } } const getPnlColor = (value: string): string => { const num = parseFloat(value) if (isNaN(num)) return '#666' return num >= 0 ? '#3f8600' : '#cf1322' } const columns = [ { title: '卖出订单ID', dataIndex: 'sellOrderId', key: 'sellOrderId', width: isMobile ? 100 : 150, render: (text: string) => ( {isMobile ? `${text.slice(0, 6)}...${text.slice(-4)}` : `${text.slice(0, 8)}...${text.slice(-6)}` } ) }, { title: '买入订单ID', dataIndex: 'buyOrderId', key: 'buyOrderId', width: isMobile ? 100 : 150, render: (text: string) => ( {isMobile ? `${text.slice(0, 6)}...${text.slice(-4)}` : `${text.slice(0, 8)}...${text.slice(-6)}` } ) }, { title: '匹配数量', dataIndex: 'matchedQuantity', key: 'matchedQuantity', width: isMobile ? 80 : 100, render: (value: string) => ( {formatUSDC(value)} ) }, { title: '买入价格', dataIndex: 'buyPrice', key: 'buyPrice', width: isMobile ? 80 : 100, render: (value: string) => ( {formatUSDC(value)} ) }, { title: '卖出价格', dataIndex: 'sellPrice', key: 'sellPrice', width: isMobile ? 80 : 100, render: (value: string) => ( {formatUSDC(value)} ) }, { title: '盈亏', dataIndex: 'realizedPnl', key: 'realizedPnl', width: isMobile ? 100 : 120, render: (value: string) => ( {isMobile ? formatUSDC(value) : `${formatUSDC(value)} USDC`} ) }, { title: '匹配时间', dataIndex: 'matchedAt', key: 'matchedAt', width: isMobile ? 120 : 160, render: (timestamp: number) => ( {isMobile ? new Date(timestamp).toLocaleDateString('zh-CN') : new Date(timestamp).toLocaleString('zh-CN') } ) } ] return (

匹配关系列表

setFilters({ ...filters, sellOrderId: e.target.value || undefined })} /> setFilters({ ...filters, buyOrderId: e.target.value || undefined })} />
{isMobile ? ( // 移动端卡片布局
{loading ? (
) : orders.length === 0 ? (
暂无匹配关系
) : (
{orders.map((order) => { const date = new Date(order.matchedAt) const formattedDate = date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) return ( {/* 订单ID */}
卖出订单ID
{order.sellOrderId.slice(0, 8)}...{order.sellOrderId.slice(-6)}
买入订单ID
{order.buyOrderId.slice(0, 8)}...{order.buyOrderId.slice(-6)}
{/* 匹配信息 */}
匹配数量
{formatUSDC(order.matchedQuantity)}
{/* 价格信息 */}
价格信息
买入: {formatUSDC(order.buyPrice)} | 卖出: {formatUSDC(order.sellPrice)}
{/* 盈亏 */}
盈亏
{formatUSDC(order.realizedPnl)} USDC
{/* 匹配时间 */}
匹配时间: {formattedDate}
) })}
)}
) : ( // 桌面端表格布局 `${record.sellOrderId}-${record.buyOrderId}-${record.matchedAt}`} loading={loading} pagination={{ current: page, pageSize: limit, total, showSizeChanger: true, showTotal: (total) => `共 ${total} 条`, onChange: (newPage, newLimit) => { setPage(newPage) setLimit(newLimit) } }} /> )} ) } export default CopyTradingMatchedOrdersPage