exam11/background/service/examingService.js
2025-09-13 07:24:13 +08:00

691 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 首先在文件顶部的require语句中添加getExamineePaper
const {
generateExamineePaper,
loadPaperSerial,
getQuestionByRelatedId,
updateExamineeAnswer,
startPaper,
submitPaper,
endPaper,
processPaper,
checkPaperAnswers,
getPaper,
getExamineePaper,
continueExam, // 添加continueExam到导入列表中
} = 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;
}
}
/**
* 服务层:更新试卷状态
* @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}`,
};
}
});
}
// 导出使用CommonJS格式
module.exports = {
generateExamineePaperService,
getExamineePaperStatusService,
updatePaperStatusService,
loadPaperSerialService,
getQuestionByRelatedIdService,
updateExamineeAnswerService,
startPaperService,
submitPaperService,
endPaperService,
processPaperService,
checkPaperAnswersService,
getExamResultService,
getExamineePaperService,
continueExamService,
getPaperService,
initExamingIpc,
};