Browse Source

重写所有插件

gaoshuaixing 3 years ago
parent
commit
c78de0a614

+ 165 - 0
electron/addon/autoUpdater/index.js

@@ -0,0 +1,165 @@
+const { app } = require('electron');
+const { autoUpdater } = require("electron-updater");
+const is = require('electron-is');
+
+/**
+ * 自动升级插件
+ * @class
+ */
+class AutoUpdaterAddon {
+
+  constructor(app) {
+    this.app = app;
+    this.cfg = app.config.addons.autoUpdater;
+    this.mainWindow = app.electron.mainWindow;
+  }
+
+  /**
+   * 创建
+   */
+  create () {
+    this.app.console.info('[addon:autoUpdater] load');
+
+    if ((is.windows() && this.cfg.windows)
+        || (is.macOS() && this.cfg.macOS)
+        || (is.linux() && this.cfg.linux))
+    {
+      // continue
+    } else {
+      return
+    }
+
+    // 是否检查更新
+    if (this.cfg.force) {
+      this.checkUpdate();
+    }
+
+    const status = {
+      error: -1,
+      available: 1,
+      noAvailable: 2,
+      downloading: 3,
+      downloaded: 4,
+    }
+
+    const updateConfig = this.cfg;
+    const version = app.getVersion();
+    this.app.logger.info('[addon:autoUpdater] current version: ', version);
+  
+    // 设置下载服务器地址
+    let server = updateConfig.options.url;
+    let lastChar = server.substring(server.length - 1);
+    server = lastChar === '/' ? server : server + "/";
+    //this.app.logger.info('[addon:autoUpdater] server: ', server);
+    updateConfig.options.url = server;
+  
+    // 是否后台自动下载
+    autoUpdater.autoDownload = updateConfig.force ? true : false;
+    // if (Utils.getEnv() == 'local') {
+    //   autoUpdater.updateConfigPath = path.join(__dirname, '../../out/dev-app-update.yml')
+    // }
+  
+    try {
+      autoUpdater.setFeedURL(updateConfig.options);
+    } catch (error) {
+      this.app.logger.error('[addon:autoUpdater] setFeedURL error : ', error);
+    }
+  
+    autoUpdater.on('checking-for-update', () => {
+      //sendStatusToWindow('正在检查更新...');
+    })
+    autoUpdater.on('update-available', (info) => {
+      info.status = status.available;
+      info.desc = '有可用更新';
+      this.sendStatusToWindow(info);
+    })
+    autoUpdater.on('update-not-available', (info) => {
+      info.status = status.noAvailable;
+      info.desc = '没有可用更新';
+      this.sendStatusToWindow(info);
+    })
+    autoUpdater.on('error', (err) => {
+      let info = {
+        status: status.error,
+        desc: err
+      }
+      this.sendStatusToWindow(info);
+    })
+    autoUpdater.on('download-progress', (progressObj) => {
+      let percentNumber = parseInt(progressObj.percent);
+      let totalSize = this.bytesChange(progressObj.total);
+      let transferredSize = this.bytesChange(progressObj.transferred);
+      let text = '已下载 ' + percentNumber + '%';
+      text = text + ' (' + transferredSize + "/" + totalSize + ')';
+  
+      let info = {
+        status: status.downloading,
+        desc: text,
+        percentNumber: percentNumber,
+        totalSize: totalSize,
+        transferredSize: transferredSize
+      }
+      this.app.logger.info('[addon:autoUpdater] progress: ', text);
+      this.sendStatusToWindow(info);
+    })
+    autoUpdater.on('update-downloaded', (info) => {
+      info.status = status.downloaded;
+      info.desc = '下载完成';
+      this.sendStatusToWindow(info);
+      // quit and update
+      this.app.appQuit();
+      autoUpdater.quitAndInstall();
+    });
+  }
+
+  /**
+   * 检查更新
+   */
+  checkUpdate () {
+    autoUpdater.checkForUpdates();
+  }
+  
+  /**
+   * 下载更新
+   */
+  download () {
+    autoUpdater.downloadUpdate();
+  }
+
+  /**
+   * 向前端发消息
+   */
+  sendStatusToWindow(content = {}) {
+    const textJson = JSON.stringify(content);
+    const channel = 'app.updater';
+    this.mainWindow.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;
+  }  
+}
+
+AutoUpdaterAddon.toString = () => '[class AutoUpdaterAddon]';
+module.exports = AutoUpdaterAddon;

+ 67 - 0
electron/addon/awaken/index.js

@@ -0,0 +1,67 @@
+const electronApp = require('electron').app;
+
+/**
+ * 唤醒插件
+ * @class
+ */
+class AwakenAddon {
+
+  constructor(app) {
+    this.app = app;
+    this.cfg = app.config.addons.awaken;
+    this.protocol = '';
+  }
+
+  /**
+   * 创建
+   */
+  create () {
+    this.app.console.info('[addon:awaken] load');
+
+    this.protocol = this.cfg.protocol;
+  
+    electronApp.setAsDefaultProtocolClient(this.protocol);
+  
+    const self = this;
+    this.handleArgv(process.argv);
+    electronApp.on('second-instance', (event, argv) => {
+      if (process.platform === 'win32') {
+        self.handleArgv(argv)
+      }
+    })
+  
+    // 仅用于macOS
+    electronApp.on('open-url', (event, urlStr) => {
+      self.handleUrl(urlStr)
+    })
+  }
+
+  /**
+   * 参数处理
+   */  
+  handleArgv(argv) {
+    const offset = electronApp.isPackaged ? 1 : 2;
+    const url = argv.find((arg, i) => i >= offset && arg.startsWith(this.protocol));
+    this.handleUrl(url)
+  }
+
+  /**
+   * url解析
+   */
+  handleUrl(awakeUrlStr) {
+    if (!awakeUrlStr || awakeUrlStr.length === 0) {
+      return
+    }
+    const {hostname, pathname, search} = new URL(awakeUrlStr);
+    let awakeUrlInfo = {
+      urlStr: awakeUrlStr,
+      urlHost: hostname,
+      urlPath: pathname,
+      urlParams: search && search.slice(1)
+    }
+    this.app.logger.info('[addon:awaken] awakeUrlInfo:', awakeUrlInfo);
+  }
+}
+
+AwakenAddon.toString = () => '[class AwakenAddon]';
+module.exports = AwakenAddon;

