diff --git a/main.js b/main.js index 9c56267..7e8511d 100644 --- a/main.js +++ b/main.js @@ -3,48 +3,13 @@ const path = require('node:path') const server = require('./server/server'); const log = require('electron-log') +const mainWin = require('./windows/app'); + if (require('electron-squirrel-startup')) { app.quit() return } -const createWindow = () => { - const win = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - devTools: false, - webSecurity: false, - allowRunningInsecureContent: true, - preload: path.join(__dirname, 'preload.js') - } - }) - - require("./menu/menu.js") - require("./menu/tray.js") - - const url = require('url').format({ - protocol: 'http', - slashes: true, - hostname: '127.0.0.1', - port: 8787 - }) - - win.loadURL(url) - - win.on('minimize', (event) => { - event.preventDefault() - win.hide() - }) - - win.on('close', (event) => { - event.preventDefault() - win.hide() - }) -} - app.whenReady().then(() => { log.transports.file.encoding = 'utf8'; log.transports.file.file = path.join(app.getPath('userData'), 'logs/iyuu.log'); @@ -52,40 +17,27 @@ app.whenReady().then(() => { log.info('App is starting...'); server.startServer() + + require("./menu/tray.js") + log.info("[About] 新疆萌森软件开发工作室提供技术支持"); setTimeout(() => { - createWindow() - }, 5000) -}) - -app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow() - } else { - app.show() - BrowserWindow.getAllWindows().forEach(win => { - win.show() - }) - } + mainWin.createWindow() + }, 3000) }) app.on('window-all-closed', () => { - BrowserWindow.getAllWindows().forEach(win => { - win.hide() - }) - app.hide() + mainWin.hideWindows() }) app.on('before-quit', () => { + mainWin.hideWindows() server.stopServer() log.info('App is quitting...'); }) -process.on('uncaughtException', (error) => { - log.error('Uncaught Exception:', error); -}); - -process.on('unhandledRejection', (reason, promise) => { - log.error('Unhandled Rejection at:', promise, 'reason:', reason); -}); +app.on('quit', () => { + app.quit() + log.info('App is quitted'); +}) \ No newline at end of file diff --git a/menu/menu.js b/menu/menu.js index a4a1653..28b0490 100644 --- a/menu/menu.js +++ b/menu/menu.js @@ -1,5 +1,6 @@ const { Menu, BrowserWindow } = require("electron") const server = require('../server/server'); +const mainWin = require('../windows/app'); let template = [ { @@ -8,20 +9,14 @@ let template = [ { label: "刷新", click: () => { - BrowserWindow.getAllWindows().forEach(win => { - win.reload() - }) + mainWin.refreshUrl() } }, { label: "重启服务", click: () => { + mainWin.closeWindows() server.restartServer() - setTimeout(() => { - BrowserWindow.getAllWindows().forEach(win => { - win.reload() - }) - }, 2000) } }, diff --git a/menu/tray.js b/menu/tray.js index 05748a1..0913b93 100644 --- a/menu/tray.js +++ b/menu/tray.js @@ -1,43 +1,38 @@ -const { app, Menu, Tray, BrowserWindow } = require("electron") +const { app, Menu, Tray } = require("electron") const path = require('node:path') const server = require('../server/server'); +const mainWin = require('../windows/app'); const tray = new Tray('iyuu.ico'); -const contextMenu = Menu.buildFromTemplate([{ - label: '打开主窗口', - click: () => { - BrowserWindow.getAllWindows().forEach(win => { - win.show() - }) +const contextMenu = Menu.buildFromTemplate([ + { + label: '打开主窗口', + click: () => { + mainWin.showWindows() + } + }, + { + label: '重启服务', + click: () => { + server.restartServer() + } + }, + { + label: '退出', + click: () => { + app.quit() + } } -}, { - label: '重启服务', - click: () => { - BrowserWindow.getAllWindows().forEach(win => { - win.hide() - }) - server.restartServer() - setTimeout(() => { - BrowserWindow.getAllWindows().forEach(win => { - win.show() - win.reload() - }) - }, 1000) - } -}, -{ - label: '退出', - click: () => { - app.quit() - } -} ]); tray.setToolTip('IYUU'); tray.setContextMenu(contextMenu); tray.on('double-click', () => { - win.isVisible() ? win.hide() : win.show() - win.isVisible() ? win.setSkipTaskbar(false) : win.setSkipTaskbar(true); + if (mainWin.visibleWindows()) { + mainWin.showWindows() + } else { + mainWin.hideWindows() + } }); \ No newline at end of file diff --git a/package.json b/package.json index 0709119..47ac090 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "electron-log": "^5.1.5", "electron-squirrel-startup": "^1.0.1", + "jquery": "^3.7.1", "tree-kill": "^1.2.2" } } diff --git a/server/server.js b/server/server.js index 600dba9..b134b36 100644 --- a/server/server.js +++ b/server/server.js @@ -2,6 +2,9 @@ const { spawn, exec, execFile } = require('child_process'); const os = require('os'); const path = require('path'); const log = require('electron-log') +const mainWin = require('../windows/app') + +let serverProcess = null; function getPhpPath(resourcePath) { const arch = os.arch(); @@ -15,95 +18,76 @@ function getPhpPath(resourcePath) { } } -let serverProcess = null; - function startServer() { - let resourcePath = process.resourcesPath; - if (resourcePath.includes('node_modules')) { - resourcePath = process.cwd(); - } + if (!serverProcess) { + let resourcePath = process.resourcesPath; + if (resourcePath.includes('node_modules')) { + resourcePath = process.cwd(); + } - const env = { ...process.env }; - const phpDir = getPhpPath(resourcePath); - env.Path = `${phpDir};${env.Path}`; + const env = { ...process.env }; + const phpDir = getPhpPath(resourcePath); + env.Path = `${phpDir};${env.Path}`; - const workingDir = path.resolve(path.join(resourcePath, 'iyuu')); - - log.info(`[IYUU] 工作目录: ${workingDir}`); + const workingDir = path.resolve(path.join(resourcePath, 'iyuu')); - // serverProcess = exec(`cmd /c ${batPath}`, { - // cwd: workingDirectory, - // env: env, - // windowsHide: true - // }, (error, stdout, stderr) => { - // if (error) { - // log.error(`[IYUU] 服务启动错误: ${error.message}`); - // return; - // } - // if (stderr) { - // log.error(`[IYUU] 服务启动 stderr: ${stderr}`); - // return; - // } - // log.info(`[IYUU] 服务启动成功: ${stdout}`); - // }); + log.info(`[IYUU] 工作目录: ${workingDir}`); - - // serverProcess = execFile('cmd', ['/c', batPath], { - // cwd: workingDirectory, - // env: env, - // killSignal: 'SIGTERM', - // windowsHide: true, - // }, (error, stdout, stderr) => { - // if (error) { - // log.error(`[IYUU] 服务启动错误: ${error.message}`); - // } else { - // log.error(`[IYUU] 服务启动 stderr: ${stderr}`); - // log.info(`[IYUU] 服务启动成功: ${stdout}`); - // } - // }); - - serverProcess = spawn('cmd', ['/k', 'windows.bat'], { - cwd: workingDir, - stdio: 'pipe', - env: env, - detached: true, - windowsHide: false - }); - - serverProcess.unref(); - - if (serverProcess.stdout) { - serverProcess.stdout.on('data', (data) => { - log.info(`[IYUU] ${data}`); + serverProcess = execFile('cmd', ['/c', 'windows.bat'], { + cwd: workingDir, + env: env, + killSignal: 'SIGTERM', + windowsHide: true, + }, (error, stdout, stderr) => { + if (error) { + log.error(`[IYUU] 服务启动错误: ${error.message}`); + } else { + log.error(`[IYUU] 服务启动 stderr: ${stderr}`); + log.info(`[IYUU] 服务启动成功: ${stdout}`); + } }); - serverProcess.stderr.on('data', (data) => { - log.error(`[IYUU] ${data}`); + // serverProcess = spawn('cmd', ['/c', 'windows.bat'], { + // cwd: workingDir, + // stdio: 'pipe', + // env: env, + // detached: true, + // windowsHide: true + // }); + + serverProcess.unref(); + + if (serverProcess.stdout) { + serverProcess.stdout.on('data', (data) => { + log.info(`[IYUU] ${data}`); + }); + + serverProcess.stderr.on('data', (data) => { + log.error(`[IYUU] ${data}`); + }); + } + + serverProcess.on('error', (err) => { + log.error(`[IYUU] 服务启动错误: ${err.message}`); }); - + serverProcess.on("close", function (code) { + log.info("[IYUU] 服务退出:" + code); + }); } - - serverProcess.on('error', (err) => { - log.error(`[IYUU] 服务启动错误: ${err.message}`); - }); - - serverProcess.on("close", function (code) { - log.info("[IYUU] 服务退出:" + code); - }); } function stopServer() { if (serverProcess) { + mainWin.closeWindows() log.info("Killing server process with PID:", serverProcess.pid); - try { process.kill(-serverProcess.pid, 'SIGTERM'); log.info("后台服务已关闭..."); serverProcess = null; } catch (err) { log.error('Error using process.kill:', err); - exec(`taskkill /PID ${serverProcess.pid} /T /F`, (err, stdout, stderr) => { + exec(`taskkill /PID ${serverProcess.pid} /T /F`, (err, _stdout, _stderr) => { if (err) { log.error('Error using taskkill:', err); } else { @@ -121,6 +105,9 @@ function restartServer() { stopServer(); setTimeout(() => { startServer(); + setTimeout(() => { + mainWin.showWindows() + }, 2000) }, 1000); } diff --git a/windows/app.js b/windows/app.js new file mode 100644 index 0000000..46eaad2 --- /dev/null +++ b/windows/app.js @@ -0,0 +1,102 @@ +const { BrowserWindow } = require('electron') +const path = require('node:path') +const log = require('electron-log') + +const url = require('url').format({ + protocol: 'http', + hostname: '127.0.0.1', + port: 8787 +}) + +/** @type {BrowserWindow | null} */ +let mainWindow = null + +const createWindow = () => { + if (mainWindow === null) { + log.info('Create main window') + mainWindow = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + preload: path.join(__dirname, '..', 'preload.js') + } + }) + + // mainWindow.webContents.openDevTools() + + require("../menu/menu") + + mainWindow.webContents.loadURL(url) + // mainWindow.loadURL(url) + + mainWindow.on('minimize', (event) => { + event.preventDefault() + mainWindow.hide() + }) + mainWindow.on('close', (event) => { + event.preventDefault() + mainWindow.hide() + }) + } else { + log.info('Main window already created') + } +} + +const showWindows = () => { + log.info('Show main window') + if (!mainWindow) { + createWindow() + return + } + if (!mainWindow.isVisible()) { + mainWindow.show() + } +} + +const hideWindows = () => { + log.info('Hide main window') + if (!mainWindow) { + createWindow() + } + if (visibleWindows()) { + mainWindow.hide() + } +} + +const closeWindows = () => { + log.info('Close main window') + if (visibleWindows()) { + mainWindow.close() + mainWindow = null + } +} + +const refreshWindows = () => { + log.info('Refresh main window') + hideWindows() + if (visibleWindows()) { + mainWindow.reload() + } +} + +const refreshUrl = () => { + log.info('Refresh main window') + if (visibleWindows()) { + mainWindow.loadURL(url) + } +} + +const rebootWindows = () => { + log.info('Reboot main window') + hideWindows() + if (visibleWindows()) { + mainWindow.reload() + } +} + +const visibleWindows = () => { + return mainWindow && mainWindow.isVisible() +} + + +module.exports = { hideWindows, showWindows, createWindow, closeWindows, refreshWindows, rebootWindows, visibleWindows, refreshUrl }; \ No newline at end of file