'use strict'; const Addon = require('ee-core/addon'); const { Controller } = require('ee-core'); const config = require('../config/config.default'); const path = require('path'); const fs = require('fs'); const { ipcMain, app, BrowserWindow, shell, dialog } = require('electron'); const { session } = require('electron'); const CoreWindow = require("ee-core/electron/window"); const Log = require('ee-core/log'); const { spawn } = require('child_process'); /** * example * @class */ class OTAController extends Controller { constructor(ctx) { super(ctx); } async updateVersion(url) { const status = { error: -1, available: 1, noAvailable: 2, downloading: 3, downloaded: 4, }; const win = new BrowserWindow({ show: false }); // 设置下载路径为系统临时目录 win.webContents.downloadURL(url); win.webContents.session.removeAllListeners('will-download'); win.webContents.session.on('will-download', (event, item, webContents) => { // event.preventDefault(); // 设置默认下载路径为系统下载目录 const fileName = item.getFilename(); const downloadPath = path.join(app.getPath('downloads'), fileName); console.log('下载路径:', downloadPath); // 确保目录存在 const dir = path.dirname(downloadPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } if (fs.existsSync(downloadPath)) { fs.unlinkSync(downloadPath); // 删除旧文件 } console.log(item); item.setSavePath(downloadPath); item.on('updated', (event, state) => { Log.info('[addon:updated] 状态: ', state); if (state === 'interrupted') { Log.error('[addon:autoUpdater] 下载中断'); } else if (state === 'progressing') { const receivedBytes = item.getReceivedBytes(); const totalBytes = item.getTotalBytes(); const percentNumber = Math.floor((receivedBytes / totalBytes) * 100); const transferredSize = this.bytesChange(receivedBytes); const totalSize = this.bytesChange(totalBytes); const text = `已下载 ${percentNumber}% (${transferredSize}/${totalSize})`; let info = { status: status.downloading, desc: text, percentNumber: percentNumber, totalSize: totalSize, transferredSize: transferredSize }; Log.info('[addon:updated] 下载进度: ', text); this.sendStatusToWindow(info); } }); item.once('done', (event, state) => { Log.info('[addon:done] 状态: ', state); if (state === 'completed') { Log.info('[addon:autoUpdater] 文件已下载完成: ', item.getSavePath()); let info = { status: status.downloaded, desc: '下载完成', filePath: item.getSavePath() }; this.sendStatusToWindow(info); // 提醒用户选择操作 dialog.showMessageBox({ type: 'info', title: '下载完成', message: '文件已下载完成,请选择操作:', buttons: ['关闭智惠映服装并自动安装', '打开目录手动安装', '取消'] }).then(result => { if (result.response === 0) { // 用户选择“立即安装”,执行安装操作 this.install(item.getSavePath()); } else if (result.response === 1) { // 用户选择“打开目录”,打开文件所在目录 shell.openPath(path.dirname(item.getSavePath())); } }); } else { Log.error('[addon:autoUpdater] 下载失败: ', state); let info = { status: status.error, desc: `下载失败: ${state}` }; this.sendStatusToWindow(info); } win.close(); // 关闭隐藏窗口 }); }); } install(filePath) { // 启动安装程序并脱离主进程 const child = spawn(filePath, [], { detached: true, stdio: 'ignore' }); child.on('error', (err) => { console.error('启动安装程序失败:', err); }); // 让安装程序独立运行后,退出当前应用 child.unref(); app.quit(); } /** * 向前端发消息 */ sendStatusToWindow(content = {}) { const textJson = JSON.stringify(content); const channel = 'app.updater'; this.app.electron['ota'].webContents.send(channel, textJson); /* const win = CoreWindow.getMainWindow(); win.webContents.send(channel, textJson);*/ } /** * 单位转换 */ bytesChange (limit) { let size = ""; if(limit < 0.1 * 1024){ size = limit.toFixed(2) + "B"; }else if(limit < 0.1 * 1024 * 1024){ size = (limit/1024).toFixed(2) + "KB"; }else if(limit < 0.1 * 1024 * 1024 * 1024){ size = (limit/(1024 * 1024)).toFixed(2) + "MB"; }else{ size = (limit/(1024 * 1024 * 1024)).toFixed(2) + "GB"; } let sizeStr = size + ""; let index = sizeStr.indexOf("."); let dou = sizeStr.substring(index + 1 , index + 3); if(dou == "00"){ return sizeStr.substring(0, index) + sizeStr.substring(index + 3, index + 5); } return size; } } OTAController.toString = () => '[class OTAController]'; module.exports = OTAController;