12 KiB
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。
第一阶段的核心改动是先解决“桌面端如何知道并访问服务端地址”,同时尽量不触碰业务页面。
目标架构
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 目录放在现有前端工程内:
frontend/
src-tauri/
tauri.conf.json
Cargo.toml
src/
main.rs
capabilities/
default.json
建议新增脚本:
{
"scripts": {
"tauri": "tauri",
"desktop:dev": "tauri dev",
"desktop:build": "tauri build",
"desktop:bundle:dmg": "tauri build -- --bundles dmg"
}
}
Tauri 配置方向:
build.beforeDevCommand:npm run devbuild.beforeBuildCommand:npm run buildbuild.devUrl:http://localhost:5173build.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_*。
服务端地址配置
新增运行时适配层:
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/。 - 统一规范尾斜杠,避免拼接出错。
- Web 端返回
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 端不显示桌面端服务器设置入口。
建议新增文件:
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 打包路径
开发构建:
cd /Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop/frontend
npm run desktop:dev
生产构建:
cd /Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop/frontend
npm run desktop:build
DMG 构建:
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 签名的内部开发构建,但不能把它描述为正式可分发版本。
实施步骤
-
初始化 Tauri
- 安装
@tauri-apps/cli。 - 在
frontend/下生成src-tauri/。 - 固定基础配置:app name、window title、bundle identifier、devUrl、frontendDist。
- 安装
-
调整 Vite
- 引入 Tauri 兼容配置。
- 保持 Docker/nginx 开发代理不破坏。
- 使用环境变量控制代理和 HMR。
-
新增运行时适配层
- 添加
platform.ts。 - 添加
apiBaseUrl.ts。 - 添加
desktopServerConfig.ts。 - 新增单元测试覆盖 URL 规范化、Web/Tauri 分支和非法 URL 拒绝。
- 添加
-
改造 API client
axios.ts使用统一 baseURL。authClient.ts使用统一 baseURL。- 服务端地址变化后刷新 Axios baseURL。
- 保持 API path 和业务模块不变。
-
添加桌面服务端设置界面
- 桌面端未配置服务端时拦截到设置页。
- 保存时校验 URL 和
/health。 - 修改服务端地址时清理当前登录态和项目上下文。
-
最小 Tauri 权限
- 检查
capabilities/default.json。 - 移除第一阶段不需要的插件和权限。
- 不新增自定义 command,除非实现过程证明必要。
- 检查
-
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/