import { app, shell, BrowserWindow, ipcMain, session, BrowserView } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/icon.png?asset' import File from './file' import Logger from './logger' // 日志封装 import chat from './chat' // chat封装 import Store from './store' // Store封装 import updateInit from './update' // 代理 electron/remote // 第一步:引入remote import remote from '@electron/remote/main' // 第二步: 初始化remote remote.initialize() // 日志配置-初始化(日志直接绑定到console上) if(!is.dev) Logger.initialize() // 持久化数据-初始化 Store.initialize() File({ app, shell, BrowserWindow, ipcMain }) process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true' let mainWindow, loginWindow const additionalData = {myKey:'ys_axi_smarttalk'} const gotTheLock = app.requestSingleInstanceLock(additionalData) if(!gotTheLock){ app.quit() }else{ app.on('second-instance',(event,commandLine,workingDirectory,additionalData)=>{ //输入从第二个实例中接收到的数据 console.log(additionalData) //有人试图运行第二个实例,我们应该关注我们的窗口 if(mainWindow){ if(mainWindow.isMinimized()) mainWindow.restore() mainWindow.focus() } if(loginWindow){ if(loginWindow.isMinimized()) loginWindow.restore() loginWindow.focus() } }) } //登录窗口 function createLoginWindow() { if (loginWindow) return loginWindow = new BrowserWindow({ width: 888, height: 520, show: false, frame: false, autoHideMenuBar: true, maximizable: false, resizable: false, icon: join(__dirname, '../../resources/logo2.ico'), ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { defaultEncoding: 'utf-8', preload: join(__dirname, '../preload/index.js'), sandbox: false, nodeIntegration: true, contextIsolation: false // 沙箱取消 } }) loginWindow.type = 'login' // 唯一标识 // handleUpdate(loginWindow,ipcMain) // const loginURL = is.dev ? `http://localhost:5173/#/login` : `file://${__dirname}/index.html/#/login` // loginWindow.loadURL(loginURL) if (is.dev && process.env['ELECTRON_RENDERER_URL']) { loginWindow.loadURL('http://localhost:5173/#/login') } else { loginWindow.loadFile(join(__dirname, '../renderer/index.html'), { hash: 'login' }) updateInit(loginWindow) } if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') loginWindow.webContents.openDevTools() loginWindow.once('ready-to-show', () => { loginWindow.show() }) loginWindow.on('closed', () => { loginWindow = null }) remote.enable(loginWindow.webContents) } //主窗口 function createMainWindow() { mainWindow = new BrowserWindow({ width: 1350, minWidth: 1370, height: 700, minHeight: 700, show: false, frame: false, // 无边框 autoHideMenuBar: true, maximizable: false, icon: join(__dirname, '../../resources/logo2.ico'), ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { defaultEncoding: 'utf-8', preload: join(__dirname, '../preload/index.js'), sandbox: false, // nodeIntegration: true, nodeIntegration: true, // nodeApi调用 contextIsolation: false // 沙箱取消 // webSecurity: false // 跨域关闭 } }) mainWindow.type = 'main' // 唯一标识 mainWindow.on('ready-to-show', () => { mainWindow.show() }) mainWindow.on('closed', () => { setTimeout(() => { // 延迟销毁 mainWindow = null }, 1000) // app.quit() // 主窗口关闭-结束所有进程 }) mainWindow.on('resize', () => { const { width, height } = mainWindow.getBounds(); mainWindow.webContents.send('minWinResize', { width, height }); }); mainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') mainWindow.webContents.openDevTools() if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) } else { mainWindow.loadFile(join(__dirname, '../renderer/index.html')) } // mainWindow.setAlwaysOnTop(true, "screen-saver") // 将窗口设置为顶层窗口 // mainWindow.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见 // mainWindow.maximize(); // 第三步: 开启remote服务 remote.enable(mainWindow.webContents) } // 打开外部链接窗口 let linkWin = {} async function createLinkWin(data) { if (linkWin[data.key]) return linkWin[data.key] = new BrowserWindow({ show: false, frame: true, maximizable: true, autoHideMenuBar: true, ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { defaultEncoding: 'utf-8', sandbox: false, nodeIntegration: true, worldSafeExecuteJavaScript: true, contextIsolation: true } }) linkWin[data.key].type = 'link'+data.key // 唯一标识 let cookieDetails = { ...data.cookieData } await linkWin[data.key].webContents.session.cookies .set(cookieDetails) .then(() => {}) .catch((error) => {}) data.fullPath = data.fullPath.replaceAll('//', '/') if (data.fullPath.indexOf('?') !== -1) { data.fullPath += '&urlSource=smarttalk&t' + Date.now() }else { data.fullPath += '?urlSource=smarttalk&t' + Date.now() } linkWin[data.key].loadURL(data.fullPath) linkWin[data.key].once('ready-to-show', () => { linkWin[data.key].show() linkWin[data.key].maximize() }) linkWin[data.key].on('closed', () => { linkWin[data.key] = null delete linkWin[data.key] }) } // 初始化完成 app.on('ready', () => { appWatchError() // 监听app错误 process.env.LANG = 'en_US.UTF-8' // 设置应用程序用户模型标识符 electronApp.setAppUserModelId('com.electron') //一个新的browserWindow 被创建时触发 app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window) }) //窗口 最大、最小、关闭 ipcMain.on('minimize-window', () => { if (loginWindow) { loginWindow.minimize() } if (mainWindow) { mainWindow.minimize() } }) ipcMain.on('maximize-window', () => { mainWindow.isMaximized() ? mainWindow.unmaximize() : mainWindow.maximize() }) ipcMain.on('close-window', () => { if (loginWindow) { loginWindow.destroy() } if (mainWindow) { mainWindow.close() // 先发出这个关闭指令 setTimeout(() => { // mainWindow.destroy() }, 200) } }) // 打开主窗口 ipcMain.on('openMainWindow', () => { if (!mainWindow) { createMainWindow() } loginWindow.destroy() loginWindow = null }) // 打开登录窗口 ipcMain.on('openLoginWindow', () => { if (!loginWindow) { createLoginWindow() } mainWindow.destroy() mainWindow = null loginWindow.show() loginWindow.focus() }) //打开作业窗口 ipcMain.on('openWindow', (e, data) => { createLinkWin(data) }) // zdg: 消息监听 handleAll() // 打开-登录窗口 createLoginWindow() app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createLoginWindow() }) }) // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) // 监听全局事件 function handleAll() { const chatInstance = chat.initialize() // im-chat 实例 // 新窗口创建-监听 ipcMain.handle('new-window', (e, data) => { const { id, type } = data const win = BrowserWindow.fromId(id) win.type = type // 绑定独立标识 remote.enable(win.webContents) // 开启远程服务 chatInstance.enable(win.webContents) // 开启im-chat console.log(`主进程 [${type}]: 窗口注册-远程代理-完毕(${Date.now()})`) }) // 用于监听-状态管理变化-同步所有窗口 ipcMain.handle('pinia-state-change', (e, storeName, jsonStr) => { for(const curWin of BrowserWindow.getAllWindows()){ const id = curWin.webContents.id const bool = id !== e.sender.id && !curWin.isDestroyed() if (bool) { // 除了消息发送窗口和销毁的窗口 其他都发送 curWin.webContents.send('pinia-state-set', storeName, jsonStr) } } }) // 用于监听-状态管理变化-初始同步 ipcMain.handle('pinia-state-init', (e, wid, storeName, jsonStr) => { // console.log('pinia-state-init', jsonStr) const win = BrowserWindow.fromId(wid) win.webContents.send('pinia-state-set', storeName, jsonStr) }) } // app 崩溃监听器 function appWatchError() { // 渲染进程崩溃 app.on('renderer-process-crashed', (event, webContents, killed) => { console.error( `APP-ERROR:renderer-process-crashed; event: ${JSON.stringify(event)}; webContents:${JSON.stringify( webContents )}; killed:${JSON.stringify(killed)}` ) }) // GPU进程崩溃 app.on('gpu-process-crashed', (event, killed) => { console.error(`APP-ERROR:gpu-process-crashed; event: ${JSON.stringify(event)}; killed: ${JSON.stringify(killed)}`) }) // 渲染进程结束 app.on('render-process-gone', async (event, webContents, details) => { console.error( `APP-ERROR:render-process-gone; event: ${JSON.stringify(event)}; webContents:${JSON.stringify( webContents )}; details:${JSON.stringify(details)}` ) }) // 子进程结束 app.on('child-process-gone', async (event, details) => { console.error(`APP-ERROR:child-process-gone; event: ${JSON.stringify(event)}; details:${JSON.stringify(details)}`) }) }