13 KiB
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.winControlwindow.contextMenuwindow.pauseMenuwindow.sessionwindow.appLoggerwindow.appConfigwindow.nativeDialogwindow.ticketToMainwindow.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.handleipcRenderer.invokeipcRenderer.send/oncontextBridge.exposeInMainWorld
Tauri 对应方案:
invoke()调用 Rust#[tauri::command]emit/listen做窗口间事件通信- 直接在前端封装
src/renderer/src/tauri-api/*替代window.xxx
建议:
- 不再保留
window.xxx直挂模式 - 改为前端统一封装模块,例如:
src/renderer/src/host/session.tssrc/renderer/src/host/config.tssrc/renderer/src/host/logger.tssrc/renderer/src/host/window.tssrc/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> - 其他平台:应用数据目录
- Linux:
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获取/设置
建议:
- 维持现有结构:
empUidwinUidqueueToken
4.8 多窗口事件转发
当前 Electron:
ticket:main-actionmain:ticket-action
Tauri 对应方案:
- 指定窗口
emit_to - 目标窗口
listen
建议:
- 保持当前事件模型:
ticket -> main呼叫ticket -> main评价
- 仅把传输媒介从 Electron IPC 改为 Tauri Event
5. 迁移范围拆解
5.1 前端可直接复用部分
这些部分原则上可以原样保留:
src/renderer/src/views/*.vuesrc/renderer/src/router/index.tssrc/renderer/src/api/index.tssrc/renderer/src/utils/service.ts- 大部分 TypeScript 类型定义
- Axios 与后端接口封装
需要改动的地方主要是所有 window.xxx 调用。
5.2 必须重写的部分
这些 Electron 专属模块需要全部替换:
src/main/index.tssrc/main/window.tssrc/preload/index.tssrc/renderer/src/env.d.ts中的 Electron 全局声明electron.vite.config.tselectron-builder.ymlpackage.json中 Electron 构建脚本和依赖
5.3 可迁移但建议重构的部分
pauseMenu建议从原生菜单改成前端弹窗contextMenu可按实际需要决定是否保留原生window.winControl.loginSuccess()可重构为前端路由 + 新窗口显示逻辑
6. 推荐的 Tauri 目标结构
建议最终目录结构:
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 而重写。
现有:
axiossrc/renderer/src/api/index.tssrc/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
以下逻辑不能直接复用:
fspathosapp.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 依赖
删除:
electronelectron-builderelectron-vitesrc/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
推荐实施顺序:
- 先建立 Tauri 壳与前端适配层
- 再迁移配置、日志、session
- 再迁移窗口、事件、对话框、菜单
- 最后移除 Electron
15. 下一步建议
如果你确认要开始迁移,下一份文档建议继续输出:
TAURI-MIGRATION-TASKS.md
内容包括:
- 逐文件改造清单
- Electron API 到 Tauri API 映射表
src-tauri初始代码结构package.json新脚本方案- 每一步验收标准