You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

646 lines
13 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# `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` 新脚本方案
- 每一步验收标准