初始化
This commit is contained in:
278
electron/main.js
Normal file
278
electron/main.js
Normal file
@@ -0,0 +1,278 @@
|
||||
const { ElectronEgg } = require('ee-core');
|
||||
const { app, Menu, ipcMain, Tray, dialog, BrowserWindow } = require('electron');
|
||||
const path = require('path');
|
||||
const lifecycle = require('./preload/lifecycle');
|
||||
const { preload } = require('./preload');
|
||||
|
||||
const APP_DISPLAY_NAME = 'CN_Tool 灿能运维工具';
|
||||
|
||||
// new app
|
||||
const electronApp = new ElectronEgg();
|
||||
|
||||
// 全局变量
|
||||
let tray = null;
|
||||
let isQuitting = false;
|
||||
|
||||
/**
|
||||
* 统一定位当前应用自己的主窗口,避免继续依赖旧品牌关键字。
|
||||
* 优先按当前主窗口标题精确匹配;如果主窗口尚未完全就绪,再回退到顶层可用窗口。
|
||||
*/
|
||||
function findAppMainWindow() {
|
||||
const windows = BrowserWindow.getAllWindows().filter(win => !win.isDestroyed());
|
||||
|
||||
return windows.find(win => win.getTitle() === APP_DISPLAY_NAME)
|
||||
|| windows.find(win => !win.getParentWindow())
|
||||
|| null;
|
||||
}
|
||||
|
||||
// 创建系统托盘
|
||||
function createTray() {
|
||||
try {
|
||||
// 开发环境和生产环境的图标路径
|
||||
const isDev = !process.resourcesPath;
|
||||
const iconPath = isDev
|
||||
? path.join(__dirname, '..', 'public', 'images', 'tray.png')
|
||||
: path.join(process.resourcesPath, 'app.asar.unpacked', 'public', 'images', 'tray.png');
|
||||
|
||||
console.log('[Tray] Icon path:', iconPath);
|
||||
|
||||
// 检查图标文件是否存在
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync(iconPath)) {
|
||||
console.error('[Tray] Icon file not found:', iconPath);
|
||||
// 如果找不到,尝试使用备用路径(主图标)
|
||||
const fallbackIcon = isDev
|
||||
? path.join(__dirname, '..', 'public', 'images', 'icon.png')
|
||||
: path.join(process.resourcesPath, 'app.asar.unpacked', 'public', 'images', 'icon.png');
|
||||
|
||||
if (fs.existsSync(fallbackIcon)) {
|
||||
console.log('[Tray] Using fallback icon:', fallbackIcon);
|
||||
tray = new Tray(fallbackIcon);
|
||||
} else {
|
||||
console.error('[Tray] No icon available, tray not created');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tray = new Tray(iconPath);
|
||||
}
|
||||
|
||||
tray.setToolTip(APP_DISPLAY_NAME);
|
||||
console.log('[Tray] Tray created successfully');
|
||||
|
||||
// 创建托盘菜单
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: '显示主窗口',
|
||||
click: () => {
|
||||
const mainWindow = findAppMainWindow();
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '退出',
|
||||
click: async () => {
|
||||
// 弹出确认对话框
|
||||
const { response } = await dialog.showMessageBox({
|
||||
type: 'question',
|
||||
title: '退出确认',
|
||||
message: '确定退出应用吗?',
|
||||
buttons: ['取消', '确定退出'],
|
||||
defaultId: 0,
|
||||
cancelId: 0
|
||||
});
|
||||
|
||||
if (response === 1) {
|
||||
// 用户点击了"确定退出"
|
||||
isQuitting = true;
|
||||
|
||||
// 获取主窗口
|
||||
const mainWindow = findAppMainWindow();
|
||||
|
||||
// 移除所有 close 监听器,避免阻止关闭
|
||||
if (mainWindow) {
|
||||
mainWindow.removeAllListeners('close');
|
||||
}
|
||||
|
||||
// 执行清理
|
||||
await lifecycle.cleanup();
|
||||
|
||||
// 退出应用
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
tray.setContextMenu(contextMenu);
|
||||
|
||||
// 双击托盘图标显示窗口
|
||||
tray.on('double-click', () => {
|
||||
const mainWindow = findAppMainWindow();
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('[Tray] Failed to create tray:', error);
|
||||
tray = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建应用菜单
|
||||
function createApplicationMenu() {
|
||||
// 生产环境隐藏菜单栏
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
// 调试时可以使用下面的菜单(取消注释)
|
||||
/*
|
||||
const template = [
|
||||
{
|
||||
label: '查看',
|
||||
submenu: [
|
||||
{ role: 'reload', label: '刷新' },
|
||||
{ role: 'forceReload', label: '强制刷新' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'toggleDevTools', label: '开发者工具' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '帮助',
|
||||
submenu: [
|
||||
{
|
||||
label: '使用说明',
|
||||
click: () => {
|
||||
// 可以打开帮助文档
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '关于',
|
||||
click: () => {
|
||||
// 可以显示关于信息
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
*/
|
||||
}
|
||||
|
||||
// 注册 IPC 处理器
|
||||
ipcMain.handle('show-log-window', () => {
|
||||
if (lifecycle.logWindowManager) {
|
||||
lifecycle.logWindowManager.show();
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('hide-log-window', () => {
|
||||
if (lifecycle.logWindowManager) {
|
||||
lifecycle.logWindowManager.hide();
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('toggle-log-window', () => {
|
||||
if (lifecycle.logWindowManager) {
|
||||
lifecycle.logWindowManager.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
// 检查是否正在退出
|
||||
ipcMain.handle('is-quitting', () => {
|
||||
return isQuitting;
|
||||
});
|
||||
|
||||
// 处理单实例:当尝试启动第二个实例时,聚焦已有窗口
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
console.log('[Main] Second instance detected, focusing main window...');
|
||||
|
||||
// 单实例激活时只聚焦当前应用自己的主窗口,避免误用历史命名判断。
|
||||
const mainWindow = findAppMainWindow();
|
||||
|
||||
if (mainWindow) {
|
||||
// 如果窗口最小化,恢复它
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
|
||||
// 如果窗口隐藏,显示它
|
||||
if (!mainWindow.isVisible()) {
|
||||
mainWindow.show();
|
||||
}
|
||||
|
||||
// 聚焦窗口
|
||||
mainWindow.focus();
|
||||
|
||||
console.log('[Main] Main window focused');
|
||||
} else {
|
||||
console.warn('[Main] Main window not found');
|
||||
}
|
||||
});
|
||||
|
||||
// 监听应用退出前事件(确保清理托盘)
|
||||
app.on('before-quit', () => {
|
||||
console.log('[Main] App before-quit, destroying tray...');
|
||||
|
||||
// 销毁托盘图标
|
||||
if (tray && !tray.isDestroyed()) {
|
||||
tray.destroy();
|
||||
tray = null;
|
||||
}
|
||||
});
|
||||
|
||||
// 监听 will-quit 事件(强制退出时)
|
||||
app.on('will-quit', () => {
|
||||
console.log('[Main] App will-quit');
|
||||
|
||||
// 确保托盘被销毁
|
||||
if (tray && !tray.isDestroyed()) {
|
||||
tray.destroy();
|
||||
tray = null;
|
||||
}
|
||||
});
|
||||
|
||||
// register lifecycle (绑定 this 上下文)
|
||||
electronApp.register("ready", lifecycle.ready.bind(lifecycle));
|
||||
electronApp.register("electron-app-ready", () => {
|
||||
lifecycle.electronAppReady.bind(lifecycle)();
|
||||
createApplicationMenu();
|
||||
createTray(); // 创建系统托盘
|
||||
});
|
||||
electronApp.register("window-ready", lifecycle.windowReady.bind(lifecycle));
|
||||
electronApp.register("before-close", async () => {
|
||||
// 如果不是真正退出,不执行清理
|
||||
if (!isQuitting) {
|
||||
console.log('[Main] Not quitting, skip cleanup');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Main] Quitting, execute cleanup');
|
||||
|
||||
// 销毁托盘图标
|
||||
if (tray && !tray.isDestroyed()) {
|
||||
tray.destroy();
|
||||
tray = null;
|
||||
}
|
||||
|
||||
await lifecycle.beforeClose.bind(lifecycle)();
|
||||
});
|
||||
|
||||
// register preload
|
||||
electronApp.register("preload", preload);
|
||||
|
||||
// run
|
||||
electronApp.run();
|
||||
Reference in New Issue
Block a user