"use client"; /** 基于 ECharts 的折线图(净值 / 回撤),按需引入模块以压缩 bundle。 */ import { useEffect, useRef } from "react"; import * as echarts from "echarts/core"; import { LineChart as EChartsLine } from "echarts/charts"; import { GridComponent, TitleComponent, TooltipComponent } from "echarts/components"; import { CanvasRenderer } from "echarts/renderers"; echarts.use([EChartsLine, GridComponent, TitleComponent, TooltipComponent, CanvasRenderer]); export interface XY { date: string; value: number; } const C = { text: "#a8b3c9", faint: "#8b98b2", line: "rgba(150,165,195,0.13)", tooltipBg: "#141d30", tooltipBorder: "rgba(150,165,195,0.28)", }; export function LineChart({ title, data, color = "#3fb6ff", fill = false, height = 320, yFmt, xFmt, }: { title?: string; data: XY[]; color?: string; /** 线下渐变面积(净值类曲线推荐开启) */ fill?: boolean; height?: number; yFmt?: (v: number) => string; xFmt?: (v: string) => string; }) { const ref = useRef(null); useEffect(() => { if (!ref.current || data.length === 0) return; const chart = echarts.init(ref.current); const areaColor = { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: color + "3d" }, { offset: 1, color: color + "00" }, ], }; chart.setOption({ backgroundColor: "transparent", title: title ? { text: title, textStyle: { color: "#e9eef7", fontSize: 13, fontWeight: 600 }, } : undefined, tooltip: { trigger: "axis", backgroundColor: C.tooltipBg, borderColor: C.tooltipBorder, textStyle: { color: "#e9eef7", fontSize: 12 }, valueFormatter: (v: unknown) => typeof v === "number" ? (yFmt ? yFmt(v) : String(v)) : String(v), }, grid: { left: 8, right: 14, top: title ? 42 : 18, bottom: 8, containLabel: true }, xAxis: { type: "category", boundaryGap: false, data: data.map((p) => p.date), axisLine: { lineStyle: { color: C.line } }, axisTick: { show: false }, axisLabel: { color: C.faint, fontSize: 10, formatter: (v: string) => (xFmt ? xFmt(v) : v), }, }, yAxis: { type: "value", scale: true, axisLabel: { color: C.faint, fontSize: 10, formatter: yFmt }, splitLine: { lineStyle: { color: C.line } }, }, series: [ { type: "line", showSymbol: false, symbol: "circle", data: data.map((p) => p.value), lineStyle: { color, width: 1.8 }, itemStyle: { color }, areaStyle: fill ? { color: areaColor } : undefined, emphasis: { focus: "series" }, }, ], }); const onResize = () => chart.resize(); window.addEventListener("resize", onResize); return () => { window.removeEventListener("resize", onResize); chart.dispose(); }; }, [data, color, fill, title, height, yFmt, xFmt]); if (data.length === 0) return
暂无数据
; return
; }