|
|
# `call-client` 迁移到 Tauri 技术文档
|
|
|
|
|
|
## 1. 目标
|
|
|
|
|
|
将当前基于 `Electron + Vue 3 + TypeScript + electron-vite` 的桌面应用迁移为 `Tauri + Vue 3 + TypeScript`,在尽量保留现有前端业务代码的前提下,替换主进程、窗口管理、IPC、配置与日志等宿主能力。
|
|
|
|
|
|
迁移完成后应满足:
|
|
|
|
|
|
- 保持现有登录、主叫号、票号列表、服务地址配置等业务功能不变
|
|
|
- 保持 Linux(麒麟)打包能力,优先支持 `x64` / `arm64`
|
|
|
- 保持本地配置与日志的 XDG 规范行为
|
|
|
- 保持多窗口、原生确认框、菜单、前后端通信能力
|
|
|
- 为后续减小安装包体积、降低内存占用、提高跨平台一致性做准备
|
|
|
|
|
|
---
|
|
|
|
|
|
## 2. 当前项目现状
|
|
|
|
|
|
当前项目目录与能力大致如下:
|
|
|
|
|
|
- 前端:`Vue 3 + vue-router + element-plus + axios`
|
|
|
- 宿主:`Electron`
|
|
|
- 构建:`electron-vite + electron-builder`
|
|
|
- 主进程入口:`src/main/index.ts`
|
|
|
- 窗口创建:`src/main/window.ts`
|
|
|
- 预加载桥接:`src/preload/index.ts`
|
|
|
- 本地配置:`src/main/app-config.ts`
|
|
|
- 文件日志:`src/main/file-logger.ts`
|
|
|
- 渲染层类型声明:`src/renderer/src/env.d.ts`
|
|
|
|
|
|
当前渲染层大量依赖 `window.xxx` 能力:
|
|
|
|
|
|
- `window.winControl`
|
|
|
- `window.contextMenu`
|
|
|
- `window.pauseMenu`
|
|
|
- `window.session`
|
|
|
- `window.appLogger`
|
|
|
- `window.appConfig`
|
|
|
- `window.nativeDialog`
|
|
|
- `window.ticketToMain`
|
|
|
- `window.mainTicketEvents`
|
|
|
|
|
|
这意味着迁移的核心不是 Vue 页面重写,而是把这些 Electron 注入能力改造成 Tauri 的命令、事件和窗口 API。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 3. 为什么适合迁移到 Tauri
|
|
|
|
|
|
当前项目业务逻辑主要集中在前端,宿主层职责相对清晰:
|
|
|
|
|
|
- 管理窗口
|
|
|
- 提供原生菜单和对话框
|
|
|
- 管理会话状态
|
|
|
- 提供配置读写
|
|
|
- 提供文件日志
|
|
|
- 在多个窗口之间转发事件
|
|
|
|
|
|
这些能力都可以在 Tauri 中找到对应实现,因此该项目具备较好的迁移可行性。
|
|
|
|
|
|
适合迁移的原因:
|
|
|
|
|
|
- 前端已是标准 Vite/Vue 结构,Tauri 可直接复用
|
|
|
- 本地能力边界清晰,便于逐项替换
|
|
|
- Linux 发行打包对 Tauri 更友好
|
|
|
- 当前没有深度依赖 Electron 的 `BrowserView`、`desktopCapturer`、`webContents` 高级能力
|
|
|
|
|
|
---
|
|
|
|
|
|
## 4. Electron 到 Tauri 能力映射
|
|
|
|
|
|
### 4.1 窗口
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `createLoginWindow()`
|
|
|
- `createMainWindow()`
|
|
|
- `createTicketWindow()`
|
|
|
- 运行时调用 `show()`、`focus()`、`restore()`、`minimize()`
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- 主窗口由 Tauri 启动时创建
|
|
|
- 其它窗口通过 `WebviewWindow` 或 Rust 端创建
|
|
|
- 窗口最小化、关闭、显示、聚焦使用 `@tauri-apps/api/window`
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- `login`、`main`、`ticketList` 改为具名 Tauri 窗口
|
|
|
- 窗口路由仍保留 `hash` 路由,降低前端改造成本
|
|
|
|
|
|
### 4.2 IPC / 桥接
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `ipcMain.handle`
|
|
|
- `ipcRenderer.invoke`
|
|
|
- `ipcRenderer.send/on`
|
|
|
- `contextBridge.exposeInMainWorld`
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- `invoke()` 调用 Rust `#[tauri::command]`
|
|
|
- `emit/listen` 做窗口间事件通信
|
|
|
- 直接在前端封装 `src/renderer/src/tauri-api/*` 替代 `window.xxx`
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 不再保留 `window.xxx` 直挂模式
|
|
|
- 改为前端统一封装模块,例如:
|
|
|
- `src/renderer/src/host/session.ts`
|
|
|
- `src/renderer/src/host/config.ts`
|
|
|
- `src/renderer/src/host/logger.ts`
|
|
|
- `src/renderer/src/host/window.ts`
|
|
|
- `src/renderer/src/host/menu.ts`
|
|
|
|
|
|
### 4.3 原生菜单
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- 主进程动态构建菜单
|
|
|
- 用于“办税员窗口 / 票号列表 / 退出程序”
|
|
|
- 暂停菜单用于选择暂停原因
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- Rust 菜单 API
|
|
|
- 或前端自绘菜单 + Rust 命令
|
|
|
- 简单场景也可直接使用前端弹层替代原生菜单
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- “系统/上下文菜单”优先保留原生
|
|
|
- “暂停原因菜单”可以迁移成前端 `Element Plus` 下拉/弹窗,降低 Rust 复杂度
|
|
|
|
|
|
### 4.4 原生确认框
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `dialog.showMessageBox`
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- `@tauri-apps/plugin-dialog`
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- `window.nativeDialog.confirm()` 改为前端封装 `confirmNative()`
|
|
|
- 接口签名保持一致,减少页面改动
|
|
|
|
|
|
### 4.5 配置文件
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `src/main/app-config.ts`
|
|
|
- Linux 下遵循 `XDG_CONFIG_HOME`
|
|
|
- 使用 JSON 文件持久化
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- Rust 命令自己读写 JSON 文件
|
|
|
- 目录使用 `tauri::api::path` 或 Tauri 2 对应 path API
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 继续保持当前配置文件结构不变
|
|
|
- 继续使用 `config.json`
|
|
|
- 路径规则继续保持:
|
|
|
- Linux:`$XDG_CONFIG_HOME/<app>` 或 `~/.config/<app>`
|
|
|
- 其他平台:应用数据目录
|
|
|
|
|
|
### 4.6 文件日志
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `src/main/file-logger.ts`
|
|
|
- Linux 遵循 `XDG_STATE_HOME`
|
|
|
- 纯文本
|
|
|
- 100MB 轮转
|
|
|
- 7 天清理
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- Rust 端实现同样的文件日志模块
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 日志逻辑直接迁移到 Rust
|
|
|
- 保持现有文件命名、轮转、保留策略不变
|
|
|
- 渲染层仍使用统一 `log(level, message)` 接口
|
|
|
|
|
|
### 4.7 Session 状态
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- 主进程内存维护 `sessionState`
|
|
|
- 渲染层通过 IPC 获取/设置
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- Rust `State<T>` 保存内存会话
|
|
|
- 通过 `command` 获取/设置
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 维持现有结构:
|
|
|
- `empUid`
|
|
|
- `winUid`
|
|
|
- `queueToken`
|
|
|
|
|
|
### 4.8 多窗口事件转发
|
|
|
|
|
|
当前 Electron:
|
|
|
|
|
|
- `ticket:main-action`
|
|
|
- `main:ticket-action`
|
|
|
|
|
|
Tauri 对应方案:
|
|
|
|
|
|
- 指定窗口 `emit_to`
|
|
|
- 目标窗口 `listen`
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 保持当前事件模型:
|
|
|
- `ticket -> main` 呼叫
|
|
|
- `ticket -> main` 评价
|
|
|
- 仅把传输媒介从 Electron IPC 改为 Tauri Event
|
|
|
|
|
|
---
|
|
|
|
|
|
## 5. 迁移范围拆解
|
|
|
|
|
|
### 5.1 前端可直接复用部分
|
|
|
|
|
|
这些部分原则上可以原样保留:
|
|
|
|
|
|
- `src/renderer/src/views/*.vue`
|
|
|
- `src/renderer/src/router/index.ts`
|
|
|
- `src/renderer/src/api/index.ts`
|
|
|
- `src/renderer/src/utils/service.ts`
|
|
|
- 大部分 TypeScript 类型定义
|
|
|
- Axios 与后端接口封装
|
|
|
|
|
|
需要改动的地方主要是所有 `window.xxx` 调用。
|
|
|
|
|
|
### 5.2 必须重写的部分
|
|
|
|
|
|
这些 Electron 专属模块需要全部替换:
|
|
|
|
|
|
- `src/main/index.ts`
|
|
|
- `src/main/window.ts`
|
|
|
- `src/preload/index.ts`
|
|
|
- `src/renderer/src/env.d.ts` 中的 Electron 全局声明
|
|
|
- `electron.vite.config.ts`
|
|
|
- `electron-builder.yml`
|
|
|
- `package.json` 中 Electron 构建脚本和依赖
|
|
|
|
|
|
### 5.3 可迁移但建议重构的部分
|
|
|
|
|
|
- `pauseMenu` 建议从原生菜单改成前端弹窗
|
|
|
- `contextMenu` 可按实际需要决定是否保留原生
|
|
|
- `window.winControl.loginSuccess()` 可重构为前端路由 + 新窗口显示逻辑
|
|
|
|
|
|
---
|
|
|
|
|
|
## 6. 推荐的 Tauri 目标结构
|
|
|
|
|
|
建议最终目录结构:
|
|
|
|
|
|
```text
|
|
|
call-client/
|
|
|
├─ src/
|
|
|
│ ├─ renderer/
|
|
|
│ │ └─ src/
|
|
|
│ │ ├─ api/
|
|
|
│ │ ├─ host/
|
|
|
│ │ │ ├─ session.ts
|
|
|
│ │ │ ├─ config.ts
|
|
|
│ │ │ ├─ logger.ts
|
|
|
│ │ │ ├─ window.ts
|
|
|
│ │ │ ├─ dialog.ts
|
|
|
│ │ │ └─ events.ts
|
|
|
│ │ ├─ router/
|
|
|
│ │ ├─ views/
|
|
|
│ │ └─ ...
|
|
|
│ └─ shared/
|
|
|
├─ src-tauri/
|
|
|
│ ├─ src/
|
|
|
│ │ ├─ main.rs
|
|
|
│ │ ├─ commands/
|
|
|
│ │ │ ├─ session.rs
|
|
|
│ │ │ ├─ config.rs
|
|
|
│ │ │ ├─ logger.rs
|
|
|
│ │ │ ├─ window.rs
|
|
|
│ │ │ ├─ dialog.rs
|
|
|
│ │ │ └─ events.rs
|
|
|
│ │ └─ state.rs
|
|
|
│ ├─ tauri.conf.json
|
|
|
│ └─ Cargo.toml
|
|
|
└─ package.json
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 7. 前端接口替换清单
|
|
|
|
|
|
当前前端依赖的 Electron 注入接口,需要替换为 Tauri 封装:
|
|
|
|
|
|
### 7.1 `window.winControl`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- `windowMinimize()`
|
|
|
- `windowClose()`
|
|
|
- `loginSuccess()`
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- `getCurrentWindow().minimize()`
|
|
|
- `getCurrentWindow().close()`
|
|
|
- 登录成功后触发:
|
|
|
- 显示主窗口
|
|
|
- 关闭登录窗口
|
|
|
- 或仅路由切换,视最终窗口方案而定
|
|
|
|
|
|
### 7.2 `window.contextMenu`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- 打开上下文菜单
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- Rust 菜单
|
|
|
- 或前端菜单组件
|
|
|
|
|
|
### 7.3 `window.pauseMenu`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- 弹出暂停原因菜单
|
|
|
- 回传用户选中的原因
|
|
|
|
|
|
建议替代:
|
|
|
|
|
|
- 使用前端对话框/选择器,避免专门做 Rust 菜单事件回传
|
|
|
|
|
|
### 7.4 `window.session`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- `get()`
|
|
|
- `set()`
|
|
|
- `clear()`
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- `invoke('session_get')`
|
|
|
- `invoke('session_set', { ... })`
|
|
|
- `invoke('session_clear')`
|
|
|
|
|
|
### 7.5 `window.appLogger`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- `log(level, message)`
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- `invoke('app_log', { level, message })`
|
|
|
|
|
|
### 7.6 `window.appConfig`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- `getAll()`
|
|
|
- `set(partial)`
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- `invoke('config_get_all')`
|
|
|
- `invoke('config_merge', { partial })`
|
|
|
|
|
|
### 7.7 `window.nativeDialog`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- `confirm({ title, message, okLabel, cancelLabel })`
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- 封装 `plugin-dialog`
|
|
|
|
|
|
### 7.8 `window.ticketToMain` / `window.mainTicketEvents`
|
|
|
|
|
|
当前能力:
|
|
|
|
|
|
- 票号列表窗口通知主窗口执行呼叫/评价
|
|
|
|
|
|
Tauri 替代:
|
|
|
|
|
|
- `emitTo('main', 'ticket-action', payload)`
|
|
|
- 主窗口 `listen('ticket-action', ...)`
|
|
|
|
|
|
---
|
|
|
|
|
|
## 8. 后端 API 层迁移影响
|
|
|
|
|
|
后端 API 请求层基本不需要因为迁移到 Tauri 而重写。
|
|
|
|
|
|
现有:
|
|
|
|
|
|
- `axios`
|
|
|
- `src/renderer/src/api/index.ts`
|
|
|
- `src/renderer/src/utils/service.ts`
|
|
|
|
|
|
保留原则:
|
|
|
|
|
|
- 所有 `/auth/login`、`/call-terminal/*`、`/isRank`、`/getQueueCount` 保持不变
|
|
|
- 仅调整“token 获取来源”和“应用配置读取来源”
|
|
|
|
|
|
需要注意:
|
|
|
|
|
|
- 目前 `service.ts` 从 `window.session.get()` 中拿 `queueToken`
|
|
|
- 迁移后应改成 `host/session.ts` 封装
|
|
|
|
|
|
---
|
|
|
|
|
|
## 9. 打包与发布迁移
|
|
|
|
|
|
当前:
|
|
|
|
|
|
- 使用 `electron-builder`
|
|
|
- 面向 `deb` / `AppImage`
|
|
|
|
|
|
迁移到 Tauri 后:
|
|
|
|
|
|
- 使用 `tauri build`
|
|
|
- Linux 侧通常可生成 `deb` / `AppImage`
|
|
|
|
|
|
建议:
|
|
|
|
|
|
- 保留现有 `resources/call_icon.png`
|
|
|
- 重新配置 Tauri 的:
|
|
|
- 应用名
|
|
|
- 图标
|
|
|
- 窗口尺寸
|
|
|
- 标题栏/装饰策略
|
|
|
|
|
|
---
|
|
|
|
|
|
## 10. 重点风险
|
|
|
|
|
|
### 10.1 多窗口迁移复杂度
|
|
|
|
|
|
当前项目不是单窗口,而是至少有:
|
|
|
|
|
|
- 登录窗口
|
|
|
- 主窗口
|
|
|
- 票号列表窗口
|
|
|
|
|
|
这在 Tauri 可以实现,但实现方式与 Electron 不同,需要提前设计窗口生命周期和事件路由。
|
|
|
|
|
|
### 10.2 原生菜单差异
|
|
|
|
|
|
Electron 菜单 API 较成熟,Tauri 菜单方案和事件模型不同,暂停菜单与上下文菜单可能需要重构。
|
|
|
|
|
|
### 10.3 文件系统逻辑要从 Node 改到 Rust
|
|
|
|
|
|
以下逻辑不能直接复用:
|
|
|
|
|
|
- `fs`
|
|
|
- `path`
|
|
|
- `os`
|
|
|
- `app.getPath()`
|
|
|
|
|
|
需要改写为 Rust。
|
|
|
|
|
|
### 10.4 前端大量 `window.xxx` 依赖
|
|
|
|
|
|
虽然页面 UI 可复用,但所有页面中使用的宿主能力都需要替换接口。
|
|
|
|
|
|
建议先做适配层,不要在页面里直接写 Tauri API。
|
|
|
|
|
|
### 10.5 开发流程变化
|
|
|
|
|
|
从:
|
|
|
|
|
|
- `electron-vite dev`
|
|
|
|
|
|
改为:
|
|
|
|
|
|
- `tauri dev`
|
|
|
|
|
|
工程脚本、CI、打包环境都要同步调整。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 11. 推荐迁移策略
|
|
|
|
|
|
建议使用“分阶段替换”,不要一次性推倒重来。
|
|
|
|
|
|
### 阶段 1:建立 Tauri 空壳
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 保留现有 Vue 前端
|
|
|
- 新建 `src-tauri`
|
|
|
- 跑通 `tauri dev`
|
|
|
- 页面能正常打开
|
|
|
|
|
|
产出:
|
|
|
|
|
|
- `src-tauri/`
|
|
|
- `tauri.conf.json`
|
|
|
- 基础窗口配置
|
|
|
|
|
|
### 阶段 2:建立宿主适配层
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 新建前端 `host/*` 封装
|
|
|
- 暂时不改页面业务,只改调用入口
|
|
|
|
|
|
例如将:
|
|
|
|
|
|
- `window.appConfig.getAll()`
|
|
|
|
|
|
替换为:
|
|
|
|
|
|
- `hostConfig.getAll()`
|
|
|
|
|
|
这样后续无论是 Electron 还是 Tauri,都能通过适配层承接。
|
|
|
|
|
|
### 阶段 3:迁移配置、日志、session
|
|
|
|
|
|
优先迁移最基础的宿主能力:
|
|
|
|
|
|
- 配置文件
|
|
|
- 日志
|
|
|
- 会话状态
|
|
|
|
|
|
因为这些能力会被多个页面依赖。
|
|
|
|
|
|
### 阶段 4:迁移窗口与事件
|
|
|
|
|
|
迁移:
|
|
|
|
|
|
- 登录成功切主窗口
|
|
|
- 票号列表子窗口
|
|
|
- 主窗口与子窗口之间动作事件
|
|
|
|
|
|
### 阶段 5:迁移原生菜单/对话框
|
|
|
|
|
|
迁移:
|
|
|
|
|
|
- 确认框
|
|
|
- 上下文菜单
|
|
|
- 暂停菜单
|
|
|
|
|
|
此阶段可顺便评估哪些能力改成前端组件更合适。
|
|
|
|
|
|
### 阶段 6:移除 Electron 依赖
|
|
|
|
|
|
删除:
|
|
|
|
|
|
- `electron`
|
|
|
- `electron-builder`
|
|
|
- `electron-vite`
|
|
|
- `src/main/*`
|
|
|
- `src/preload/*`
|
|
|
|
|
|
并重写 `package.json` 脚本。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 12. 预计工作量
|
|
|
|
|
|
按当前项目规模估算:
|
|
|
|
|
|
- 前端页面复用:高
|
|
|
- 宿主层重写:中到高
|
|
|
- 多窗口与事件:中
|
|
|
- 打包与环境:中
|
|
|
|
|
|
大致可按以下量级评估:
|
|
|
|
|
|
- 基础可运行 Tauri 版本:1 到 2 天
|
|
|
- 功能完整迁移:3 到 7 天
|
|
|
- 打包与麒麟环境联调:1 到 3 天
|
|
|
|
|
|
实际取决于:
|
|
|
|
|
|
- 是否保留原生菜单
|
|
|
- 是否保留多窗口
|
|
|
- 是否要求与当前行为完全一致
|
|
|
|
|
|
---
|
|
|
|
|
|
## 13. 最小可行迁移方案
|
|
|
|
|
|
如果目标是“尽快落地”,建议先做最小版本:
|
|
|
|
|
|
- 保留单主窗口
|
|
|
- `ticketList` 改为路由页/弹层,而不是独立窗口
|
|
|
- 暂停菜单改为前端弹窗
|
|
|
- 原生确认框使用 Tauri dialog 插件
|
|
|
- 配置、日志、session 用 Rust 命令重写
|
|
|
|
|
|
这样能明显降低迁移复杂度。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 14. 结论
|
|
|
|
|
|
该项目适合迁移到 Tauri,且前端业务代码可大量复用。真正的迁移重点在于:
|
|
|
|
|
|
- 宿主能力替换
|
|
|
- 多窗口与事件通信重构
|
|
|
- 本地配置/日志/session 的 Rust 实现
|
|
|
- 打包链路从 Electron Builder 迁移到 Tauri Build
|
|
|
|
|
|
推荐实施顺序:
|
|
|
|
|
|
1. 先建立 Tauri 壳与前端适配层
|
|
|
2. 再迁移配置、日志、session
|
|
|
3. 再迁移窗口、事件、对话框、菜单
|
|
|
4. 最后移除 Electron
|
|
|
|
|
|
---
|
|
|
|
|
|
## 15. 下一步建议
|
|
|
|
|
|
如果你确认要开始迁移,下一份文档建议继续输出:
|
|
|
|
|
|
- `TAURI-MIGRATION-TASKS.md`
|
|
|
|
|
|
内容包括:
|
|
|
|
|
|
- 逐文件改造清单
|
|
|
- Electron API 到 Tauri API 映射表
|
|
|
- `src-tauri` 初始代码结构
|
|
|
- `package.json` 新脚本方案
|
|
|
- 每一步验收标准
|
|
|
|