"use server"; // xuchao: 数学每周检测判分(同英语 takeWeekly,打卡联动数学) 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 { buildMathWeeklyQuestions, currentMathWeekKey, getMathWeeklyRecord } from "@/lib/math-weekly"; import { recordWrong } from "@/lib/wrongbook"; import { db } from "@/db"; import { taskInstances, mathWeeklyTest } from "@/db/schema"; import { todayStr } from "@/lib/dates"; import { awardRulePoints } from "@/lib/points"; export type MathWeeklyResult = | { score: number; passed: boolean; correct: number; total: number; detail: boolean[]; pointsEarned: number } | { error: string }; // 提交数学每周检测:判分、记录、错题入库、达标关联当日数学打卡 export async function takeMathWeekly(answers: AnswerValue[]): Promise { const user = await getSessionUser(); if (!user || user.role !== "child") return { error: "会话无效,请重新激活设备" }; const wk = currentMathWeekKey(); const existing = await getMathWeeklyRecord(user.id, wk); if (existing) return { error: "本周已完成数学检测,下周再来。" }; const questions = await buildMathWeeklyQuestions(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, "mweekly", wk, `数学周检测 ${wk}`, q, answers[i]); }); await db .insert(mathWeeklyTest) .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 } }); // 达标关联当日数学打卡,并发积分(首次达标才发) let pointsEarned = 0; if (g.passed) { pointsEarned = await awardRulePoints(user.id, "math_weekly", `week-${wk}`, `数学周检测 ${wk}`); 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: "math", status: "done", doneAt: new Date(), sortOrder: 95, }); } } revalidatePath("/math/weekly"); revalidatePath("/kid"); revalidatePath("/parent"); revalidatePath("/wrongbook"); revalidatePath("/points"); return { ...g, pointsEarned }; }