"use client"; import { useEffect, useState } from "react"; import { authFetch } from "@/lib/auth"; interface TradeRow { time_ms: number; price: number; qty: number; is_buyer_maker: number; // 0=主动买, 1=主动卖 agg_id: number; } interface TradesResponse { symbol: string; count: number; data: TradeRow[]; } const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? ""; async function fetchLatestTrades(symbol: string): Promise { // 查最近5秒的原始trades const end_ms = Date.now(); const start_ms = end_ms - 5000; const res = await authFetch( `/api/trades/latest?symbol=${symbol}&limit=30`, { cache: "no-store" } ); if (!res.ok) return []; const data: TradesResponse = await res.json(); return data.data || []; } function timeStr(ms: number): string { const d = new Date(ms + 8 * 3600 * 1000); return `${String(d.getUTCHours()).padStart(2,"0")}:${String(d.getUTCMinutes()).padStart(2,"0")}:${String(d.getUTCSeconds()).padStart(2,"0")}`; } export default function LiveTradesCard({ symbol }: { symbol: "BTC" | "ETH" }) { const [trades, setTrades] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { let running = true; const fetch = async () => { try { const data = await fetchLatestTrades(symbol); if (running) { setTrades(prev => { // 合并新数据,按时间降序,最多保留50条 const existingIds = new Set(prev.map(t => t.agg_id)); const newOnes = data.filter(t => !existingIds.has(t.agg_id)); return [...newOnes, ...prev].slice(0, 50); }); setLoading(false); } } catch (e) { if (running) setError("加载失败"); } }; fetch(); const iv = setInterval(fetch, 1000); return () => { running = false; clearInterval(iv); }; }, [symbol]); return (

实时成交流 · {symbol}/USDT

▲ 绿色 = 主动买入(多方发动)   ▼ 红色 = 主动卖出(空方发动)

实时
{loading ? (
加载中...
) : error ? (
{error}
) : trades.length === 0 ? (
等待数据...
) : ( {trades.map(t => ( ))}
价格(USDT) 数量 时间
{t.is_buyer_maker === 0 ? "▲" : "▼"} {t.price.toLocaleString("en-US", { minimumFractionDigits: 1, maximumFractionDigits: 1 })} {t.qty >= 1000 ? `${(t.qty / 1000).toFixed(2)}K` : t.qty.toFixed(symbol === "BTC" ? 4 : 3)} {timeStr(t.time_ms)}
)}
); }