feat: 添加得分占比计算功能;优化时间格式化工具函数;更新考试记录和用户任务页面以显示得分占比;新增得分占比测试用例;修复时间解析逻辑

This commit is contained in:
2025-12-30 15:26:53 +08:00
parent 8cd6950631
commit 1822d8b4da
18 changed files with 347 additions and 68 deletions

View File

@@ -42,6 +42,8 @@ export interface SubmitAnswerData {
export interface SubmitQuizData {
userId: string;
answers: SubmitAnswerData[];
// 试卷总分(题目满分之和)。用于计算得分占比 = totalScore/totalPossibleScore * 100
totalPossibleScore?: number;
}
export class QuizModel {
@@ -53,9 +55,11 @@ export class QuizModel {
}
// 创建答题记录
static async createRecord(data: { userId: string; totalScore: number; correctCount: number; totalCount: number }): Promise<QuizRecord> {
static async createRecord(data: { userId: string; totalScore: number; correctCount: number; totalCount: number; totalPossibleScore?: number }): Promise<QuizRecord> {
const id = uuidv4();
const scorePercentage = data.totalCount > 0 ? (data.totalScore / data.totalCount) * 100 : 0;
const denomRaw = typeof data.totalPossibleScore === 'number' ? data.totalPossibleScore : data.totalCount;
const denom = denomRaw > 0 ? denomRaw : 0;
const scorePercentage = denom > 0 ? (data.totalScore / denom) * 100 : 0;
const status = this.calculateStatus(scorePercentage);
const sql = `
@@ -119,7 +123,8 @@ export class QuizModel {
userId: data.userId,
totalScore,
correctCount,
totalCount
totalCount,
totalPossibleScore: data.totalPossibleScore
});
// 创建答题答案
@@ -130,7 +135,35 @@ export class QuizModel {
// 根据ID查找答题记录
static async findRecordById(id: string): Promise<QuizRecord | null> {
const sql = `SELECT id, user_id as userId, total_score as totalScore, correct_count as correctCount, total_count as totalCount, score_percentage as scorePercentage, status, created_at as createdAt FROM quiz_records WHERE id = ?`;
const sql = `
SELECT r.id,
r.user_id as userId,
r.total_score as totalScore,
r.correct_count as correctCount,
r.total_count as totalCount,
CASE
WHEN totals.totalPossibleScore > 0 THEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100
ELSE r.score_percentage
END as scorePercentage,
CASE
WHEN totals.totalPossibleScore > 0 THEN
CASE
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 60 THEN '不及格'
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 80 THEN '合格'
ELSE '优秀'
END
ELSE r.status
END as status,
r.created_at as createdAt
FROM quiz_records r
LEFT JOIN (
SELECT a.record_id as recordId, SUM(q.score) as totalPossibleScore
FROM quiz_answers a
JOIN questions q ON a.question_id = q.id
GROUP BY a.record_id
) totals ON totals.recordId = r.id
WHERE r.id = ?
`;
const record = await get(sql, [id]);
return record || null;
}
@@ -139,11 +172,30 @@ export class QuizModel {
static async findRecordsByUserId(userId: string, limit = 10, offset = 0): Promise<{ records: QuizRecord[]; total: number }> {
const recordsSql = `
SELECT r.id, r.user_id as userId, r.total_score as totalScore, r.correct_count as correctCount, r.total_count as totalCount,
r.score_percentage as scorePercentage, r.status, r.created_at as createdAt,
CASE
WHEN totals.totalPossibleScore > 0 THEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100
ELSE r.score_percentage
END as scorePercentage,
CASE
WHEN totals.totalPossibleScore > 0 THEN
CASE
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 60 THEN '不及格'
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 80 THEN '合格'
ELSE '优秀'
END
ELSE r.status
END as status,
r.created_at as createdAt,
COALESCE(r.subject_id, t.subject_id) as subjectId,
COALESCE(s.name, ts.name) as subjectName,
r.task_id as taskId, t.name as taskName
FROM quiz_records r
LEFT JOIN (
SELECT a.record_id as recordId, SUM(q.score) as totalPossibleScore
FROM quiz_answers a
JOIN questions q ON a.question_id = q.id
GROUP BY a.record_id
) totals ON totals.recordId = r.id
LEFT JOIN exam_tasks t ON r.task_id = t.id
LEFT JOIN exam_subjects s ON r.subject_id = s.id
LEFT JOIN exam_subjects ts ON t.subject_id = ts.id
@@ -170,7 +222,19 @@ export class QuizModel {
const recordsSql = `
SELECT r.id, r.user_id as userId, u.name as userName, u.phone as userPhone,
r.total_score as totalScore, r.correct_count as correctCount, r.total_count as totalCount,
r.score_percentage as scorePercentage, r.status,
CASE
WHEN totals.totalPossibleScore > 0 THEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100
ELSE r.score_percentage
END as scorePercentage,
CASE
WHEN totals.totalPossibleScore > 0 THEN
CASE
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 60 THEN '不及格'
WHEN (r.total_score * 1.0 / totals.totalPossibleScore) * 100 < 80 THEN '合格'
ELSE '优秀'
END
ELSE r.status
END as status,
r.created_at as createdAt,
COALESCE(r.subject_id, t.subject_id) as subjectId,
COALESCE(s.name, ts.name) as subjectName,
@@ -178,6 +242,12 @@ export class QuizModel {
t.name as taskName
FROM quiz_records r
JOIN users u ON r.user_id = u.id
LEFT JOIN (
SELECT a.record_id as recordId, SUM(q.score) as totalPossibleScore
FROM quiz_answers a
JOIN questions q ON a.question_id = q.id
GROUP BY a.record_id
) totals ON totals.recordId = r.id
LEFT JOIN exam_tasks t ON r.task_id = t.id
LEFT JOIN exam_subjects s ON r.subject_id = s.id
LEFT JOIN exam_subjects ts ON t.subject_id = ts.id