0.1.20 • Published 1 year ago

@ultra-node/electron-engine v0.1.20

Weekly downloads
-
License
LGPL 2.1
Repository
-
Last release
1 year ago

electron 项目开发基础库,便于直接开发业务逻辑

toc

1. 引擎初始化

1.1 主进程初始化引擎

​ 在electron主进程入口(main.ts 或 background.ts) 入增加如下代码:

import { initEngine } from '@electron-engine/engine.main'
initEngine()

​ 完整主程序入口文件如下:

import { app } from 'electron'
import { initEngine } from '@electron-engine/engine.main'
import windows from './core/windows/main'

initEngine()

app.on('ready', async () => {
  windows.LoginWindow.createWindow()
})
1.1.1 参数说明
export interface IEngineConfig {
    logger?: ILoggerConfig
    httpServer?: IHttpServerConfig
    rcElectron?: IRCElectronConfig
    appConfig?: IAppConfigConfig
    notification?: INotificationConfig
    shortcut?: IShortcutConfig
    appTray?: IAppTrayConfig
}

1.2 渲染进程初始化引擎

​ 在窗体preload.js文件中增加如下代码:

require('@electron-engine/engine.renderer')

2. Http请求

2.1 业务的http请求基类

import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import HttpRequestBase from '@ultra-node/electron-engine/http-request/HttpRequestBase'
import { IResult } from '@ultra-node/electron-engine/types'
import { EErrorCode } from '@/types'

interface IServerData {
  data: any
  errCode: string
  errMsg: string
  flag: boolean
}
export default class ApiBase extends HttpRequestBase {
  constructor(apiConfig?: AxiosRequestConfig) {
    const config: AxiosRequestConfig = {
      timeout: 1000 * 15, // 15秒
      baseURL: ''
    }
    !!apiConfig && Object.assign(config, apiConfig)
    super(config)
    super.intercepReqeust({
      onBeforeRequest: this.onBeforeRequest,
      onRequestError: this.onRequestError
    })
    super.intercepResponse({
      onAfterResponse: this.onAfterResponse,
      onResponseError: this.onResponseError
    })
  }

  private onBeforeRequest(config: AxiosRequestConfig<any>): AxiosRequestConfig<any> {
    return config
  }

  private onRequestError(error: AxiosError): any {
    const code = error.message === 'canceled' ? EErrorCode.Canceled : error.response?.status
    const result: IResult = {
      isOK: false,
      data: {},
      code,
      msg: error.message
    }
    return Promise.resolve({ data: result })
  }
  /**
   * 将服务端返回格式转化成应用封装格式
   * @param result 服务原始响应数据
   * @returns 应用所需要的响应数据格式
   */
  private onAfterResponse(result: AxiosResponse<any, any>): AxiosResponse<any, any> {
    const serverData = result.data as IServerData
    const appData: IResult = {
      isOK: serverData.flag,
      data: serverData.data,
      code: serverData.flag ? 0 : serverData.errCode, // 将server的成功码统一转换成 0,为和应用其它模块保持一致
      msg: serverData.errMsg
    }
    result.data = appData
    return result
  }

  private onResponseError(error: AxiosError): any {
    const code = error.message === 'canceled' ? EErrorCode.Canceled : error.response?.status
    const msg = error.code === 'ERR_NETWORK' ? '当前网络不可用,请检查网络设置' : error.message?.includes('timeout of') ? '加载超时' : error.message
    const result: IResult = {
      isOK: false,
      data: {},
      code,
      msg
    }
    return Promise.resolve({ data: result })
  }
}

2.2 具体业务请求类

import ApiBase from './ApiBase'

export default class LoginApi extends ApiBase {
  public login(name: string, pwd: string) {
    return this.postForm('/login', { name, pwd })
  }
}

3. 窗体管理

3.1 主进程使用的窗体对象

import MainWindow from '@ultra-node/electron-engine/window/MainWindow'

export default class LoginWindow extends MainWindow {
  devUrl = (process.env.WEBPACK_DEV_SERVER_URL as string) + '/login.html'
  prodUrl = 'app://./login.html'
  windowOptions: Electron.BrowserWindowConstructorOptions = {
    width: 508,
    height: 611,
    minWidth: 508,
    minHeight: 611,
    maxWidth: 508,
    maxHeight: 611,
    frame: false,
    webPreferences: {
      preload: path.join(__dirname, '/preload-login.js'),
      nodeIntegration: true,
      contextIsolation: false
    }
  }
  constructor() {
    super(EWindowName.LoginWindow)
  }
}

3.2 渲染进程使用的窗体对象

