import { Tray, Menu, dialog, BrowserWindow } from 'electron'; import { join } from 'path'; import { getBaseDir } from 'ee-core/ps'; import { logger } from 'ee-core/log'; import { app as electronApp } from 'electron'; import { getMainWindow, getCloseAndQuit, setCloseAndQuit } from 'ee-core/electron'; import { isSmartWindowOpen } from '../window/smartWindow'; /** * 托盘 * @class */ class TrayService { constructor() { this.tray = null; this.quitConfirming = false; this.config = { title: 'electron-egg', icon: '/public/images/tray.png' } } /** * 创建托盘 */ create () { logger.info('[tray] load'); const cfg = this.config; const mainWindow = getMainWindow(); // tray icon const iconPath = join(getBaseDir(), cfg.icon); /** * 托盘退出前确认:退出会中止智能工作台正在进行的对话/任务。 * *

托盘点击发生在主进程,此时主窗口可能已经收进托盘(不可见), * 没法可靠地在渲染层弹 Ant Design 确认框,所以用系统原生对话框。 */ const quitWithConfirm = async () => { if (this.quitConfirming) return; this.quitConfirming = true; try { const options = { type: 'warning', title: '退出程序', message: '确认退出清鉴?', detail: isSmartWindowOpen() ? '退出程序会中止智能工作台中正在进行的对话或任务,已生成的内容会保留。' : '退出程序会关闭所有窗口。', buttons: ['取消', '退出'], defaultId: 0, cancelId: 0, noLink: true, }; // 有聚焦窗口就挂成它的模态;托盘菜单打开时通常没有聚焦窗口,用独立对话框, // 避免始终挂到可能被智能窗口挡住的 mainWindow 后面 const focused = BrowserWindow.getFocusedWindow(); const parent = focused && !focused.isDestroyed() ? focused : undefined; const result = parent ? await dialog.showMessageBox(parent, options) : await dialog.showMessageBox(options); if (result.response === 1) { electronApp.quit(); } } catch (e) { logger.error('[tray] 退出确认失败:', e instanceof Error ? e.message : String(e)); } finally { this.quitConfirming = false; } }; // 托盘菜单功能列表 // 智能工作台不放入口:顶栏「智能」开关是唯一入口(案件/账号生命周期也只在主窗口) const trayMenuTemplate = [ { label: '显示主窗口', click: function () { if (mainWindow.isMinimized()) { mainWindow.restore(); } mainWindow.show(); mainWindow.focus(); } }, { label: '退出程序', click: () => { void quitWithConfirm(); } } ] // 设置一个标识,点击关闭,最小化到托盘 setCloseAndQuit(false); mainWindow.on('close', (event) => { if (getCloseAndQuit()) { return; } mainWindow.hide(); event.preventDefault(); }); // 实例化托盘 this.tray = new Tray(iconPath); this.tray.setToolTip(cfg.title); const contextMenu = Menu.buildFromTemplate(trayMenuTemplate); this.tray.setContextMenu(contextMenu); // 左键单击的时候能够显示主窗口 this.tray.on('click', () => { mainWindow.show() }) } } TrayService.toString = () => '[class TrayService]'; export const trayService = new TrayService();