e833b923c8
接入 Playwright Worker、会话 WebSocket 与全局浏览器面板(固定于 App Bar 下); 含验证码 stealth、设置项默认音与 URL 安全校验;附带 worker 部署与设计文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
113 lines
4.0 KiB
Markdown
113 lines
4.0 KiB
Markdown
# 内置浏览器 — 网站导航(收藏)设计说明
|
||
|
||
> 关联:[2026-06-11-embedded-browser-design.md](./2026-06-11-embedded-browser-design.md) · [2026-06-11-global-floating-browser 变更](../../changelog/2026-06-11-global-floating-browser.md)
|
||
|
||
## 背景与目标
|
||
|
||
用户希望在 Nexus **全局浮动浏览器**内维护一份**自定义网站导航**(类似浏览器收藏夹),便于反复打开常用运维站点(监控、面板、客户站点等),而不依赖浏览器自带书签。
|
||
|
||
### 用户原话(2026-06-11)
|
||
|
||
> 浏览器内置网站导航,我自己可以增加,类似收藏功能。
|
||
|
||
### 与现有能力的关系
|
||
|
||
| 已有 | 导航(收藏) |
|
||
|------|----------------|
|
||
| **浏览记录** `visits` | 被动、按访问时间倒序,不可编辑名称 |
|
||
| **URL 历史** `url_history` | 去重 URL 列表,无自定义标题 |
|
||
| **网站导航** `nav_links` | 用户主动添加/编辑/删除,固定名称 + URL,长期入口 |
|
||
|
||
三者并存:记录 ≠ 收藏;收藏用于「我关心的固定站点」。
|
||
|
||
## 非目标
|
||
|
||
- 不做浏览器引擎替换(首版 iframe;**2026-06-11 改为服务端 Chromium**,见 [server-browser-chromium-design.md](./2026-06-11-server-browser-chromium-design.md))
|
||
- 不做 HTTP 反向代理
|
||
- 不做跨管理员共享导航(按账号隔离,与 `admin_ui_preferences` 一致)
|
||
- 首版不做文件夹/分组(可后续 `group` 字段扩展)
|
||
|
||
## 数据模型
|
||
|
||
存储:`admin_ui_preferences`,`context = embedded_browser`,字段 `nav_links`(JSON 数组)。
|
||
|
||
```json
|
||
{
|
||
"nav_links": [
|
||
{
|
||
"id": "uuid",
|
||
"title": "Grafana",
|
||
"url": "https://grafana.example.com",
|
||
"sort_order": 0
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
约束(后端 `browser_ui_state.py`):
|
||
|
||
| 字段 | 规则 |
|
||
|------|------|
|
||
| `id` | 非空字符串,≤64 |
|
||
| `title` | 非空,≤80 |
|
||
| `url` | 仅 `http`/`https`,无凭据,与现有 URL 白名单一致 |
|
||
| 数量上限 | 64 条 |
|
||
| `sort_order` | 整数,用于排序 |
|
||
|
||
API:沿用 `GET/PUT /api/browser/state`,`nav_links` 随整体 state 读写(与 tabs、visits 相同)。
|
||
|
||
## 交互设计
|
||
|
||
### 入口
|
||
|
||
1. 浮动浏览器工具栏:**「导航」**按钮(`mdi-star-outline`),与「浏览记录」并列
|
||
2. 侧栏 Tab:**网站导航** | **浏览记录**(同一侧栏区域切换,避免双栏占宽)
|
||
3. 空白页:展示导航卡片网格,点击即打开
|
||
|
||
### 用户操作
|
||
|
||
| 操作 | 行为 |
|
||
|------|------|
|
||
| 添加 | 对话框:名称 + URL;可预填当前地址栏 / 当前页 URL |
|
||
| 编辑 | 同对话框,改名称或 URL |
|
||
| 删除 | 列表项菜单或删除图标,需确认(可选) |
|
||
| 打开 | 点击条目 → 当前标签导航到该 URL |
|
||
| 从当前页收藏 | 地址栏旁「星标」一键添加(已存在则提示或进入编辑) |
|
||
|
||
### 持久化
|
||
|
||
- 保存至 MySQL,换设备/清 localStorage 不丢
|
||
- 与浏览记录、标签、窗口位置同一 debounce 写入策略
|
||
|
||
## 安全
|
||
|
||
- URL 校验复用 `_is_safe_url`,拒绝 `javascript:`、`data:` 等
|
||
- 无服务端 fetch,无 SSRF
|
||
- 按 `admin_id` 隔离
|
||
|
||
## 内核与风控说明(用户关切)
|
||
|
||
内置浏览器 **不是** 独立 Firefox/Chrome 安装包,而是 **iframe + 用户当前浏览器引擎**。
|
||
|
||
- User-Agent 与普通浏览器一致,**不会因 Nexus 被单独判为机器人**
|
||
- 部分站点禁止 iframe 或要求顶层窗口 → 仍用「新标签打开」
|
||
- 收藏导航仅保存 URL,不改变加载方式
|
||
|
||
## 实现状态(2026-06-11)
|
||
|
||
| 层 | 状态 |
|
||
|----|------|
|
||
| 后端 `nav_links` 解析 / API 字段 | ✅ 已入代码(待前端联调) |
|
||
| 前端侧栏 + 增删改 UI | ⏳ 待实现 |
|
||
| 单测 `nav_links` 解析 | ✅ `tests/test_browser_ui_state.py::test_parse_nav_links` |
|
||
| 部署 | ⏳ 前端完成后一并门控 |
|
||
|
||
## 验收标准
|
||
|
||
- [ ] 可添加、编辑、删除导航项,刷新后仍在
|
||
- [ ] 点击导航项在当前标签打开对应 https 站点
|
||
- [ ] 可从当前页一键加入收藏
|
||
- [ ] 非法 URL 拒绝并提示
|
||
- [ ] 不同管理员账号导航互不可见
|
||
- [ ] 与浏览记录、标签、最小化状态可同时正常工作
|