From 44e58f48a6d2d99db481db6e6a19b7d48346aad3 Mon Sep 17 00:00:00 2001 From: jacobxu666 Date: Wed, 5 Aug 2026 20:42:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=B6=E9=95=BF=E7=AB=AF=E8=AF=BE=E7=A8=8B?= =?UTF-8?q?=E7=AE=A1=E7=90=86:=E5=8F=AF=E8=A7=81=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E6=98=8E=E7=BB=86+=E5=AD=A9=E5=AD=90?= =?UTF-8?q?=E9=94=99=E9=A2=98=E6=9C=AC+=E8=B7=9F=E8=AF=BB=E5=BD=95?= =?UTF-8?q?=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 语法检测:列出孩子每课检测的标题/分数/是否通过 - 错题本:展示孩子错题(题干/孩子答案/正确答案),含单词与语法错题 - 跟读录音:已有,保持可回放 Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/parent/dashboard.tsx | 39 ++++++++++++++++++++++ src/app/parent/page.tsx | 65 +++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/app/parent/dashboard.tsx b/src/app/parent/dashboard.tsx index bf2778e..47e080e 100644 --- a/src/app/parent/dashboard.tsx +++ b/src/app/parent/dashboard.tsx @@ -55,6 +55,15 @@ export type DevicesData = { }; export type WeeklyRow = { childName: string; weekKey: string; score: number; passed: boolean }; export type RecordingRow = { childName: string; word: string; url: string; at: string }; +export type GrammarTestRow = { childName: string; title: string; score: number; passed: boolean; at: string }; +export type WrongItemRow = { + childName: string; + stem: string; + userAnswer: string; + correctAnswer: string; + sourceTitle: string; + mastered: boolean; +}; const tabCls = "data-[state=active]:bg-white data-[state=active]:text-indigo-600 data-[state=active]:shadow-soft"; @@ -74,12 +83,16 @@ export function ParentDashboard({ devices, weekly, recordings, + grammarTests, + wrongItems, }: { overview: OverviewData; templates: TemplatesData; devices: DevicesData; weekly: WeeklyRow[]; recordings: RecordingRow[]; + grammarTests: GrammarTestRow[]; + wrongItems: WrongItemRow[]; }) { return (
@@ -146,6 +159,32 @@ export function ParentDashboard({ ))} +
+

📘 英语语法检测

+
+ {grammarTests.length === 0 &&

暂无检测记录

} + {grammarTests.map((g, i) => ( +

+ {g.childName} · {g.title} · {g.score} 分 {g.passed ? "✅" : "❌"} +

+ ))} +
+
+
+

📒 孩子错题本

+
+ {wrongItems.length === 0 &&

暂无错题

} + {wrongItems.map((w, i) => ( +
+

+ {w.childName} · {w.stem} +

+

答:{w.userAnswer || "未作答"}

+

正:{w.correctAnswer}

+
+ ))} +
+
diff --git a/src/app/parent/page.tsx b/src/app/parent/page.tsx index 3b98a6b..341c7a4 100644 --- a/src/app/parent/page.tsx +++ b/src/app/parent/page.tsx @@ -190,7 +190,70 @@ export default async function ParentPage() { at: dstr(r.createdAt), })); + // ===== 英语语法检测明细 ===== + const grammarRows = await db + .select({ + childName: users.displayName, + title: grammarPoints.title, + score: grammarProgress.score, + passed: grammarProgress.passed, + completedAt: grammarProgress.completedAt, + }) + .from(grammarProgress) + .innerJoin(users, eq(users.id, grammarProgress.childUserId)) + .innerJoin(grammarPoints, eq(grammarPoints.pointId, grammarProgress.pointId)) + .where(eq(users.familyId, parent.familyId)) + .orderBy(desc(grammarProgress.completedAt)) + .limit(20); + const grammarTests = grammarRows.map((g) => ({ + childName: g.childName, + title: g.title, + score: g.score ?? 0, + passed: g.passed, + at: g.completedAt ? dstr(g.completedAt) : "", + })); + + // ===== 孩子错题数据 ===== + const wrongRows = await db + .select({ + childName: users.displayName, + question: wrongBook.question, + userAnswer: wrongBook.userAnswer, + correctAnswer: wrongBook.correctAnswer, + sourceTitle: wrongBook.sourceTitle, + mastered: wrongBook.mastered, + }) + .from(wrongBook) + .innerJoin(users, eq(users.id, wrongBook.childUserId)) + .where(eq(users.familyId, parent.familyId)) + .orderBy(desc(wrongBook.createdAt)) + .limit(30); + const wrongItems = wrongRows.map((w) => { + let stem = ""; + try { + stem = (JSON.parse(w.question) as { stem?: string }).stem ?? ""; + } catch { + stem = ""; + } + return { + childName: w.childName, + stem, + userAnswer: w.userAnswer ?? "", + correctAnswer: w.correctAnswer ?? "", + sourceTitle: w.sourceTitle ?? "", + mastered: w.mastered, + }; + }); + return ( - + ); }