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

View File

@@ -46,10 +46,11 @@
4. 窗口间通信统一通过主进程转发(或使用 MessagePort 等 Electron 支持的机制),保持窗口独立性。
- 路由与导航:主窗口为 单页应用,使用 React Router v7+ 管理页面切换,支持嵌套路由。
- 路由与导航:主窗口为单页应用,使用 React Router v7+ 管理页面切换。**遵循 QT 多窗口模型映射原则**
- 叠加层(设置、公告、素材库等)→ Modal/Drawer + 事件总线驱动,主页面不卸载
- 页面跳转(真正的视图切换)→ React Router需跨页保持的状态放 Provider 或 localStorage
- 辅助窗口(设置、预览、导入导出等)为独立 BrowserWindow加载独立的 HTML 入口(可根据路由参数或 windowId 决定内部路由),不与主窗口共享
DOM。
- 辅助窗口(设置、预览、导入导出等)以 Modal/Drawer 叠加在主窗口之上,不与主窗口共享 DOM但保持在同一个 React 组件树中以确保状态一致性。
# 目录结构
@@ -175,6 +176,36 @@
- 脱敏shared/utils/sanitize.ts 在日志写入前自动处理 ID哈希、邮箱/手机/名称/Token 等字段。
# 安全与认证
## Token 加密存储
- `access_token``refresh_token` 通过 Electron `safeStorage` API 加密存储,不落明文:
- macOS → Keychain
- Windows → DPAPI
- Linux → libsecret
- 实现文件:
- `electron/main/safe-storage-ipc.ts` — 主进程加密/解密 IPC 处理(`BIDIRECTIONAL.SAFESTORAGE_ENCRYPT / DECRYPT`
- `src/utils/safe-storage.ts` — 渲染进程桥接层(`initSafeStore / getSafeStore / setSafeStore / clearSafeStore`
- `src/services/request.ts` — token 存取通过 `getSafeStore / setSafeStore`,无需感知加密细节
- `src/services/auth-token.ts` — refresh_token 同理通过 safeStorage 存取
## 双 Token 机制
- `access_token`(短效)+ `refresh_token`(长效),登录成功同时下发
- 请求拦截器自动附加 `Authorization: Bearer <access_token>`
- 401 响应 → 双重校验HTTP `status` + 业务 `data.code`)→ 仅 `code === 401` 时触发刷新
- 刷新期间并发请求排队(`failedQueue`),刷新完成后批量重试
- refresh 接口自身 401 直接拒绝防死循环login 接口 401 穿透透传后端 `message`
- 启动时 `refresh_token` 静默续期(自动登录),失败仅清除标记不影响用户名回填
- 登录/退出通过事件总线解耦(`LOGIN_SUCCESS` / `LOGOUT` / `AUTH_REQUIRED`
## 日志脱敏
- `shared/utils/sanitize.ts` 在日志写入前自动脱敏处理
- 覆盖字段:用户 IDSHA256 哈希)、邮箱(`***@domain`、手机号掩码、用户名称、Token截断
- 主进程 `electron/main/logger.ts` 和渲染进程 `src/utils/logger.ts` 均写入前调用 `sanitizeLogEntry()`
# 样式与主题
- 优先使用 Tailwind 工具类 完成布局与常规样式,自定义设计令牌应映射为 Tailwind 扩展(在 tailwind.config.ts 中配置
@@ -240,6 +271,17 @@
| `UpdateSetting` | `src/pages/settings/UpdateSetting.tsx` | 设置页更新区块(含"查看详情"弹窗) |
| `server.py` | `test-server/server.py` | 本地测试服务器,扫描 release/ 目录,语义版本排序 |
## 增量更新(差分下载)
- `package.json` 配置 `"differentialPackage": true`electron-builder 打包时自动生成 `.exe.blockmap` 文件
- 自定义 Provider 模式:`HeiXiuNsisUpdater extends NsisUpdater` / `HeiXiuMacUpdater extends MacUpdater` / `HeiXiuAppImageUpdater extends AppImageUpdater`
- 三平台 Updater 均覆盖 `getUpdateInfoAndProvider()` 注入 `HeiXiuProvider`(自定义 API 版本检查),差分下载由 electron-updater 父类原生处理
- blockmap 文件流程:
- `scripts/generate-update-info.mjs` — 扫描 blockmap 文件,写 `blockmap.url` + `blockmap.size``update-info.json`
- `scripts/upload-oss.mjs` — 安装包 + blockmap 文件一并上传 OSS支持 Node.js 直传和 ossutil 两种模式)
- `scripts/publish-release.mjs` — 通过 `--blockmap-url` 参数将 blockmap 信息发布到后端 API
- 效果:日常更新仅下载变更区块,预计节省 60%~90% 流量
## 环境变量加载机制(主进程)
加载顺序后者覆盖前者OS 环境变量始终优先):