> ## Documentation Index
> Fetch the complete documentation index at: https://www.worldmonitor.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 桌面版发布打包指南（本地、可复现）

> 本指南提供两种桌面变体：full（World Monitor）和 tech（Tech Monitor）的可复现本地打包步骤，涵盖构建脚本、代码签名、公证、图标与安装包生成，帮助维护者与贡献者在 macOS、Windows 与 Linux 上产出与官方发布一致的桌面二进制，并对每一步进行确定性校验。

本指南为两种桌面变体提供可复现的本地打包步骤：

* **full** → `World Monitor`
* **tech** → `Tech Monitor`

变体标识由 Tauri 配置控制：

* full：`src-tauri/tauri.conf.json`
* tech：`src-tauri/tauri.tech.conf.json`

## 前置条件

* Node.js + npm
* Rust 工具链
* 操作系统原生 Tauri 构建前置条件：
  * macOS：Xcode 命令行工具
  * Windows：Visual Studio Build Tools + NSIS + WiX

安装依赖（此操作也会安装桌面脚本所使用的已锁定 Tauri CLI 版本）：

```bash theme={null}
npm ci
```

所有桌面脚本都调用 `node_modules/.bin` 中的本地 `tauri` 二进制文件；在执行 `npm ci` 之后，无需在运行时通过 `npx` 下载包。
如果本地 CLI 缺失，`scripts/desktop-package.mjs` 会立即失败，并显示明确的 `npm ci` 修复提示信息。

## 网络预检与修复

在 CI 或托管网络中运行桌面打包之前，请验证连接性和代理配置：

```bash theme={null}
npm ping
curl -I https://index.crates.io/
env | grep -E '^(HTTP_PROXY|HTTPS_PROXY|NO_PROXY)='
```

如果上述命令失败，请使用以下支持的修复方案之一：

* 内部 npm 镜像/代理。
* 内部 Cargo 稀疏索引/注册表镜像。
* 预先打包的 Rust crates（`src-tauri/vendor/`）+ Cargo 离线模式。
* 在构建之前还原所需包输入的 CI 制品/缓存策略。

有关失败分类标签和故障排除流程，请参见 `docs/TAURI_VALIDATION_REPORT.md`。

## 打包命令

查看脚本用法/帮助：

```bash theme={null}
npm run desktop:package -- --help
```

### macOS（`.app` + `.dmg`）

```bash theme={null}
npm run desktop:package:macos:full
npm run desktop:package:macos:tech
# 或使用通用运行器
npm run desktop:package -- --os macos --variant full
```

### Windows（`.exe` + `.msi`）

```bash theme={null}
npm run desktop:package:windows:full
npm run desktop:package:windows:tech
# 或使用通用运行器
npm run desktop:package -- --os windows --variant tech
```

打包器目标在两个 Tauri 配置中均已锁定，并由打包脚本强制执行：

* macOS：`app,dmg`
* Windows：`nsis,msi`

## Rust 依赖模式（在线与受限网络）

在 `src-tauri/` 中，项目支持两种打包路径：

### 1) 标准在线构建（默认）

使用常规 Cargo 行为（crates.io）：

```bash theme={null}
cd src-tauri
cargo generate-lockfile
cargo tauri build --config tauri.conf.json
```

### 2) 受限网络构建（预打包或内部镜像）

`src-tauri/.cargo/config.toml` 中定义了一个可选的打包源。要使用它，首先在具有注册表访问权限的机器上准备打包好的 crates：

```bash theme={null}
# 从仓库根目录执行
cargo vendor --manifest-path src-tauri/Cargo.toml src-tauri/vendor
```

然后使用以下任一方法启用离线模式：

* 一次性 CLI 覆盖（不修改文件）：

```bash theme={null}
cd src-tauri
cargo generate-lockfile --offline --config 'source.crates-io.replace-with="vendored-sources"'
cargo tauri build --offline --config 'source.crates-io.replace-with="vendored-sources"' --config tauri.conf.json
```

* 本地覆盖文件（推荐用于 CI/可重复的离线作业）：

```bash theme={null}
cp src-tauri/.cargo/config.local.toml.example src-tauri/.cargo/config.local.toml
cd src-tauri
cargo generate-lockfile --offline
cargo tauri build --offline --config tauri.conf.json
```

