fix: 修复主题切换后首页状态重置 + 首页 UX 优化 + 文档同步

## 根因
  设置页 `navigate('/settings')` 导致 React Router `/*` 的 index
  路由不匹配,HomePage 被卸载重挂载,所有 useState 回到默认值。

  ## 修复(6 文件)
  - event-bus.ts: 新增 OPEN_SETTINGS 事件
  - nav-config.ts: 设置按钮 action: 'navigate' → 'button',去路由化
  - NavBar.tsx: button case 中 emit(OPEN_SETTINGS)
  - SettingsPage.tsx: 去路由化,改为 Modal 居中叠加 + open/onClose props,
    使用 antd 6.x 正确 API destroyOnHidden(非废弃的 destroyOnClose),
    mask={{ closable: false }} + keyboard={false} 仅允许 X 按钮关闭
  - router/index.tsx: 移除 SettingsPage 渲染
  - App.tsx: 添加 SettingsPage Modal,事件驱动(与 LoginPage 模式一致)

  ## UX 优化(2 文件)
  - HomeContent.tsx: 右侧分隔条移除多余 marginLeft,左右视觉对称
  - BannerCarousel.tsx: 新增关闭按钮,session 级别 useState 隐藏,
    不做 localStorage 持久化,确保每次启动重新展示

  ## 架构原则
  确立 QT 多窗口模型 → Web 映射:叠加层走 Modal/Drawer + 事件总线,
  主页面不卸载;真正的视图切换才用 React Router。

  ## 文档同步
  - TODO.md: 移除已完成项详细记录,精简为未完成待办
  - WORKLOG.md: 追加 2026-06-07 完整工作日志
  - PROJECT.md: 更新路由/叠加层架构说明
  - CHANGELOG.md: 追加 v0.0.13 条目
  - ARCHITECTURE.md: 更新日期 + 新增叠加层模式章节
This commit is contained in:
2026-06-05 21:03:14 +08:00
parent a8ace232a4
commit 72ec1a5459
15 changed files with 192 additions and 164 deletions

113
TODO.md
View File

@@ -1,49 +1,6 @@
# TODO — 船长·HeiXiu 待办与优化清单
> 最后更新2026-06-03
---
## 🔴 安全加固(优先级高)
### 1. 敏感数据加密存储
当前所有敏感数据存储在 `localStorage` 明文/Base64
| 数据 | 现状 | 目标方案 |
|------------------|-----------|----------------------------------------|
| `access_token` | 明文 | Electron `safeStorage.encryptString()` |
| `refresh_token` | 明文 | Electron `safeStorage.encryptString()` |
| `passwordBase64` | Base64 编码 | 移除密码存储,仅靠 refresh_token 自动登录 |
**方案 A推荐**:使用 Electron `safeStorage` API
- macOS → Keychain
- Windows → DPAPI
- Linux → libsecret
```ts
// preload.ts 暴露安全方法
contextBridge.exposeInMainWorld('safeStorage', {
encrypt: (plain: string) => ipcRenderer.invoke('safe-storage:encrypt', plain),
decrypt: (encrypted: Buffer) => ipcRenderer.invoke('safe-storage:decrypt', encrypted),
});
// 替代现有 setToken / setStoredRefreshToken
// 渲染进程不再直接操作 localStorage
```
**方案 B**:敏感操作下沉到主进程
- `access_token` / `refresh_token` 由主进程管理
- 渲染进程通过 IPC 发起请求时由主进程追加 Token
- 渲染进程永不持有明文 Token
### 2. 密码存储策略调整
- [ ] "记住密码" → 仅回填用户名,不再存储密码(已完成)
- [ ] 清理 `StoredAuth.passwordBase64` 字段
- [ ] "自动登录" 完全依赖 `refresh_token` 静默续期
> 最后更新2026-06-07
---
@@ -87,54 +44,6 @@ 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/` 类型和常量
@@ -152,17 +61,19 @@ class HeiXiuProvider extends Provider<UpdateInfo> {
## ⚠️ 已知技术债务
| 问题 | 说明 | 影响 |
|-----------------|---------------------------------------|----------------|
| localStorage 依赖 | 所有持久化数据依赖 localStorage | 清理浏览器数据会丢失所有配置 |
| IPC 监听器 | useUpdater 已改为单例,其他 IPC hook 可能也有类似问题 | 长期运行可能内存泄漏 |
| `test.py` | 仓库根目录残留测试文件 | 无实际作用,应清理 |
| `null` 文件 | 仓库根目录名为 null 的文件 | 构建产物或误操作残留 |
| 问题 | 说明 | 影响 |
|-----------------|---------------------------------------|------------------|
| localStorage 依赖 | 所有持久化数据依赖 localStorage | 清理浏览器数据会丢失所有配置 |
| IPC 监听器 | useUpdater 已改为单例,其他 IPC hook 可能也有类似问题 | 长期运行可能内存泄漏 |
| ~~主题切换状态重置~~ | ✅ 已修复 — 根因:设置页 `navigate('/settings')` 导致路由 `/*` 仅匹配 indexHomePage 被卸载重挂载。修复SettingsPage 改为事件总线驱动的 Modal 居中叠加,不走路由 | ~~用户体验差~~ |
| `test.py` | 仓库根目录残留测试文件 | 无实际作用,应清理 |
| `null` 文件 | 仓库根目录名为 null 的文件 | 构建产物或误操作残留 |
---
## 📋 下次开发计划
1. **safeStorage 加密改造**(安全加固 #1
2. **合规素材库页面**(功能待完善 Route 页面
3. **各页面 nav 导航补齐**
1. **合规素材库页面**(功能待完善 — 按 QT 原版设计,以 Modal/Drawer 叠加而非路由跳转实现
2. **各页面 nav 导航补齐**(后续页面优先使用叠加模式,遵循 QT 多窗口模型 → 见 WORKLOG 2026-06-07
3. **leftWidth / rightWidth / taskPage 加 localStorage 持久化**UX 优化:刷新页面后保持用户偏好)
4. **轮播图关闭按钮状态优化**(当前为 session 级别 useState可考虑加 localStorage 记录关闭时间戳,超过 N 天再显示)