diff --git a/package.json b/package.json index 49b5b86..b26fcd8 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A fast, desktop software development framework", "main": "./electron/main.js", "scripts": { + "vite-test": "tsc && vite build", "dev": "ee-bin dev", "dev-frontend": "ee-bin dev --serve=frontend", "dev-electron": "ee-bin dev --serve=electron", @@ -53,11 +54,16 @@ "license": "Apache", "devDependencies": { "@electron/rebuild": "^3.7.1", + "@types/electron": "^1.4.38", + "@types/node": "^22.10.2", "cross-env": "^7.0.3", "debug": "^4.4.0", "ee-bin": "file:.yalc/ee-bin", "electron": "^31.7.6", - "electron-builder": "^25.1.8" + "electron-builder": "^25.1.8", + "typescript": "^5.4.2", + "vite": "^6.0.6", + "vite-plugin-dts": "^4.4.0" }, "dependencies": { "axios": "^1.7.9", diff --git a/src/electron/config/config.default.ts b/src/electron/config/config.default.ts index ac87532..4c38c42 100644 --- a/src/electron/config/config.default.ts +++ b/src/electron/config/config.default.ts @@ -1,12 +1,88 @@ -'use strict'; +import path from 'path'; +import { getBaseDir } from 'ee-core/ps'; -const path = require('path'); -const { getBaseDir } = require('ee-core/ps'); +interface WindowOption { + title: string; + width: number; + height: number; + minWidth: number; + minHeight: number; + webPreferences: { + contextIsolation: boolean; + nodeIntegration: boolean; + }; + frame: boolean; + show: boolean; + icon: string; +} -/** - * 默认配置 - */ -module.exports = () => { +interface Logger { + level: 'INFO' | 'DEBUG' | 'WARN' | 'ERROR'; + outputJSON: boolean; + appLogName: string; + coreLogName: string; + errorLogName: string; +} + +interface Remote { + enable: boolean; + url: string; +} + +interface SocketServer { + enable: boolean; + port: number; + path: string; + connectTimeout: number; + pingTimeout: number; + pingInterval: number; + maxHttpBufferSize: number; + transports: ('polling' | 'websocket')[]; + cors: { + origin: boolean | string | ((origin: string, callback: (err: any, allow: boolean) => void) => void); + }; + channel: string; +} + +interface HttpServer { + enable: boolean; + https: { + enable: boolean; + key: string; + cert: string; + }; + host: string; + port: number; +} + +interface MainServer { + indexPath: string; +} + +interface Customize { + tray: { + title: string; + icon: string; + }; + awaken: { + protocol: string; + args: any[]; + }; +} + +interface AppConfig { + openDevTools: boolean; + singleLock: boolean; + windowsOption: WindowOption; + logger: Logger; + remote: Remote; + socketServer: SocketServer; + httpServer: HttpServer; + mainServer: MainServer; + customize: Customize; +} + +const config: () => AppConfig = () => { return { openDevTools: false, singleLock: true, @@ -17,10 +93,8 @@ module.exports = () => { minWidth: 400, minHeight: 300, webPreferences: { - //webSecurity: false, - contextIsolation: false, // false -> 可在渲染进程中使用electron的api,true->需要bridge.js(contextBridge) + contextIsolation: false, nodeIntegration: true, - //preload: path.join(getElectronDir(), 'preload', 'bridge.js'), }, frame: true, show: true, @@ -31,11 +105,11 @@ module.exports = () => { outputJSON: false, appLogName: 'ee.log', coreLogName: 'ee-core.log', - errorLogName: 'ee-error.log' + errorLogName: 'ee-error.log', }, remote: { enable: false, - url: 'http://electron-egg.kaka996.com/' + url: 'http://electron-egg.kaka996.com/', }, socketServer: { enable: false, @@ -49,14 +123,14 @@ module.exports = () => { cors: { origin: true, }, - channel: 'c1' + channel: 'c1', }, httpServer: { enable: false, https: { - enable: false, + enable: false, key: '/public/ssl/localhost+1.key', - cert: '/public/ssl/localhost+1.pem' + cert: '/public/ssl/localhost+1.pem', }, host: '127.0.0.1', port: 7071, @@ -67,12 +141,14 @@ module.exports = () => { customize: { tray: { title: 'EE程序', - icon: '/public/images/tray.png' + icon: '/public/images/tray.png', }, awaken: { protocol: 'ee', - args: [] - } + args: [], + }, }, - } -} + }; +}; + +export default config; \ No newline at end of file diff --git a/src/electron/config/config.local.ts b/src/electron/config/config.local.ts index 20ecc4b..2c9a49e 100644 --- a/src/electron/config/config.local.ts +++ b/src/electron/config/config.local.ts @@ -1,9 +1,17 @@ -'use strict'; +interface OpenDevTools { + mode: string; +} -/** - * Development environment configuration, coverage config.default.js - */ -module.exports = () => { +interface Jobs { + messageLog: boolean; +} + +interface AppConfig { + openDevTools: OpenDevTools; + jobs: Jobs; +} + +const config: () => AppConfig = () => { return { openDevTools: { mode: 'bottom' @@ -13,3 +21,5 @@ module.exports = () => { } }; }; + +export default config; \ No newline at end of file diff --git a/src/electron/config/config.prod.ts b/src/electron/config/config.prod.ts index db1ce01..8ef9055 100644 --- a/src/electron/config/config.prod.ts +++ b/src/electron/config/config.prod.ts @@ -1,10 +1,11 @@ -'use strict'; +interface AppConfig { + openDevTools: boolean; +} -/** - * coverage config.default.js - */ -module.exports = () => { +const config: () => AppConfig = () => { return { openDevTools: false, }; }; + +export default config; \ No newline at end of file diff --git a/src/electron/controller/child/friend/school.ts b/src/electron/controller/child/friend/school.ts index d89582b..3c2f767 100644 --- a/src/electron/controller/child/friend/school.ts +++ b/src/electron/controller/child/friend/school.ts @@ -1,18 +1,14 @@ -'use strict'; - /** - * school - * @class + * SchoolController class */ class SchoolController { - /** - * test + * Test method */ - async test () { + async test(): Promise { return 'hello electron-egg'; } } SchoolController.toString = () => '[class SchoolController]'; -module.exports = SchoolController; \ No newline at end of file +export default SchoolController; \ No newline at end of file diff --git a/src/electron/controller/child/tool.ts b/src/electron/controller/child/tool.ts index 143d960..9487582 100644 --- a/src/electron/controller/child/tool.ts +++ b/src/electron/controller/child/tool.ts @@ -1,18 +1,14 @@ -'use strict'; - /** - * tool - * @class + * ToolController class */ class ToolController { - /** - * test + * Test method */ - async test () { + async test(): Promise { return 'hello electron-egg'; } } ToolController.toString = () => '[class ToolController]'; -module.exports = ToolController; \ No newline at end of file +export default ToolController; \ No newline at end of file diff --git a/src/electron/controller/child/user.ts b/src/electron/controller/child/user.ts index 169f11f..9d723d3 100644 --- a/src/electron/controller/child/user.ts +++ b/src/electron/controller/child/user.ts @@ -1,18 +1,14 @@ -'use strict'; - /** - * user - * @class + * UserController class */ class UserController { - /** - * test + * Test method */ - async test () { + async test(): Promise { return 'hello electron-egg'; } } UserController.toString = () => '[class UserController]'; -module.exports = UserController; \ No newline at end of file +export default UserController; \ No newline at end of file diff --git a/src/electron/controller/cross.ts b/src/electron/controller/cross.ts index a289912..2402289 100644 --- a/src/electron/controller/cross.ts +++ b/src/electron/controller/cross.ts @@ -1,65 +1,61 @@ -'use strict'; - -const { crossService } = require('../service/cross'); +import { crossService } from '../service/cross'; /** - * Cross - * @class + * CrossController class */ class CrossController { - /** * View process service information */ - info() { + info(): string { crossService.info(); return 'hello electron-egg'; } /** * Get service url - */ - async getUrl(args) { + */ + async getUrl(args: { name: string }): Promise { const { name } = args; const serverUrl = crossService.getUrl(name); return serverUrl; } /** - * kill service + * Kill service * By default (modifiable), killing the process will exit the electron application. - */ - async killServer(args) { + */ + async killServer(args: { type: string; name: string }): Promise { const { type, name } = args; crossService.killServer(type, name); - return; } /** - * create service - */ - async createServer(args) { + * Create service + */ + async createServer(args: { program: string }): Promise { const { program } = args; - if (program == 'go') { + if (program === 'go') { crossService.createGoServer(); - } else if (program == 'java') { + } else if (program === 'java') { crossService.createJavaServer(); - } else if (program == 'python') { + } else if (program === 'python') { crossService.createPythonServer(); } - - return; } /** * Access the api for the cross service */ - async requestApi(args) { - const { name, urlPath, params} = args; + async requestApi(args: { name: string; urlPath: string; params: any }): Promise { + const { name, urlPath, params } = args; const data = await crossService.requestApi(name, urlPath, params); return data; } } +// 设置类的toString方法,虽然在TypeScript中不常见 CrossController.toString = () => '[class CrossController]'; -module.exports = CrossController; \ No newline at end of file + +// 默认导出类 +export default CrossController; \ No newline at end of file diff --git a/src/electron/controller/effect.ts b/src/electron/controller/effect.ts index f4c692a..9bca358 100644 --- a/src/electron/controller/effect.ts +++ b/src/electron/controller/effect.ts @@ -1,66 +1,65 @@ -'use strict'; - -const { dialog } = require('electron'); -const _ = require('lodash'); -const { getMainWindow } = require('ee-core/electron/window'); +import { dialog } from 'electron'; +import _ from 'lodash'; +import { getMainWindow } from 'ee-core/electron/window'; /** - * effect - demo - * @class + * EffectController class */ class EffectController { - /** - * select file + * Select file */ - selectFile() { + selectFile(): string | null { const filePaths = dialog.showOpenDialogSync({ properties: ['openFile'] }); if (_.isEmpty(filePaths)) { - return null + return null; } return filePaths[0]; } /** - * login window + * Login window */ - loginWindow(args) { + loginWindow(args: { width?: number; height?: number }): void { const { width, height } = args; const win = getMainWindow(); - + const size = { width: width || 400, height: height || 300 - } + }; win.setSize(size.width, size.height); win.setResizable(true); win.center(); win.show(); win.focus(); } - + /** - * restore window + * Restore window */ - restoreWindow(args) { + restoreWindow(args: { width?: number; height?: number }): void { const { width, height } = args; const win = getMainWindow(); const size = { width: width || 980, height: height || 650 - } + }; win.setSize(size.width, size.height); win.setResizable(true); win.center(); win.show(); win.focus(); - } + } } +// 设置类的toString方法,虽然在TypeScript中不常见 EffectController.toString = () => '[class EffectController]'; -module.exports = EffectController; \ No newline at end of file + +// 默认导出类 +export default EffectController; \ No newline at end of file diff --git a/src/electron/controller/example.ts b/src/electron/controller/example.ts index 7ec8da5..57c7f09 100644 --- a/src/electron/controller/example.ts +++ b/src/electron/controller/example.ts @@ -1,18 +1,17 @@ -'use strict'; - /** - * example - * @class + * ExampleController class */ class ExampleController { - /** - * test + * Test method */ - async test () { + async test(): Promise { return 'hello electron-egg'; } } +// 设置类的toString方法,虽然在TypeScript中不常见 ExampleController.toString = () => '[class ExampleController]'; -module.exports = ExampleController; \ No newline at end of file + +// 默认导出类 +export default ExampleController; \ No newline at end of file diff --git a/src/electron/controller/framework.ts b/src/electron/controller/framework.ts index 1033f8a..094bc76 100644 --- a/src/electron/controller/framework.ts +++ b/src/electron/controller/framework.ts @@ -1,15 +1,12 @@ -'use strict'; - -const dayjs = require('dayjs'); -const path = require('path'); -const fs = require('fs'); -const { exec } = require('child_process'); -const { app: electronApp, shell } = require('electron'); -const { getExtraResourcesDir } = require('ee-core/ps'); -const { logger } = require('ee-core/log'); -const { getConfig } = require('ee-core/config'); -const { frameworkService } = require('../service/framework'); -const { sqlitedbService } = require('../service/database/sqlitedb'); +import path from 'path'; +import fs from 'fs'; +import { exec } from 'child_process'; +import { app as electronApp, shell } from 'electron'; +import { getExtraResourcesDir } from 'ee-core/ps'; +import { logger } from 'ee-core/log'; +import { getConfig } from 'ee-core/config'; +import { frameworkService } from '../service/framework'; +import { sqlitedbService } from '../service/database/sqlitedb'; /** * framework - demo @@ -250,4 +247,4 @@ class FrameworkController { } FrameworkController.toString = () => '[class FrameworkController]'; -module.exports = FrameworkController; \ No newline at end of file +export default FrameworkController; \ No newline at end of file diff --git a/src/electron/controller/os.ts b/src/electron/controller/os.ts index 3ebfd30..6e9bc35 100644 --- a/src/electron/controller/os.ts +++ b/src/electron/controller/os.ts @@ -1,76 +1,67 @@ -'use strict'; - -const _ = require('lodash'); -const fs = require('fs'); -const path = require('path'); -const { - app: electronApp, dialog, shell, Notification, -} = require('electron'); -const { windowService } = require('../service/os/window'); +import _ from 'lodash'; +import fs from 'fs'; +import path from 'path'; +import { + app as electronApp, dialog, shell, Notification, +} from 'electron'; +import { windowService } from '../service/os/window'; /** - * example - * @class + * OsController class */ class OsController { - /** - * All methods receive two parameters - * @param args Parameters transmitted by the frontend - * @param event - Event are only available during IPC communication. For details, please refer to the controller documentation - */ - /** * Message prompt dialog box */ - messageShow() { + messageShow(): string { dialog.showMessageBoxSync({ - type: 'info', // "none", "info", "error", "question" 或者 "warning" + type: 'info', title: 'Custom Title', message: 'Customize message content', - detail: 'Other additional information' - }) - + detail: 'Other additional information', + }); + return 'Opened the message box'; } /** * Message prompt and confirmation dialog box */ - messageShowConfirm() { + messageShowConfirm(): string { const res = dialog.showMessageBoxSync({ type: 'info', title: 'Custom Title', message: 'Customize message content', detail: 'Other additional information', - cancelId: 1, // Index of buttons used to cancel dialog boxes - defaultId: 0, // Set default selected button - buttons: ['confirm', 'cancel'], - }) + cancelId: 1, + defaultId: 0, + buttons: ['confirm', 'cancel'], + }); let data = (res === 0) ? 'click the confirm button' : 'click the cancel button'; - + return data; } /** * Select Directory */ - selectFolder() { + selectFolder(): string | null { const filePaths = dialog.showOpenDialogSync({ properties: ['openDirectory', 'createDirectory'] }); if (_.isEmpty(filePaths)) { - return null + return null; } return filePaths[0]; - } + } /** - * open directory + * Open directory */ - openDirectory(args) { + openDirectory(args: { id: string }): boolean { const { id } = args; if (!id) { return false; @@ -89,7 +80,7 @@ class OsController { /** * Select Picture */ - selectPic() { + selectPic(): string | null { const filePaths = dialog.showOpenDialogSync({ title: 'select pic', properties: ['openFile'], @@ -98,31 +89,31 @@ class OsController { ] }); if (_.isEmpty(filePaths)) { - return null + return null; } - + try { const data = fs.readFileSync(filePaths[0]); - const pic = 'data:image/jpeg;base64,' + data.toString('base64'); + const pic = 'data:image/jpeg;base64,' + data.toString('base64'); return pic; } catch (err) { console.error(err); return null; } - } + } /** * Open a new window */ - createWindow(args) { + createWindow(args: any): string { const wcid = windowService.createWindow(args); return wcid; } - + /** * Get Window contents id */ - getWCid(args) { + getWCid(args: any): string | null { const wcid = windowService.getWCid(args); return wcid; } @@ -130,47 +121,46 @@ class OsController { /** * Realize communication between two windows through the transfer of the main process */ - window1ToWindow2(args, event) { + window1ToWindow2(args: any, event: any): void { windowService.communicate(args, event); - return; } /** * Realize communication between two windows through the transfer of the main process */ - window2ToWindow1(args, event) { + window2ToWindow1(args: any, event: any): void { windowService.communicate(args, event); - return; } /** * Create system notifications */ - sendNotification(args, event) { - const { title, subtitle, body, silent} = args; - + sendNotification(args: { title?: string; subtitle?: string; body?: string; silent?: boolean }, event: any): boolean { if (!Notification.isSupported()) { - return '当前系统不支持通知'; + return false; } let options = {}; - if (!_.isEmpty(title)) { - options.title = title; + if (!_.isEmpty(args.title)) { + options.title = args.title; } - if (!_.isEmpty(subtitle)) { - options.subtitle = subtitle; + if (!_.isEmpty(args.subtitle)) { + options.subtitle = args.subtitle; } - if (!_.isEmpty(body)) { - options.body = body; + if (!_.isEmpty(args.body)) { + options.body = args.body; } - if (!_.isEmpty(silent)) { - options.silent = silent; + if (!_.isEmpty(args.silent)) { + options.silent = args.silent; } windowService.createNotification(options, event); - return true - } + return true; + } } +// 设置类的toString方法,虽然在TypeScript中不常见 OsController.toString = () => '[class OsController]'; -module.exports = OsController; \ No newline at end of file + +// 默认导出类 +export default OsController; \ No newline at end of file diff --git a/src/electron/jobs/example/hello.ts b/src/electron/jobs/example/hello.ts index a4b0250..5c48f69 100644 --- a/src/electron/jobs/example/hello.ts +++ b/src/electron/jobs/example/hello.ts @@ -1,11 +1,7 @@ -'use strict'; +import { logger } from 'ee-core/log'; -const { logger } = require('ee-core/log'); - -function welcome() { +function welcome(): void { logger.info('[child-process] [jobs/example/hello] welcome ! '); } -module.exports = { - welcome -}; \ No newline at end of file +export { welcome }; \ No newline at end of file diff --git a/src/electron/jobs/example/timer.ts b/src/electron/jobs/example/timer.ts index ed70364..d496c00 100644 --- a/src/electron/jobs/example/timer.ts +++ b/src/electron/jobs/example/timer.ts @@ -1,18 +1,20 @@ -'use strict'; - -const { logger } = require('ee-core/log'); -const { isChildJob, exit } = require('ee-core/ps'); -const { childMessage } = require('ee-core/message'); -const { welcome } = require('./hello'); -const { UserService } = require('../../service/job/user'); +import { logger } from 'ee-core/log'; +import { isChildJob, exit } from 'ee-core/ps'; +import { childMessage } from 'ee-core/message'; +import { welcome } from './hello'; +import { UserService } from '../../service/job/user'; /** - * example - TimerJob - * @class + * TimerJob class */ class TimerJob { + params: any; + timer?: NodeJS.Timeout; + timeoutTimer?: NodeJS.Timeout; + number: number; + countdown: number; - constructor(params) { + constructor(params: any) { this.params = params; this.timer = undefined; this.timeoutTimer = undefined; @@ -23,7 +25,7 @@ class TimerJob { /** * handle()方法是必要的,且会被自动调用 */ - async handle () { + async handle(): Promise { logger.info("[child-process] TimerJob params: ", this.params); const { jobId } = this.params; @@ -35,34 +37,34 @@ class TimerJob { // 执行任务 this.doTimer(jobId); } - + /** * 暂停任务运行 */ - async pause(jobId) { + async pause(jobId: string): Promise { logger.info("[child-process] Pause timerJob, jobId: ", jobId); - clearInterval(this.timer); - clearInterval(this.timeoutTimer); + if (this.timer) clearInterval(this.timer); + if (this.timeoutTimer) clearInterval(this.timeoutTimer); } /** * 恢复任务运行 */ - async resume(jobId, pid) { + async resume(jobId: string, pid: number): Promise { logger.info("[child-process] Resume timerJob, jobId: ", jobId, ", pid: ", pid); this.doTimer(jobId); - } + } /** * 运行任务 */ - async doTimer(jobId) { + async doTimer(jobId: string): Promise { // 计时器模拟任务 const eventName = 'job-timer-progress-' + jobId; this.timer = setInterval(() => { welcome(); - childMessage.send(eventName, {jobId, number: this.number, end: false}); + childMessage.send(eventName, { jobId, number: this.number, end: false }); this.number++; this.countdown--; }, 1000); @@ -70,19 +72,21 @@ class TimerJob { // 用 setTimeout 模拟任务运行时长 this.timeoutTimer = setTimeout(() => { // 关闭计时器模拟任务 - clearInterval(this.timer); + if (this.timer) clearInterval(this.timer); // 任务结束,重置前端显示 - childMessage.send(eventName, {jobId, number:0, pid:0, end: true}); + childMessage.send(eventName, { jobId, number: 0, pid: 0, end: true }); // 如果是childJob任务,必须调用 exit() 方法,让进程退出,否则会常驻内存 // 如果是childPoolJob任务,常驻内存,等待下一个业务 if (isChildJob()) { exit(); } - }, this.countdown * 1000) + }, this.countdown * 1000); } } +// 设置类的toString方法,虽然在TypeScript中不常见 TimerJob.toString = () => '[class TimerJob]'; -module.exports = TimerJob; + +export default TimerJob; \ No newline at end of file diff --git a/src/electron/main.ts b/src/electron/main.ts index b005896..f3f9a91 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -1,19 +1,19 @@ -const { ElectronEgg } = require('ee-core'); -const { Lifecycle } = require('./preload/lifecycle'); -const { preload } = require('./preload'); +import { ElectronEgg } from 'ee-core'; +import { Lifecycle } from './preload/lifecycle'; +import { preload } from './preload'; -// new app +// New app const app = new ElectronEgg(); -// register lifecycle +// 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 +// Register preload app.register("preload", preload); -// run +// Run app.run(); \ No newline at end of file diff --git a/src/electron/preload/bridge.ts b/src/electron/preload/bridge.ts index c9b86db..d6b072e 100644 --- a/src/electron/preload/bridge.ts +++ b/src/electron/preload/bridge.ts @@ -3,8 +3,13 @@ * 可通过contextBridge 导出api给渲染进程使用 */ -const { contextBridge, ipcRenderer } = require('electron') +import { contextBridge, ipcRenderer } from 'electron'; + +// 确保contextBridge.exposeInMainWorld的参数类型正确,这里进行简单的类型定义示例 +type ElectronApi = { + ipcRenderer: typeof ipcRenderer; +}; contextBridge.exposeInMainWorld('electron', { - ipcRenderer: ipcRenderer, -}) \ No newline at end of file + ipcRenderer: ipcRenderer, +} as ElectronApi); \ No newline at end of file diff --git a/src/electron/preload/index.ts b/src/electron/preload/index.ts index d2c53a7..1cb0bc9 100644 --- a/src/electron/preload/index.ts +++ b/src/electron/preload/index.ts @@ -1,15 +1,12 @@ -/************************************************* - ** preload为预加载模块,该文件将会在程序启动时加载 ** - *************************************************/ - -function preload() { - // 示例功能模块,可选择性使用和修改 +/** + * Preload module, this file will be loaded when the program starts. + */ +function preload(): void { + // Example feature module, optional to use and modify console.log('preload/index.js'); } /** -* 预加载模块入口 -*/ -module.exports = { - preload -} \ No newline at end of file + * Entry point of the preload module + */ +export { preload }; \ No newline at end of file diff --git a/src/electron/preload/lifecycle.ts b/src/electron/preload/lifecycle.ts index 396be77..7fe23c1 100644 --- a/src/electron/preload/lifecycle.ts +++ b/src/electron/preload/lifecycle.ts @@ -1,51 +1,49 @@ -'use strict'; - -const { getConfig } = require('ee-core/config'); -const { getMainWindow } = require('ee-core/electron'); +import { getConfig, Config } from 'ee-core/config'; +import { getMainWindow } from 'ee-core/electron'; class Lifecycle { - /** - * core app have been loaded + * Core app has been loaded */ - async ready() { - // do some things + async ready(): Promise { + // Do some things console.log('[lifecycle] ready'); } /** - * electron app ready + * Electron app is ready */ - async electronAppReady() { - // do some things + async electronAppReady(): Promise { + // Do some things console.log('[lifecycle] electron-app-ready'); } /** - * main window have been loaded + * Main window has been loaded */ - async windowReady() { + async windowReady(): Promise { console.log('[lifecycle] window-ready'); - // 延迟加载,无白屏 - const { windowsOption } = getConfig(); - if (windowsOption.show == false) { + // Delay loading, no white screen + const config: Config = getConfig(); + const { windowsOption } = config; + if (windowsOption.show === false) { const win = getMainWindow(); win.once('ready-to-show', () => { win.show(); win.focus(); - }) + }); } } /** - * before app close - */ - async beforeClose() { + * Before app close + */ + async beforeClose(): Promise { console.log('[lifecycle] before-close'); } } +// 设置类的toString方法,虽然在TypeScript中不常见 Lifecycle.toString = () => '[class Lifecycle]'; -module.exports = { - Lifecycle -}; \ No newline at end of file + +export { Lifecycle }; \ No newline at end of file diff --git a/src/electron/service/cross.ts b/src/electron/service/cross.ts index c850d06..71cb997 100644 --- a/src/electron/service/cross.ts +++ b/src/electron/service/cross.ts @@ -1,56 +1,46 @@ -'use strict'; - -const { logger } = require('ee-core/log'); -const { getExtraResourcesDir } = require('ee-core/ps'); -const path = require("path"); -const axios = require('axios'); -const { is } = require('ee-core/utils'); -const { cross } = require('ee-core/cross'); +import { logger } from 'ee-core/log'; +import { getExtraResourcesDir } from 'ee-core/ps'; +import path from 'path'; +import axios from 'axios'; +import { is } from 'ee-core/utils'; +import { cross } from 'ee-core/cross'; /** - * cross - * @class + * CrossService class for cross platform service management */ class CrossService { - - info() { + info(): string { const pids = cross.getPids(); logger.info('cross pids:', pids); let num = 1; pids.forEach(pid => { let entity = cross.getProc(pid); - logger.info(`server-${num} name:${entity.name}`); + logger.info(`server-${num} name: ${entity.name}`); logger.info(`server-${num} config:`, entity.config); num++; - }) + }); return 'hello electron-egg'; } - getUrl(name) { + getUrl(name: string): string { const serverUrl = cross.getUrl(name); return serverUrl; } - killServer(type, name) { - if (type == 'all') { + killServer(type: string, name: string): void { + if (type === 'all') { cross.killAll(); } else { cross.killByName(name); } - } + } /** - * create go service - * In the default configuration, services can be started with applications. - * Developers can turn off the configuration and create it manually. - */ - async createGoServer() { - // method 1: Use the default Settings - //const entity = await cross.run(serviceName); - - // method 2: Use custom configuration + * Create a go service + */ + async createGoServer(): Promise { const serviceName = "go"; const opt = { name: 'goapp', @@ -58,54 +48,43 @@ class CrossService { directory: getExtraResourcesDir(), args: ['--port=7073'], appExit: true, - } + }; const entity = await cross.run(serviceName, opt); logger.info('server name:', entity.name); logger.info('server config:', entity.config); logger.info('server url:', entity.getUrl()); - - return; } /** - * create java server + * Create a java server */ - async createJavaServer() { + async createJavaServer(): Promise { const serviceName = "java"; const jarPath = path.join(getExtraResourcesDir(), 'java-app.jar'); const opt = { name: 'javaapp', cmd: path.join(getExtraResourcesDir(), 'jre1.8.0_201/bin/javaw.exe'), directory: getExtraResourcesDir(), - args: ['-jar', '-server', '-Xms512M', '-Xmx512M', '-Xss512k', '-Dspring.profiles.active=prod', `-Dserver.port=18080`, `-Dlogging.file.path=${Ps.getLogDir()}`, `${jarPath}`], + args: ['-jar', '-server', '-Xms512M', '-Xmx512M', '-Xss512k', '-Dspring.profiles.active=prod', `-Dserver.port=18080`, `-Dlogging.file.path=${getExtraResourcesDir()}`, `${jarPath}`], appExit: false, - } + }; if (is.macOS()) { - // Setup Java program opt.cmd = path.join(getExtraResourcesDir(), 'jre1.8.0_201.jre/Contents/Home/bin/java'); } if (is.linux()) { - // Setup Java program + // Setup for Linux } const entity = await cross.run(serviceName, opt); logger.info('server name:', entity.name); logger.info('server config:', entity.config); logger.info('server url:', cross.getUrl(entity.name)); - - return; - } + } /** - * create python service - * In the default configuration, services can be started with applications. - * Developers can turn off the configuration and create it manually. - */ - async createPythonServer() { - // method 1: Use the default Settings - //const entity = await cross.run(serviceName); - - // method 2: Use custom configuration + * Create a python service + */ + async createPythonServer(): Promise { const serviceName = "python"; const opt = { name: 'pyapp', @@ -114,16 +93,14 @@ class CrossService { args: ['--port=7074'], windowsExtname: true, appExit: true, - } + }; const entity = await cross.run(serviceName, opt); logger.info('server name:', entity.name); logger.info('server config:', entity.config); logger.info('server url:', entity.getUrl()); - - return; } - async requestApi(name, urlPath, params) { + async requestApi(name: string, urlPath: string, params: any): Promise { const serverUrl = cross.getUrl(name); const apiHello = serverUrl + urlPath; console.log('Server Url:', serverUrl); @@ -135,17 +112,16 @@ class CrossService { params, proxy: false, }); - if (response.status == 200) { + if (response.status === 200) { const { data } = response; return data; } return null; - } + } } +// Setting the class toString method, which is not common in TypeScript CrossService.toString = () => '[class CrossService]'; -module.exports = { - CrossService, - crossService: new CrossService() -}; \ No newline at end of file + +export { CrossService, new CrossService() as crossService }; \ No newline at end of file diff --git a/src/electron/service/database/basedb.ts b/src/electron/service/database/basedb.ts index 0d5d05a..63e79ee 100644 --- a/src/electron/service/database/basedb.ts +++ b/src/electron/service/database/basedb.ts @@ -1,52 +1,50 @@ -'use strict'; - -const { SqliteStorage } = require('ee-core/storage'); -const { getDataDir } = require('ee-core/ps'); -const path = require('path'); +import { SqliteStorage } from 'ee-core/storage'; +import { getDataDir } from 'ee-core/ps'; +import path from 'path'; /** - * sqlite数据存储 - * @class + * BasedbService class for sqlite data storage */ class BasedbService { + dbname: string; + db: any; // Replace 'any' with the actual type if known + storage: SqliteStorage; - constructor(options) { - const { dbname } = options; - this.dbname = dbname; - this.db = undefined; + constructor(options: { dbname: string }) { + this.dbname = options.dbname; this._init(); } - /* - * 初始化 + /** + * Initializes the sqlite database */ - _init() { - // 定义数据文件 + private _init(): void { + // Define the data file const dbFile = path.join(getDataDir(), "db", this.dbname); const sqliteOptions = { timeout: 6000, verbose: console.log - } + }; this.storage = new SqliteStorage(dbFile, sqliteOptions); this.db = this.storage.db; } - /* - * change data dir (sqlite) + /** + * Changes the data directory for the sqlite database */ - changeDataDir(dir) { - // the absolute path of the db file + changeDataDir(dir: string): void { + // The absolute path of the db file const dbFile = path.join(dir, this.dbname); const sqliteOptions = { timeout: 6000, verbose: console.log - } + }; this.storage = new SqliteStorage(dbFile, sqliteOptions); - this.db = this.storage.db; + this.db = this.storage.db; } -} +} +// Setting the class toString method, which is not common in TypeScript BasedbService.toString = () => '[class BasedbService]'; -module.exports = { - BasedbService, -}; \ No newline at end of file + +export { BasedbService }; \ No newline at end of file diff --git a/src/electron/service/database/sqlitedb.ts b/src/electron/service/database/sqlitedb.ts index 3707e06..9a440f3 100644 --- a/src/electron/service/database/sqlitedb.ts +++ b/src/electron/service/database/sqlitedb.ts @@ -1,112 +1,112 @@ -'use strict'; - -const { BasedbService } = require('./basedb'); -const _ = require('lodash'); +import { BasedbService } from './basedb'; +import _ from 'lodash'; +import { SqliteStorage } from 'ee-core/storage'; /** - * sqlite数据存储 - * @class + * SqlitedbService class for sqlite data storage */ class SqlitedbService extends BasedbService { + userTableName: string; + storage: SqliteStorage; - constructor () { + constructor() { const options = { dbname: 'sqlite-demo.db', - } + }; super(options); this.userTableName = 'user'; this._initTable(); } - /* - * 初始化表 + /** + * Initializes the table */ - _initTable() { - // 检查表是否存在 + private _initTable(): void { + // Check if the table exists const masterStmt = this.db.prepare('SELECT * FROM sqlite_master WHERE type=? AND name = ?'); let tableExists = masterStmt.get('table', this.userTableName); if (!tableExists) { - // 创建表 + // Create the table const create_user_table_sql = - `CREATE TABLE ${this.userTableName} - ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name CHAR(50) NOT NULL, - age INT - );` + `CREATE TABLE ${this.userTableName} ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name CHAR(50) NOT NULL, + age INT + );` this.db.exec(create_user_table_sql); } } - /* - * 增 Test data (sqlite) + /** + * Adds test data to sqlite */ - async addTestDataSqlite(data) { + async addTestDataSqlite(data: { name: string; age: number }): Promise { const insert = this.db.prepare(`INSERT INTO ${this.userTableName} (name, age) VALUES (@name, @age)`); insert.run(data); return true; } - /* - * 删 Test data (sqlite) + /** + * Deletes test data from sqlite */ - async delTestDataSqlite(name = '') { + async delTestDataSqlite(name: string = ''): Promise { const delUser = this.db.prepare(`DELETE FROM ${this.userTableName} WHERE name = ?`); delUser.run(name); return true; } - /* - * 改 Test data (sqlite) + /** + * Updates test data in sqlite */ - async updateTestDataSqlite(name= '', age = 0) { + async updateTestDataSqlite(name: string = '', age: number = 0): Promise { const updateUser = this.db.prepare(`UPDATE ${this.userTableName} SET age = ? WHERE name = ?`); updateUser.run(age, name); return true; - } + } - /* - * 查 Test data (sqlite) + /** + * Retrieves test data from sqlite */ - async getTestDataSqlite(age = 0) { + async getTestDataSqlite(age: number = 0): Promise { const selectUser = this.db.prepare(`SELECT * FROM ${this.userTableName} WHERE age = @age`); - const users = selectUser.all({age: age}); + const users = selectUser.all({ age: age }); return users; - } - - /* - * all Test data (sqlite) + } + + /** + * Retrieves all test data from sqlite */ - async getAllTestDataSqlite() { + async getAllTestDataSqlite(): Promise { const selectAllUser = this.db.prepare(`SELECT * FROM ${this.userTableName} `); - const allUser = selectAllUser.all(); + const allUser = selectAllUser.all(); return allUser; } - - /* - * get data dir (sqlite) - */ - async getDataDir() { - const dir = this.storage.getStorageDir(); - return dir; - } - /* - * set custom data dir (sqlite) + /** + * Gets the data directory for sqlite */ - async setCustomDataDir(dir) { + async getDataDir(): Promise { + const dir = this.storage.getStorageDir(); + return dir; + } + + /** + * Sets a custom data directory for sqlite + */ + async setCustomDataDir(dir: string): Promise { if (_.isEmpty(dir)) { return; } this.changeDataDir(dir); this._initTable(); - return; } } +// Setting the class toString method, which is not common in TypeScript SqlitedbService.toString = () => '[class SqlitedbService]'; -module.exports = { - SqlitedbService, + +export { + SqlitedbService, sqlitedbService: new SqlitedbService() -}; +}; \ No newline at end of file diff --git a/src/electron/service/effect.ts b/src/electron/service/effect.ts index 06bee6e..3f5ff13 100644 --- a/src/electron/service/effect.ts +++ b/src/electron/service/effect.ts @@ -1,30 +1,25 @@ -'use strict'; - -const { logger } = require('ee-core/log'); +import { logger } from 'ee-core/log'; /** - * effect - * @class + * EffectService class for handling effects */ class EffectService { - /** - * hello + * Hello method + * @param args The arguments passed to the method */ - async hello(args) { + async hello(args: any): Promise<{ status: string; params: any }> { let obj = { - status:'ok', - params: args - } + status: 'ok', + params: args, + }; logger.info('EffectService obj:', obj); return obj; } - } +// Setting the class toString method, which is not common in TypeScript EffectService.toString = () => '[class EffectService]'; -module.exports = { - EffectService, - effectService: new EffectService() -}; \ No newline at end of file + +export { EffectService, new EffectService() as effectService }; \ No newline at end of file diff --git a/src/electron/service/example.ts b/src/electron/service/example.ts index d7fab41..74183af 100644 --- a/src/electron/service/example.ts +++ b/src/electron/service/example.ts @@ -1,32 +1,28 @@ -'use strict'; - -const { logger } = require('ee-core/log'); +import { logger } from 'ee-core/log'; /** - * 示例服务 - * @class + * ExampleService class for demonstration purposes */ class ExampleService { - /** - * test + * Test method + * @param args The arguments passed to the method */ - async test(args) { + async test(args: any): Promise<{ status: string; params: any }> { let obj = { - status:'ok', - params: args - } + status: 'ok', + params: args, + }; logger.info('ExampleService obj:', obj); - //Services.get('framework').test('egg'); + // Services.get('framework').test('egg'); // This line is commented out and would need proper typing if used return obj; } } +// Setting the class toString method, which is not common in TypeScript ExampleService.toString = () => '[class ExampleService]'; -module.exports = { - ExampleService, - exampleService: new ExampleService() -}; \ No newline at end of file + +export { ExampleService, exampleService: new ExampleService() }; \ No newline at end of file diff --git a/src/electron/service/framework.ts b/src/electron/service/framework.ts index 9c219f5..9517d46 100644 --- a/src/electron/service/framework.ts +++ b/src/electron/service/framework.ts @@ -1,16 +1,17 @@ -'use strict'; - -const { logger } = require('ee-core/log'); -const { ChildJob, ChildPoolJob } = require('ee-core/jobs'); +import { logger } from 'ee-core/log'; +import { ChildJob, ChildPoolJob } from 'ee-core/jobs'; /** - * framework - * @class + * FrameworkService class for framework-related operations */ class FrameworkService { + myTimer: NodeJS.Timeout | null; + myJob: ChildJob; + myJobPool: ChildPoolJob; + taskForJob: { [key: string]: any }; constructor() { - // 在构造函数中初始化一些变量 + // Initialize variables in the constructor this.myTimer = null; this.myJob = new ChildJob(); this.myJobPool = new ChildPoolJob(); @@ -18,81 +19,73 @@ class FrameworkService { } /** - * test + * Test method + * @param args The arguments passed to the method */ - async test(args) { + async test(args: any): Promise<{ status: string; params: any }> { let obj = { - status:'ok', - params: args - } + status: 'ok', + params: args, + }; logger.info('FrameworkService obj:', obj); return obj; } /** - * ipc通信(双向) + * IPC communication (two-way) */ - bothWayMessage(type, content, event) { - // 前端ipc频道 channel + bothWayMessage(type: string, content: any, event: any): string { + // Frontend IPC channel const channel = 'controller.framework.ipcSendMsg'; - if (type == 'start') { - // 每隔1秒,向前端页面发送消息 - // 用定时器模拟 - this.myTimer = setInterval(function(e, c, msg) { + if (type === 'start') { + // Send messages to the frontend page every 1 second + // Simulate with a timer + this.myTimer = setInterval((e: any, c: string, msg: string) => { let timeNow = Date.now(); let data = msg + ':' + timeNow; - e.reply(`${c}`, data) - }, 1000, event, channel, content) + e.reply(`${c}`, data); + }, 1000, event, channel, content); - return '开始了' - } else if (type == 'end') { + return 'started'; + } else if (type === 'end') { clearInterval(this.myTimer); - return '停止了' + return 'stopped'; } else { - return 'ohther' + return 'other'; } } /** - * 执行任务 - */ - doJob(jobId, action, event) { + * Execute a job + */ + doJob(jobId: string, action: string, event: any): any { let res = {}; - let oneTask; + let oneTask: any; const channel = 'controller.framework.timerJobProgress'; - if (action == 'create') { - // 执行任务及监听进度 + if (action === 'create') { + // Execute the job and listen for progress let eventName = 'job-timer-progress-' + jobId; - const timerTask = this.myJob.exec('./jobs/example/timer', {jobId}); - timerTask.emitter.on(eventName, (data) => { + const timerTask = this.myJob.exec('./jobs/example/timer', { jobId }); + timerTask.emitter.on(eventName, (data: any) => { logger.info('[main-process] timerTask, from TimerJob data:', data); - // 发送数据到渲染进程 - event.sender.send(`${channel}`, data) - }) - - // 执行任务及监听进度 异步 - // myjob.execPromise('./jobs/example/timer', {jobId}).then(task => { - // task.emitter.on(eventName, (data) => { - // Log.info('[main-process] timerTask, from TimerJob data:', data); - // // 发送数据到渲染进程 - // event.sender.send(`${channel}`, data) - // }) - // }); + // Send data to the rendering process + event.sender.send(`${channel}`, data); + }); - res.pid = timerTask.pid; + res.pid = timerTask.pid; this.taskForJob[jobId] = timerTask; } - if (action == 'close') { + if (action === 'close') { oneTask = this.taskForJob[jobId]; oneTask.kill(); - event.sender.send(`${channel}`, {jobId, number:0, pid:0}); + event.sender.send(`${channel}`, { jobId, number: 0, pid: 0 }); } - if (action == 'pause') { + if (action === 'pause') { oneTask = this.taskForJob[jobId]; oneTask.callFunc('./jobs/example/timer', 'pause', jobId); } - if (action == 'resume') { + if (action === 'resume') { oneTask = this.taskForJob[jobId]; oneTask.callFunc('./jobs/example/timer', 'resume', jobId, oneTask.pid); } @@ -100,64 +93,62 @@ class FrameworkService { return res; } - - /** - * 创建pool - */ - doCreatePool(num, event) { + * Create a pool + */ + doCreatePool(num: number, event: any): void { const channel = 'controller.framework.createPoolNotice'; - this.myJobPool.create(num).then(pids => { + this.myJobPool.create(num).then((pids: number[]) => { event.reply(`${channel}`, pids); }); } /** - * 通过进程池执行任务 - */ - doJobByPool(jobId, action, event) { + * Execute a job through the job pool + */ + doJobByPool(jobId: string, action: string, event: any): any { let res = {}; const channel = 'controller.framework.timerJobProgress'; - if (action == 'run') { - // 异步-执行任务及监听进度 - this.myJobPool.runPromise('./jobs/example/timer', {jobId}).then(task => { - - // 监听器名称唯一,否则会出现重复监听。 - // 任务完成时,需要移除监听器,防止内存泄漏 + if (action === 'run') { + // Asynchronously execute the job and listen for progress + this.myJobPool.runPromise('./jobs/example/timer', { jobId }).then((task: any) => { + // Listener name must be unique, otherwise there will be duplicate listeners + // When the task is completed, the listener should be removed to prevent memory leaks let eventName = 'job-timer-progress-' + jobId; - task.emitter.on(eventName, (data) => { + task.emitter.on(eventName, (data: any) => { logger.info('[main-process] [ChildPoolJob] timerTask, from TimerJob data:', data); - - // 发送数据到渲染进程 - event.sender.send(`${channel}`, data) - // 如果收到任务完成的消息,移除监听器 + // Send data to the rendering process + event.sender.send(`${channel}`, data); + + // If the task completion message is received, remove the listener if (data.end) { task.emitter.removeAllListeners(eventName); } }); - res.pid = task.pid; + res.pid = task.pid; }); } return res; } /** - * 获取正在运行的 job 进程 - */ - monitorJob() { + * Monitor running jobs + */ + monitorJob(): void { setInterval(() => { let jobPids = this.myJob.getPids(); let jobPoolPids = this.myJobPool.getPids(); logger.info(`[main-process] [monitorJob] jobPids: ${jobPids}, jobPoolPids: ${jobPoolPids}`); - }, 5000) + }, 5000); } - } +// Setting the class toString method, which is not common in TypeScript FrameworkService.toString = () => '[class FrameworkService]'; -module.exports = { - FrameworkService, - frameworkService: new FrameworkService() -}; \ No newline at end of file +const frameworkService: FrameworkService = new FrameworkService(); +export { + FrameworkService, + frameworkService +}; \ No newline at end of file diff --git a/src/electron/service/job/user.ts b/src/electron/service/job/user.ts index e463365..b55f790 100644 --- a/src/electron/service/job/user.ts +++ b/src/electron/service/job/user.ts @@ -1,26 +1,23 @@ -'use strict'; - -const { logger } = require('ee-core/log'); +import { logger } from 'ee-core/log'; // The service used in the job should not rely on Electron's API, as it may cause errors class UserService { - /** - * hello + * Hello method + * @param args The arguments passed to the method */ - async hello(args) { + async hello(args: any): Promise<{ status: string; params: any }> { let obj = { - status:'ok', - params: args - } + status: 'ok', + params: args, + }; logger.info('UserService obj:', obj); return obj; } - } +// Setting the class toString method, which is not common in TypeScript UserService.toString = () => '[class UserService]'; -module.exports = { - UserService -}; \ No newline at end of file + +export { UserService }; \ No newline at end of file diff --git a/src/electron/service/os/auto_updater.ts b/src/electron/service/os/auto_updater.ts index 84135f1..d8e8612 100644 --- a/src/electron/service/os/auto_updater.ts +++ b/src/electron/service/os/auto_updater.ts @@ -1,35 +1,31 @@ -const { app: electronApp } = require('electron'); -const { autoUpdater } = require("electron-updater"); -const { is } = require('ee-core/utils'); -const { logger } = require('ee-core/log'); -const { getConfig } = require('ee-core/config'); -const { getMainWindow, setCloseAndQuit } = require('ee-core/electron/window'); +import { app as electronApp } from 'electron'; +import { autoUpdater } from 'electron-updater'; +import { is } from 'ee-core/utils'; +import { logger } from 'ee-core/log'; +import { getConfig } from 'ee-core/config'; +import { getMainWindow, setCloseAndQuit } from 'ee-core/electron/window'; /** - * 自动升级 - * @class + * AutoUpdater class for automatic updates */ class AutoUpdater { - - constructor() { - } + constructor() {} /** - * 创建 + * Create and configure the auto updater */ - create () { + create(): void { logger.info('[addon:autoUpdater] load'); const cfg = getConfig().customize.autoUpdater; - if ((is.windows() && cfg.windows) - || (is.macOS() && cfg.macOS) - || (is.linux() && cfg.linux)) - { + if ((is.windows() && cfg.windows) || + (is.macOS() && cfg.macOS) || + (is.linux() && cfg.linux)) { // continue } else { - return + return; } - // 是否检查更新 + // Check for updates immediately if (cfg.force) { this.checkUpdate(); } @@ -40,127 +36,127 @@ class AutoUpdater { noAvailable: 2, downloading: 3, downloaded: 4, - } + } as const; const version = electronApp.getVersion(); logger.info('[addon:autoUpdater] current version: ', version); - - // 设置下载服务器地址 + + // Set the update server URL let server = cfg.options.url; let lastChar = server.substring(server.length - 1); server = lastChar === '/' ? server : server + "/"; cfg.options.url = server; - - // 是否后台自动下载 + + // Auto download updates in the background autoUpdater.autoDownload = cfg.force ? true : false; - + try { autoUpdater.setFeedURL(cfg.options); } catch (error) { logger.error('[addon:autoUpdater] setFeedURL error : ', error); } - + autoUpdater.on('checking-for-update', () => { - //sendStatusToWindow('正在检查更新...'); - }) + // 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) => { const info = { status: status.error, - desc: err - } + 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 - } + transferredSize: transferredSize, + }; logger.info('[addon:autoUpdater] progress: ', text); this.sendStatusToWindow(info); - }) + }); autoUpdater.on('update-downloaded', (info) => { info.status = status.downloaded; info.desc = '下载完成'; this.sendStatusToWindow(info); - // 托盘插件里面设置了阻止窗口关闭,这里设置允许关闭窗口 + // Allow the window to close setCloseAndQuit(true); - + // Install updates and exit the application autoUpdater.quitAndInstall(); }); } /** - * 检查更新 + * Check for updates */ - checkUpdate () { + checkUpdate(): void { autoUpdater.checkForUpdates(); } - + /** - * 下载更新 + * Download updates */ - download () { + download(): void { autoUpdater.downloadUpdate(); } /** - * 向前端发消息 + * Send status to the frontend */ - sendStatusToWindow(content = {}) { + sendStatusToWindow(content = {}): void { const textJson = JSON.stringify(content); const channel = 'custom.app.updater'; const win = getMainWindow(); win.webContents.send(channel, textJson); } - + /** - * 单位转换 + * Convert bytes to a more readable format */ - bytesChange (limit) { + bytesChange(limit: number): string { let size = ""; - if(limit < 0.1 * 1024){ + 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"; + } 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); + 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; - } + } } +// Setting the class toString method, which is not common in TypeScript AutoUpdater.toString = () => '[class AutoUpdater]'; -module.exports = { - autoUpdater: new AutoUpdater() -}; \ No newline at end of file + +export { AutoUpdater, autoUpdater: new AutoUpdater() }; \ No newline at end of file diff --git a/src/electron/service/os/window.ts b/src/electron/service/os/window.ts index f648d94..ecb53e5 100644 --- a/src/electron/service/os/window.ts +++ b/src/electron/service/os/window.ts @@ -1,34 +1,33 @@ -'use strict'; - -const path = require('path'); -const { app: electronApp } = require('electron'); -const { BrowserWindow, Notification } = require('electron'); -const { getMainWindow } = require('ee-core/electron/window'); -const { isProd, getBaseDir } = require('ee-core/ps'); +import path from 'path'; +import { app as electronApp, BrowserWindow, Notification } from 'electron'; +import { getMainWindow } from 'ee-core/electron/window'; +import { isProd, getBaseDir } from 'ee-core/ps'; +import { getConfig } from 'ee-core/config'; /** - * Window - * @class + * WindowService class for managing windows */ class WindowService { + myNotification: Notification | null; + windows: { [key: string]: BrowserWindow }; constructor() { this.myNotification = null; - this.windows = {} + this.windows = {}; } /** * Create a new window */ - createWindow(args) { + createWindow(args: { type: string; content: string; windowName: string; windowTitle: string }): number { const { type, content, windowName, windowTitle } = args; - let contentUrl = null; - if (type == 'html') { - contentUrl = path.join('file://', getBaseDir(), content) - } else if (type == 'web') { + let contentUrl: string | null = null; + if (type === 'html') { + contentUrl = path.join('file://', getBaseDir(), content); + } else if (type === 'web') { contentUrl = content; - } else if (type == 'vue') { - let addr = 'http://localhost:8080' + } else if (type === 'vue') { + let addr = 'http://localhost:8080'; if (isProd()) { const { mainServer } = getConfig(); if (isFileProtocol(mainServer)) { @@ -40,7 +39,7 @@ class WindowService { contentUrl = addr + content; } else { - // some + // Handle other types if necessary } console.log('contentUrl: ', contentUrl); @@ -48,85 +47,83 @@ class WindowService { title: windowTitle, x: 10, y: 10, - width: 980, + width: 980, height: 650, webPreferences: { contextIsolation: false, nodeIntegration: true, }, - } + }; const win = new BrowserWindow(opt); const winContentsId = win.webContents.id; - win.loadURL(contentUrl); + win.loadURL(contentUrl!); win.webContents.openDevTools(); this.windows[windowName] = win; return winContentsId; } - + /** * Get window contents id */ - getWCid(args) { + getWCid(args: { windowName: string }): number { const { windowName } = args; - let win; - if (windowName == 'main') { + let win: BrowserWindow; + if (windowName === 'main') { win = getMainWindow(); } else { win = this.windows[windowName]; } - + return win.webContents.id; } /** * Realize communication between two windows through the transfer of the main process */ - communicate(args) { + communicate(args: { receiver: string; content: any }): void { const { receiver, content } = args; - if (receiver == 'main') { + if (receiver === 'main') { const win = getMainWindow(); win.webContents.send('controller.os.window2ToWindow1', content); - } else if (receiver == 'window2') { + } else if (receiver === 'window2') { const win = this.windows[receiver]; win.webContents.send('controller.os.window1ToWindow2', content); } - } + } /** - * createNotification + * Create a notification */ - createNotification(options, event) { + createNotification(options: { [key: string]: any }, event: any): void { const channel = 'controller.os.sendNotification'; this.myNotification = new Notification(options); if (options.clickEvent) { - this.myNotification.on('click', (e) => { + this.myNotification.on('click', () => { let data = { type: 'click', - msg: '您点击了通知消息' - } - event.reply(`${channel}`, data) + msg: '您点击了通知消息', + }; + event.reply(`${channel}`, data); }); } if (options.closeEvent) { - this.myNotification.on('close', (e) => { + this.myNotification.on('close', () => { let data = { type: 'close', - msg: '您关闭了通知消息' - } - event.reply(`${channel}`, data) + msg: '您关闭了通知消息', + }; + event.reply(`${channel}`, data); }); } this.myNotification.show(); } - } +// Setting the class toString method, which is not common in TypeScript WindowService.toString = () => '[class WindowService]'; -module.exports = { - WindowService, - windowService: new WindowService() -}; \ No newline at end of file + +export { WindowService, windowService: new WindowService() }; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..554d30c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "useDefineForClassFields": true, + "sourceMap": true, + "skipLibCheck": true, + "types": ["node"], + "esModuleInterop": true, + + // "allowJs": true, + // "checkJs": true, + + /* Bundler mode */ + "moduleResolution": "bundler", // node + "resolveJsonModule": true, + "isolatedModules": true, + //"noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src/**/*" + ] +} + \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..05020bd --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,17 @@ +import {defineConfig} from 'vite' +import {resolve} from 'path'; +import dts from 'vite-plugin-dts' + +export default defineConfig({ + define: {'process.env': {}}, + build: { + minify: "esbuild", + lib: { + entry: resolve(__dirname, './src/electron/main.ts'), + formats: ['cjs'] + }, + outDir: "runtime", + }, + plugins: [dts({rollupTypes: true}), + ], +})