# 项目概览

- 本项目使用 Vite + React 19 + TypeScript + Electron 重构现有 Python Qt
  桌面应用，打造跨平台（Windows/macOS）的多窗口桌面程序。
- 核心界面为单页应用（SPA），同时支持通过 Electron 打开独立窗口以承载子功能。

# 核心需求

- 完整还原原有 Qt 应用的业务逻辑与视觉体验，并对交互进行现代化改造。

- 必须支持 多窗口（主窗口 + 可动态创建的辅助窗口），窗口间需通过事件/消息进行低耦合通信。

- 适配 Windows 与 macOS，处理好快捷键、托盘、菜单、窗口边框等平台差异。

- 采用 离线优先 架构，保障本地数据处理性能，合理使用本地存储（如 electron-store 或 SQLite）。

- 所有对系统底层能力的调用必须通过 Electron 主进程，严禁在渲染进程直接使用 Node.js API（除非通过 preload 安全暴露）。

# 技术架构

## 整体分层

- 主进程（Main Process）：Electron 主进程，管理窗口生命周期、系统菜单、托盘、IPC 事件调度、本地文件/数据库操作。

- 预加载脚本（Preload）：桥接渲染进程与主进程，使用 contextBridge 安全暴露有限 API。

- 渲染进程（Renderer）：基于 React 19 的 SPA（主窗口）与独立窗口的 React 入口，负责 UI 展示与用户交互。

- 共享层（Shared）：进程间共享的 TypeScript 类型、常量、工具函数、事件名称枚举。

## 前端架构原则

- 组件化：以函数组件 + Hooks 为唯一组件形式，UI 拆分为展示组件与容器组件。

- 单向数据流：全局状态使用 Context + Provider 模式（AppContext / ThemeContext / SettingsContext），
  遵循 Provider → Context → Comsumer 单向流动。组件内部状态使用 useState/useReducer，不污染全局 Context。

- 事件驱动（EDA）：
    1. 主进程与渲染进程通信基于 Electron IPC（ipcMain/ipcRenderer），定义明确的事件通道与载荷类型。

    2. 渲染进程内跨组件通信优先使用 Context；需要解耦的场景使用自定义事件总线（src/shared/utils/bus.ts），
       所有 emit 调用自动记录到日志文件用于审计追踪。

    3. 自定义错误体系（RequestError / RefreshError）通过事件总线解耦：请求拦截器抛出自定义错误 →
       全局捕获 → emit 事件 → UI 层响应。

    4. 窗口间通信统一通过主进程转发（或使用 MessagePort 等 Electron 支持的机制），保持窗口独立性。

- 路由与导航：主窗口为单页应用，不使用 React Router。所有页面切换通过事件总线 + PageDispatcher 实现：
    - 叠加层（设置、公告、素材库等）→ Modal/Drawer + 事件总线驱动，主页面不卸载
    - NavBar 导航项点击 → `emit(OPEN_PAGE, { target, modalType })` → PageDispatcher 按 `PAGE_MAP` 注册表渲染对应容器
    - 每个页面路径在 `PageDispatcher.PAGE_MAP` 中注册一行（target → { component, modalType, width, height }）
    - 需跨页保持的状态放 Provider 或 localStorage

- 辅助窗口（设置、预览、导入导出等）以 Modal/Drawer 叠加在主窗口之上，不与主窗口共享 DOM，但保持在同一个 React 组件树中以确保状态一致性。

# 目录结构

> 2026-06-29 重构：业务模块从 `pages/` + `services/modules/` 分散模式统一为 `modules/` 下的
> VCHSM 五层架构（Views → Controllers → Hooks → Settings → Model）。

