const { app, BrowserWindow, ipcMain, net, shell } = require('electron'); const path = require('path'); const url = require('url'); const fs = require('fs'); const { spawn } = require('child_process'); // 用于启动子进程 let win = null; // 创建窗口 const createWindow = () => { win = new BrowserWindow({ // width: 1200, // height: 800, show: false, // 是否显示窗口 autoHideMenuBar: true, // 隐藏菜单栏 webPreferences: { nodeIntegration: true, // 是否集成 Node.js // enableRemoteModule: true, // 是否启用 remote 模块 webSecurity: false, // 是否禁用同源策略 preload: path.join(__dirname, 'preload.js'), // 预加载脚本 }, }); win.loadURL( url.format({ pathname: path.join(__dirname, './dist', 'index.html'), protocol: 'file:', slashes: true, // true: file://, false: file: hash: '/login', // /image_change 图片切换页 }), ); win.once('ready-to-show', () => { win.maximize(); win.show(); }); // 拦截当前窗口的导航,防止外部链接在应用内打开 win.webContents.on('will-navigate', (event, url) => { if (url.startsWith('http://') || url.startsWith('https://')) { event.preventDefault(); shell.openExternal(url); } }); }; // 当 Electron 完成初始化并准备创建浏览器窗口时调用此方法 app.whenReady().then(() => { createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); // 检查更新 ipcMain.handle('check-update', async () => { const apiUrl = 'https://your-api.com/api/app/latest'; // <-- 替换为真实接口 const currentVersion = app.getVersion(); return new Promise((resolve, reject) => { const req = net.request(apiUrl); let body = ''; req.on('response', (res) => { res.on('data', (chunk) => (body += chunk)); res.on('end', () => { try { const latest = JSON.parse(body); const update = latest.version && latest.version !== currentVersion; resolve({ update, latest, currentVersion }); } catch (e) { reject(e); } }); }); req.on('error', (err) => reject(err)); req.end(); }); }); // 下载更新(渲染进程发起),主进程负责流式保存并推送进度 ipcMain.on('download-update', (event, downloadUrl) => { const win = BrowserWindow.getAllWindows()[0]; const filename = path.basename(downloadUrl).split('?')[0] || `update-${Date.now()}.exe`; const tmpPath = path.join(app.getPath('temp'), filename); const fileStream = fs.createWriteStream(tmpPath); const req = net.request(downloadUrl); let received = 0; let total = 0; req.on('response', (res) => { total = parseInt(res.headers['content-length'] || res.headers['Content-Length'] || '0'); res.on('data', (chunk) => { received += chunk.length; fileStream.write(chunk); win.webContents.send('update-download-progress', { received, total }); }); res.on('end', () => { fileStream.end(); win.webContents.send('update-downloaded', { path: tmpPath }); }); }); req.on('error', (err) => { win.webContents.send('update-error', { message: err.message || String(err) }); }); req.end(); }); // 安装更新(渲染进程确认安装时调用) ipcMain.on('install-update', (event, filePath) => { if (!fs.existsSync(filePath)) { event.sender.send('update-error', { message: '安装文件不存在' }); return; } if (process.platform === 'win32') { // Windows:直接执行安装程序(根据你的安装包参数添加静默/等待参数) try { spawn(filePath, [], { detached: true, stdio: 'ignore' }).unref(); app.quit(); } catch (e) { event.sender.send('update-error', { message: e.message }); } } else if (process.platform === 'darwin') { // macOS:打开 dmg 或者打开 .pkg shell.openPath(filePath).then(() => app.quit()); } else { // linux:按照需要实现 shell.openPath(filePath).then(() => app.quit()); } }); // 当所有窗口都已关闭时退出 app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });