整理main.js把ipc注册方法分别写到各个service中,StudentHomeView改名为ExamineeHomeView
This commit is contained in:
parent
637906b241
commit
31b8f81aa3
@ -8,7 +8,7 @@ import * as argon2 from "argon2";
|
||||
const dbConnections = new Map();
|
||||
|
||||
// 获取数据库连接
|
||||
async function getDbConnection(dbPath) {
|
||||
export async function getDbConnection(dbPath) {
|
||||
if (dbConnections.has(dbPath)) {
|
||||
console.log(`使用现有数据库连接: ${dbPath}`);
|
||||
return dbConnections.get(dbPath);
|
||||
@ -33,7 +33,7 @@ function closeAllConnections() {
|
||||
}
|
||||
|
||||
// 检查数据库是否已初始化
|
||||
async function checkDatabaseInitialized() {
|
||||
export async function checkDatabaseInitialized() {
|
||||
try {
|
||||
console.log('开始检查数据库初始化状态...');
|
||||
const systemDb = await getDbConnection(getSystemDbPath());
|
||||
@ -198,7 +198,7 @@ async function initializeUserDatabase() {
|
||||
}
|
||||
|
||||
// 初始化数据库
|
||||
async function initializeDatabase() {
|
||||
export async function initializeDatabase() {
|
||||
try {
|
||||
console.log('开始初始化数据库...');
|
||||
|
||||
@ -252,10 +252,3 @@ async function initializeDatabase() {
|
||||
|
||||
// 应用退出时关闭所有连接
|
||||
process.on('exit', closeAllConnections);
|
||||
|
||||
// 替换module.exports为export
|
||||
export {
|
||||
initializeDatabase,
|
||||
checkDatabaseInitialized,
|
||||
getDbConnection,
|
||||
};
|
528
electron/main.js
528
electron/main.js
@ -2,66 +2,29 @@
|
||||
import { app, BrowserWindow, ipcMain } from "electron";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { checkDatabaseInitialized, initializeDatabase } from "./db/index.js";
|
||||
import {
|
||||
checkDatabaseInitialized,
|
||||
initializeDatabase,
|
||||
} from "./db/index.js";
|
||||
// 导入配置项服务
|
||||
import {
|
||||
fetchAllConfigs,
|
||||
fetchConfigById,
|
||||
saveConfig,
|
||||
removeConfig,
|
||||
getSystemConfig,
|
||||
updateSystemConfig,
|
||||
increaseQuestionBankVersion,
|
||||
initAuthIpc,
|
||||
initConfigIpc,
|
||||
} from "./service/configService.js";
|
||||
// 导入字典服务 - 使用实际导出的函数名称
|
||||
import {
|
||||
fetchDictTypes,
|
||||
fetchDictItemsByTypeCode,
|
||||
createDictType,
|
||||
modifyDictType,
|
||||
removeDictType,
|
||||
createDictItem,
|
||||
modifyDictItem,
|
||||
removeDictItem,
|
||||
fetchDictItemsWithTypes,
|
||||
checkDictParentCode, // 添加这一行
|
||||
checkDictChildReferences, // 添加这一行
|
||||
initDictIpc,
|
||||
} from "./service/dictService.js";
|
||||
// 导入题干服务
|
||||
import {
|
||||
createQuestion,
|
||||
fetchAllQuestions,
|
||||
fetchQuestionById,
|
||||
modifyQuestion,
|
||||
removeQuestion,
|
||||
fetchAllQuestionsWithRelations,
|
||||
modifyQuestionDescription,
|
||||
createChoiceQuestion,
|
||||
modifyChoiceQuestion,
|
||||
createFillBlankQuestion,
|
||||
modifyFillBlankQuestion,
|
||||
removeFillBlankQuestion,
|
||||
fetchFillBlankQuestionsByQuestionId
|
||||
initQuestionIpc,
|
||||
} from './service/questionService.js';
|
||||
import {
|
||||
createNewExam,
|
||||
fetchAllExams,
|
||||
fetchExamById,
|
||||
modifyExam,
|
||||
removeExam,
|
||||
fetchLastExam, // 添加这一行
|
||||
initExamIpc,
|
||||
} from "./service/examService.js";
|
||||
|
||||
// 添加考生服务导入
|
||||
// 在文件开头的导入语句中添加新函数
|
||||
import {
|
||||
fetchAllExaminees,
|
||||
fetchExamineeById,
|
||||
createExamineeService,
|
||||
updateExamineeService,
|
||||
deleteExamineeService,
|
||||
fetchExamineeByIdCardAndAdmissionTicket,
|
||||
initExamineeIpc
|
||||
} from "./service/examineeService.js";
|
||||
|
||||
// 定义 __dirname 和 __filename
|
||||
@ -160,23 +123,7 @@ async function setupApp() {
|
||||
}
|
||||
|
||||
function setupIpcMain() {
|
||||
// 考生登录IPC
|
||||
ipcMain.handle("user-login", async (event, {idCard, admissionTicket}) => {
|
||||
// return {data: 'hello world'};
|
||||
try {
|
||||
const examinee = await fetchExamineeByIdCardAndAdmissionTicket(idCard, admissionTicket);
|
||||
console.log(examinee);
|
||||
// const examinee = 'hello world';
|
||||
if (examinee) {
|
||||
return { success: true, data: examinee };
|
||||
} else {
|
||||
return { success: false, error: "未找到匹配的考生信息" };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to login examinee:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
// 数据库相关
|
||||
ipcMain.handle("check-database-initialized", async () => {
|
||||
try {
|
||||
@ -196,454 +143,20 @@ function setupIpcMain() {
|
||||
}
|
||||
});
|
||||
|
||||
// 系统相关
|
||||
ipcMain.handle("system-get-config", async () => {
|
||||
try {
|
||||
return await getSystemConfig();
|
||||
} catch (error) {
|
||||
console.error("Failed to get system config:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// 初始化config相关IPC
|
||||
initConfigIpc(ipcMain);
|
||||
|
||||
ipcMain.handle("system-update-config", async (event, config) => {
|
||||
try {
|
||||
return await updateSystemConfig(config);
|
||||
} catch (error) {
|
||||
console.error("Failed to update system config:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// 初始化dict相关IPC
|
||||
initDictIpc(ipcMain);
|
||||
|
||||
ipcMain.handle("system-increase-question-band-version", async () => {
|
||||
try {
|
||||
return await increaseQuestionBankVersion();
|
||||
} catch (error) {
|
||||
console.error("Failed to increase question band version:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// 初始化exam相关IPC
|
||||
initExamIpc(ipcMain);
|
||||
|
||||
// 初始化认证相关IPC
|
||||
initAuthIpc(ipcMain);
|
||||
|
||||
// 配置项管理相关IPC
|
||||
ipcMain.handle("config-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllConfigs();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all configs:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchConfigById(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch config by id ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-save", async (event, { key, value }) => {
|
||||
try {
|
||||
await saveConfig(key, value);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Failed to save config ${key}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-delete", async (event, id) => {
|
||||
try {
|
||||
await removeConfig(id);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete config ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 字典管理相关IPC - 使用正确的函数名称
|
||||
ipcMain.handle("dict-fetch-types", async () => {
|
||||
try {
|
||||
return await fetchDictTypes();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch dict types:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle(
|
||||
"dict-fetch-items-by-type",
|
||||
async (event, typeCode, isActive = undefined) => {
|
||||
try {
|
||||
return await fetchDictItemsByTypeCode(typeCode, isActive);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch dict items by type ${typeCode}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle("dict-create-type", async (event, dictType) => {
|
||||
try {
|
||||
return await createDictType(dictType);
|
||||
} catch (error) {
|
||||
console.error("Failed to create dict type:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 updateDictType 改为 modifyDictType
|
||||
ipcMain.handle("dict-update-type", async (event, dictType) => {
|
||||
try {
|
||||
return await modifyDictType(dictType.id, dictType);
|
||||
} catch (error) {
|
||||
console.error("Failed to update dict type:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 deleteDictType 改为 removeDictType
|
||||
ipcMain.handle("dict-delete-type", async (event, typeCode) => {
|
||||
try {
|
||||
return await removeDictType(typeCode);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete dict type ${typeCode}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("dict-create-item", async (event, dictItem) => {
|
||||
try {
|
||||
return await createDictItem(dictItem);
|
||||
} catch (error) {
|
||||
console.error("Failed to create dict item:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 updateDictItem 改为 modifyDictItem
|
||||
ipcMain.handle("dict-update-item", async (event, dictItem) => {
|
||||
try {
|
||||
return await modifyDictItem(dictItem.id, dictItem);
|
||||
} catch (error) {
|
||||
console.error("Failed to update dict item:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 deleteDictItem 改为 removeDictItem
|
||||
ipcMain.handle("dict-delete-item", async (event, id) => {
|
||||
try {
|
||||
return await removeDictItem(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete dict item ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 fetchAllDictItemsWithTypes 改为 fetchDictItemsWithTypes
|
||||
ipcMain.handle("dict-fetch-all-items-with-types", async () => {
|
||||
try {
|
||||
return await fetchDictItemsWithTypes();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all dict items with types:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
// 添加在setupIpcMain函数中
|
||||
// 检查parent_code是否存在
|
||||
ipcMain.handle("dict-check-parent-code", async (event, parentCode) => {
|
||||
try {
|
||||
return await checkDictParentCode(parentCode); // 修改这一行
|
||||
} catch (error) {
|
||||
console.error("检查parent_code失败:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 检查是否有子引用
|
||||
ipcMain.handle("dict-check-child-references", async (event, itemCode) => {
|
||||
try {
|
||||
return await checkDictChildReferences(itemCode); // 修改这一行
|
||||
} catch (error) {
|
||||
console.error("检查子引用失败:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 题干管理相关IPC
|
||||
ipcMain.handle("question-create", async (event, questionData) => {
|
||||
try {
|
||||
return await createQuestion(questionData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllQuestions();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch questions:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchQuestionById(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch question by id ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-update", async (event, id, questionData) => {
|
||||
try {
|
||||
return await modifyQuestion(id, questionData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-delete", async (event, id) => {
|
||||
try {
|
||||
return await removeQuestion(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete question ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 在已有的 question 相关 IPC 处理程序区域添加
|
||||
ipcMain.handle("question-fetch-all-with-relations", async (event) => {
|
||||
try {
|
||||
return await fetchAllQuestionsWithRelations();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all questions with relations:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加更新题干描述的 IPC 处理程序
|
||||
ipcMain.handle(
|
||||
"question-update-description",
|
||||
async (event, id, questionDescription) => {
|
||||
try {
|
||||
return await modifyQuestionDescription(id, questionDescription);
|
||||
} catch (error) {
|
||||
console.error("Failed to update question description:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 添加选择题问题的IPC处理程序
|
||||
ipcMain.handle('question-update-choice', async (event, id, choiceData) => {
|
||||
try {
|
||||
return await modifyChoiceQuestion(id, choiceData);
|
||||
} catch (error) {
|
||||
console.error('Failed to update choice question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加选择题问题的IPC处理程序
|
||||
ipcMain.handle("question-create-choice", async (event, choiceData) => {
|
||||
try {
|
||||
return await createChoiceQuestion(choiceData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create choice question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-create-fill-blank', async (event, fillBlankData) => {
|
||||
try {
|
||||
return await createFillBlankQuestion(fillBlankData);
|
||||
} catch (error) {
|
||||
console.error('Failed to create fill blank question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 更新填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-update-fill-blank', async (event, id, fillBlankData) => {
|
||||
try {
|
||||
return await modifyFillBlankQuestion(id, fillBlankData);
|
||||
} catch (error) {
|
||||
console.error('Failed to update fill blank question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 删除填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-delete-fill-blank', async (event, id) => {
|
||||
try {
|
||||
return await removeFillBlankQuestion(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete fill blank question ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 根据题干ID查询填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-fetch-fill-blank-by-question-id', async (event, questionId) => {
|
||||
try {
|
||||
return await fetchFillBlankQuestionsByQuestionId(questionId);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch fill blank questions by question id ${questionId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 考试管理相关IPC
|
||||
ipcMain.handle("exam-create", async (event, examData) => {
|
||||
try {
|
||||
// 确保exam_notice是序列化的JSON字符串
|
||||
if (examData.exam_notice && typeof examData.exam_notice === "object") {
|
||||
examData.exam_notice = JSON.stringify(examData.exam_notice);
|
||||
}
|
||||
return await createNewExam(examData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-update", async (event, { id, examData }) => {
|
||||
try {
|
||||
// 确保exam_notice是序列化的JSON字符串
|
||||
if (examData.exam_notice && typeof examData.exam_notice === "object") {
|
||||
examData.exam_notice = JSON.stringify(examData.exam_notice);
|
||||
}
|
||||
return await modifyExam(id, examData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-last", async () => {
|
||||
try {
|
||||
const exam = await fetchLastExam();
|
||||
// 将exam_notice字符串解析为数组
|
||||
if (exam && exam.exam_notice) {
|
||||
try {
|
||||
exam.exam_notice = JSON.parse(exam.exam_notice);
|
||||
} catch (e) {
|
||||
console.error("解析考试须知失败:", e);
|
||||
exam.exam_notice = [];
|
||||
}
|
||||
}
|
||||
return exam;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch last exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-all", async () => {
|
||||
try {
|
||||
return { success: true, data: await fetchAllExams() };
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all exams:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-last", async () => {
|
||||
try {
|
||||
return { success: true, data: await fetchLastExam() };
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch last exam:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return { success: true, data: await fetchExamById(id) };
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch exam by id ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-update", async (event, { id, examData }) => {
|
||||
try {
|
||||
const result = await modifyExam(id, examData);
|
||||
return { success: result, data: { id, ...examData } };
|
||||
} catch (error) {
|
||||
console.error(`Failed to update exam ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-delete", async (event, id) => {
|
||||
try {
|
||||
const result = await removeExam(id);
|
||||
return { success: result, data: { id } };
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete exam ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
// 考生管理相关IPC
|
||||
ipcMain.handle("examinee-create", async (event, examineeData) => {
|
||||
try {
|
||||
return await createExamineeService(examineeData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create examinee:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("examinee-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllExaminees();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all examinees:", error);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("examinee-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchExamineeById(id);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch examinee by id:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("examinee-update", async (event, id, examineeData) => {
|
||||
try {
|
||||
return await updateExamineeService(id, examineeData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update examinee:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("examinee-delete", async (event, id) => {
|
||||
try {
|
||||
return await deleteExamineeService(id);
|
||||
} catch (error) {
|
||||
console.error("Failed to delete examinee:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// 初始化question相关IPC
|
||||
initQuestionIpc(ipcMain);
|
||||
|
||||
// 初始化考生相关IPC
|
||||
initExamineeIpc(ipcMain);
|
||||
}
|
||||
|
||||
// 确保在 app.whenReady() 中调用 setupIpcMain()
|
||||
@ -656,5 +169,4 @@ app.whenReady().then(() => {
|
||||
// 在应用退出前关闭所有数据库连接
|
||||
app.on("will-quit", () => {
|
||||
console.log("应用即将退出...");
|
||||
// closeAllConnections();
|
||||
});
|
||||
|
@ -55,11 +55,12 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
fetchExamById: (id) => ipcRenderer.invoke('exam-fetch-by-id', id),
|
||||
updateExam: (id, examData) => ipcRenderer.invoke('exam-update', { id, examData }),
|
||||
deleteExam: (id) => ipcRenderer.invoke('exam-delete', id),
|
||||
fetchLastExam: () => ipcRenderer.invoke('exam-fetch-last'), // 添加这一行
|
||||
fetchLastExam: () => ipcRenderer.invoke('exam-fetch-last'),
|
||||
// 考生管理相关API
|
||||
fetchAllExaminees: () => ipcRenderer.invoke('examinee-fetch-all'),
|
||||
fetchExamineeById: (id) => ipcRenderer.invoke('examinee-fetch-by-id', id),
|
||||
createExaminee: (examineeData) => ipcRenderer.invoke('examinee-create', examineeData),
|
||||
updateExaminee: (id, examineeData) => ipcRenderer.invoke('examinee-update', id, examineeData),
|
||||
updateExaminee: (id, examineeData) => ipcRenderer.invoke('examinee-update', { id, examineeData }),
|
||||
deleteExaminee: (id) => ipcRenderer.invoke('examinee-delete', id),
|
||||
userLogin: (idCard, admissionTicket) => ipcRenderer.invoke('user-login', { idCard, admissionTicket })
|
||||
});
|
@ -1,6 +1,12 @@
|
||||
// 导入数据库操作方法
|
||||
import { getConfig, setConfig, getAllConfigs, getConfigById, deleteConfig } from '../db/config.js';
|
||||
import argon2 from 'argon2';
|
||||
import {
|
||||
getConfig,
|
||||
setConfig,
|
||||
getAllConfigs,
|
||||
getConfigById,
|
||||
deleteConfig,
|
||||
} from "../db/config.js";
|
||||
import argon2 from "argon2";
|
||||
|
||||
// 原有接口保持不变
|
||||
/**
|
||||
@ -12,7 +18,7 @@ export async function fetchConfig(key) {
|
||||
try {
|
||||
return await getConfig(key);
|
||||
} catch (error) {
|
||||
console.error('服务层: 获取配置项失败', error);
|
||||
console.error("服务层: 获取配置项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -25,7 +31,7 @@ export async function fetchAllConfigs() {
|
||||
try {
|
||||
return await getAllConfigs();
|
||||
} catch (error) {
|
||||
console.error('服务层: 获取所有配置项失败', error);
|
||||
console.error("服务层: 获取所有配置项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -39,7 +45,7 @@ export async function fetchConfigById(id) {
|
||||
try {
|
||||
return await getConfigById(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 通过ID获取配置项失败', error);
|
||||
console.error("服务层: 通过ID获取配置项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -54,7 +60,7 @@ export async function saveConfig(key, value) {
|
||||
try {
|
||||
await setConfig(key, value);
|
||||
} catch (error) {
|
||||
console.error('服务层: 保存配置项失败', error);
|
||||
console.error("服务层: 保存配置项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -68,12 +74,11 @@ export async function removeConfig(id) {
|
||||
try {
|
||||
await deleteConfig(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 删除配置项失败', error);
|
||||
console.error("服务层: 删除配置项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 从 system.js 整合的接口
|
||||
/**
|
||||
* 获取系统配置并转为Map
|
||||
* @returns {Promise<{[key: string]: string}>}
|
||||
@ -82,12 +87,12 @@ export async function getSystemConfig() {
|
||||
try {
|
||||
const configs = await getAllConfigs();
|
||||
const configMap = {};
|
||||
configs.forEach(config => {
|
||||
configs.forEach((config) => {
|
||||
configMap[config.key] = config.value;
|
||||
});
|
||||
return configMap;
|
||||
} catch (error) {
|
||||
console.error('获取系统配置失败:', error);
|
||||
console.error("获取系统配置失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -104,7 +109,7 @@ export async function updateSystemConfig(config) {
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('更新系统配置失败:', error);
|
||||
console.error("更新系统配置失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -115,17 +120,16 @@ export async function updateSystemConfig(config) {
|
||||
*/
|
||||
export async function increaseQuestionBankVersion() {
|
||||
try {
|
||||
const currentVersion = await getConfig('question_bank_version');
|
||||
const currentVersion = await getConfig("question_bank_version");
|
||||
const newVersion = currentVersion ? parseInt(currentVersion.value) + 1 : 1;
|
||||
await setConfig('question_bank_version', newVersion.toString());
|
||||
await setConfig("question_bank_version", newVersion.toString());
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('增加题库版本号失败:', error);
|
||||
console.error("增加题库版本号失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 从 auth.service.js 整合的接口
|
||||
/**
|
||||
* 管理员登录验证
|
||||
* @param {string} password - 用户输入的密码
|
||||
@ -133,30 +137,102 @@ export async function increaseQuestionBankVersion() {
|
||||
*/
|
||||
export async function verifyAdminPassword(password) {
|
||||
try {
|
||||
const config = await getConfig('admin_password');
|
||||
const config = await getConfig("admin_password");
|
||||
if (!config || !config.value) {
|
||||
return { success: false, message: '管理员密码未设置' };
|
||||
return { success: false, message: "管理员密码未设置" };
|
||||
}
|
||||
|
||||
const isMatch = await argon2.verify(config.value, password);
|
||||
if (isMatch) {
|
||||
return { success: true, message: '登录成功' };
|
||||
return { success: true, message: "登录成功" };
|
||||
} else {
|
||||
return { success: false, message: '密码错误' };
|
||||
return { success: false, message: "密码错误" };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('验证管理员密码失败:', error);
|
||||
return { success: false, message: '验证过程发生错误' };
|
||||
console.error("验证管理员密码失败:", error);
|
||||
return { success: false, message: "验证过程发生错误" };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化认证相关的IPC处理程序
|
||||
* 初始化配置相关的IPC处理程序
|
||||
* @param {import('electron').IpcMain} ipcMain - IPC主进程实例
|
||||
*/
|
||||
export function initAuthIpc(ipcMain) {
|
||||
export function initConfigIpc(ipcMain) {
|
||||
// 管理员登录验证
|
||||
ipcMain.handle('admin-login', async (event, credentials) => {
|
||||
return await verifyAdminPassword(credentials.password);
|
||||
ipcMain.handle("admin-login", async (event, credentials) => {
|
||||
try {
|
||||
return await verifyAdminPassword(credentials.password);
|
||||
} catch (error) {
|
||||
console.error("Failed to verify admin password:", error);
|
||||
return { success: false, message: "验证过程发生错误" };
|
||||
}
|
||||
});
|
||||
|
||||
// 系统相关
|
||||
ipcMain.handle("system-get-config", async () => {
|
||||
try {
|
||||
return await getSystemConfig();
|
||||
} catch (error) {
|
||||
console.error("Failed to get system config:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("system-update-config", async (event, config) => {
|
||||
try {
|
||||
return await updateSystemConfig(config);
|
||||
} catch (error) {
|
||||
console.error("Failed to update system config:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("system-increase-question-band-version", async () => {
|
||||
try {
|
||||
return await increaseQuestionBankVersion();
|
||||
} catch (error) {
|
||||
console.error("Failed to increase question band version:", error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 配置项管理相关IPC
|
||||
ipcMain.handle("config-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllConfigs();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all configs:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchConfigById(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch config by id ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-save", async (event, { key, value }) => {
|
||||
try {
|
||||
await saveConfig(key, value);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Failed to save config ${key}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("config-delete", async (event, id) => {
|
||||
try {
|
||||
await removeConfig(id);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete config ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
@ -11,9 +11,9 @@ import {
|
||||
updateDictItem,
|
||||
deleteDictType,
|
||||
deleteDictItem,
|
||||
checkParentCodeExists, // 添加这一行
|
||||
hasChildReferences // 添加这一行
|
||||
} from '../db/dict.js';
|
||||
checkParentCodeExists, // 添加这一行
|
||||
hasChildReferences, // 添加这一行
|
||||
} from "../db/dict.js";
|
||||
|
||||
/**
|
||||
* 服务层:查询字典项及其类型
|
||||
@ -23,7 +23,7 @@ export async function fetchDictItemsWithTypes() {
|
||||
try {
|
||||
return await getDictItemsWithTypes();
|
||||
} catch (error) {
|
||||
console.error('服务层: 查询字典项及其类型失败', error);
|
||||
console.error("服务层: 查询字典项及其类型失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,7 @@ export async function fetchDictTypes() {
|
||||
try {
|
||||
return await getDictTypes();
|
||||
} catch (error) {
|
||||
console.error('服务层: 查询字典类型列表失败', error);
|
||||
console.error("服务层: 查询字典类型列表失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -50,7 +50,7 @@ export async function createDictType(typeData) {
|
||||
try {
|
||||
return await addDictType(typeData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 添加字典类型失败', error);
|
||||
console.error("服务层: 添加字典类型失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -64,7 +64,7 @@ export async function createDictItem(itemData) {
|
||||
try {
|
||||
return await addDictItem(itemData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 添加字典项失败', error);
|
||||
console.error("服务层: 添加字典项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ export async function fetchDictTypeById(id) {
|
||||
try {
|
||||
return await getDictTypeById(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 根据ID查询字典类型失败', error);
|
||||
console.error("服务层: 根据ID查询字典类型失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -92,7 +92,7 @@ export async function fetchDictItemById(id) {
|
||||
try {
|
||||
return await getDictItemById(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 根据ID查询字典项失败', error);
|
||||
console.error("服务层: 根据ID查询字典项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@ export async function fetchDictItemsByTypeCode(typeCode, isActive = undefined) {
|
||||
try {
|
||||
return await getDictItemsByTypeCode(typeCode, isActive);
|
||||
} catch (error) {
|
||||
console.error('服务层: 根据类型编码查询字典项失败', error);
|
||||
console.error("服务层: 根据类型编码查询字典项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -122,7 +122,7 @@ export async function modifyDictType(id, typeData) {
|
||||
try {
|
||||
return await updateDictType(id, typeData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 更新字典类型失败', error);
|
||||
console.error("服务层: 更新字典类型失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -137,7 +137,7 @@ export async function modifyDictItem(id, itemData) {
|
||||
try {
|
||||
return await updateDictItem(id, itemData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 更新字典项失败', error);
|
||||
console.error("服务层: 更新字典项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -151,7 +151,7 @@ export async function removeDictType(id) {
|
||||
try {
|
||||
return await deleteDictType(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 删除字典类型失败', error);
|
||||
console.error("服务层: 删除字典类型失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -165,7 +165,7 @@ export async function removeDictItem(id) {
|
||||
try {
|
||||
return await deleteDictItem(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 删除字典项失败', error);
|
||||
console.error("服务层: 删除字典项失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -180,7 +180,7 @@ export async function checkDictParentCode(parentCode) {
|
||||
try {
|
||||
return await checkParentCodeExists(parentCode);
|
||||
} catch (error) {
|
||||
console.error('服务层: 检查父级编码失败', error);
|
||||
console.error("服务层: 检查父级编码失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -194,7 +194,119 @@ export async function checkDictChildReferences(itemCode) {
|
||||
try {
|
||||
return await hasChildReferences(itemCode);
|
||||
} catch (error) {
|
||||
console.error('服务层: 检查子引用失败', error);
|
||||
console.error("服务层: 检查子引用失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function initDictIpc(ipcMain) {
|
||||
// 字典管理相关IPC - 使用正确的函数名称
|
||||
ipcMain.handle("dict-fetch-types", async () => {
|
||||
try {
|
||||
return await fetchDictTypes();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch dict types:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle(
|
||||
"dict-fetch-items-by-type",
|
||||
async (event, typeCode, isActive = undefined) => {
|
||||
try {
|
||||
return await fetchDictItemsByTypeCode(typeCode, isActive);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch dict items by type ${typeCode}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ipcMain.handle("dict-create-type", async (event, dictType) => {
|
||||
try {
|
||||
return await createDictType(dictType);
|
||||
} catch (error) {
|
||||
console.error("Failed to create dict type:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 updateDictType 改为 modifyDictType
|
||||
ipcMain.handle("dict-update-type", async (event, dictType) => {
|
||||
try {
|
||||
return await modifyDictType(dictType.id, dictType);
|
||||
} catch (error) {
|
||||
console.error("Failed to update dict type:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 deleteDictType 改为 removeDictType
|
||||
ipcMain.handle("dict-delete-type", async (event, typeCode) => {
|
||||
try {
|
||||
return await removeDictType(typeCode);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete dict type ${typeCode}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("dict-create-item", async (event, dictItem) => {
|
||||
try {
|
||||
return await createDictItem(dictItem);
|
||||
} catch (error) {
|
||||
console.error("Failed to create dict item:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 updateDictItem 改为 modifyDictItem
|
||||
ipcMain.handle("dict-update-item", async (event, dictItem) => {
|
||||
try {
|
||||
return await modifyDictItem(dictItem.id, dictItem);
|
||||
} catch (error) {
|
||||
console.error("Failed to update dict item:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 deleteDictItem 改为 removeDictItem
|
||||
ipcMain.handle("dict-delete-item", async (event, id) => {
|
||||
try {
|
||||
return await removeDictItem(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete dict item ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 将 fetchAllDictItemsWithTypes 改为 fetchDictItemsWithTypes
|
||||
ipcMain.handle("dict-fetch-all-items-with-types", async () => {
|
||||
try {
|
||||
return await fetchDictItemsWithTypes();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all dict items with types:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
// 添加在setupIpcMain函数中
|
||||
// 检查parent_code是否存在
|
||||
ipcMain.handle("dict-check-parent-code", async (event, parentCode) => {
|
||||
try {
|
||||
return await checkDictParentCode(parentCode); // 修改这一行
|
||||
} catch (error) {
|
||||
console.error("检查parent_code失败:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 检查是否有子引用
|
||||
ipcMain.handle("dict-check-child-references", async (event, itemCode) => {
|
||||
try {
|
||||
return await checkDictChildReferences(itemCode); // 修改这一行
|
||||
} catch (error) {
|
||||
console.error("检查子引用失败:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import {
|
||||
getExamById,
|
||||
updateExam,
|
||||
deleteExam,
|
||||
getLastExam // 添加这一行
|
||||
} from '../db/exam.js';
|
||||
getLastExam, // 添加这一行
|
||||
} from "../db/exam.js";
|
||||
|
||||
/**
|
||||
* 服务层:创建考试
|
||||
@ -16,22 +16,22 @@ export async function createNewExam(examData) {
|
||||
try {
|
||||
// 数据验证 - 修改为exam_minutes和exam_minutes_min必填
|
||||
if (!examData.exam_minutes || !examData.exam_minutes_min) {
|
||||
throw new Error('考试时长和最少考试时间为必填项');
|
||||
throw new Error("考试时长和最少考试时间为必填项");
|
||||
}
|
||||
|
||||
// 移除默认值设置,因为现在是必填项
|
||||
if (typeof examData.exam_minutes_min !== 'number') {
|
||||
throw new Error('最少考试时间必须是数字');
|
||||
if (typeof examData.exam_minutes_min !== "number") {
|
||||
throw new Error("最少考试时间必须是数字");
|
||||
}
|
||||
|
||||
// 确保最少考试时间不大于考试时长
|
||||
if (examData.exam_minutes_min > examData.exam_minutes) {
|
||||
throw new Error('最少考试时间不能大于考试时长');
|
||||
throw new Error("最少考试时间不能大于考试时长");
|
||||
}
|
||||
|
||||
return await createExam(examData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 创建考试失败', error);
|
||||
console.error("服务层: 创建考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ export async function fetchAllExams() {
|
||||
try {
|
||||
return await getAllExams();
|
||||
} catch (error) {
|
||||
console.error('服务层: 查询所有考试失败', error);
|
||||
console.error("服务层: 查询所有考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -57,17 +57,17 @@ export async function fetchAllExams() {
|
||||
export async function fetchExamById(id) {
|
||||
try {
|
||||
if (!id) {
|
||||
throw new Error('考试ID不能为空');
|
||||
throw new Error("考试ID不能为空");
|
||||
}
|
||||
|
||||
const exam = await getExamById(id);
|
||||
if (!exam) {
|
||||
throw new Error('未找到指定考试');
|
||||
throw new Error("未找到指定考试");
|
||||
}
|
||||
|
||||
return exam;
|
||||
} catch (error) {
|
||||
console.error('服务层: 根据ID查询考试失败', error);
|
||||
console.error("服务层: 根据ID查询考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -81,33 +81,33 @@ export async function fetchExamById(id) {
|
||||
export async function modifyExam(id, examData) {
|
||||
try {
|
||||
if (!id) {
|
||||
throw new Error('考试ID不能为空');
|
||||
throw new Error("考试ID不能为空");
|
||||
}
|
||||
|
||||
// 验证考试是否存在
|
||||
const existingExam = await getExamById(id);
|
||||
if (!existingExam) {
|
||||
throw new Error('未找到指定考试');
|
||||
throw new Error("未找到指定考试");
|
||||
}
|
||||
|
||||
// 数据验证 - 修改为exam_minutes和exam_minutes_min必填
|
||||
if (!examData.exam_minutes || !examData.exam_minutes_min) {
|
||||
throw new Error('考试时长和最少考试时间为必填项');
|
||||
throw new Error("考试时长和最少考试时间为必填项");
|
||||
}
|
||||
|
||||
// 移除默认值设置,因为现在是必填项
|
||||
if (typeof examData.exam_minutes_min !== 'number') {
|
||||
throw new Error('最少考试时间必须是数字');
|
||||
if (typeof examData.exam_minutes_min !== "number") {
|
||||
throw new Error("最少考试时间必须是数字");
|
||||
}
|
||||
|
||||
// 确保最少考试时间不大于考试时长
|
||||
if (examData.exam_minutes_min > examData.exam_minutes) {
|
||||
throw new Error('最少考试时间不能大于考试时长');
|
||||
throw new Error("最少考试时间不能大于考试时长");
|
||||
}
|
||||
|
||||
return await updateExam(id, examData);
|
||||
} catch (error) {
|
||||
console.error('服务层: 更新考试失败', error);
|
||||
console.error("服务层: 更新考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -120,18 +120,18 @@ export async function modifyExam(id, examData) {
|
||||
export async function removeExam(id) {
|
||||
try {
|
||||
if (!id) {
|
||||
throw new Error('考试ID不能为空');
|
||||
throw new Error("考试ID不能为空");
|
||||
}
|
||||
|
||||
// 验证考试是否存在
|
||||
const existingExam = await getExamById(id);
|
||||
if (!existingExam) {
|
||||
throw new Error('未找到指定考试');
|
||||
throw new Error("未找到指定考试");
|
||||
}
|
||||
|
||||
return await deleteExam(id);
|
||||
} catch (error) {
|
||||
console.error('服务层: 删除考试失败', error);
|
||||
console.error("服务层: 删除考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -144,7 +144,102 @@ export async function fetchLastExam() {
|
||||
try {
|
||||
return await getLastExam();
|
||||
} catch (error) {
|
||||
console.error('服务层: 查询ID最大的考试失败', error);
|
||||
console.error("服务层: 查询ID最大的考试失败", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function initExamIpc(ipcMain) {
|
||||
// 考试管理相关IPC
|
||||
ipcMain.handle("exam-create", async (event, examData) => {
|
||||
try {
|
||||
// 确保exam_notice是序列化的JSON字符串
|
||||
if (examData.exam_notice && typeof examData.exam_notice === "object") {
|
||||
examData.exam_notice = JSON.stringify(examData.exam_notice);
|
||||
}
|
||||
return await createNewExam(examData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-update", async (event, { id, examData }) => {
|
||||
try {
|
||||
// 确保exam_notice是序列化的JSON字符串
|
||||
if (examData.exam_notice && typeof examData.exam_notice === "object") {
|
||||
examData.exam_notice = JSON.stringify(examData.exam_notice);
|
||||
}
|
||||
return await modifyExam(id, examData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-last", async () => {
|
||||
try {
|
||||
const exam = await fetchLastExam();
|
||||
// 将exam_notice字符串解析为数组
|
||||
if (exam && exam.exam_notice) {
|
||||
try {
|
||||
exam.exam_notice = JSON.parse(exam.exam_notice);
|
||||
} catch (e) {
|
||||
console.error("解析考试须知失败:", e);
|
||||
exam.exam_notice = [];
|
||||
}
|
||||
}
|
||||
return exam;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch last exam:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-all", async () => {
|
||||
try {
|
||||
return { success: true, data: await fetchAllExams() };
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all exams:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-last", async () => {
|
||||
try {
|
||||
return { success: true, data: await fetchLastExam() };
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch last exam:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return { success: true, data: await fetchExamById(id) };
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch exam by id ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-update", async (event, { id, examData }) => {
|
||||
try {
|
||||
const result = await modifyExam(id, examData);
|
||||
return { success: result, data: { id, ...examData } };
|
||||
} catch (error) {
|
||||
console.error(`Failed to update exam ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("exam-delete", async (event, id) => {
|
||||
try {
|
||||
const result = await removeExam(id);
|
||||
return { success: result, data: { id } };
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete exam ${id}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
* 服务层:获取所有考生列表
|
||||
* @returns {Promise<Array>} 考生列表
|
||||
*/
|
||||
export async function fetchAllExaminees() {
|
||||
export async function fetchAllExamineesService() {
|
||||
try {
|
||||
return await getAllExaminees();
|
||||
} catch (error) {
|
||||
@ -27,7 +27,7 @@ export async function fetchAllExaminees() {
|
||||
* @param {number} id 考生ID
|
||||
* @returns {Promise<Object|null>} 考生数据
|
||||
*/
|
||||
export async function fetchExamineeById(id) {
|
||||
export async function fetchExamineeByIdService(id) {
|
||||
try {
|
||||
return await getExamineeById(id);
|
||||
} catch (error) {
|
||||
@ -62,6 +62,8 @@ export async function createExamineeService(examineeData) {
|
||||
* @returns {Promise<boolean>} 是否更新成功
|
||||
*/
|
||||
export async function updateExamineeService(id, examineeData) {
|
||||
console.log(id);
|
||||
console.log(examineeData);
|
||||
try {
|
||||
if (!id) {
|
||||
throw new Error('考生ID不能为空');
|
||||
@ -105,7 +107,7 @@ export async function deleteExamineeService(id) {
|
||||
* @param {string} admissionTicket 准考证号
|
||||
* @returns {Promise<Object|null>} 考生数据或null
|
||||
*/
|
||||
export async function fetchExamineeByIdCardAndAdmissionTicket(idCard, admissionTicket) {
|
||||
export async function fetchExamineeByIdCardAndAdmissionTicketService(idCard, admissionTicket) {
|
||||
try {
|
||||
if (!idCard || !admissionTicket) {
|
||||
throw new Error('身份证号和准考证号不能为空');
|
||||
@ -116,3 +118,54 @@ export async function fetchExamineeByIdCardAndAdmissionTicket(idCard, admissionT
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function initExamineeIpc(ipcMain) {
|
||||
ipcMain.handle("examinee-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllExamineesService();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all examinees:", error);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
ipcMain.handle("user-login", async (event, {idCard, admissionTicket}) => {
|
||||
try {
|
||||
return await fetchExamineeByIdCardAndAdmissionTicketService(idCard, admissionTicket);
|
||||
} catch (error) {
|
||||
console.error("Failed to login examinee:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ipcMain.handle("examinee-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchExamineeByIdService(id);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch examinee by id:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ipcMain.handle("examinee-create", async (event, examineeData) => {
|
||||
try {
|
||||
return await createExamineeService(examineeData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create examinee:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ipcMain.handle("examinee-update", async (event, {id, examineeData}) => {
|
||||
try {
|
||||
return await updateExamineeService(id, examineeData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update examinee:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ipcMain.handle("examinee-delete", async (event, id) => {
|
||||
try {
|
||||
return await deleteExamineeService(id);
|
||||
} catch (error) {
|
||||
console.error("Failed to delete examinee:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -229,3 +229,136 @@ export async function fetchFillBlankQuestionsByQuestionId(questionId) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化question相关IPC
|
||||
* @param {*} ipcMain
|
||||
*/
|
||||
export async function initQuestionIpc(ipcMain) {
|
||||
// 题干管理相关IPC
|
||||
ipcMain.handle("question-create", async (event, questionData) => {
|
||||
try {
|
||||
return await createQuestion(questionData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-fetch-all", async () => {
|
||||
try {
|
||||
return await fetchAllQuestions();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch questions:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-fetch-by-id", async (event, id) => {
|
||||
try {
|
||||
return await fetchQuestionById(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch question by id ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-update", async (event, id, questionData) => {
|
||||
try {
|
||||
return await modifyQuestion(id, questionData);
|
||||
} catch (error) {
|
||||
console.error("Failed to update question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("question-delete", async (event, id) => {
|
||||
try {
|
||||
return await removeQuestion(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete question ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 在已有的 question 相关 IPC 处理程序区域添加
|
||||
ipcMain.handle("question-fetch-all-with-relations", async (event) => {
|
||||
try {
|
||||
return await fetchAllQuestionsWithRelations();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch all questions with relations:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加更新题干描述的 IPC 处理程序
|
||||
ipcMain.handle("question-update-description", async (event, id, questionDescription) => {
|
||||
try {
|
||||
return await modifyQuestionDescription(id, questionDescription);
|
||||
} catch (error) {
|
||||
console.error("Failed to update question description:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 添加选择题问题的IPC处理程序
|
||||
ipcMain.handle('question-update-choice', async (event, id, choiceData) => {
|
||||
try {
|
||||
return await modifyChoiceQuestion(id, choiceData);
|
||||
} catch (error) {
|
||||
console.error('Failed to update choice question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加选择题问题的IPC处理程序
|
||||
ipcMain.handle("question-create-choice", async (event, choiceData) => {
|
||||
try {
|
||||
return await createChoiceQuestion(choiceData);
|
||||
} catch (error) {
|
||||
console.error("Failed to create choice question:", error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-create-fill-blank', async (event, fillBlankData) => {
|
||||
try {
|
||||
return await createFillBlankQuestion(fillBlankData);
|
||||
} catch (error) {
|
||||
console.error('Failed to create fill blank question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 更新填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-update-fill-blank', async (event, id, fillBlankData) => {
|
||||
try {
|
||||
return await modifyFillBlankQuestion(id, fillBlankData);
|
||||
} catch (error) {
|
||||
console.error('Failed to update fill blank question:', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 删除填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-delete-fill-blank', async (event, id) => {
|
||||
try {
|
||||
return await removeFillBlankQuestion(id);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete fill blank question ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 根据题干ID查询填空题问题的IPC处理程序
|
||||
ipcMain.handle('question-fetch-fill-blank-by-question-id', async (event, questionId) => {
|
||||
try {
|
||||
return await fetchFillBlankQuestionsByQuestionId(questionId);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch fill blank questions by question id ${questionId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import WelcomeView from '@/views/WelcomeView.vue'
|
||||
import StudentHomeView from '@/views/user/StudentHomeView.vue'
|
||||
import ExamineeHomeView from '@/views/user/ExamineeHomeView.vue'
|
||||
import AdminHomeView from '@/views/admin/AdminHomeView.vue'
|
||||
// 导入QuestionManagementView
|
||||
import QuestionManagementView from '@/views/admin/QuestionManagementView.vue'
|
||||
@ -22,9 +22,9 @@ const router = createRouter({
|
||||
component: WelcomeView,
|
||||
},
|
||||
{
|
||||
path: '/student/home',
|
||||
name: 'student-home',
|
||||
component: StudentHomeView,
|
||||
path: '/examinee/home',
|
||||
name: 'examinee-home',
|
||||
component: ExamineeHomeView,
|
||||
},
|
||||
// admin/AdminHomeView路由
|
||||
{
|
||||
|
@ -196,18 +196,19 @@ const handleExamineeLogin = async () => {
|
||||
try {
|
||||
// 调用登录API
|
||||
const result = await window.electronAPI.userLogin(idCard, admissionTicket);
|
||||
console.log(result);
|
||||
|
||||
if (result.success) {
|
||||
console.log('考生登录 - 成功', result.data);
|
||||
if (result && result.id) {
|
||||
console.log('考生登录 - 成功', result);
|
||||
// 保存用户信息到store - 修改这里
|
||||
userStore.setExaminee({
|
||||
...result.data
|
||||
...result
|
||||
});
|
||||
ElMessage.success('登录成功');
|
||||
// 跳转到考生首页
|
||||
router.push('/student/home');
|
||||
router.push('/examinee/home');
|
||||
} else {
|
||||
console.warn('考生登录 - 失败:', result.error);
|
||||
console.warn('考生登录 - 失败:', result);
|
||||
ElMessage.error(result.error || '登录失败,请检查身份证号和准考证号');
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -152,6 +152,7 @@ const handleSaveExaminee = async () => {
|
||||
const examineeData = {...formData.value};
|
||||
|
||||
if (isEdit.value) {
|
||||
console.log(examineeData);
|
||||
await window.electronAPI.updateExaminee(examineeData.id, examineeData)
|
||||
ElMessage.success('考生更新成功')
|
||||
} else {
|
||||
|
@ -53,7 +53,7 @@
|
||||
<h2 class="text-2xl font-bold text-primary">考试信息</h2>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<el-descriptions class="margin-top" :column="3" :size="size" border>
|
||||
<el-descriptions class="margin-top" :column="2" :size="size" border>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
@ -65,13 +65,24 @@
|
||||
</template>
|
||||
{{ formatExamDuration(lastExam?.exam_minutes) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
<el-icon :style="iconStyle">
|
||||
<Timer />
|
||||
</el-icon>
|
||||
最短考试时长
|
||||
</div>
|
||||
</template>
|
||||
{{ formatExamDuration(lastExam?.exam_minutes_min) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
<el-icon :style="iconStyle">
|
||||
<ScaleToOriginal />
|
||||
</el-icon>
|
||||
考试总分
|
||||
考题数量
|
||||
</div>
|
||||
</template>
|
||||
<span class="text-gray-500">待设置</span>
|
||||
@ -80,13 +91,14 @@
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
<el-icon :style="iconStyle">
|
||||
<Timer />
|
||||
<ScaleToOriginal />
|
||||
</el-icon>
|
||||
最短考试时长
|
||||
考试总分
|
||||
</div>
|
||||
</template>
|
||||
{{ formatExamDuration(lastExam?.exam_minutes_min) }}
|
||||
<span class="text-gray-500">待设置</span>
|
||||
</el-descriptions-item>
|
||||
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<el-divider />
|
Loading…
Reference in New Issue
Block a user