Files
users/components/charts.tsx

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>
)
}