import type { JSX } from "react" import Link from "next/link" import { BarChart3, ArrowLeft } from "lucide-react" import { getTranslations } from "next-intl/server" import { Button } from "@/shared/components/ui/button" import { EmptyState } from "@/shared/components/ui/empty-state" import { requirePermission } from "@/shared/lib/auth-guard" import { Permissions } from "@/shared/types/permissions" import { getParam, type SearchParams } from "@/shared/lib/search-params" import { getTeacherClasses } from "@/modules/classes/data-access" import { getGrades } from "@/modules/school/data-access" import { getSubjectOptions } from "@/modules/school/data-access" import { getClassComparisonWithSignificance, getExamOptionsForGrades, getGradeDistribution, getGradeTrend, getSubjectComparison, } from "@/modules/grades/data-access-analytics" import { GradeTrendChart } from "@/modules/grades/components/grade-trend-chart" import { ClassComparisonChart } from "@/modules/grades/components/class-comparison-chart" import { SubjectComparisonChart } from "@/modules/grades/components/subject-comparison-chart" import { GradeDistributionChart } from "@/modules/grades/components/grade-distribution-chart" import { AnalyticsGradeFilters } from "./analytics-grade-filters" import { KnowledgePointMasteryChart } from "@/modules/grades/components/knowledge-point-mastery-chart" import { getClassMasterySummary } from "@/modules/diagnostic/data-access" import { WidgetBoundary } from "@/shared/components/widget-boundary" export const dynamic = "force-dynamic" export default async function GradeAnalyticsPage({ searchParams, }: { searchParams: Promise }): Promise { const sp = await searchParams const ctx = await requirePermission(Permissions.GRADE_RECORD_READ) const t = await getTranslations("grades") const classId = getParam(sp, "classId") const subjectId = getParam(sp, "subjectId") const gradeId = getParam(sp, "gradeId") // v3-P2-7: 学期和考试筛选 const examId = getParam(sp, "examId") const semester = getParam(sp, "semester") const [classes, allGrades, allSubjects] = await Promise.all([ getTeacherClasses(), getGrades(), getSubjectOptions(), ]) if (classes.length === 0) { return (

{t("title.analytics")}

{t("page.analytics.description")}

) } const targetClassId = classId ?? classes[0].id const targetSubjectId = subjectId && subjectId !== "all" ? subjectId : undefined const targetGradeId = gradeId ?? allGrades[0]?.id // v3-P2-7: 解析 semester 和 examId const targetSemester: "1" | "2" | undefined = semester === "1" || semester === "2" ? semester : undefined const targetExamId = examId && examId !== "all" ? examId : undefined // Run analytics queries in parallel // P3-3: 集成 diagnostic 模块的知识点掌握度视图(classId 已由 getTeacherClasses 校验在 scope 内) const [ trend, distribution, subjectComparison, classComparisonResult, examOptions, classMasterySummary, ] = await Promise.all([ getGradeTrend({ classId: targetClassId, subjectId: targetSubjectId, semester: targetSemester, examId: targetExamId, scope: ctx.dataScope, currentUserId: ctx.userId, }), getGradeDistribution({ classId: targetClassId, subjectId: targetSubjectId, examId: targetExamId, semester: targetSemester, scope: ctx.dataScope, currentUserId: ctx.userId, }), getSubjectComparison({ classId: targetClassId, examId: targetExamId, semester: targetSemester, scope: ctx.dataScope, }), targetGradeId ? getClassComparisonWithSignificance({ gradeId: targetGradeId, subjectId: targetSubjectId ?? allSubjects[0]?.id ?? "", examId: targetExamId, semester: targetSemester, scope: ctx.dataScope, }) : Promise.resolve({ items: [], significance: null }), getExamOptionsForGrades({ classId: targetClassId, subjectId: targetSubjectId, scope: ctx.dataScope, }), getClassMasterySummary(targetClassId), ]) return (

{t("title.analytics")}

{t("page.analytics.description")}

({ id: c.id, name: c.name }))} grades={allGrades.map((g) => ({ id: g.id, name: g.name }))} subjects={allSubjects.map((s) => ({ id: s.id, name: s.name ?? "Unknown" }))} exams={examOptions} currentClassId={targetClassId} currentSubjectId={subjectId ?? "all"} currentGradeId={targetGradeId ?? ""} currentExamId={examId ?? "all"} currentSemester={semester ?? "all"} />
{trend ? ( ) : ( )} {distribution.totalCount > 0 ? ( ) : ( )} {subjectComparison.length > 0 ? ( ) : ( )} {classComparisonResult.items.length > 0 ? ( ) : ( )}
) }