+ 39 - 32
electron/library/chromeExtension.js → electron/addon/chromeExtension/index.js

@@ -1,35 +1,39 @@
-'use strict';
-
 const { app, session } = require('electron');
 const _ = require('lodash');
 const fs = require('fs');
 const path = require('path');
 
 /**
- * chrome扩展模块
+ * 安全插件
+ * @class
  */
-module.exports = {
+class ChromeExtensionAddon {
+
+  constructor(app) {
+    this.app = app;
+  }
 
   /**
-   * 安装
-   */   
-  async install () {
-    console.log('[preload] load chrome extension module');
+   * 创建
+   */
+  async create () {
+    this.app.console.info('[addon:chromeExtension] load');
+
     const extensionIds = this.getAllIds();
     for (let i = 0; i < extensionIds.length; i++) {
       await this.load(extensionIds[i]);
     }
-  },
+  }
 
   /**
    * 获取扩展id列表(crx解压后的目录名,即是该扩展的id)
    */
   getAllIds () {
     const extendsionDir = this.getDirectory();
-    const ids = getDirs(extendsionDir);
+    const ids = this.getDirs(extendsionDir);
 
     return ids;
-  },
+  }
 
   /**
    * 扩展所在目录
@@ -43,7 +47,7 @@ module.exports = {
     extensionDirPath = path.join(app.getAppPath(), variablePath, "extraResources", "chromeExtension");
   
     return extensionDirPath;
-  },
+  }
 
   /**
    * 加载扩展
@@ -55,33 +59,36 @@ module.exports = {
     
     try {
       const extensionPath = path.join(this.getDirectory(), extensionId);
-      console.log('[chromeExtension] [load] extensionPath:', extensionPath);
+      console.log('[addon:chromeExtension] extensionPath:', extensionPath);
       await session.defaultSession.loadExtension(extensionPath, { allowFileAccess: true });
     } catch (e) {
-     console.log('[chromeExtension] [load] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
+      console.log('[addon:chromeExtension] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
       return false
     }
   
     return true
   }
-}
+  
+  /**
+   * 获取目录下所有文件夹
+   */
+  getDirs(dir) {
+    if (!dir) {
+      return [];
+    }
 
-/**
- * 获取目录下所有文件夹
- */
-function getDirs(dir) {
-  if (!dir) {
-    return [];
-  }
+    const components = [];
+    const files = fs.readdirSync(dir);
+    files.forEach(function(item, index) {
+      const stat = fs.lstatSync(dir + '/' + item);
+      if (stat.isDirectory() === true) {
+        components.push(item);
+      }
+    });
 
-  const components = [];
-  const files = fs.readdirSync(dir);
-  files.forEach(function(item, index) {
-    const stat = fs.lstatSync(dir + '/' + item);
-    if (stat.isDirectory() === true) {
-      components.push(item);
-    }
-  });
+    return components;
+  };
+}
 
-  return components;
-};
+ChromeExtensionAddon.toString = () => '[class ChromeExtensionAddon]';
+module.exports = ChromeExtensionAddon;

+ 30 - 0
electron/addon/security/index.js

@@ -0,0 +1,30 @@
+/**
+ * 安全插件
+ * @class
+ */
+class SecurityAddon {
+
+  constructor(app) {
+    this.app = app;
+  }
+
+  /**
+   * 创建
+   */
+  create () {
+    this.app.console.info('[addon:security] load');
+    const runWithDebug = process.argv.find(function(e){
+      let isHasDebug = e.includes("--inspect") || e.includes("--inspect-brk") || e.includes("--remote-debugging-port");
+      return isHasDebug;
+    })
+  
+    // 不允许远程调试
+    if (runWithDebug) {
+      this.app.logger.error('[error] Remote debugging is not allowed,  runWithDebug:', runWithDebug);
+      this.app.appQuit();
+    }
+  }
+}
+
+SecurityAddon.toString = () => '[class SecurityAddon]';
+module.exports = SecurityAddon;

+ 65 - 0
electron/addon/tray/index.js

