// 导入必要的模块和函数 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} - 包含试卷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} - 包含试题序列的数组 */ 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} - 完整的试题数据 */ 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} - 是否更新成功 */ 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} - 包含操作结果和试卷数据的对象 */ 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} - 包含操作结果和试卷数据的对象 */ 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} - 包含操作结果和试卷数据的对象 */ 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} - 包含操作结果和试卷数据的对象 */ 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} - 包含操作结果和带关联的试卷数据的对象 */ 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; for (const correct of correctAnswersCopy) { if (Number(answer) === Number(correct)) { isCorrect = true; break; } } 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 }; } }