一个基于 Electron + React + TypeScript 的 macOS 多账号隔离网页会话管理器。
每个账号都会绑定一个独立的持久化 persist:... partition。用户可以为同一网站创建多个账号容器,按需打开对应窗口,自行登录,关闭后保留会话状态,下次继续复用。
- 添加账号容器并自动打开专属网页登录窗口
- 列表展示名称、分组、网址、状态、创建时间、最近打开时间
- 支持按分组展示账号,并按名称 / 分组 / 网址快速检索
- 编辑账号名称和默认网址
- 为指定账号从文件导入 Cookies
- 查看账号当前 Cookies,包含最后更新时间、来源和过期时间
- 为指定账号抓取页面自动刷新的候选地址,并选择一个作为后台保活请求
- 按账号配置定时发起保活请求,尽量在长时间不手动打开的情况下维持登录态
- 账号窗口里的视频旁边会出现明显区别于网站原生 UI 的
预览 / 下载悬浮按钮 - 删除账号元数据并清理对应 session 数据
- 同账号单窗口限制,重复打开时聚焦已有窗口
- 账号状态持久化,应用重启后仍可恢复账号列表
- 配置损坏自动备份并重建空配置
- 主进程状态变更实时推送到渲染层
- Electron
- React
- TypeScript
- Vite
- Vitest
- electron-builder
npm install
npm run dev开发模式会启动 Vite renderer,并在本地拉起 Electron 主进程。
npm run build构建产物:
dist/:renderer 静态资源dist-electron/:主进程与 preload 编译结果
npm run pack
npm run distnpm run pack:生成未封装目录npm run dist:生成可分发安装包
npm run typecheck
npm test
npm run test:e2e说明:
npm test覆盖单元测试与集成测试npm run test:e2e是 UI 端到端测试,走真实 renderer + service + repository 流程
列表项里提供 导入 Cookies 按钮,会打开系统文件选择器,并把选中的 Cookie 文件导入到该账号对应的独立 session partition。
当前支持的文件格式:
[
{
"name": "sid",
"value": "abc",
"domain": ".example.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "Lax"
}
]或:
{
"cookies": [
{
"name": "sid",
"value": "abc",
"url": "https://example.com/"
}
]
}说明:
- 第二种格式兼容 Playwright
storageState里的cookies - 首版只导入 Cookies,不导入 localStorage / IndexedDB / storage state
- 某些网站仅靠 Cookies 不足以恢复完整登录态,这是站点实现限制,不是导入器本身能完全规避的问题
每个账号卡片提供 查看 Cookies 按钮,会读取该账号当前 session 里的 Cookies,并展示:
- 最后一次保活刷新时间
- 每条 Cookie 的最后更新时间
- 这条 Cookie 最近是后台保活刷新的,还是打开页面时自动获取的,或者来自手动导入
- 当前过期时间或是否为会话级 Cookie
每个账号卡片里提供 保活设置 按钮。点击后可以:
-
新账号创建后默认就是启用后台保活,初始同域页面默认为账号配置里的目标网址
-
抓取候选地址:自动打开或聚焦该账号页面,并在 20 秒内记录这个页面自己发出的刷新请求
-
选择一个候选地址:只会列出账号目标地址同域的请求,通常优先选
GET、xhr或主文档刷新请求 -
设置刷新间隔:应用会在后台按分钟间隔发起一次同 session 的保活请求
-
立即刷新一次:手动验证当前选择的地址是否还能成功返回
工作方式:
- 保活请求使用该账号自己的 Electron
persist:session 发出,所以会复用这个账号现有 Cookies - 如果保活地址返回 302/跳转,应用会跟随跳转,并把最终登录后的同域页面记成后续保活目标
- 不会定时整页打开网站,只会请求你选中的同域地址;如果你没有手动选择,就默认刷新最近一次打开到的同域页面
- 保活属于“尽量维持登录态”,不能保证所有站点 30 天后仍然有效
限制:
- 如果站点登录态依赖页面脚本、动态签名、WebSocket、短期 token、设备指纹或人机校验,单纯刷一个 URL 可能不够
- 如果候选地址已经失效,可以重新抓取一轮并改选新的地址
- 只有应用在运行时,后台保活才会继续执行
src/
main/ Electron 主进程、服务层、IPC、窗口与持久化
preload/ 最小化暴露渲染层 API
renderer/ React UI
shared/ 共享类型
tests/
unit/
integration/
e2e/
src/main/repositories/accountRepository.ts负责accounts.json读取、损坏恢复、原子写入。src/main/services/accountService.ts负责业务规则、状态变更、删除回滚和状态广播。src/main/services/sessionService.ts负责 partition 命名与 session 清理。src/main/services/windowService.ts负责账号窗口创建、复用、关闭、幂等清理。src/main/ipc/accountHandlers.ts负责统一 IPC 返回结构。
默认写入用户家目录下的隐藏目录,例如当前应用会使用 ~/.user-switcher/。这样即使删掉 app 包重新打开,配置和持久化 cookies 仍然可以复用。测试或定制部署时可通过环境变量覆盖:
USER_SWITCHER_DATA_DIR=/custom/path npm run dev目录结构:
~/.user-switcher/
config/accounts.json
logs/app.log
logs/error.log
temp/
session/
- 不保存账号密码
- 不读取外部浏览器 profile 数据库
nodeIntegration: falsecontextIsolation: true- preload 仅暴露最小账户管理 API
- 登录态检测
- 更细粒度的账号会话调试工具
- Chrome / Edge 当前 profile 一键导入