723 lines
19 KiB
JavaScript
723 lines
19 KiB
JavaScript
// 首先在文件顶部的require语句中添加getExamineePaper
|
||
const {
|
||
generateExamineePaper,
|
||
loadPaperSerial,
|
||
getQuestionByRelatedId,
|
||
updateExamineeAnswer,
|
||
startPaper,
|
||
submitPaper,
|
||
endPaper,
|
||
processPaper,
|
||
checkPaperAnswers,
|
||
getPaper,
|
||
getExamineePaper,
|
||
continueExam,
|
||
clearExamineePaper,
|
||
} = require("../db/examing.js");
|
||
const { getDbConnection, closeAllConnections } = require("../db/index.js");
|
||
const { getUserDbPath } = require("../db/path.js");
|
||
|
||
/**
|
||
* 服务层:生成考生试卷
|
||
* @param {Object} examineeData - 考生数据
|
||
* @param {number} examDuration - 考试时长(分钟)
|
||
* @returns {Promise<Object>} - 包含试卷ID和状态的对象
|
||
*/
|
||
async function generateExamineePaperService(examineeData, examData) {
|
||
try {
|
||
// 数据验证
|
||
if (!examineeData || !examineeData.id || !examineeData.examinee_name) {
|
||
throw new Error("考生数据不完整,必须包含ID和姓名");
|
||
}
|
||
|
||
if (!examData || !examData.exam_minutes || examData.exam_minutes <= 0) {
|
||
throw new Error("考试时长必须为正数");
|
||
}
|
||
|
||
if (
|
||
examData.exam_minutes_min === undefined ||
|
||
examData.exam_minutes_min < 0
|
||
) {
|
||
throw new Error("最短考试时长必须为非负数");
|
||
}
|
||
|
||
const result = await generateExamineePaper(examineeData, examData);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 生成考生试卷失败", error);
|
||
return {
|
||
success: false,
|
||
message: `生成试卷失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:获取考生试卷状态
|
||
* @param {number} examineeId - 考生ID
|
||
* @returns {Promise<Object|null>} - 试卷状态信息
|
||
*/
|
||
async function getExamineePaperStatusService(examineeId) {
|
||
try {
|
||
if (!examineeId || examineeId <= 0) {
|
||
throw new Error("考生ID必须为正数");
|
||
}
|
||
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
const paperStatus = await userDb.getAsync(
|
||
"SELECT * FROM examinee_papers WHERE examinee_id = ?",
|
||
[examineeId]
|
||
);
|
||
|
||
return paperStatus;
|
||
} catch (error) {
|
||
console.error("服务层: 获取考生试卷状态失败", error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async function clearExamineePaperService(paperId) {
|
||
try {
|
||
const result = await clearExamineePaper(paperId);
|
||
return {
|
||
success: true,
|
||
message: "试卷数据清理成功",
|
||
data: result,
|
||
};
|
||
} catch (error) {
|
||
console.error("清理试卷数据失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `清理试卷数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:更新试卷状态
|
||
* @param {number} paperId - 试卷ID
|
||
* @param {Object} statusData - 状态数据
|
||
* @returns {Promise<boolean>} - 是否更新成功
|
||
*/
|
||
async function updatePaperStatusService(paperId, statusData) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const userDb = await getDbConnection(getUserDbPath());
|
||
|
||
// 构建更新字段
|
||
const fields = [];
|
||
const values = [];
|
||
|
||
if (statusData.paper_start_time !== undefined) {
|
||
fields.push("paper_start_time = ?");
|
||
values.push(statusData.paper_start_time);
|
||
}
|
||
|
||
if (statusData.paper_last_time !== undefined) {
|
||
fields.push("paper_last_time = ?");
|
||
values.push(statusData.paper_last_time);
|
||
}
|
||
|
||
if (statusData.paper_submit_time !== undefined) {
|
||
fields.push("paper_submit_time = ?");
|
||
values.push(statusData.paper_submit_time);
|
||
}
|
||
|
||
if (statusData.paper_end_time !== undefined) {
|
||
fields.push("paper_end_time = ?");
|
||
values.push(statusData.paper_end_time);
|
||
}
|
||
|
||
if (statusData.paper_status !== undefined) {
|
||
fields.push("paper_status = ?");
|
||
values.push(statusData.paper_status);
|
||
}
|
||
|
||
if (statusData.paper_score_real !== undefined) {
|
||
fields.push("paper_score_real = ?");
|
||
values.push(statusData.paper_score_real);
|
||
}
|
||
|
||
if (fields.length === 0) {
|
||
return true; // 没有需要更新的字段
|
||
}
|
||
|
||
// 添加WHERE条件的值
|
||
values.push(paperId);
|
||
|
||
const sql = `UPDATE examinee_papers SET ${fields.join(", ")} WHERE id = ?`;
|
||
await userDb.runAsync(sql, values);
|
||
|
||
return true;
|
||
} catch (error) {
|
||
console.error("服务层: 更新试卷状态失败", error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:加载试卷试题序列
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Array>} - 包含试题序列的数组
|
||
*/
|
||
async function loadPaperSerialService(paperId) {
|
||
console.log("0903调试(loadPaperSerialService): ", paperId);
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await loadPaperSerial(paperId);
|
||
return {
|
||
success: true,
|
||
data: result,
|
||
};
|
||
} catch (error) {
|
||
console.error("服务层: 加载试卷试题序列失败", error);
|
||
return {
|
||
success: false,
|
||
message: `加载试卷试题序列失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:根据表名和ID获取完整的试题数据
|
||
* @param {string} tableName - 表名 (question_choices 或 question_fill_blanks)
|
||
* @param {number} id - 记录ID
|
||
* @returns {Promise<Object>} - 包含试题数据的对象
|
||
*/
|
||
async function getQuestionByRelatedIdService(tableName, id) {
|
||
try {
|
||
const result = await getQuestionByRelatedId(tableName, id);
|
||
return {
|
||
success: true,
|
||
data: result,
|
||
};
|
||
} catch (error) {
|
||
console.error("服务层: 获取试题数据失败", error);
|
||
return {
|
||
success: false,
|
||
message: `获取试题数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:更新考生答案
|
||
* @param {string} tableName - 表名 (question_choices 或 question_fill_blanks)
|
||
* @param {number} id - 记录ID
|
||
* @param {Array|string} answers - 考生答案
|
||
* @returns {Promise<Object>} - 包含更新结果的对象
|
||
*/
|
||
async function updateExamineeAnswerService(tableName, id, answers) {
|
||
try {
|
||
if (!["question_choices", "question_fill_blanks"].includes(tableName)) {
|
||
throw new Error(
|
||
"无效的表名,只能是 question_choices 或 question_fill_blanks"
|
||
);
|
||
}
|
||
|
||
if (!id || id <= 0) {
|
||
throw new Error("记录ID必须为正数");
|
||
}
|
||
|
||
const result = await updateExamineeAnswer(tableName, id, answers);
|
||
return {
|
||
success: true,
|
||
message: "答案更新成功",
|
||
};
|
||
} catch (error) {
|
||
console.error("服务层: 更新考生答案失败", error);
|
||
return {
|
||
success: false,
|
||
message: `更新答案失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:开始考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function startPaperService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await startPaper(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 开始考试失败", error);
|
||
return {
|
||
success: false,
|
||
message: `开始考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:获取试卷详细信息
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含试卷详细信息的对象
|
||
*/
|
||
async function getPaperService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await getPaper(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 获取试卷详细信息失败", error);
|
||
return {
|
||
success: false,
|
||
message: `获取试卷详细信息失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:提交考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function submitPaperService(paperId, duration_seconds) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
// 1. 提交试卷
|
||
const submitResult = await submitPaper(paperId, duration_seconds);
|
||
|
||
if (!submitResult.success) {
|
||
throw new Error(submitResult.message);
|
||
}
|
||
|
||
// 2. 判卷
|
||
const checkResult = await checkPaperAnswers(paperId);
|
||
|
||
if (!checkResult.success) {
|
||
throw new Error(checkResult.message);
|
||
}
|
||
|
||
// 3. 获取完整试卷数据
|
||
const paperResult = await getPaper(paperId);
|
||
|
||
if (!paperResult.success) {
|
||
throw new Error(paperResult.message);
|
||
}
|
||
|
||
// 返回带有完整试卷数据的结果
|
||
return {
|
||
success: true,
|
||
message: "考试提交并判卷成功",
|
||
data: paperResult.data,
|
||
};
|
||
} catch (error) {
|
||
console.error("服务层: 提交考试失败", error);
|
||
return {
|
||
success: false,
|
||
message: `提交考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:获取考试结果
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function getExamResultService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await getPaper(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 获取考试结果失败", error);
|
||
return {
|
||
success: false,
|
||
message: `获取考试结果失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:结束考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function endPaperService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await endPaper(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 结束考试失败", error);
|
||
return {
|
||
success: false,
|
||
message: `结束考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:处理试卷
|
||
* @param {number} paperId - 试卷ID
|
||
* @param {number} duration_seconds - 答题时长(秒)
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function processPaperService(paperId, duration_seconds) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
// 这样在继续考试时,就不会覆盖数据库中已有的paper_duration_seconds值
|
||
if (duration_seconds === undefined || duration_seconds === null) {
|
||
return await processPaper(paperId);
|
||
}
|
||
return await processPaper(paperId, duration_seconds);
|
||
} catch (error) {
|
||
console.error("服务层: 处理试卷失败", error);
|
||
return {
|
||
success: false,
|
||
message: `处理试卷失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:检查试卷答案并计算得分
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果和试卷数据的对象
|
||
*/
|
||
async function checkPaperAnswersService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await checkPaperAnswers(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 检查试卷答案失败", error);
|
||
return {
|
||
success: false,
|
||
message: `检查试卷答案失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:根据考生ID获取试卷数据
|
||
* @param {number} examineeId - 考生ID
|
||
* @returns {Promise<Object>} - 包含试卷数据的对象
|
||
*/
|
||
async function getExamineePaperService(examineeId) {
|
||
try {
|
||
if (!examineeId || examineeId <= 0) {
|
||
throw new Error("考生ID必须为正数");
|
||
}
|
||
|
||
const result = await getExamineePaper(examineeId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 获取考生试卷数据失败", error);
|
||
return {
|
||
success: false,
|
||
message: `获取考生试卷数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 服务层:继续未完成的考试
|
||
* @param {number} paperId - 试卷ID
|
||
* @returns {Promise<Object>} - 包含操作结果的对象
|
||
*/
|
||
async function continueExamService(paperId) {
|
||
try {
|
||
if (!paperId || paperId <= 0) {
|
||
throw new Error("试卷ID必须为正数");
|
||
}
|
||
|
||
const result = await continueExam(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("服务层: 继续考试失败", error);
|
||
return {
|
||
success: false,
|
||
message: `继续考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 在initExamingIpc函数中添加continueExam的IPC处理程序(在其他处理器之后添加)
|
||
function initExamingIpc(ipcMain) {
|
||
// 生成考生试卷
|
||
ipcMain.handle(
|
||
"examing-generate-paper",
|
||
async (event, { examineeData, examData }) => {
|
||
try {
|
||
return await generateExamineePaperService(examineeData, examData);
|
||
} catch (error) {
|
||
console.error("生成考生试卷失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `生成试卷失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 获取考生试卷状态
|
||
ipcMain.handle("examing-get-paper-status", async (event, examineeId) => {
|
||
try {
|
||
return await getExamineePaperStatusService(examineeId);
|
||
} catch (error) {
|
||
console.error("获取考生试卷状态失败:", error);
|
||
return null;
|
||
}
|
||
});
|
||
|
||
// 更新试卷状态
|
||
ipcMain.handle(
|
||
"examing-update-paper-status",
|
||
async (event, { paperId, statusData }) => {
|
||
try {
|
||
return await updatePaperStatusService(paperId, statusData);
|
||
} catch (error) {
|
||
console.error("更新试卷状态失败:", error);
|
||
return false;
|
||
}
|
||
}
|
||
);
|
||
|
||
// 加载试卷试题序列
|
||
// 移除或注释掉loadPaperSerial处理程序中的调试日志
|
||
ipcMain.handle("examing-load-paper-serial", async (event, { paperId }) => {
|
||
try {
|
||
// 注释掉这行调试日志
|
||
// console.log("0903调试:", paperId);
|
||
return await loadPaperSerialService(paperId);
|
||
} catch (error) {
|
||
console.error("加载试卷试题序列失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `加载试卷试题序列失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 根据表名和ID获取完整的试题数据
|
||
ipcMain.handle(
|
||
"examing-get-question-by-related-id",
|
||
async (event, { tableName, relatedId }) => {
|
||
try {
|
||
return await getQuestionByRelatedIdService(tableName, relatedId);
|
||
} catch (error) {
|
||
console.error("获取试题数据失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `获取试题数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 更新考生答案
|
||
ipcMain.handle(
|
||
"examing-update-answer",
|
||
async (event, { tableName, id, answers }) => {
|
||
try {
|
||
return await updateExamineeAnswerService(tableName, id, answers);
|
||
} catch (error) {
|
||
console.error("更新考生答案失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `更新答案失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 开始考试
|
||
// 在initExamingIpc函数中添加examing-start-paper处理器
|
||
ipcMain.handle("examing-start-paper", async (event, args) => {
|
||
try {
|
||
const { paperId } = args;
|
||
if (!paperId) {
|
||
return { success: false, message: "缺少试卷ID" };
|
||
}
|
||
|
||
const result = await startPaper(paperId);
|
||
return result;
|
||
} catch (error) {
|
||
console.error("开始考试失败:", error);
|
||
return { success: false, message: error.message };
|
||
}
|
||
});
|
||
|
||
// 提交考试
|
||
// 提交考试
|
||
ipcMain.handle(
|
||
"examing-submit-paper",
|
||
async (event, { paperId, duration_seconds }) => {
|
||
try {
|
||
return await submitPaperService(paperId, duration_seconds);
|
||
} catch (error) {
|
||
console.error("提交考试失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `提交考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 结束考试
|
||
ipcMain.handle("examing-end-paper", async (event, { paperId }) => {
|
||
try {
|
||
return await endPaperService(paperId);
|
||
} catch (error) {
|
||
console.error("结束考试失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `结束考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 处理试卷
|
||
ipcMain.handle(
|
||
"examing-process-paper",
|
||
async (event, { paperId, duration_seconds }) => {
|
||
try {
|
||
return await processPaperService(paperId, duration_seconds);
|
||
} catch (error) {
|
||
console.error("处理试卷失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `处理试卷失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 检查试卷答案并计算得分
|
||
ipcMain.handle("examing-check-paper-answers", async (event, { paperId }) => {
|
||
try {
|
||
return await checkPaperAnswersService(paperId);
|
||
} catch (error) {
|
||
console.error("检查试卷答案失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `检查试卷答案失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 添加获取考试结果的IPC处理器
|
||
ipcMain.handle("examing-get-exam-result", async (event, { paperId }) => {
|
||
try {
|
||
return await getExamResultService(paperId);
|
||
} catch (error) {
|
||
console.error("获取考试结果失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `获取考试结果失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 添加通过考生ID获取试卷数据的IPC处理器
|
||
ipcMain.handle(
|
||
"examing-get-examinee-paper",
|
||
async (event, { examineeId }) => {
|
||
try {
|
||
return await getExamineePaperService(examineeId);
|
||
} catch (error) {
|
||
console.error("获取考生试卷数据失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `获取考生试卷数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
}
|
||
);
|
||
|
||
// 添加继续考试的IPC处理器
|
||
ipcMain.handle("examing-continue-paper", async (event, { paperId }) => {
|
||
try {
|
||
return await continueExamService(paperId);
|
||
} catch (error) {
|
||
console.error("继续考试失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `继续考试失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 在initExamingIpc函数中添加getPaper的IPC处理器
|
||
ipcMain.handle("examing-get-paper", async (event, { paperId }) => {
|
||
try {
|
||
return await getPaperService(paperId);
|
||
} catch (error) {
|
||
console.error("获取试卷详细信息失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `获取试卷详细信息失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
|
||
// 找到initExamingIpc函数,在合适位置添加以下代码
|
||
ipcMain.handle("examing-clear-paper", async (event, { paperId }) => {
|
||
try {
|
||
return await clearExamineePaperService(paperId);
|
||
} catch (error) {
|
||
console.error("清理试卷数据失败:", error);
|
||
return {
|
||
success: false,
|
||
message: `清理试卷数据失败: ${error.message}`,
|
||
};
|
||
}
|
||
});
|
||
}
|
||
|
||
// 导出使用CommonJS格式
|
||
module.exports = {
|
||
generateExamineePaperService,
|
||
getExamineePaperStatusService,
|
||
updatePaperStatusService,
|
||
loadPaperSerialService,
|
||
getQuestionByRelatedIdService,
|
||
updateExamineeAnswerService,
|
||
startPaperService,
|
||
submitPaperService,
|
||
endPaperService,
|
||
processPaperService,
|
||
checkPaperAnswersService,
|
||
getExamResultService,
|
||
getExamineePaperService,
|
||
continueExamService,
|
||
getPaperService,
|
||
clearExamineePaperService,
|
||
initExamingIpc,
|
||
};
|