ota.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. 'use strict';
  2. const Addon = require('ee-core/addon');
  3. const { Controller } = require('ee-core');
  4. const config = require('../config/config.default');
  5. const path = require('path');
  6. const fs = require('fs');
  7. const { ipcMain, app, BrowserWindow, shell, dialog } = require('electron');
  8. const { session } = require('electron');
  9. const CoreWindow = require("ee-core/electron/window");
  10. const Log = require('ee-core/log');
  11. const { spawn } = require('child_process');
  12. /**
  13. * example
  14. * @class
  15. */
  16. class OTAController extends Controller {
  17. constructor(ctx) {
  18. super(ctx);
  19. }
  20. async updateVersion(url) {
  21. const status = {
  22. error: -1,
  23. available: 1,
  24. noAvailable: 2,
  25. downloading: 3,
  26. downloaded: 4,
  27. };
  28. const win = new BrowserWindow({ show: false });
  29. // 设置下载路径为系统临时目录
  30. win.webContents.downloadURL(url);
  31. win.webContents.session.on('will-download', (event, item, webContents) => {
  32. item.on('updated', (event, state) => {
  33. Log.info('[addon:updated] 状态: ', state);
  34. if (state === 'interrupted') {
  35. Log.error('[addon:autoUpdater] 下载中断');
  36. } else if (state === 'progressing') {
  37. const receivedBytes = item.getReceivedBytes();
  38. const totalBytes = item.getTotalBytes();
  39. const percentNumber = Math.floor((receivedBytes / totalBytes) * 100);
  40. const transferredSize = this.bytesChange(receivedBytes);
  41. const totalSize = this.bytesChange(totalBytes);
  42. const text = `已下载 ${percentNumber}% (${transferredSize}/${totalSize})`;
  43. let info = {
  44. status: status.downloading,
  45. desc: text,
  46. percentNumber: percentNumber,
  47. totalSize: totalSize,
  48. transferredSize: transferredSize
  49. };
  50. Log.info('[addon:updated] 下载进度: ', text);
  51. this.sendStatusToWindow(info);
  52. }
  53. });
  54. item.once('done', (event, state) => {
  55. Log.info('[addon:done] 状态: ', state);
  56. if (state === 'completed') {
  57. Log.info('[addon:autoUpdater] 文件已下载完成: ', item.getSavePath());
  58. let info = {
  59. status: status.downloaded,
  60. desc: '下载完成',
  61. filePath: item.getSavePath()
  62. };
  63. this.sendStatusToWindow(info);
  64. // 提醒用户选择操作
  65. dialog.showMessageBox({
  66. type: 'info',
  67. title: '下载完成',
  68. message: '文件已下载完成,请选择操作:',
  69. buttons: ['立即安装', '打开目录', '取消']
  70. }).then(result => {
  71. if (result.response === 0) {
  72. // 用户选择“立即安装”,执行安装操作
  73. this.install(item.getSavePath());
  74. } else if (result.response === 1) {
  75. // 用户选择“打开目录”,打开文件所在目录
  76. shell.openPath(path.dirname(item.getSavePath()));
  77. }
  78. });
  79. } else {
  80. Log.error('[addon:autoUpdater] 下载失败: ', state);
  81. let info = {
  82. status: status.error,
  83. desc: `下载失败: ${state}`
  84. };
  85. this.sendStatusToWindow(info);
  86. }
  87. win.close(); // 关闭隐藏窗口
  88. });
  89. });
  90. }
  91. install(filePath) {
  92. // 启动安装程序并脱离主进程
  93. const child = spawn(filePath, [], {
  94. detached: true,
  95. stdio: 'ignore'
  96. });
  97. child.on('error', (err) => {
  98. console.error('启动安装程序失败:', err);
  99. });
  100. // 让安装程序独立运行后,退出当前应用
  101. child.unref();
  102. app.quit();
  103. }
  104. /**
  105. * 向前端发消息
  106. */
  107. sendStatusToWindow(content = {}) {
  108. const textJson = JSON.stringify(content);
  109. const channel = 'app.updater';
  110. const win = CoreWindow.getMainWindow();
  111. win.webContents.send(channel, textJson);
  112. }
  113. /**
  114. * 单位转换
  115. */
  116. bytesChange (limit) {
  117. let size = "";
  118. if(limit < 0.1 * 1024){
  119. size = limit.toFixed(2) + "B";
  120. }else if(limit < 0.1 * 1024 * 1024){
  121. size = (limit/1024).toFixed(2) + "KB";
  122. }else if(limit < 0.1 * 1024 * 1024 * 1024){
  123. size = (limit/(1024 * 1024)).toFixed(2) + "MB";
  124. }else{
  125. size = (limit/(1024 * 1024 * 1024)).toFixed(2) + "GB";
  126. }
  127. let sizeStr = size + "";
  128. let index = sizeStr.indexOf(".");
  129. let dou = sizeStr.substring(index + 1 , index + 3);
  130. if(dou == "00"){
  131. return sizeStr.substring(0, index) + sizeStr.substring(index + 3, index + 5);
  132. }
  133. return size;
  134. }
  135. }
  136. OTAController.toString = () => '[class OTAController]';
  137. module.exports = OTAController;