Files
ele-HeiXiu/UpdateA.md
YoungestSongMo 3becdb85d4 feat: 实现设置页面 + 路由系统 + JWT认证体系 + 公告优化 + 错误类型系统
## 新增功能

### 设置页面(Router + Modal 叠加)
- HashRouter 路由系统,Electron file:// 协议兼容
- 设置页以居中 Modal 叠加首页,仅 X 按钮关闭
- 主题切换 Segmented 控件(与首页 Switch 共享 Context)
- 大模型产物存储仓库路径配置(原生文件夹选择对话框)
- 企业版额外:团队创作存储仓库路径
- 系统信息展示(平台/版本/版本类型/环境)
- 版本更新检查(状态机:idle→checking→no-update/available→downloading→downloaded→error)

### JWT 认证体系
- 双 Token 机制:access_token + refresh_token
- Axios 拦截器 401 自动刷新 + 并发请求去重队列
- 启动时 refresh_token 静默续期(自动登录)
- 记住密码:Base64 编码存储,表单自动回填
- setTokenRefreshHandler 解耦模式:request.ts 不知晓 auth

### 自定义错误类型系统
- RefreshError 继承 RequestError,type = AUTH_EXPIRED
- 全局拦截器捕获 RefreshError → 自动 clearToken + AUTH_REQUIRED
- 任何位置 throw new RefreshError() 即可触发登录 Modal

### 公告卡片优化
- 长文本 Tooltip 悬浮预览
- 点击卡片弹出详情 Modal(全文保留换行)

### SettingsContext(类似 Vue Pinia)
- 集中式设置状态管理
- localStorage 持久化:ele-heixiu-output-path / ele-heixiu-team-repo-path
- useSettings() 全局消费

## 架构变更
- App.tsx → HashRouter + AppRoutes + LoginPage 弹层
- Layout.tsx = NavBar + <Outlet /> 页面壳
- HomePage.tsx 从 App.tsx 提取
- NavBar 使用 useNavigate() 真实路由导航
- useUpdater 改为模块级单例 IPC 监听器(修复 MaxListenersExceededWarning)
- electron/main.ts 新增 FILE_DIALOG IPC handler

## 依赖
- 新增 react-router-dom
2026-06-03 19:25:15 +08:00