@@ -0,0 +1,65 @@
+const {Tray, Menu} = require('electron');
+const path = require('path');
+
+/**
+ * 托盘插件
+ * @class
+ */
+class TrayAddon {
+
+  constructor(app) {
+    this.app = app;
+    this.cfg = app.config.addons.tray;
+    this.tray = null;
+  }
+
+  /**
+   * 创建托盘
+   */
+  create () {
+    // 开发环境,代码热更新开启时,会导致托盘中有残影
+    if (process.env.EE_SERVER_ENV == 'local' && process.env.HOT_RELOAD == 'true') return;
+    
+    this.app.console.info('[addon:tray] load');
+    const mainWindow = this.app.electron.mainWindow;
+
+    // 托盘图标
+    let iconPath = path.join(this.app.config.homeDir, this.cfg.icon);
+  
+    // 托盘菜单功能列表
+    const self = this;
+    let trayMenuTemplate = [
+      {
+        label: '显示',
+        click: function () {
+          mainWindow.show();
+        }
+      },
+      {
+        label: '退出',
+        click: function () {
+          self.app.appQuit();
+        }
+      }
+    ]
+  
+    // 点击关闭,最小化到托盘
+    mainWindow.on('close', (event) => {
+      const extraObj = this.app.electron.extra;
+      if (extraObj.closeWindow == true) {
+        return;
+      }
+      mainWindow.hide();
+      event.preventDefault();
+    });
+    
+    // 实例化托盘
+    this.tray = new Tray(iconPath);
+    this.tray.setToolTip(this.cfg.title);
+    const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
+    this.tray.setContextMenu(contextMenu);
+  }
+}
+
+TrayAddon.toString = () => '[class TrayAddon]';
+module.exports = TrayAddon;

+ 38 - 35
electron/config/config.default.js

