feat(exams,homework): add error collection data-access for error book integration
- Add data-access-error-collection in exams module for collecting wrong exam answers - Add data-access-error-collection in homework module for collecting wrong homework answers - Update exams actions, exam-ai-generator, data-access, and types - Update homework actions and data-access-write
This commit is contained in:
94
src/modules/exams/data-access-error-collection.ts
Normal file
94
src/modules/exams/data-access-error-collection.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
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<ExamSubmissionDataForErrorCollection | null> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user