From 31b8f81aa3d3a8a65b000dcd9fb432a1d8205c7d Mon Sep 17 00:00:00 2001 From: chenqiang Date: Sat, 9 Aug 2025 16:17:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86main.js=E6=8A=8Aipc=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E6=96=B9=E6=B3=95=E5=88=86=E5=88=AB=E5=86=99=E5=88=B0?= =?UTF-8?q?=E5=90=84=E4=B8=AAservice=E4=B8=AD=EF=BC=8CStudentHomeView?= =?UTF-8?q?=E6=94=B9=E5=90=8D=E4=B8=BAExamineeHomeView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/db/index.js | 13 +- electron/main.js | 528 +----------------- electron/preload.js | 5 +- electron/service/configService.js | 128 ++++- electron/service/dictService.js | 146 ++++- electron/service/examService.js | 141 ++++- electron/service/examineeService.js | 61 +- electron/service/questionService.js | 133 +++++ src/router/index.js | 8 +- src/views/WelcomeView.vue | 11 +- src/views/admin/ExamineeManagementView.vue | 1 + ...udentHomeView.vue => ExamineeHomeView.vue} | 22 +- 12 files changed, 593 insertions(+), 604 deletions(-) rename src/views/user/{StudentHomeView.vue => ExamineeHomeView.vue} (94%) diff --git a/electron/db/index.js b/electron/db/index.js index 3554f0b..01ad571 100644 --- a/electron/db/index.js +++ b/electron/db/index.js @@ -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, -}; \ No newline at end of file diff --git a/electron/main.js b/electron/main.js index 328607d..468d94b 100644 --- a/electron/main.js +++ b/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(); }); diff --git a/electron/preload.js b/electron/preload.js index 42a8212..dbfd2f0 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -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 }) }); \ No newline at end of file diff --git a/electron/service/configService.js b/electron/service/configService.js index e7807cd..c0a4012 100644 --- a/electron/service/configService.js +++ b/electron/service/configService.js @@ -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: "验证过程发生错误" }; + } }); -} \ No newline at end of file + + // 系统相关 + 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; + } + }); +} diff --git a/electron/service/dictService.js b/electron/service/dictService.js index f9a1af3..ed8af48 100644 --- a/electron/service/dictService.js +++ b/electron/service/dictService.js @@ -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; } -} \ No newline at end of file +} + +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; + } + }); +} diff --git a/electron/service/examService.js b/electron/service/examService.js index 49ed0a2..1d1eba8 100644 --- a/electron/service/examService.js +++ b/electron/service/examService.js @@ -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; } -} \ No newline at end of file +} + +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 }; + } + }); +} diff --git a/electron/service/examineeService.js b/electron/service/examineeService.js index d2d7eaa..a4f5ed4 100644 --- a/electron/service/examineeService.js +++ b/electron/service/examineeService.js @@ -12,7 +12,7 @@ import { * 服务层:获取所有考生列表 * @returns {Promise} 考生列表 */ -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} 考生数据 */ -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} 是否更新成功 */ 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} 考生数据或null */ -export async function fetchExamineeByIdCardAndAdmissionTicket(idCard, admissionTicket) { +export async function fetchExamineeByIdCardAndAdmissionTicketService(idCard, admissionTicket) { try { if (!idCard || !admissionTicket) { throw new Error('身份证号和准考证号不能为空'); @@ -115,4 +117,55 @@ export async function fetchExamineeByIdCardAndAdmissionTicket(idCard, admissionT console.error('服务层: 考生登录失败', error); throw error; } -} \ No newline at end of file +} + +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; + } + }); +} diff --git a/electron/service/questionService.js b/electron/service/questionService.js index 69fe6db..bcb22ad 100644 --- a/electron/service/questionService.js +++ b/electron/service/questionService.js @@ -228,4 +228,137 @@ export async function fetchFillBlankQuestionsByQuestionId(questionId) { console.error('服务层: 根据题干ID查询填空题失败', error); 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; + } + }); } \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index baa6007..ef7d18c 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -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路由 { diff --git a/src/views/WelcomeView.vue b/src/views/WelcomeView.vue index cc5f131..c173241 100644 --- a/src/views/WelcomeView.vue +++ b/src/views/WelcomeView.vue @@ -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) { diff --git a/src/views/admin/ExamineeManagementView.vue b/src/views/admin/ExamineeManagementView.vue index 90d97e9..5ed4713 100644 --- a/src/views/admin/ExamineeManagementView.vue +++ b/src/views/admin/ExamineeManagementView.vue @@ -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 { diff --git a/src/views/user/StudentHomeView.vue b/src/views/user/ExamineeHomeView.vue similarity index 94% rename from src/views/user/StudentHomeView.vue rename to src/views/user/ExamineeHomeView.vue index 18b9e68..33aa0d2 100644 --- a/src/views/user/StudentHomeView.vue +++ b/src/views/user/ExamineeHomeView.vue @@ -53,7 +53,7 @@

考试信息

- + {{ formatExamDuration(lastExam?.exam_minutes) }} + + + {{ formatExamDuration(lastExam?.exam_minutes_min) }} + 待设置 @@ -80,13 +91,14 @@ - {{ formatExamDuration(lastExam?.exam_minutes_min) }} + 待设置 +