diff --git a/README.md b/README.md
index 3d3a358..82ea4d2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
[](https://gitee.com/dromara/electron-egg/stargazers)
-
🎉🎉🎉 ElectronEgg V3.14.0已发布! 🎉🎉🎉
+🎉🎉🎉 ElectronEgg v4.0.0 已发布! 🎉🎉🎉
@@ -32,7 +32,7 @@
## 📺 特点
- 🍩 **为什么使用?** 桌面软件(办公方向、 个人工具),仍然是未来十几年PC端需求之一,提高工作效率
-- 🍉 **简单:** 只需懂 JavaScript
+- 🍉 **简单:** 支持 js、ts
- 🍑 **愿景:** 所有开发者都能学会桌面软件研发
- 🍰 **gitee:** https://gitee.com/dromara/electron-egg **5200+**
- 🍨 **github:** https://github.com/dromara/electron-egg **1900+**
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 241826a..82ea4d2 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,7 +1,7 @@
[](https://gitee.com/dromara/electron-egg/stargazers)
-
🎉🎉🎉 ElectronEgg V3.15.0已发布! 🎉🎉🎉
+🎉🎉🎉 ElectronEgg v4.0.0 已发布! 🎉🎉🎉
@@ -32,7 +32,7 @@
## 📺 特点
- 🍩 **为什么使用?** 桌面软件(办公方向、 个人工具),仍然是未来十几年PC端需求之一,提高工作效率
-- 🍉 **简单:** 只需懂 JavaScript
+- 🍉 **简单:** 支持 js、ts
- 🍑 **愿景:** 所有开发者都能学会桌面软件研发
- 🍰 **gitee:** https://gitee.com/dromara/electron-egg **5200+**
- 🍨 **github:** https://github.com/dromara/electron-egg **1900+**
diff --git a/build/extraResources/chromeExtension/read.txt b/build/extraResources/chromeExtension/read.txt
deleted file mode 100644
index 57b4b84..0000000
--- a/build/extraResources/chromeExtension/read.txt
+++ /dev/null
@@ -1 +0,0 @@
-chrome应用商店ctx文件,解压后,放置在此目录中,打包时会将资源加入安装包内。
\ No newline at end of file
diff --git a/cmd/bin.js b/cmd/bin.js
new file mode 100644
index 0000000..c00e5a3
--- /dev/null
+++ b/cmd/bin.js
@@ -0,0 +1,195 @@
+/**
+ * ee-bin 配置
+ * 仅适用于开发环境
+ */
+module.exports = {
+ /**
+ * development serve ("frontend" "electron" )
+ * ee-bin dev
+ */
+ dev: {
+ frontend: {
+ directory: './frontend',
+ cmd: 'npm',
+ args: ['run', 'dev'],
+ port: 8080,
+ },
+ electron: {
+ directory: './',
+ cmd: 'electron',
+ args: ['.', '--env=local'],
+ watch: true,
+ }
+ },
+
+ /**
+ * 构建
+ * ee-bin build
+ */
+ build: {
+ frontend: {
+ directory: './frontend',
+ cmd: 'npm',
+ args: ['run', 'build'],
+ },
+ electron: {
+ type: 'javascript',
+ bundleType: 'copy'
+ },
+ win64: {
+ cmd: 'electron-builder',
+ directory: './',
+ args: ['--config=./cmd/builder.json', '-w=nsis', '--x64'],
+ },
+ win32: {
+ args: ['--config=./cmd/builder.json', '-w=nsis', '--ia32'],
+ },
+ win_e: {
+ args: ['--config=./cmd/builder.json', '-w=portable', '--x64'],
+ },
+ win_7z: {
+ args: ['--config=./cmd/builder.json', '-w=7z', '--x64'],
+ },
+ mac: {
+ args: ['--config=./cmd/builder-mac.json', '-m'],
+ },
+ mac_arm64: {
+ args: ['--config=./cmd/builder-mac-arm64.json', '-m', '--arm64'],
+ },
+ linux: {
+ args: ['--config=./cmd/builder-linux.json', '-l=deb', '--x64'],
+ },
+ linux_arm64: {
+ args: ['--config=./cmd/builder-linux.json', '-l=deb', '--arm64'],
+ },
+ go_w: {
+ directory: './go',
+ cmd: 'go',
+ args: ['build', '-o=../build/extraResources/goapp.exe'],
+ },
+ go_m: {
+ directory: './go',
+ cmd: 'go',
+ args: ['build', '-o=../build/extraResources/goapp'],
+ },
+ go_l: {
+ directory: './go',
+ cmd: 'go',
+ args: ['build', '-o=../build/extraResources/goapp'],
+ },
+ python: {
+ directory: './python',
+ cmd: 'python',
+ args: ['./setup.py', 'build'],
+ },
+ },
+
+ /**
+ * 移动资源
+ * ee-bin move
+ */
+ move: {
+ frontend_dist: {
+ src: './frontend/dist',
+ dest: './public/dist'
+ },
+ go_static: {
+ src: './frontend/dist',
+ dest: './go/public/dist'
+ },
+ go_config: {
+ src: './go/config',
+ dest: './go/public/config'
+ },
+ go_package: {
+ src: './package.json',
+ dest: './go/public/package.json'
+ },
+ go_images: {
+ src: './public/images',
+ dest: './go/public/images'
+ },
+ python_dist: {
+ src: './python/dist',
+ dest: './build/extraResources/py'
+ },
+ },
+
+ /**
+ * 预发布模式(prod)
+ * ee-bin start
+ */
+ start: {
+ directory: './',
+ cmd: 'electron',
+ args: ['.', '--env=prod']
+ },
+
+ /**
+ * 加密
+ */
+ encrypt: {
+ frontend: {
+ type: 'none',
+ files: [
+ './public/dist/**/*.(js|json)',
+ ],
+ cleanFiles: ['./public/dist'],
+ confusionOptions: {
+ compact: true,
+ stringArray: true,
+ stringArrayEncoding: ['none'],
+ stringArrayCallsTransform: true,
+ numbersToExpressions: true,
+ target: 'browser',
+ }
+ },
+ electron: {
+ type: 'confusion',
+ files: [
+ './public/electron/**/*.(js|json)',
+ ],
+ cleanFiles: ['./public/electron'],
+ confusionOptions: {
+ compact: true,
+ stringArray: true,
+ stringArrayEncoding: ['rc4'],
+ deadCodeInjection: false,
+ stringArrayCallsTransform: true,
+ numbersToExpressions: true,
+ target: 'node',
+ }
+ }
+ },
+
+ /**
+ * 执行自定义命令
+ * ee-bin exec
+ */
+ exec: {
+ // 单独调试,air 实现 go 热重载
+ go: {
+ directory: './go',
+ cmd: 'air',
+ args: ['-c=config/.air.toml' ],
+ },
+ // windows 单独调试,air 实现 go 热重载
+ go_w: {
+ directory: './go',
+ cmd: 'air',
+ args: ['-c=config/.air.windows.toml' ],
+ },
+ // 单独调试,以基础方式启动 go
+ go2: {
+ directory: './go',
+ cmd: 'go',
+ args: ['run', './main.go', '--env=dev','--basedir=../', '--port=7073'],
+ },
+ python: {
+ directory: './python',
+ cmd: 'python',
+ args: ['./main.py', '--port=7074'],
+ stdio: "inherit", // ignore
+ },
+ },
+};
\ No newline at end of file
diff --git a/cmd/builder-linux.json b/cmd/builder-linux.json
new file mode 100644
index 0000000..eb4dfb2
--- /dev/null
+++ b/cmd/builder-linux.json
@@ -0,0 +1,40 @@
+{
+ "productName": "ee",
+ "appId": "com.bilibili.ee",
+ "copyright": "© 2025 duola Technology Co., Ltd.",
+ "directories": {
+ "output": "out"
+ },
+ "asar": true,
+ "files": [
+ "**/*",
+ "!cmd/",
+ "!data/",
+ "!electron/",
+ "!frontend/",
+ "!logs/",
+ "!out/",
+ "!go/",
+ "!python/"
+ ],
+ "extraResources": [
+ {
+ "from": "build/extraResources",
+ "to": "extraResources"
+ }
+ ],
+ "publish": [
+ {
+ "provider": "generic",
+ "url": ""
+ }
+ ],
+ "linux": {
+ "icon": "build/icons/icon.icns",
+ "artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
+ "target": [
+ "deb"
+ ],
+ "category": "Utility"
+ }
+}
\ No newline at end of file
diff --git a/cmd/builder-mac-arm64.json b/cmd/builder-mac-arm64.json
new file mode 100644
index 0000000..b110fc6
--- /dev/null
+++ b/cmd/builder-mac-arm64.json
@@ -0,0 +1,38 @@
+{
+ "productName": "ee",
+ "appId": "com.bilibili.ee",
+ "copyright": "© 2025 duola Technology Co., Ltd.",
+ "directories": {
+ "output": "out"
+ },
+ "asar": true,
+ "files": [
+ "**/*",
+ "!cmd/",
+ "!data/",
+ "!electron/",
+ "!frontend/",
+ "!logs/",
+ "!out/",
+ "!go/",
+ "!python/"
+ ],
+ "extraResources": [
+ {
+ "from": "build/extraResources",
+ "to": "extraResources"
+ }
+ ],
+ "publish": [
+ {
+ "provider": "generic",
+ "url": ""
+ }
+ ],
+ "mac": {
+ "icon": "build/icons/icon.icns",
+ "artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
+ "darkModeSupport": true,
+ "hardenedRuntime": false
+ }
+}
\ No newline at end of file
diff --git a/cmd/builder-mac.json b/cmd/builder-mac.json
new file mode 100644
index 0000000..b110fc6
--- /dev/null
+++ b/cmd/builder-mac.json
@@ -0,0 +1,38 @@
+{
+ "productName": "ee",
+ "appId": "com.bilibili.ee",
+ "copyright": "© 2025 duola Technology Co., Ltd.",
+ "directories": {
+ "output": "out"
+ },
+ "asar": true,
+ "files": [
+ "**/*",
+ "!cmd/",
+ "!data/",
+ "!electron/",
+ "!frontend/",
+ "!logs/",
+ "!out/",
+ "!go/",
+ "!python/"
+ ],
+ "extraResources": [
+ {
+ "from": "build/extraResources",
+ "to": "extraResources"
+ }
+ ],
+ "publish": [
+ {
+ "provider": "generic",
+ "url": ""
+ }
+ ],
+ "mac": {
+ "icon": "build/icons/icon.icns",
+ "artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
+ "darkModeSupport": true,
+ "hardenedRuntime": false
+ }
+}
\ No newline at end of file
diff --git a/electron/config/builder.json b/cmd/builder.json
similarity index 65%
rename from electron/config/builder.json
rename to cmd/builder.json
index 0fef3ea..c1c2a05 100644
--- a/electron/config/builder.json
+++ b/cmd/builder.json
@@ -1,17 +1,21 @@
{
"productName": "ee",
"appId": "com.electron.ee",
- "copyright": "© 2025 哆啦好梦 Technology Co., Ltd.",
+ "copyright": "© 2025 duola Technology Co., Ltd.",
"directories": {
"output": "out"
},
"asar": true,
"files": [
"**/*",
+ "!cmd/",
+ "!data/",
+ "!electron/",
"!frontend/",
- "!run/",
"!logs/",
- "!data/"
+ "!out/",
+ "!go/",
+ "!python/"
],
"extraResources": {
"from": "build/extraResources/",
@@ -26,7 +30,7 @@
"installerHeaderIcon": "build/icons/icon.ico",
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
- "shortcutName": "EE框架"
+ "shortcutName": "ee"
},
"publish": [
{
@@ -34,12 +38,6 @@
"url": "https://github.com/wallace5303/electron-egg"
}
],
- "mac": {
- "icon": "build/icons/icon.icns",
- "artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
- "darkModeSupport": true,
- "hardenedRuntime": false
- },
"win": {
"icon": "build/icons/icon.ico",
"artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
@@ -48,13 +46,5 @@
"target": "nsis"
}
]
- },
- "linux": {
- "icon": "build/icons/icon.icns",
- "artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
- "target": [
- "deb"
- ],
- "category": "Utility"
}
}
\ No newline at end of file
diff --git a/electron/addon/autoUpdater/index.js b/electron/addon/autoUpdater/index.js
deleted file mode 100644
index 63baf58..0000000
--- a/electron/addon/autoUpdater/index.js
+++ /dev/null
@@ -1,170 +0,0 @@
-const { app: electronApp } = require('electron');
-const { autoUpdater } = require("electron-updater");
-const is = require('ee-core/utils/is');
-const Log = require('ee-core/log');
-const Conf = require('ee-core/config');
-const CoreWindow = require('ee-core/electron/window');
-const Electron = require('ee-core/electron');
-
-/**
- * 自动升级插件
- * @class
- */
-class AutoUpdaterAddon {
-
- constructor() {
- }
-
- /**
- * 创建
- */
- create () {
- Log.info('[addon:autoUpdater] load');
- const cfg = Conf.getValue('addons.autoUpdater');
- if ((is.windows() && cfg.windows)
- || (is.macOS() && cfg.macOS)
- || (is.linux() && cfg.linux))
- {
- // continue
- } else {
- return
- }
-
- // 是否检查更新
- if (cfg.force) {
- this.checkUpdate();
- }
-
- const status = {
- error: -1,
- available: 1,
- noAvailable: 2,
- downloading: 3,
- downloaded: 4,
- }
-
- const version = electronApp.getVersion();
- Log.info('[addon:autoUpdater] current version: ', version);
-
- // 设置下载服务器地址
- let server = cfg.options.url;
- let lastChar = server.substring(server.length - 1);
- server = lastChar === '/' ? server : server + "/";
- //Log.info('[addon:autoUpdater] server: ', server);
- cfg.options.url = server;
-
- // 是否后台自动下载
- autoUpdater.autoDownload = cfg.force ? true : false;
-
- try {
- autoUpdater.setFeedURL(cfg.options);
- } catch (error) {
- Log.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
- }
- Log.info('[addon:autoUpdater] progress: ', text);
- this.sendStatusToWindow(info);
- })
- autoUpdater.on('update-downloaded', (info) => {
- info.status = status.downloaded;
- info.desc = '下载完成';
- this.sendStatusToWindow(info);
-
- // 托盘插件默认会阻止窗口关闭,这里设置允许关闭窗口
- Electron.extra.closeWindow = true;
-
- autoUpdater.quitAndInstall();
- // const mainWindow = CoreWindow.getMainWindow();
- // if (mainWindow) {
- // mainWindow.destroy()
- // }
- // electronApp.appQuit()
- });
- }
-
- /**
- * 检查更新
- */
- checkUpdate () {
- autoUpdater.checkForUpdates();
- }
-
- /**
- * 下载更新
- */
- download () {
- autoUpdater.downloadUpdate();
- }
-
- /**
- * 向前端发消息
- */
- sendStatusToWindow(content = {}) {
- const textJson = JSON.stringify(content);
- const channel = 'app.updater';
- 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;
- }
-}
-
-AutoUpdaterAddon.toString = () => '[class AutoUpdaterAddon]';
-module.exports = AutoUpdaterAddon;
\ No newline at end of file
diff --git a/electron/addon/awaken/index.js b/electron/addon/awaken/index.js
deleted file mode 100644
index e4c8a35..0000000
--- a/electron/addon/awaken/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-const { app: electronApp } = require('electron');
-const Log = require('ee-core/log');
-const Conf = require('ee-core/config');
-
-/**
- * 唤醒插件
- * @class
- */
-class AwakenAddon {
-
- constructor() {
- this.protocol = '';
- }
-
- /**
- * 创建
- */
- create () {
- Log.info('[addon:awaken] load');
-
- const cfg = Conf.getValue('addons.awaken');
- this.protocol = cfg.protocol;
-
- electronApp.setAsDefaultProtocolClient(this.protocol);
-
- this.handleArgv(process.argv);
- electronApp.on('second-instance', (event, argv) => {
- if (process.platform === 'win32') {
- this.handleArgv(argv)
- }
- })
-
- // 仅用于macOS
- electronApp.on('open-url', (event, urlStr) => {
- this.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)
- }
- Log.info('[addon:awaken] awakeUrlInfo:', awakeUrlInfo);
- }
-}
-
-AwakenAddon.toString = () => '[class AwakenAddon]';
-module.exports = AwakenAddon;
\ No newline at end of file
diff --git a/electron/addon/chromeExtension/index.js b/electron/addon/chromeExtension/index.js
deleted file mode 100644
index 28ec636..0000000
--- a/electron/addon/chromeExtension/index.js
+++ /dev/null
@@ -1,94 +0,0 @@
-const { app, session } = require('electron');
-const _ = require('lodash');
-const fs = require('fs');
-const path = require('path');
-const Log = require('ee-core/log');
-
-/**
- * 扩展插件 (electron自身对该功能并不完全支持,官方也不建议使用)
- * @class
- */
-class ChromeExtensionAddon {
-
- constructor() {
- }
-
- /**
- * 创建
- */
- async create () {
- Log.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 = this.getDirs(extendsionDir);
-
- return ids;
- }
-
- /**
- * 扩展所在目录
- */
- getDirectory () {
- let extensionDirPath = '';
- let variablePath = 'build'; // 打包前路径
- if (app.isPackaged) {
- variablePath = '..'; // 打包后路径
- }
- extensionDirPath = path.join(app.getAppPath(), variablePath, "extraResources", "chromeExtension");
-
- return extensionDirPath;
- }
-
- /**
- * 加载扩展
- */
- async load (extensionId = '') {
- if (_.isEmpty(extensionId)) {
- return false
- }
-
- try {
- const extensionPath = path.join(this.getDirectory(), extensionId);
- Log.info('[addon:chromeExtension] extensionPath:', extensionPath);
- await session.defaultSession.loadExtension(extensionPath, { allowFileAccess: true });
- } catch (e) {
- Log.info('[addon:chromeExtension] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
- return false
- }
-
- return true
- }
-
- /**
- * 获取目录下所有文件夹
- */
- 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);
- }
- });
-
- return components;
- };
-}
-
-ChromeExtensionAddon.toString = () => '[class ChromeExtensionAddon]';
-module.exports = ChromeExtensionAddon;
\ No newline at end of file
diff --git a/electron/addon/security/index.js b/electron/addon/security/index.js
deleted file mode 100644
index 4d87e94..0000000
--- a/electron/addon/security/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const Log = require('ee-core/log');
-const EE = require('ee-core/ee');
-
-/**
- * 安全插件
- * @class
- */
-class SecurityAddon {
-
- constructor() {
- }
-
- /**
- * 创建
- */
- create () {
- Log.info('[addon:security] load');
- const { CoreApp } = EE;
- 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) {
- Log.error('[error] Remote debugging is not allowed, runWithDebug:', runWithDebug);
- CoreApp.appQuit();
- }
- }
-}
-
-SecurityAddon.toString = () => '[class SecurityAddon]';
-module.exports = SecurityAddon;
\ No newline at end of file
diff --git a/electron/addon/tray/index.js b/electron/addon/tray/index.js
deleted file mode 100644
index 106f06f..0000000
--- a/electron/addon/tray/index.js
+++ /dev/null
@@ -1,72 +0,0 @@
-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 CoreWindow = require('ee-core/electron/window');
-const Conf = require('ee-core/config');
-const EE = require('ee-core/ee');
-
-/**
- * 托盘插件
- * @class
- */
-class TrayAddon {
-
- constructor() {
- this.tray = null;
- }
-
- /**
- * 创建托盘
- */
- create () {
- // 开发环境,代码热更新开启时,会导致托盘中有残影
- if (Ps.isDev() && Ps.isHotReload()) return;
-
- Log.info('[addon:tray] load');
- const { CoreApp } = EE;
- const cfg = Conf.getValue('addons.tray');
- const mainWindow = CoreWindow.getMainWindow();
-
- // 托盘图标
- let iconPath = path.join(Ps.getHomeDir(), cfg.icon);
-
- // 托盘菜单功能列表
- let trayMenuTemplate = [
- {
- label: '显示',
- click: function () {
- mainWindow.show();
- }
- },
- {
- label: '退出',
- click: function () {
- CoreApp.appQuit();
- }
- }
- ]
-
- // 点击关闭,最小化到托盘
- mainWindow.on('close', (event) => {
- if (Electron.extra.closeWindow == true) {
- return;
- }
- mainWindow.hide();
- event.preventDefault();
- });
-
- // 实例化托盘
- this.tray = new Tray(iconPath);
- this.tray.setToolTip(cfg.title);
- const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
- this.tray.setContextMenu(contextMenu);
- this.tray.on('double-click', () => {
- mainWindow.show()
- })
- }
-}
-
-TrayAddon.toString = () => '[class TrayAddon]';
-module.exports = TrayAddon;
\ No newline at end of file
diff --git a/electron/config/bin.js b/electron/config/bin.js
deleted file mode 100644
index 62fd44c..0000000
--- a/electron/config/bin.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * ee-bin 配置
- * 仅适用于开发环境
- */
-module.exports = {
- /**
- * development serve ("frontend" "electron" )
- * ee-bin dev
- */
- dev: {
- frontend: {
- directory: './frontend',
- cmd: 'npm',
- args: ['run', 'dev'],
- protocol: 'http://',
- hostname: 'localhost',
- port: 8080,
- indexPath: 'index.html'
- },
- electron: {
- directory: './',
- cmd: 'electron',
- args: ['.', '--env=local', '--color=always'],
- }
- },
-
- /**
- * 构建
- * ee-bin build
- */
- build: {
- frontend: {
- directory: './frontend',
- cmd: 'npm',
- args: ['run', 'build'],
- }
- },
-
- /**
- * 移动资源
- * ee-bin move
- */
- move: {
- frontend_dist: {
- dist: './frontend/dist',
- target: './public/dist'
- }
- },
-
- /**
- * 预发布模式(prod)
- * ee-bin start
- */
- start: {
- directory: './',
- cmd: 'electron',
- args: ['.', '--env=prod']
- },
-
- /**
- * 加密
- */
- encrypt: {
- type: 'confusion',
- files: [
- 'electron/**/*.(js|json)',
- '!electron/config/encrypt.js',
- '!electron/config/nodemon.json',
- '!electron/config/builder.json',
- '!electron/config/bin.json',
- ],
- fileExt: ['.js'],
- confusionOptions: {
- compact: true,
- stringArray: true,
- stringArrayEncoding: ['none'],
- deadCodeInjection: false,
- }
- },
-
- /**
- * 执行自定义命令
- * ee-bin exec
- */
- exec: {
- node_v: {
- directory: './',
- cmd: 'node',
- args: ['-v'],
- },
- npm_v: {
- directory: './',
- cmd: 'npm',
- args: ['-v'],
- },
- },
-};
diff --git a/electron/config/config.default.js b/electron/config/config.default.js
index 9f355a2..70b4719 100644
--- a/electron/config/config.default.js
+++ b/electron/config/config.default.js
@@ -1,179 +1,69 @@
'use strict';
const path = require('path');
+const { getBaseDir } = require('ee-core/ps');
/**
* 默认配置
*/
-module.exports = (appInfo) => {
-
- const config = {};
-
- /**
- * 开发者工具
- */
- config.openDevTools = false;
-
- /**
- * 应用程序顶部菜单
- */
- config.openAppMenu = true;
-
- /**
- * 主窗口
- */
- config.windowsOption = {
- title: 'EE框架',
- width: 980,
- height: 650,
- minWidth: 400,
- minHeight: 300,
- webPreferences: {
- //webSecurity: false,
- contextIsolation: false, // false -> 可在渲染进程中使用electron的api,true->需要bridge.js(contextBridge)
- nodeIntegration: true,
- //preload: path.join(appInfo.baseDir, 'preload', 'bridge.js'),
- },
- frame: true,
- show: false,
- icon: path.join(appInfo.home, 'public', 'images', 'logo-32.png'),
- };
-
- /**
- * ee框架日志
- */
- config.logger = {
- encoding: 'utf8',
- level: 'INFO',
- outputJSON: false,
- buffer: true,
- enablePerformanceTimer: false,
- rotator: 'day',
- appLogName: 'ee.log',
- coreLogName: 'ee-core.log',
- errorLogName: 'ee-error.log'
- }
-
- /**
- * 远程模式-web地址
- */
- config.remoteUrl = {
- enable: false,
- url: 'http://electron-egg.kaka996.com/'
- };
-
- /**
- * 内置socket服务
- */
- config.socketServer = {
- enable: false,
- port: 7070,
- path: "/socket.io/",
- connectTimeout: 45000,
- pingTimeout: 30000,
- pingInterval: 25000,
- maxHttpBufferSize: 1e8,
- transports: ["polling", "websocket"],
- cors: {
- origin: true,
- },
- channel: 'c1'
- };
-
- /**
- * 内置http服务
- */
- config.httpServer = {
- enable: false,
- https: {
- enable: false,
- key: '/public/ssl/localhost+1.key',
- cert: '/public/ssl/localhost+1.pem'
- },
- host: '127.0.0.1',
- port: 7071,
- cors: {
- origin: "*"
- },
- body: {
- multipart: true,
- formidable: {
- keepExtensions: true
- }
- },
- filterRequest: {
- uris: [
- 'favicon.ico'
- ],
- returnData: ''
- }
- };
-
- /**
- * 主进程
- */
- config.mainServer = {
- protocol: 'file://',
- indexPath: '/public/dist/index.html',
- };
-
- /**
- * 硬件加速
- */
- config.hardGpu = {
- enable: true
- };
-
- /**
- * 异常捕获
- */
- config.exception = {
- mainExit: false,
- childExit: true,
- rendererExit: true,
- };
-
- /**
- * jobs
- */
- config.jobs = {
- messageLog: true
- };
-
- /**
- * 插件功能
- */
- config.addons = {
- window: {
- enable: true,
- },
- tray: {
- enable: true,
- title: 'EE程序',
- icon: '/public/images/tray.png'
- },
- security: {
- enable: true,
- },
- awaken: {
- enable: true,
- protocol: 'ee',
- args: []
- },
- autoUpdater: {
- enable: true,
- windows: false,
- macOS: false,
- linux: false,
- options: {
- provider: 'generic',
- url: 'http://kodo.qiniu.com/'
- },
- force: false,
- }
- };
-
+module.exports = () => {
return {
- ...config
- };
+ openDevTools: false,
+ singleLock: true,
+ windowsOption: {
+ title: 'electron-egg',
+ width: 980,
+ height: 650,
+ minWidth: 400,
+ minHeight: 300,
+ webPreferences: {
+ //webSecurity: false,
+ contextIsolation: false, // false -> 可在渲染进程中使用electron的api,true->需要bridge.js(contextBridge)
+ nodeIntegration: true,
+ //preload: path.join(getElectronDir(), 'preload', 'bridge.js'),
+ },
+ frame: true,
+ show: true,
+ icon: path.join(getBaseDir(), 'public', 'images', 'logo-32.png'),
+ },
+ logger: {
+ level: 'INFO',
+ outputJSON: false,
+ appLogName: 'ee.log',
+ coreLogName: 'ee-core.log',
+ errorLogName: 'ee-error.log'
+ },
+ remote: {
+ enable: false,
+ url: 'http://electron-egg.kaka996.com/'
+ },
+ socketServer: {
+ enable: false,
+ port: 7070,
+ path: "/socket.io/",
+ connectTimeout: 45000,
+ pingTimeout: 30000,
+ pingInterval: 25000,
+ maxHttpBufferSize: 1e8,
+ transports: ["polling", "websocket"],
+ cors: {
+ origin: true,
+ },
+ channel: 'socket-channel'
+ },
+ httpServer: {
+ enable: false,
+ https: {
+ enable: false,
+ key: '/public/ssl/localhost+1.key',
+ cert: '/public/ssl/localhost+1.pem'
+ },
+ host: '127.0.0.1',
+ port: 7071,
+ },
+ mainServer: {
+ indexPath: '/public/dist/index.html',
+ channelSeparator: '/',
+ }
+ }
}
diff --git a/electron/config/config.local.js b/electron/config/config.local.js
index 69938ca..287fe84 100644
--- a/electron/config/config.local.js
+++ b/electron/config/config.local.js
@@ -1,31 +1,13 @@
'use strict';
/**
- * 开发环境配置,覆盖 config.default.js
+ * Development environment configuration, coverage config.default.js
*/
-module.exports = (appInfo) => {
- const config = {};
-
- /**
- * 开发者工具
- */
- config.openDevTools = {
- mode: 'undocked'
- };
-
- /**
- * 应用程序顶部菜单
- */
- config.openAppMenu = true;
-
- /**
- * jobs
- */
- config.jobs = {
- messageLog: true
- };
-
+module.exports = () => {
return {
- ...config
+ openDevTools: false,
+ jobs: {
+ messageLog: false
+ }
};
};
diff --git a/electron/config/config.prod.js b/electron/config/config.prod.js
index 5c5218d..db1ce01 100644
--- a/electron/config/config.prod.js
+++ b/electron/config/config.prod.js
@@ -1,29 +1,10 @@
'use strict';
/**
- * 生产环境配置,覆盖 config.default.js
+ * coverage config.default.js
*/
-module.exports = (appInfo) => {
- const config = {};
-
- /**
- * 开发者工具
- */
- config.openDevTools = false;
-
- /**
- * 应用程序顶部菜单
- */
- config.openAppMenu = false;
-
- /**
- * jobs
- */
- config.jobs = {
- messageLog: false
- };
-
+module.exports = () => {
return {
- ...config
+ openDevTools: false,
};
};
diff --git a/electron/config/nodemon.json b/electron/config/nodemon.json
deleted file mode 100644
index 96a9fe7..0000000
--- a/electron/config/nodemon.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "watch": [
- "electron/",
- "main.js"
- ],
- "ignore": [],
- "ext": "js,json",
- "verbose": true,
- "exec": "electron . --env=local --hot-reload=1",
- "restartable": "hr",
- "colours": true,
- "events": {}
-}
\ No newline at end of file
diff --git a/electron/controller/example.js b/electron/controller/example.js
index 52baff0..32f55f0 100644
--- a/electron/controller/example.js
+++ b/electron/controller/example.js
@@ -1,19 +1,13 @@
'use strict';
-const { Controller } = require('ee-core');
-const Log = require('ee-core/log');
-const Services = require('ee-core/services');
+const { logger } = require('ee-core/log');
+const { exampleService } = require('../service/example');
/**
* example
* @class
*/
-class ExampleController extends Controller {
-
- constructor(ctx) {
- super(ctx);
- }
-
+class ExampleController {
/**
* 所有方法接收两个参数
@@ -25,12 +19,12 @@ class ExampleController extends Controller {
* test
*/
async test () {
- const result = await Services.get('example').test('electron');
- Log.info('service result:', result);
+ const result = await exampleService.test('electron');
+ logger.info('service result:', result);
return 'hello electron-egg';
}
}
-
ExampleController.toString = () => '[class ExampleController]';
-module.exports = ExampleController;
\ No newline at end of file
+
+module.exports = ExampleController;
\ No newline at end of file
diff --git a/electron/index.js b/electron/index.js
deleted file mode 100644
index c0028e2..0000000
--- a/electron/index.js
+++ /dev/null
@@ -1,50 +0,0 @@
-const { Application } = require('ee-core');
-
-class Index extends Application {
-
- constructor() {
- super();
- // this === eeApp;
- }
-
- /**
- * core app have been loaded
- */
- async ready () {
- // do some things
- }
-
- /**
- * electron app ready
- */
- async electronAppReady () {
- // do some things
- }
-
- /**
- * main window have been loaded
- */
- async windowReady () {
- // do some things
- // 延迟加载,无白屏
- const winOpt = this.config.windowsOption;
- if (winOpt.show == false) {
- const win = this.electron.mainWindow;
- win.once('ready-to-show', () => {
- win.show();
- win.focus();
- })
- }
- }
-
- /**
- * before app close
- */
- async beforeClose () {
- // do some things
-
- }
-}
-
-Index.toString = () => '[class Index]';
-module.exports = Index;
\ No newline at end of file
diff --git a/electron/jobs/example/hello.js b/electron/jobs/example/hello.js
deleted file mode 100644
index 66dc1dc..0000000
--- a/electron/jobs/example/hello.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const Log = require('ee-core/log');
-
-exports.welcome = function () {
- Log.info('[child-process] [jobs/example/hello] welcome ! ');
-}
\ No newline at end of file
diff --git a/electron/jobs/example/timer.js b/electron/jobs/example/timer.js
deleted file mode 100644
index 343b1d8..0000000
--- a/electron/jobs/example/timer.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const Job = require('ee-core/jobs/baseJobClass');
-const Log = require('ee-core/log');
-const Ps = require('ee-core/ps');
-
-/**
- * example - TimerJob
- * @class
- */
-class TimerJob extends Job {
-
- constructor(params) {
- super();
- this.params = params;
- }
-
- /**
- * handle()方法是必要的,且会被自动调用
- */
- async handle () {
- Log.info("[child-process] TimerJob params: ", this.params);
-
- if (Ps.isChildJob()) {
- Ps.exit();
- }
- }
-}
-
-TimerJob.toString = () => '[class TimerJob]';
-module.exports = TimerJob;
diff --git a/electron/main.js b/electron/main.js
new file mode 100644
index 0000000..b005896
--- /dev/null
+++ b/electron/main.js
@@ -0,0 +1,19 @@
+const { ElectronEgg } = require('ee-core');
+const { Lifecycle } = require('./preload/lifecycle');
+const { preload } = require('./preload');
+
+// new app
+const app = new ElectronEgg();
+
+// register lifecycle
+const life = new Lifecycle();
+app.register("ready", life.ready);
+app.register("electron-app-ready", life.electronAppReady);
+app.register("window-ready", life.windowReady);
+app.register("before-close", life.beforeClose);
+
+// register preload
+app.register("preload", preload);
+
+// run
+app.run();
\ No newline at end of file
diff --git a/electron/preload/index.js b/electron/preload/index.js
index 36d8349..555170f 100644
--- a/electron/preload/index.js
+++ b/electron/preload/index.js
@@ -1,14 +1,16 @@
/*************************************************
** preload为预加载模块,该文件将会在程序启动时加载 **
*************************************************/
-const Addon = require('ee-core/addon');
-/**
-* 预加载模块入口
-*/
-module.exports = async () => {
-
- // 示例功能模块,可选择性使用和修改
- Addon.get('tray').create();
- Addon.get('security').create();
-}
\ No newline at end of file
+ const { logger } = require('ee-core/log');
+
+ function preload() {
+ logger.info('[preload] load 1');
+ }
+
+ /**
+ * 预加载模块入口
+ */
+ module.exports = {
+ preload
+ }
\ No newline at end of file
diff --git a/electron/preload/lifecycle.js b/electron/preload/lifecycle.js
new file mode 100644
index 0000000..a18a2cc
--- /dev/null
+++ b/electron/preload/lifecycle.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const { logger } = require('ee-core/log');
+const { getConfig } = require('ee-core/config');
+const { getMainWindow } = require('ee-core/electron');
+
+class Lifecycle {
+
+ /**
+ * core app have been loaded
+ */
+ async ready() {
+ logger.info('[lifecycle] ready');
+ }
+
+ /**
+ * electron app ready
+ */
+ async electronAppReady() {
+ logger.info('[lifecycle] electron-app-ready');
+ }
+
+ /**
+ * main window have been loaded
+ */
+ async windowReady() {
+ logger.info('[lifecycle] window-ready');
+ // 延迟加载,无白屏
+ const { windowsOption } = getConfig();
+ if (windowsOption.show == false) {
+ const win = getMainWindow();
+ win.once('ready-to-show', () => {
+ win.show();
+ win.focus();
+ })
+ }
+ }
+
+ /**
+ * before app close
+ */
+ async beforeClose() {
+ logger.info('[lifecycle] before-close');
+ }
+}
+Lifecycle.toString = () => '[class Lifecycle]';
+
+module.exports = {
+ Lifecycle
+};
\ No newline at end of file
diff --git a/electron/service/example.js b/electron/service/example.js
index 99a81c3..cf55fb6 100644
--- a/electron/service/example.js
+++ b/electron/service/example.js
@@ -1,16 +1,12 @@
'use strict';
-const { Service } = require('ee-core');
+const { logger } = require('ee-core/log');
/**
- * 示例服务(service层为单例)
+ * 示例服务
* @class
*/
-class ExampleService extends Service {
-
- constructor(ctx) {
- super(ctx);
- }
+class ExampleService {
/**
* test
@@ -21,9 +17,14 @@ class ExampleService extends Service {
params: args
}
+ logger.info('ExampleService obj:', obj);
+
return obj;
}
}
-
ExampleService.toString = () => '[class ExampleService]';
-module.exports = ExampleService;
\ No newline at end of file
+
+module.exports = {
+ ExampleService,
+ exampleService: new ExampleService()
+};
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index dce1566..3bff615 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "ee",
- "version": "1.0.0",
+ "version": "4.0.0",
"scripts": {
"dev": "vite --host --port 8080",
"serve": "vite --host --port 8080",
@@ -9,7 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
- "vue": "^3.2.33",
+ "vue": "^3.5.12",
"vue-router": "^4.0.14"
},
"devDependencies": {
@@ -18,6 +18,6 @@
"less": "^4.1.2",
"less-loader": "^10.2.0",
"terser": "^5.19.1",
- "vite": "^4.4.4"
+ "vite": "^5.4.11"
}
}
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index a824727..f7183e3 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,13 +1,14 @@
+
diff --git a/frontend/src/api/main.js b/frontend/src/api/index.js
similarity index 84%
rename from frontend/src/api/main.js
rename to frontend/src/api/index.js
index d3adbbb..381453a 100644
--- a/frontend/src/api/main.js
+++ b/frontend/src/api/index.js
@@ -4,7 +4,7 @@
* Definition of communication channels between main process and rendering process
*/
const ipcApiRoute = {
- test: 'controller.example.test',
+ test: 'controller/example/test',
}
export {
diff --git a/frontend/src/components/global/index.js b/frontend/src/components/global/index.js
index a5fc33b..6dd921a 100644
--- a/frontend/src/components/global/index.js
+++ b/frontend/src/components/global/index.js
@@ -1,4 +1,4 @@
-const modules = import.meta.globEager('./*.vue')
+const modules = import.meta.glob('./*.vue', { eager: true })
const map = {}
Object.keys(modules).forEach(file => {
const modulesName = file.replace('./', '').replace('.vue', '')
diff --git a/frontend/src/main.js b/frontend/src/main.js
index c5678b3..76083dc 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -5,7 +5,6 @@ import components from './components/global';
import Router from './router/index';
const app = createApp(App)
-app.config.productionTip = false
// components
for (const i in components) {
diff --git a/frontend/src/views/example/hello/Index.vue b/frontend/src/views/example/hello/Index.vue
index a86e029..64cc69b 100644
--- a/frontend/src/views/example/hello/Index.vue
+++ b/frontend/src/views/example/hello/Index.vue
@@ -11,13 +11,8 @@
-
-
-
-
-
-
-
-
-
-