@@ -143,38 +143,13 @@ module.exports = (appInfo) => {
   };
 
   /**
-   * 应用自动升级 (可选)
-   */   
-  config.autoUpdate = {
-    windows: false, // windows平台
-    macOS: false, // macOs 需要签名验证
-    linux: false, // linux平台
-    options: {
-      provider: 'generic', // or github, s3, bintray
-      url: 'http://kodo.qiniu.com/' // resource dir, end with '/'
-    },
-    force: false, // 强制更新(运行软件时,检查新版本并后台下载安装)
-  };
-
-  /**
-   * 被浏览器唤醒 (可选)
-   */     
-  config.awakeProtocol = {
-    protocol: 'ee', // 自定义协议名(默认你的应用名称-英文)
-    args: []
-  };
-
-  /**
-   * 托盘 (可选)
-   */    
-  config.tray = {
-    title: 'EE程序', // 托盘显示标题
-    icon: '/public/images/tray_logo.png' // 托盘图标
-  };
-
-  /**
    * 插件功能
    * window 官方内置插件
+   * tray 托盘插件
+   * security 安全插件
+   * awaken 唤醒插件
+   * autoUpdater 自动升级插件
+   * javaServer java项目插件
    * example demo插件
    */
   config.addons = {
@@ -182,16 +157,44 @@ module.exports = (appInfo) => {
     window: {
       enable: true,
     },
+    // 托盘
+    tray: {
+      enable: true,
+      title: 'EE程序', // 托盘显示标题
+      icon: '/public/images/tray_logo.png' // 托盘图标
+    },
+    // 安全
+    security: {
+      enable: true,
+    },
+    // 唤醒
+    awaken: {
+      enable: true,
+      protocol: 'ee', // 自定义协议名(默认你的应用名称-英文)
+      args: []
+    },
+    // 自动升级
+    autoUpdater: {
+      enable: true,
+      windows: true, // windows平台
+      macOS: false, // macOs 需要签名验证
+      linux: false, // linux平台
+      options: {
+        provider: 'generic', // or github, s3, bintray
+        url: 'http://kodo.qiniu.com/' // resource dir, end with '/'
+      },
+      force: false, // 强制更新(运行软件时,检查新版本并后台下载安装)
+    },      
     // java服务
     javaServer: {
-      enable: true,  // 是否启用,true时,启动程序时,会自动启动 build/extraResources/java-app.jar 下的 java程序
-      port: 18080,    // 端口,端口被占用时随机一个端口,并通知前端修改请求地址。
-      jreVersion: 'jre1.8.0_201', // build/extraResources/目录下 jre 文件夹名称
+      enable: false,
+      port: 18080,    // 默认端口(如果端口被使用,则随机获取一个)
+      jreVersion: 'jre1.8.0_201', // 额外资源目录下 jre 文件夹名称
       opt: '-server -Xms512M -Xmx512M -Xss512k -Dspring.profiles.active=prod -Dserver.port=${port} -Dlogging.file.path="${path}" ',
-      name: 'java-app.jar' // build/extraResources/目录下 jar 名称
+      name: 'java-app.jar' // 额外资源目录下 jar 名称
     },
     example: {
-      enable: true, 
+      enable: true,
     },
   };
 

+ 7 - 38
electron/controller/example.js

@@ -3,14 +3,11 @@
 const _ = require('lodash');
 const path = require('path');
 const fs = require('fs');
-const is = require('electron-is');
 const { exec } = require('child_process');
-const Controller = require('ee-core').Controller;
-const Utils = require('ee-core').Utils;
+const { Controller, Utils } = require('ee-core');
 const electronApp = require('electron').app;
-const {dialog, webContents, shell, BrowserWindow, BrowserView, 
+const {dialog, shell, BrowserView, 
   Notification, powerMonitor, screen, nativeTheme} = require('electron');
-const autoLaunchManager = require('../library/autoLaunch');
 const dayjs = require('dayjs');
 
 let myTimer = null;
@@ -453,28 +450,6 @@ class ExampleController extends Controller {
   }  
 
   /**
-   * 开机启动-开启
-   */
-  autoLaunch (type) {
-    console.log('type:', type);
-    let res = {
-      type: type,
-      status: null
-    };
-    if (type == 'check') {
-      res.status = autoLaunchManager.isEnabled();
-    } else if (type == 'open') {
-      autoLaunchManager.enable();
-      res.status = true;
-    } else if (type == 'close') {
-      autoLaunchManager.disable();
-      res.status = false;
-    }
-
-    return res
-  }
-
-  /**
    * 获取系统主题
    */
   getTheme () {
@@ -503,12 +478,9 @@ class ExampleController extends Controller {
   /**
    * 检查是否有新版本
    */
-  checkForUpdater () {
-    const config = this.app.config.autoUpdate;
-    if ( (is.windows() && config.windows) || (is.macOS() && config.macOS) || (is.linux() && config.linux) ) {
-      const autoUpdater = require('../library/autoUpdater');
-      autoUpdater.checkUpdate();
-    }    
+  checkForUpdater () { 
+    const autoUpdaterAddon = this.app.addon.autoUpdater;
+    autoUpdaterAddon.checkUpdate();  
 
     return;
   }
@@ -517,11 +489,8 @@ class ExampleController extends Controller {
    * 下载新版本
    */
   downloadApp () {
-    const config = this.app.config.autoUpdate;
-    if ( (is.windows() && config.windows) || (is.macOS() && config.macOS) || (is.linux() && config.linux) ) {
-      const autoUpdater = require('../library/autoUpdater');
-      autoUpdater.download();
-    }  
+    const autoUpdaterAddon = this.app.addon.autoUpdater;
+    autoUpdaterAddon.download();
     return;
   }
 

+ 0 - 46
electron/library/autoLaunch.js

@@ -1,46 +0,0 @@
-'use strict';
-
-const { app } = require('electron');
-const LOGIN_SETTING_OPTIONS = {
-  // For Windows
-  args: [
-    '--opened-at-login=1'
-  ]
-}
-
-/**
- * 开机启动模块
- */
-module.exports = {
-
-  /**
-   * 设置为开机启动
-   */ 
-  enable () {
-    const enabled = app.getLoginItemSettings(LOGIN_SETTING_OPTIONS).openAtLogin;
-    if (enabled) {
-      return true;
-    }
-    app.setLoginItemSettings({
-      ...LOGIN_SETTING_OPTIONS,
-      openAtLogin: true
-    })
-    return true;
-  },
-  
-  /**
-   * 关闭开机启动
-   */   
-  disable () {
-    app.setLoginItemSettings({ openAtLogin: false })
-    return true;
-  },
-
-  /**
-   * 检查是否开启
-   */   
-  isEnabled () {
-    const enabled = app.getLoginItemSettings(LOGIN_SETTING_OPTIONS).openAtLogin;
-    return enabled;
-  }
-}

+ 0 - 147
electron/library/autoUpdater.js

@@ -1,147 +0,0 @@
-'use strict';
-
-const {app} = require('electron');
-const updater = require("electron-updater");
-const autoUpdater = updater.autoUpdater;
-const path = require('path');
-
-/**
- * 自动升级模块
- */
-module.exports = {
-
-  /**
-   * 安装
-   */
-  install (eeApp) {
-    eeApp.logger.info('[preload] load AutoUpdater module');
-
-    const status = {
-      error: -1,
-      available: 1,
-      noAvailable: 2,
-      downloading: 3,
-      downloaded: 4,
-    }
-
-    const updateConfig = eeApp.config.autoUpdate;
-    const mainWindow = eeApp.electron.mainWindow;
-    const version = app.getVersion();
-    eeApp.logger.info('[preload:autoUpdater] current version: ', version);
-  
-    // 设置下载服务器地址
-    let server = updateConfig.options.url;
-    let lastChar = server.substring(server.length - 1);
-    server = lastChar === '/' ? server : server + "/";
-    eeApp.logger.info('[preload:autoUpdater] server: ', server);
-    updateConfig.options.url = server;
-  
-    // 是否后台自动下载
-    autoUpdater.autoDownload = updateConfig.force ? true : false;
-    if (process.env.EE_SERVER_ENV == 'local') {
-      autoUpdater.updateConfigPath = path.join(__dirname, '../../out/dev-app-update.yml')
-    }
-  
-    try {
-      autoUpdater.setFeedURL(updateConfig.options);
-    } catch (error) {
-      eeApp.logger.error('[preload:autoUpdater] setFeedURL error : ', error);
-    }
-  
-    autoUpdater.on('checking-for-update', () => {
-      //sendStatusToWindow('正在检查更新...');
-    })
-    autoUpdater.on('update-available', (info) => {
-      info.status = status.available;
-      info.desc = '有可用更新';
-      sendStatusToWindow(mainWindow, info);
-    })
-    autoUpdater.on('update-not-available', (info) => {
-      info.status = status.noAvailable;
-      info.desc = '没有可用更新';
-      sendStatusToWindow(mainWindow, info);
-    })
-    autoUpdater.on('error', (err) => {
-      let info = {
-        status: status.error,
-        desc: err
-      }
-      sendStatusToWindow(mainWindow, info);
-    })
-    autoUpdater.on('download-progress', (progressObj) => {
-      let percentNumber = parseInt(progressObj.percent);
-      let totalSize = bytesChange(progressObj.total);
-      let transferredSize = bytesChange(progressObj.transferred);
-      let text = '已下载 ' + percentNumber + '%';
-      text = text + ' (' + transferredSize + "/" + totalSize + ')';
-  
-      let info = {
-        status: status.downloading,
-        desc: text,
-        percentNumber: percentNumber,
-        totalSize: totalSize,
-        transferredSize: transferredSize
-      }
-      eeApp.logger.info('[preload:download-progress] progress: ', text);
-      sendStatusToWindow(mainWindow, info);
-    })
-    autoUpdater.on('update-downloaded', (info) => {
-      info.status = status.downloaded;
-      info.desc = '下载完成';
-      sendStatusToWindow(mainWindow, info);
-      // quit and update
-      eeApp.appQuit();
-      autoUpdater.quitAndInstall();
-    });
-    
-
-  },
-
-  /**
-   * 检查更新
-   */
-  checkUpdate () {
-    autoUpdater.checkForUpdates();
-  },
-  
-  /**
-   * 下载更新
-   */
-  download () {
-    autoUpdater.downloadUpdate();
-  },
-
-}
-
-/**
- * 向前端发消息
- */
-function sendStatusToWindow(mainWindow, content = {}) {
-  const textJson = JSON.stringify(content);
-  const channel = 'app.updater';
-  mainWindow.webContents.send(channel, textJson);
-}
- 
-function 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;
-}
-
-  

+ 0 - 56
electron/library/awaken.js

@@ -1,56 +0,0 @@
-'use strict';
-
-const { app } = require('electron');
-
-/**
- * 应用唤醒模块
- */
-module.exports = {
-
-  /**
-   * 安装
-   */     
-  install (eeApp) {
-    eeApp.logger.info('[preload] load awaken module');
-    const protocolInfo = eeApp.config.awakeProtocol;
-    const PROTOCOL = protocolInfo.protocol;
-  
-    app.setAsDefaultProtocolClient(PROTOCOL);
-  
-    handleArgv(process.argv);
-  
-    app.on('second-instance', (event, argv) => {
-      if (process.platform === 'win32') {
-        handleArgv(argv)
-      }
-    })
-  
-    // 仅用于macOS
-    app.on('open-url', (event, urlStr) => {
-      handleUrl(urlStr)
-    })
-  
-    // 参数处理
-    function handleArgv(argv) {
-      const offset = app.isPackaged ? 1 : 2;
-      const url = argv.find((arg, i) => i >= offset && arg.startsWith(PROTOCOL));
-      handleUrl(url)
-    }
-
-    // url解析
-    function handleUrl(awakeUrlStr) {
-      if (!awakeUrlStr || awakeUrlStr.length === 0) {
-        return
-      }
-      const {hostname, pathname, search} = new URL(awakeUrlStr);
-      let awakeUrlInfo = {
-        urlStr: awakeUrlStr,
-        urlHost: hostname,
-        urlPath: pathname,
-        urlParams: search && search.slice(1)
-      }
-      eeApp.logger.info('[awaken] [handleUrl] awakeUrlInfo:', awakeUrlInfo);
-    }
-  }
-}
-

+ 0 - 26
electron/library/security.js

@@ -1,26 +0,0 @@
-'use strict';
-
-/**
- * 安全模块
- */
-
-module.exports = {
-  
-  /**
-   * 安装
-   */  
-  install (eeApp) {
-    eeApp.logger.info('[preload] load security module');
-    const runWithDebug = process.argv.find(function(e){
-      let isHasDebug = e.includes("--inspect") || e.includes("--inspect-brk") || e.includes("--remote-debugging-port");
-      return isHasDebug;
-    })
-  
-    // 不允许远程调试
-    if (runWithDebug) {
-      eeApp.logger.error('[error] Remote debugging is not allowed,  runWithDebug:', runWithDebug);
-      eeApp.appQuit();
-    }
-  }
-
-}

+ 0 - 76
electron/library/tray.js

@@ -1,76 +0,0 @@
-'use strict';
-
-const {Tray, Menu} = require('electron');
-const path = require('path');
-
-/**
- * 托盘模块
- */
-
-module.exports = {
-
-  /**
-   * 安装
-   */
-  install (eeApp) {
-    // 开发环境,代码热更新开启时,会导致托盘中有残影
-    // 目前没有找到合适的解决方案
-    // 启用热更新功能时,不加载该模块
-    // 如果调试该模式,请使用dev模式
-    if (process.env.EE_SERVER_ENV == 'local' && process.env.HOT_RELOAD == 'true') return;
-    
-    eeApp.logger.info('[preload] load tray module');
-    const trayConfig = eeApp.config.tray;
-    const mainWindow = eeApp.electron.mainWindow;
-
-    // 托盘图标
-    let iconPath = path.join(eeApp.config.homeDir, trayConfig.icon);
-  
-    // 托盘菜单功能列表
-    let trayMenuTemplate = [
-      {
-        label: '显示',
-        click: function () {
-          mainWindow.show();
-        }
-      },
-      {
-        label: '退出',
-        click: function () {
-          eeApp.appQuit();
-        }
-      }
-    ]
-  
-    // 点击关闭,最小化到托盘
-    mainWindow.on('close', (event) => {
-      if (eeApp.electron.extra.closeWindow == true) {
-        return;
-      }
-      mainWindow.hide();
-      event.preventDefault();
-    });
-
-    // 测试发现:创建的Tray对象实例变量和app.whenReady()在同一模块中定义才行
-    // 赋值给eeApp.electron.tray,已在框架ee-core包中定义
-    // 如果赋值给其它变量,可能出现异常,估计是electron的bug
-    
-    eeApp.electron.tray = new Tray(iconPath);
-    let appTray = eeApp.electron.tray;
-
-    appTray.setToolTip(trayConfig.title); // 托盘标题
-    const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
-    appTray.setContextMenu(contextMenu);
-  
-    // 监听 显示/隐藏
-    // appTray.on('click', function(){
-    //   if (mainWindow.isVisible()) {
-    //     mainWindow.hide();
-    //     //mainWindow.setSkipTaskbar(true);
-    //   } else {
-    //     mainWindow.show();
-    //     //mainWindow.setSkipTaskbar(false);
-    //   }
-    // });
-  }
-}

+ 8 - 31
electron/preload/index.js

@@ -1,14 +1,7 @@
-'use strict';
-
 /*************************************************
  ** preload为预加载模块,该文件将会在程序启动时加载 **
  *************************************************/
 
-const is = require('electron-is');
-const tray = require('../library/tray');
-const security = require('../library/security');
-const awaken = require('../library/awaken');
-
 /**
  * 预加载模块入口
  * @param {Object} app - 全局app对象
@@ -16,29 +9,13 @@ const awaken = require('../library/awaken');
 module.exports = async (app) => {
 
   //已实现的功能模块,可选择性使用和修改
+  const trayAddon = app.addon.tray;
+  const securityAddon = app.addon.security;
+  const awakenAddon = app.addon.awaken;
+  const autoUpdaterAddon = app.addon.autoUpdater;
   
-  tray.install(app);
-
-  security.install(app);
-
-  awaken.install(app);
-  
-  loadUpdate(app);
-
-}
-
-/**
- * 加载自动升级模块
- */
-function loadUpdate (app) {
-  const config = app.config.autoUpdate;
-  if ( (is.windows() && config.windows) || (is.macOS() && config.macOS) || (is.linux() && config.linux) ) {
-    const autoUpdater = require('../library/autoUpdater');
-    autoUpdater.install(app);
-
-    // 是否检查更新
-    if (config.force) {
-      autoUpdater.checkUpdate();
-    }
-  }
+  trayAddon.create();
+  securityAddon.create();
+  awakenAddon.create();
+  autoUpdaterAddon.create();
 }

+ 4 - 25
frontend/src/views/other/java/Index.vue

@@ -2,7 +2,7 @@
   <div id="app-other">
     <div class="one-block-1">
       <span>
-        请求java后台接口, 本示例需要修改如下: <br/>
+        请求java服务接口
       </span>
     </div>  
     <div class="one-block-2">
@@ -12,26 +12,6 @@
         <a-button @click="closeServer()"> 关闭java项目 </a-button>
       </a-space>
     </div>
-    <div class="one-block-2">
-      <span>
-        1. 修改 electron/config/config.default.js 中 config.server.enable = true <br/>
-        2. 官方下载 jre 并解压到: build/extraResources <br/>
-        3. 编译 spring boot 可执行jar到: build/extraResources <br/>
-
-        下载我准备好的 jre 和 app.jar 看效果: <br/>
-        链接: https://pan.baidu.com/s/1QLtFC76uD6_dm01S6xaUSA  密码: cqpf   <br/>
-        注意: 请根据你的操作系统,选择正确的jre进行下载 <br/>
-
-        同时可以去oracle官方下载其他版本的jre: <br/>
-
-        https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
-        <br/>
-
-        <br/>
-        同时,你可以将18080端口先占用,后启动ee程序,观察请求的端口
-
-      </span>
-    </div>
   </div>
 </template>
 <script>
@@ -53,7 +33,7 @@ export default {
         if (r.code != 0) {
           this.$message.error(r.msg);
         }
-        this.$message.info('启动成功');
+        this.$message.info('异步启动');
         storage.set('javaService', r.server);
       })
     },
@@ -64,14 +44,14 @@ export default {
           this.$message.error(r.msg);
         }
         this.$message.info('服务已关闭');
-        storage.remove('javaService:');
+        storage.remove('javaService');
       })
     },
 
     sendRequest () {
       const server = storage.get('javaService') || '';
       if (server == '') {
-        this.$message.error('服务未开启');
+        this.$message.error('服务未开启 或 正在启动中');
         return
       }
       let testApi = server + '/test1/get';
@@ -82,7 +62,6 @@ export default {
         timeout: 60000,
       }
       this.$http(params).then(res => {
-        console.log('res:', res);
         this.$message.info(`java服务返回: ${res}`, );
       })
     },

