新增英语单词打卡模块:3694词/247天,发音/详情/跟读录音/每日检测

- 数据源:解析 3500 词 PDF 得 3694 词,按每天 15 词分 247 天,覆盖全部单词
- 孩子端 /words 地图 + 当天学习页:点词标准发音(有道语音)、详情(释义/
  形近词/例句)、学会标记、跟读录音(MediaRecorder 直传 OSS)、每日检测
  (选释义,达标点亮并计入英语打卡)
- 家长端课程管理可回放孩子跟读录音
- 形近词运行时编辑距离计算;例句按需取词典 API

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jacobxu666
2026-08-05 00:04:46 +08:00
co-authored by Claude Opus 4.8
parent 38a64b4ec1
commit 2bbf349e0c
10 changed files with 573 additions and 1 deletions
+41
View File
@@ -0,0 +1,41 @@
import { redirect } from "next/navigation";
import { and, eq } from "drizzle-orm";
import { db } from "@/db";
import { wordProgress } from "@/db/schema";
import { getSessionUser } from "@/lib/auth";
import { buildWordTest, similarWords, wordsByDay } from "@/lib/words";
import { WordDayClient } from "../word-day";
export default async function WordDayPage({ params }: { params: Promise<{ day: string }> }) {
const user = await getSessionUser();
if (!user) redirect("/join");
if (user.role !== "child") redirect("/parent");
const day = Number((await params).day);
const words = wordsByDay(day);
if (words.length === 0) redirect("/words");
const [prog] = await db
.select()
.from(wordProgress)
.where(and(eq(wordProgress.childUserId, user.id), eq(wordProgress.day, day)))
.limit(1);
const learned: string[] = prog?.learned ? JSON.parse(prog.learned) : [];
const items = words.map((w) => ({
word: w.word,
meaning: w.meaning,
similar: similarWords(w.word, 3).map((s) => ({ word: s.word, meaning: s.meaning })),
}));
return (
<WordDayClient
day={day}
items={items}
learned={learned}
test={buildWordTest(day)}
passed={prog?.passed ?? false}
score={prog?.score ?? null}
/>
);
}