291 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HeiXiu 构建 & 发布手册
> 面向前端发版 + 后端 API 对接
---
## 一、整体架构
```
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 客户端 (Electron)│ │ ECS (API 服务) │ │ OSS (阿里云) │
│ │ GET │ │ │ │
│ 版本检查 ─────────┼────────▶│ /api/v1/update/ │ │ │
│ │ │ check │ │ │
│ │◀────────│ 返回 JSON │ │ │
│ │ │ │ │ │
│ 下载安装包 ───────┼─────────┼──────────────────┼────────▶│ 静态文件托管 │
│ │◀────────┼──────────────────┼─────────│ .exe / .dmg │
│ │ │ │ │ │
│ 安装 (spawn) │ │ │ │ │
│ → app.quit() │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
```
| 角色 | 技术 | 职责 |
|-----|--------------------|---------------------------------|
| 客户端 | Electron + `axios` | 调用 API → 下载安装包 → 校验 SHA512 → 安装 |
| ECS | 任意后端语言 | 提供版本检查 API |
| OSS | 阿里云对象存储 | 托管 .exe / .dmg / .AppImage |
---
## 二、项目脚本速查
### 总入口:`build.mjs`
```bash
node build.mjs --help # 查看完整帮助
npm run build:win # 打包 Windows 个人版(快捷命令)
```
### npm 命令速查
```bash
# 构建(仅打包,不上传/发布)
npm run build:win # Windows 个人版
npm run build:win:enterprise # Windows 企业版
npm run build:mac # macOS 个人版
npm run build:linux # Linux 个人版
# 工具
npm run build:clean # 清理 release/ + dist/ + dist-electron/
node build.mjs --win --personal --help # 查看完整 CLI 指南
# 独立脚本(需传参数)
node scripts/generate-update-info.mjs <平台> <版本类型> [版本号] [--url <url>]
node scripts/upload-oss.mjs <平台> <版本类型> [版本号]
node scripts/publish-release.mjs <平台> <版本类型> [版本号] [--url <url>]
```
### `build.mjs` 操作组合
| 操作 | 说明 |
|-------------|------------------------------------------------------|
| `--build` | 构建tsc + vite + electron-builder + update-info.json |
| `--clean` | 清理旧产物 |
| `--sign` | 代码签名(配合 `--cert` 或环境变量) |
| `--upload` | 上传 OSS |
| `--publish` | POST 版本信息到后端 API |
| `--all` | 全流程 = clean + build + sign + upload + publish |
---
## 三、发版工作流
### 路径 A快速打包日常开发 / 内部测试)
```bash
# 1. 修改版本号
# package.json → "version": "0.1.0"
# 2. 写更新日志
# CHANGELOG.md → 顶部新增 ## 0.1.02026-xx-xx...
# 3. 打包
npm run build:win && npm run build:win:enterprise
# 4. 产物在 release/0.1.0/ 下:
# - xxx-Setup.exe安装包
# - xxx-update-info.json所有 API 字段downloadUrl 为预判 URL
# 5. 手动上传 exe 到 OSS releases/0.1.0/
# 6. 将 update-info.json 内容录入数据库 releases 表
```
### 路径 B先上传再确定 URL
```bash
# 打包
npm run build:win
# 上传到 OSS自动打印实际 URL
node scripts/upload-oss.mjs win32 personal 0.1.0
# 用实际 URL 重新生成 update-info.json
node scripts/generate-update-info.mjs win32 personal 0.1.0 \
--url "https://heixiu.oss-cn-hangzhou.aliyuncs.com/releases/0.1.0/xxx.exe"
# 将 update-info.json 录入数据库
```
### 路径 C全自动上传 + 发布一条龙)
```bash
# 一步到位(需先配置环境变量)
OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com \
OSS_BUCKET=heixiu \
OSS_ACCESS_KEY_ID=xxx \
OSS_ACCESS_KEY_SECRET=xxx \
UPDATE_API_KEY=xxx \
node build.mjs --win --personal --upload --publish
```
---
## 四、代码签名
### 证书获取
| 平台 | 格式 | 渠道 | 年费 |
|---------|-------------------|---------------------------------|----------|
| Windows | `.pfx` / `.p12` | DigiCert / Sectigo / GlobalSign | $200-700 |
| macOS | `.p12` / Keychain | Apple Developer Program | $99 |
> EV 证书立即消除 SmartScreen 警告OV 证书需积累下载量。
### 签名方式
```bash
# 方式 1build.mjs 参数
node build.mjs --win --personal --sign --cert ./cert.pfx --cert-password xxx
# 方式 2环境变量CI/CD 友好)
CSC_LINK=/path/to/cert.pfx CSC_KEY_PASSWORD=xxx npm run build:win
```
> SHA512 校验值会在签名后自动计算(签名改变文件字节,必须先签后校)。
---
## 五、API 接口
### `GET /api/v1/update/check`
**参数**`platform`win32/darwin/linux`version`(三段式 semver`edition`personal/enterprise
**有更新**
```json
{
"code": 0,
"data": {
"hasUpdate": true,
"latestVersion": "0.1.0",
"downloadUrl": "https://heixiu.oss-cn-hangzhou.aliyuncs.com/releases/0.1.0/xxx.exe",
"fileSize": 98765432,
"sha512": "Base64...",
"changelog": "更新日志...",
"releaseDate": "2026-06-03",
"forceUpdate": false,
"minimumVersion": "0.0.0"
}
}
```
**无更新**
```json
{
"code": 0,
"data": {
"hasUpdate": false
}
}
```
### `POST /api/v1/releases`(发布用)
```json
{
"platform": "win32",
"edition": "personal",
"latestVersion": "0.1.0",
"downloadUrl": "https://...",
"fileSize": 112910987,
"sha512": "Base64...",
"changelog": "...",
"releaseDate": "2026-06-03",
"forceUpdate": false,
"minimumVersion": "0.0.0"
}
```
> Header: `Authorization: Bearer <UPDATE_API_KEY>`
---
## 六、数据库
```sql
CREATE TABLE releases
(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
platform VARCHAR(10) NOT NULL COMMENT 'win32 / darwin / linux',
edition VARCHAR(10) NOT NULL COMMENT 'personal / enterprise',
version VARCHAR(20) NOT NULL COMMENT '三段式 semver',
file_url VARCHAR(500) NOT NULL COMMENT 'OSS HTTPS 地址',
file_size BIGINT NOT NULL COMMENT '字节数',
sha512 VARCHAR(128) NOT NULL COMMENT 'Base64 编码',
changelog TEXT,
force_update TINYINT(1) DEFAULT 0,
min_version VARCHAR(20) DEFAULT '',
release_date DATE NOT NULL,
status VARCHAR(10) DEFAULT 'draft' COMMENT 'draft / published / deprecated',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_platform_edition_version (platform, edition, version),
INDEX idx_platform_edition_status (platform, edition, status)
);
```
---
## 七、客户端行为
| 场景 | 行为 |
|------|-----------------------------------|
| 启动 | 5 秒后静默检查更新(仅生产环境) |
| 手动检查 | 点击按钮 → 调用 API → 反馈结果 |
| 下载 | 流式写入临时目录SHA512 实时校验,每 250ms 推送进度 |
| 安装 | 用户确认 → spawn NSIS /S → app.quit() |
| 强制更新 | `forceUpdate=true` 时不可跳过 |
| 开发模式 | 跳过所有更新检查 |
---
## 八、环境变量速查
| 变量 | 默认值 | 用途 |
|-------------------------|--------------------------------------------------------|----------------------|
| `UPDATE_API_URL` | `https://www.heixiu.com` | 版本检查 API 基地址 |
| `UPDATE_API_KEY` | — | 发布 API 鉴权 Key |
| `UPDATE_DOWNLOAD_BASE` | `https://heixiu.oss-cn-hangzhou.aliyuncs.com/releases` | 预判 URL 基地址 |
| `OSS_ENDPOINT` | — | 阿里云 OSS endpoint |
| `OSS_BUCKET` | — | 阿里云 OSS bucket |
| `OSS_ACCESS_KEY_ID` | — | 阿里云 AccessKey ID |
| `OSS_ACCESS_KEY_SECRET` | — | 阿里云 AccessKey Secret |
| `OSS_BASE_PATH` | `releases` | OSS 内基路径 |
| `CSC_LINK` | — | 签名证书路径 |
| `CSC_KEY_PASSWORD` | — | 签名证书密码 |
| `UPDATE_FORCE` | `false` | 强制更新标记(打包时) |
| `UPDATE_CHANGELOG` | 读取 CHANGELOG.md | 覆盖更新日志CI/CD |
---
## 九、文件结构
```
ele-heixiu/
├ build.mjs ← 构建总管npm run build 入口)
├ CHANGELOG.md ← 更新日志(打包时自动提取)
├ UpdateA.md ← 本文档
├ package.json ← 仅保留简短的 npm 快捷命令
├ scripts/
│ ├ clean.mjs ← 清理产物
│ ├ generate-update-info.mjs ← 生成 API 信息 JSON
│ ├ upload-oss.mjs ← 上传 OSS
│ └ publish-release.mjs ← 发布到 APIaxios
├ release/ ← 构建产物目录(按版本分)
│ └ 0.1.0/
│ ├ xxx-Setup.exe
│ └ xxx-update-info.json
├ dist/ ← Vite 前端产物(构建输入)
└ dist-electron/ ← Electron 主进程产物(构建输入)
```
---
_如有接口或流程变更,请同步更新此文档。_