哆啦好梦 2 years ago
parent
commit
78c9e2349f
40 changed files with 349 additions and 176 deletions
  1. 23 21
      electron/addon/autoUpdater/index.js
  2. 7 5
      electron/addon/awaken/index.js
  3. 4 3
      electron/addon/chromeExtension/index.js
  4. 11 7
      electron/addon/javaServer/index.js
  5. 18 17
      electron/addon/javaServer/server.js
  6. 4 2
      electron/addon/security/index.js
  7. 14 9
      electron/addon/tray/index.js
  8. 4 4
      electron/config/config.default.js
  9. 1 1
      electron/config/encrypt.js
  10. 45 22
      electron/controller/example.js
  11. 5 0
      electron/jobs/example/hello.js
  12. 46 0
      electron/jobs/example/timer.js
  13. 0 1
      electron/preload/index.js
  14. 5 4
      electron/service/example.js
  15. 6 6
      electron/service/storage.js
  16. 3 1
      frontend/src/api/main.js
  17. 5 0
      frontend/src/config/router.config.js
  18. 6 0
      frontend/src/config/subMenu.js
  19. 2 2
      frontend/src/main.js
  20. 20 23
      frontend/src/utils/ipcRenderer.js
  21. 2 2
      frontend/src/views/base/db/Index.vue
  22. 6 7
      frontend/src/views/base/file/Index.vue
  23. 75 0
      frontend/src/views/base/jobs/Index.vue
  24. 1 1
      frontend/src/views/base/powermonitor/Index.vue
  25. 1 1
      frontend/src/views/base/screen/Index.vue
  26. 1 1
      frontend/src/views/base/socket/HttpServer.vue
  27. 5 5
      frontend/src/views/base/socket/Ipc.vue
  28. 1 1
      frontend/src/views/base/socket/SocketServer.vue
  29. 1 1
      frontend/src/views/base/software/Index.vue
  30. 6 6
      frontend/src/views/base/sqlitedb/Index.vue
  31. 4 4
      frontend/src/views/base/subwindow/Ipc.vue
  32. 1 2
      frontend/src/views/base/system/Index.vue
  33. 1 1
      frontend/src/views/base/testapi/Index.vue
  34. 2 2
      frontend/src/views/base/theme/Index.vue
  35. 2 2
      frontend/src/views/base/updater/Index.vue
  36. 1 1
      frontend/src/views/base/window/Index.vue
  37. 2 4
      frontend/src/views/base/windowview/Index.vue
  38. 2 2
      frontend/src/views/other/java/Index.vue
  39. 4 2
      main.js
  40. 2 3
      package.json

+ 23 - 21
electron/addon/autoUpdater/index.js

@@ -1,6 +1,9 @@
-const { app } = require('electron');
+const { app: electronApp } = require('electron');
 const { autoUpdater } = require("electron-updater");
-const is = require('electron-is');
+const is = require('ee-core/utils/is');
+const Log = require('ee-core/log');
+const Conf = require('ee-core/config');
+const Electron = require('ee-core/electron');
 
 /**
  * 自动升级插件
@@ -10,19 +13,19 @@ 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');
+    Log.info('[addon:autoUpdater] load');
 
-    if ((is.windows() && this.cfg.windows)
-        || (is.macOS() && this.cfg.macOS)
-        || (is.linux() && this.cfg.linux))
+    const app = this.app;
+    const cfg = Conf.getValue('addons.autoUpdater');
+    if ((is.windows() && cfg.windows)
+        || (is.macOS() && cfg.macOS)
+        || (is.linux() && cfg.linux))
     {
       // continue
     } else {
@@ -30,7 +33,7 @@ class AutoUpdaterAddon {
     }
 
     // 是否检查更新
-    if (this.cfg.force) {
+    if (cfg.force) {
       this.checkUpdate();
     }
 
@@ -42,24 +45,23 @@ class AutoUpdaterAddon {
       downloaded: 4,
     }
 
-    const updateConfig = this.cfg;
-    const version = app.getVersion();
-    this.app.logger.info('[addon:autoUpdater] current version: ', version);
+    const version = electronApp.getVersion();
+    Log.info('[addon:autoUpdater] current version: ', version);
   
     // 设置下载服务器地址
-    let server = updateConfig.options.url;
+    let server = cfg.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;
+    //Log.info('[addon:autoUpdater] server: ', server);
+    cfg.options.url = server;
   
     // 是否后台自动下载
-    autoUpdater.autoDownload = updateConfig.force ? true : false;
+    autoUpdater.autoDownload = cfg.force ? true : false;
   
     try {
-      autoUpdater.setFeedURL(updateConfig.options);
+      autoUpdater.setFeedURL(cfg.options);
     } catch (error) {
-      this.app.logger.error('[addon:autoUpdater] setFeedURL error : ', error);
+      Log.error('[addon:autoUpdater] setFeedURL error : ', error);
     }
   
     autoUpdater.on('checking-for-update', () => {
@@ -96,7 +98,7 @@ class AutoUpdaterAddon {
         totalSize: totalSize,
         transferredSize: transferredSize
       }
-      this.app.logger.info('[addon:autoUpdater] progress: ', text);
+      Log.info('[addon:autoUpdater] progress: ', text);
       this.sendStatusToWindow(info);
     })
     autoUpdater.on('update-downloaded', (info) => {
@@ -104,7 +106,7 @@ class AutoUpdaterAddon {
       info.desc = '下载完成';
       this.sendStatusToWindow(info);
       // quit and update
-      this.app.appQuit();
+      app.appQuit();
       autoUpdater.quitAndInstall();
     });
   }
@@ -129,7 +131,7 @@ class AutoUpdaterAddon {
   sendStatusToWindow(content = {}) {
     const textJson = JSON.stringify(content);
     const channel = 'app.updater';
-    this.mainWindow.webContents.send(channel, textJson);
+    Electron.mainWindow.webContents.send(channel, textJson);
   }
   
   /**

+ 7 - 5
electron/addon/awaken/index.js

@@ -1,4 +1,6 @@
-const electronApp = require('electron').app;
+const { app: electronApp } = require('electron');
+const Log = require('ee-core/log');
+const Conf = require('ee-core/config');
 
 /**
  * 唤醒插件
@@ -8,7 +10,6 @@ class AwakenAddon {
 
   constructor(app) {
     this.app = app;
-    this.cfg = app.config.addons.awaken;
     this.protocol = '';
   }
 
@@ -16,9 +17,10 @@ class AwakenAddon {
    * 创建
    */
   create () {
-    this.app.console.info('[addon:awaken] load');
+    Log.info('[addon:awaken] load');
 
-    this.protocol = this.cfg.protocol;
+    const cfg = Conf.getValue('addons.awaken');
+    this.protocol = cfg.protocol;
   
     electronApp.setAsDefaultProtocolClient(this.protocol);
   
@@ -59,7 +61,7 @@ class AwakenAddon {
       urlPath: pathname,
       urlParams: search && search.slice(1)
     }
-    this.app.logger.info('[addon:awaken] awakeUrlInfo:', awakeUrlInfo);
+    Log.info('[addon:awaken] awakeUrlInfo:', awakeUrlInfo);
   }
 }
 