import RendererWindow from '@ultra-node/electron-engine/window/RendererWindow'
import { EWindowName } from '..'

export default class LoginWindow extends RendererWindow {
  constructor() {
    super(EWindowName.LoginWindow)
  }
}

4. Ipc 通讯封装

4.1 渲染进程调用主进程,同步返回结果

  • 主进程中:

    import { listenFromRendererSync } from '@ultra-node/electron-engine/ipc/ipc.main'
    
    listenFromRendererSync('event-name', (event: any, param: string) => {
      return 'result'
    })
  • 渲染进程中:

    import { sendToMainSync } from '@ultra-node/electron-engine/ipc/ipc.renderer'
    
    const result = sendToMainSync('event-name','我是参数')

4.2 渲染进程调用主进程,异步返回结果

  • 主进程中:

    import { listenFromRendererAsync } from '@ultra-node/electron-engine/ipc/ipc.main'
    
    listenFromRendererAsync('event-name', (event: any, param: string) => {
      return await OtherMethod()
    })
  • 渲染进程中:

    import { sendToMainAsync } from '@ultra-node/electron-engine/ipc/ipc.renderer'
    
    const result = await sendToMainAsync('event-name','我是参数')

4.3 渲染进程调用主进程,无返回结果

  • 主进程中:

    import { listenFromRendererVoid } from '@ultra-node/electron-engine/ipc/ipc.main'
    
    listenFromRendererVoid('event-name', (event: any, param: string) => {
      OtherMethod()
    })
  • 渲染进程中:

    import { sendToMainVoid } from '@ultra-node/electron-engine/ipc/ipc.renderer'
    
    sendToMainVoid('event-name','我是参数')

4.4 主进程调用渲染进程

  • 主进程中:

    import { sendToRendererVoid } from '@ultra-node/electron-engine/ipc/ipc.main'
    
    sendToRendererVoid(webcontents, 'event-name','我是参数')
  • 渲染进程中:

    import { listenFromMainVoid } from '@ultra-node/electron-engine/ipc/ipc.renderer'
    
    listenFromMainVoid('event-name', (event: any, param: string) => {
      OtherMethod()
    })

5. 日志

5.1 日志初始化

​ 在做engine初始化时,可以添加日志相关参数

	initEngine({
        logger:{
            filePath: 'full path'
        }
    })

// export interface ILoggerConfig {
//   fileLevel?: TLoggerLevel
//   fileMaxSize?: number
//   filePath?: string
//   fileFormat?: string
// }

5.2 主进程使用日志输出

import logger from '@ultra-node/electron-engine/logger/logger.main'
logger.info('i am from main process')

5.3 渲染进程使用日志输出

import logger from '@ultra-node/electron-engine/logger/logger.renderer'
logger.info('i am from renderer process')
logger.debug('i am from renderer process')
logger.error('i am from renderer process')

6. 快捷键管理

6.1 系统快捷键

​ 只要软件存活,无轮是否被焦点,都可以监听到

import { listenSysShortcut, registerSysShortcut } from '@ultra-node/electron-engine/shortcut/shortcut.renderer'

// 注册
registerSysShortcut('shortcut-name','shift+j')
// 监听
listenSysShortcut('shortcut-name',()=>{
    console.log('shortcut-name pressed')
})

6.2 应用快捷键

​ 软件存活,且处于被焦点状态时,才可以收到监听

import { listenAppShortcut, registerAppShortcut } from '@ultra-node/electron-engine/shortcut/shortcut.renderer'

// 注册
registerAppShortcut('shortcut-name','shift+j')
// 监听
listenAppShortcut('shortcut-name',()=>{
    console.log('shortcut-name pressed')
})

7. 应用协议

​ 注册应用唤醒协议,可以将协议格式放到浏览器中进行唤醒app, 生成的协议格式为: protocol://

  • 主进程中注册协议

    import { registerProtocol, unregisterProtocol } from '@ultra-node/electron-engine/protocol/protocol.main'
    
    registerProtocol('rcbw')
  • 主进程中监听协议唤起

    import { listenProtocol } from '@ultra-node/electron-engine/protocol/protocol.main'
    
    listenProtocol('rcbw',(url: string)=> {
        console.log('用户用这个url唤醒的App', url)
    })

8. 应用托盘图标

import initAppTray, { IAppTrayOptions } from '@ultra-node/electron-engine/tray/tray.main'

