const { app, BrowserWindow, ipcMain } = require('electron') const path = require('path') const fs = require('fs') const os = require('os') const WindowStateManager = require('./windowState') // 窗口状态管理器(延迟初始化) let windowStateManager = null // 设置进程编码,确保中文正常显示 process.env.LANG = 'zh_CN.UTF-8' process.env.LC_ALL = 'zh_CN.UTF-8' // 获取项目根目录绝对路径 const appRoot = path.resolve(__dirname, '../..') // 获取本地IP地址 function getLocalIPAddresses() { try { const interfaces = os.networkInterfaces() const addresses = [] for (const name of Object.keys(interfaces)) { for (const interface of interfaces[name]) { // 跳过内部地址和非IPv4地址 if (interface.family === 'IPv4' && !interface.internal) { addresses.push({ name: name, address: interface.address, netmask: interface.netmask, family: interface.family }) } } } // 优先返回非回环地址 const nonLoopback = addresses.filter(addr => addr.address !== '127.0.0.1') return nonLoopback.length > 0 ? nonLoopback[0] : addresses[0] || null } catch (error) { console.error('获取本地IP地址失败:', error) return null } } let mainWindow let errorLogCount = 0 let logFilePath // 检查是否为开发环境(延迟初始化) let isDev = null function getIsDev() { if (isDev === null) { try { isDev = process.env.NODE_ENV === 'development' || !app.isPackaged } catch (error) { // 如果app对象还没有准备好,默认使用开发环境 isDev = process.env.NODE_ENV === 'development' || true } } return isDev } // 初始化日志系统 function initLogging() { try { // 创建日志目录 const logDir = path.join(app.getPath('userData'), 'logs') if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) } // 设置日志文件路径 const timestamp = new Date().toISOString().split('T')[0] logFilePath = path.join(logDir, `gofaster-${timestamp}.log`) // 重定向控制台输出到日志文件,设置UTF-8编码 const logStream = fs.createWriteStream(logFilePath, { flags: 'a', encoding: 'utf8' }) // 重写console.log const originalLog = console.log console.log = function(...args) { const timestamp = new Date().toISOString() const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg) ).join(' ') logStream.write(`[${timestamp}] [INFO] ${message}\n`) originalLog.apply(console, args) } // 重写console.error const originalError = console.error console.error = function(...args) { const timestamp = new Date().toISOString() const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg) ).join(' ') errorLogCount++ logStream.write(`[${timestamp}] [ERROR] ${message}\n`) originalError.apply(console, args) // 通知渲染进程错误计数更新 if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.webContents.send('error-log-updated', { count: errorLogCount }) } } // 重写console.warn const originalWarn = console.warn console.warn = function(...args) { const timestamp = new Date().toISOString() const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg) ).join(' ') logStream.write(`[${timestamp}] [WARN] ${message}\n`) originalWarn.apply(console, args) } } catch (error) { console.error('初始化日志系统失败:', error) } } // 开发环境热重载 - 只在非watch模式下启用 if (getIsDev() && !process.argv.includes('--watch')) { try { // 修复热重载配置 require('electron-reload')(appRoot, { electron: path.join(__dirname, '..', '..', 'node_modules', 'electron', 'dist', 'electron.exe'), hardResetMethod: 'exit', // 添加更稳定的配置 forceHardReset: true, ignored: [ /node_modules|[\/\\]\./, /dist|[\/\\]\./, /\.git|[\/\\]\./ ] }); } catch (error) { console.log('Hot reload failed:', error.message); } } // 监听文件变化(用于watch模式) if (getIsDev() && process.argv.includes('--watch')) { // 监听dist目录变化 const distPath = path.join(appRoot, 'dist/renderer'); if (fs.existsSync(distPath)) { let reloadTimeout = null; fs.watch(distPath, { recursive: true }, (eventType, filename) => { if (filename && mainWindow && !mainWindow.isDestroyed()) { // 添加防抖机制,避免频繁重载 if (reloadTimeout) { clearTimeout(reloadTimeout); } reloadTimeout = setTimeout(() => { try { mainWindow.reload(); } catch (error) { console.log('Page reload failed:', error.message); } }, 500); // 500ms防抖延迟 } }); } } function createWindow() { try { // 加载保存的窗口状态 let windowState if (!windowStateManager) { console.warn('窗口状态管理器未初始化,使用默认状态') windowState = { width: 1200, height: 800, x: undefined, y: undefined, isMaximized: false, isFullScreen: false } } else { windowState = windowStateManager.loadState() } mainWindow = new BrowserWindow({ width: windowState.width, height: windowState.height, x: windowState.x, y: windowState.y, autoHideMenuBar: true, webPreferences: { nodeIntegration: false, contextIsolation: true, enableRemoteModule: false, preload: path.join(appRoot, 'src/preload.js'), // 强化安全配置 webSecurity: true, allowRunningInsecureContent: false, experimentalFeatures: false, // 禁用Node.js集成 nodeIntegrationInWorker: false, nodeIntegrationInSubFrames: false, // 沙箱模式 sandbox: false, // 保持false以支持preload脚本 // 禁用eval相关功能 enableBlinkFeatures: '', disableBlinkFeatures: 'Auxclick' }, // 添加字体配置,确保中文正常显示 titleBarStyle: 'default', show: false // 先隐藏窗口,等加载完成后再显示 }) // 如果保存的状态是最大化或全屏,应用这些状态 if (windowState.isMaximized) { mainWindow.maximize() } else if (windowState.isFullScreen) { mainWindow.setFullScreen(true) } // 开发环境下抑制安全警告 if (getIsDev()) { mainWindow.webContents.on('did-frame-finish-load', () => { // 移除有问题的JavaScript执行,避免IPC通信错误 // 简化JavaScript注入,避免序列化错误 mainWindow.webContents.executeJavaScript(` // 重写console.warn和console.error来抑制特定警告 const originalWarn = console.warn; const originalError = console.error; console.warn = function(...args) { const message = args.join(' '); if (message.includes('Electron Security Warning') || message.includes('Insecure Content-Security-Policy') || message.includes('unsafe-eval')) { return; // 抑制这些警告 } originalWarn.apply(console, args); }; console.error = function(...args) { const message = args.join(' '); if (message.includes('Electron Security Warning') || message.includes('Insecure Content-Security-Policy') || message.includes('unsafe-eval')) { return; // 抑制这些警告 } originalError.apply(console, args); }; `).catch(err => { console.log('JavaScript injection failed:', err.message); // 注入失败不影响应用运行 }); }); // 抑制Electron安全警告 mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => { // 抑制Autofill相关警告 if (message.includes('Autofill.enable failed') || message.includes('Autofill.setAddresses failed') || message.includes('Request Autofill')) { event.preventDefault(); return false; } // 抑制Electron安全警告 if (message.includes('Electron Security Warning') || message.includes('Insecure Content-Security-Policy') || message.includes('unsafe-eval')) { event.preventDefault(); return false; } }); } const loadPath = path.join(appRoot, 'dist/renderer/index.html') // 检查文件是否存在 if (!fs.existsSync(loadPath)) { // 在watch模式下等待文件构建完成 if (getIsDev() && process.argv.includes('--watch')) { const checkFile = () => { if (fs.existsSync(loadPath)) { loadMainWindow(); } else { setTimeout(checkFile, 1000); // 每秒检查一次 } }; checkFile(); return; // 重要:如果文件不存在,直接返回,不执行后续代码 } else { // 非watch模式,直接显示错误 console.error('File not found:', loadPath); mainWindow.loadURL(`data:text/html,