```md
├── electron/                          # Electron 主进程 + 预加载
│ ├── main.ts                          # 入口编排：窗口创建 / IPC 注册 / 生命周期
│ ├── preload.ts                       # contextBridge：向渲染进程暴露安全 API
│ ├── electron-env.d.ts                # 类型声明（APP_ROOT、Window 扩展）
│ └── main/                            # 主进程核心模块
│ │ ├── load-env.ts                    # .env.{mode} + .env.local 加载器
│ │ ├── logger.ts                      # 日志核心：JSON Lines / 每日轮转 / 批量冲刷
│ │ ├── net-request.ts                 # Electron net.request 的 axios 风格封装
│ │ ├── updater.ts                     # 自动更新：自定义 Provider + 平台 Updater
│ │ ├── menu/index.ts                  # 系统菜单（macOS Edit / Win 无菜单）
│ │ ├── ipc/                           # IPC handler 集合
│ │ │ ├── log-ipc.ts                   # 渲染进程日志 → 主进程日志桥接
│ │ │ ├── safe-storage-ipc.ts          # safeStorage 加密/解密 IPC handler
│ │ │ ├── storage-ipc.ts               # 沙箱文件存储 IPC handler（heixiu-data/）
│ │ │ └── canvas-ipc.ts                # 画布文件操作 IPC handler
│ │ └── utils/                         # 平台判断 / 图标路径
│ └── preload/                         # 预加载脚本（contextBridge 桥接层）
│   ├── device.ts                      # 硬件指纹采集
│   └── device_service.ts              # 设备信息缓存层
│
├── src/                               # 渲染进程（React 19 + Vite + TypeScript）
│ │
│ ├── app/                             # ═══ 应用壳 ═══
│ │ ├── App.tsx                        # 根组件：叠加层编排（登录/设置/页面调度）
│ │ ├── main.tsx                       # React 挂载 + Provider 嵌套 + 全局错误捕获
│ │ ├── providers/                     # 全局 Context Provider
│ │ │ ├── AppProvider.tsx              # 认证状态（login/logout/Token 刷新）
│ │ │ ├── ThemeProvider.tsx            # 亮/暗主题切换 + antd ConfigProvider
│ │ │ └── SettingsProvider.tsx         # 本地持久化设置（存储路径等）
│ │ └── layout/                        # 布局框架
│ │   ├── Layout.tsx                   # 全高 flex 列布局壳（NavBar + 内容区）
│ │   └── PageDispatcher.tsx           # 通用页面调度器（Modal/Drawer/FloatingPanel）
│ │
│ ├── modules/                         # ═══ 业务模块（VCHSM 五层架构）═══
│ │ │                                  # V=views C=controllers H=hooks S=settings M=model
│ │ ├── navbar/          V+C+S+M       # 导航栏 UI 壳
│ │ │ ├── views/                       # NavBar.tsx / NavItem.tsx
│ │ │ ├── settings/                    # nav-config.ts（左右导航项注册表）
│ │ │ └── model/                       # 导航类型定义
│ │ ├── announcement/    V+C           # 公告（Badge 角标 + 15 分钟轮询缓存）
│ │ │ ├── views/                       # AnnouncementDrawer.tsx
│ │ │ └── controllers/                 # announcement-api.ts
│ │ ├── auth/            V+C+H+S+M     # 认证模块（14 文件）
│ │ │ ├── views/                       # AuthPage.tsx + components/（LoginForm/RegisterForm/改密/忘记密码）
│ │ │ ├── controllers/                 # auth-api.ts / token-manager.ts / auth-persistence.ts
│ │ │ ├── hooks/                       # use-auth-state.ts / use-sms-cooldown.ts
│ │ │ ├── settings/                    # login-fields.ts / register-fields.ts / validators.ts
│ │ │ └── model/                       # 类型定义
│ │ ├── home/            V+C+H+S+M     # 主工作区（三栏布局 → VCHSM 嵌套）
│ │ │ ├── views/
│ │ │ │ ├── HomePage.tsx / HomeContent.tsx
│ │ │ │ ├── left/                      # 左侧栏 — 输入控件（LeftPanel + controls/）
│ │ │ │ ├── center/                    # 中央栏 — 预览区（CenterPanel）
│ │ │ │ └── right/                     # 右侧栏 — 模型/任务/输出/Banner
│ │ │ ├── controllers/                 # task-api.ts / model-api.ts / banner-api.ts / menus/
│ │ │ ├── hooks/                       # useModelUI.ts
│ │ │ ├── stores/                      # HomeContext.tsx（页面级状态）
│ │ │ └── model/                       # 类型定义
│ │ ├── account/         V+C           # 账户与支付（6 子功能独立子目录）
│ │ │ ├── views/                       # info/ vip/ recharge/ billing/ orders/ wechat-work/
│ │ │ └── controllers/                 # vip-api.ts / payment-api.ts / billing-api.ts
│ │ ├── canvas/          V+C+H+M+S     # 无限画布 + 项目管理
│ │ │ ├── views/                       # CanvasApp.tsx / CanvasPage.tsx
│ │ │ │ ├── core/                      # CanvasViewport / LODImage / MediaCard / MediaPreview
│ │ │ │ ├── navigation/                # CanvasSidebar / ProjectSelector / EpisodeSelector / ShotList
│ │ │ │ └── toolbar/                   # CanvasToolbar / CanvasFilterBar / CategoryTabs / StageTabs
│ │ │ ├── controllers/                 # menus/（右键菜单注册）
│ │ │ ├── hooks/                       # useCanvasInteraction / useDirectoryScan / useSidecarSync
│ │ │ ├── stores/                      # useCanvasStore.ts（Zustand store）
│ │ │ └── utils/                       # scanner.ts / layout.ts / LocalFileDataSource.ts
│ │ └── settings/        V+C           # 应用设置
│ │   ├── views/                       # SettingsPage.tsx + sections/（6 个设置分区）
│ │   └── controllers/                 # settings-actions.ts
│ │
│ └── shared/                          # ═══ 跨模块共享 ═══
│   ├── components/                    # 通用 UI（FloatingPanel / FormField / LegalTextModal / ContextMenu）
│   ├── hooks/                         # 全局 Hooks（useAnnouncements / useApi / useAsync / useUpdater）
│   ├── services/                      # HTTP 客户端 http.ts + API 类型
│   ├── utils/                         # 工具函数（bus / env / enum-resolver / display / pricing / safe-storage）
│   ├── infrastructure/storage/        # 本地加密数据库（sql.js + safeStorage）
│   │ ├── core/                        # db-core.ts / db-encrypt.ts / schema.ts
│   │ ├── stores/                      # task-store / order-store / media-store / settings-store
│   │ └── services/                    # media-loader / sync-manager / data-sync / user-scope
│   └── theme/                         # 主题系统（tokens / antd-theme / CSS 过渡）
│
├── shared/                            # 主进程 & 渲染进程共享（根级 @shared 别名）
│ ├── constants/                       # app.ts / ipc-channels.ts / version.ts / keyboard.ts
│ ├── types/                           # index.ts（Platform/Theme/Edition）/ logging.ts
│ └── utils/                           # sanitize.ts（日志脱敏）+ index.ts（通用工具）
│
├── scripts/                           # 构建与发布脚本
├── vite.config.ts                     # Vite 构建配置
├── package.json                       # 含 electron-builder 打包配置
└── pnpm-workspace.yaml
```

