eSearch 开发指南:基于 Electron + electron-vite 的跨平台识屏工具源码结构解析
【免费下载链接】eSearch截屏 离线OCR 搜索翻译 以图搜图 贴图 录屏 万向滚动截屏 屏幕翻译 Screenshot Offline OCR Search Translate Search for picture Paste the picture on the screen Screen recorder Omnidirectional scrolling screenshot Screen translator 支持Windows Linux macOS项目地址: https://gitcode.com/GitHub_Trending/es/eSearch
导读
本文是 eSearch 开源项目(仓库根目录 AGENTS.md)的完整开发指南,面向希望理解或参与该项目开发的工程师与研究者。eSearch 是一个基于 Electron 的跨平台桌面应用,覆盖截屏、离线 OCR、搜索、翻译、贴图、屏幕翻译、以图搜图、滚动截屏、录屏等能力。读完本文,你将掌握 eSearch 的技术栈与常用命令、多页面渲染进程的目录结构、基于dkh-ui的界面开发方式、类型安全的进程间通信(IPC)机制、设置项的新增流程,以及一套完整的国际化翻译工作流。
一、项目概述与技术栈
1.1 项目定位
根据 AGENTS.md 的描述,eSearch 是一个基于 Electron 的跨平台桌面应用,功能涵盖:截屏(截图)、OCR(文字识别)、搜索、翻译、贴图、屏幕翻译、以图搜图、滚动截屏、录屏。从 package.json 可见其作者自述为「识屏 · 搜索」,当前仓库版本为 15.5.1,许可证为 GPL-3.0,包管理器固定为pnpm@10.17.0。
1.2 技术栈清单
AGENTS.md 明确列出的技术栈为:
- 框架:Electron + electron-vite(主进程打包由 electron-vite 驱动,参见 electron.vite.config.ts)
- 语言:TypeScript(含
src/ShareTypes.d.ts这类全局共享类型声明) - 包管理器:pnpm(仓库同时提供
pnpm-workspace.yaml与pnpm-lock.yaml) - 代码规范:Biome(同时承担 lint 与 format)
- 测试:Vitest(仓库中存在
src/renderer/lib/isDeepStrictEqual.test.ts与src/renderer/screenShot/test/waylandShot.test.ts等测试文件)
从 package.json 的 dependencies 可以看到支撑各功能的核心依赖,这些与 AGENTS.md 描述的功能一一对应:
| 功能领域 | 关键依赖 | 说明 |
|---|---|---|
| 截屏 | node-screenshots、@xushengfeng/...平台原生依赖 | 提供跨平台截屏能力,optionalDependencies 中为 win/darwin/linux 各架构准备了预编译产物 |
| OCR | esearch-ocr、onnxruntime-node、esearch-seg | 离线 OCR 推理与图像分割 |
| 翻译 | xtranslator | 多种翻译引擎接入 |
| 录屏/视频 | mediabunny、gifenc | 视频处理与 GIF 编码 |
| 界面 | dkh-ui、fabric、@erase2d/fabric | UI 组件库与画布编辑(图片/视频编辑器) |
| 其他 | hotkeys-js(快捷键)、uiohook-napi(全局鼠标键盘钩子)、qr-scanner-wechat(二维码)、picture_match(以图搜图) | 支撑快捷键、屏幕翻译取词等 |
二、常用命令与构建流程
AGENTS.md 给出了最核心的五条命令。结合 package.json 中的 scripts,可整理出完整的命令矩阵:
# 安装依赖(使用 pnpm) pnpm install # 开发模式(electron-vite dev,带 HMR) pnpm run dev # 构建(electron-vite build,产物输出到 out/) pnpm run build # 预览构建产物 pnpm run start # 打包(electron-builder 生成安装包,-p never 表示不上传) pnpm run distpackage.json 中还有几条 AGENTS.md 未列出但同样常用的脚本,属于「开发流程」环节的补充:
# 打包但不生成安装器(electron-builder --dir),用于本地快速验证 pnpm run pack # 类型检查:基于 tsconfig 的 project build,--noEmit --force 强制执行全量检查 pnpm run typecheck # 代码格式化:Biome 直接写回 src/ 目录 pnpm run format # 代码检查:Biome check 校验 src/(lint + 格式) pnpm run lint # 强格式化:Biome check --write,会自动整理 import 顺序 pnpm run fix # 打包体积分析(electron-vite preview --mode analyze) pnpm run ana # UI 测试(使用独立的 electron.vite.config_test.ts 配置) pnpm run uitest需要特别说明的是,dist与pack都依赖electron-builder的 electron-builder.config.js 配置文件,且dist与pack会先执行build。开发者模式还支持命令行参数-d、环境变量ESEARCH_DEV或设置项dev自动开启(见 src/main/main.ts)。
三、项目结构:主进程与多页面渲染进程
3.1 总体布局
AGENTS.md 将项目结构分为三块:src/main/(Electron 主进程)、src/renderer/(渲染进程,内含多个功能页面)、src/ShareTypes.d.ts(共享类型定义)。此外仓库根目录还有lib/(供主进程与渲染进程共用的公共库)与assets/(Logo、图标、桌面文件等资源)。
从 electron.vite.config.ts 的rollupOptions.input可以看到渲染进程实际是一个多页面应用(MPA),共注册了 12 个 HTML 入口:editor、clip、setting、ding、recorder、recorderTip、browser_bg、translator、translate、photoEditor、videoEditor、aiVision。这与 AGENTS.md 列出的页面一一对应。
3.2 主进程(src/main/)
- src/main/main.ts:Electron 主进程入口(package.json 的
main字段指向./out/main/main.js)。该文件承担窗口创建、全局快捷键注册、系统托盘、用户数据路径解析(支持--userData参数、preload_config文件以及portable便携目录)、Store 初始化等职责。
3.3 渲染进程功能页面(src/renderer/)
按 AGENTS.md 的划分:
| 目录 | 功能 | 说明 |
|---|---|---|
aiVision/ | AI 识图 | 作为主页面(editor)的子页面 |
clip/ | 截屏 | 截图窗口逻辑 |
editor/ | 主页面 | 应用的聚合主界面 |
ding/ | 贴图 | 屏幕贴图,同时承载贴图翻译 |
setting/ | 设置 | 设置窗口 |
photoEditor/ | 高级图片编辑 | 独立图片编辑器 |
recorder/ | 普通录屏 | 基础屏幕录制 |
recorderTip/ | 录屏覆盖层 | 显示倒计时、结束提示等浮层 |
translate/ | 翻译 | 展示不同翻译器结果,作为主页面的子页面 |
translator/ | 屏幕翻译 | 屏幕区域实时翻译 |
videoEditor/ | 高级录屏 | 含鼠标跟踪、视频编辑 |
root/ | 界面样式定义 | 全局样式与主题 |
ocr/ | OCR 相关 | 离线/在线 OCR 引擎封装 |
screenShot/ | 截屏库 | 跨平台截屏实现(含 Wayland 适配) |
此外 AGENTS.md 还提及lib/属于「杂项公共功能」目录。结合仓库源码,lib/实际是主进程与渲染进程共享的关键基础设施,包括:
lib/ipc.ts:进程间通信的类型安全封装(详见下文第四节)lib/store/:设置存储(store.ts、parse.ts、renderStore.ts),实现基于点路径的读写与类型推导lib/translate/:国际化翻译工具链(source.json原始文本、各语言 JSON、tool.js命令行工具)lib/key.ts、lib/time_format.ts、lib/utils.ts等工具模块
3.4 共享类型(src/ShareTypes.d.ts)
src/ShareTypes.d.ts是整个项目的类型中枢,定义了setting(全部设置项的树状结构)、功能(工具枚举)、MainWinType、translateWinType、DingStart、DingResize等类型。主进程、渲染进程与lib/store都从它导入类型,例如 lib/store/store.ts 与 src/renderer/setting/setting.ts 均import type { setting }。新增设置项的第一步就是在该文件中扩展setting类型(详见第五节)。
四、开发流程规范:格式、类型与检查
AGENTS.md 明确规定了质量门槛:
ts 修改都需要 biome 格式化(
pnpm run format)和 ts 类型检查(pnpm run typecheck),还要(pnpm run lint);新文件可以pnpm run fix进行更强格式化和引入重排。
从 biome.json 可以看到具体规则:indentStyle: space、indentWidth: 4(缩进为 4 空格);organizeImports开启(即fix会重排 import);linter 启用 recommended 规则集,并额外开启了useDateNow、useValidForDirection两条错误级规则,同时关闭了noNonNullAssertion(允许非空断言)。也就是说:
- 日常修改:
pnpm run format(格式化)→pnpm run typecheck(类型)→pnpm run lint(静态检查) - 新增文件:改用
pnpm run fix,一步完成格式化 + import 排序
五、界面开发:dkh-ui 与单文件页面
AGENTS.md 指出界面开发采用dkh-ui创建、修改 DOM 与 CSS,且「单 ts 文件覆盖界面绘制」——每个页面是一个 TS 文件配合对应的 HTML 入口(如setting.ts+setting.html),页面逻辑不依赖框架组件树。
dkh-ui已作为正式依赖声明在 package.json(版本^0.14.2)。以设置页 src/renderer/setting/setting.ts 为例,其导入了一整套 UI 构建函数:
import { ele, input, select, textarea, radioGroup, dynamicList, ... } from "dkh-ui";AGENTS.md 还特别提醒:「如果修改文本,需要修改翻译」——所有面向用户的文案都必须走国际化流程(见第七节),否则会在控制台出现翻译缺失的提示。
六、进程交互:lib/ipc.ts 的类型安全通信
AGENTS.md 对进程交互的描述是:页面与主进程交互,lib/ipc.ts添加了类型约束,所有消息都登记在Message变量上。这实际上是本项目中设计最精巧的基础设施之一,值得深入讲解。
6.1 Message 类型契约
lib/ipc.ts 定义了Message类型——一个以消息名为键、以函数签名为值的映射表。每个键对应一种消息,参数类型和返回值类型都在这里声明。例如:
type Message = { clip_show: () => void; // 无参、无返回值 clip_save: (ext: string) => string; // 返回保存路径(同步) clip_ding: (img: string, type: "translate" | "ding", rect: { w: number; h: number; x: number; y: number }) => void; hotkey: ((type: "快捷键", name: keyof setting["快捷键"], key: string) => boolean) | ((type: "快捷键2", name: 功能, key: string) => boolean); // ... 共约 60 条消息 };借助Parameters<Message[K]>、ReturnType<Message[K]>等内置工具类型,底层 API 的参数与返回值类型全部由Message推导,从而保证主进程与渲染进程两端签名严格一致。
6.2 四个方向的通信 API
lib/ipc.ts导出的核心函数及其语义如下:
| 函数 | 方向 | 语义 |
|---|---|---|
mainSend(webContents, key, data) | 主进程 → 指定页面 | 向某个WebContents发送消息 |
renderOn(key, callback) | 页面接收 | 页面注册监听,等待主进程消息 |
renderSend(key, data) | 页面 → 主进程 | 页面发送异步消息 |
renderSendSync(key, data) | 页面 → 主进程(同步) | 等待主进程返回(用于获取路径、设置值等) |
mainOn(key, callback) | 主进程接收 | 主进程注册监听,callback 可同步或异步返回结果 |
mainOnReflect(key, callback) | 渲染进程间中转 | 主进程将消息转发给 callback 返回的一组WebContents,实现页面间广播 |
从源码实现看(lib/ipc.ts),两端统一监听名为ipc的通道,消息以(key, data)二元组传递;renderSendSync走ipcRenderer.sendSync,主进程侧通过设置event.returnValue回传结果。mainOnReflect专门用于「渲染进程之间的通信,主进程起中转作用」的场景,并借助VoidKeys<Message>类型约束只允许转发无返回值的消息。
6.3 与设置存储的关系
主进程在 src/main/main.ts 中另注册了store通道,支持get / set / path / getAll / setAll五种操作。渲染进程侧的封装见 lib/store/renderStore.ts:store.get使用sendSync同步读取,store.set使用异步send写入。这是下一节「添加设置」的底层通道。
七、添加设置项的完整流程
AGENTS.md 给出的最小流程是:在src/ShareTypes.d.ts的setting变量中添加设置项,再用store.get('a.b.c')/store.set('a.b.c', v)读写。项目的 设置文档 进一步细化了这一流程,可总结为以下五步:
7.1 第一步:扩展类型定义
在 src/ShareTypes.d.ts 的setting类型中新增字段。设置项以点路径组织(如语言.语言、快捷键.截屏)。类型定义是整个链路的地基——lib/store会从setting推导出SettingPath与GetValue:
// lib/store/renderStore.ts 中的核心类型推导 type Paths<T> = T extends object ? { [K in keyof T]-?: `${K}` | Join<K, Paths<T[K]>> }[keyof T] : never; type SettingPath = Paths<setting>; type GetValue<T, P extends string> = ...; // 递归解析出路径对应的值类型renderStore.ts注释中明确写着「使用类型映射和条件类型来解析路径」。这意味着store.get('a.b.c')的路径和返回类型在编译期就是受检的——写错路径名或类型会直接报类型错误。
7.2 第二步:在设置页面添加 UI
在 src/renderer/setting/setting.ts 中,为设置项创建el渲染函数,返回的元素应使用dkh-ui创建,且sv(设置值)、gv(获取值)的类型要与设置类型匹配。设置文档列出的常用 UI 构件:
| 构件 | 用途 |
|---|---|
xNumber | 数值输入 |
xSwitch | 开关(gv类型兼容boolean) |
xColor | 颜色选择 |
xPath | 路径选择 |
xSecret | 密文/密钥输入 |
xFont | 字体选择 |
sortList | 可排序列表 |
dialogB | 对话框按钮 |
xGroup | 仅用于排版布局(类似 flexbox) |
设置文档特别提醒:元素onchange事件要能触发,否则修改不会被记录。
7.3 第三步:注册到设置 key
在setting.ts的main中把新设置项添加进设置的 key 集合,并可通过bind(修改某些项后触发其他项页面更新)、bindF(触发具体函数)、bindF2(哪些项更新后触发「重启应用」提示)等机制挂接联动行为。
7.4 第四步:读写设置
读写设置推荐使用getSet而不是直接store.get;如需写值,尽量使用setSet而不是store.set。getSet/setSet封装在setting.ts内部,会结合oldStore/nowStore快照(见 src/renderer/setting/setting.ts)来跟踪设置记忆与变更。
底层存储实现可参考 lib/store/store.ts:配置保存在userData/config.json(configPath由主进程在 src/main/main.ts 中传入),get未命中时会回退到默认值,getAll通过deepMerge将用户数据与默认数据合并。
7.5 第五步:翻译文案
设置项的名称、描述等一切新增文本都要走翻译流程(第七节)。AGENTS.md 与设置文档均强调:「添加、修改、删除文字都要触发翻译流程」。
八、国际化与翻译工作流
翻译是 eSearch 开发中贯穿始终的一环。AGENTS.md 给出的起点是:在lib/translate/source.json中添加"[原始中文]":"",然后执行node lib/translate/tool.js -u为文本创建 id。完整工作流记录在 翻译文档,可以拆解为以下环节:
8.1 生成待翻译 CSV
# 输出英文语言的待翻译 csv(包含未翻译/未跟进的新增文本) node lib/translate/tool.js -l en # en.csv "abc","你好世界",""-l <lang>:指定目标语言(en、es、fr、ru、eo、ar、zh-HANT等,对应 lib/translate 目录下的各语言 JSON)-a:输出全部文字。翻译文档特别提示:若原有翻译存在不足需要修改,用-a;若只是跟进新增文本(eSearch 某些文字已修改而翻译未修改),不要加-a,以聚焦增量-e:同时输出中英文对照,便于译者参考:
"abc","你好世界","Hello World",""8.2 编辑与保存
编辑 csv 时,将第三列(目标语言)翻译补全;lib/translate/readme.md甚至给出了可直接复制的 AI Prompt:「以下是 csv 文件,把第二列翻译成 en 并复制到第三列」。完成编辑后导入:
node lib/translate/tool.js -i en.csv保存时tool.js会把翻译结果写回对应语言的 JSON 文件(如en.json)。注意:只有在source.json里定义的文字才能被翻译;若界面存在无法翻译的文字,说明该页面未国际化,需要反馈 bug 并指明位置。
8.3 标记翻译进度(srcCommit / finishId)
tool.js定义了srcCommit变量(见 lib/translate/tool.js),借助 git 的 diff 能力跟踪翻译进度:
- 每个语言记录其翻译所基于的
source.json的 commit id(id) - 翻译完某个 id 后,将其加入该语言的
finishId数组,再次输出 csv 时会忽略它,从而专注于未翻译/刚修改的文本 - 全部翻译完成后,将
srcCommit的id改为latestSrcId(即git log -n 1输出的source.json最新 commit),并清空finishId
8.4 开发者控制台提示
翻译文档还定义了运行期的可视化反馈:若source.json没有定义的语言文本,控制台会以红色 🟥字体和背景输出;若定义了但未翻译,则以蓝色 🟦输出。这为运行时排查遗漏的国际化文本提供了直接线索。
8.5 运行期翻译
运行期的文案替换由 lib/translate/translate.ts 承担,主进程在 src/main/main.ts 中导入t(翻译函数)、lan(当前语言)、getLans(可用语言列表);渲染进程的 src/renderer/lib/translate.ts 同样提供相应能力。source.json中的中文原文即各语言翻译的 key 来源。
九、常见开发场景速查
综合 AGENTS.md 与上述源码分析,可将常见开发任务归纳为一张速查表:
| 任务 | 入口/步骤 | 关键文件 |
|---|---|---|
| 修改界面或功能 | 用dkh-ui创建 DOM,单 ts 文件覆盖绘制;修改文本必须走翻译 | src/renderer/editor/editor.ts、src/renderer/*/*.ts |
| 页面与主进程通信 | 在Message中登记名称/参数/返回值,两端用mainSend/mainOn、renderOn/renderSend/renderSendSync | lib/ipc.ts |
| 页面间通信 | 用mainOnReflect让主进程向多个页面广播 | lib/ipc.ts |
| 新增设置项 | ①ShareTypes.d.ts扩展setting→ ②setting.ts添加 UI → ③main注册 key → ④ 用getSet/setSet读写 → ⑤ 翻译 | src/ShareTypes.d.ts、src/renderer/setting/setting.ts、设置文档 |
| 修改/新增文案 | source.json加"原文":""→node lib/translate/tool.js -u生成 id → csv 翻译 →-i导入 | lib/translate/source.json、lib/translate/tool.js、翻译文档 |
| 代码质量把关 | pnpm run format→pnpm run typecheck→pnpm run lint;新文件用pnpm run fix | biome.json、tsconfig.json |
| 本地运行与打包 | pnpm run dev/pnpm run build/pnpm run start/pnpm run dist | package.json、electron.vite.config.ts |
十、小结
eSearch 是一个「以识屏为核心、多能力聚合」的 Electron 桌面应用。从 AGENTS.md 这份开发指南可以看出其工程化的关键设计:
- 多页面渲染架构:主进程 + 12 个功能页面(electron.vite.config.ts),每页一个 TS 入口、一套 HTML;
- 类型即契约:
Message(lib/ipc.ts)与setting/SettingPath(src/ShareTypes.d.ts、lib/store/renderStore.ts)分别在 IPC 与设置存储层面提供编译期校验; - 统一质量门槛:Biome(format + lint + import 整理)与
tsc --noEmit类型检查是每次改动的必选项; - 国际化内建到流程:一切文案修改都必须同步走
source.json→tool.js→ 各语言 JSON 的翻译链路。
对于想要深入参与项目的开发者,建议按「设置项新增 → IPC 消息扩展 → 翻译文本提交」的最小闭环先做一次完整实践,即可快速熟悉项目从类型到运行时的全链路;随后再按需深入截屏(src/renderer/screenShot)、OCR(src/renderer/ocr)、录屏(src/renderer/videoEditor)等具体功能模块。
【免费下载链接】eSearch截屏 离线OCR 搜索翻译 以图搜图 贴图 录屏 万向滚动截屏 屏幕翻译 Screenshot Offline OCR Search Translate Search for picture Paste the picture on the screen Screen recorder Omnidirectional scrolling screenshot Screen translator 支持Windows Linux macOS项目地址: https://gitcode.com/GitHub_Trending/es/eSearch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考