From 9fade2542bf4a2bfef82b5f16238ed591701aad4 Mon Sep 17 00:00:00 2001 From: hejl Date: Sun, 24 Aug 2025 22:37:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AA=97=E5=8F=A3=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E4=BF=9D=E6=8C=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + gofaster/app/src/main/index.js | 109 ++++++++++++++++- gofaster/app/src/main/windowState.js | 167 +++++++++++++++++++++++++++ 3 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 gofaster/app/src/main/windowState.js diff --git a/.gitignore b/.gitignore index 804a403..d7b922c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /gofaster/app/dist /gofaster/backend/logs /gofaster/tmp/ +/gofaster/app/dist/*/*/ \ No newline at end of file diff --git a/gofaster/app/src/main/index.js b/gofaster/app/src/main/index.js index 0687c64..a323269 100644 --- a/gofaster/app/src/main/index.js +++ b/gofaster/app/src/main/index.js @@ -2,6 +2,10 @@ const { app, BrowserWindow, ipcMain } = require('electron') const path = require('path') const fs = require('fs') const os = require('os') +const WindowStateManager = require('./windowState') + +// 创建窗口状态管理器 +const windowStateManager = new WindowStateManager('main') // 设置进程编码,确保中文正常显示 process.env.LANG = 'zh_CN.UTF-8' @@ -167,9 +171,14 @@ if (isDev && process.argv.includes('--watch')) { function createWindow() { try { + // 加载保存的窗口状态 + const windowState = windowStateManager.loadState() + mainWindow = new BrowserWindow({ - width: 1200, - height: 800, + width: windowState.width, + height: windowState.height, + x: windowState.x, + y: windowState.y, autoHideMenuBar: true, webPreferences: { nodeIntegration: false, @@ -194,6 +203,13 @@ function createWindow() { show: false // 先隐藏窗口,等加载完成后再显示 }) + // 如果保存的状态是最大化或全屏,应用这些状态 + if (windowState.isMaximized) { + mainWindow.maximize() + } else if (windowState.isFullScreen) { + mainWindow.setFullScreen(true) + } + console.log('Main window created'); // 开发环境下抑制安全警告 @@ -313,8 +329,51 @@ function createWindow() { }) } + // 添加窗口状态监听器 + // 窗口大小改变时保存状态(防抖) + let resizeTimeout + mainWindow.on('resize', () => { + clearTimeout(resizeTimeout) + resizeTimeout = setTimeout(() => { + if (!mainWindow.isMaximized() && !mainWindow.isFullScreen()) { + windowStateManager.saveState(mainWindow) + } + }, 500) // 500ms防抖 + }) + + // 窗口移动时保存状态(防抖) + let moveTimeout + mainWindow.on('move', () => { + clearTimeout(moveTimeout) + moveTimeout = setTimeout(() => { + if (!mainWindow.isMaximized() && !mainWindow.isFullScreen()) { + windowStateManager.saveState(mainWindow) + } + }, 500) // 500ms防抖 + }) + + // 窗口最大化状态变化时保存状态 + mainWindow.on('maximize', () => { + windowStateManager.saveState(mainWindow) + }) + + mainWindow.on('unmaximize', () => { + windowStateManager.saveState(mainWindow) + }) + + // 窗口全屏状态变化时保存状态 + mainWindow.on('enter-full-screen', () => { + windowStateManager.saveState(mainWindow) + }) + + mainWindow.on('leave-full-screen', () => { + windowStateManager.saveState(mainWindow) + }) + // 窗口关闭事件 mainWindow.on('closed', () => { + // 保存窗口状态 + windowStateManager.saveState(mainWindow) mainWindow = null }) @@ -456,6 +515,52 @@ ipcMain.handle('get-local-ip', async () => { } }); +// 窗口状态管理相关的IPC处理器 +ipcMain.handle('reset-window-state', async () => { + try { + 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 { + 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', () => { diff --git a/gofaster/app/src/main/windowState.js b/gofaster/app/src/main/windowState.js new file mode 100644 index 0000000..1e6ce8f --- /dev/null +++ b/gofaster/app/src/main/windowState.js @@ -0,0 +1,167 @@ +const { app, screen } = require('electron') +const path = require('path') +const fs = require('fs') + +class WindowStateManager { + constructor(windowName = 'main') { + this.windowName = windowName + this.statePath = path.join(app.getPath('userData'), `${windowName}-window-state.json`) + } + + // 加载窗口状态 + loadState() { + try { + if (!this.hasSavedState()) { + return this.getDefaultState() + } + + const stateData = fs.readFileSync(this.statePath, 'utf8') + const state = JSON.parse(stateData) + + // 验证状态数据 + if (!this.validateState(state)) { + return this.getDefaultState() + } + + // 调整状态到屏幕边界内 + const adjustedState = this.adjustStateToScreen(state) + return adjustedState + } catch (error) { + console.error(`加载窗口状态失败 (${this.windowName}):`, error) + return this.getDefaultState() + } + } + + // 获取默认状态 + getDefaultState() { + return { + width: 1200, + height: 800, + x: undefined, // 让Electron自动居中 + y: undefined, // 让Electron自动居中 + isMaximized: false, + isFullScreen: false + } + } + + // 验证状态数据 + validateState(state) { + return state && + typeof state.width === 'number' && + typeof state.height === 'number' && + state.width > 0 && + state.height > 0 && + (state.x === undefined || (typeof state.x === 'number' && state.x >= 0)) && + (state.y === undefined || (typeof state.y === 'number' && state.y >= 0)) + } + + // 调整状态到屏幕边界内 + adjustStateToScreen(state) { + try { + const displays = screen.getAllDisplays() + if (displays.length === 0) { + return state + } + + // 使用主显示器 + const primaryDisplay = displays.find(d => d.bounds.x === 0 && d.bounds.y === 0) || displays[0] + const { bounds: screenBounds } = primaryDisplay + + let { width, height, x, y, isMaximized, isFullScreen } = state + + // 如果窗口太大,调整到屏幕大小 + if (width > screenBounds.width) { + width = Math.max(800, screenBounds.width - 100) + } + if (height > screenBounds.height) { + height = Math.max(600, screenBounds.height - 100) + } + + // 如果窗口太小,设置最小尺寸 + if (width < 800) width = 800 + if (height < 600) height = 600 + + // 调整位置,确保窗口完全在屏幕内 + if (x !== undefined && y !== undefined) { + // 确保窗口右边界不超出屏幕 + if (x + width > screenBounds.width) { + x = screenBounds.width - width + } + // 确保窗口下边界不超出屏幕 + if (y + height > screenBounds.height) { + y = screenBounds.height - height + } + // 确保窗口左边界不超出屏幕 + if (x < screenBounds.x) { + x = screenBounds.x + } + // 确保窗口上边界不超出屏幕 + if (y < screenBounds.y) { + y = screenBounds.y + } + } + + return { width, height, x, y, isMaximized, isFullScreen } + } catch (error) { + console.error(`调整窗口状态到屏幕边界失败:`, error) + return state + } + } + + // 保存窗口状态 + saveState(window) { + try { + if (!window || window.isDestroyed()) { + return false + } + + const bounds = window.getBounds() + const state = { + width: bounds.width, + height: bounds.height, + x: bounds.x, + y: bounds.y, + isMaximized: window.isMaximized(), + isFullScreen: window.isFullScreen() + } + + // 确保目录存在 + const dir = path.dirname(this.statePath) + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }) + } + + fs.writeFileSync(this.statePath, JSON.stringify(state, null, 2)) + return true + } catch (error) { + console.error(`保存窗口状态失败 (${this.windowName}):`, error) + return false + } + } + + // 检查是否有保存的状态 + hasSavedState() { + return fs.existsSync(this.statePath) + } + + // 获取状态文件路径 + getStatePath() { + return this.statePath + } + + // 重置状态(删除保存的状态文件) + resetState() { + try { + if (this.hasSavedState()) { + fs.unlinkSync(this.statePath) + return true + } + return false + } catch (error) { + console.error(`重置窗口状态失败 (${this.windowName}):`, error) + return false + } + } +} + +module.exports = WindowStateManager