### VCHSM 五层架构说明

| 层 | 目录 | 职责 | 示例 |
|----|------|------|------|
| **V** views | `views/` | 页面组件，纯 JSX 结构 | `NavBar.tsx`, `VipPage.tsx`, `CanvasViewport.tsx` |
| **C** controllers | `controllers/` | 交互逻辑 + API 请求 + 菜单注册 | `auth-api.ts`, `task-api.ts`, `menus/` |
| **H** hooks | `hooks/` | 组件间复用逻辑（状态/副作用/数据流） | `use-auth-state.ts`, `useCanvasInteraction.ts` |
| **S** settings | `settings/` | 配置常量、字段映射、验证规则、注册表 | `nav-config.ts`, `login-fields.ts` |
| **M** model | `model/` | 纯 TS 类型/接口/枚举（编译时） | `types.ts` |

模块按需建层：navbar 只用 V+S+M，auth 用 V+C+H+S+M，canvas 额外有 stores/ + utils/。

# 多窗口与平台判定

- 窗口管理由 `electron/main.ts` 统一负责：`createMainWindow()` 创建主窗口，`BrowserWindow` 通过 `contextIsolation: true` + `nodeIntegration: false` 运行沙箱化渲染进程。辅助窗口通过 `RENDERER_TO_MAIN.OPEN_SUB_WINDOW` IPC 通道按需创建。

- 平台判定双端各有一份：`electron/main/utils/platform.ts`（主进程，直接使用 `process.platform`）和 `src/shared/utils/env.ts`（渲染进程，优先 `process.platform`，降级 `navigator.userAgent`）。

- 打包配置 (`package.json` build 字段) 须针对平台设置不同的图标、签名策略、安装包格式。

# 代码风格

## TypeScript

- 所有语句必须以分号 ; 结尾，缺失分号将被视为错误。

- 启用 strict 模式，禁止隐式 any，优先使用 interface 定义对象类型，复杂类型可适度使用 type。

- 文件名使用小写短横线连接（kebab-case），如 use-window-state.ts；组件文件名与组件名保持一致（PascalCase），如
  ThemeAdapter.tsx。

- 导入顺序：第三方库 → 项目内共享模块 → 相对路径模块，中间用空行分隔。

## React

- 只允许函数组件与 Hooks，禁止使用类组件。

