feat: 日志模块 + netRequest 封装 + PROJECT.md 更新

日志模块(文件持久化 + 事件总线联动 + 脱敏)
    新增:
      - shared/types/logging.ts         — LogLevel / LogCategory / LogEntry 类型
      - electron/main/logger.ts         — 主进程日志核心(JSON Lines / 每日轮转 / 7天清理)
      - electron/main/log-ipc.ts        — 渲染进程日志 IPC 通道接收
      - src/utils/logger.ts             — 渲染进程日志器(IPC 转发 / DEV 控制台 / 事件总线钩子)
      - shared/utils/sanitize.ts        — 脱敏工具(ID哈希 / 邮箱 / 手机 / 名称 / Token)
    修改:
      - electron/main.ts                — initLogger + flushLogger + uncaughtException
      - src/main.tsx                    — renderer 全局错误捕获
      - src/utils/event-bus.ts          — setEventLogListener 钩子,emit 自动审计
      - src/services/request.ts         — 拦截器结构化错误分级记录
      - electron/main/updater.ts        — 14处 console → logger 迁移
      - src/components/AppProvider.tsx   — 登录/登出/自动登录 auth 事件日志
      - shared/constants/ipc-channels.ts — 新增 LOG_MESSAGE 通道

  netRequest 封装(Electron net.request 的 axios 风格 API)
    新增:
      - electron/main/net-request.ts     — netRequest.get/post/put/del 命名空间
    修改:
      - electron/main/updater.ts         — fetchUpdateInfo 改用 netRequest(22→12行)

  文档更新
    - PROJECT.md                       — 目录结构 / 状态管理 / 日志系统 / IPC 章节同步现状
    - TODO.md                          — 增量更新改造 + 日志模块待办
    - UpdateA.md                       — API blockmap 字段 / 数据库字段说明
This commit is contained in:
2026-06-04 11:03:25 +08:00
parent 337234443a
commit ae733016bb
21 changed files with 1245 additions and 154 deletions

76
TODO.md
View File

@@ -10,13 +10,14 @@
当前所有敏感数据存储在 `localStorage` 明文/Base64
| 数据 | 现状 | 目标方案 |
|------|------|---------|
| `access_token` | 明文 | Electron `safeStorage.encryptString()` |
| `refresh_token` | 明文 | Electron `safeStorage.encryptString()` |
| `passwordBase64` | Base64 编码 | 移除密码存储,仅靠 refresh_token 自动登录 |
| 数据 | 现状 | 目标方案 |
|------------------|-----------|----------------------------------------|
| `access_token` | 明文 | Electron `safeStorage.encryptString()` |
| `refresh_token` | 明文 | Electron `safeStorage.encryptString()` |
| `passwordBase64` | Base64 编码 | 移除密码存储,仅靠 refresh_token 自动登录 |
**方案 A推荐**:使用 Electron `safeStorage` API
- macOS → Keychain
- Windows → DPAPI
- Linux → libsecret
@@ -24,8 +25,8 @@
```ts
// preload.ts 暴露安全方法
contextBridge.exposeInMainWorld('safeStorage', {
encrypt: (plain: string) => ipcRenderer.invoke('safe-storage:encrypt', plain),
decrypt: (encrypted: Buffer) => ipcRenderer.invoke('safe-storage:decrypt', encrypted),
encrypt: (plain: string) => ipcRenderer.invoke('safe-storage:encrypt', plain),
decrypt: (encrypted: Buffer) => ipcRenderer.invoke('safe-storage:decrypt', encrypted),
});
// 替代现有 setToken / setStoredRefreshToken
@@ -33,6 +34,7 @@ contextBridge.exposeInMainWorld('safeStorage', {
```
**方案 B**:敏感操作下沉到主进程
- `access_token` / `refresh_token` 由主进程管理
- 渲染进程通过 IPC 发起请求时由主进程追加 Token
- 渲染进程永不持有明文 Token
@@ -85,6 +87,54 @@ contextBridge.exposeInMainWorld('safeStorage', {
- [ ] 单元测试覆盖Vitest
- [ ] Bundle 体积分析优化rollup-plugin-visualizer 已有,定期检查)
### 增量更新改造
当前状态:
- `electron-builder` 已配置 `"differential": true`,打包时已生成 `.exe.blockmap` 文件 ✅
- `electron/main/updater.ts` 为**手写全量下载**`net.request`),未使用 `electron-updater` npm 包 ❌
- blockmap 文件生成了但从未被消费,每次更新都是完整下载
目标方案 — 自定义 Provider + electron-updater
```ts
// electron/main/updater-v2.ts
import { autoUpdater } from 'electron-updater';
import { Provider } from 'electron-updater/out/providers/Provider';
class HeiXiuProvider extends Provider<UpdateInfo> {
// 版本检查 → 走自定义 API保留灰度/强更控制)
async getLatestVersion(): Promise<UpdateInfo> {
const res = await fetch(`${API_BASE}/api/v1/update/check?...`);
const data = await res.json();
return {
version: data.latestVersion,
files: [{
url: data.downloadUrl,
sha512: data.sha512,
size: data.fileSize,
blockMapSize: data.blockMapSize, // 后端新增字段
}],
path: data.downloadUrl,
sha512: data.sha512,
releaseDate: data.releaseDate,
};
}
}
```
改造内容:
- [ ] 安装 `electron-updater` npm 包
- [ ] 重写 `electron/main/updater.ts` 为自定义 Provider 模式
- [ ] 发布脚本 `upload-oss.mjs` 增加 blockmap 文件上传
- [ ] `generate-update-info.mjs` 增加 blockmap 字段(`blockMapUrl``blockMapSize`
- [ ] 后端 API `/api/v1/update/check` 响应增加 `blockMapUrl``blockMapSize` 字段
- [ ] 后端 `releases` 表增加 `blockmap_url``blockmap_size`
- [ ] OSS 上传每次版本需同时上传 `.exe` + `.exe.blockmap` 两个文件
增量效果预估:日常更新下载量从完整安装包 → 仅变化的块(预计节省 60%~90% 流量)。
### 代码质量
- [ ] 移除未使用的 `shared/` 类型和常量
@@ -102,12 +152,12 @@ contextBridge.exposeInMainWorld('safeStorage', {
## ⚠️ 已知技术债务
| 问题 | 说明 | 影响 |
|------|------|------|
| localStorage 依赖 | 所有持久化数据依赖 localStorage | 清理浏览器数据会丢失所有配置 |
| IPC 监听器 | useUpdater 已改为单例,其他 IPC hook 可能也有类似问题 | 长期运行可能内存泄漏 |
| `test.py` | 仓库根目录残留测试文件 | 无实际作用,应清理 |
| `null` 文件 | 仓库根目录名为 null 的文件 | 构建产物或误操作残留 |
| 问题 | 说明 | 影响 |
|-----------------|---------------------------------------|----------------|
| localStorage 依赖 | 所有持久化数据依赖 localStorage | 清理浏览器数据会丢失所有配置 |
| IPC 监听器 | useUpdater 已改为单例,其他 IPC hook 可能也有类似问题 | 长期运行可能内存泄漏 |
| `test.py` | 仓库根目录残留测试文件 | 无实际作用,应清理 |
| `null` 文件 | 仓库根目录名为 null 的文件 | 构建产物或误操作残留 |
---