Build file not found, please run npm run dev first

`); return; } } // 文件存在,直接加载 loadMainWindow(); function loadMainWindow() { mainWindow.loadFile(loadPath).then(() => { // 开发环境下打开开发者工具 if (getIsDev()) { mainWindow.webContents.openDevTools() } // 页面加载完成后显示窗口 mainWindow.show() }).catch(err => { console.error('Load failed:', err) mainWindow.loadURL(`data:text/html,

Load failed: ${err.toString()}

`) // 即使加载失败也要显示窗口 mainWindow.show() }) } // 添加窗口状态监听器 // 窗口大小改变时保存状态(防抖) let resizeTimeout mainWindow.on('resize', () => { clearTimeout(resizeTimeout) resizeTimeout = setTimeout(() => { if (!mainWindow.isMaximized() && !mainWindow.isFullScreen() && windowStateManager) { windowStateManager.saveState(mainWindow) } }, 500) // 500ms防抖 }) // 窗口移动时保存状态(防抖) let moveTimeout mainWindow.on('move', () => { clearTimeout(moveTimeout) moveTimeout = setTimeout(() => { if (!mainWindow.isMaximized() && !mainWindow.isFullScreen() && windowStateManager) { windowStateManager.saveState(mainWindow) } }, 500) // 500ms防抖 }) // 窗口最大化状态变化时保存状态 mainWindow.on('maximize', () => { if (windowStateManager) { windowStateManager.saveState(mainWindow) } }) mainWindow.on('unmaximize', () => { if (windowStateManager) { windowStateManager.saveState(mainWindow) } }) // 窗口全屏状态变化时保存状态 mainWindow.on('enter-full-screen', () => { if (windowStateManager) { windowStateManager.saveState(mainWindow) } }) mainWindow.on('leave-full-screen', () => { if (windowStateManager) { windowStateManager.saveState(mainWindow) } }) // 窗口即将关闭事件(更早触发) mainWindow.on('close', (event) => { // 立即发送事件,不等待 if (!mainWindow.isDestroyed()) { mainWindow.webContents.send('app-will-close') } }) // 窗口关闭事件 mainWindow.on('closed', () => { // 保存窗口状态 if (windowStateManager) { windowStateManager.saveState(mainWindow) } mainWindow = null }) } catch (error) { console.error('Failed to create window:', error) } } app.whenReady().then(() => { // 初始化窗口状态管理器 windowStateManager = new WindowStateManager('main') // 初始化日志系统 initLogging() createWindow() // 修复IPC通信问题 ipcMain.on('request-status', (event) => { try { const statusData = { status: 'running', timestamp: Date.now() } event.sender.send('status-update', statusData) } catch (error) { console.error('IPC communication error:', error); } }) // 添加获取进程内存信息的API ipcMain.handle('get-process-memory-info', async (event) => { try { // 使用 process.memoryUsage 获取内存信息 const memoryUsage = process.memoryUsage(); // 获取更详细的系统内存信息 let systemMemoryInfo = {}; try { // 尝试使用 require('os') 获取系统内存信息 const os = require('os'); systemMemoryInfo = { totalMemory: os.totalmem(), freeMemory: os.freemem(), usedMemory: os.totalmem() - os.freemem() }; } catch (osError) { console.warn('Cannot get system memory info:', osError.message); } return { // 进程内存使用情况 privateBytes: memoryUsage.rss, // Resident Set Size - 进程占用的物理内存 sharedBytes: memoryUsage.external, // 外部内存使用 heapUsed: memoryUsage.heapUsed, // JavaScript堆内存使用 heapTotal: memoryUsage.heapTotal, // JavaScript堆内存总量 // 系统内存信息 systemTotal: systemMemoryInfo.totalMemory || 0, systemFree: systemMemoryInfo.freeMemory || 0, systemUsed: systemMemoryInfo.usedMemory || 0 }; } catch (error) { console.error('Failed to get memory info:', error); // 返回默认值 return { privateBytes: 0, sharedBytes: 0, heapUsed: 0, heapTotal: 0, systemTotal: 0, systemFree: 0, systemUsed: 0 }; } }); // 添加更新窗口标题的API ipcMain.handle('update-window-title', async (event, newTitle) => { try { if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.setTitle(newTitle); return { success: true, message: '窗口标题更新成功' }; } else { return { success: false, message: '主窗口不存在或已销毁' }; } } catch (error) { console.error('更新窗口标题失败:', error); return { success: false, message: '更新窗口标题失败: ' + error.message }; } }); // 获取错误日志计数 ipcMain.handle('get-error-log-count', async () => { return { count: errorLogCount } }); // 获取日志文件路径 ipcMain.handle('get-log-file-path', async () => { return { path: logFilePath } }); // 打开日志文件所在文件夹 ipcMain.handle('open-log-folder', async () => { try { const path = require('path'); const logDir = path.dirname(logFilePath); require('electron').shell.openPath(logDir); return { success: true, message: '日志文件夹已打开' }; } catch (error) { console.error('打开日志文件夹失败:', error); return { success: false, message: '打开日志文件夹失败: ' + error.message }; } }); // 获取本地IP地址 ipcMain.handle('get-local-ip', async () => { try { const ipInfo = getLocalIPAddresses(); if (ipInfo) { return { success: true, ip: ipInfo.address, interface: ipInfo.name, netmask: ipInfo.netmask }; } else { return { success: false, message: '无法获取本地IP地址', fallback: '127.0.0.1' }; } } catch (error) { console.error('获取本地IP地址失败:', error); return { success: false, message: '获取本地IP地址失败: ' + error.message, fallback: '127.0.0.1' }; } }); // 窗口状态管理相关的IPC处理器 ipcMain.handle('reset-window-state', async () => { try { if (!windowStateManager) { return { success: false, message: '窗口状态管理器未初始化' } } const result = windowStateManager.resetState() return { success: result, message: result ? '窗口状态已重置' : '没有找到保存的窗口状态' } } catch (error) { console.error('重置窗口状态失败:', error) return { success: false, message: '重置窗口状态失败: ' + error.message } } }) ipcMain.handle('get-window-state-info', async () => { try { if (!windowStateManager) { return { success: false, message: '窗口状态管理器未初始化' } } const hasState = windowStateManager.hasSavedState() const statePath = windowStateManager.getStatePath() let currentState = null if (hasState) { try { const stateData = fs.readFileSync(statePath, 'utf8') currentState = JSON.parse(stateData) } catch (error) { console.error('读取当前窗口状态失败:', error) } } return { hasSavedState: hasState, statePath: statePath, currentState: currentState } } catch (error) { console.error('获取窗口状态信息失败:', error) return { success: false, message: '获取窗口状态信息失败: ' + error.message } } }) }); // 闭合 app.whenReady().then() 的回调函数 app.on('window-all-closed', () => { // 由于已经在窗口 close 事件中处理了退出登录,这里直接退出 if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { if (mainWindow === null) createWindow() }) // 添加错误处理 process.on('uncaughtException', (error) => { console.error('Uncaught exception:', error) }) process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled promise rejection:', reason) }) // 测试日志系统 - 在开发环境下生成一些测试错误 if (getIsDev()) { setTimeout(() => { console.error('测试错误日志 1: 这是一个模拟的错误信息') }, 5000) setTimeout(() => { console.error('测试错误日志 2: 另一个模拟的错误信息') }, 10000) }