+ 2 - 2
package.json

@@ -114,7 +114,7 @@
     "dayjs": "^1.10.7",
     "ee-core": "^1.4.0",
     "electron-is": "^3.0.0",
-    "lodash": "^4.17.21",
-    "table-parser": "^0.1.3"
+    "electron-updater": "^5.3.0",
+    "lodash": "^4.17.21"
   }
 }

+ 0 - 124
public/lib/javaServer.js

@@ -1,124 +0,0 @@
-"use strict";
-
-const _ = require("lodash");
-const assert = require("assert");
-const fs = require("fs");
-const os = require("os");
-const path = require("path");
-const { execSync, exec } = require("child_process");
-const Utils = require("ee-core").Utils;
-const ps = require("./ps");
-
-function getCoreDB() {
-  const Storage = require("ee-core").Storage;
-  return Storage.JsonDB.connection("system");
-}
-
-function getJavaPort() {
-  const cdb = getCoreDB();
-  const port = cdb.getItem("config").javaServer.port;
-  return port;
-}
-
-function getJarName() {
-  const cdb = getCoreDB();
-  return cdb.getItem("config").javaServer.name;
-}
-
-function getOpt(port, path) {
-  const cdb = getCoreDB();
-  const opt = cdb.getItem("config").javaServer.opt;
-  let javaOpt = _.replace(opt, "${port}", port);
-  return _.replace(javaOpt, "${path}", path);
-}
-
-function getJreVersion() {
-  const cdb = getCoreDB();
-  return cdb.getItem("config").javaServer.jreVersion;
-}
-
-async function start(app) {
-  const options = app.config.javaServer;
-  if (!options.enable) {
-    return;
-  }
-
-  let port = process.env.EE_JAVA_PORT ? parseInt(process.env.EE_JAVA_PORT) : parseInt(getJavaPort());
-  assert(typeof port === "number", "java port required, and must be a number");
-  app.logger.info("[javaServer] java server port is:", port);
-
-  const jarName = getJarName();
-  let softwarePath = path.join(Utils.getExtraResourcesDir(), jarName);
-  app.logger.info("[javaServer] jar存放路径:", softwarePath);
-
-  const logPath = Utils.getLogDir()
-
-  // 检查程序是否存在
-  if (!fs.existsSync(softwarePath)) {
-    app.logger.info("[javaServer] java程序不存在", softwarePath);
-  }
-
-  const JAVA_OPT = getOpt(port, logPath);
-  if (os.platform() === "win32") {
-    let jrePath = path.join(
-      Utils.getExtraResourcesDir(),
-      getJreVersion(),
-      "bin",
-      "javaw.exe"
-    );
-    // 命令行字符串 并 执行
-    let cmdStr = `start ${jrePath} -jar ${JAVA_OPT} ${softwarePath}`;
-    app.logger.info("[javaServer] cmdStr:", cmdStr);
-    exec(cmdStr);
-  } else {
-    // 不受信任请执行:  sudo spctl --master-disable
-    let jrePath = path.join(
-      Utils.getExtraResourcesDir(),
-      getJreVersion(),
-      "Contents",
-      "Home",
-      "bin",
-      "java"
-    );
-    // 命令行字符串 并 执行
-    // let cmdStr = `${jrePath} -jar ${JAVA_OPT} ${softwarePath} > /Users/tangyh/Downloads/app.log`;
-    let cmdStr = `nohup ${jrePath} -jar ${JAVA_OPT} ${softwarePath} >/dev/null 2>&1 &`;
-    app.logger.info("[javaServer] cmdStr:", cmdStr);
-    await execSync(cmdStr);
-  }
-}
-
-async function kill(app) {
-  const port = getJavaPort();
-  const jarName = getJarName();
-  app.logger.info("[javaServer] kill port: ", port);
-
-  if (os.platform() === "win32") {
-    const resultList = ps.lookup({
-      command: "java",
-      where: 'caption="javaw.exe"',
-      arguments: jarName,
-    });
-
-    app.logger.info("[javaServer] resultList:", resultList);
-    resultList.forEach((item) => {
-      ps.kill(item.pid, "SIGKILL", (err) => {
-        if (err) {
-          throw new Error(err);
-        }
-        app.logger.info("[javaServer] 已经退出后台程序: %O", item);
-      });
-    });
-
-    //   const cmd = `for /f "tokens=1-5" %i in ('netstat -ano ^| findstr ":${port}"') do taskkill /F /T /PID %m`;
-    //   const a = await execSync(cmd, {encoding: 'utf-8'});
-    //   app.logger.info("[javaServer] kill:", a);
-  } else {
-    const cmd = `ps -ef | grep java | grep ${jarName} | grep -v grep | awk '{print $2}' | xargs kill -9`;
-    const result = await execSync(cmd);
-    app.logger.info("[javaServer] kill:", result != null ? result.toString(): '');
-  }
-}
-
-module.exports.start = start;
-module.exports.kill = kill;

