parent
6e033c053a
commit
64cf22280b
@ -0,0 +1,111 @@
|
|||||||
|
const Exam = require('../models/Exam');
|
||||||
|
|
||||||
|
// 获取所有考试
|
||||||
|
exports.getExams = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const exams = await Exam.find({ isActive: true })
|
||||||
|
.select('-questions.answer') // 不返回答案
|
||||||
|
.populate('createdBy', 'username');
|
||||||
|
|
||||||
|
res.json(exams);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取单个考试详情
|
||||||
|
exports.getExam = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const exam = await Exam.findById(req.params.id)
|
||||||
|
.select('-questions.answer') // 不返回答案
|
||||||
|
.populate('createdBy', 'username');
|
||||||
|
|
||||||
|
if (!exam) {
|
||||||
|
return res.status(404).json({ message: 'Exam not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(exam);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建新考试 (教师/管理员)
|
||||||
|
exports.createExam = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { title, description, duration, questions } = req.body;
|
||||||
|
|
||||||
|
const exam = new Exam({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
duration,
|
||||||
|
questions,
|
||||||
|
createdBy: req.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await exam.save();
|
||||||
|
|
||||||
|
res.status(201).json(exam);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 验证考试答案
|
||||||
|
exports.validateAnswers = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { answers } = req.body;
|
||||||
|
|
||||||
|
// 获取考试(包含正确答案)
|
||||||
|
const exam = await Exam.findById(req.params.id);
|
||||||
|
if (!exam) {
|
||||||
|
return res.status(404).json({ message: 'Exam not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算分数
|
||||||
|
let totalScore = 0;
|
||||||
|
const results = exam.questions.map(question => {
|
||||||
|
const userAnswer = answers[question._id];
|
||||||
|
let isCorrect = false;
|
||||||
|
let score = 0;
|
||||||
|
|
||||||
|
if (question.type === 'text') {
|
||||||
|
// 简答题默认给一半分
|
||||||
|
if (userAnswer && userAnswer.trim().length > 0) {
|
||||||
|
isCorrect = true;
|
||||||
|
score = question.score / 2;
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(question.answer)) {
|
||||||
|
// 多选题
|
||||||
|
const correctAnswers = [...question.answer].sort().toString();
|
||||||
|
const userAns = [...userAnswer].sort().toString();
|
||||||
|
isCorrect = correctAnswers === userAns;
|
||||||
|
score = isCorrect ? question.score : 0;
|
||||||
|
} else {
|
||||||
|
// 单选题
|
||||||
|
isCorrect = userAnswer === question.answer;
|
||||||
|
score = isCorrect ? question.score : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalScore += score;
|
||||||
|
|
||||||
|
return {
|
||||||
|
questionId: question._id,
|
||||||
|
question: question.question,
|
||||||
|
userAnswer,
|
||||||
|
correctAnswer: question.answer,
|
||||||
|
isCorrect,
|
||||||
|
score
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
examId: exam._id,
|
||||||
|
totalScore,
|
||||||
|
maxScore: exam.questions.reduce((sum, q) => sum + q.score, 0),
|
||||||
|
results
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in new issue