"use client"; import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { CheckCircle2, Save, Trash2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import type { QuizQ } from "@/lib/quiz-parse"; import { deleteExamPaper, saveExamPaper } from "../actions"; import { QuestionList } from "./question-list"; // xuchao: 与 lib/exam.ts 的 EXAM_TYPE_LABEL 保持同步(客户端不能直接引用服务端模块) const EXAM_TYPE_LABEL: Record = { entrance: "入学考", monthly: "月考", unit: "单元卷", midterm: "期中", final: "期末", }; export type PaperMeta = { paperId: string; title: string; examType: string; region: string | null; year: number | null; duration: number | null; fullScore: number | null; month: number; seq: number; sourceUrl: string | null; summary: string | null; questions: string; }; // xuchao: 试卷编辑器——元信息表单 + 结构化题目编辑器;保存走服务端完整校验 export function PaperForm({ paper, isNew }: { paper: PaperMeta | null; isNew: boolean }) { const router = useRouter(); const [f, setF] = useState({ paperId: paper?.paperId ?? "", title: paper?.title ?? "", examType: paper?.examType ?? "monthly", region: paper?.region ?? "", year: paper?.year != null ? String(paper.year) : "", duration: paper?.duration != null ? String(paper.duration) : "", fullScore: paper?.fullScore != null ? String(paper.fullScore) : "100", month: String(paper?.month ?? 9), seq: String(paper?.seq ?? 1), sourceUrl: paper?.sourceUrl ?? "", summary: paper?.summary ?? "", }); // xuchao: 题目用结构化数组管理,保存时序列化为 JSON(与旧 JSON 形状一致) const [questions, setQuestions] = useState(() => { try { return paper ? (JSON.parse(paper.questions) as QuizQ[]) : []; } catch { return []; } }); const [msg, setMsg] = useState<{ ok?: boolean; text: string } | null>(null); const [pending, startTransition] = useTransition(); const save = () => { setMsg(null); const fd = new FormData(); (Object.keys(f) as (keyof typeof f)[]).forEach((k) => fd.set(k, f[k])); fd.set("questions", JSON.stringify(questions)); startTransition(() => { saveExamPaper(fd).then((r) => { if (r.error) setMsg({ text: r.error }); else setMsg({ ok: true, text: "已保存,孩子端立即生效" }); }); }); }; const remove = () => { if (!paper || !confirm(`确定删除试卷「${paper.title}」?孩子的历史作答记录会保留。`)) return; startTransition(() => { deleteExamPaper(paper.paperId).then(() => router.push("/parent/exams")); }); }; const n = (key: keyof typeof f) => ({ value: f[key], onChange: (e: React.ChangeEvent) => setF((prev) => ({ ...prev, [key]: e.target.value })), }); return (
setQuestions(qs)} />
{msg &&

{msg.text}

}
{!isNew && ( )} {msg?.ok && }
); }