const { app, Tray, Menu, screen, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const Store = require('electron-store'); // 初始化存储实例 const store = new Store({ username: { type: 'string', default: '' }, password: { type: 'string', default: '' }, token: { type: 'string', default: '' }, // name: 'auth-data', // 存储文件名称(可选) // encryptionKey: 'your-encryption-key', // 可选加密(生产环境建议设置) }); // store.set('username', ''); // store.set('password', ''); // if(store.get()) if (store.get('token')) { store.delete('token'); } // console.log(store.get('username')) let tray = null; let win = null; let floatingWindow = null; let tooltipWindow = null; let smart_win = null; let isFloatingWindowVisible = true; // 新增:跟踪悬浮球可见状态 // 新增:记录登录状态 let isLoggedIn = false; // 尝试获取单实例锁 const gotTheLock = app.requestSingleInstanceLock(); let iconPath; if (app.isPackaged) { iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png'); } else { iconPath = path.join(__dirname, '/tray-icon.png'); } function createWindow(w = 1200, h = 800) { win = new BrowserWindow({ width: w, height: h, // frame: false, icon: iconPath, // 使用平台特定图标 backgroundColor: '#fff', webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: true, //启用nodejs集成 contextIsolation: true, contentSecurityPolicy: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'" } }); // 强刷 win.webContents.reloadIgnoringCache() // 禁用默认菜单栏(保留窗口控制按钮) Menu.setApplicationMenu(null); // 初始设置为登录页模式(固定大小,禁止调整) setLoginWindowMode(); const primaryDisplay = screen.getPrimaryDisplay(); const { width, height } = primaryDisplay.workAreaSize; // win.setPosition(width - 660 - 900, 100); win.center(); if (process.env.NODE_ENV === 'development') { win.loadURL(' http://localhost:5173/'); } else { if (isLoggedIn) { win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/conversation?id=znwd') } else { win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/login') } // win.loadFile(path.join(__dirname, 'dist', 'index.html')); } // 设置窗口标题 win.setTitle('智库问答助手'); win.on('close', (e) => { if (!app.isQuitting) { e.preventDefault(); win.hide(); } return false; }); win.on('closed', function () { win = null; }); } // 设置登录窗口模式(固定大小,禁止调整) function setLoginWindowMode() { if (win && !win.isDestroyed()) { win.setResizable(false); // 禁止调整大小 win.setMaximizable(false); // 禁用最大化按钮 win.setMinimumSize(1080, 608); // 设置最小尺寸(可选) win.setSize(1080, 608); // 设置为固定尺寸 win.center(); // 窗口居中 win.setTitle('智库问答助手'); isLoggedIn = false; } } // 设置主窗口模式(可调整大小,有最小限制) function setMainWindowMode() { if (win && !win.isDestroyed()) { win.setResizable(true); // 允许调整大小 win.setMaximizable(true); // 启用最大化按钮 win.setMinimumSize(1200, 800); // 设置最小尺寸 win.setTitle('智库问答助手'); isLoggedIn = true; } } // 创建快捷对话窗口 function createSmartWindow() { smart_win = new BrowserWindow({ width: 520, height: 110, // maxHeight: 500, frame: false, icon: iconPath, // 使用平台特定图标 resizable: false, // 禁止调整窗口大小 maximizable: false, // 禁止最大化 webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: true, contextIsolation: true, contentSecurityPolicy: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'" } }); // 禁用默认菜单栏(保留窗口控制按钮) Menu.setApplicationMenu(null); const primaryDisplay = screen.getPrimaryDisplay(); const { width, height } = primaryDisplay.workAreaSize; smart_win.setPosition(width - 660, 100); if (process.env.NODE_ENV === 'development') { smart_win.loadURL('http://localhost:5173/#/smart'); } else { // smart_win.loadFile(path.join(__dirname, 'dist', 'index.html'), { // hash: '/smart' // }); smart_win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/smart') } } // 新增:设置悬浮窗事件监听 function setupFloatingWindowEvents() { if (floatingWindow && !floatingWindow.isDestroyed()) { // 移除旧的事件监听器(如果存在) floatingWindow.removeAllListeners('closed'); // 添加关闭事件处理 floatingWindow.on('closed', () => { floatingWindow = null; }); } } // 新增:切换悬浮球可见性 function toggleFloatingWindow() { if (floatingWindow && !floatingWindow.isDestroyed()) { if (isFloatingWindowVisible) { smart_win?.close() // smart_win?.destroy() floatingWindow?.hide(); hideTooltip(); // 隐藏可能显示的工具提示 } else { floatingWindow?.show(); // 重新设置悬浮窗事件监听 setupFloatingWindowEvents(); } isFloatingWindowVisible = !isFloatingWindowVisible; updateTrayMenu(); // 更新托盘菜单文本 } } // 新增:更新托盘菜单 function updateTrayMenu(show_float_item = true) { if (!tray) return; const menu_list = [ { label: '打开', click: () => { if (win && !win.isDestroyed()) { if (win.isMinimized()) win.restore(); win.show(); win.focus(); } else { createWindow(); } } }, // { // label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球', // click: toggleFloatingWindow // }, { label: '退出', click: () => { app.isQuitting = true; if (floatingWindow) floatingWindow.destroy(); app.quit(); } } ] const float_item = { label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球', click: toggleFloatingWindow } if (show_float_item) { menu_list.splice(1, 0, float_item) } const contextMenu = Menu.buildFromTemplate(menu_list); tray.setContextMenu(contextMenu); } // 创建系统托盘 function createTray() { let iconPath; if (app.isPackaged) { iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png'); } else { iconPath = path.join(__dirname, '/tray-icon.png'); } tray = new Tray(iconPath); updateTrayMenu(); // 使用函数设置菜单 tray.setToolTip('智库问答助手'); tray.on('click', () => { if (win && !win.isDestroyed()) { if (win.isMinimized()) win.restore(); win.show(); win.focus(); } else { createWindow(); } }); } // 创建悬浮窗 function createFloatingWindow() { floatingWindow = new BrowserWindow({ width: 42, height: 42, frame: false, transparent: false, alwaysOnTop: true, skipTaskbar: true, resizable: false, backgroundColor: '#00000000', // 强制有颜色背景,否则 tooltip 不触发 hasShadow: false, transparent: true, webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: true, contextIsolation: true }, type: 'desktop' }); floatingWindow.setAlwaysOnTop(true, 'screen-saver'); // 在macOS有效 if (process.env.NODE_ENV === 'development') { floatingWindow.loadURL('http://localhost:5173/#/floating'); } else { // floatingWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), { // hash: '/floating' // }); floatingWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/floating') } const primaryDisplay = screen.getPrimaryDisplay(); const { width, height } = primaryDisplay.workAreaSize; floatingWindow.setPosition(width - 50, height - 200); // 设置悬浮窗事件监听 setupFloatingWindowEvents(); } // 提示窗口 function showTooltip(adsorbedPosition, x, y) { if (tooltipWindow) return; let tooltipX; if (adsorbedPosition === 0) { // 悬浮球吸附在左侧,tooltip 显示在右侧 tooltipX = x + 50; } else { // 悬浮球吸附在右侧,tooltip 显示在左侧 tooltipX = x - 125; } tooltipWindow = new BrowserWindow({ width: 120, height: 40, x: tooltipX, y: y + 5, frame: false, alwaysOnTop: true, skipTaskbar: true, resizable: false, transparent: true, hasShadow: false, focusable: false, webPreferences: { nodeIntegration: true, contextIsolation: false } }); if (process.env.NODE_ENV === 'development') { tooltipWindow.loadURL(' http://localhost:5173/#/tips'); } else { // tooltipWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), { // hash: '/tips' // }); tooltipWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/tips') } tooltipWindow.once('ready-to-show', () => { tooltipWindow?.showInactive(); }); } function hideTooltip() { if (tooltipWindow) { tooltipWindow.close(); tooltipWindow = null; } } // 监听打开窗口事件 ipcMain.on('open-window', () => { if (win && !win.isDestroyed()) { if (win.isMinimized()) win.restore(); win.show(); win.focus(); } else { createWindow(); } }); // 监听窗口大小变化时间 ipcMain.on('resize-main-window', (event, width, height) => { if (win && !win.isDestroyed()) { // 1. 先退出全屏状态(如果是全屏) if (win.isFullScreen()) { win.setFullScreen(false); // 等待全屏状态变更完成后再调整大小 win.once('leave-full-screen', () => { adjustWindowSize(width, height); }); } // 2. 再恢复窗口(如果是最大化) else if (win.isMaximized()) { win.unmaximize(); // 等待窗口恢复后再调整大小 win.once('unmaximize', () => { adjustWindowSize(width, height); }); } // 3. 直接调整大小(普通状态) else { adjustWindowSize(width, height); } } else { createWindow(width, height); } }); // 提取调整窗口大小的公共逻辑 function adjustWindowSize(width, height) { win.setSize(width, height); win.center(); } ipcMain.on('open-smart-window', () => { if (smart_win && !smart_win.isDestroyed()) { if (smart_win.isMinimized()) smart_win.restore(); smart_win.show(); smart_win.focus(); } else { createSmartWindow(); } }); ipcMain.on('toggle-smart-window', () => { if (smart_win && !smart_win.isDestroyed()) { smart_win.hide(); smart_win.close(); smart_win.destroy() smart_win = null } else { createSmartWindow(); smart_win.focus(); } }); ipcMain.on('close-smart-window', () => { if (smart_win && !smart_win.isDestroyed()) { smart_win.close(); } }); ipcMain.on('resize-smart-window', (event, height) => { if (smart_win && !smart_win.isDestroyed()) { // 获取当前窗口宽度 const [width] = smart_win.getSize(); // 设置新的窗口大小(保持宽度不变,修改高度) smart_win.setSize(width, height); } }); ipcMain.on('set-float-window-position', (event, x, y) => { if (floatingWindow && !floatingWindow.isDestroyed()) { floatingWindow.setBounds({ x, y, width: 50, height: 50 }); } }); ipcMain.handle('get-float-window-position', () => { if (floatingWindow && !floatingWindow.isDestroyed()) { const [x, y] = floatingWindow.getPosition(); return { x, y }; } return { x: 0, y: 0 }; }); ipcMain.handle('get-smart-window-position', () => { if (smart_win && !smart_win.isDestroyed()) { const [x, y] = smart_win.getPosition(); return { x, y }; } return { x: 0, y: 0 }; }); ipcMain.on('set-smart-window-position', (event, x, y) => { if (smart_win && !smart_win.isDestroyed()) { smart_win.setBounds({ x, y }); } }); ipcMain.on('show-tooltip', (event, adsorbedPosition) => { if (!floatingWindow) return; const [x, y] = floatingWindow.getPosition(); showTooltip(adsorbedPosition, x, y); }); ipcMain.on('hide-tooltip', hideTooltip); ipcMain.on('hide-tray-float-window', (event) => { if (floatingWindow && !floatingWindow.isDestroyed()) { if (isFloatingWindowVisible) { if (smart_win) { smart_win?.close() // smart_win?.destroy() floatingWindow?.hide(); hideTooltip(); // 隐藏可能显示的工具提示 } else { floatingWindow?.close() } } updateTrayMenu(false); // 更新托盘菜单文本 } }) ipcMain.on('show-tray-float-window', (event) => { createFloatingWindow(); floatingWindow.focus(); isFloatingWindowVisible = true; updateTrayMenu(); // 更新托盘菜单文本 }) // 新增:监听登录状态变化 ipcMain.on('set-login-state', (event, loggedIn) => { if (loggedIn) { setLoginWindowMode(); } else { setMainWindowMode(); } }); // 封装存储操作 // 保存认证信息 ipcMain.handle('save-auth', (event, username, password, token) => { console.log('Saving auth:', username, password, token); try { console.log('Saving auth:', username, password, token); store.set('username', username); store.set('password', password); store.set('token', token); return { success: true, message: '认证信息保存成功' }; } catch (error) { console.error('Failed to save auth:', error); return new Error('保存认证信息失败: ' + error.message); } }); // 获取用户名 ipcMain.handle('get-username', () => { return store.get('username') || ''; }); // 获取密码 ipcMain.handle('get-password', () => { return store.get('password') || ''; }); // 获取 Token ipcMain.handle('get-token', () => { return store.get('token') || ''; }); // 删除认证信息 ipcMain.handle('clear-auth', () => { // store.delete('username');n store.delete('token'); // store.delete('password') }); ipcMain.on('logout', () => { updateTrayMenu(false) if (smart_win && !smart_win.isDestroyed()) { smart_win.destroy(); smart_win = null; } if (floatingWindow && !floatingWindow.isDestroyed()) { floatingWindow.destroy(); floatingWindow = null; } }); // 显示主窗口 function showMainWindow() { if (win && !win.isDestroyed()) { if (win.isMinimized()) win.restore(); win.show(); win.focus(); } else { createWindow(); } } if (!gotTheLock) { // 如果没有获取到锁,说明已经有一个实例在运行,直接退出当前实例 app.quit(); } else { app.whenReady().then(() => { createWindow(); createTray(); createFloatingWindow(); app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); }); app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit(); }); // 再次启动时,如果有主窗口,则显示主窗口 app.on('second-instance', showMainWindow); }