# 项目概览 - 本项目使用 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/utils/event-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 组件树中以确保状态一致性。 # 目录结构 > 每个文件夹下均有 `README.md` 说明该目录的职责与代码边界(自动生成,不进 Git)。 ```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/) │ │ └── utils/ # 平台判断 / 图标路径 │ └── preload/ # 预加载脚本(contextBridge 桥接层) │ ├── device.ts # 硬件指纹采集(wmic/powershell | ioreg/sysctl) │ └── device_service.ts # 设备信息缓存层(机器码/IP/MAC) ├── src/ # 渲染进程(React 19 + Vite + TypeScript) │ ├── main.tsx # React 挂载 + Provider 嵌套 + 全局错误捕获 │ ├── App.tsx # 根组件:叠加层编排(登录/设置/页面调度) │ ├── vite-env.d.ts # Vite 类型声明 │ ├── components/ # 通用组件层 │ │ ├── providers/ # 全局 Context Provider │ │ │ ├── AppProvider.tsx # 认证状态(login/logout/Token 刷新) │ │ │ ├── ThemeProvider.tsx # 亮/暗主题切换 + antd ConfigProvider │ │ │ └── SettingsProvider.tsx # 本地持久化设置(存储路径等) │ │ ├── frame/ # 应用框架(外层结构 + 页面调度) │ │ │ ├── Layout.tsx # 全高 flex 列布局壳 │ │ │ ├── PageDispatcher.tsx # 通用页面调度器(Modal/Drawer/FloatingPanel) │ │ │ └── navbar/ # 导航栏(nav-config → NavBar → NavItem) │ │ └── ui/ # 通用 UI 原子组件 │ │ ├── FloatingPanel.tsx # 可拖拽非模态浮动面板 │ │ ├── LegalTextModal.tsx # 法律/协议文本 Modal │ │ ├── FormField.tsx # 通用表单字段渲染器(数据驱动,从 auth/components 提升) │ │ └── types.ts # FieldConfig / FieldRule / InputType 通用类型 │ ├── hooks/ # 自定义 Hooks │ │ ├── use-async.ts # 通用异步基础设施(竞态/取消/门控) │ │ ├── use-api.ts # 业务 API Hooks(Banner/模型/任务/账户/财务) │ │ └── use-updater.ts # 更新状态机(单例 IPC 监听) │ ├── infrastructure/ # 基础设施层 │ │ └── storage/ # 本地加密数据库(core/ + stores/ + services/) │ │ ├── index.ts # 统一入口:init/clear/stats + 全部 re-export │ │ ├── ipc-file.ts # 渲染进程端文件操作桥接 │ │ ├── core/ # 数据库核心(4 文件) │ │ │ ├── db-core.ts # sql.js WASM 初始化 + 通用 CRUD │ │ │ ├── db-encrypt.ts # 序列化 → safeStorage 加密 → IPC 写磁盘 │ │ │ ├── schema.ts # 6 张业务表 DDL(含索引) │ │ │ └── types.ts # 实体类型定义 │ │ ├── stores/ # 实体 CRUD Store(5 文件) │ │ │ ├── task-store.ts # 任务记录 │ │ │ ├── order-store.ts # 订单记录(充值 + VIP) │ │ │ ├── param-store.ts # 参数历史快照 │ │ │ ├── media-store.ts # 媒体缓存元数据 │ │ │ └── settings-store.ts # 应用设置 key-value │ │ └── services/ # 高级服务(4 文件) │ │ ├── media-loader.ts # 媒体下载与三级缓存 │ │ ├── sync-manager.ts # 分页同步游标 │ │ ├── data-sync.ts # 数据同步辅助(从 settings/sections 归位) │ │ └── user-scope.ts # 用户作用域隔离(JWT user_id) │ ├── pages/ # 业务页面(按功能模块组织) │ │ ├── auth/ # 认证模块 │ │ │ ├── index.tsx # LoginPage Modal(登录/注册 Tabs) │ │ │ ├── components/ # 表单组件(LoginForm/RegisterForm/FormField/改密/忘记密码) │ │ │ ├── config/ # 字段配置(login-fields/register-fields)+ 校验函数库 │ │ │ └── hooks/ # use-auth-state(偏好)/ use-sms-cooldown(短信冷却) │ │ ├── home/ # 首页主工作区 │ │ │ ├── HomePage.tsx # 首页入口 │ │ │ ├── HomeContent.tsx # 三列可拖拽面板 + HomeContext.Provider │ │ │ ├── HomeContext.tsx # 共享状态(选中模型/任务/分页) │ │ │ ├── panels/ # 三列面板容器(Left/Center/Right) │ │ │ ├── features/ # 功能模块(Banner/ModelSelector/ModelInputForm/TaskHistory/OutputPreview) │ │ │ ├── controls/ # Widget 控件体系(6 种 Qt→React 映射 + WIDGET_MAP) │ │ │ │ ├── types.ts # WidgetProps 统一接口 │ │ │ │ ├── index.ts # WIDGET_MAP 注册表 │ │ │ │ ├── simple-widgets.tsx # 6 个简单控件(Checkbox/LineInput/TextInput/ComboBox/SpinBox/DoubleSpinBox) │ │ │ │ ├── upload-widgets.tsx # 单文件上传(ImageInput/VideoInput,共享 enable_switch) │ │ │ │ ├── list-upload-widgets.tsx # 多文件拖拽上传(ImageListInput/AudioListInput) │ │ │ │ └── SeedanceContent.tsx # 复合内容编排 │ │ │ └── hooks/ # useModelUI(param_schema → UIFieldConfig) │ │ ├── panels/ # NavBar 触发的功能面板页 │ │ │ ├── AccountInfo.tsx # 账户信息(用户/积分/套餐/统计) │ │ │ ├── BillingInfo.tsx # 财务信息(余额 + 账单流水) │ │ │ ├── OrdersPage.tsx # 订单明细(充值/VIP 双 Tab + 轮询) │ │ │ ├── RechargePage.tsx # 积分充值(预设/自定义金额 + 支付追踪) │ │ │ ├── VipPage.tsx # VIP 开通(激活码/套餐选购/权益预览) │ │ │ └── WechatWorkPage.tsx # 企业微信二维码 │ │ └── settings/ # 设置页面 │ │ ├── SettingsPage.tsx # 设置 Modal 主页面 │ │ └── sections/ # 6 个设置分区(主题/系统/更新/路径/密码/数据) │ ├── services/ # 服务层(HTTP 请求封装) │ │ ├── request.ts # Axios 实例:拦截器 + Token 注入 + 401 刷新队列 │ │ ├── auth-token.ts # Token 生命周期(refresh_token 持久化/主动刷新) │ │ ├── auth-persistence.ts # 登录表单偏好(用户名回填/记住密码/自动登录) │ │ ├── types.ts # 通用 API 类型(ApiResponse/RequestError/RefreshError) │ │ ├── cache/ # 客户端缓存 │ │ │ └── model-cache.ts # 模型列表加密本地缓存 │ │ └── modules/ # API 模块(按业务域拆分) │ │ ├── auth.ts # 认证 API(登录/注册/刷新/用户/改密/短信) │ │ ├── models.ts # 模型 API + 分类常量 │ │ ├── task.ts # 任务 API(CRUD + 批量状态 + CSV + 轮询常量) │ │ ├── banner.ts # Banner/轮播图 API │ │ ├── billing.ts # 财务 API(余额/账单/导出) │ │ ├── payments.ts # 支付 API(订单 CRUD + 状态映射) │ │ ├── vip-api.ts # VIP API(激活/等级/订单) │ │ └── announcement.ts # 公告 API + 类型标签颜色 │ ├── theme/ # 主题系统 │ │ ├── tokens.ts # TypeScript 设计令牌 │ │ ├── tokens.css # CSS 设计令牌(Tailwind @theme + CSS 变量亮/暗) │ │ ├── antd-theme.ts # Ant Design ConfigProvider 主题配置(亮/暗) │ │ ├── transitions.css # 主题切换过渡(View Transitions API + CSS fallback) │ │ ├── base.css # 全局重置(盒模型/滚动条/聚焦环/拖拽区域) │ │ └── globals.css # 入口文件(按序导入以上 CSS) │ └── utils/ # 渲染进程工具函数(7 文件,已按功能合并) │ ├── env.ts # 运行时环境:平台检测 + 设备 ID(← platform + device) │ ├── bus.ts # 通信层:事件总线 + IPC 守卫 + 日志(← event-bus + ipc + logger) │ ├── display.ts # 展示/格式化:金额、日期、Logo、Nullable(← display + logo + type) │ ├── enum-resolver.ts # 枚举外观模式(7 模块标签/颜色统一解析) │ ├── pricing.ts # 成本计算(Python 六种定价模式移植) │ ├── safe-storage.ts # 加密 localStorage 封装(safeStorage 桥接) │ └── media-upload.ts # 媒体上传共享工具(← controls/media-upload-utils) ├── shared/ # 主进程 & 渲染进程共享 │ ├── constants/ │ │ ├── app.ts # 应用名称/版本类型/窗口标题 │ │ ├── ipc-channels.ts # 全部 IPC 通道名称(三类命名空间) │ │ └── version.ts # 从 package.json 读取版本号 │ ├── types/ │ │ ├── index.ts # 通用类型(Platform/Theme/Edition/Update/Window) │ │ └── logging.ts # 日志类型(LogLevel/LogCategory/LogEntry) │ └── utils/ │ ├── index.ts # 纯工具函数(debounce/throttle/compareVersions/deepClone) │ └── sanitize.ts # 日志脱敏(token/密码/邮箱/手机/ID/金额) ├── scripts/ # 构建与发布脚本 │ ├── clean.mjs # 清理构建产物 │ ├── generate-update-info.mjs # 生成 update-info.json(SHA512 + CHANGELOG) │ ├── upload-oss.mjs # 上传安装包到阿里云 OSS │ └── publish-release.mjs # 发布版本到后端 API ├── build.mjs # electron-builder 构建总管 ├── vite.config.ts # Vite 构建配置 ├── package.json # 含 electron-builder 打包配置 └── pnpm-workspace.yaml ``` # 多窗口与平台判定 - 窗口管理由 `electron/main.ts` 统一负责:`createMainWindow()` 创建主窗口,`BrowserWindow` 通过 `contextIsolation: true` + `nodeIntegration: false` 运行沙箱化渲染进程。辅助窗口通过 `RENDERER_TO_MAIN.OPEN_SUB_WINDOW` IPC 通道按需创建。 - 平台判定双端各有一份:`electron/main/utils/platform.ts`(主进程,直接使用 `process.platform`)和 `src/utils/platform.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 合并在 `components/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/utils/logger.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/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 ` - 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/utils/logger.ts` 均写入前调用 `sanitizeLogEntry()` # 样式与主题 - 优先使用 Tailwind 工具类完成布局与常规样式。自定义设计令牌在 `src/theme/tokens.css` 的 `@theme` 块中定义(Tailwind v4 语法),自动生成 `bg-primary-500`、`text-secondary` 等工具类。 - Ant Design 组件样式通过 ConfigProvider 的 theme 属性覆盖,确保与 Tailwind 主题令牌同步。 `ConfigProvider` 同时配置 `locale={zhCN}` 实现全局中文(分页器"条/页"等无需逐个组件设置)。 在 src/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/utils/ipc.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/hooks/use-updater.ts` | 渲染进程更新状态 Hook(单例 IPC 监听) | | `UpdateSetting` | `src/pages/settings/blocks/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,确保三处一致。