对于 CI 或内部镜像，请将 `src-tauri/vendor/` 作为制品发布，并在受限网络构建之前还原它。如果您的组织使用内部 crates 镜像而非打包方式，请在 CI 专用 Cargo 配置中将 `source.crates-io.replace-with` 指向该镜像，并运行相同的构建命令。

## 可选的签名/公证钩子

默认情况下使用未签名打包。

如果环境变量中存在签名凭据，Tauri 将在相同的打包命令期间自动签名/公证。

### macOS Apple 开发者签名 + 公证

在打包之前设置（Developer ID 签名）：

```bash theme={null}
export TAURI_BUNDLE_MACOS_SIGNING_IDENTITY="Developer ID Application: Your Company (TEAMID)"
export TAURI_BUNDLE_MACOS_PROVIDER_SHORT_NAME="TEAMID"
# Tauri 工具也接受的可选备用密钥：
export APPLE_SIGNING_IDENTITY="Developer ID Application: Your Company (TEAMID)"
```

对于公证，请选择一种身份验证方式：

```bash theme={null}
# Apple ID + 应用专用密码
export APPLE_ID="you@example.com"
export APPLE_PASSWORD="app-specific-password"
export APPLE_TEAM_ID="TEAMID"

# 或 App Store Connect API 密钥
export APPLE_API_KEY="ABC123DEFG"
export APPLE_API_ISSUER="00000000-0000-0000-0000-000000000000"
export APPLE_API_KEY_PATH="$HOME/.keys/AuthKey_ABC123DEFG.p8"
```

然后运行标准或显式签名脚本别名之一：

```bash theme={null}
npm run desktop:package:macos:full
# 或
npm run desktop:package:macos:full:sign
```

### Windows Authenticode 签名

在打包之前设置（PowerShell）：

```powershell theme={null}
$env:TAURI_BUNDLE_WINDOWS_CERTIFICATE_THUMBPRINT="<CERT_THUMBPRINT>"
$env:TAURI_BUNDLE_WINDOWS_TIMESTAMP_URL="https://timestamp.digicert.com"
# 可选：如果使用证书文件 + 密码而非证书存储
$env:TAURI_BUNDLE_WINDOWS_CERTIFICATE="C:\path\to\codesign.pfx"
$env:TAURI_BUNDLE_WINDOWS_CERTIFICATE_PASSWORD="<PFX_PASSWORD>"
```

然后运行标准或显式签名脚本别名之一：

```powershell theme={null}
npm run desktop:package:windows:full
# 或
npm run desktop:package:windows:full:sign
```

## 区分变体的输出（名称/图标）

* Full 变体：`World Monitor` / `world-monitor`
* Tech 变体：`Tech Monitor` / `tech-monitor`

不同的名称在 Tauri 中配置：

* `src-tauri/tauri.conf.json` → `World Monitor` / `world-monitor`
* `src-tauri/tauri.tech.conf.json` → `Tech Monitor` / `tech-monitor`

如果需要变体特定的图标，请分别在每个配置中设置 `bundle.icon`，并将每个变体指向专用的图标资源。

## 输出位置

制品生成在以下位置：

```text theme={null}
src-tauri/target/release/bundle/
```

常见子文件夹：

* `app/` → macOS `.app`
* `dmg/` → macOS `.dmg`
* `nsis/` → Windows `.exe` 安装程序
* `msi/` → Windows `.msi` 安装程序

## 发布检查清单（干净机器）

1. 构建所需的 OS + 变体包。
2. 将制品移动到干净机器（或全新的 VM）。
3. 安装/启动：
   * macOS：挂载 `.dmg`，将应用拖到"应用程序"，然后启动。
   * Windows：运行 `.exe` 或 `.msi`，从"开始"菜单启动。
4. 验证启动：
   * 应用窗口无崩溃地打开。
   * 地图视图正常渲染。
   * 初始数据加载路径不会出现致命错误。
5. 验证变体标识：
   * 窗口标题和产品名称与预期变体匹配。
6. 如果启用了签名：
   * 在 OS 对话框/属性中验证代码签名元数据。
   * 在 macOS 上验证公证/Gatekeeper 接受情况。