// 鼠标事件
const onMouseClick = () => {
    // 鼠标点击图标
}
// 右键菜单
const contextMenuItems: MenuItemConstructorOptions[] = [
    {
        label: '退出',
        role: 'quit',
        click: () => {
            app.quit()
        }
    }
]
// 基本信息
const trayOptions: IAppTrayOptions = {
    iconPath: PathUtil.resolvePath('extraResources/icons/32x32.png'),
    toolTip: 'appName',
    contextMenuItems,
    onClick: onMouseClick
}
// 初始化托盘
initAppTray(trayOptions)

9. 系统通知

  • 主进程初始化

    initEngine({
        notification:{
            appId: 'appId',
            init: true
        }
    })
  • 渲染进程发起

    import { showNotification } from '@ultra-node/electron-engine/notification/notification.renderer'
    
    showNotification({
        title:'',
        body:''
    })

10. shell 功能

10.1 打开文件夹,并选中文件

import { showItemInFolder } from '@ultra-node/electron-engine/shell'

showItemInFolder('/data/a.txt')

11. Dictionary 字典类封装

import { Dictionary } from '@ultra-node/electron-engine/dictionary'

const dict = new Dictionary()
dict.set('key', 'value')
dict.get('key')

12. 本地 Http 服务器

​ 使用 express 在主进程搭建的 http 服务,用于资源代理,也可用于第三方应用调用此应用

12.1 服务初始化

// 初始化
initEngine({
    httpServer:{
        init: true,
        defaultControll: true // 是否开启默认处理器
    }
})

12.2 使用

import { startServer } from '@ultra-node/electron-engine/http-server/httpServer.main'

const localhost = await startServer([])
// localhost: http://localhost:8088

12.3 默认处理器

localhost/local/path/filename?url=remote_address

处理机制:当在 local/path 有 filename 资源时,直接返回,否则会从url下载完后返回,并将资源放到 local/path/filename 处

12.4 增加自定义处理

import { ControllerBase } from '@ultra-node/electron-engine/http-server'

class MyController extends ControllerBase{
  public method: 'get' | 'post' = 'get'
  public routePath: string = '/pic/*'
  public handler(req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>, rsp: Response<any, Record<string, any>>): void {
    throw new Error('Method not implemented.')
  }
}

await startServer([new MyController()])

13. app-config: 应用配置

​ 数据会存到本地文件,每次操作都是io, 因此存储仅用于存储简单的软件配置信息

13.1 初始化配置

initEngine({
    appConfig:{
      init: boolean // 是否开启此功能
      fileDir?: string // 文件目录
      fileName?: string // 文件名
      fileExt?: string // 文件后缀
      encryptionKey?: string // 加密字符串
      default?: T // 默认数据格式
    }
})

13.2 使用

import { appConfig } from '@ultra-node/electron-engine/app-config/appConfig.renderer'

appConfig.set('key','value')
appConfig.get('key')

14. app-session: 应用全局缓存

​ 使用主进程存储数据,使用ipc做桥梁,因此此session可用于不同窗体间数据共享,适合全局性变量,但不适合存储业务大量数据

import { appSession } from '@ultra-node/electron-engine/app-session/appSession.renderer'

appSession.set('key','value')
appSession.get('key')

15. rc-electron 融云 imsdk PC端解决方案

​ 开启后,融云 IM 将直接使用协议栈功能,代替websocket通过socket进行通讯

initEngine({
    rcElectron: {
        init: true // 开启功能
    }
})

16. utils: 工具类

16.1 快捷键打开 userdata 目录

import { useOpenUserData } from '@ultra-node/electron-engine/utils/appShortcutUtil'

useOpenUserData()

16.2 获取绝对路径

​ 自动适配开发、生产环境

import { resolvePath } from '@ultra-node/electron-engine/utils/pathUril'

resolvePath('/extraResources/icon')

16.3 获取当前文件寄宿的窗体名称

import { getHostWindowName } from '@ultra-node/electron-engine/utils/windowUtil'

const currentWindowName = getHostWindowName()
0.1.10

1 year ago

0.1.11

1 year ago

0.1.12

1 year ago

0.1.13

1 year ago

0.1.14

1 year ago

0.1.15

1 year ago

0.1.20

1 year ago

0.1.16

1 year ago

0.1.8

1 year ago

0.1.17

1 year ago

0.1.18

1 year ago

0.1.19

1 year ago

0.1.9

1 year ago

0.1.4

1 year ago

0.1.6

1 year ago

0.1.5

1 year ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.0.22

1 year ago

0.0.21

1 year ago

0.0.18

1 year ago

0.0.17

1 year ago

0.0.13

1 year ago

0.0.12

1 year ago

0.0.11

1 year ago

0.0.10

1 year ago

0.0.9

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago