96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
"use client";
|
||
|
||
import { HistoryResponse } from "@/lib/api";
|
||
import {
|
||
LineChart,
|
||
Line,
|
||
XAxis,
|
||
YAxis,
|
||
Tooltip,
|
||
Legend,
|
||
ResponsiveContainer,
|
||
ReferenceLine,
|
||
} from "recharts";
|
||
|
||
interface Props {
|
||
history: HistoryResponse;
|
||
}
|
||
|
||
export default function FundingChart({ history }: Props) {
|
||
// 合并BTC和ETH数据,按时间对齐
|
||
const btcMap = new Map(
|
||
history.BTC.map((p) => [p.timestamp.slice(0, 13), p.fundingRate * 100])
|
||
);
|
||
const ethMap = new Map(
|
||
history.ETH.map((p) => [p.timestamp.slice(0, 13), p.fundingRate * 100])
|
||
);
|
||
|
||
const allTimes = Array.from(
|
||
new Set([...btcMap.keys(), ...ethMap.keys()])
|
||
).sort();
|
||
|
||
const data = allTimes.map((t) => ({
|
||
time: t.slice(5).replace("T", " "), // "02-26 12"
|
||
BTC: btcMap.get(t) ?? null,
|
||
ETH: ethMap.get(t) ?? null,
|
||
}));
|
||
|
||
// 只显示最近 42 条(7天×6次/天)
|
||
const displayData = data.slice(-42);
|
||
|
||
const CustomTooltip = ({ active, payload, label }: any) => {
|
||
if (!active || !payload?.length) return null;
|
||
return (
|
||
<div className="bg-slate-800 border border-slate-600 rounded-lg p-3 text-xs">
|
||
<p className="text-slate-400 mb-2">{label}</p>
|
||
{payload.map((p: any) => (
|
||
<p key={p.dataKey} style={{ color: p.color }}>
|
||
{p.dataKey}: {p.value !== null ? `${p.value.toFixed(4)}%` : "--"}
|
||
</p>
|
||
))}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<ResponsiveContainer width="100%" height={240}>
|
||
<LineChart data={displayData} margin={{ top: 4, right: 8, bottom: 4, left: 8 }}>
|
||
<XAxis
|
||
dataKey="time"
|
||
tick={{ fill: "#64748b", fontSize: 10 }}
|
||
tickLine={false}
|
||
interval="preserveStartEnd"
|
||
/>
|
||
<YAxis
|
||
tick={{ fill: "#64748b", fontSize: 10 }}
|
||
tickLine={false}
|
||
axisLine={false}
|
||
tickFormatter={(v) => `${v.toFixed(3)}%`}
|
||
width={60}
|
||
/>
|
||
<Tooltip content={<CustomTooltip />} />
|
||
<Legend
|
||
wrapperStyle={{ fontSize: 12, color: "#94a3b8" }}
|
||
/>
|
||
<ReferenceLine y={0} stroke="#475569" strokeDasharray="4 2" />
|
||
<Line
|
||
type="monotone"
|
||
dataKey="BTC"
|
||
stroke="#06b6d4"
|
||
strokeWidth={1.5}
|
||
dot={false}
|
||
connectNulls
|
||
/>
|
||
<Line
|
||
type="monotone"
|
||
dataKey="ETH"
|
||
stroke="#8b5cf6"
|
||
strokeWidth={1.5}
|
||
dot={false}
|
||
connectNulls
|
||
/>
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
);
|
||
}
|