docs: Add new documentation files and update the package version to 0.2.1.

This commit is contained in:
ZenEcho committed 2026-03-27 11:07:44 +08:00
1 parent 3cf582e71b
commit 0a5b1780da
9 files changed
+831 -823

No files matched your search

+45
View File
@@ -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 或设置项,建议同步更新这组文档。
+157
View File
@@ -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 与系统代理两种模式切换
- 本地代理自动选点与健康检查
- 托盘状态同步、主窗口关闭行为、应用重置
-579
View File
@@ -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/<platform>.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` 目录可能会被随机丢弃,从而彻底丧失被扫描到的机会。
-97
View File
@@ -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` 后缀),确保规则匹配的准确性。
+423
View File
@@ -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
<script setup lang="ts">
import { useGameStore } from '@/stores/games'
const gameStore = useGameStore()
async function onStart(gameId: string) {
await gameStore.startGame(gameId)
}
async function onStop(gameId: string) {
await gameStore.stopGame(gameId)
}
</script>
```
使用建议:
- 如果只是编辑游戏资料,用 `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
<script setup lang="ts">
import { useNodeStore } from '@/stores/nodes'
const nodeStore = useNodeStore()
await nodeStore.loadNodes()
await nodeStore.checkAllNodes()
const importedCount = await nodeStore.addNodes(shareLinksText)
console.log('imported:', importedCount)
</script>
```
使用建议:
- 页面层不要自己解析节点分享链接,统一复用 `addNodes`
- 订阅刷新默认会做去重,手动导入允许重复
- 如果删除节点会影响当前加速中的游戏,`nodes` store 已内置停机兜底逻辑
### 2.3 本地代理模块
相关文件:
- `src/stores/local-proxy.ts`
- `src/main.ts`
职责:
- 应用启动时自动拉起本地代理
- 在可用节点中递归探测并选择健康节点
- 节点变更后自动切换或恢复
- 定时做本地代理健康检查
常用方法:
- `startLocalProxy(reason?)`
- `stopLocalProxy()`
- `recheckLocalProxyHealth()`
- `handleNodeListChanged()`
- `applySettingsChange()`
示例:
```ts
<script setup lang="ts">
import { useLocalProxyStore } from '@/stores/local-proxy'
const localProxyStore = useLocalProxyStore()
async function onProxySettingsChanged() {
await localProxyStore.applySettingsChange()
}
</script>
```
使用建议:
- 不要在组件里直接拼测试端口、递归探测等流程,这些都已经封装在 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
<script setup lang="ts">
import { useSettingsStore } from '@/stores/settings'
const settingsStore = useSettingsStore()
settingsStore.accelNetworkMode = 'tun'
settingsStore.applySessionNetworkProfilePreset('aggressive', {
isCurrentNodeVless: true
})
</script>
```
### 2.5 游戏扫描模块
相关文件:
- `src/composables/useGameScanner.ts`
- `electron/services/game-scanner.ts`
- `electron/services/scanners/*.ts`
职责:
- 调用主进程扫描本地游戏平台与本地快捷方式
- 自动匹配分类并写入游戏库
- 扫描运行进程并回填游戏运行状态
常用方法:
- `scanGames()`
- `isScanning`
- `scanProgressText`
示例:
```ts
<script setup lang="ts">
import { useGameScanner } from '@/composables/useGameScanner'
const { isScanning, scanProgressText, scanGames } = useGameScanner()
</script>
```
### 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,导致跨进程复用失败
+205
View File
@@ -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`
-54
View File
@@ -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. 自动生成小写版本的文件名,以处理部分系统的大小写敏感问题,增强兼容性。
-92
View File
@@ -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 和后端扫描接口,处理扫描进度和结果展示。
+1 -1
View File
@@ -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",