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
This commit is contained in:
2026-06-03 19:25:15 +08:00
parent 767bb8b297
commit 3becdb85d4
34 changed files with 2253 additions and 1880 deletions

View File

@@ -22,11 +22,11 @@
└──────────────────┘ └──────────────────┘ └──────────────────┘
```
| 角色 | 技术 | 职责 |
| ------ | -------------------------- | ------------------------------------------ |
| 客户端 | Electron + `net.request()` | 调用 API → 下载安装包 → 校验 SHA512 → 安装 |
| ECS | 任意后端语言 | 提供版本检查 API |
| OSS | 阿里云对象存储 | 托管 .exe / .dmg / .AppImage |
| 角色 | 技术 | 职责 |
|-----|--------------------|---------------------------------|
| 客户端 | Electron + `axios` | 调用 API → 下载安装包 → 校验 SHA512 → 安装 |
| ECS | 任意后端语言 | 提供版本检查 API |
| OSS | 阿里云对象存储 | 托管 .exe / .dmg / .AppImage |
---
@@ -60,14 +60,14 @@ 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 |
| `--clean` | 清理旧产物 |
| `--sign` | 代码签名(配合 `--cert` 或环境变量) |
| `--upload` | 上传 OSS |
| `--publish` | POST 版本信息到后端 API |
| `--all` | 全流程 = clean + build + sign + upload + publish |
---
@@ -127,8 +127,8 @@ node build.mjs --win --personal --upload --publish
### 证书获取
| 平台 | 格式 | 渠道 | 年费 |
| ------- | ----------------- | ------------------------------- | -------- |
| 平台 | 格式 | 渠道 | 年费 |
|---------|-------------------|---------------------------------|----------|
| Windows | `.pfx` / `.p12` | DigiCert / Sectigo / GlobalSign | $200-700 |
| macOS | `.p12` / Keychain | Apple Developer Program | $99 |
@@ -158,41 +158,46 @@ CSC_LINK=/path/to/cert.pfx CSC_KEY_PASSWORD=xxx npm run build:win
```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"
}
"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 } }
{
"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"
"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"
}
```
@@ -203,24 +208,25 @@ CSC_LINK=/path/to/cert.pfx CSC_KEY_PASSWORD=xxx npm run build:win
## 六、数据库
```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,
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)
INDEX idx_platform_edition_status (platform, edition, status)
);
```
@@ -228,33 +234,33 @@ CREATE TABLE releases (
## 七、客户端行为
| 场景 | 行为 |
| -------- | ---------------------------------------------------- |
| 启动 | 5 秒后静默检查更新(仅生产环境) |
| 手动检查 | 点击按钮 → 调用 API → 反馈结果 |
| 下载 | 流式写入临时目录SHA512 实时校验,每 250ms 推送进度 |
| 安装 | 用户确认 → spawn NSIS /S → app.quit() |
| 强制更新 | `forceUpdate=true` 时不可跳过 |
| 开发模式 | 跳过所有更新检查 |
| 场景 | 行为 |
|------|-----------------------------------|
| 启动 | 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 基地址 |
| 变量 | 默认值 | 用途 |
|-------------------------|--------------------------------------------------------|----------------------|
| `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 |
| `OSS_BASE_PATH` | `releases` | OSS 内基路径 |
| `CSC_LINK` | — | 签名证书路径 |
| `CSC_KEY_PASSWORD` | — | 签名证书密码 |
| `UPDATE_FORCE` | `false` | 强制更新标记(打包时) |
| `UPDATE_CHANGELOG` | 读取 CHANGELOG.md | 覆盖更新日志CI/CD |
---