import "server-only" import { and, eq } from "drizzle-orm" import { db } from "@/shared/db" import { examQuestions, examSubmissions, exams, submissionAnswers } from "@/shared/db/schema" /** * 错题采集所需的答案数据(单题) */ export type AnswerForErrorCollection = { questionId: string answerContent: unknown score: number | null feedback: string | null maxScore: number } /** * 考试提交的错题采集数据 */ export type ExamSubmissionDataForErrorCollection = { examId: string subjectId: string | null answers: AnswerForErrorCollection[] } /** * 跨模块接口:获取考试提交的错题采集数据。 * * 供 error-book 模块调用,避免 error-book 直接查询 examSubmissions、 * submissionAnswers、examQuestions、exams 等属于 exams 模块的表。 * * 返回该提交的所有答案(含得分、反馈、满分),由 error-book 模块 * 自行筛选错题(score < maxScore)并采集。 * * @param submissionId 考试提交 ID * @param studentId 学生 ID(用于校验提交归属) * @returns 提交数据;若提交不存在或 studentId 不匹配则返回 null */ export async function getExamSubmissionDataForErrorCollection( submissionId: string, studentId: string, ): Promise { const submission = await db.query.examSubmissions.findFirst({ where: and( eq(examSubmissions.id, submissionId), eq(examSubmissions.studentId, studentId), ), columns: { id: true, examId: true }, }) if (!submission) return null // 并行获取考试学科、提交答案、题目满分 const [exam, answers, examQuestionScores] = await Promise.all([ db.query.exams.findFirst({ where: eq(exams.id, submission.examId), columns: { subjectId: true }, }), db .select({ questionId: submissionAnswers.questionId, answerContent: submissionAnswers.answerContent, score: submissionAnswers.score, feedback: submissionAnswers.feedback, }) .from(submissionAnswers) .where(eq(submissionAnswers.submissionId, submissionId)), db .select({ questionId: examQuestions.questionId, maxScore: examQuestions.score, }) .from(examQuestions) .where(eq(examQuestions.examId, submission.examId)), ]) const maxScoreMap = new Map(examQuestionScores.map((q) => [q.questionId, q.maxScore ?? 0])) const mappedAnswers: AnswerForErrorCollection[] = answers.map((a) => ({ questionId: a.questionId, answerContent: a.answerContent, score: a.score, feedback: a.feedback, maxScore: maxScoreMap.get(a.questionId) ?? 0, })) return { examId: submission.examId, subjectId: exam?.subjectId ?? null, answers: mappedAnswers, } }