+ 4 - 3
electron/addon/chromeExtension/index.js

@@ -2,6 +2,7 @@ const { app, session } = require('electron');
 const _ = require('lodash');
 const fs = require('fs');
 const path = require('path');
+const Log = require('ee-core/log');
 
 /**
  * 安全插件
@@ -17,7 +18,7 @@ class ChromeExtensionAddon {
    * 创建
    */
   async create () {
-    this.app.console.info('[addon:chromeExtension] load');
+    Log.info('[addon:chromeExtension] load');
 
     const extensionIds = this.getAllIds();
     for (let i = 0; i < extensionIds.length; i++) {
@@ -59,10 +60,10 @@ class ChromeExtensionAddon {
     
     try {
       const extensionPath = path.join(this.getDirectory(), extensionId);
-      console.log('[addon:chromeExtension] extensionPath:', extensionPath);
+      Log.info('[addon:chromeExtension] extensionPath:', extensionPath);
       await session.defaultSession.loadExtension(extensionPath, { allowFileAccess: true });
     } catch (e) {
-      console.log('[addon:chromeExtension] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
+      Log.info('[addon:chromeExtension] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
       return false
     }
   

+ 11 - 7
electron/addon/javaServer/index.js

@@ -1,6 +1,8 @@
 const getPort = require('get-port');
 const server = require("./server");
-const electronApp = require('electron').app;
+const { app: electronApp } = require('electron');
+const Log = require('ee-core/log');
+const Conf = require('ee-core/config');
 
 /**
  * java server插件
@@ -10,8 +12,8 @@ class JavaServerAddon {
 
   constructor(app) {
     this.app = app;
-    this.cfg = app.config.addons.javaServer;
-    this.javaServer = null;
+    this.cfg;
+    this.javaServer;
   }
 
   /**
@@ -21,14 +23,16 @@ class JavaServerAddon {
    * @since 1.0.0
    */
   async createServer () {
+
+    this.cfg = Conf.getValue('addons.javaServer');
     await this.createJavaPorts();
 
-    this.javaServer = new server(this.app);
-    await this.javaServer.create();
+    this.javaServer = new server();
+    await this.javaServer.create(this.cfg);
 
     // kill
     electronApp.on("before-quit", async () => {
-      this.app.logger.info("[addon:javaServer] before-quit: kill-----------");
+      Log.info("[addon:javaServer] before-quit: kill-----------");
       await this.javaServer.kill();
     });
 
@@ -60,7 +64,7 @@ class JavaServerAddon {
     this.cfg.port = javaPort;
 
     // 更新config配置
-    this.app.getCoreDB().setItem("config", this.app.config);
+    Conf.setValue('addons.javaServer', this.cfg);
   }
 
   /**

+ 18 - 17
electron/addon/javaServer/server.js

@@ -1,26 +1,27 @@
 const _ = require("lodash");
 const assert = require("assert");
 const fs = require("fs");
-const is = require('electron-is');
 const path = require("path");
 const { exec, execSync } = require("child_process");
-const Utils = require("ee-core").Utils;
 const ps = require("./ps");
+const Log = require('ee-core/log');
+const is = require('ee-core/utils/is');
+const UtilsPs = require('ee-core/ps');
 
 /**
  * java server
  */
 class JavaServer {
-  constructor (app) {
-    this.app = app;
-    this.options = app.config.addons.javaServer;
+  constructor () {
+    this.options;
   }
 
   /**
    * 创建服务
    */
-  async create () {
-    if (!this.options.enable) {
+  async create (cfg) {
+    this.options = cfg;
+    if (this.options.enable == false) {
       return;
     }
   
@@ -29,17 +30,17 @@ class JavaServer {
   
     try {
       const jarName = this.options.name;
-      let softwarePath = path.join(Utils.getExtraResourcesDir(), jarName);
+      let softwarePath = path.join(UtilsPs.getExtraResourcesDir(), jarName);
       let javaOptStr = this.options.opt;
-      let jrePath = path.join(Utils.getExtraResourcesDir(), this.options.jreVersion);
+      let jrePath = path.join(UtilsPs.getExtraResourcesDir(), this.options.jreVersion);
       let cmdStr = '';
       
-      this.app.console.info("[addon:javaServer] jar file path:", softwarePath); 
+      Log.info("[addon:javaServer] jar file path:", softwarePath); 
       if (!fs.existsSync(softwarePath)) throw new Error('java program does not exist');
 
       // 替换opt参数
       javaOptStr = _.replace(javaOptStr, "${port}", port);
-      javaOptStr = _.replace(javaOptStr, "${path}", Utils.getLogDir());
+      javaOptStr = _.replace(javaOptStr, "${path}", UtilsPs.getLogDir());
 
       if (is.windows()) {
         jrePath = path.join(jrePath, "bin", "javaw.exe");
@@ -53,11 +54,11 @@ class JavaServer {
         // todo linux
       }
 
-      this.app.logger.info("[addon:javaServer] cmdStr:", cmdStr);
+      Log.info("[addon:javaServer] cmdStr:", cmdStr);
       exec(cmdStr);
 
     } catch (err) {
-      this.app.logger.error('[addon:javaServer] throw error:', err);
+      Log.error('[addon:javaServer] throw error:', err);
     }
   }
 
@@ -73,23 +74,23 @@ class JavaServer {
         arguments: jarName,
       });
   
-      //this.app.logger.info("[addon:javaServer] resultList:", resultList);
+      //Log.info("[addon:javaServer] resultList:", resultList);
       resultList.forEach((item) => {
         ps.kill(item.pid, "SIGKILL", (err) => {
           if (err) {
             throw new Error(err);
           }
-          console.info("[addon:javaServer] java程序退出 pid: ", item.pid);
+          Log.info("[addon:javaServer] java程序退出 pid: ", item.pid);
         });
       });
   
       //   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);
+      //   Log.info("[javaServer] kill:", a);
     } else if (is.macOS()) {
       const cmd = `ps -ef | grep java | grep ${jarName} | grep -v grep | awk '{print $2}' | xargs kill -9`;
       const result = await execSync(cmd);
-      this.app.logger.info("[addon:javaServer] kill:", result != null ? result.toString(): '');
+      Log.info("[addon:javaServer] kill:", result != null ? result.toString(): '');
     } else {
       // todo linux
     }

+ 4 - 2
electron/addon/security/index.js

@@ -1,3 +1,5 @@
+const Log = require('ee-core/log');
+
 /**
  * 安全插件
  * @class
@@ -12,7 +14,7 @@ class SecurityAddon {
    * 创建
    */
   create () {
-    this.app.console.info('[addon:security] load');
+    Log.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;
@@ -20,7 +22,7 @@ class SecurityAddon {
   
     // 不允许远程调试
     if (runWithDebug) {
-      this.app.logger.error('[error] Remote debugging is not allowed,  runWithDebug:', runWithDebug);
+      Log.error('[error] Remote debugging is not allowed,  runWithDebug:', runWithDebug);
       this.app.appQuit();
     }
   }

+ 14 - 9
electron/addon/tray/index.js

@@ -1,5 +1,9 @@
 const {Tray, Menu} = require('electron');
 const path = require('path');
+const Ps = require('ee-core/ps');
+const Log = require('ee-core/log');
+const Electron = require('ee-core/electron');
+const Conf = require('ee-core/config');
 
 /**
  * 托盘插件
@@ -9,7 +13,6 @@ class TrayAddon {
 
   constructor(app) {
     this.app = app;
-    this.cfg = app.config.addons.tray;
     this.tray = null;
   }
 
@@ -18,16 +21,18 @@ class TrayAddon {
    */
   create () {
     // 开发环境,代码热更新开启时,会导致托盘中有残影
-    if (process.env.EE_SERVER_ENV == 'local' && process.env.HOT_RELOAD == 'true') return;
+    if (Ps.isDev() && Ps.isHotReload()) return;
     
-    this.app.console.info('[addon:tray] load');
-    const mainWindow = this.app.electron.mainWindow;
+    Log.info('[addon:tray] load');
+
+    const app = this.app;
+    const cfg = Conf.getValue('addons.tray');
+    const mainWindow = Electron.mainWindow;
 
     // 托盘图标
-    let iconPath = path.join(this.app.config.homeDir, this.cfg.icon);
+    let iconPath = path.join(Ps.getHomeDir(), cfg.icon);
   
     // 托盘菜单功能列表
-    const self = this;
     let trayMenuTemplate = [
       {
         label: '显示',
@@ -38,14 +43,14 @@ class TrayAddon {
       {
         label: '退出',
         click: function () {
-          self.app.appQuit();
+          app.appQuit();
         }
       }
     ]
   
     // 点击关闭,最小化到托盘
     mainWindow.on('close', (event) => {
-      const extraObj = this.app.electron.extra;
+      const extraObj = Electron.extra;
       if (extraObj.closeWindow == true) {
         return;
       }
@@ -55,7 +60,7 @@ class TrayAddon {
     
     // 实例化托盘
     this.tray = new Tray(iconPath);
-    this.tray.setToolTip(this.cfg.title);
+    this.tray.setToolTip(cfg.title);
     const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
     this.tray.setContextMenu(contextMenu);
   }

+ 4 - 4
electron/config/config.default.js

@@ -81,7 +81,7 @@ module.exports = (appInfo) => {
    * 内置socket服务
    */   
   config.socketServer = {
-    enable: false,
+    enable: true,
     port: 7070,
     path: "/socket.io/",
     connectTimeout: 45000,
@@ -98,7 +98,7 @@ module.exports = (appInfo) => {
    * 内置http服务
    */     
   config.httpServer = {
-    enable: false,
+    enable: true,
     https: {
       enable: false, 
       key: '/public/ssl/localhost+1.key',
@@ -126,7 +126,7 @@ module.exports = (appInfo) => {
    * 主进程
    */     
   config.mainServer = {
-    host: '127.0.0.1',
+    host: 'localhost',
     port: 7072,
   }; 
 
@@ -176,7 +176,7 @@ module.exports = (appInfo) => {
       name: 'java-app.jar'
     },
     example: {
-      enable: true,
+      enable: false,
     },
   };
 

+ 1 - 1
electron/config/encrypt.js

@@ -10,7 +10,7 @@ module.exports = {
   confusionOptions: {
     compact: true,      
     stringArray: true,
-    stringArrayEncoding: ['base64'],
+    stringArrayEncoding: ['none'],
     deadCodeInjection: false,
   }
 };

+ 45 - 22
electron/controller/example.js

@@ -4,11 +4,16 @@ const _ = require('lodash');
 const path = require('path');
 const fs = require('fs');
 const { exec } = require('child_process');
-const { Controller, Utils } = require('ee-core');
-const electronApp = require('electron').app;
-const {dialog, shell, BrowserView, 
-  Notification, powerMonitor, screen, nativeTheme} = require('electron');
+const { Controller } = require('ee-core');
+const {
+  app: electronApp,
+  dialog, shell, BrowserView, Notification, 
+  powerMonitor, screen, nativeTheme
+} = require('electron');
 const dayjs = require('dayjs');
+const { ChildJob } = require('ee-core/jobs');
+const Ps = require('ee-core/ps');
+const Log = require('ee-core/log');
 
 let myTimer = null;
 let browserViewObj = null;
@@ -36,14 +41,8 @@ class ExampleController extends Controller {
   async test () {
     const result = await this.service.example.test('electron');
 
-    let tmpDir = Utils.getLogDir();
-    console.log('tmpDir:', tmpDir);
-
-    // console.log('this.app.request:', this.app.request.query);
-
-    // const exampleAddon = this.app.addon.example;
-    // const str = exampleAddon.hello();
-    // console.log('str:', str);
+    let tmpDir = Ps.getLogDir();
+    Log.info('tmpDir:', tmpDir);
 
     return result;
   }
@@ -54,7 +53,7 @@ class ExampleController extends Controller {
   async dbOperation(args) {
     const { service } = this;
     const paramsObj = args;
-    //console.log('eeeee paramsObj:', paramsObj);
+    //Log.info('eeeee paramsObj:', paramsObj);
     const data = {
       action: paramsObj.action,
       result: null,
@@ -87,7 +86,7 @@ class ExampleController extends Controller {
   async sqlitedbOperation(args) {
     const { service } = this;
     const paramsObj = args;
-    //console.log('eeeee paramsObj:', paramsObj);
+    //Log.info('eeeee paramsObj:', paramsObj);
     const data = {
       action: paramsObj.action,
       result: null,
@@ -196,6 +195,7 @@ class ExampleController extends Controller {
       content = args.content;
     }
 
+    // electron实验性功能,慎用
     browserViewObj = new BrowserView();
     this.app.electron.mainWindow.setBrowserView(browserViewObj)
     browserViewObj.setBounds({
@@ -212,6 +212,7 @@ class ExampleController extends Controller {
    * 移除视图内容
    */
   removeViewContent () {
+    // removeBrowserView移除视图后,进程依然存在,估计是electron bug
     this.app.electron.mainWindow.removeBrowserView(browserViewObj);
     return true
   }  
@@ -276,9 +277,9 @@ class ExampleController extends Controller {
   //   const chromeExtensionDir = chromeExtension.getDirectory();
   //   const extensionDir = path.join(chromeExtensionDir, extensionId);
 
-  //   console.log("[api] [example] [loadExtension] extension id:", extensionId);
+  //   Log.info("[api] [example] [loadExtension] extension id:", extensionId);
   //   unzip(crxFile, extensionDir).then(() => {    
-  //     console.log("[api] [example] [loadExtension] unzip success!");
+  //     Log.info("[api] [example] [loadExtension] unzip success!");
   //     chromeExtension.load(extensionId);
   //   });
 
@@ -404,7 +405,7 @@ class ExampleController extends Controller {
       // 数组,只取一个吧
       res = resArr[0];
     }
-    // console.log('[electron] [ipc] [example] [getScreen] res:', res);
+    // Log.info('[electron] [ipc] [example] [getScreen] res:', res);
     data = [
       {
         title: '分辨率',
@@ -447,8 +448,8 @@ class ExampleController extends Controller {
       return false;
     }
 
-    let softwarePath = path.join(Utils.getExtraResourcesDir(), softName);
-    this.app.logger.info('[openSoftware] softwarePath:', softwarePath);
+    let softwarePath = path.join(Ps.getExtraResourcesDir(), softName);
+    Log.info('[openSoftware] softwarePath:', softwarePath);
 
     // 检查程序是否存在
     if (!fs.existsSync(softwarePath)) {
@@ -537,7 +538,7 @@ class ExampleController extends Controller {
       params,
       body
     }
-    console.log('httpInfo:', httpInfo);
+    Log.info('httpInfo:', httpInfo);
 
     if (!body.id) {
       return false;
@@ -616,7 +617,7 @@ class ExampleController extends Controller {
    * 上传文件
    */  
   async uploadFile() {
-    let tmpDir = Utils.getLogDir();
+    let tmpDir = Ps.getLogDir();
     const files = this.app.request.files;
     let file = files.file;
     
@@ -679,10 +680,32 @@ class ExampleController extends Controller {
   }
 
   /**
+   * 任务
+   */ 
+  someJob (args, event) {
+    let jobId = args.id;
+    if (args.type == 'timer') {
+      let myjob = new ChildJob();
+      myjob.exec('./jobs/example/timer', {jobId});
+  
+      // 监听任务进度
+      const channel = 'controller.example.timerJobProgress';
+      myjob.on('job-timer-progress', (data) => {
+        Log.info('[main-process] from TimerJob data:', data);
+
+        // 发送数据到渲染进程
+        event.reply(`${channel}`, data)
+      })
+    }
+    
+    return;
+  }
+
+  /**
    * 测试接口
    */ 
   hello (args) {
-    console.log('hello ', args);
+    Log.info('hello ', args);
   }   
 }
 

+ 5 - 0
electron/jobs/example/hello.js

@@ -0,0 +1,5 @@
+const Log = require('ee-core/log');
+
+exports.welcome = function () {
+  Log.info('[child-process] [jobs/example/hello] welcome ! ');
+}

+ 46 - 0
electron/jobs/example/timer.js

@@ -0,0 +1,46 @@
+const Job = require('ee-core/jobs/baseJobClass');
+const Loader = require('ee-core/loader');
+const Log = require('ee-core/log');
+const Ps = require('ee-core/ps');
+const Message = require('ee-core/message');
+const Hello = Loader.requireJobsModule('./example/hello');
+
+/**
+ * example - TimerJob
+ * @class
+ */
+class TimerJob extends Job {
+
+  constructor(params) {
+    super();
+    this.params = params;
+  }
+
+  /**
+   * handle()方法是必要的,且会被自动调用
+   */
+  async handle () {
+    Log.info("[child-process] TimerJob params: ", this.params);
+
+    // 计时器任务
+    let childMessage = Message.childMessage;
+    let eventName = 'job-timer-progress';
+    let number = 0;
+    let jobId = this.params.jobId;
+    setInterval(function() {
+      Hello.welcome();
+
+      childMessage.sendToMain(eventName, {jobId, number});
+      number++;
+    }, 1000);
+
+    // 用 setTimeout 模拟任务运行时长
+    // 任务完成后,必须调用 Ps.exit() 方法,让进程退出,否则会常驻内存
+    setTimeout(function(){
+      Ps.exit(1);
+    }, 10 * 1000)
+  }   
+}
+
+TimerJob.toString = () => '[class TimerJob]';
+module.exports = TimerJob;

+ 0 - 1
electron/preload/index.js

@@ -4,7 +4,6 @@
 
 /**
  * 预加载模块入口
- * @param {Object} app - 全局app对象
  */
 module.exports = async (app) => {
 

+ 5 - 4
electron/service/example.js

@@ -1,6 +1,7 @@
 'use strict';
 
-const Service = require('ee-core').Service;
+const { Service } = require('ee-core');
+const Log = require('ee-core/log');
 
 /**
  * 示例服务
@@ -50,14 +51,14 @@ class ExampleService extends Service {
       });
       const result = response.data;
       if (this.app.config.env === 'local') {
-        this.app.logger.info('[ExampleService] [uploadFileToSMMS]: info result:%j', result);
+        Log.info('[ExampleService] [uploadFileToSMMS]: info result:%j', result);
       }
       if (result.code !== 'success') {
-        this.app.logger.error('[ExampleService] [uploadFileToSMMS]: res error result:%j', result);
+        Log.error('[ExampleService] [uploadFileToSMMS]: res error result:%j', result);
       }
       return result;
     } catch (e) {
-      this.app.logger.error('[ExampleService] [uploadFileToSMMS]:  ERROR ', e);
+      Log.error('[ExampleService] [uploadFileToSMMS]:  ERROR ', e);
     }
 
     return res;

+ 6 - 6
electron/service/storage.js

@@ -1,7 +1,7 @@
 'use strict';
 
-const Service = require('ee-core').Service;
-const Storage = require('ee-core').Storage;
+const { Service } = require('ee-core');
+const Storage = require('ee-core/storage');
 const _ = require('lodash');
 const path = require('path');
 
@@ -15,12 +15,12 @@ class StorageService extends Service {
     super(ctx);
 
     // lowdb数据库
-    this.systemDB = Storage.JsonDB.connection('system');
+    this.systemDB = Storage.connection('system');
 
     let lowdbOptions = {
       driver: 'lowdb'
     }
-    this.demoDB = Storage.JsonDB.connection('demo', lowdbOptions);  
+    this.demoDB = Storage.connection('demo', lowdbOptions);  
     this.demoDBKey = {
       test_data: 'test_data'
     };
@@ -34,7 +34,7 @@ class StorageService extends Service {
         verbose: console.log // 打印sql语法
       }
     }
-    this.demoSqliteDB = Storage.JsonDB.connection(this.sqliteFile, sqliteOptions);
+    this.demoSqliteDB = Storage.connection(this.sqliteFile, sqliteOptions);
   }
 
   /*
@@ -252,7 +252,7 @@ class StorageService extends Service {
         verbose: console.log
       }
     }
-    this.demoSqliteDB = Storage.JsonDB.connection(dbFile, sqliteOptions);    
+    this.demoSqliteDB = Storage.connection(dbFile, sqliteOptions);    
 
     return;
   }

+ 3 - 1
frontend/src/api/main.js

@@ -34,6 +34,8 @@ const ipcApiRoute = {
   getWCid: 'controller.example.getWCid',
   startJavaServer: 'controller.example.startJavaServer',
   closeJavaServer: 'controller.example.closeJavaServer',
+  someJob: 'controller.example.someJob',
+  timerJobProgress: 'controller.example.timerJobProgress',
   hello: 'controller.example.hello',
 }
 
@@ -52,7 +54,7 @@ const specialIpcRoute = {
 const requestHttp = (uri, parameter) => {
   // url转换
   const config = storage.get('httpServiceConfig');
-  const host = config.server || 'http://127.0.0.1:7071';
+  const host = config.server || 'http://localhost:7071';
   let url = uri.split('.').join('/');
   url = host + '/' + url;
   console.log('url:', url);

+ 5 - 0
frontend/src/config/router.config.js

@@ -52,6 +52,11 @@ export const constantRouterMap = [
             component: () => import('@/views/base/window/Index')
           },
           {
+            path: '/base/jobs/index',
+            name: 'BaseJobsIndex',
+            component: () => import('@/views/base/jobs/Index')
+          },
+          {
             path: '/base/notification/index',
             name: 'BaseNotificationIndex',
             component: () => import('@/views/base/notification/Index')

+ 6 - 0
frontend/src/config/subMenu.js

@@ -39,6 +39,12 @@ export default {
 			pageName: 'BaseSqliteDBIndex',
 			params: {}
 		},
+		'menu_330' : {
+			icon: 'profile',
+			title: '任务',
+			pageName: 'BaseJobsIndex',
+			params: {}
+		},				
 		'menu_400' : {
 			icon: 'profile',
 			title: '视图',

+ 2 - 2
frontend/src/main.js

@@ -4,7 +4,7 @@ import 'ant-design-vue/dist/antd.less';
 import App from './App'
 import router from './router'
 import { VueAxios } from './utils/request'
-import IpcRenderer from '@/utils/ipcRenderer'
+import { ipc } from '@/utils/ipcRenderer'
 
 // 使用antd
 Vue.use(antd)
@@ -13,7 +13,7 @@ Vue.use(antd)
 Vue.use(VueAxios)
 
 // 全局注入IPC通信
-Vue.use(IpcRenderer)
+Vue.prototype.$ipc = ipc
 
 Vue.config.productionTip = false
 

+ 20 - 23
frontend/src/utils/ipcRenderer.js

@@ -1,31 +1,28 @@
-const { ipcRenderer: ipc } = (window.require && window.require('electron')) || window.electron || {}
+const { ipcRenderer: ipc } = (window.require && window.require('electron')) || window.electron || null;
 
 /**
- * 发送异步消息(invoke/handle 模型)
- * @param channel
- * @param param
- * @returns {Promise}
+ * ipc
+ * 官方api说明:https://www.electronjs.org/zh/docs/latest/api/ipc-renderer
+ * 
+ * 属性/方法
+ * ipc.invoke(channel, param) - 发送异步消息(invoke/handle 模型)
+ * ipc.sendSync(channel, param) - 发送同步消息(send/on 模型)
+ * ipc.on(channel, listener) - 监听 channel, 当新消息到达,调用 listener
+ * ipc.once(channel, listener) - 添加一次性 listener 函数
+ * ipc.removeListener(channel, listener) - 为特定的 channel 从监听队列中删除特定的 listener 监听者
+ * ipc.removeAllListeners(channel) - 移除所有的监听器,当指定 channel 时只移除与其相关的所有监听器
+ * ipc.send(channel, ...args) - 通过channel向主进程发送异步消息
+ * ipc.postMessage(channel, message, [transfer]) - 发送消息到主进程
+ * ipc.sendTo(webContentsId, channel, ...args) - 通过 channel 发送消息到带有 webContentsId 的窗口
+ * ipc.sendToHost(channel, ...args) - 消息会被发送到 host 页面上的 <webview> 元素
  */
-const invoke = (channel, param) => {
-  const message = ipc.invoke(channel, param);
-  return message;
-}
 
 /**
- * 发送同步消息(send/on 模型)
- * @param channel
- * @param param
- * @returns {Any}
+ * 是否为EE环境
  */
-const sendSync = (channel, param) => {
-  const message = ipc.sendSync(channel, param);
-  return message;
-}
+const isEE = ipc ? true : false;
 
-export default {
-  install(Vue) {
-    Vue.prototype.$ipc = ipc // 全局注入ipc
-    Vue.prototype.$ipcInvoke = invoke
-    Vue.prototype.$ipcSendSync = sendSync
-  }
+export {
+  ipc,
+  isEE
 }

+ 2 - 2
frontend/src/views/base/db/Index.vue

@@ -156,7 +156,7 @@ export default {
       const params = {
         action: 'all',
       }
-      this.$ipcInvoke(ipcApiRoute.dbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.dbOperation, params).then(res => {
         console.log('res:', res);
         if (res.all_list.length == 0) {
           return false;
@@ -180,7 +180,7 @@ export default {
       if (ac == 'add' && this.name.length == 0) {
         self.$message.error(`请填写数据`);
       }
-      this.$ipcInvoke(ipcApiRoute.dbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.dbOperation, params).then(res => {
         console.log('res:', res);
         if (ac == 'get') {
           if (res.result.length == 0) {

+ 6 - 7
frontend/src/views/base/file/Index.vue

@@ -111,28 +111,27 @@ export default {
   methods: {
     getHost () {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.checkHttpServer, {}).then(r => {
+      this.$ipc.invoke(ipcApiRoute.checkHttpServer, {}).then(r => {
         if (r.enable) {
           self.servicAddress = r.server;
           storage.set('httpServiceConfig', r);
 
           // url转换
-          const host = r.server || 'http://127.0.0.1:7071';
+          const host = r.server || 'http://localhost:7071';
           let uri = ipcApiRoute.uploadFile;
           let url = uri.split('.').join('/');
           this.action_url = host + '/' + url;
         }
-        console.log('action_url:', this.action_url);
       })
     },
     openDirectry (id) {
-      this.$ipcInvoke(ipcApiRoute.openDirectory, {id: id}).then(res => {
+      this.$ipc.invoke(ipcApiRoute.openDirectory, {id: id}).then(res => {
         //console.log('res:', res)
       })      
     },
     selectDir() {
       const self = this;
-      self.$ipcInvoke(ipcApiRoute.selectFolder, '').then(r => {
+      this.$ipc.invoke(ipcApiRoute.selectFolder, '').then(r => {
         self.dir_path = r;
         self.$message.info(r);
       })      
@@ -140,14 +139,14 @@ export default {
 		messageShow(type) {
       const self = this;
       console.log('[messageShow] type:', type)
-      this.$ipcInvoke(ipcApiRoute.messageShow, '').then(r => {
+      this.$ipc.invoke(ipcApiRoute.messageShow, '').then(r => {
         self.$message.info(r);
       })
     },    
     messageShowConfirm(type) {
       const self = this;
       console.log('[messageShowConfirm] type:', type)
-      this.$ipcInvoke(ipcApiRoute.messageShowConfirm, '').then(r => {
+      this.$ipc.invoke(ipcApiRoute.messageShowConfirm, '').then(r => {
         self.$message.info(r);
       })
     },

+ 75 - 0
frontend/src/views/base/jobs/Index.vue

@@ -0,0 +1,75 @@
+<template>
+  <div id="app-base-jobs">
+    <div class="one-block-1">
+      <span>
+        1. 任务/并发任务
+      </span>
+    </div>  
+    <div class="one-block-2">
+      <a-space>
+        <a-button @click="runJob(1)">执行任务1</a-button>
+        进度:{{ progress1 }}
+      </a-space>
+      <p></p>
+      <a-space>
+        <a-button @click="runJob(2)">执行任务2</a-button>
+        进度:{{ progress2 }}
+      </a-space>            
+    </div>        
+  </div>
+</template>
+<script>
+import { ipcApiRoute } from '@/api/main'
+export default {
+  data() {
+    return {
+      progress1: 0,
+      progress2: 0,
+    }
+  },
+  mounted () {
+    this.init();
+  },
+  methods: {
+    init () {
+      // 避免重复监听,或者将 on 功能写到一个统一的地方,只加载一次
+      this.$ipc.removeAllListeners(ipcApiRoute.timerJobProgress);
+
+      // 监听任务进度
+      this.$ipc.on(ipcApiRoute.timerJobProgress, (event, result) => {
+        console.log('[ipcRenderer] [someJob] result:', result);
+
+        switch (result.jobId) {
+          case 1:
+            this.progress1 = result.number;
+            break;
+          case 2:
+            this.progress2 = result.number;
+            break;
+        }
+      })
+    },
+    runJob(jobId) {
+      let params = {
+        id: jobId,
+        type: 'timer'
+      }
+      this.$ipc.send(ipcApiRoute.someJob, params)
+    },
+  }
+}
+</script>
+<style lang="less" scoped>
+#app-base-jobs {
+  padding: 0px 10px;
+  text-align: left;
+  width: 100%;
+  .one-block-1 {
+    font-size: 16px;
+    padding-top: 10px;
+  }
+  .one-block-2 {
+    padding-top: 10px;
+  }
+}
+</style>

+ 1 - 1
frontend/src/views/base/powermonitor/Index.vue

@@ -32,7 +32,7 @@ export default {
     init () {
       const self = this;
       this.$ipc.removeAllListeners(ipcApiRoute.initPowerMonitor);
-      self.$ipc.on(ipcApiRoute.initPowerMonitor, (event, result) => {
+      this.$ipc.on(ipcApiRoute.initPowerMonitor, (event, result) => {
         if (Object.prototype.toString.call(result) == '[object Object]') {
           self.currentStatus = result.msg;
           self.$message.info(result.msg);

+ 1 - 1
frontend/src/views/base/screen/Index.vue

@@ -40,7 +40,7 @@ export default {
   methods: {
     getScreen (index) {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.getScreen, index).then(result => {
+      this.$ipc.invoke(ipcApiRoute.getScreen, index).then(result => {
         self.data = result;
       })
     },

+ 1 - 1
frontend/src/views/base/socket/HttpServer.vue

@@ -40,7 +40,7 @@ export default {
   methods: {
     init () {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.checkHttpServer, {}).then(r => {
+      this.$ipc.invoke(ipcApiRoute.checkHttpServer, {}).then(r => {
         if (r.enable) {
           self.currentStatus = '开启';
           self.servicAddress = r.server;

+ 5 - 5
frontend/src/views/base/socket/Ipc.vue

@@ -112,28 +112,28 @@ export default {
     },
     handleInvoke () {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.ipcInvokeMsg, '异步-回调').then(r => {
+      this.$ipc.invoke(ipcApiRoute.ipcInvokeMsg, '异步-回调').then(r => {
         console.log('r:', r);
         self.message1 = r;
       });
     },
     async handleInvoke2 () {
-      const msg = await this.$ipcInvoke(ipcApiRoute.ipcInvokeMsg, '异步');
+      const msg = await this.$ipc.invoke(ipcApiRoute.ipcInvokeMsg, '异步');
       console.log('msg:', msg);
       this.message2 = msg;
     },
     handleSendSync () {
-      const msg = this.$ipcSendSync(ipcApiRoute.ipcSendSyncMsg, '同步');
+      const msg = this.$ipc.sendSync(ipcApiRoute.ipcSendSyncMsg, '同步');
       this.message3 = msg;
     },
     createWindow (index) {
-      this.$ipcInvoke(ipcApiRoute.createWindow, this.views[index]).then(id => {
+      this.$ipc.invoke(ipcApiRoute.createWindow, this.views[index]).then(id => {
         console.log('[createWindow] id:', id);
       })
     },
     async sendTosubWindow () {
       // 新窗口id
-      this.newWcId = await this.$ipcInvoke(ipcApiRoute.getWCid, this.windowName);
+      this.newWcId = await this.$ipc.invoke(ipcApiRoute.getWCid, this.windowName);
       this.$ipc.sendTo(this.newWcId, specialIpcRoute.window1ToWindow2, '窗口1通过 sendTo 给窗口2发送消息');
     },
   }

+ 1 - 1
frontend/src/views/base/socket/SocketServer.vue

@@ -31,7 +31,7 @@ export default {
   data() {
     return {
       currentStatus: '关闭',
-      servicAddress: 'ws://127.0.0.1:7070'
+      servicAddress: 'ws://localhost:7070'
     };
   },
   mounted () {

+ 1 - 1
frontend/src/views/base/software/Index.vue

@@ -40,7 +40,7 @@ export default {
   methods: {
     openSoft (id) {
       const self = this;   
-      this.$ipcInvoke(ipcApiRoute.openSoftware, id).then(result => {
+      this.$ipc.invoke(ipcApiRoute.openSoftware, id).then(result => {
         if (!result) {
           self.$message.error('程序不存在');
         }

+ 6 - 6
frontend/src/views/base/sqlitedb/Index.vue

@@ -181,7 +181,7 @@ export default {
       const params = {
         action: 'getDataDir',
       }
-      this.$ipcInvoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
         this.data_dir = res.result;
       }) 
     },
@@ -190,7 +190,7 @@ export default {
       const params = {
         action: 'all',
       }
-      this.$ipcInvoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
         if (res.all_list.length == 0) {
           return false;
         }
@@ -198,7 +198,7 @@ export default {
       }) 
     },
     selectDir() {
-      this.$ipcInvoke(ipcApiRoute.selectFolder, '').then(r => {
+      this.$ipc.invoke(ipcApiRoute.selectFolder, '').then(r => {
         this.data_dir = r;
         // 修改数据目录
         this.modifyDataDir(r);
@@ -206,7 +206,7 @@ export default {
     },
     openDir() {
       console.log('dd:', this.data_dir);
-      this.$ipcInvoke(ipcApiRoute.openDirectory, {id: this.data_dir}).then(res => {
+      this.$ipc.invoke(ipcApiRoute.openDirectory, {id: this.data_dir}).then(res => {
         //
       })
     },    
@@ -215,7 +215,7 @@ export default {
         action: 'setDataDir',
         data_dir: dir
       }
-      this.$ipcInvoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
         this.all_list = res.all_list;
       }) 
     },
@@ -235,7 +235,7 @@ export default {
       if (ac == 'add' && this.name.length == 0) {
         self.$message.error(`请填写数据`);
       }
-      this.$ipcInvoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.sqlitedbOperation, params).then(res => {
         console.log('res:', res);
         if (ac == 'get') {
           if (res.result.length == 0) {

+ 4 - 4
frontend/src/views/base/subwindow/Ipc.vue

@@ -102,23 +102,23 @@ export default {
     },
     handleInvoke () {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.ipcInvokeMsg, '异步-回调').then(r => {
+      this.$ipc.invoke(ipcApiRoute.ipcInvokeMsg, '异步-回调').then(r => {
         console.log('r:', r);
         self.message1 = r;
       });
     },
     async handleInvoke2 () {
-      const msg = await this.$ipcInvoke(ipcApiRoute.ipcInvokeMsg, '异步');
+      const msg = await this.$ipc.invoke(ipcApiRoute.ipcInvokeMsg, '异步');
       console.log('msg:', msg);
       this.message2 = msg;
     },
     handleSendSync () {
-      const msg = this.$ipcSendSync(ipcApiRoute.ipcSendSyncMsg, '同步');
+      const msg = this.$ipc.sendSync(ipcApiRoute.ipcSendSyncMsg, '同步');
       this.message3 = msg;
     },
     sendTosubWindow () {
       // 获取主窗口id
-      this.$ipcInvoke(ipcApiRoute.getWCid, 'main').then(id => {
+      this.$ipc.invoke(ipcApiRoute.getWCid, 'main').then(id => {
         this.mainWCid = id;
         this.$ipc.sendTo(this.mainWCid, specialIpcRoute.window2ToWindow1, '窗口2 通过 sendTo 给主窗口发送消息');
       });

+ 1 - 2
frontend/src/views/base/system/Index.vue

@@ -36,8 +36,7 @@ export default {
   methods: {
     init () {
       // todo .....
-      const self = this;
-      self.$ipcInvoke(ipcApiRoute.autoLaunch, 'check').then(result => {
+      this.$ipc.invoke(ipcApiRoute.autoLaunch, 'check').then(result => {
         console.log('[ipcRenderer] [autoLaunch] result:', result)
         this.autoLaunchChecked = result.status;
       })      

+ 1 - 1
frontend/src/views/base/testapi/Index.vue

@@ -27,7 +27,7 @@ export default {
       const params = {
         id: id
       }
-      this.$ipcInvoke(ipcApiRoute.test, params).then(res => {
+      this.$ipc.invoke(ipcApiRoute.test, params).then(res => {
         console.log('res:', res)
       }) 
     },

+ 2 - 2
frontend/src/views/base/theme/Index.vue

@@ -53,14 +53,14 @@ export default {
       this.currentThemeMode = e.target.value;
       console.log('setTheme currentThemeMode:', this.currentThemeMode)
 
-      this.$ipcInvoke(ipcApiRoute.setTheme, this.currentThemeMode).then(result => {
+      this.$ipc.invoke(ipcApiRoute.setTheme, this.currentThemeMode).then(result => {
         console.log('result:', result)
         self.currentThemeMode = result;
       })      
     },
     getTheme () {
       const self = this;
-      this.$ipcInvoke(ipcApiRoute.getTheme).then(result => {
+      this.$ipc.invoke(ipcApiRoute.getTheme).then(result => {
         console.log('result:', result)
         self.currentThemeMode = result;
       })  

+ 2 - 2
frontend/src/views/base/updater/Index.vue

@@ -54,7 +54,7 @@ export default {
       })
     },
     checkForUpdater () {
-      this.$ipcInvoke(ipcApiRoute.checkForUpdater).then(r => {
+      this.$ipc.invoke(ipcApiRoute.checkForUpdater).then(r => {
         console.log(r);
       })
     },
@@ -63,7 +63,7 @@ export default {
         this.$message.info('没有可用版本');
         return
       }
-      this.$ipcInvoke(ipcApiRoute.downloadApp).then(r => {
+      this.$ipc.invoke(ipcApiRoute.downloadApp).then(r => {
         console.log(r);
       })
     },

+ 1 - 1
frontend/src/views/base/window/Index.vue

@@ -56,7 +56,7 @@ export default {
   },
   methods: {
     createWindow (index) {
-      this.$ipcInvoke(ipcApiRoute.createWindow, this.views[index]).then(r => {
+      this.$ipc.invoke(ipcApiRoute.createWindow, this.views[index]).then(r => {
         console.log(r);
       })
     },

+ 2 - 4
frontend/src/views/base/windowview/Index.vue

@@ -44,14 +44,12 @@ export default {
   },
   methods: {
     loadViewContent (index) {
-      const self = this;
-      self.$ipcInvoke(ipcApiRoute.loadViewContent, this.views[index]).then(r => {
+      this.$ipc.invoke(ipcApiRoute.loadViewContent, this.views[index]).then(r => {
         console.log(r);
       })
     },
     removeViewContent (index) {
-      const self = this;
-      self.$ipcInvoke(ipcApiRoute.removeViewContent, self.views[index]).then(r => {
+      this.$ipc.invoke(ipcApiRoute.removeViewContent, self.views[index]).then(r => {
         console.log(r);
       })
     },

+ 2 - 2
frontend/src/views/other/java/Index.vue

@@ -29,7 +29,7 @@ export default {
   },  
   methods: {
     startServer () {
-      this.$ipcInvoke(ipcApiRoute.startJavaServer, {}).then(r => {
+      this.$ipc.invoke(ipcApiRoute.startJavaServer, {}).then(r => {
         if (r.code != 0) {
           this.$message.error(r.msg);
         }
@@ -39,7 +39,7 @@ export default {
     },
 
     closeServer () {
-      this.$ipcInvoke(ipcApiRoute.closeJavaServer, {}).then(r => {
+      this.$ipc.invoke(ipcApiRoute.closeJavaServer, {}).then(r => {
         if (r.code != 0) {
           this.$message.error(r.msg);
         }

+ 4 - 2
main.js

@@ -1,4 +1,5 @@
-const Appliaction = require('ee-core').Appliaction;
+const { Appliaction } = require('ee-core');
+const EE = require('ee-core/ee');
 
 class Main extends Appliaction {
 
@@ -45,5 +46,6 @@ class Main extends Appliaction {
   }
 }
 
-new Main();
+// Instantiate an app object
+EE.app = new Main();
  

+ 2 - 3
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ee",
-  "version": "2.5.0",
+  "version": "3.0.0",
   "description": "A fast, desktop software development framework",
   "main": "main.js",
   "scripts": {
@@ -111,8 +111,7 @@
   "dependencies": {
     "better-sqlite3": "^7.6.0",
     "dayjs": "^1.10.7",
-    "ee-core": "^1.5.1",
-    "electron-is": "^3.0.0",
+    "ee-core": "^2.0.0",
     "electron-updater": "^5.3.0",
     "lodash": "^4.17.21"
   }