electron-vue-exam-single/electron/main.js
2025-08-12 22:35:36 +08:00

273 lines
7.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

// 确保所有导入都使用 ES 模块语法
import { app, BrowserWindow, ipcMain, dialog } from "electron";
// 修改fs模块的导入方式 - 从命名导入改为默认导入
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { migrateDatabases } from './db/migration.js';
import {
checkDatabaseInitialized,
initializeDatabase,
} from "./db/index.js";
// 导入配置项服务
import {
initConfigIpc,
} from "./service/configService.js";
// 导入字典服务 - 使用实际导出的函数名称
import {
initDictIpc,
} from "./service/dictService.js";
// 导入题干服务
import {
initQuestionIpc,
} from './service/questionService.js';
import {
initExamIpc,
} from "./service/examService.js";
// 添加考生服务导入
import {
initExamineeIpc
} from "./service/examineeService.js";
import {
initExamingIpc
} from "./service/examingService.js";
import {
initFileIpc
} from "./service/fileService.js";
// 定义 __dirname 和 __filename
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 确保在应用最开始处添加单实例锁检查
// 尝试获取单实例锁
const gotTheLock = app.requestSingleInstanceLock();
// 如果获取锁失败,说明已有实例在运行,直接退出
if (!gotTheLock) {
app.quit();
} else {
// 设置第二个实例启动时的处理
app.on("second-instance", (event, commandLine, workingDirectory) => {
// 当用户尝试启动第二个实例时,聚焦到已有的主窗口
const mainWindow = BrowserWindow.getAllWindows()[0];
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});
}
// 保存主窗口引用
let mainWindow = null;
function createWindow() {
// 如果已经有窗口,直接返回
if (mainWindow) {
return;
}
mainWindow = new BrowserWindow({
// 设置窗口宽度和高度为屏幕大小
width: 1200,
height: 800,
// 确保窗口最大化
maximized: true,
// 隐藏菜单栏
autoHideMenuBar: true,
// 完全禁用菜单栏
menuBarVisible: false,
webPreferences: {
preload: path.join(__dirname, "../electron/preload.js"),
nodeIntegration: false,
contextIsolation: true,
},
});
// 显式调用最大化方法,确保窗口最大化
mainWindow.maximize();
if (process.env.NODE_ENV === "development") {
mainWindow.loadURL("http://localhost:5173/");
mainWindow.webContents.openDevTools();
} else {
// 使用应用路径来构建更可靠的加载路径
const appPath = app.getAppPath();
console.log(`应用路径: ${appPath}`);
// 尝试多种可能的路径
const pathsToTry = [
// 尝试1: 相对路径 (原有逻辑)
path.join(__dirname, "../dist/index.html"),
// 尝试2: 直接使用应用路径 + dist
path.join(appPath, "dist/index.html"),
// 尝试3: 应用路径的上一级 + dist
path.join(path.dirname(appPath), "dist/index.html")
];
let indexPath = null;
// 检查哪个路径存在
for (const pathOption of pathsToTry) {
console.log(`尝试检查路径: ${pathOption}`);
try {
if (fs.existsSync(pathOption)) {
indexPath = pathOption;
console.log(`找到文件: ${indexPath}`);
break;
}
} catch (error) {
console.error(`检查路径时出错: ${error}`);
}
}
if (indexPath) {
try {
// 使用file://协议加载本地文件,避免路径问题
mainWindow.loadFile(indexPath);
// 添加加载完成事件监听
mainWindow.webContents.on('did-finish-load', () => {
console.log('文件加载完成');
});
// 添加加载失败事件监听
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error(`文件加载失败: ${errorCode} - ${errorDescription}`);
dialog.showErrorBox('加载失败', `无法加载应用界面: ${errorDescription}`);
});
} catch (error) {
console.error(`加载文件时出错: ${error}`);
dialog.showErrorBox('加载失败', `无法加载应用界面: ${error.message}`);
}
} else {
console.error(`所有路径都不存在: ${pathsToTry.join(', ')}`);
dialog.showErrorBox('文件不存在', `无法找到应用界面文件,请检查打包配置`);
}
}
// 添加窗口关闭前的确认对话框
mainWindow.on('close', (event) => {
// 阻止默认关闭行为
event.preventDefault();
// 显示确认对话框
dialog.showMessageBox({
type: 'warning',
title: '关闭确认',
message: '系统关闭后,已进行中的试卷将不会被保存,是否确认要关闭?',
buttons: ['取消', '确认关闭'],
defaultId: 0
}).then((result) => {
// 如果用户点击确认关闭
if (result.response === 1) {
// 允许窗口关闭
mainWindow.destroy();
}
// 否则取消关闭
});
});
// 当窗口关闭时,清空引用
mainWindow.on("closed", () => {
mainWindow = null;
});
}
// 初始化应用
async function setupApp() {
try {
console.log("应用启动 - 检查数据库初始化状态...");
// 等待应用就绪
await app.whenReady();
// 执行数据库迁移
await migrateDatabases();
// 使用全局变量防止重复初始化检查
if (global.dbInitCheck) {
console.log("数据库初始化检查已完成");
return;
}
global.dbInitCheck = true;
const isInitialized = await checkDatabaseInitialized();
console.log("数据库初始化状态:", isInitialized);
// 只检查状态,不自动初始化
} catch (error) {
console.error("数据库检查过程中出错:", error);
}
}
function setupIpcMain() {
// 数据库相关
ipcMain.handle("check-database-initialized", async () => {
try {
return await checkDatabaseInitialized();
} catch (error) {
console.error("Failed to check database initialization:", error);
return false;
}
});
ipcMain.handle("initialize-database", async () => {
try {
return await initializeDatabase();
} catch (error) {
console.error("Failed to initialize database:", error);
return false;
}
});
// 初始化config相关IPC
initConfigIpc(ipcMain);
// 初始化dict相关IPC
initDictIpc(ipcMain);
// 初始化exam相关IPC
initExamIpc(ipcMain);
// 初始化question相关IPC
initQuestionIpc(ipcMain);
// 初始化考生相关IPC
initExamineeIpc(ipcMain);
initExamingIpc(ipcMain);
initFileIpc(ipcMain);
}
// 只保留一个app.whenReady().then()调用
app.whenReady().then(() => {
setupApp();
createWindow();
setupIpcMain();
});
app.on("window-all-closed", () => {
// 在所有窗口关闭后,清空主窗口引用
mainWindow = null;
// 对于非macOS平台仍然需要退出应用
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
// 只有当没有窗口时才创建新窗口
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// 在应用退出前关闭所有数据库连接
app.on("will-quit", () => {
console.log("应用即将退出...");
});