- 数据源:解析 3500 词 PDF 得 3694 词,按每天 15 词分 247 天,覆盖全部单词 - 孩子端 /words 地图 + 当天学习页:点词标准发音(有道语音)、详情(释义/ 形近词/例句)、学会标记、跟读录音(MediaRecorder 直传 OSS)、每日检测 (选释义,达标点亮并计入英语打卡) - 家长端课程管理可回放孩子跟读录音 - 形近词运行时编辑距离计算;例句按需取词典 API Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
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}
|
|
/>
|
|
);
|
|
}
|