Files
ele-HeiXiu/PROJECT.md
YoungestSongMo 136a17c0bf feat: 任务列表右键菜单回调 + 主进程下载 + sharp 缩略图 + IPC 精简重构
- 任务右键菜单:实现打开输出目录(inputs/outputs/.cache 结构)、
    复制资源链接、重新编辑、再次生成、拉取结果、重新下载、收藏、删除记录
  - 主进程下载:通过 Electron net 模块绕过 CORS,支持 CDN 媒体文件下载
  - sharp 缩略图:替换 nativeImage,支持 4K/8K+ 大尺寸素材的流式处理
  - IPC 精简:40+ 冗余通道 → 15 个分组通道,移除未使用的 preload 桥接方法
  - 任务存储:新增收藏字段、schema 迁移、task-store 持久化
  - 清理废弃模块:canvas-ipc / updater / request / pricing

refactor: IPC/Preload/Services 模块化拆分 — 单一职责 + 向后兼容

  主要变更:
  - shared/constants/ipc-channels.ts → ipc/ 模块 (base/storage/canvas/updater)
  - electron/preload.ts → preload/ 模块 (base/safe-storage/file-storage/canvas)
  - electron/main/ipc/canvas-ipc.ts → canvas/ 模块 (types/walk/sidecar/mime/thumbnail)
  - electron/main/ipc/storage-ipc.ts → 提取 utils/ (path/download/thumbnail)
  - electron/main/updater.ts → updater/ 模块 (provider/platform-updaters)
  - src/services/request.ts → request/ 模块 (token/interceptors/methods)
  - src/shared/utils/pricing.ts → pricing/ 模块 (types/helpers/format/calculate/fields)
  - src/modules/home/center/views/ModelInputForm.tsx → 提取 utils + DependentFormItem

  架构优化:
  - 所有拆分均保持向后兼容(旧导入路径仍可用)
  - TypeScript 编译通过 ✓
  - 每个模块单一职责,平均 ~130 行
2026-07-03 11:13:36 +08:00

28 KiB
Raw Permalink Blame History

项目概览

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

核心需求

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

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

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

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

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

技术架构

整体分层

  • 主进程Main ProcessElectron 主进程管理窗口生命周期、系统菜单、托盘、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 IPCipcMain/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

