feat(desktop): implement phase 1 tauri client
This commit is contained in:
@@ -5,6 +5,7 @@ CTMS 文档入口只展示当前仍会影响开发、发布和运维决策的内
|
||||
## 当前约束
|
||||
|
||||
- [`desktop-project-plan.md`](desktop-project-plan.md): 桌面端 Tauri 项目边界、阶段计划与必读约束
|
||||
- [`desktop-phase-1-design.md`](desktop-phase-1-design.md): 桌面端第一阶段 macOS 在线客户端详细方案
|
||||
- [`branch-governance.md`](branch-governance.md): 长期分支治理规则
|
||||
- [`guides/release-checklist.md`](guides/release-checklist.md): 发布前检查项与回归门禁
|
||||
- [`audits/storage-persistence-governance.md`](audits/storage-persistence-governance.md): 重要数据落库治理基线
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
# CTMS 桌面端第一阶段详细方案
|
||||
|
||||
日期:2026-06-30
|
||||
|
||||
## 目标
|
||||
|
||||
第一阶段只交付 macOS 在线桌面客户端。桌面端使用 Tauri 承载现有 Vue/Vite 前端,连接已有 CTMS 服务端,不内嵌后端、不内嵌数据库、不做离线能力。
|
||||
|
||||
本阶段结束后,应能在 macOS 上启动 CTMS 桌面 App,配置 CTMS 服务端地址,完成登录,并执行现有 Web 端的常规在线业务流程。Web 端构建和现有 Docker/nginx 部署必须继续可用。
|
||||
|
||||
## 范围边界
|
||||
|
||||
本阶段必须做:
|
||||
|
||||
- 在 `frontend/` 内加入 Tauri 工程结构。
|
||||
- 复用现有 Vue 3、Vite、Element Plus、Pinia、Vue Router、Axios 前端代码。
|
||||
- 让桌面端连接已有 CTMS 后端公开入口,推荐连接 nginx 入口而不是直接连接后端容器。
|
||||
- 提供桌面端服务端地址配置能力。
|
||||
- 抽出最小运行时适配层,避免业务页面直接依赖 Tauri API。
|
||||
- 保持认证、权限、审计和业务数据持久化由 FastAPI 后端裁决。
|
||||
- 产出 macOS 开发构建流程和后续签名、公证、DMG 发布路径。
|
||||
|
||||
本阶段明确不做:
|
||||
|
||||
- 离线登录、离线浏览、离线草稿、离线队列、离线同步。
|
||||
- 本地 PostgreSQL、SQLite、IndexedDB 业务数据缓存或本地 API 镜像。
|
||||
- 内嵌 Python/FastAPI 后端服务。
|
||||
- 重写 CTMS 业务页面。
|
||||
- Windows 安装包交付。
|
||||
- 自动更新实现。
|
||||
- token/session 安全存储迁移;该事项进入第二阶段。
|
||||
|
||||
## 当前代码影响点
|
||||
|
||||
现状:
|
||||
|
||||
- `frontend/src/api/axios.ts` 和 `frontend/src/api/authClient.ts` 的 `baseURL` 都是 `/`。
|
||||
- API 调用路径均为 `/api/v1/...`。
|
||||
- Web 端依赖 nginx 同域反代 `/api`。
|
||||
- Tauri 打包后页面运行在桌面 WebView 中,不能继续假设 `/api` 一定代表 CTMS 服务端。
|
||||
- `frontend/src/utils/auth.ts` 当前使用 `localStorage` 保存 token。
|
||||
- `frontend/src/session/sessionManager.ts` 依赖 `localStorage`、`sessionStorage` 和 `BroadcastChannel`。
|
||||
|
||||
第一阶段的核心改动是先解决“桌面端如何知道并访问服务端地址”,同时尽量不触碰业务页面。
|
||||
|
||||
## 目标架构
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Tauri macOS App"] --> B["Bundled Vue/Vite Frontend"]
|
||||
B --> C["Runtime Adapters"]
|
||||
C --> D["Configured CTMS Server URL"]
|
||||
D --> E["nginx / HTTPS entry"]
|
||||
E --> F["FastAPI backend"]
|
||||
F --> G["PostgreSQL"]
|
||||
```
|
||||
|
||||
桌面端只负责本地窗口、运行时配置和少量平台能力。业务数据仍走服务端 API,权限和审计仍由后端完成。
|
||||
|
||||
## Tauri 工程方案
|
||||
|
||||
Tauri 目录放在现有前端工程内:
|
||||
|
||||
```text
|
||||
frontend/
|
||||
src-tauri/
|
||||
tauri.conf.json
|
||||
Cargo.toml
|
||||
src/
|
||||
main.rs
|
||||
capabilities/
|
||||
default.json
|
||||
```
|
||||
|
||||
建议新增脚本:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"tauri": "tauri",
|
||||
"desktop:dev": "tauri dev",
|
||||
"desktop:build": "tauri build",
|
||||
"desktop:bundle:dmg": "tauri build -- --bundles dmg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Tauri 配置方向:
|
||||
|
||||
- `build.beforeDevCommand`: `npm run dev`
|
||||
- `build.beforeBuildCommand`: `npm run build`
|
||||
- `build.devUrl`: `http://localhost:5173`
|
||||
- `build.frontendDist`: `../dist`
|
||||
- 主窗口标题:`CTMS`
|
||||
- 主窗口初始尺寸建议:`1440x900`
|
||||
- 最小窗口尺寸建议:`1180x760`
|
||||
- bundle identifier 待最终确认,临时建议:`cn.huapont.ctms.desktop`
|
||||
|
||||
第一阶段不加载远程 Web UI。Tauri 只加载本地打包出的前端资源,远程访问仅限 Axios 访问配置好的 CTMS 服务端。
|
||||
|
||||
## Vite 调整方案
|
||||
|
||||
当前 `vite.config.ts` 为 Docker 开发做了固定代理:
|
||||
|
||||
- dev server 端口:`5173`
|
||||
- HMR client port:`8888`
|
||||
- `/api` 代理目标:`http://backend:8000`
|
||||
|
||||
为兼容 Web、Docker 和 Tauri,建议改成环境变量驱动:
|
||||
|
||||
- `VITE_DEV_API_PROXY_TARGET`:默认 `http://backend:8000`。
|
||||
- `VITE_HMR_CLIENT_PORT`:Docker/nginx 开发时设为 `8888`,桌面端开发不设置。
|
||||
- `TAURI_DEV_HOST`:按 Tauri/Vite 推荐方式兼容 Tauri dev。
|
||||
|
||||
Vite 配置需要补充:
|
||||
|
||||
- `server.strictPort: true`,避免 Tauri devUrl 与 Vite 实际端口不一致。
|
||||
- `server.watch.ignored: ["**/src-tauri/**"]`,避免 Rust 目录变动触发不必要的前端监听。
|
||||
- `clearScreen: false`,避免 Rust 编译错误被 Vite 清屏隐藏。
|
||||
- `build.target` 按 Tauri 平台设置:Windows 使用 Chromium 目标,macOS 使用 Safari/WebKit 目标。
|
||||
- `envPrefix` 保留 `VITE_`,并允许 `TAURI_ENV_*`。
|
||||
|
||||
## 服务端地址配置
|
||||
|
||||
新增运行时适配层:
|
||||
|
||||
```text
|
||||
frontend/src/runtime/
|
||||
platform.ts
|
||||
apiBaseUrl.ts
|
||||
desktopServerConfig.ts
|
||||
```
|
||||
|
||||
职责:
|
||||
|
||||
- `platform.ts`
|
||||
- 判断当前是否运行在 Tauri。
|
||||
- 判断目标平台是 Web、macOS 桌面端还是 Windows 桌面端。
|
||||
- 业务页面不得直接读取 Tauri 全局对象。
|
||||
|
||||
- `desktopServerConfig.ts`
|
||||
- 保存和读取桌面端服务端地址。
|
||||
- 第一阶段可继续使用 `localStorage` 保存服务器地址;这不是业务数据,也不是离线能力。
|
||||
- key 建议:`ctms_desktop_server_url`。
|
||||
- 仅接受 `http://localhost`、`http://127.0.0.1` 或 `https://...`。非本地生产服务不接受明文 HTTP。
|
||||
|
||||
- `apiBaseUrl.ts`
|
||||
- Web 端返回 `/`,保持现有同域 `/api` 行为。
|
||||
- 桌面端返回配置的服务端 origin,例如 `https://ctms.example.com/`。
|
||||
- 统一规范尾斜杠,避免拼接出错。
|
||||
|
||||
Axios 调整:
|
||||
|
||||
- `frontend/src/api/axios.ts` 使用 `resolveApiBaseUrl()` 初始化 `baseURL`。
|
||||
- `frontend/src/api/authClient.ts` 同步使用同一 baseURL。
|
||||
- 当桌面端服务端地址变化时,需要更新两个 Axios 实例的 `defaults.baseURL`。
|
||||
- 现有 API path 继续保持 `/api/v1/...`,不修改业务 API 文件。
|
||||
|
||||
## 服务端配置入口
|
||||
|
||||
第一阶段需要一个轻量的桌面端服务端设置入口。
|
||||
|
||||
建议实现方式:
|
||||
|
||||
- 桌面端启动时,如果没有服务端地址,则在登录页前展示服务端设置界面。
|
||||
- 登录页提供“服务器设置”入口,允许修改当前服务端地址。
|
||||
- 保存前调用 `${serverUrl}/health` 做连通性检查。
|
||||
- 连通性检查失败时允许用户重新输入,不自动降级到离线模式。
|
||||
- Web 端不显示桌面端服务器设置入口。
|
||||
|
||||
建议新增文件:
|
||||
|
||||
```text
|
||||
frontend/src/views/DesktopServerSettings.vue
|
||||
frontend/src/router/desktopGuard.ts
|
||||
frontend/src/runtime/desktopServerConfig.ts
|
||||
```
|
||||
|
||||
路由策略:
|
||||
|
||||
- 保持现有 Web 路由结构。
|
||||
- 桌面端未配置服务端时,将用户导向 `/desktop/server-settings`。
|
||||
- `/login` 页面中允许打开服务器设置。
|
||||
- Web 端访问 `/desktop/server-settings` 时重定向到 `/login` 或显示不可用状态。
|
||||
|
||||
## 认证和会话策略
|
||||
|
||||
第一阶段保持现有认证机制:
|
||||
|
||||
- 登录仍使用后端登录公钥和加密登录流程。
|
||||
- token 仍通过 `frontend/src/utils/auth.ts` 存储在 `localStorage`。
|
||||
- 会话超时、token keep-alive、401 refresh 仍沿用现有逻辑。
|
||||
|
||||
本阶段只允许做为 Tauri 接入所必需的最小改动:
|
||||
|
||||
- API baseURL 可切换。
|
||||
- 服务端地址变化时清理当前 token 和项目上下文,要求重新登录。
|
||||
- 不引入桌面安全存储;该事项归入第二阶段。
|
||||
|
||||
## Tauri 权限策略
|
||||
|
||||
第一阶段不需要文件系统、Shell、系统通知、自动更新或单实例插件。
|
||||
|
||||
权限原则:
|
||||
|
||||
- 只启用主窗口运行所需的最小 core capability。
|
||||
- 不开放宽泛文件系统权限。
|
||||
- 不开放 shell 执行能力。
|
||||
- 不开放远程页面访问 Tauri command 的能力。
|
||||
- 如确实需要读取 App 版本或平台信息,优先通过窄适配层处理,并明确 capability。
|
||||
|
||||
第一阶段建议不新增自定义 Tauri command。服务端地址配置可以先由前端 `localStorage` 完成。
|
||||
|
||||
## macOS 打包路径
|
||||
|
||||
开发构建:
|
||||
|
||||
```bash
|
||||
cd /Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop/frontend
|
||||
npm run desktop:dev
|
||||
```
|
||||
|
||||
生产构建:
|
||||
|
||||
```bash
|
||||
cd /Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop/frontend
|
||||
npm run desktop:build
|
||||
```
|
||||
|
||||
DMG 构建:
|
||||
|
||||
```bash
|
||||
cd /Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop/frontend
|
||||
npm run desktop:bundle:dmg
|
||||
```
|
||||
|
||||
正式分发前需要:
|
||||
|
||||
- Apple Developer 账号。
|
||||
- macOS 代码签名证书。
|
||||
- notarization 所需 App Store Connect API 或 Apple ID 凭据。
|
||||
- 明确是否分发 DMG,第一阶段推荐 DMG。
|
||||
|
||||
第一阶段可以先产出未签名或 ad-hoc 签名的内部开发构建,但不能把它描述为正式可分发版本。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 初始化 Tauri
|
||||
- 安装 `@tauri-apps/cli`。
|
||||
- 在 `frontend/` 下生成 `src-tauri/`。
|
||||
- 固定基础配置:app name、window title、bundle identifier、devUrl、frontendDist。
|
||||
|
||||
2. 调整 Vite
|
||||
- 引入 Tauri 兼容配置。
|
||||
- 保持 Docker/nginx 开发代理不破坏。
|
||||
- 使用环境变量控制代理和 HMR。
|
||||
|
||||
3. 新增运行时适配层
|
||||
- 添加 `platform.ts`。
|
||||
- 添加 `apiBaseUrl.ts`。
|
||||
- 添加 `desktopServerConfig.ts`。
|
||||
- 新增单元测试覆盖 URL 规范化、Web/Tauri 分支和非法 URL 拒绝。
|
||||
|
||||
4. 改造 API client
|
||||
- `axios.ts` 使用统一 baseURL。
|
||||
- `authClient.ts` 使用统一 baseURL。
|
||||
- 服务端地址变化后刷新 Axios baseURL。
|
||||
- 保持 API path 和业务模块不变。
|
||||
|
||||
5. 添加桌面服务端设置界面
|
||||
- 桌面端未配置服务端时拦截到设置页。
|
||||
- 保存时校验 URL 和 `/health`。
|
||||
- 修改服务端地址时清理当前登录态和项目上下文。
|
||||
|
||||
6. 最小 Tauri 权限
|
||||
- 检查 `capabilities/default.json`。
|
||||
- 移除第一阶段不需要的插件和权限。
|
||||
- 不新增自定义 command,除非实现过程证明必要。
|
||||
|
||||
7. macOS 验证和文档
|
||||
- 运行 Web 构建、类型检查、单元测试。
|
||||
- 运行 Tauri dev。
|
||||
- 验证 macOS 打包。
|
||||
- 补充桌面端运行说明。
|
||||
|
||||
## 验收清单
|
||||
|
||||
功能验收:
|
||||
|
||||
- macOS 桌面 App 可以启动。
|
||||
- 首次启动未配置服务端时进入服务器设置。
|
||||
- 服务端地址保存前会校验 `/health`。
|
||||
- 配置有效服务端后可以登录。
|
||||
- 登录后能进入项目列表和项目工作区。
|
||||
- 现有权限控制、401 refresh、会话超时行为与 Web 端一致。
|
||||
- 切换服务端地址会清理当前登录态。
|
||||
|
||||
工程验收:
|
||||
|
||||
- `npm run build` 通过。
|
||||
- `npm run type-check` 通过。
|
||||
- `npm run test:unit` 通过,或明确记录失败原因。
|
||||
- `npm run desktop:dev` 可启动 macOS 窗口。
|
||||
- `npm run desktop:build` 可完成构建。
|
||||
- Web 端 Docker/nginx 访问不回归。
|
||||
|
||||
边界验收:
|
||||
|
||||
- 没有新增本地业务数据缓存。
|
||||
- 没有内嵌后端服务。
|
||||
- 没有本地数据库。
|
||||
- 没有离线队列或同步机制。
|
||||
- Tauri API 没有散落在业务页面中。
|
||||
- Tauri capability 没有开放第一阶段不需要的文件系统或 shell 权限。
|
||||
|
||||
## 风险和决策点
|
||||
|
||||
- bundle identifier 需要正式确认,建议在第一阶段实现前由产品或组织负责人定稿。
|
||||
- 桌面端连接公开 CTMS 服务时,生产环境应使用 HTTPS;本地开发可允许 localhost HTTP。
|
||||
- 当前后端 CORS 是宽松配置。第一阶段可先不改后端,但正式分发前应评估是否收紧允许来源。
|
||||
- token 第一阶段仍在 `localStorage`,这是有意识的阶段性选择;安全存储迁移必须排入第二阶段。
|
||||
- macOS 正式分发需要 Apple Developer、签名和 notarization,不应等到最后一天处理。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- Tauri 创建项目与向现有前端加入 Tauri:https://tauri.app/start/create-project/
|
||||
- Tauri + Vite 配置:https://tauri.app/start/frontend/vite/
|
||||
- Tauri capabilities:https://tauri.app/security/capabilities/
|
||||
- Tauri DMG 分发:https://tauri.app/distribute/dmg/
|
||||
- Tauri macOS 签名与公证:https://tauri.app/distribute/sign/macos/
|
||||
- Tauri updater 资料,供第二阶段使用:https://tauri.app/plugin/updater/
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
第一阶段交付一个面向现有 CTMS 服务的 macOS 桌面壳。
|
||||
|
||||
详细方案见 [`desktop-phase-1-design.md`](desktop-phase-1-design.md)。
|
||||
|
||||
范围:
|
||||
|
||||
- 在现有前端工程中加入 Tauri 项目结构。
|
||||
|
||||
Reference in New Issue
Block a user