- 每个组件必须有明确的 Props 类型，使用 React.FC<Props> 或直接标注函数参数类型（推荐直接标注）。

- 事件处理函数命名以 handle 开头（如 handleClick），自定义 Hook 以 use 开头。

- 避免直接操作 DOM，除非封装在自定义 Hook 中（如焦点管理）。

- 使用 React.memo、useMemo、useCallback 优化性能，但不要过早优化。

## 状态管理

- 使用 React Context + Provider 模式管理全局状态，按领域拆分：AppContext（平台/登录）、ThemeContext（主题）、
  SettingsContext（设置项）。各 Context 定义与 Provider 合并在 `app/providers/` 目录下，避免引入 Redux 等重量级方案。

- Provider 在 main.tsx 中按层级嵌套挂载：
  AppProvider → ThemeProvider → SettingsProvider → AntdApp → App

- 各模块通过自定义 Hook 消费（useAppContext / useTheme / useSettings），Hook 内部做 null 检查并抛出明确错误信息。

- 页面级状态（如首页的 selectedModel / selectedTask / 分页）放在 HomeContext 中，由 HomeContent 提供，遵循与全局 Provider 相同的 Context + Provider + Hook 模式。

## 日志系统

- 双端日志：主进程直接写文件（electron/main/logger.ts），渲染进程通过 IPC send 上报（src/shared/utils/bus.ts）。
  两端暴露一致的 API：`logger.debug / info / warn / error(category, message, error?, context?)`。

- 文件存储：JSON Lines 格式（每行一个 JSON），路径 `{userData}/logs/app-YYYY-MM-DD.log`，
  每日轮转 + 7 天自动清理。

- 事件总线联动：event-bus.ts 暴露 `setEventLogListener` 钩子，logger 注册后所有 emit 自动记录 DEBUG 日志。

- 错误日志：request.ts 拦截器根据错误类型自动分级记录（AUTH_EXPIRED → debug，5xx → error，其余 → warn）。

- 401 判断策略：HTTP 401 拦截处双重校验——同时检查 HTTP 状态码和响应体中的业务码 `data.code`。
  仅 `status === 401 && data?.code === 401` 才走 token 刷新流程；其他业务码（如密码错误）穿透到正常错误处理，
  透传后端的 `data.message`。这确保登录接口返回的"账号或密码错误"不被 RefreshError("登录已过期") 覆盖。

- 脱敏：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/shared/utils/safe-storage.ts` — 渲染进程桥接层（`initSafeStore / getSafeStore / setSafeStore / clearSafeStore`）
    - `src/shared/services/http.ts` — token 存取通过 `getSafeStore / setSafeStore`，无需感知加密细节
    - `src/modules/auth/controllers/token-manager.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` 在日志写入前自动脱敏处理
- 覆盖字段：用户 ID（SHA256 哈希）、邮箱（`***@domain`）、手机号（掩码）、用户名称、Token（截断）
- 主进程 `electron/main/logger.ts` 和渲染进程 `src/shared/utils/bus.ts` 均写入前调用 `sanitizeLogEntry()`

# 样式与主题

- 优先使用 Tailwind 工具类完成布局与常规样式。自定义设计令牌在 `src/shared/theme/tokens.css` 的 `@theme` 块中定义（Tailwind v4 语法），自动生成 `bg-primary-500`、`text-secondary` 等工具类。

- Ant Design 组件样式通过 ConfigProvider 的 theme 属性覆盖，确保与 Tailwind 主题令牌同步。
  `ConfigProvider` 同时配置 `locale={zhCN}` 实现全局中文（分页器"条/页"等无需逐个组件设置）。
  在 src/shared/theme/ 中创建 antd-theme.ts，导出主题配置对象，引用 tokens.ts 中的设计变量。
  组件级 token（如 Pagination.itemActiveColor / itemActiveBg）在 sharedComponents 中统一管理，
  亮色/暗色主题共享，避免 CSS !important hack。

- 禁止在组件中硬编码颜色、字号等设计令牌，一律使用主题变量或 Tailwind 类名。

- 全局样式文件 globals.css 只引入 Tailwind 指令和必要的重置样式，不堆积组件样式。

# 事件与 IPC

- 所有 IPC 通道名称定义在 shared/constants/ipc-channels.ts 中，分为三类：
  MAIN_TO_RENDERER / RENDERER_TO_MAIN / BIDIRECTIONAL。

- 渲染进程通过 src/shared/utils/bus.ts 中的安全守卫访问 IPC（hasIpc 检查 → safeIpcOn / send / invoke），
  非 Electron 环境下静默跳过，保证浏览器预览不崩溃。

- 主进程事件处理函数需做好错误捕获与日志记录，渲染进程调用 IPC 时使用 try-catch 并处理超时。

- 窗口间通信走主进程转发：发送窗口 safeIpcSend，主进程接收后定位目标窗口并 webContents.send。

# 开发与构建命令

- 开发模式：npm run dev 或 yarn dev（同时启动 Vite 与 Electron，支持热重载）。

- 构建：npm run build 编译渲染进程 → 打包 Electron 应用。

- 代码检查：npm run lint（ESLint + Prettier，规则已配置为强制分号、单引号等）。

- 类型检查：npm run typecheck（tsc --noEmit）。

# 自动更新系统

## 架构

```
客户端 (Electron 主进程)
  checkForUpdates()
    ├─ ① HeiXiuProvider.getLatestVersion()  → 调用自有版本检查 API
    │    └─ hasUpdate=false → 直接 IPC 通知 UI（不经过 electron-updater）
    └─ ② hasUpdate=true → electron-updater.checkForUpdates()
         ├─ HeiXiuProvider.getLatestVersion() → TTL 缓存命中，不重复请求
         ├─ emit 'update-available'（含 releaseNotes）→ UI 展示版本信息
         └─ 用户点击"下载更新" → downloadUpdate()
              ├─ 差分下载（对比 .blockmap，仅下载变更区块）
              ├─ SHA512 校验
              └─ 下载完成 → 用户点击"安装更新" → NSIS/DMG/AppImage 执行
