学习闭环增强:错题本+每周能力检测+学习概览日历+模板日历+课程管理
- 错题本:所有检测错题自动入库,带详细讲解,可标记掌握,孩子端可查 - 每周能力检测:从已学知识点确定性组卷10题,计分记录,达标关联当日 英语打卡,错题进错题本,家长可见成绩 - 家长"今日概览"改"学习概览",月日历展示每日打卡/语法点亮/周检测 - 任务模板改日历展示,灵活添加:某一天/每周X/本周/日期区间批量,可删 - 家长中心新增"课程管理"栏目(语法课程编辑+周测成绩),设备管理弱化为 栏目内二级区块 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f98a21672d
commit
d84d827202
@@ -0,0 +1,76 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import { getSessionUser } from "@/lib/auth";
|
||||
import { gradeAnswers, type AnswerValue } from "@/lib/grammar";
|
||||
import { buildWeeklyQuestions, currentWeekKey, getWeeklyRecord } from "@/lib/weekly";
|
||||
import { recordWrong } from "@/lib/wrongbook";
|
||||
import { db } from "@/db";
|
||||
import { taskInstances, weeklyTest } from "@/db/schema";
|
||||
import { todayStr } from "@/lib/dates";
|
||||
|
||||
export type WeeklyResult =
|
||||
| { score: number; passed: boolean; correct: number; total: number; detail: boolean[] }
|
||||
| { error: string };
|
||||
|
||||
// 提交每周能力检测:判分、记录、错题入库、达标关联当日英语打卡
|
||||
export async function takeWeekly(answers: AnswerValue[]): Promise<WeeklyResult> {
|
||||
const user = await getSessionUser();
|
||||
if (!user || user.role !== "child") return { error: "会话无效,请重新激活设备" };
|
||||
const wk = currentWeekKey();
|
||||
const existing = await getWeeklyRecord(user.id, wk);
|
||||
if (existing) return { error: "本周已完成检测,下周再来。" };
|
||||
|
||||
const questions = await buildWeeklyQuestions(user.id, wk);
|
||||
if (questions.length === 0) return { error: "暂无可组卷的题目,先学几课吧。" };
|
||||
|
||||
const g = gradeAnswers(questions, answers);
|
||||
questions.forEach((q, i) => {
|
||||
if (!g.detail[i]) void recordWrong(user.id, "weekly", wk, `每周检测 ${wk}`, q, answers[i]);
|
||||
});
|
||||
|
||||
await db
|
||||
.insert(weeklyTest)
|
||||
.values({
|
||||
childUserId: user.id,
|
||||
weekKey: wk,
|
||||
score: g.score,
|
||||
correct: g.correct,
|
||||
total: g.total,
|
||||
passed: g.passed,
|
||||
questions: JSON.stringify(questions),
|
||||
})
|
||||
.onDuplicateKeyUpdate({ set: { score: g.score, correct: g.correct, total: g.total, passed: g.passed } });
|
||||
|
||||
// 达标关联当日英语打卡
|
||||
if (g.passed) {
|
||||
const today = todayStr();
|
||||
const title = `英语周检测 · ${wk}`;
|
||||
const [ex] = await db
|
||||
.select({ id: taskInstances.id, status: taskInstances.status })
|
||||
.from(taskInstances)
|
||||
.where(and(eq(taskInstances.childUserId, user.id), eq(taskInstances.date, today), eq(taskInstances.title, title)))
|
||||
.limit(1);
|
||||
if (ex) {
|
||||
if (ex.status !== "done")
|
||||
await db.update(taskInstances).set({ status: "done", doneAt: sql`CURRENT_TIMESTAMP` }).where(eq(taskInstances.id, ex.id));
|
||||
} else {
|
||||
await db.insert(taskInstances).values({
|
||||
childUserId: user.id,
|
||||
date: today,
|
||||
title,
|
||||
subject: "english",
|
||||
status: "done",
|
||||
doneAt: new Date(),
|
||||
sortOrder: 98,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
revalidatePath("/weekly");
|
||||
revalidatePath("/kid");
|
||||
revalidatePath("/parent");
|
||||
revalidatePath("/wrongbook");
|
||||
return g;
|
||||
}
|
||||
Reference in New Issue
Block a user