家长端考试试卷管理:列表/新建/编辑(/parent/exams),题目 JSON 保存校验,孩子端即时生效
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
1b5e95725e
commit
522ff91525
@@ -0,0 +1,87 @@
|
||||
import Link from "next/link";
|
||||
import { Plus } from "lucide-react";
|
||||
import { redirect } from "next/navigation";
|
||||
import { BackgroundBlobs } from "@/components/background-blobs";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getSessionUser } from "@/lib/auth";
|
||||
import { EXAM_TYPE_LABEL, listPapers } from "@/lib/exam";
|
||||
|
||||
// xuchao: 试卷管理列表——与孩子端考试中心同分组(月份),点击进入编辑
|
||||
const MONTH_LABEL: Record<number, string> = {
|
||||
0: "入学 · 分班考",
|
||||
9: "9 月 · 有理数",
|
||||
10: "10 月 · 整式的加减",
|
||||
11: "11 月 · 一元一次方程",
|
||||
12: "12 月 · 几何图形初步",
|
||||
1: "1 月 · 期末全册",
|
||||
};
|
||||
const MONTH_ORDER = [0, 9, 10, 11, 12, 1];
|
||||
|
||||
function countQuestions(qs: string): number {
|
||||
try {
|
||||
const arr = JSON.parse(qs) as unknown[];
|
||||
return Array.isArray(arr) ? arr.length : 0;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function ExamsAdmin() {
|
||||
const parent = await getSessionUser();
|
||||
if (!parent) redirect("/login");
|
||||
if (parent.role !== "parent") redirect("/kid");
|
||||
|
||||
const papers = await listPapers("g7", "s1");
|
||||
|
||||
return (
|
||||
<main className="relative mx-auto max-w-2xl space-y-5 p-4 pb-10">
|
||||
<BackgroundBlobs />
|
||||
<header className="flex items-center justify-between">
|
||||
<Link href="/parent" className="text-sm font-medium text-indigo-600">
|
||||
← 返回家长中心
|
||||
</Link>
|
||||
<h1 className="text-xl font-extrabold text-slate-900">考试试卷管理</h1>
|
||||
<Link href="/parent/exams/new">
|
||||
<Button size="sm">
|
||||
<Plus className="size-4" /> 新建试卷
|
||||
</Button>
|
||||
</Link>
|
||||
</header>
|
||||
<p className="rounded-lg border-l-4 border-indigo-400 bg-indigo-50 px-3 py-2 text-sm text-indigo-800">
|
||||
点击试卷可编辑元信息与题目,保存后孩子端考试中心立即生效。
|
||||
</p>
|
||||
|
||||
{papers.length === 0 && (
|
||||
<div className="rounded-2xl border border-slate-100 bg-white p-8 text-center shadow-soft">
|
||||
<p className="text-sm text-muted-foreground">还没有试卷,点右上角新建</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{MONTH_ORDER.map((m) => {
|
||||
const group = papers.filter((p) => p.month === m);
|
||||
if (group.length === 0) return null;
|
||||
return (
|
||||
<section key={m} className="rounded-xl border border-slate-100 bg-white p-4 shadow-soft">
|
||||
<h2 className="mb-2 text-sm font-extrabold text-slate-900">{MONTH_LABEL[m]}</h2>
|
||||
<div className="space-y-1.5">
|
||||
{group.map((p) => (
|
||||
<Link
|
||||
key={p.paperId}
|
||||
href={`/parent/exams/${p.paperId}`}
|
||||
className="flex items-center gap-2 rounded-lg border border-slate-200 px-3 py-2 text-sm text-slate-700 transition-colors hover:border-indigo-300"
|
||||
>
|
||||
<span className="truncate font-medium text-slate-800">{p.title}</span>
|
||||
<Badge className="shrink-0 bg-indigo-100 text-indigo-700 hover:bg-indigo-100">
|
||||
{EXAM_TYPE_LABEL[p.examType] ?? p.examType}
|
||||
</Badge>
|
||||
<span className="ml-auto shrink-0 text-xs text-muted-foreground">{p.seq} 号卷</span>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user