"use client"; import { useEffect, useState } from "react"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, LineChart, Line, ResponsiveContainer } from "recharts"; interface ClassAnalysis { class_id: string; class_name: string; count: number; avg: number; max: number; min: number; std_dev: number; q1: number; q2: number; q3: number; pass_rate: number; excellent_rate: number; segments: { label: string; count: number; rate: number }[]; } interface Suggestion { class_name: string; rank: number; suggestion: string; } const COLORS = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6"]; export default function GradeDistributionChart() { const [data, setData] = useState<{ class_analysis: ClassAnalysis[]; suggestions: Suggestion[] } | null>(null); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState<"bar" | "quantile" | "segment" | "suggest">("bar"); useEffect(() => { fetch("/api/analytics/grade-distribution") .then(r => r.json()) .then(d => { setData(d); setLoading(false); }) .catch(() => setLoading(false)); }, []); if (loading) return
加载中...
; if (!data) return
数据加载失败
; const avgChartData = data.class_analysis.map(c => ({ name: c.class_name, 平均分: c.avg, 最高分: c.max, 最低分: c.min, 标准差: c.std_dev, })); const quantileData = data.class_analysis.map(c => ({ name: c.class_name, Q1: c.q1, Q2中位数: c.q2, Q3: c.q3, 优秀率: c.excellent_rate, 及格率: c.pass_rate, })); const tabs = [ { key: "bar", label: "均分对比" }, { key: "quantile", label: "分位数" }, { key: "segment", label: "分数段" }, { key: "suggest", label: "教师建议" }, ] as const; return (

年级层面 — 宏观对比分析

{/* Tab 切换 */}
{tabs.map(t => ( ))}
{/* 均分柱形图 */} {activeTab === "bar" && (

各班级平均分、最高分、最低分横向对比(从高到低排序)

{/* 统计表格 */} {data.class_analysis.map((c, i) => ( ))}
班级 平均分 最高分 最低分 标准差 及格率
{c.class_name} {c.avg} {c.max} {c.min} {c.std_dev} {c.pass_rate}%
)} {/* 分位数分析 */} {activeTab === "quantile" && (

四分位数分析:Q1(25%)、中位数(50%)、Q3(75%)

)} {/* 分数段分布 */} {activeTab === "segment" && (

各班级分数段人数分布

{data.class_analysis.map(cls => (

{cls.class_name}(共{cls.count}人)

{cls.segments.map(seg => (
{seg.label}
{seg.count}
{seg.rate}%
))}
))}
)} {/* 教师建议 */} {activeTab === "suggest" && (
{data.suggestions.map((s, i) => (
第{s.rank}名 {s.class_name}

{s.suggestion}

))}
)}
); }