1298 lines
43 KiB
JavaScript
1298 lines
43 KiB
JavaScript
// 导入必要的模块和函数
|
||
import { getSystemDbPath, getUserDbPath } from './path.js';
|
||
import { getDbConnection, closeAllConnections } from './index.js';
|
||
import { batchInsert } from './utils.js';
|
||
|
||
// 新增:格式化日期为年-月-日 时:分:秒
|
||
export function formatDateTime(date) {
|
||
if (!(date instanceof Date)) {
|
||
date = new Date(date);
|
||
}
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const hours = String(date.getHours()).padStart(2, '0');
|
||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||
}
|
||
|
||
/**
|
||
* 生成考生试卷
|
||
* @param {Object} examineeData - 考生数据
|
||
* @param {Object} examData - 考试数据
|
||
* @returns {Promise<Object>} - 包含试卷ID和状态的对象
|
||
*/
|
||
export async function generateExamineePaper(examineeData, examData) {
|
||
try {
|
||
// 1. 获取数据库连接
|
||
const systemDb = await getDbConnection(getSystemDbPath());
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
|
||
// 2. 处理考生数据,将空值转换为空字符串
|
||
console.log('开始处理考生数据...', examineeData);
|
||
const processedExamineeData = {
|
||
id: examineeData.id,
|
||
examinee_name: examineeData.examinee_name || '',
|
||
examinee_gender: examineeData.examinee_gender || '',
|
||
examinee_unit: examineeData.examinee_unit || '',
|
||
written_exam_room: examineeData.written_exam_room || '',
|
||
written_exam_seat: examineeData.written_exam_seat || '',
|
||
computer_exam_room: examineeData.computer_exam_room || '',
|
||
computer_exam_seat: examineeData.computer_exam_seat || '',
|
||
examinee_id_card: examineeData.examinee_id_card || '',
|
||
examinee_admission_ticket: examineeData.examinee_admission_ticket || ''
|
||
};
|
||
|
||
// 3. 检查考生是否已存在
|
||
console.log('检查考生是否已存在...');
|
||
const existingExaminee = await userDb.getAsync(
|
||
`SELECT id FROM examinee WHERE id = ?`,
|
||
[processedExamineeData.id]
|
||
);
|
||
|
||
let examineeId;
|
||
|
||
if (existingExaminee) {
|
||
// 考生已存在
|
||
examineeId = existingExaminee.id;
|
||
console.log(`考生已存在,ID: ${examineeId}`);
|
||
/// TODO: 更新考生信息
|
||
// 实现考生信息更新
|
||
await userDb.runAsync(
|
||
`UPDATE examinee SET
|
||
examinee_name = ?,
|
||
examinee_gender = ?,
|
||
examinee_unit = ?,
|
||
written_exam_room = ?,
|
||
written_exam_seat = ?,
|
||
computer_exam_room = ?,
|
||
computer_exam_seat = ?,
|
||
examinee_admission_ticket = ?,
|
||
created_at = ?
|
||
WHERE id = ?`,
|
||
[
|
||
processedExamineeData.examinee_name,
|
||
processedExamineeData.examinee_gender,
|
||
processedExamineeData.examinee_unit,
|
||
processedExamineeData.written_exam_room,
|
||
processedExamineeData.written_exam_seat,
|
||
processedExamineeData.computer_exam_room,
|
||
processedExamineeData.computer_exam_seat,
|
||
processedExamineeData.examinee_admission_ticket,
|
||
new Date().toISOString(),
|
||
examineeId
|
||
]
|
||
);
|
||
console.log(`考生信息已更新,ID: ${examineeId}`);
|
||
// 4. 检查该考生是否有试卷记录
|
||
console.log('检查考生试卷记录...');
|
||
const existingPaper = await userDb.getAsync(
|
||
`SELECT id, paper_status FROM examinee_papers WHERE examinee_id = ? ORDER BY created_at DESC LIMIT 1`,
|
||
[examineeId]
|
||
);
|
||
|
||
if (existingPaper) {
|
||
// 试卷已存在
|
||
const paperId = existingPaper.id;
|
||
const paperStatus = existingPaper.paper_status;
|
||
console.log(`试卷已存在,ID: ${paperId},状态: ${paperStatus}`);
|
||
|
||
if (paperStatus === 2) {
|
||
// 状态为2:已完成考试,不能重复考试
|
||
console.log('考生已完成考试,不能重复考试');
|
||
return {
|
||
success: false,
|
||
message: '已完成考试,不能重复考试。'
|
||
};
|
||
// } else if (paperStatus === 1) {
|
||
// // 状态为1:进行中,直接返回该试卷
|
||
// console.log('返回进行中的考试');
|
||
// return {
|
||
// success: true,
|
||
// paperId,
|
||
// examineeId,
|
||
// message: '已进入上次进行中的考试'
|
||
// };
|
||
// } else if (paperStatus === 0) {
|
||
} else {
|
||
// 状态为0:未开始,删除旧试卷及相关数据,重新组卷
|
||
console.log('删除未开始的旧试卷及相关数据...');
|
||
|
||
// 删除question_choices记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM question_choices WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
|
||
// 删除question_fill_blanks记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM question_fill_blanks WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
|
||
// 删除question_images记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM question_images WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
|
||
// 删除question_datasets记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM question_datasets WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
|
||
// 删除paper_questions记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM paper_questions WHERE paper_id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
// 删除examinee_papers记录
|
||
await userDb.runAsync(
|
||
`DELETE FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
console.log('旧试卷数据删除完成');
|
||
}
|
||
}
|
||
} else {
|
||
// 考生不存在,添加新考生
|
||
console.log('添加新考生...');
|
||
const examineeResult = await userDb.runAsync(
|
||
`INSERT INTO examinee (
|
||
id, examinee_name, examinee_gender, examinee_unit,
|
||
written_exam_room, written_exam_seat, computer_exam_room,
|
||
computer_exam_seat, examinee_id_card, examinee_admission_ticket, created_at
|
||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||
[
|
||
processedExamineeData.id,
|
||
processedExamineeData.examinee_name,
|
||
processedExamineeData.examinee_gender,
|
||
processedExamineeData.examinee_unit,
|
||
processedExamineeData.written_exam_room,
|
||
processedExamineeData.written_exam_seat,
|
||
processedExamineeData.computer_exam_room,
|
||
processedExamineeData.computer_exam_seat,
|
||
processedExamineeData.examinee_id_card,
|
||
processedExamineeData.examinee_admission_ticket,
|
||
new Date().toISOString() // 修改为toISOString格式
|
||
]
|
||
);
|
||
examineeId = examineeResult.lastID;
|
||
console.log(`新考生添加成功,ID: ${examineeId}`);
|
||
}
|
||
|
||
// 5. 生成新的examinee_papers记录
|
||
console.log('生成新试卷记录...');
|
||
const paperResult = await userDb.runAsync(
|
||
`INSERT INTO examinee_papers (
|
||
examinee_id, paper_minutes, paper_minutes_min, paper_status
|
||
) VALUES (?, ?, ?, ?)`,
|
||
[examineeId, examData.exam_minutes, examData.exam_minutes_min, 0] // 0表示未开始
|
||
);
|
||
const paperId = paperResult.lastID;
|
||
console.log(`试卷记录生成成功,ID: ${paperId}`);
|
||
|
||
// 6. 从system库获取所有questions记录
|
||
console.log('获取系统题库...');
|
||
const systemQuestions = await systemDb.allAsync('SELECT * FROM questions');
|
||
console.log(`成功获取 ${systemQuestions.length} 道题目`);
|
||
|
||
// 打乱题目顺序
|
||
const shuffledQuestions = [...systemQuestions].sort(() => Math.random() - 0.5);
|
||
|
||
// 7. 准备paper_questions数据
|
||
console.log('准备试卷题目数据...');
|
||
const paperQuestionsData = shuffledQuestions.map(question => ({
|
||
examinee_id: examineeId,
|
||
paper_id: paperId,
|
||
question_type: question.question_type,
|
||
question_name: question.question_name,
|
||
question_description: question.question_description,
|
||
created_at: new Date().toISOString() // 修改为toISOString格式
|
||
}));
|
||
|
||
// 创建question_id映射关系(system_id -> user_id)
|
||
const questionIdMap = new Map();
|
||
|
||
// 8. 插入paper_questions数据并记录映射关系
|
||
console.log('插入试卷题目数据...');
|
||
for (let i = 0; i < paperQuestionsData.length; i++) {
|
||
const result = await userDb.runAsync(
|
||
`INSERT INTO paper_questions (
|
||
examinee_id, paper_id, question_type,
|
||
question_name, question_description, created_at
|
||
) VALUES (?, ?, ?, ?, ?, ?)`,
|
||
[
|
||
paperQuestionsData[i].examinee_id,
|
||
paperQuestionsData[i].paper_id,
|
||
paperQuestionsData[i].question_type,
|
||
paperQuestionsData[i].question_name,
|
||
paperQuestionsData[i].question_description,
|
||
paperQuestionsData[i].created_at
|
||
]
|
||
);
|
||
// 使用shuffledQuestions[i].id而不是systemQuestions[i].id
|
||
questionIdMap.set(shuffledQuestions[i].id, result.lastID);
|
||
}
|
||
console.log(`成功插入 ${paperQuestionsData.length} 条试卷题目数据`);
|
||
|
||
// 9. 处理question_datasets表
|
||
console.log('处理数据集...');
|
||
const systemDatasets = await systemDb.allAsync('SELECT * FROM question_datasets');
|
||
const userDatasets = systemDatasets
|
||
.filter(dataset => questionIdMap.has(dataset.question_id))
|
||
.map(dataset => ({
|
||
question_id: questionIdMap.get(dataset.question_id),
|
||
dataset_name: dataset.dataset_name,
|
||
dataset_data: dataset.dataset_data,
|
||
created_at: new Date().toISOString() // 修改为toISOString格式
|
||
}));
|
||
if (userDatasets.length > 0) {
|
||
await batchInsert(userDb, 'question_datasets', userDatasets);
|
||
}
|
||
console.log(`成功处理 ${userDatasets.length} 个数据集`);
|
||
|
||
// 10. 处理question_images表
|
||
console.log('处理图片...');
|
||
const systemImages = await systemDb.allAsync('SELECT * FROM question_images');
|
||
const userImages = systemImages
|
||
.filter(image => questionIdMap.has(image.question_id))
|
||
.map(image => ({
|
||
question_id: questionIdMap.get(image.question_id),
|
||
image_name: image.image_name,
|
||
image_base64: image.image_base64,
|
||
created_at: new Date().toISOString(), // 修改为toISOString格式
|
||
updated_at: new Date().toISOString() // 修改为toISOString格式
|
||
}));
|
||
if (userImages.length > 0) {
|
||
await batchInsert(userDb, 'question_images', userImages);
|
||
}
|
||
console.log(`成功处理 ${userImages.length} 张图片`);
|
||
|
||
// 11. 处理question_choices表
|
||
console.log('处理选择题...');
|
||
const systemChoices = await systemDb.allAsync('SELECT * FROM question_choices');
|
||
let userChoices = systemChoices
|
||
.filter(choice => questionIdMap.has(choice.question_id))
|
||
.map(choice => {
|
||
// 打乱选项顺序
|
||
const options = JSON.parse(choice.choice_options);
|
||
|
||
// const sortedOptions = [...options].sort();
|
||
|
||
return {
|
||
question_id: questionIdMap.get(choice.question_id),
|
||
choice_description: choice.choice_description,
|
||
choice_type: choice.choice_type,
|
||
choice_options: JSON.stringify(options),
|
||
correct_answers: choice.correct_answers,
|
||
examinee_answers: '',
|
||
score: choice.score,
|
||
score_real: 0,
|
||
created_at: new Date().toISOString(), // 修改为toISOString格式
|
||
updated_at: new Date().toISOString() // 修改为toISOString格式
|
||
};
|
||
});
|
||
|
||
// 打乱选择题顺序
|
||
userChoices = userChoices.sort(() => Math.random() - 0.5);
|
||
|
||
if (userChoices.length > 0) {
|
||
await batchInsert(userDb, 'question_choices', userChoices);
|
||
}
|
||
console.log(`成功处理 ${userChoices.length} 道选择题`);
|
||
|
||
// 12. 处理question_fill_blanks表
|
||
console.log('处理填空题...');
|
||
const systemFillBlanks = await systemDb.allAsync('SELECT * FROM question_fill_blanks');
|
||
let userFillBlanks = systemFillBlanks
|
||
.filter(blank => questionIdMap.has(blank.question_id))
|
||
.map(blank => ({
|
||
question_id: questionIdMap.get(blank.question_id),
|
||
blank_description: blank.blank_description,
|
||
blank_count: blank.blank_count,
|
||
correct_answers: blank.correct_answers,
|
||
examinee_answers: '',
|
||
score: blank.score,
|
||
score_real: 0,
|
||
created_at: new Date().toISOString(), // 修改为toISOString格式
|
||
updated_at: new Date().toISOString() // 修改为toISOString格式
|
||
}));
|
||
|
||
// 打乱填空题顺序
|
||
userFillBlanks = userFillBlanks.sort(() => Math.random() - 0.5);
|
||
|
||
if (userFillBlanks.length > 0) {
|
||
await batchInsert(userDb, 'question_fill_blanks', userFillBlanks);
|
||
}
|
||
console.log(`成功处理 ${userFillBlanks.length} 道填空题`);
|
||
|
||
// 新增: 计算试卷总分
|
||
console.log('计算试卷总分...');
|
||
// 查询所有选择题分数
|
||
const choicesScoreResult = await userDb.getAsync(
|
||
`SELECT SUM(score) as total FROM question_choices WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
const choicesScore = choicesScoreResult.total || 0;
|
||
|
||
// 查询所有填空题分数
|
||
const fillBlanksScoreResult = await userDb.getAsync(
|
||
`SELECT SUM(score) as total FROM question_fill_blanks WHERE question_id IN (
|
||
SELECT id FROM paper_questions WHERE paper_id = ?
|
||
)`,
|
||
[paperId]
|
||
);
|
||
const fillBlanksScore = fillBlanksScoreResult.total || 0;
|
||
|
||
// 计算总分
|
||
const paperScore = choicesScore + fillBlanksScore;
|
||
console.log(`试卷总分计算完成: ${paperScore}分`);
|
||
|
||
// 更新试卷总分
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers SET paper_score = ? WHERE id = ?`,
|
||
[paperScore, paperId]
|
||
);
|
||
|
||
// 返回成功结果
|
||
// 先查询完整的试卷数据
|
||
const paperData = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
// 查询试卷题目数量
|
||
const questionCount = await userDb.getAsync(
|
||
`SELECT COUNT(*) as count FROM paper_questions WHERE paper_id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
// 构建完整的试卷数据对象
|
||
const completePaperData = {
|
||
...paperData,
|
||
question_count: questionCount.count,
|
||
examinee_id: examineeId,
|
||
examinee_name: processedExamineeData.examinee_name,
|
||
examinee_id_card: processedExamineeData.examinee_id_card,
|
||
examinee_admission_ticket: processedExamineeData.examinee_admission_ticket
|
||
};
|
||
|
||
return {
|
||
success: true,
|
||
message: '试卷生成成功',
|
||
data: completePaperData
|
||
};
|
||
} catch (error) {
|
||
console.error('生成试卷失败:', error);
|
||
return {
|
||
success: false,
|
||
message: `生成试卷失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载试卷试题序列
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Array>} - 包含试题序列的数组
|
||
*/
|
||
export async function loadPaperSerial(paperId) {
|
||
// 函数实现保持不变
|
||
try {
|
||
// 1. 获取数据库连接
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const systemDb = await getDbConnection(getSystemDbPath());
|
||
|
||
// 2. 查询题型字典,获取题型名称
|
||
console.log('开始查询题型字典...');
|
||
const questionTypeDict = await systemDb.allAsync(
|
||
`SELECT item_code, item_name FROM dict_items WHERE type_code = ?`,
|
||
['question_type']
|
||
);
|
||
const questionTypeMap = new Map();
|
||
questionTypeDict.forEach(item => {
|
||
questionTypeMap.set(item.item_code, item.item_name);
|
||
});
|
||
console.log('成功获取题型字典');
|
||
|
||
// 3. 查询试卷中的所有题目,并按question_type和id升序排序
|
||
console.log(`开始查询试卷 ${paperId} 的所有题目...`);
|
||
const paperQuestions = await userDb.allAsync(
|
||
`SELECT * FROM paper_questions
|
||
WHERE paper_id = ?
|
||
ORDER BY question_type ASC, id ASC`,
|
||
[paperId]
|
||
);
|
||
console.log(`成功获取试卷 ${paperId} 的 ${paperQuestions.length} 道题目`);
|
||
|
||
// 4. 构建试题序列
|
||
const paperSerial = [];
|
||
let addedCount = 0;
|
||
let skippedCount = 0;
|
||
let globalSerialNo = 1; // 全局序列号
|
||
|
||
console.log('开始构建试题序列...');
|
||
console.log(`试卷 ${paperId} 的题目列表:`);
|
||
paperQuestions.forEach((q, idx) => {
|
||
console.log(` ${idx + 1}. ID: ${q.id}, 题型: ${q.question_type}`);
|
||
});
|
||
|
||
for (let i = 0; i < paperQuestions.length; i++) {
|
||
const question = paperQuestions[i];
|
||
const questionType = question.question_type;
|
||
const questionTypeName = questionTypeMap.get(questionType) || '未知题型';
|
||
|
||
console.log(`处理第 ${i + 1} 题题干 (ID: ${question.id}, 题型: ${questionType})`);
|
||
|
||
let tableName = '';
|
||
let relatedRecords = [];
|
||
|
||
// 根据题型查询相关表的所有记录
|
||
if (questionType === 'choice') { // 选择题
|
||
tableName = 'question_choices';
|
||
relatedRecords = await userDb.allAsync(
|
||
`SELECT id, examinee_answers FROM question_choices WHERE question_id = ?`,
|
||
[question.id]
|
||
);
|
||
console.log(` 找到 ${relatedRecords.length} 条选择题记录`);
|
||
} else if (questionType === 'fill_blank') { // 填空题
|
||
tableName = 'question_fill_blanks';
|
||
relatedRecords = await userDb.allAsync(
|
||
`SELECT id, examinee_answers FROM question_fill_blanks WHERE question_id = ?`,
|
||
[question.id]
|
||
);
|
||
console.log(` 找到 ${relatedRecords.length} 条填空题记录`);
|
||
} else {
|
||
console.log(` 未处理的题型: ${questionType}`);
|
||
}
|
||
|
||
// 为每条记录添加到试题序列
|
||
if (relatedRecords.length > 0) {
|
||
relatedRecords.forEach((record, recordIdx) => {
|
||
const answered = record.examinee_answers ? 1 : 0;
|
||
const serialNo = globalSerialNo++;
|
||
|
||
// 添加到试题序列
|
||
paperSerial.push({
|
||
serial_no: serialNo,
|
||
id: record.id,
|
||
table_name: tableName,
|
||
question_id: question.id,
|
||
question_type: questionType,
|
||
question_type_name: questionTypeName,
|
||
[tableName === 'question_choices' ? 'choice_id' : 'fill_blank_id']: record.id,
|
||
answered
|
||
});
|
||
|
||
console.log(` 添加第 ${recordIdx + 1} 个具体问题到试题序列,序列号: ${serialNo}`);
|
||
addedCount++;
|
||
});
|
||
} else {
|
||
console.log(` 未找到相关记录,跳过`);
|
||
skippedCount++;
|
||
}
|
||
}
|
||
console.log(`试题序列构建完成: 共 ${paperQuestions.length} 道题,添加 ${addedCount} 道,跳过 ${skippedCount} 道`);
|
||
return paperSerial;
|
||
} catch (error) {
|
||
console.error('加载试卷试题序列失败:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据表名和ID获取完整的试题数据
|
||
* @param {string} tableName - 表名 (question_choices 或 question_fill_blanks)
|
||
* @param {number} id - 记录ID
|
||
* @returns {Promise<Object>} - 完整的试题数据
|
||
*/
|
||
export async function getQuestionByRelatedId(tableName, id) {
|
||
try {
|
||
// 1. 获取数据库连接
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const systemDb = await getDbConnection(getSystemDbPath());
|
||
|
||
// 2. 验证表名
|
||
// if (!['question_choices', 'question_fill_blanks'].includes(tableName)) {
|
||
// throw new Error('无效的表名,只能是 question_choices 或 question_fill_blanks');
|
||
// }
|
||
|
||
// 3. 查询相关表获取question_id
|
||
console.log(`查询 ${tableName} 表,ID: ${id}`);
|
||
const relatedRecord = await userDb.getAsync(
|
||
`SELECT * FROM ${tableName} WHERE id = ?`,
|
||
[id]
|
||
);
|
||
|
||
if (!relatedRecord) {
|
||
throw new Error(`未找到 ${tableName} 表中ID为 ${id} 的记录`);
|
||
}
|
||
|
||
const questionId = relatedRecord.question_id;
|
||
console.log(`找到关联的题干ID: ${questionId}`);
|
||
|
||
// 4. 查询题干信息
|
||
const question = await userDb.getAsync(
|
||
`SELECT * FROM paper_questions WHERE id = ?`,
|
||
[questionId]
|
||
);
|
||
|
||
if (!question) {
|
||
throw new Error(`未找到题干ID为 ${questionId} 的记录`);
|
||
}
|
||
|
||
// 5. 查询题型字典信息
|
||
const questionType = question.question_type;
|
||
const dictItem = await systemDb.getAsync(
|
||
`SELECT * FROM dict_items WHERE item_code = ? AND type_code = 'question_type'`,
|
||
[questionType]
|
||
);
|
||
|
||
// 6. 查询关联的数据集
|
||
const datasets = await userDb.allAsync(
|
||
`SELECT * FROM question_datasets WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
|
||
// 7. 查询关联的图片
|
||
const images = await userDb.allAsync(
|
||
`SELECT * FROM question_images WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
|
||
// 8. 根据题型查询关联问题
|
||
// let relatedQuestionData = [];
|
||
// if (questionType === 'choice') {
|
||
// relatedQuestionData = await userDb.allAsync(
|
||
// `SELECT * FROM question_choices WHERE question_id = ?`,
|
||
// [questionId]
|
||
// );
|
||
// // 将选项、正确答案和考生答案解析为数组
|
||
// relatedQuestionData.forEach(item => {
|
||
// // 解析选项
|
||
// if (item.choice_options) {
|
||
// try {
|
||
// item.choice_options = JSON.parse(item.choice_options);
|
||
// if (!Array.isArray(item.choice_options)) {
|
||
// item.choice_options = [item.choice_options];
|
||
// }
|
||
// } catch (e) {
|
||
// console.error('解析选项失败:', e);
|
||
// item.choice_options = []; // 解析失败时设置为空数组
|
||
// }
|
||
// } else {
|
||
// item.choice_options = [];
|
||
// }
|
||
|
||
// // 解析正确答案
|
||
// if (item.correct_answers) {
|
||
// try {
|
||
// item.correct_answers = JSON.parse(item.correct_answers);
|
||
// if (!Array.isArray(item.correct_answers)) {
|
||
// item.correct_answers = [item.correct_answers];
|
||
// }
|
||
// } catch (e) {
|
||
// console.error('解析正确答案失败:', e);
|
||
// item.correct_answers = []; // 解析失败时设置为空数组
|
||
// }
|
||
// } else {
|
||
// item.correct_answers = [];
|
||
// }
|
||
|
||
// // 解析考生答案
|
||
// if (item.examinee_answers) {
|
||
// // 处理空字符串情况
|
||
// if (item.examinee_answers.trim() === '') {
|
||
// item.examinee_answers = [];
|
||
// } else {
|
||
// try {
|
||
// item.examinee_answers = JSON.parse(item.examinee_answers);
|
||
// if (!Array.isArray(item.examinee_answers)) {
|
||
// item.examinee_answers = [item.examinee_answers];
|
||
// }
|
||
// } catch (e) {
|
||
// console.error('解析考生答案失败:', e);
|
||
// item.examinee_answers = []; // 解析失败时设置为空数组
|
||
// }
|
||
// }
|
||
// } else {
|
||
// item.examinee_answers = [];
|
||
// }
|
||
// });
|
||
// } else if (questionType === 'fill_blank') {
|
||
// relatedQuestionData = await userDb.allAsync(
|
||
// `SELECT * FROM question_fill_blanks WHERE question_id = ?`,
|
||
// [questionId]
|
||
// );
|
||
// // 解析填空题的正确答案和考生答案
|
||
// relatedQuestionData.forEach(item => {
|
||
// // 解析正确答案
|
||
// if (item.correct_answers) {
|
||
// try {
|
||
// item.correct_answers = JSON.parse(item.correct_answers);
|
||
// // 确保结果是数组
|
||
// if (!Array.isArray(item.correct_answers)) {
|
||
// item.correct_answers = [item.correct_answers];
|
||
// }
|
||
// } catch (e) {
|
||
// console.error('解析正确答案失败:', e);
|
||
// item.correct_answers = [];
|
||
// }
|
||
// } else {
|
||
// item.correct_answers = [];
|
||
// }
|
||
|
||
// // 解析考生答案
|
||
// if (item.examinee_answers) {
|
||
// // 处理空字符串情况
|
||
// if (item.examinee_answers.trim() === '') {
|
||
// item.examinee_answers = [];
|
||
// } else {
|
||
// try {
|
||
// item.examinee_answers = JSON.parse(item.examinee_answers);
|
||
// // 确保结果是数组
|
||
// if (!Array.isArray(item.examinee_answers)) {
|
||
// item.examinee_answers = [item.examinee_answers];
|
||
// }
|
||
// } catch (e) {
|
||
// console.error('解析考生答案失败:', e);
|
||
// item.examinee_answers = [];
|
||
// }
|
||
// }
|
||
// } else {
|
||
// item.examinee_answers = [];
|
||
// }
|
||
// });
|
||
// }
|
||
|
||
// 9. 构建返回结果
|
||
question.datasets = datasets;
|
||
question.images = images;
|
||
question.type_info = dictItem || null;
|
||
|
||
// 将关联问题数据添加到question对象
|
||
// if (relatedQuestionData.length > 0) {
|
||
// if (questionType === 'choice') {
|
||
// question.choices = relatedQuestionData;
|
||
// } else if (questionType === 'fill_blank') {
|
||
// question.fill_blanks = relatedQuestionData;
|
||
// }
|
||
// }
|
||
|
||
/// TODO: 如果question.question_type是choice
|
||
/// 把relatedRecord的choice_options、correct_answers、examinee_answers解析成数组,注意有可能是空字符串
|
||
/// 如果是fill_blank,把relatedRecord的correct_answers、examinee_answers解析成数组
|
||
/// 解析选项
|
||
if (question.question_type === 'choice') {
|
||
if (relatedRecord.choice_options) {
|
||
try {
|
||
relatedRecord.choice_options = JSON.parse(relatedRecord.choice_options);
|
||
if (!Array.isArray(relatedRecord.choice_options)) {
|
||
relatedRecord.choice_options = [relatedRecord.choice_options];
|
||
}
|
||
} catch (e) {
|
||
console.error('解析选项失败:', e);
|
||
relatedRecord.choice_options = []; // 解析失败时设置为空数组
|
||
}
|
||
} else {
|
||
relatedRecord.choice_options = [];
|
||
}
|
||
}
|
||
/// 解析正确答案
|
||
if (question.question_type === 'choice') {
|
||
if (relatedRecord.correct_answers) {
|
||
try {
|
||
relatedRecord.correct_answers = JSON.parse(relatedRecord.correct_answers);
|
||
if (!Array.isArray(relatedRecord.correct_answers)) {
|
||
relatedRecord.correct_answers = [relatedRecord.correct_answers];
|
||
}
|
||
} catch (e) {
|
||
console.error('解析正确答案失败:', e);
|
||
relatedRecord.correct_answers = []; // 解析失败时设置为空数组
|
||
}
|
||
} else {
|
||
relatedRecord.correct_answers = [];
|
||
}
|
||
}
|
||
/// 解析考生答案
|
||
if (question.question_type === 'choice') {
|
||
if (relatedRecord.examinee_answers) {
|
||
try {
|
||
relatedRecord.examinee_answers = JSON.parse(relatedRecord.examinee_answers);
|
||
if (!Array.isArray(relatedRecord.examinee_answers)) {
|
||
relatedRecord.examinee_answers = [relatedRecord.examinee_answers];
|
||
}
|
||
} catch (e) {
|
||
console.error('解析考生答案失败:', e);
|
||
relatedRecord.examinee_answers = []; // 解析失败时设置为空数组
|
||
}
|
||
} else {
|
||
relatedRecord.examinee_answers = [];
|
||
}
|
||
}
|
||
/// 如果是fill_blank,把relatedRecord的correct_answers、examinee_answers解析成数组
|
||
if (question.question_type === 'fill_blank') {
|
||
if (relatedRecord.correct_answers) {
|
||
try {
|
||
relatedRecord.correct_answers = JSON.parse(relatedRecord.correct_answers);
|
||
if (!Array.isArray(relatedRecord.correct_answers)) {
|
||
relatedRecord.correct_answers = [relatedRecord.correct_answers];
|
||
}
|
||
} catch (e) {
|
||
console.error('解析正确答案失败:', e);
|
||
relatedRecord.correct_answers = []; // 解析失败时设置为空数组
|
||
}
|
||
} else {
|
||
relatedRecord.correct_answers = [];
|
||
}
|
||
}
|
||
/// 解析考生答案
|
||
if (question.question_type === 'fill_blank') {
|
||
if (relatedRecord.examinee_answers) {
|
||
try {
|
||
relatedRecord.examinee_answers = JSON.parse(relatedRecord.examinee_answers);
|
||
if (!Array.isArray(relatedRecord.examinee_answers)) {
|
||
relatedRecord.examinee_answers = [relatedRecord.examinee_answers];
|
||
}
|
||
} catch (e) {
|
||
console.error('解析考生答案失败:', e);
|
||
relatedRecord.examinee_answers = []; // 解析失败时设置为空数组
|
||
}
|
||
} else {
|
||
relatedRecord.examinee_answers = [];
|
||
}
|
||
}
|
||
|
||
const result = {
|
||
question_detail: relatedRecord,
|
||
question: question
|
||
};
|
||
|
||
console.log('成功获取完整试题数据');
|
||
return result;
|
||
} catch (error) {
|
||
console.error('获取试题数据失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新考生答案
|
||
* @param {string} tableName - 表名 (question_choices 或 question_fill_blanks)
|
||
* @param {number} id - 记录ID
|
||
* @param {Array|string} answers - 考生答案
|
||
* @returns {Promise<boolean>} - 是否更新成功
|
||
*/
|
||
export async function updateExamineeAnswer(tableName, id, answers) {
|
||
try {
|
||
// 验证表名
|
||
if (!['question_choices', 'question_fill_blanks'].includes(tableName)) {
|
||
throw new Error('无效的表名,只能是 question_choices 或 question_fill_blanks');
|
||
}
|
||
|
||
// 获取数据库连接
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
|
||
// 确保答案是JSON字符串
|
||
const answersJson = Array.isArray(answers) ? JSON.stringify(answers) : answers;
|
||
|
||
// 更新考生答案
|
||
const result = await userDb.runAsync(
|
||
`UPDATE ${tableName} SET examinee_answers = ?, updated_at = ? WHERE id = ?`,
|
||
[answersJson, new Date().toISOString(), id] // 修改为toISOString格式
|
||
);
|
||
|
||
return result.changes > 0;
|
||
} catch (error) {
|
||
console.error('更新考生答案失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 替换现有的startPaper方法
|
||
/**
|
||
* 开始考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和试卷数据的对象
|
||
*/
|
||
export async function startPaper(paperId) {
|
||
try {
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const currentTime = formatDateTime(new Date()); // 修改为格式化日期
|
||
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers
|
||
SET paper_status = 1,
|
||
paper_start_time = ?
|
||
WHERE id = ?`,
|
||
[currentTime, paperId]
|
||
);
|
||
|
||
// 查询更新后的试卷数据
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
message: '考试已成功开始',
|
||
data: paper
|
||
};
|
||
} catch (error) {
|
||
console.error('开始考试失败:', error);
|
||
return {
|
||
success: false,
|
||
message: `开始考试失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
// 替换现有的submitPaper方法
|
||
/**
|
||
* 提交考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和试卷数据的对象
|
||
*/
|
||
export async function submitPaper(paperId) {
|
||
try {
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const currentTime = formatDateTime(new Date()); // 修改为格式化日期
|
||
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers
|
||
SET paper_status = 2,
|
||
paper_submit_time = ?,
|
||
paper_end_time = ?
|
||
WHERE id = ?`,
|
||
[currentTime, currentTime, paperId]
|
||
);
|
||
|
||
// 查询更新后的试卷数据
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
message: '考试已成功提交',
|
||
data: paper
|
||
};
|
||
} catch (error) {
|
||
console.error('提交考试失败:', error);
|
||
return {
|
||
success: false,
|
||
message: `提交考试失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
// 替换现有的endPaper方法
|
||
/**
|
||
* 结束考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和试卷数据的对象
|
||
*/
|
||
export async function endPaper(paperId) {
|
||
try {
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const currentTime = formatDateTime(new Date()); // 修改为格式化日期
|
||
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers
|
||
SET paper_status = 2,
|
||
paper_end_time = ?
|
||
WHERE id = ?`,
|
||
[currentTime, paperId]
|
||
);
|
||
|
||
// 查询更新后的试卷数据
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
message: '考试已成功结束',
|
||
data: paper
|
||
};
|
||
} catch (error) {
|
||
console.error('结束考试失败:', error);
|
||
return {
|
||
success: false,
|
||
message: `结束考试失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
// 替换现有的processPaper方法
|
||
/**
|
||
* 更新试卷最后操作时间
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和试卷数据的对象
|
||
*/
|
||
export async function processPaper(paperId) {
|
||
try {
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const currentTime = formatDateTime(new Date()); // 统一使用格式化日期
|
||
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers
|
||
SET paper_last_time = ?
|
||
WHERE id = ?`,
|
||
[currentTime, paperId]
|
||
);
|
||
|
||
// 查询更新后的试卷数据
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
console.log('更新试卷最后操作时间成功:', paper); // 修复拼写错误并添加日志
|
||
return {
|
||
success: true,
|
||
message: '试卷处理时间已更新',
|
||
data: paper
|
||
};
|
||
} catch (error) {
|
||
console.error('处理试卷失败:', error);
|
||
return {
|
||
success: false,
|
||
message: `处理试卷失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查试卷答案并计算得分
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和带关联的试卷数据的对象
|
||
*/
|
||
export async function checkPaperAnswers(paperId) {
|
||
try {
|
||
// 获取用户数据库路径
|
||
const userDbPath = getUserDbPath();
|
||
// 连接用户数据库
|
||
const userDb = await getDbConnection(userDbPath);
|
||
|
||
// 1. 查询试卷基本信息
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
if (!paper) {
|
||
await closeAllConnections();
|
||
return {
|
||
success: false,
|
||
message: `未找到ID为${paperId}的试卷`,
|
||
data: null
|
||
};
|
||
}
|
||
|
||
// 2. 查询试卷关联的所有试题
|
||
const paperQuestions = await userDb.allAsync(
|
||
`SELECT * FROM paper_questions WHERE paper_id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
let totalScore = 0;
|
||
|
||
// 3. 遍历所有试题,查询并比对答案
|
||
for (const question of paperQuestions) {
|
||
const questionId = question.id;
|
||
const questionType = question.question_type;
|
||
|
||
// 根据题型查询对应的答案表
|
||
if (questionType === 'choice') {
|
||
// 选择题
|
||
const choices = await userDb.allAsync(
|
||
`SELECT * FROM question_choices WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
|
||
for (const choice of choices) {
|
||
// 解析正确答案和考生答案
|
||
const correctAnswers = JSON.parse(choice.correct_answers || '[]');
|
||
const examineeAnswers = JSON.parse(choice.examinee_answers || '[]');
|
||
|
||
// 打印题目信息
|
||
console.log(`\n选择题ID: ${choice.id}`);
|
||
console.log(`正确答案:`, correctAnswers);
|
||
console.log(`考生答案:`, examineeAnswers);
|
||
|
||
// 比对答案 - 不考虑顺序
|
||
let isCorrect = true;
|
||
if (correctAnswers.length !== examineeAnswers.length) {
|
||
isCorrect = false;
|
||
} else {
|
||
// 创建正确答案的副本用于比对
|
||
const correctAnswersCopy = [...correctAnswers];
|
||
|
||
// 检查考生答案中的每个元素是否在正确答案中存在
|
||
for (const answer of examineeAnswers) {
|
||
const index = correctAnswersCopy.indexOf(answer);
|
||
if (index === -1) {
|
||
isCorrect = false;
|
||
break;
|
||
}
|
||
// 移除已匹配的答案,避免重复匹配
|
||
correctAnswersCopy.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
// 计算得分
|
||
const scoreReal = isCorrect ? (choice.score || 0) : 0;
|
||
totalScore += scoreReal;
|
||
|
||
// 打印判断结果和得分
|
||
console.log(`判断结果: ${isCorrect ? '正确' : '错误'}`);
|
||
console.log(`本题得分: ${scoreReal}`);
|
||
|
||
// 更新本题得分
|
||
await userDb.runAsync(
|
||
`UPDATE question_choices SET score_real = ? WHERE id = ?`,
|
||
[scoreReal, choice.id]
|
||
);
|
||
}
|
||
} else if (questionType === 'fill_blank') {
|
||
// 填空题
|
||
const blanks = await userDb.allAsync(
|
||
`SELECT * FROM question_fill_blanks WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
|
||
for (const blank of blanks) {
|
||
// 解析正确答案和考生答案
|
||
const correctAnswers = JSON.parse(blank.correct_answers || '[]');
|
||
const examineeAnswers = JSON.parse(blank.examinee_answers || '[]');
|
||
|
||
// 打印题目信息
|
||
console.log(`\n填空题ID: ${blank.id}`);
|
||
console.log(`正确答案:`, correctAnswers);
|
||
console.log(`考生答案:`, examineeAnswers);
|
||
|
||
// 比对答案 - 不考虑顺序
|
||
let isCorrect = true;
|
||
if (correctAnswers.length !== examineeAnswers.length) {
|
||
isCorrect = false;
|
||
} else {
|
||
// 创建正确答案的副本用于比对
|
||
const correctAnswersCopy = [...correctAnswers];
|
||
|
||
// 检查考生答案中的每个元素是否在正确答案中存在
|
||
for (const answer of examineeAnswers) {
|
||
const index = correctAnswersCopy.indexOf(answer);
|
||
if (index === -1) {
|
||
isCorrect = false;
|
||
break;
|
||
}
|
||
// 移除已匹配的答案,避免重复匹配
|
||
correctAnswersCopy.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
// 计算得分
|
||
const scoreReal = isCorrect ? (blank.score || 0) : 0;
|
||
totalScore += scoreReal;
|
||
|
||
// 打印判断结果和得分
|
||
console.log(`判断结果: ${isCorrect ? '正确' : '错误'}`);
|
||
console.log(`本题得分: ${scoreReal}`);
|
||
|
||
// 更新本题得分
|
||
await userDb.runAsync(
|
||
`UPDATE question_fill_blanks SET score_real = ? WHERE id = ?`,
|
||
[scoreReal, blank.id]
|
||
);
|
||
}
|
||
}
|
||
// 可以根据需要添加其他题型的处理
|
||
}
|
||
|
||
// 4. 更新试卷总分
|
||
await userDb.runAsync(
|
||
`UPDATE examinee_papers SET paper_score_real = ? WHERE id = ?`,
|
||
[totalScore, paperId]
|
||
);
|
||
|
||
// 5. 查询更新后的试卷信息(包含关联数据)
|
||
// const updatedPaper = await userDb.getAsync(
|
||
// `SELECT * FROM examinee_papers WHERE id = ?`,
|
||
// [paperId]
|
||
// );
|
||
const updatedPaper = await getPaper(paperId);
|
||
console.log(updatedPaper);
|
||
// 关闭数据库连接
|
||
await closeAllConnections();
|
||
|
||
return {
|
||
success: true,
|
||
message: '试卷判卷成功',
|
||
data: updatedPaper.data
|
||
};
|
||
} catch (error) {
|
||
console.error('判卷过程中发生错误:', error);
|
||
await closeAllConnections();
|
||
return {
|
||
success: false,
|
||
message: `判卷失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
}
|
||
|
||
export async function getPaper(paperId) {
|
||
try {
|
||
// 获取数据库路径
|
||
const systemDbPath = getSystemDbPath();
|
||
const userDbPath = getUserDbPath();
|
||
|
||
// 连接数据库
|
||
const systemDb = await getDbConnection(systemDbPath);
|
||
const userDb = await getDbConnection(userDbPath);
|
||
|
||
// 1. 查询试卷基本信息
|
||
const paper = await userDb.getAsync(
|
||
`SELECT * FROM examinee_papers WHERE id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
if (!paper) {
|
||
await closeAllConnections();
|
||
return {
|
||
success: false,
|
||
message: `未找到ID为${paperId}的试卷`,
|
||
data: null
|
||
};
|
||
}
|
||
|
||
// 补充: 查询关联的examinee
|
||
const examinee = await userDb.getAsync(
|
||
`SELECT * FROM examinee WHERE id = ?`,
|
||
[paper.examinee_id]
|
||
);
|
||
|
||
// 2. 查询试卷关联的题目
|
||
const paperQuestions = await userDb.allAsync(
|
||
`SELECT * FROM paper_questions WHERE paper_id = ?`,
|
||
[paperId]
|
||
);
|
||
|
||
// 3. 为每个题目获取详细信息
|
||
const questionsWithDetails = [];
|
||
for (const question of paperQuestions) {
|
||
const questionId = question.id;
|
||
const questionType = question.question_type;
|
||
|
||
// 3.1 查询题型名称
|
||
const dictItem = await systemDb.getAsync(
|
||
`SELECT item_name FROM dict_items WHERE type_code = 'question_type' AND item_code = ?`,
|
||
[questionType]
|
||
);
|
||
|
||
const questionWithDetails = {
|
||
...question,
|
||
question_type_name: dictItem?.item_name || '',
|
||
images: [],
|
||
datasets: [],
|
||
choices: [],
|
||
blanks: []
|
||
};
|
||
|
||
// 3.2 查询题目图片
|
||
const images = await userDb.allAsync(
|
||
`SELECT * FROM question_images WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
questionWithDetails.images = images;
|
||
|
||
// 3.3 查询题目数据集
|
||
const datasets = await userDb.allAsync(
|
||
`SELECT * FROM question_datasets WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
// 解析dataset_data为数组
|
||
questionWithDetails.datasets = datasets.map(dataset => ({
|
||
...dataset,
|
||
dataset_data: JSON.parse(dataset.dataset_data || '[]')
|
||
}));
|
||
|
||
// 3.4 根据题型查询对应的答案表
|
||
if (questionType === 'choice') {
|
||
// 查询选择题
|
||
const choices = await userDb.allAsync(
|
||
`SELECT * FROM question_choices WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
// 解析数组列
|
||
questionWithDetails.choices = choices.map(choice => ({
|
||
...choice,
|
||
choice_options: JSON.parse(choice.choice_options || '[]'),
|
||
correct_answers: JSON.parse(choice.correct_answers || '[]'),
|
||
examinee_answers: JSON.parse(choice.examinee_answers || '[]')
|
||
}));
|
||
} else if (questionType === 'fill_blank') {
|
||
// 查询填空题
|
||
const blanks = await userDb.allAsync(
|
||
`SELECT * FROM question_fill_blanks WHERE question_id = ?`,
|
||
[questionId]
|
||
);
|
||
// 解析数组列
|
||
questionWithDetails.blanks = blanks.map(blank => ({
|
||
...blank,
|
||
correct_answers: JSON.parse(blank.correct_answers || '[]'),
|
||
examinee_answers: JSON.parse(blank.examinee_answers || '[]')
|
||
}));
|
||
}
|
||
|
||
questionsWithDetails.push(questionWithDetails);
|
||
}
|
||
|
||
// 4. 构建完整的试卷对象
|
||
const fullPaper = {
|
||
...paper,
|
||
examinee: examinee,
|
||
questions: questionsWithDetails
|
||
};
|
||
|
||
// 关闭数据库连接
|
||
await closeAllConnections();
|
||
|
||
return {
|
||
success: true,
|
||
message: '获取试卷成功',
|
||
data: JSON.stringify(fullPaper)
|
||
};
|
||
} catch (error) {
|
||
console.error('获取试卷过程中发生错误:', error);
|
||
await closeAllConnections();
|
||
return {
|
||
success: false,
|
||
message: `获取试卷失败: ${error.message}`,
|
||
data: null
|
||
};
|
||
}
|
||
} |