From 0a5b1780da3615fbd4910cfc848a813b6b5dfc64 Mon Sep 17 00:00:00 2001 From: ZenEcho Date: Fri, 27 Mar 2026 11:07:44 +0800 Subject: [PATCH] docs: Add new documentation files and update the package version to 0.2.1. --- docs/README.md | 45 +++ docs/development-guide.md | 157 ++++++++ docs/electron-scanners-deep-dive.md | 579 ---------------------------- docs/electron-structure.md | 97 ----- docs/module-usage.md | 423 ++++++++++++++++++++ docs/project-structure.md | 205 ++++++++++ docs/singbox-config.md | 54 --- docs/src-structure.md | 92 ----- package.json | 2 +- 9 files changed, 831 insertions(+), 823 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/development-guide.md delete mode 100644 docs/electron-scanners-deep-dive.md delete mode 100644 docs/electron-structure.md create mode 100644 docs/module-usage.md create mode 100644 docs/project-structure.md delete mode 100644 docs/singbox-config.md delete mode 100644 docs/src-structure.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..05f0b01 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,45 @@ +# LagZero 开发文档 + +本文档面向参与 LagZero 开发与维护的同学,基于当前仓库代码整理。项目整体是一个 `Vue 3 + Vite + Electron` 的桌面应用,业务核心围绕游戏库、节点管理、sing-box 加速链路、本地代理与系统代理控制展开。 + +## 文档导航 + +- [development-guide.md](./development-guide.md): 环境准备、常用命令、启动流程、日常开发建议 +- [project-structure.md](./project-structure.md): 仓库目录树、关键目录职责、推荐阅读顺序 +- [module-usage.md](./module-usage.md): 前端模块、Electron 服务、常见调用方式与扩展路径 + +## 架构概览 + +```mermaid +flowchart LR + A["Vue Views / Components"] --> B["Pinia Stores / Composables"] + B --> C["src/api"] + C --> D["window.* (preload expose)"] + D --> E["ipcMain channels"] + E --> F["Electron Services"] + F --> G["SQLite / FileSystem / sing-box / OS"] +``` + +## 当前代码分层 + +- `src/`: 渲染进程,负责页面、状态管理、配置生成与 UI 交互 +- `electron/`: 主进程,负责窗口、托盘、IPC、数据库、系统能力与 sing-box 生命周期 +- `shared/`: 主进程与渲染进程共用的类型和纯函数工具 +- `tests/unit/`: 以 Vitest 为主的单元测试 + +## 阅读建议 + +如果是第一次接手项目,建议按下面顺序阅读: + +1. [development-guide.md](./development-guide.md) +2. [project-structure.md](./project-structure.md) +3. `electron/main/index.ts` +4. `electron/preload/index.ts` +5. `src/main.ts` +6. `src/stores/` +7. [module-usage.md](./module-usage.md) + +## 说明 + +- 文档中的目录树是“开发视角”的精简版,刻意省略了 `node_modules`、构建产物与本地工具目录。 +- 若后续新增 IPC、store、scanner 或设置项,建议同步更新这组文档。 diff --git a/docs/development-guide.md b/docs/development-guide.md new file mode 100644 index 0000000..1c8cfa8 --- /dev/null +++ b/docs/development-guide.md @@ -0,0 +1,157 @@ +# LagZero 开发指南 + +## 1. 项目定位 + +LagZero 是一个面向游戏加速场景的桌面客户端,主要由以下几部分组成: + +- 渲染进程:`Vue 3 + Pinia + Vue Router + Naive UI + UnoCSS` +- 主进程:`Electron` +- 网络内核:`sing-box` +- 数据存储:`better-sqlite3 + Kysely` +- 测试:`Vitest + happy-dom` + +项目采用 Hash 路由,并同时维护主窗口与托盘窗口两套入口视图。 + +## 2. 环境准备 + +### 基础要求 + +- Node.js `18+` +- `pnpm` +- Windows 环境下建议使用管理员权限运行开发环境,尤其是调试 TUN、系统代理和 DNS 相关逻辑时 + +### 安装与启动 + +```bash +pnpm install +pnpm rebuild:native +pnpm dev +``` + +### 为什么一定要执行 `pnpm rebuild:native` + +项目依赖 `better-sqlite3`,它是原生模块。Electron 的 Node ABI 与普通 Node.js 不完全一致,如果不重建,开发阶段很容易遇到启动失败或 ABI 不匹配问题。 + +## 3. 常用命令 + +| 命令 | 作用 | +| --- | --- | +| `pnpm dev` | 启动 Vite + Electron 开发环境 | +| `pnpm build` | 执行 `vue-tsc -b` 后构建渲染进程产物 | +| `pnpm test` | 运行 Vitest 单元测试 | +| `pnpm pack` | 打包为未安装目录,便于验证桌面运行环境 | +| `pnpm dist` | 构建当前平台安装包 | +| `pnpm dist:win:all` | 构建 Windows x64/arm64 的 NSIS 与 Portable 包 | +| `pnpm rebuild:native` | 重建 Electron 原生依赖 | +| `pnpm rebuild:sqlite` | 仅重建 `better-sqlite3` | + +## 4. 启动流程 + +### 主进程启动 + +`electron/main/index.ts` 是主进程总入口,主要负责: + +- 设置 `userData` 路径与单实例锁 +- 启用提权、CSP、CrashReporter、日志系统 +- 创建主窗口与托盘窗口 +- 实例化 `DatabaseService`、`SingBoxService`、`SystemService` 等核心服务 +- 注册应用级 IPC、对话框 IPC、扫描 IPC 与更新 IPC + +### 渲染进程启动 + +`src/main.ts` 是渲染进程入口,主要负责: + +- 初始化运行时日志与延迟会话存储 +- 挂载 `router`、`pinia`、`i18n` +- 在主窗口中初始化本地代理自动启动与节点监听逻辑 +- 对托盘窗口 `#/tray` 做特判,避免执行不必要的业务初始化 + +### 启动顺序图 + +```mermaid +sequenceDiagram + participant App as Electron App + participant Main as electron/main/index.ts + participant Preload as electron/preload/index.ts + participant Renderer as src/main.ts + participant Store as Pinia Stores + + App->>Main: app.whenReady() + Main->>Main: 创建窗口 / 托盘 / 注册 IPC + Main->>Main: 初始化 DatabaseService 等服务 + Main->>Preload: 加载 preload + Preload->>Renderer: 暴露 window.electron / window.system / window.singbox ... + Renderer->>Store: 初始化 settings / nodes / games / local-proxy + Store->>Main: 通过 src/api -> preload -> IPC 调用主进程能力 +``` + +## 5. 日常开发建议 + +### 新增一个前端功能 + +推荐顺序: + +1. 如果主渲染进程都要用到数据结构,先在 `shared/types/` 定义类型 +2. 如果只是页面逻辑,先评估放进 `store` 还是 `composable` +3. 如果需要主进程能力,先在 `preload` 和 `src/api` 打通桥接 +4. 页面层优先走 `store`,不要在组件里直接拼 IPC 调用链 + +### 新增一个 Electron 能力 + +推荐顺序: + +1. 在 `electron/services/` 新建或扩展服务 +2. 在服务中注册 `ipcMain.handle(...)` +3. 在 `electron/preload/index.ts` 暴露到 `window.*` +4. 在 `src/api/*.ts` 增加薄封装 +5. 在 `store` 或 `composable` 中消费 + +### 新增一个设置项 + +推荐落点: + +- 持久化设置:`src/stores/settings.ts` +- 设置界面:`src/components/settings/` +- 若会影响加速流程:同步检查 `src/stores/games.ts`、`src/stores/local-proxy.ts`、`src/utils/singbox-config.ts` + +### 新增一个游戏平台扫描器 + +推荐顺序: + +1. 在 `electron/services/scanners/` 新增平台扫描器 +2. 在 `electron/services/game-scanner.ts` 注册到 `scanners` 列表 +3. 复用现有 `ScanProgressCallback`、`dedupeProcessNames`、`normalizeFsPath` 等工具 +4. 通过 `useGameScanner()` 触发扫描,并让 `gameStore` 负责入库 + +## 6. 开发时需要特别注意的约束 + +- 渲染进程不要直接暴露或使用 `ipcRenderer`,统一经过 `preload` +- `shared/` 层不要依赖 Vue、Electron 或浏览器对象 +- 托盘窗口走 `#/tray`,`src/main.ts` 已明确跳过本地代理自动初始化 +- `generateSingboxConfig()` 是加速配置的单一出口,改代理规则优先改这里 +- 本地代理与游戏加速共用 sing-box 进程,变更逻辑时要同时考虑 `games` 与 `local-proxy` 两条链路 + +## 7. 测试与验证 + +### 单元测试 + +```bash +pnpm test +``` + +当前测试主要覆盖: + +- 协议解析 +- sing-box 配置生成 +- 代理监控逻辑 +- Steam 扫描器与扫描工具 +- 主题逻辑 +- 分类管理和 JSON store + +### 手动验证建议 + +- 节点导入、节点测速、订阅刷新 +- 游戏扫描、游戏启动/停止加速 +- TUN 与系统代理两种模式切换 +- 本地代理自动选点与健康检查 +- 托盘状态同步、主窗口关闭行为、应用重置 diff --git a/docs/electron-scanners-deep-dive.md b/docs/electron-scanners-deep-dive.md deleted file mode 100644 index 3b64ac4..0000000 --- a/docs/electron-scanners-deep-dive.md +++ /dev/null @@ -1,579 +0,0 @@ -# electron/services/scanners 重解读(功能增删与优化决策版) - -更新时间:2026-03-05 -适用代码:`electron/services/scanners/*` + `electron/services/game-scanner.ts` 及其联动链路 - -## 0. 这份文档解决什么问题 - -你要做的是: - -1. 功能增删(新增/移除平台、改扫描策略、改字段) -2. 再决定优化(性能、稳定性、维护成本) - -这份文档按“先看清系统,再做改造”组织,重点回答: - -- 当前模块到底做了哪些功能 -- 每个功能用什么技术实现 -- 扫描结果会联动哪些模块 -- 哪些点改起来风险高/耦合重 -- 你应该先改哪里,后改哪里 - -## 1. 模块总览 - -### 1.1 目录结构与职责 - -`electron/services/scanners` 目录当前包含: - -- `types.ts`: 扫描统一类型与过滤常量 -- `utils.ts`: 通用工具层(并发、目录扫描、exe 评分、图标提取、路径标准化) -- `steam.ts`: Steam 扫描器 -- `microsoft.ts`: Microsoft Store / Xbox 扫描器 -- `epic.ts`: Epic 扫描器 -- `ea.ts`: EA 扫描器 -- `battlenet.ts`: Battle.net 扫描器 -- `wegame.ts`: WeGame 扫描器 -- `local.ts`: 本地快捷方式扫描器 -- `flat.ts`: 通用“平铺目录扫描器”(Epic/EA/Microsoft 复用) - -聚合入口不在该目录,而在: - -- `electron/services/game-scanner.ts` - -### 1.2 统一结果模型(所有扫描器必须遵守) - -```ts -type LocalGameScanResult = { - name: string; - processName: string[]; - source: - | "Steam" - | "Microsoft" - | "Epic" - | "EA" - | "BattleNet" - | "WeGame" - | "Local" - | "GOG"; - installDir: string; - iconUrl?: string; -}; -``` - -这 5 个字段是该系统最核心的“数据契约”。 - -## 2. 端到端链路(扫描结果如何流动) - -```mermaid -flowchart LR - A["Renderer useGameScanner.scanGames()"] --> B["Preload system.scanLocalGames()"] - B --> C["Main IPC: system:scan-local-games"] - C --> D["GameScannerService.scanLocalGamesFromPlatforms()"] - D --> E["各平台 scanner"] - E --> F["LocalGameScanResult[]"] - F --> G["autoAddGamesFromLibraryScan() 自动入库"] - G --> H["Database games.process_name 保存"] - H --> I["ProxyMonitor 读取 processName"] - I --> J["SingBoxConfigManager.updateProcessNames()"] -``` - -进度事件协议: - -- `system:scan-progress` 事件 -- `status` 目前约定值:`scanning_platform` / `scanning_dir` - -对应联动代码: - -- Main IPC: `electron/main/index.ts` -- Preload 暴露: `electron/preload/index.ts` -- 前端消费: `src/composables/useGameScanner.ts` - -## 3. 技术实现清单(扫描到底用了什么技术) - -### 3.1 文件系统与路径 - -- `fs-extra`: `readdir/stat/pathExists/readFile/readJSON` -- `path`: 目录拼接、标准化 -- `os`: CPU 核数/用户目录 - -### 3.2 系统信息采集(Windows) - -- PowerShell + 注册表查询(通过 `runCommand('powershell', ...)`) -- 查询来源: - - Steam 注册表 - - 卸载项注册表(EA/BattleNet/Microsoft 提示) - - WeGame 注册表 - - `Get-AppxPackage`(Microsoft) - -### 3.3 Electron 原生能力 - -- `nativeImage.createFromPath()`:从 exe 抽图标 data URL -- `shell.readShortcutLink()`:解析 `.lnk` 目标路径 - -### 3.4 并发控制(核心) - -`mapWithConcurrency()` 是全模块通用执行器: - -- 固定 worker 数量 -- 任务索引共享 -- 避免 `Promise.all` 一次性打满 I/O - -并发参数分布(当前代码): - -- 平台聚合并发:4(`GameScannerService`) -- 多数目录层并发:4~8 -- 盘符探测并发:8 - -### 3.5 启发式识别(主进程挑选) - -核心算法:`pickRelatedExecutables()` - -- 分阶段深度扫描:2 -> 4 -> 6 -- 快速评分: - - 文件名与目标名匹配度 - - 路径中 `shipping/win64/binaries` 等特征 - - `launcher` 降噪 - - 软过滤关键词降权 -- 二次评分:文件体积补分(`stat`) -- 结果截断:最多取 4 个 - -## 4. 通用层深解(types.ts + utils.ts) - -### 4.1 `types.ts` 的过滤体系 - -过滤分 3 层: - -1. 目录硬过滤:`GAME_SCAN_IGNORE_DIR_NAMES` -2. 可执行文件硬过滤:`GAME_SCAN_IGNORE_EXE_KEYWORDS` -3. 文件名硬排除:`GAME_SCAN_EXE_HARD_EXCLUDE` - -再加一层软过滤: - -- `GAME_SCAN_SOFT_IGNORE_EXE_KEYWORDS`(只降权,不直接丢弃) - -这套设计兼顾了“减少误报”和“避免误杀”。 - -### 4.2 `normalizeFsPath()` 的作用 - -- 路径 normalize -- 去尾部分隔符 -- 转小写 - -这是跨平台扫描器最终去重的关键函数。 - -### 4.3 `getWindowsDriveRoots()`(当前实现) - -- 每次调用都重新并发探测 `C:` 到 `Z:` -- 不做盘符结果缓存 - -优点:实时性高(插拔盘符后能即时反映) -代价:不同扫描器会重复探测盘符。 - -### 4.4 `pickGameIconDataUrl()`(当前实现) - -- 图标结果不缓存 -- 只缓存 `nativeImage` API 句柄(模块级) -- 候选 exe 只看前 4 个 - -优点:逻辑简单、不会有旧缓存污染 -代价:跨平台/跨轮扫描时会重复读取同一 exe 图标。 - -### 4.5 `collectExePaths()`:已从递归改为迭代任务队列 - -当前行为: - -- 维护 `pending` 队列(`{dir, depth}`) -- 按深度限制推进 -- 大目录优先级裁剪子目录(最多 120) -- 目录去重 `visited` - -你需要特别注意的现实情况: - -- 当前 `workerCount` 初始化受 `pending.length` 影响,初始基本为 1,等价于单 worker 扫描。 - 这意味着虽然代码形态是“并发 worker”,实际常常是串行队列。 - -这个点在你后续做性能优化时值得优先评估。 - -## 5. 各平台扫描器详解 - -## 5.1 Steam(`steam.ts`) - -实现策略:清单优先 + 目录兜底 - -流程: - -1. 盘符推导候选 Steam 根目录 -2. 限制性嗅探 `steamapps`,避免全盘暴扫 -3. 读注册表补充 Steam 安装根目录 -4. 解析 `steamapps/libraryfolders.vdf`(兼容新旧格式) -5. 扫 `appmanifest_*.acf`: - - 读取 `name` / `installdir` / `StateFlags` - - 若 `StateFlags` 表示未安装则跳过 -6. 对安装目录执行 `pickRelatedExecutables` -7. 若该库存在 manifest,则不再深扫 `steamapps/common` - -技术亮点: - -- `libraryfolders.vdf` 新旧格式兼容 -- 基于 manifest 的 I/O 节流策略 - -## 5.2 Microsoft(`microsoft.ts`) - -实现策略:目录扫描 + Appx 包扫描 + 名称提示修正 - -流程: - -1. `XboxGames` 根目录平铺扫描(`scanFlatPlatformFolder`) -2. `Get-AppxPackage` 获取安装位置 -3. 读取 `AppxManifest.xml` 判断是否“像游戏” -4. 通过 `DisplayName/Identity Name` 解析名称 -5. 合并 base 与 appx 结果(按 installDir) -6. 再用注册表 hints + manifest hints 做名称修正 - -关键技术: - -- XML 文本正则解析 -- 多来源结果融合 + 最长路径提示优先 - -## 5.3 Epic(`epic.ts`) - -实现策略:manifest 优先,平铺目录兜底 - -流程: - -1. 读取 `%ProgramData%/.../Manifests/*.item` -2. 用 `InstallLocation + DisplayName/AppName` -3. 若有 `LaunchExecutable`,优先作为进程名候选 -4. 再跑 `pickRelatedExecutables` 追加进程名 -5. 平铺目录兜底扫描(`scanFlatPlatformFolder('Epic', roots)`) - -## 5.4 EA(`ea.ts`) - -实现策略:注册表双通道 + 平铺兜底 + 启动器排除 - -流程: - -1. 专有 EA 注册表读取 `Install Dir` -2. 卸载项注册表读取 `DisplayName + InstallLocation` -3. 合并 hints,统一扫描函数 `scanEAHintInstall` -4. 排除 `EA app / EA desktop / Origin` 启动器 -5. 平铺目录兜底,且附加目录过滤钩子 - -## 5.5 BattleNet(`battlenet.ts`) - -实现策略:注册表 hints + 一级目录可疑项扫描 - -流程: - -1. 卸载项注册表收集候选 -2. 过滤 launcher/agent/updater -3. 判断游戏目录特征: - - `.build.info` 存在 - - 或目录名命中游戏关键词 -4. fallback:在 `Games/Game/Program Files` 一级扫可疑目录 - -特征: - -- BattleNet 识别更依赖“目录特征+关键词”,准确率受目录命名影响较大。 - -## 5.6 WeGame(`wegame.ts`) - -实现策略:注册表根目录 + 容器目录展开 - -流程: - -1. 读腾讯 WeGame 注册表路径 -2. 组合常见安装根 -3. 对 `rail_apps/common_apps/apps/games` 容器做二层展开 -4. 跳过 cache/log/temp/patch 等非游戏目录 - -## 5.7 Local(`local.ts`) - -实现策略:快捷方式反查 exe - -流程: - -1. 递归扫描桌面和开始菜单(深度 <= 3)找 `.lnk` -2. `shell.readShortcutLink()` 拿 target -3. 排除浏览器/系统目录/Office 等路径 -4. 基于 target 所在目录再执行 `pickRelatedExecutables` - -说明: - -- 这里仍是递归 `collectLnks()`,并未迭代化。 - -## 5.8 Flat(`flat.ts`) - -这是“平台复用模板”,做三件事: - -1. 扫 root 的一级目录 -2. 可选目录过滤(`ignoreDirNames`, `shouldIncludeDir`) -3. 每个目录执行 `pickRelatedExecutables` - -这个文件是后续做“平台插件化”最好的抽象基础。 - -## 6. 聚合器(`game-scanner.ts`) - -### 6.1 聚合流程 - -- 同时运行 7 个扫描器(并发上限 4) -- 将各平台结果拼接后统一去重 - -### 6.2 去重策略 - -第一优先级:`installDir` 归一化后作为 key -第二优先级:无 installDir 时,`name + sorted(processName)` - -冲突合并策略: - -- `name` 选长度更长的 -- `processName` 合并去重 -- `iconUrl` 取已有优先 - -### 6.3 额外接口 - -`scanDir()` 用于“手动选目录扫描 exe”,当前仍使用递归实现。 - -## 7. 联动与耦合(必须清楚) - -## 7.1 IPC 协议耦合 - -- 主进程 channel:`system:scan-local-games` -- 进度事件:`system:scan-progress` -- 前端写死了 `scanning_platform/scanning_dir` 两个状态解释逻辑 - -改这些名字或状态值,会直接影响 UI 展示。 - -## 7.2 前端自动入库耦合 - -`useGameScanner.autoAddGamesFromLibraryScan()` 会: - -- 按 `source` 自动创建平台分类(使用 `PLATFORMS`) -- 用 `name+process` 去重 -- 调 `categoryApi.match` 自动匹配分类 - -所以 `source` 与 `processName` 的语义变化会影响入库行为。 - -## 7.3 数据库耦合 - -`DatabaseService.saveGame()`: - -- `processName` 最终写入 `games.process_name`(JSON 字符串) -- `getAllGames()` 再解析为数组返回 - -字段兼容性要求: - -- 扫描层始终保证 `processName: string[]` -- 避免输出路径形式(最好仅文件名) - -## 7.4 代理链路耦合(最关键) - -`proxy-monitor` + `singbox/config` 直接依赖扫描得到的进程名: - -1. `ProxyMonitorService.startMonitoring(gameId, processNames)` 接收初始进程 -2. 归一化后监控进程树,每 3 秒轮询 -3. 发现子进程后更新 monitored set -4. `SingBoxConfigManager.updateProcessNames()` 更新 route/dns 规则中的 `process_name` - -如果扫描器输出噪声进程,会导致代理规则扩大,带来副作用。 - -## 8. 当前功能清单(你可以据此做增删) - -模块当前已经具备: - -1. 多平台自动发现(Steam/Microsoft/Epic/EA/BattleNet/WeGame/Local) -2. 平台级并发扫描 -3. 游戏进程多候选输出(不是单 exe) -4. 图标提取(可选) -5. 统一去重与结果合并 -6. 扫描进度实时推送给前端 -7. 自动入库与分类关联 -8. 与运行时代理规则联动 - -## 9. 性能与复杂度观察(基于当前实现) - -## 9.1 已做的控制 - -- 多层并发限流(避免 I/O 风暴) -- 大目录子目录截断(3000+ 条目) -- 分阶段深度探测(2/4/6) -- Steam manifest 优先,减少 common 深扫 -- 图标提取最多探测 4 个 exe - -## 9.2 当前热点 - -1. 多平台重复调用 `getWindowsDriveRoots()`(每次全探测) -2. PowerShell 调用较多(冷启动明显) -3. `pickRelatedExecutables` 仍是最重路径(目录遍历/评分/stat) -4. 本地快捷方式扫描仍递归 -5. `collectExePaths` 迭代队列当前 worker 并发度偏低(常为 1) - -## 9.3 稳定性风险点 - -- 大量 `catch { return null }` 吞错,问题定位依赖人工加日志 -- 缺少取消机制,重复触发扫描会叠加资源占用 -- 平台关键词策略(EA/BN/WeGame)易受安装路径命名差异影响 - -## 10. 功能增删时的改动清单 - -## 10.1 新增平台 scanner - -建议步骤: - -1. 新建 `electron/services/scanners/.ts` -2. 复用 `pickRelatedExecutables + pickGameIconDataUrl` -3. 在 `game-scanner.ts` 注册扫描器 -4. 同步 `Platform`(`types.ts`)与前端 `PLATFORMS`(`src/constants/index.ts`) -5. 增加至少 2 类测试:命中样例 + 误报防护 - -## 10.2 移除平台 scanner - -必须同步: - -1. `game-scanner.ts` scanners 列表 -2. `Platform` 类型 -3. 前端 `PLATFORMS`(避免继续自动建分类) -4. 文案与 UI 过滤逻辑(如有) - -## 10.3 改扫描结果字段 - -高风险字段: - -- `processName`: 影响入库 + proxy-monitor + sing-box -- `source`: 影响分类与 UI -- `installDir`: 影响全局去重正确性 - -## 11. 你做优化前建议先定的决策 - -建议先回答这 5 个问题,再动代码: - -1. 目标是“首扫更快”还是“重复扫描更快”? -2. 可接受的漏报率上限是多少? -3. 是否允许增加缓存(盘符/图标/平台查询结果)? -4. 是否需要中断扫描(Abort)? -5. 优先优化哪个平台(Steam 还是 Microsoft/EA/BN)? - -这会直接决定是做: - -- 扫描算法优化 -- 数据源策略优化 -- 缓存策略优化 -- 架构改造(平台插件化) - -## 12. 测试覆盖现状 - -当前与扫描强相关的单测集中在 `tests/unit`: - -- `scanner-utils.spec.ts` - - 大目录根 exe 不丢失 - - 深度边界正确 - - 明显误报 exe 被过滤 -- `steam-scanner.spec.ts` - - 深层目录 exe 可被选出 - -缺口: - -1. 平台扫描器端到端测试基本没有 -2. IPC 进度事件协议无测试 -3. 去重冲突策略无回归测试 -4. 性能基准测试无自动化 - -## 13. 给你的落地建议(按顺序) - -1. 先做“观测”:加每平台耗时/命中率/失败率日志 -2. 修 `collectExePaths` 并发度(当前常为 1 的问题) -3. 再决定是否上缓存(你现在倾向不用缓存,可先不加) -4. 把 `local.ts` 的递归 `collectLnks` 迭代化(与 utils 保持一致) -5. 最后再做平台适配器抽象,降低后续功能增删成本 - ---- - -如果你下一步要开始“功能增删”,推荐先从 `flat.ts + game-scanner.ts` 的接口层入手,先稳住契约,再改各平台内部策略。 - -## 14. 附录:核心控制常量详解 (utils.ts) - -这部分解释了 `electron/services/scanners/utils.ts` 中的核心常量,这些常量直接决定了整个游戏扫描器的性能(CPU/IO占用)、准确率和极端情况下的兜底保护行为。如果要修改这些值,请务必参考以下实例。 - -### I/O 与并发控制 - -#### `UV_THREADPOOL_SIZE` - -- **当前设置**: `String(Math.max(4, os.cpus().length * 2))` -- **含义**: Node.js 底层 libuv 异步 I/O 线程池大小。 -- **影响与示例**: - - **调大**(例如 `os.cpus().length * 4`):如果在 NVMe 固态硬盘上,可以并发读取更多文件状态,大幅缩短全盘探测或高深度目录的扫描时间;但在机械硬盘(HDD)上,过高的并发会导致磁头频繁寻道,反而会让扫描龟速进行。 - - **调小**(例如固定为 `4`,Node默认值):对于深层文件夹,文件系统的 API (`fs.stat`, `fs.readdir`) 会因为排队严重饥饿,扫描整个机器所需时间呈倍数级增长。 - -#### `DEFAULT_IO_CONCURRENCY` - -- **当前设置**: `Math.max(4, Math.min(16, os.cpus().length))` -- **含义**: 基于 Worker 队列的任务并发度(常用于目录级别的异步 map 操作),最高卡在 16。 -- **影响与示例**: - - **调大**(例如 `32`):理论上瞬间能并行处理更多的子目录解析,但如果配合前面的 `UV_THREADPOOL_SIZE` 扩大,极易造成瞬间内存峰值(堆积大量 pending I/O 操作),导致 Electron 进程内存爆炸被系统 kill。 - - **调小**(例如 `2`):安全但慢。每轮只探测两个目录,适合极其脆弱的存储设备,但整体扫描会肉眼可见地拖沓。 - -#### `DRIVE_DETECT_CONCURRENCY` - -- **当前设置**: `8` -- **含义**: 找根目录时,向系统探测 `C:` ~ `Z:` 盘符并发请求数。 -- **影响与示例**: - - **调大**(例如 `24`):会同时试图访问 A-Z 全部的盘符。在一些老旧机器或者带有“休眠的外接机械硬盘/局域网断网的网络映射盘”上,会导致防病毒软件频繁拦截扫描,或者引发较长时间的操作系 I/O 卡死休眠。 - - **调小**(例如 `1`):必须等 `C:` 响应完才能访问 `D:`。如果 `D:` 恰好是一个断连的网络盘(Windows可能要等 15 秒才抛错),那扫描器的最初启动就会白白浪费这 15 秒甚至更多,用户体验极差。 - -### 启发式执行文件探测 (`pickRelatedExecutables`) - -#### `PICK_EXE_DEPTH_STAGES` - -- **当前设置**: `[2, 4, 6]` -- **含义**: 渐进式的目录探索深度。第一次在深度 2 找,没有或不满意再到 4 找,再没有就深入到 6。这是因为游戏主程序总是相对较浅,而插件、日志、引擎附属文件往往很深。 -- **影响与示例**: - - **增加**(例如 `[2, 5, 8]`):如果一个游戏的目录极大,扫到第 8 层,文件数量会呈指数级爆炸。不但消耗大量算力和耗时,还容易把位于 `Game/Engine/Plugins/Media/ThirdParty/bin/test.exe` 这种无关甚至冲突的 exe 给翻出来。 - - **减少**(例如 `[2, 3]`):扫描会变得极度敏捷,但这绝对会导致部分现代 3A 大作(常常嵌套很深,如 `[安装盘]/SteamLibrary/steamapps/common/GameName/EngineName/Binaries/Win64/game.exe` 往往涉及 4~6 层深度)的主执行文件被彻底遗漏,因为深度不够而提早放弃了。 - -#### `PICK_EXE_STAT_SAMPLE_LIMIT` - -- **当前设置**: `40` -- **含义**: 如果浅层过滤出来的“疑似主程序 exe”非常多,我们最多只取前 40 个去做真正的 `fs.stat`(用来取文件大小补分),超出的直接放弃处理。 -- **影响与示例**: - - **调大**(例如 `200`):假设遇到了一个包含了成百上千小工具的 SDK 目录,这会产生 200 次真实的文件系统 `stat` 请求。速度会被拖慢。 - - **调小**(例如 `5`):假设有 10 个看似匹配的 exe(包含各种 debug版、shipping版),由于限制,部分主程序在按字符串排序时落在了第 6 位,导致直接没有进入 `stat` 阶段没法获得“大文件加分”,最终挑出了一个 50KB 的 `Game_crash_reporter.exe` 而丢掉了 100MB 的 `Game.exe`。 - -#### `PICK_EXE_EARLY_ACCEPT_SCORE` 与 `PICK_EXE_EARLY_ACCEPT_COUNT` - -- **当前设置**: 积分 `8`,数量 `4` -- **含义**: “见好就收”机制。如果目前深度已经发现至少 4 个得分 >= 8,立刻终止后续深度的进一步探索。这样可以迅速跳过已明确找到目标的游戏。 -- **影响与示例**: - - **调高阈值**(如分数为 `15` 或 数量 `10`):基本上永远也触发不到这个提前结束机制。扫描器会对每个游戏文件夹都会死磕到最大深度 `6`,消耗的时间将是当前的几倍。 - - **调低阈值**(如分数 `4`,数量 `1`):只要在根目录遇到随便一个满足低分阈值(比如名叫 `Launcher.exe` 积分刚好4分),它就停止进入真实的 `Binaries` 文件夹寻找 `Game.exe`。误报率会极速上升,捡了芝麻丢了西瓜。 - -#### `PICK_EXE_DEEP_FALLBACK_DEPTH` - -- **当前设置**: `6` -- **含义**: 深度退避限制的兜底。防止意外或者递归逃逸死循环跑得过深。 -- **影响与示例**: - - 和 `PICK_EXE_DEPTH_STAGES` 对应,如果将其放宽,碰到畸形的套娃快捷方式或无限重定向的符号链接目录结构时,可能导致系统崩溃或爆栈。 - -### 大目录保护机制 - -#### `LARGE_DIR_ENTRY_THRESHOLD` - -- **当前设置**: `3000` -- **含义**: 当某个目录下的直接文件+子目录条目数大于 3000 时,判定该目录过于庞杂(比如游戏截图堆、模型材质堆),进而启动子目录修剪防范机制。 -- **影响与示例**: - - **调大**(例如 `10000`):对包含海量零散碎文件(比如《Garry's Mod》大量的 addons)的复杂软件放行会把队列堵死,导致一个游戏的耗时能占平时的 90%。 - - **调小**(例如 `200`):非常容易导致误伤。比如一个普通的网游带有 200多个补丁文件在根目录,瞬间判定为“过于庞杂目录”,触发“放弃大部分子路径”的硬修剪,导致漏扫。 - -#### `LARGE_DIR_SUBDIR_SCAN_LIMIT` - -- **当前设置**: `120` -- **含义**: 如果触发了上述 `3000` 的极度庞杂限制,该目录将被保护:只挑前 120 个具有潜力的子目录继续向下探索,其它所有的多余子目录原地绝育。 -- **影响与示例**: - - **调大**(例如 `1000`):大目录修剪保护形同虚设,还是容易被一万个子文件夹打爆内存堆积。 - - **调小**(例如 `10`):修剪得过于激进。如果真实的 `Binaries` 文件夹因为按字母排(或者没有包含在高优关键词里)排在第 15 个,那么这块游戏引擎就直接无了,扫描变瞎子。 - -#### `LARGE_DIR_PRIORITY_KEYWORDS` - -- **当前设置**: `['bin', 'binaries', 'win64', 'win32', 'x64', 'x86', 'game', 'client', 'release', 'shipping', 'launcher']` -- **含义**: 配合 `LARGE_DIR_SUBDIR_SCAN_LIMIT` 用的“免死金牌”。大目录下挑出来的 120 个名额里,包含这些关键词的文件夹拥有插队绝对优先权。 -- **影响与示例**: - - **增加**(例如加上 `build` 或 `out`):能让一些特殊的独立游戏或带有开发版本的客户端,在大目录修剪时依然活下来,提高对某些特别打包结构的识别精度。 - - **减少**(例如删掉 `win32`或`x86`):那些仍然在使用十年前引擎的老游戏,一旦其目录变得庞大(累计了几千个文件)并触发了大目录保护,其 `win32` 目录可能会被随机丢弃,从而彻底丧失被扫描到的机会。 diff --git a/docs/electron-structure.md b/docs/electron-structure.md deleted file mode 100644 index db9e5ea..0000000 --- a/docs/electron-structure.md +++ /dev/null @@ -1,97 +0,0 @@ -# Electron 主进程项目结构说明 - -本文档详细描述了 `electron/` 目录下的代码结构与模块功能。本项目采用 **SOA (面向服务架构)** 设计,将业务逻辑拆分为独立的服务模块。 - -## 目录树 - -``` -electron/ -├── common/ # [公共层] 跨模块共享的通用代码 -│ └── store.ts # 简单持久化存储封装 (基于 electron-store) -│ -├── db/ # [数据层] 数据库定义 -│ └── schema.ts # SQLite 数据库表结构定义 (Kysely Schema) -│ -├── main/ # [入口层] 主进程核心引导 -│ ├── bootstrap.ts # **启动引导**:环境检查、管理员权限校验、图标加载 -│ ├── index.ts # **应用入口**:负责 App 生命周期、服务组装 -│ ├── logger.ts # 日志系统:负责日志文件写入、轮转及向渲染进程广播日志 -│ ├── tray.ts # 托盘管理:系统托盘图标与菜单逻辑 -│ └── window.ts # 窗口管理:主窗口创建、配置与生命周期控制 -│ -├── preload/ # [桥接层] 预加载脚本 -│ └── index.ts # 暴露给渲染进程的 API 定义 (ContextBridge) -│ -├── services/ # [业务层] 核心业务逻辑服务 (Service) -│ ├── scanners/ # [扫描器] 游戏扫描具体实现 -│ │ ├── flat.ts # 通用目录扫描 (Epic/EA) -│ │ ├── microsoft.ts # Xbox/Microsoft Store 游戏扫描 (Registry/Manifest) -│ │ ├── steam.ts # Steam 库扫描 (libraryfolders.vdf) -│ │ ├── types.ts # 扫描结果类型定义 -│ │ └── utils.ts # 扫描工具函数 -│ ├── singbox/ # [核心] sing-box 内核管理 -│ │ ├── config.ts # 配置管理:校验配置、更新路由规则 -│ │ ├── constants.ts # 常量定义 -│ │ ├── index.ts # **SingBoxService**:服务入口,协调各模块 -│ │ ├── installer.ts # 安装器:负责内核下载与安装 -│ │ └── utils.ts # 工具函数 -│ ├── category.ts # 游戏分类服务:管理侧边栏分类数据 -│ ├── database.ts # 数据库服务:封装 SQLite 连接与基础 CRUD 操作 -│ ├── game-scanner.ts # 游戏扫描服务:统一入口,聚合 scanners 目录下的扫描逻辑 -│ ├── game.ts # 游戏管理服务:管理“我的游戏”列表、配置与状态 -│ ├── node.ts # 节点管理服务:管理代理节点 -│ ├── process.ts # 进程管理服务:提供进程树查找、父子进程分析能力 -│ ├── proxy-monitor.ts # 监控服务:实时监控游戏进程启动,自动触发加速路由 -│ ├── system.ts # 系统服务:提供 DNS 刷新、虚拟网卡重置、网络测试等底层能力 -│ └── updater.ts # 更新服务:检查 GitHub Releases 新版本 -│ -└── utils/ # [工具层] 通用工具函数库 - ├── command.ts # 命令行工具:封装 exec/spawn 为 Promise,支持超时控制 - ├── format.ts # 格式化工具:JSON 安全解析、URL 校验、类型转换 - ├── id.ts # ID 工具:统一的 UUID 生成器 - ├── ping.ts # 网络工具:实现 ICMP Ping 和 TCP Ping 延迟测试 - ├── port.ts # 端口工具:查找可用端口、检测端口占用 - └── process-helper.ts # 进程工具:进程名称标准化、跨平台路径处理、数组比较 -``` - -## 模块详细说明 - -### 1. 入口层 (`main/`) - -经过重构,入口层职责更加单一: - -- **`index.ts`**: 核心入口,负责组装各个模块,初始化服务。 -- **`bootstrap.ts`**: 处理应用启动前的环境准备,如强制管理员权限、处理 SQLite 原生模块错误。 -- **`window.ts`**: 封装了 `BrowserWindow` 的创建与配置,管理窗口 IPC 事件(最小化/关闭)。 -- **`tray.ts`**: 独立管理系统托盘逻辑。 - -### 2. 业务层 (`services/`) - -这是代码最集中的地方,每个文件对应一个具体的业务领域。 - -#### 核心服务:`singbox/` - -将原有的 `singbox.ts` 拆分为独立模块: - -- **`index.ts`**: 服务外观 (Facade),对外提供 `start`, `stop`, `restart` 接口。 -- **`installer.ts`**: 专注于二进制文件的下载、解压和安装逻辑。 -- **`config.ts`**: 专注于配置文件的生成、校验和动态规则更新。 - -#### 扫描服务:`game-scanner.ts` & `scanners/` - -- **`game-scanner.ts`**: 作为统一入口,对外暴露 `scanLocalGamesFromPlatforms`。 -- **`scanners/`**: 包含各平台的具体扫描实现: - - **`steam.ts`**: 解析 Steam 库文件。 - - **`microsoft.ts`**: 结合注册表和 AppxManifest 解析 Xbox 游戏。 - - **`flat.ts`**: 简单的目录遍历扫描 (Epic/EA)。 - -#### 监控服务:`proxy-monitor.ts` - -- 实现了智能进程捕获。它会轮询系统进程树,当发现已配置的游戏进程及其子进程启动时,自动通知 `singbox` 服务添加分流规则。 - -### 3. 工具层 (`utils/`) - -提炼了纯函数工具,不依赖具体业务逻辑,易于测试和复用。 - -- **`command.ts`**: 解决了 Node.js 原生 `exec` 在 Windows 下的一些编码和窗口隐藏问题。 -- **`process-helper.ts`**: 统一了全项目的进程名处理逻辑(如忽略大小写、去除 `.exe` 后缀),确保规则匹配的准确性。 diff --git a/docs/module-usage.md b/docs/module-usage.md new file mode 100644 index 0000000..b68180b --- /dev/null +++ b/docs/module-usage.md @@ -0,0 +1,423 @@ +# 模块说明与使用方法 + +## 1. 通用调用链 + +在 LagZero 中,推荐遵循下面这条调用链: + +```mermaid +flowchart LR + A["View / Component"] --> B["Store / Composable"] + B --> C["src/api"] + C --> D["window.*"] + D --> E["Electron IPC"] + E --> F["Service / Database / System"] +``` + +原则上: + +- 组件负责展示与交互 +- `store` 负责跨页面业务状态 +- `composable` 负责可复用逻辑 +- `src/api` 是渲染进程调用主进程的薄封装 +- `preload` 是唯一允许暴露主进程能力给渲染进程的地方 + +## 2. 前端模块 + +### 2.1 游戏模块 + +相关文件: + +- `src/views/library/index.vue` +- `src/views/dashboard/index.vue` +- `src/stores/games.ts` +- `src/utils/singbox-config.ts` + +职责: + +- 管理游戏库、当前选中游戏、运行状态、延迟与加速时长 +- 负责游戏加速的启动与停止 +- 根据节点与设置生成 sing-box 配置 +- 在进程模式下协调 `proxyMonitor` + +常用方法: + +- `init()`: 初始化游戏库 +- `setCurrentGame(id)`: 切换当前游戏 +- `addGame(game)`, `updateGame(game)`, `removeGame(id)`: 游戏 CRUD +- `startGame(id)`: 启动加速 +- `stopGame(id)`: 停止加速 +- `matchRunningGames(processNames)`: 根据进程名回填运行状态 +- `applySessionNetworkTuningChange()`: 当前正在加速时重启应用配置 + +示例: + +```ts + +``` + +使用建议: + +- 如果只是编辑游戏资料,用 `addGame` / `updateGame` +- 如果涉及启停 sing-box,一律走 `startGame` / `stopGame` +- 修改加速规则时,优先检查 `generateSingboxConfig()` 是否也要更新 + +### 2.2 节点模块 + +相关文件: + +- `src/views/nodes/index.vue` +- `src/components/node/*` +- `src/stores/nodes.ts` +- `src/utils/protocol.ts` + +职责: + +- 管理节点列表、筛选、排序、分组与多选 +- 导入/导出分享链接 +- 节点订阅刷新 +- 延迟测速与会话统计 + +常用方法: + +- `loadNodes()`: 从数据库加载节点 +- `saveNode(node)`: 保存节点 +- `addNodes(content)`: 从分享链接文本导入节点 +- `removeNode(id)`, `removeNodes(ids)`: 删除节点 +- `refreshSubscription(id)`: 手动刷新订阅 +- `runScheduledSubscriptions(reason)`: 按启动或手动场景执行订阅刷新 +- `checkNode(node, methodOverride?, context?)`: 测单个节点 +- `checkAllNodes()`: 批量测速 + +示例: + +```ts + +``` + +使用建议: + +- 页面层不要自己解析节点分享链接,统一复用 `addNodes` +- 订阅刷新默认会做去重,手动导入允许重复 +- 如果删除节点会影响当前加速中的游戏,`nodes` store 已内置停机兜底逻辑 + +### 2.3 本地代理模块 + +相关文件: + +- `src/stores/local-proxy.ts` +- `src/main.ts` + +职责: + +- 应用启动时自动拉起本地代理 +- 在可用节点中递归探测并选择健康节点 +- 节点变更后自动切换或恢复 +- 定时做本地代理健康检查 + +常用方法: + +- `startLocalProxy(reason?)` +- `stopLocalProxy()` +- `recheckLocalProxyHealth()` +- `handleNodeListChanged()` +- `applySettingsChange()` + +示例: + +```ts + +``` + +使用建议: + +- 不要在组件里直接拼测试端口、递归探测等流程,这些都已经封装在 store 中 +- 这个模块与游戏加速共用 sing-box 进程,改动前要确认不会破坏 `games` store 的启停流程 + +### 2.4 设置模块 + +相关文件: + +- `src/stores/settings.ts` +- `src/components/settings/*` +- `src/views/settings/index.vue` + +职责: + +- 持久化语言、主题、窗口关闭行为 +- 持久化 DNS、检测方式、本地代理、系统代理与 TUN 相关设置 +- 管理全局会话级网络调优参数 + +常用字段: + +- `language`, `theme`, `themeColor` +- `windowCloseAction` +- `checkInterval`, `checkMethod`, `checkUrl` +- `dnsMode`, `dnsPrimary`, `dnsSecondary`, `dnsBootstrap` +- `localProxyEnabled`, `localProxyPort` +- `accelNetworkMode`, `systemProxyPort`, `systemProxyBypass` +- `tunInterfaceName` +- `sessionNetworkTuning` + +常用方法: + +- `resetSessionNetworkTuning()` +- `applySessionNetworkProfilePreset(profile, options?)` + +示例: + +```ts + +``` + +### 2.5 游戏扫描模块 + +相关文件: + +- `src/composables/useGameScanner.ts` +- `electron/services/game-scanner.ts` +- `electron/services/scanners/*.ts` + +职责: + +- 调用主进程扫描本地游戏平台与本地快捷方式 +- 自动匹配分类并写入游戏库 +- 扫描运行进程并回填游戏运行状态 + +常用方法: + +- `scanGames()` +- `isScanning` +- `scanProgressText` + +示例: + +```ts + +``` + +### 2.6 托盘模块 + +相关文件: + +- `src/views/tray/index.vue` +- `electron/main/tray.ts` +- `src/layouts/MainLayout.vue` + +职责: + +- 展示当前游戏、延迟、丢包与加速时长 +- 提供快速启停、显示主窗口与退出应用操作 +- 与主窗口通过托盘状态快照同步 + +注意点: + +- 托盘页走 `#/tray` +- `src/main.ts` 对托盘窗口做了特判,不会初始化主窗口的本地代理监听逻辑 + +## 3. Electron 主进程模块 + +### 3.1 `DatabaseService` + +文件:`electron/services/database.ts` + +职责: + +- 初始化 SQLite 数据库 +- 管理 `nodes`、`games`、`categories` 等核心数据 +- 做数据迁移、默认分类补齐、分类与标签冲突修复 + +建议: + +- 业务数据落库优先经过这个服务 +- `GameService` / `NodeService` / `CategoryService` 只是它的 IPC 薄封装 + +### 3.2 `SingBoxService` + +文件:`electron/services/singbox/index.ts` + +职责: + +- 下载和校验 sing-box 二进制 +- 启动、停止、重启 sing-box 进程 +- 采集日志并转发到渲染进程 +- 处理进程路由规则更新 + +对应 IPC: + +- `singbox-start` +- `singbox-stop` +- `singbox-restart` +- `singbox-ensure-core` +- `singbox-get-install-info` + +### 3.3 `SystemService` + +文件:`electron/services/system.ts` + +职责: + +- `ping` / `tcpPing` +- DNS 刷新 +- TUN 网卡重装 +- 系统代理设置与恢复 +- 本地 HTTP 代理连通性测试 +- 主进程代理 HTTP 请求 + +适用场景: + +- 节点测速 +- 本地代理健康检查 +- 系统代理模式切换 +- 网络诊断工具 + +### 3.4 `ProxyMonitorService` + +文件:`electron/services/proxy-monitor.ts` + +职责: + +- 按游戏进程名轮询进程树 +- 找出链式拉起的子进程 +- 将新发现的子进程同步给 sing-box 动态代理 + +适用场景: + +- `proxyMode = 'process'` +- `chainProxy = true` + +### 3.5 `GameScannerService` + +文件:`electron/services/game-scanner.ts` + +职责: + +- 并发调用多个平台扫描器 +- 去重安装目录和进程名 +- 提供目录扫描能力给“选择文件夹导入进程”功能 + +当前已接入平台: + +- Steam +- Microsoft +- Epic +- EA +- BattleNet +- WeGame +- Local shortcut + +### 3.6 `WindowManager` 与 `TrayManager` + +文件: + +- `electron/main/window.ts` +- `electron/main/tray.ts` + +职责: + +- `WindowManager`: 主窗口创建、窗口关闭行为管理、开发者工具、主窗口 IPC +- `TrayManager`: 托盘图标、托盘浮窗、显示主窗口、退出应用 + +注意点: + +- 关闭按钮行为可配置为 `ask / minimize / quit` +- 托盘浮窗是独立 `BrowserWindow`,不是原生菜单 + +## 4. 渲染进程与主进程之间怎么接 + +推荐固定模板: + +1. `electron/services/*` 或 `electron/main/index.ts` 注册 IPC +2. `electron/preload/index.ts` 通过 `contextBridge.exposeInMainWorld` 暴露 +3. `src/api/*.ts` 包装成统一调用方法 +4. `src/stores/*` 或 `src/composables/*` 负责消费 +5. `src/views/*` / `src/components/*` 只调用上层封装 + +示例路径: + +```text +src/views/nodes/index.vue + -> src/stores/nodes.ts + -> src/api/nodes.ts + -> window.nodes.* + -> ipcMain.handle('nodes:*') + -> electron/services/node.ts + -> electron/services/database.ts +``` + +## 5. 扩展建议 + +### 新增一个 IPC 能力 + +最推荐的文件落点: + +- 主进程逻辑:`electron/services/xxx.ts` +- 桥接层:`electron/preload/index.ts` +- 渲染进程 API:`src/api/xxx.ts` +- 业务状态:`src/stores/xxx.ts` 或 `src/composables/useXxx.ts` + +### 新增一个共享数据结构 + +最推荐的文件落点: + +- `shared/types/*.ts` +- 渲染进程 re-export:`src/types/index.ts` + +### 新增一个系统级功能 + +优先判断是否属于下面其中一种: + +- 文件系统、网络诊断、端口检查、系统代理:加到 `SystemService` +- sing-box 生命周期和配置校验:加到 `SingBoxService` +- 业务数据 CRUD:加到 `DatabaseService` +- 游戏平台扫描:加到 `GameScannerService` 或 `scanners/` + +## 6. 维护时最容易踩坑的点 + +- 直接在组件里调用 `window.*`,会让调用链分散,后期难维护 +- 修改节点结构却忘了同步 `shared/types`、数据库和协议解析 +- 只改游戏加速逻辑,没考虑本地代理复用同一 sing-box 进程 +- 给托盘页加主窗口初始化逻辑,导致托盘窗口触发多余副作用 +- 在 `shared/` 里引入 Electron 或 Vue,导致跨进程复用失败 diff --git a/docs/project-structure.md b/docs/project-structure.md new file mode 100644 index 0000000..8e3f054 --- /dev/null +++ b/docs/project-structure.md @@ -0,0 +1,205 @@ +# LagZero 目录结构 + +## 1. 说明 + +下面的目录树是面向开发的精简版,省略了以下内容: + +- 构建产物:`dist/`、`dist-electron/`、`release/` +- 依赖目录:`node_modules/` +- 本地 AI/IDE 辅助目录:`.agent/`、`.agents/`、`.codex/`、`.qoder/`、`.trae/` + +## 2. 目录树 + +```text +LagZero +├─ docs/ +├─ docImages/ +├─ electron/ +│ ├─ common/ +│ │ └─ store.ts +│ ├─ db/ +│ │ └─ schema.ts +│ ├─ main/ +│ │ ├─ bootstrap.ts +│ │ ├─ index.ts +│ │ ├─ logger.ts +│ │ ├─ tray.ts +│ │ └─ window.ts +│ ├─ preload/ +│ │ └─ index.ts +│ ├─ services/ +│ │ ├─ scanners/ +│ │ │ ├─ battlenet.ts +│ │ │ ├─ ea.ts +│ │ │ ├─ epic.ts +│ │ │ ├─ local.ts +│ │ │ ├─ microsoft.ts +│ │ │ ├─ steam.ts +│ │ │ ├─ types.ts +│ │ │ ├─ utils.ts +│ │ │ └─ wegame.ts +│ │ ├─ singbox/ +│ │ │ ├─ config.ts +│ │ │ ├─ constants.ts +│ │ │ ├─ index.ts +│ │ │ ├─ installer.ts +│ │ │ └─ utils.ts +│ │ ├─ category.ts +│ │ ├─ database.ts +│ │ ├─ game-scanner.ts +│ │ ├─ game.ts +│ │ ├─ node.ts +│ │ ├─ process.ts +│ │ ├─ proxy-monitor.ts +│ │ ├─ system.ts +│ │ └─ updater.ts +│ └─ utils/ +│ ├─ command.ts +│ ├─ id.ts +│ ├─ ping.ts +│ └─ port.ts +├─ public/ +│ ├─ logo.ico +│ ├─ logo.png +│ └─ logo.svg +├─ shared/ +│ ├─ types/ +│ │ ├─ category.ts +│ │ ├─ game.ts +│ │ ├─ index.ts +│ │ ├─ node.ts +│ │ ├─ settings.ts +│ │ └─ singbox.ts +│ └─ utils/ +│ ├─ format.ts +│ ├─ index.ts +│ ├─ ipc-safe.ts +│ ├─ node-key.ts +│ ├─ process-name.ts +│ └─ sleep.ts +├─ src/ +│ ├─ api/ +│ ├─ assets/ +│ ├─ autoImport/ +│ ├─ components/ +│ │ ├─ common/ +│ │ ├─ dashboard/ +│ │ ├─ library/ +│ │ ├─ node/ +│ │ ├─ settings/ +│ │ └─ singbox/ +│ ├─ composables/ +│ ├─ constants/ +│ ├─ layouts/ +│ ├─ locales/ +│ ├─ router/ +│ ├─ stores/ +│ ├─ types/ +│ ├─ utils/ +│ ├─ views/ +│ │ ├─ dashboard/ +│ │ ├─ library/ +│ │ ├─ nodes/ +│ │ ├─ settings/ +│ │ └─ tray/ +│ ├─ App.vue +│ ├─ i18n.ts +│ └─ main.ts +├─ tests/ +│ └─ unit/ +├─ package.json +├─ README.md +├─ uno.config.ts +├─ vite.config.ts +└─ vitest.config.ts +``` + +## 3. 关键目录职责 + +### `electron/` + +Electron 主进程代码。这里负责: + +- 应用启动与窗口生命周期 +- 托盘窗口与主窗口通信 +- IPC 注册 +- 数据库存取 +- 游戏扫描 +- 系统命令、系统代理、TUN 与 DNS 控制 +- sing-box 的安装、启动、停止、重启与日志转发 + +### `shared/` + +跨进程共享层。这里应该只放“纯 TypeScript”代码: + +- 公共类型 +- 字符串/对象/数组等纯工具函数 +- 进程名规范化、节点 key 计算、IPC 安全快照转换 + +如果一个文件需要同时在 `src/` 和 `electron/` 使用,优先考虑放到这里。 + +### `src/` + +Vue 渲染进程代码。这里负责: + +- 页面和组件 +- Pinia 状态管理 +- 路由组织 +- i18n、多主题、样式 +- sing-box 配置生成 +- 通过 `src/api/` 调用 preload 暴露的主进程能力 + +### `tests/unit/` + +Vitest 单元测试目录,当前重点覆盖: + +- 配置生成 +- 扫描工具 +- 协议解析 +- 代理监控 +- UI 主题和局部业务逻辑 + +## 4. 重点文件速查 + +| 文件 | 作用 | +| --- | --- | +| `electron/main/index.ts` | 主进程总入口,服务实例化和 IPC 汇总注册 | +| `electron/preload/index.ts` | ContextBridge 暴露层,定义 `window.*` API | +| `src/main.ts` | 渲染进程入口,挂载 router/pinia/i18n,并处理主窗口初始化逻辑 | +| `src/router/index.ts` | 主窗口与托盘窗口路由定义 | +| `src/stores/games.ts` | 游戏加速主流程入口 | +| `src/stores/nodes.ts` | 节点管理、测速、订阅刷新与导入导出 | +| `src/stores/local-proxy.ts` | 本地代理自动选点、健康检查与自动恢复 | +| `src/stores/settings.ts` | 绝大多数设置项的持久化来源 | +| `src/utils/singbox-config.ts` | sing-box 配置生成核心 | +| `electron/services/database.ts` | SQLite 与业务数据落库核心 | + +## 5. 推荐阅读顺序 + +### 想看应用怎么启动 + +1. `electron/main/index.ts` +2. `electron/main/window.ts` +3. `electron/preload/index.ts` +4. `src/main.ts` + +### 想看加速链路怎么跑通 + +1. `src/views/dashboard/index.vue` +2. `src/stores/games.ts` +3. `src/utils/singbox-config.ts` +4. `electron/services/singbox/index.ts` +5. `electron/services/proxy-monitor.ts` + +### 想看节点与订阅 + +1. `src/views/nodes/index.vue` +2. `src/stores/nodes.ts` +3. `electron/services/node.ts` +4. `electron/services/database.ts` + +### 想看游戏扫描 + +1. `src/composables/useGameScanner.ts` +2. `electron/services/game-scanner.ts` +3. `electron/services/scanners/*.ts` diff --git a/docs/singbox-config.md b/docs/singbox-config.md deleted file mode 100644 index c4b5ec0..0000000 --- a/docs/singbox-config.md +++ /dev/null @@ -1,54 +0,0 @@ -# Singbox 配置生成工具说明文档 - -该模块 (`src/utils/singbox-config.ts`) 负责根据用户选择的游戏规则和节点信息生成 Sing-box 核心能够识别的 JSON 配置文件。 - -## 主要功能 - -1. **多协议支持**:支持 Shadowsocks, VMess, VLESS, Trojan, SOCKS, HTTP 等主流代理协议。 -2. **传输层配置**:支持 WebSocket (WS) 和 gRPC 等传输方式。 -3. **TLS/REALITY**:支持标准的 TLS 配置,并集成了 REALITY 协议支持。 -4. **代理模式切换**: - - **进程模式 (Process Mode)**:仅对指定的应用程序进程进行加速,其余流量直连。 - - **路由模式 (Routing Mode)**:支持“全局代理”或“绕过中国大陆”规则。 -5. **安全 DNS**:支持 DoH/DoT 安全 DNS 查询,防止 DNS 污染。 -6. **TUN 网卡集成**:自动配置 TUN 虚拟网卡,实现透明代理。 - -## 核心接口 - -### `generateSingboxConfig(game, node, dnsOptions?)` - -这是该模块的主入口函数。 - -- **参数**: - - `game`: `Game` 类型,包含代理模式、路由规则以及需要加速的进程名称列表。 - - `node`: `NodeConfig` 类型,包含服务器地址、端口、协议参数等。 - - `dnsOptions`: `DnsConfigOptions` 类型,可选配置 DNS 模式及自定义 DNS 地址。 -- **返回值**: 格式化后的 Sing-box JSON 字符串。 - -## 路由逻辑说明 - -### 进程模式 - -在该模式下,程序会生成基于 `process_name` 的路由规则。只有匹配到游戏进程名的流量才会被导向 `proxy` 出口,默认规则为 `direct`(直连)。 - -### 路由模式 - -在该模式下,默认出口设为 `proxy`。 - -- 如果启用了 `bypass_cn` (绕过中国大陆),程序会添加一系列针对私有 IP、`.cn` 后缀域名以及常见国内域名(如 qq.com, baidu.com 等)的直连规则。 - -## DNS 逻辑 - -模块默认配置了以下 DNS 策略: - -- **远端 DNS (`remote-primary`)**: 默认使用 Google DNS 或 Cloudflare DNS,通过 `proxy` 链路进行加密查询。 -- **本地 DNS (`local`)**: 用于解析直连域名的系统默认 DNS。 -- 当开启 `secure` 模式时,指定加速的进程会强制使用远端 DNS 解析,以确保获取最准确的加速 IP。 - -## 进程名标准化 - -模块内部包含 `normalizeProcessNames` 函数,它会自动: - -1. 去除进程路径,仅保留文件名(例如 `C:\Games\Game.exe` -> `Game.exe`)。 -2. 处理 Windows 路径风格。 -3. 自动生成小写版本的文件名,以处理部分系统的大小写敏感问题,增强兼容性。 diff --git a/docs/src-structure.md b/docs/src-structure.md deleted file mode 100644 index dc9c13f..0000000 --- a/docs/src-structure.md +++ /dev/null @@ -1,92 +0,0 @@ -# Frontend (Vue) 项目结构说明 - -本文档详细描述了 `src/` 目录下的代码结构与模块功能。本项目采用 **Vue 3 + TypeScript + Vite** 技术栈,使用 **Composition API** 和 **Pinia** 进行状态管理。 - -## 目录树 - -``` -src/ -├── api/ # [接口层] 后端通信接口 (IPC 封装) -│ ├── index.ts # 统一导出所有 API 模块 -│ └── *.ts # 各业务模块 API (如 games.ts, nodes.ts, singbox.ts) -│ -├── assets/ # [资源层] 静态资源文件 -│ ├── main.css # 全局样式入口 -│ └── style.css # 基础样式定义 -│ -├── autoImport/ # [自动导入] 自动生成的类型声明 -│ ├── auto-imports.d.ts # 自动导入函数的类型声明 -│ └── components.d.ts # 自动导入组件的类型声明 -│ -├── components/ # [组件层] Vue 组件 -│ ├── common/ # 通用基础组件 (图标选择器、主题切换等) -│ ├── dashboard/ # 仪表盘相关组件 (图表、节点选择器) -│ ├── library/ # 游戏库相关组件 (分类管理、编辑弹窗) -│ ├── node/ # 节点管理相关组件 (节点卡片、编辑/导入弹窗) -│ └── settings/ # 设置页面相关组件 (侧边栏、各设置模块) -│ -├── composables/ # [逻辑层] 组合式函数 (Hooks) -│ ├── useAppUpdater.ts # 应用更新逻辑 -│ ├── useFilePicker.ts # 文件选择逻辑 -│ ├── useGameScanner.ts # 游戏扫描逻辑 -│ └── useTheme.ts # 主题切换逻辑 -│ -├── constants/ # [常量层] 全局常量定义 -│ └── index.ts # 常量统一导出 -│ -├── layouts/ # [布局层] 页面布局组件 -│ └── MainLayout.vue # 主布局 (侧边栏 + 内容区) -│ -├── locales/ # [国际化] i18n 语言包 -│ ├── en-US.json # 英文翻译 -│ └── zh-CN.json # 中文翻译 -│ -├── router/ # [路由层] 路由配置 -│ └── index.ts # Vue Router 配置 (定义路由表) -│ -├── stores/ # [状态层] Pinia 状态管理 -│ ├── index.ts # Pinia 实例导出 -│ ├── games.ts # 游戏数据状态 -│ ├── nodes.ts # 节点数据状态 -│ ├── settings.ts # 应用设置状态 -│ └── local-proxy.ts # 本地代理状态 -│ -├── types/ # [类型层] TypeScript 类型定义 -│ ├── electron.d.ts # Electron API 类型扩展 -│ └── index.ts # 核心业务类型定义 (Game, NodeConfig 等) -│ -├── utils/ # [工具层] 通用工具函数 -│ ├── latency-session.ts # 延迟测试会话管理 -│ ├── protocol.ts # 代理协议解析工具 (VMess, SS, VLESS 等) -│ ├── runtime-logger.ts # 运行时日志捕获工具 -│ └── singbox-config.ts # sing-box 配置文件生成器 -│ -├── views/ # [视图层] 页面级组件 -│ ├── dashboard/ # 仪表盘页面 -│ ├── library/ # 游戏库页面 -│ ├── nodes/ # 节点列表页面 -│ └── settings/ # 设置中心页面 -│ -├── App.vue # 应用根组件 -├── main.ts # 应用入口文件 (挂载 Vue, Pinia, Router) -└── vite-env.d.ts # Vite 环境类型声明 -``` - -## 模块详细说明 - -### 1. 接口层 (`api/`) -- **IPC 封装**: 所有与 Electron 主进程的通信都通过 `window.electron` 等预加载脚本暴露的对象进行。 -- **模块化**: 每个文件对应后端的 Service 模块,例如 `singbox.ts` 对应后端的 `SingboxService`。 - -### 2. 状态层 (`stores/`) -- **`games.ts`**: 管理本地游戏列表、当前选中游戏、加速状态。 -- **`nodes.ts`**: 管理节点列表、节点延迟测试结果。 -- **`settings.ts`**: 持久化存储用户设置(语言、主题、DNS 模式等)。 - -### 3. 工具层 (`utils/`) -- **`protocol.ts`**: 核心协议解析逻辑,负责将分享链接 (vmess://, ss://) 解析为标准节点配置对象。 -- **`singbox-config.ts`**: 根据当前游戏规则和选中的节点,动态生成 sing-box 的 JSON 配置文件。 - -### 4. 逻辑层 (`composables/`) -- **Composition API**: 封装可复用的业务逻辑,例如 `useTheme.ts` 处理深色模式切换和主题色应用。 -- **`useGameScanner.ts`**: 协调前端 UI 和后端扫描接口,处理扫描进度和结果展示。 diff --git a/package.json b/package.json index c2b90d7..ffbcaa9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "lagzero", "productName": "LagZero", "private": true, - "version": "0.2.0", + "version": "0.2.1", "main": "dist-electron/index.js", "type": "module", "author": "LagZero Team",