103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
"use client"
|
|
|
|
import { Line } from "@ant-design/plots"
|
|
import { BarChart as RechartsBarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, PieChart as RechartsPieChart, Pie, Cell, Legend } from "recharts"
|
|
|
|
interface LineChartProps {
|
|
data: { date: string; value: number }[]
|
|
xField: string
|
|
yField: string
|
|
}
|
|
|
|
export function LineChart({ data, xField, yField }: LineChartProps) {
|
|
const config = {
|
|
data,
|
|
xField,
|
|
yField,
|
|
smooth: true,
|
|
color: "#1677ff",
|
|
point: {
|
|
size: 4,
|
|
shape: "circle",
|
|
style: {
|
|
fill: "#1677ff",
|
|
stroke: "#fff",
|
|
lineWidth: 2,
|
|
},
|
|
},
|
|
tooltip: {
|
|
showMarkers: false,
|
|
},
|
|
state: {
|
|
active: {
|
|
style: {
|
|
shadowBlur: 4,
|
|
stroke: "#000",
|
|
fill: "red",
|
|
},
|
|
},
|
|
},
|
|
interactions: [
|
|
{
|
|
type: "marker-active",
|
|
},
|
|
],
|
|
}
|
|
|
|
return <Line {...config} />
|
|
}
|
|
|
|
// 图表 data 格式:{ labels, datasets: [{ data, backgroundColor?, label? }] }
|
|
interface ChartDataProps {
|
|
data: {
|
|
labels: string[]
|
|
datasets: { data: number[]; backgroundColor?: string | string[]; label?: string }[]
|
|
}
|
|
height?: number
|
|
}
|
|
|
|
export function PieChart({ data, height = 200 }: ChartDataProps) {
|
|
const labels = data.labels || []
|
|
const first = data.datasets?.[0]
|
|
const values = first?.data || []
|
|
const colors = Array.isArray(first?.backgroundColor) ? first.backgroundColor : values.map(() => "hsl(var(--primary))")
|
|
const rechartsData = labels.map((name, i) => ({ name, value: values[i] ?? 0, color: colors[i] ?? "hsl(var(--primary))" }))
|
|
|
|
return (
|
|
<div style={{ height }}>
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<RechartsPieChart>
|
|
<Pie data={rechartsData} cx="50%" cy="50%" innerRadius={50} outerRadius={80} paddingAngle={2} dataKey="value">
|
|
{rechartsData.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip />
|
|
<Legend />
|
|
</RechartsPieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function BarChart({ data, height = 200 }: ChartDataProps) {
|
|
const labels = data.labels || []
|
|
const first = data.datasets?.[0]
|
|
const values = first?.data || []
|
|
const rechartsData = labels.map((label, i) => ({ name: label, value: values[i] ?? 0 }))
|
|
const fill = (typeof first?.backgroundColor === "string" ? first.backgroundColor : "hsl(var(--primary))") as string
|
|
|
|
return (
|
|
<div style={{ height }}>
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<RechartsBarChart data={rechartsData} margin={{ top: 8, right: 8, left: 8, bottom: 8 }}>
|
|
<XAxis dataKey="name" />
|
|
<YAxis />
|
|
<Tooltip />
|
|
<Bar dataKey="value" fill={fill} />
|
|
</RechartsBarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)
|
|
}
|