用户端页面构建完成---待测试
This commit is contained in:
@@ -190,9 +190,21 @@ export class QuizController {
|
||||
}
|
||||
});
|
||||
} catch (error: any) {
|
||||
res.status(500).json({
|
||||
const message = error?.message || '生成试卷失败';
|
||||
const status = message.includes('不存在')
|
||||
? 404
|
||||
: [
|
||||
'用户ID不能为空',
|
||||
'subjectId或taskId必须提供其一',
|
||||
'当前时间不在任务有效范围内',
|
||||
'用户未被分派到此任务',
|
||||
'考试次数已用尽',
|
||||
].some((m) => message.includes(m))
|
||||
? 400
|
||||
: 500;
|
||||
res.status(status).json({
|
||||
success: false,
|
||||
message: error.message || '生成试卷失败'
|
||||
message,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -390,4 +402,4 @@ export class QuizController {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,15 @@ export interface ExamTask {
|
||||
selectionConfig?: string; // JSON string
|
||||
}
|
||||
|
||||
export interface UserExamTask extends ExamTask {
|
||||
subjectName: string;
|
||||
totalScore: number;
|
||||
timeLimitMinutes: number;
|
||||
usedAttempts: number;
|
||||
maxAttempts: number;
|
||||
bestScore: number;
|
||||
}
|
||||
|
||||
export interface ExamTaskUser {
|
||||
id: string;
|
||||
taskId: string;
|
||||
@@ -558,6 +567,13 @@ export class ExamTaskModel {
|
||||
);
|
||||
if (!isAssigned) throw new Error('用户未被分派到此任务');
|
||||
|
||||
const attemptRow = await get(
|
||||
`SELECT COUNT(*) as count FROM quiz_records WHERE user_id = ? AND task_id = ?`,
|
||||
[userId, taskId],
|
||||
);
|
||||
const usedAttempts = Number(attemptRow?.count) || 0;
|
||||
if (usedAttempts >= 3) throw new Error('考试次数已用尽');
|
||||
|
||||
const subject = await import('./examSubject').then(({ ExamSubjectModel }) => ExamSubjectModel.findById(task.subjectId));
|
||||
if (!subject) throw new Error('科目不存在');
|
||||
|
||||
@@ -705,27 +721,48 @@ export class ExamTaskModel {
|
||||
};
|
||||
}
|
||||
|
||||
static async getUserTasks(userId: string): Promise<ExamTask[]> {
|
||||
static async getUserTasks(userId: string): Promise<UserExamTask[]> {
|
||||
const now = new Date().toISOString();
|
||||
const rows = await all(`
|
||||
SELECT t.*, s.name as subjectName, s.totalScore, s.timeLimitMinutes
|
||||
SELECT
|
||||
t.id,
|
||||
t.name,
|
||||
t.subject_id as subjectId,
|
||||
t.start_at as startAt,
|
||||
t.end_at as endAt,
|
||||
t.created_at as createdAt,
|
||||
s.name as subjectName,
|
||||
s.total_score as totalScore,
|
||||
s.duration_minutes as timeLimitMinutes,
|
||||
COALESCE(q.usedAttempts, 0) as usedAttempts,
|
||||
3 as maxAttempts,
|
||||
COALESCE(q.bestScore, 0) as bestScore
|
||||
FROM exam_tasks t
|
||||
INNER JOIN exam_task_users tu ON t.id = tu.task_id
|
||||
INNER JOIN exam_subjects s ON t.subject_id = s.id
|
||||
WHERE tu.user_id = ? AND t.start_at <= ?
|
||||
ORDER BY t.start_at DESC
|
||||
`, [userId, now]);
|
||||
LEFT JOIN (
|
||||
SELECT task_id, COUNT(*) as usedAttempts, MAX(total_score) as bestScore
|
||||
FROM quiz_records
|
||||
WHERE user_id = ?
|
||||
GROUP BY task_id
|
||||
) q ON q.task_id = t.id
|
||||
WHERE tu.user_id = ? AND t.start_at <= ? AND t.end_at >= ?
|
||||
ORDER BY t.start_at ASC, t.end_at ASC
|
||||
`, [userId, userId, now, now]);
|
||||
|
||||
return rows.map(row => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
subjectId: row.subject_id,
|
||||
startAt: row.start_at,
|
||||
endAt: row.end_at,
|
||||
createdAt: row.created_at,
|
||||
subjectId: row.subjectId,
|
||||
startAt: row.startAt,
|
||||
endAt: row.endAt,
|
||||
createdAt: row.createdAt,
|
||||
subjectName: row.subjectName,
|
||||
totalScore: row.totalScore,
|
||||
timeLimitMinutes: row.timeLimitMinutes
|
||||
totalScore: Number(row.totalScore) || 0,
|
||||
timeLimitMinutes: Number(row.timeLimitMinutes) || 0,
|
||||
usedAttempts: Number(row.usedAttempts) || 0,
|
||||
maxAttempts: Number(row.maxAttempts) || 3,
|
||||
bestScore: Number(row.bestScore) || 0,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user