├── 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/                       # 自动更新模块
│ │ │ ├── provider.ts                  # 自定义 Provider + 设备指纹 + 构建配置
│ │ │ ├── platform-updaters.ts         # 平台特定 UpdaterWindows/macOS/Linux
│ │ │ └── index.ts                     # 初始化 + IPC 注册
│ │ ├── menu/index.ts                  # 系统菜单macOS Edit / Win 无菜单)
│ │ ├── ipc/                           # IPC handler 集合
│ │ │ ├── log-ipc.ts                   # 渲染进程日志 → 主进程日志桥接
│ │ │ ├── safe-storage-ipc.ts          # safeStorage 加密/解密 IPC handler
│ │ │ ├── storage-ipc.ts               # 沙箱文件存储 IPC handlerheixiu-data/
│ │ │ ├── utils/                       # 存储通用工具
│ │ │ │ ├── path.ts                    # 路径安全解析resolveSafe / ensureDir
│ │ │ │ ├── download.ts                # Electron net 文件下载(绕过 CORS
│ │ │ │ └── thumbnail.ts               # sharp 缩略图生成(内存优化)
│ │ │ └── canvas/                      # 画布文件操作模块
│ │ │   ├── types.ts                   # 类型定义StageType / ScanEntry / ThumbnailResult
│ │ │   ├── walk.ts                    # 递归目录遍历
│ │ │   ├── sidecar.ts                 # Sidecar JSON 元数据读写
│ │ │   ├── mime.ts                    # MIME 类型推断
│ │ │   ├── thumbnail.ts               # 画布缩略图生成(缓存优先)
│ │ │   ├── scan-roots.ts              # 扫描根目录计算 + 阶段过滤
│ │ │   └── index.ts                   # IPC handler 注册
│ │ └── utils/                         # 平台判断 / 图标路径
│ └── preload/                         # 预加载脚本contextBridge 桥接层)
│   ├── base.ts                        # ipcRenderer 基础桥接on/off/send/invoke
│   ├── safe-storage.ts                # safeStorage 加密/解密 API
│   ├── file-storage.ts                # 文件存储 APIgetDataDir / readFile / writeFile
│   ├── canvas.ts                      # 画布 APIopenWindow / scanProject / readSidecar
│   ├── app-runtime.ts                 # 运行时 APIsetWindowEdition
│   ├── index.ts                       # 汇总导出exposeBaseIpc / exposeSafeStorage / ...
│   ├── 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.tsZustand store
│ │ │ └── utils/                       # scanner.ts / layout.ts / LocalFileDataSource.ts
│ │ └── settings/        V+C           # 应用设置
│ │   ├── views/                       # SettingsPage.tsx + sections/6 个设置分区)
│ │   └── controllers/                 # settings-actions.ts
│ │
│ └── shared/                          # ═══ 跨模块共享 ═══
│   ├── components/                    # 通用 UIFloatingPanel / FormField / LegalTextModal / ContextMenu
│   ├── hooks/                         # 全局 HooksuseAnnouncements / useApi / useAsync / useUpdater
│   ├── services/                      # HTTP 客户端 + API 模块
│   │ ├── request/                     # Axios 请求封装
│   │ │ ├── token.ts                   # Token 管理(加密存储 + 内存缓存)
│   │ │ ├── interceptors.ts            # 请求/响应拦截器401 刷新 + 错误处理)
│   │ │ ├── methods.ts                 # 请求方法get/post/put/del/upload/download
│   │ │ └── index.ts                   # 主入口 + 导出
│   │ └── modules/                     # API 模块auth / home / account / announcement
│   ├── utils/                         # 工具函数
│   │ ├── bus.ts                       # 事件总线emit / on / off / EVENTS
│   │ ├── pricing/                     # 定价计算模块
│   │ │ ├── types.ts                   # 类型定义ModelPricingConfig / ModelDefinition
│   │ │ ├── helpers.ts                 # 内部工具asFloat / matchDimensions
│   │ │ ├── format.ts                  # 金额格式化formatYuan / formatCent
│   │ │ ├── calculate.ts               # 计价逻辑6 种定价模式)
│   │ │ ├── fields.ts                  # 依赖字段收集
│   │ │ └── index.ts                   # 主入口 + 导出
│   │ ├── enum-resolver.ts             # 枚举值解析
│   │ ├── display.ts                   # 显示工具
│   │ └── safe-storage.ts              # 安全存储工具
│   ├── 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                         # 应用名称 / 窗口标题
│ │ ├── version.ts                     # 版本号
│ │ ├── keyboard.ts                    # 快捷键映射
│ │ └── ipc/                           # IPC 通道常量(模块化)
│ │   ├── base.ts                      # 基础通道(窗口/日志/主题/配置)
│ │   ├── storage.ts                   # 存储通道(文件/加密/下载/缩略图)
│ │   ├── canvas.ts                    # 画布通道(扫描/sidecar/拖拽)
│ │   ├── updater.ts                   # 更新通道(检查/下载/安装)
│ │   └── index.ts                     # 汇总导出 + 兼容性 BIDIRECTIONAL
│ ├── types/                           # index.tsPlatform/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+Mauth 用 V+C+H+S+Mcanvas 额外有 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 或直接标注函数参数类型(推荐直接标注)。

  • 事件处理函数命名以 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 / useSettingsHook 内部做 null 检查并抛出明确错误信息。

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

日志系统

  • 双端日志主进程直接写文件electron/main/logger.ts渲染进程通过 IPC send 上报src/shared/utils/bus.ts。 两端暴露一致的 APIlogger.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 → debug5xx → 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_tokenrefresh_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 在日志写入前自动脱敏处理
  • 覆盖字段:用户 IDSHA256 哈希)、邮箱(***@domain、手机号掩码、用户名称、Token截断
  • 主进程 electron/main/logger.ts 和渲染进程 src/shared/utils/bus.ts 均写入前调用 sanitizeLogEntry()

样式与主题

  • 优先使用 Tailwind 工具类完成布局与常规样式。自定义设计令牌在 src/shared/theme/tokens.css@theme 块中定义Tailwind v4 语法),自动生成 bg-primary-500text-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 中的安全守卫访问 IPChasIpc 检查 → safeIpcOn / send / invoke 非 Electron 环境下静默跳过,保证浏览器预览不崩溃。

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

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

开发与构建命令

  • 开发模式npm run dev 或 yarn dev同时启动 Vite 与 Electron支持热重载

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

  • 代码检查npm run lintESLint + Prettier规则已配置为强制分号、单引号等

  • 类型检查npm run typechecktsc --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": trueelectron-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.sizeupdate-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.developmentbuild→.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。打包后无这些文件时自动使用代码默认值。

测试工作流

# 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.mdtest-server/README.md

与其他 AI 协作的补充说明

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

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

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

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