```

| 模块                | 位置                                            | 职责                                       |
|-------------------|-----------------------------------------------|------------------------------------------|
| `HeiXiuProvider`  | `electron/main/updater.ts`                    | 自定义 Provider，调用自有 API，无更新返回 APP_VERSION  |
| `checkForUpdates` | `electron/main/updater.ts`                    | 预检版本 → 无更新直发 IPC / 有更新交 electron-updater |
| `downloadUpdate`  | `electron/main/updater.ts`                    | 用户确认后触发下载（从 checkForUpdates 分离）          |
| `netRequest`      | `electron/main/net-request.ts`                | Electron net.request 的 axios 风格封装        |
| `useUpdater`      | `src/shared/hooks/use-updater.ts`                    | 渲染进程更新状态 Hook（单例 IPC 监听）                 |
| `UpdateSetting`   | `src/modules/settings/views/sections/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 环境变量始终优先）：

```
① OS 环境变量（set KEY=VALUE && .\app.exe）  ← 最高优先级
② .env.local（不进 git，个人覆盖用）
③ .env.{mode}（dev→.env.development，build→.env.production）
④ updater.ts 硬编码默认值（https://www.heixiu.com）
```

| 文件                 | 何时生效                | 进 git | 用途                 |
|--------------------|---------------------|:-----:|--------------------|
| `.env.development` | `npm run dev`       |   ✅   | 本地开发（API → 测试服务器）  |
| `.env.production`  | `npm run build:xxx` |   ❌   | 构建时参考（API → 生产服务器） |
| `.env.local`       | 始终（后加载）             |   ❌   | 个人特殊配置（打包后连本地测试）   |

> `.env.production` 和 `.env.local` 不打包进 ASAR。打包后无这些文件时自动使用代码默认值。

## 测试工作流

```powershell
# 1. 构建两个版本
npm run build:win                         # → release/0.0.3/
# 改 package.json version = "0.0.4"
npm run build:win                         # → release/0.0.4/

# 2. 启动测试服务器
cd test-server && python server.py --release-dir ../release --port 8000

# 3. 启动旧版本客户端
set UPDATE_API_URL=http://127.0.0.1:8000 && .\release\0.0.3\win-unpacked\船长·HeiXiu.exe
# → 5 秒后自动检测到 0.0.4 → 差分下载 → 提示安装
```

相关文档：[UpdateA.md](UpdateA.md)、[test-server/README.md](test-server/README.md)

# 与其他 AI 协作的补充说明

- 所有生成的代码片段必须放在完整的文件上下文中，并注明所属文件路径。

- 若涉及跨平台逻辑，必须同时给出 Windows 与 macOS 的兼容实现或判断分支。

- 新增窗口时，需同步说明窗口入口、预加载脚本、主进程创建逻辑及 IPC 通道注册。

- 修改主题令牌时，需同步更新 tokens.ts、tokens.css 及 antd-theme.ts，确保三处一致。