+ 0 - 264
public/lib/ps.js

@@ -1,264 +0,0 @@
-/**
- * 本文件修改至 https://github.com/neekey/ps
- * 原因是:
- * 1. lookup 只提供了异步方式
- * 2. lookup 性能太差
- */
-
-var ChildProcess = require("child_process");
-var IS_WIN = process.platform === "win32";
-var TableParser = require("table-parser");
-/**
- * End of line.
- * Basically, the EOL should be:
- * - windows: \r\n
- * - *nix: \n
- * But i'm trying to get every possibilities covered.
- */
-var EOL = /(\r\n)|(\n\r)|\n|\r/;
-var SystemEOL = require("os").EOL;
-
-/**
- * Execute child process
- * @type {Function}
- * @param {String[]} args
- * @param {String} where
- * @param {Function} callback
- * @param {Object=null} callback.err
- * @param {Object[]} callback.stdout
- */
-var Exec = function (args, where) {
-  var spawnSync = ChildProcess.spawnSync;
-  var execSync = ChildProcess.execSync;
-
-  // on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing
-  // that's why I use `cmd` instead
-  if (IS_WIN) {
-    const cmd = `wmic process where ${where} get ProcessId,ParentProcessId,CommandLine \n`;
-    const result = execSync(cmd);
-    if (!result) {
-      throw new Error(result);
-    }
-
-    var stdout = result.toString();
-
-    var beginRow;
-    stdout = stdout.split(EOL);
-
-    // Find the line index for the titles
-    stdout.forEach(function (out, index) {
-      if (
-        out &&
-        typeof beginRow == "undefined" &&
-        out.indexOf("CommandLine") === 0
-      ) {
-        beginRow = index;
-      }
-    });
-
-    // get rid of the start (copyright) and the end (current pwd)
-    stdout.splice(stdout.length - 1, 1);
-    stdout.splice(0, beginRow);
-
-    return stdout.join(SystemEOL) || false;
-  } else {
-    if (typeof args === "string") {
-      args = args.split(/\s+/);
-    }
-    const result = spawnSync("ps", args);
-    if (result.stderr && !!result.stderr.toString()) {
-      throw new Error(result.stderr);
-    } else {
-      return result.stdout.toString();
-    }
-  }
-};
-
-/**
- * Query Process: Focus on pid & cmd
- * @param query
- * @param {String|String[]} query.pid
- * @param {String} query.command RegExp String
- * @param {String} query.arguments RegExp String
- * @param {String|array} query.psargs
- * @param {String|array} query.where where 条件
- * @param {Function} callback
- * @param {Object=null} callback.err
- * @param {Object[]} callback.processList
- * @return {Object}
- */
-
-exports.lookup = function (query) {
-  /**
-   * add 'lx' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments
-   */
-  var exeArgs = query.psargs || ["lx"];
-  var where = query.where || 'name="javaw.exe"';
-  var filter = {};
-  var idList;
-
-  // Lookup by PID
-  if (query.pid) {
-    if (Array.isArray(query.pid)) {
-      idList = query.pid;
-    } else {
-      idList = [query.pid];
-    }
-
-    // Cast all PIDs as Strings
-    idList = idList.map(function (v) {
-      return String(v);
-    });
-  }
-
-  if (query.command) {
-    filter["command"] = new RegExp(query.command, "i");
-  }
-
-  if (query.arguments) {
-    filter["arguments"] = new RegExp(query.arguments, "i");
-  }
-
-  if (query.ppid) {
-    filter["ppid"] = new RegExp(query.ppid);
-  }
-
-  const result = Exec(exeArgs, where);
-
-  var processList = parseGrid(result);
-  var resultList = [];
-
-  processList.forEach(function (p) {
-    var flt;
-    var type;
-    var result = true;
-
-    if (idList && idList.indexOf(String(p.pid)) < 0) {
-      return;
-    }
-
-    for (type in filter) {
-      flt = filter[type];
-      result = flt.test(p[type]) ? result : false;
-    }
-
-    if (result) {
-      resultList.push(p);
-    }
-  });
-
-  return resultList;
-};
-
-/**
- * Kill process
- * @param pid
- * @param {Object|String} signal
- * @param {String} signal.signal
- * @param {number} signal.timeout
- * @param next
- */
-
-exports.kill = function (pid, signal, next) {
-  //opts are optional
-  if (arguments.length == 2 && typeof signal == "function") {
-    next = signal;
-    signal = undefined;
-  }
-
-  var checkTimeoutSeconds = (signal && signal.timeout) || 30;
-
-  if (typeof signal === "object") {
-    signal = signal.signal;
-  }
-
-  try {
-    process.kill(pid, signal);
-  } catch (e) {
-    return next && next(e);
-  }
-
-  var checkConfident = 0;
-  var checkTimeoutTimer = null;
-  var checkIsTimeout = false;
-
-  function checkKilled(finishCallback) {
-    exports.lookup({ pid: pid }, function (err, list) {
-      if (checkIsTimeout) return;
-
-      if (err) {
-        clearTimeout(checkTimeoutTimer);
-        finishCallback && finishCallback(err);
-      } else if (list.length > 0) {
-        checkConfident = checkConfident - 1 || 0;
-        checkKilled(finishCallback);
-      } else {
-        checkConfident++;
-        if (checkConfident === 5) {
-          clearTimeout(checkTimeoutTimer);
-          finishCallback && finishCallback();
-        } else {
-          checkKilled(finishCallback);
-        }
-      }
-    });
-  }
-
-  next && checkKilled(next);
-
-  checkTimeoutTimer =
-    next &&
-    setTimeout(function () {
-      checkIsTimeout = true;
-      next(new Error("Kill process timeout"));
-    }, checkTimeoutSeconds * 1000);
-};
-
-/**
- * Parse the stdout into readable object.
- * @param {String} output
- */
-
-function parseGrid(output) {
-  if (!output) {
-    return [];
-  }
-  return formatOutput(TableParser.parse(output));
-}
-
-/**
- * format the structure, extract pid, command, arguments, ppid
- * @param data
- * @return {Array}
- */
-
-function formatOutput(data) {
-  var formatedData = [];
-  data.forEach(function (d) {
-    var pid =
-      (d.PID && d.PID[0]) || (d.ProcessId && d.ProcessId[0]) || undefined;
-    var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;
-    var ppid =
-      (d.PPID && d.PPID[0]) ||
-      (d.ParentProcessId && d.ParentProcessId[0]) ||
-      undefined;
-
-    if (pid && cmd) {
-      var command = cmd[0];
-      var args = "";
-
-      if (cmd.length > 1) {
-        args = cmd.slice(1);
-      }
-
-      formatedData.push({
-        pid: pid,
-        command: command,
-        arguments: args,
-        ppid: ppid,
-      });
-    }
-  });
-
-  return formatedData;
-}

+ 0 - 13
public/lib/updateFrontend.js

@@ -1,13 +0,0 @@
-/** 修改前端配置 */
-module.exports = {
-  install(eeApp) {
-    if (eeApp.config.javaServer.enable) {
-      let javaServerPrefix = `http://localhost:${eeApp.config.javaServer.port}`;
-
-      const mainWindow = eeApp.electron.mainWindow;
-      const channel = "app.javaPort";
-      mainWindow.webContents.send(channel, javaServerPrefix);
-      console.log('send');
-    }
-  },
-};