Files
zclaw_openfang/docs/superpowers/specs/2026-03-17-browser-hand-ui-design.md
iven 69c874ed59 docs(spec): add Browser Hand UI design specification
Design for browser automation UI component integrated into HandsPanel:
- Dual trigger mechanism: frontend templates + agent scripts
- Real-time status + screenshot preview
- Complete template system (basic, scraping, automation)
- Task runner with progress tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:14:41 +08:00

548 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Browser Hand UI 组件设计文档
> **日期**: 2026-03-17
> **状态**: Draft
> **作者**: Claude Code
## 一、概述
Browser Hand 是 ZCLAW 的浏览器自动化能力,基于 Fantoccini (Rust WebDriver) 实现。本设计文档描述其前端 UI 组件架构和集成方案。
### 设计目标
1. **双层触发机制**: 前端任务模板 + Agent 脚本驱动
2. **实时可视化**: 执行状态 + 截图预览
3. **完整工具集**: 支持所有浏览器自动化功能
4. **标准集成**: 作为 Hand 集成到现有 HandsPanel
### 范围
- 前端 UI 组件
- 状态管理 Store
- 任务模板系统
- 与现有 HandsPanel 集成
---
## 二、架构设计
### 2.1 组件结构
```
desktop/src/
├── components/
│ ├── HandsPanel.tsx # 现有,添加 Browser Hand 特殊处理
│ └── BrowserHand/
│ ├── index.ts # 模块导出
│ ├── BrowserHandCard.tsx # Browser Hand 专用卡片
│ ├── TaskTemplateModal.tsx # 任务模板选择模态框
│ ├── TaskRunner.tsx # 任务执行状态展示
│ ├── ScreenshotPreview.tsx # 截图预览组件
│ └── templates/
│ ├── index.ts # 模板注册
│ ├── types.ts # 模板类型定义
│ ├── basic.ts # 基础操作模板
│ ├── scraping.ts # 数据采集模板
│ └── automation.ts # 自动化流程模板
├── lib/
│ ├── browser-client.ts # 已完成 - Tauri API 封装
│ └── browser-templates.ts # 模板执行引擎
└── store/
└── browserHandStore.ts # Browser Hand 状态管理
```
### 2.2 数据流
```
┌─────────────────────────────────────────────────────────────────┐
│ 前端触发流程 │
├─────────────────────────────────────────────────────────────────┤
│ HandsPanel │
│ ↓ 检测 Browser Hand │
│ BrowserHandCard │
│ ↓ 点击"执行任务" │
│ TaskTemplateModal │
│ ↓ 选择模板 + 填参数 │
│ browserHandStore.executeTemplate() │
│ ↓ 调用 │
│ Tauri Commands (browser_*) │
│ ↓ WebDriver Protocol │
│ Fantoccini → ChromeDriver │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Agent 触发流程 │
├─────────────────────────────────────────────────────────────────┤
│ 用户对话 │
│ ↓ 理解意图 │
│ LLM 生成脚本 │
│ ↓ Agent 调用 │
│ browserHandStore.executeScript() │
│ ↓ 调用 │
│ Tauri Commands (browser_execute_script) │
│ ↓ WebDriver Protocol │
│ Fantoccini → ChromeDriver │
└─────────────────────────────────────────────────────────────────┘
```
### 2.3 与现有系统集成
```typescript
// HandsPanel.tsx 修改
import { BrowserHandCard } from './BrowserHand';
function HandsPanel() {
// 检测是否为 Browser Hand
const isBrowserHand = (hand: Hand) => hand.id === 'browser' || hand.name === 'Browser';
return (
<div className="grid gap-3">
{hands.map((hand) =>
isBrowserHand(hand) ? (
<BrowserHandCard key={hand.id} hand={hand} />
) : (
<HandCard key={hand.id} hand={hand} {...props} />
)
)}
</div>
);
}
```
---
## 三、状态管理
### 3.1 Store 结构
```typescript
// store/browserHandStore.ts
interface BrowserSession {
id: string;
name: string;
currentUrl: string | null;
title: string | null;
status: 'connecting' | 'connected' | 'active' | 'idle' | 'error';
createdAt: string;
lastActivity: string;
}
interface BrowserLog {
id: string;
timestamp: string;
level: 'info' | 'warn' | 'error' | 'action';
message: string;
details?: Record<string, unknown>;
}
interface ExecutionState {
isRunning: boolean;
currentAction: string | null;
currentUrl: string | null;
lastScreenshot: string | null;
progress: number; // 0-100
startTime: string | null;
}
interface RecentTask {
id: string;
templateId: string;
templateName: string;
params: Record<string, unknown>;
status: 'success' | 'failed' | 'cancelled';
executedAt: string;
duration: number;
result?: unknown;
}
interface BrowserHandState {
// 会话管理
sessions: BrowserSession[];
activeSessionId: string | null;
// 执行状态
execution: ExecutionState;
// 日志
logs: BrowserLog[];
// 模板
templates: TaskTemplate[];
recentTasks: RecentTask[];
// UI 状态
isTemplateModalOpen: boolean;
isLoading: boolean;
error: string | null;
}
interface BrowserHandActions {
// 会话管理
createSession: (options?: SessionOptions) => Promise<string>;
closeSession: (sessionId: string) => Promise<void>;
listSessions: () => Promise<void>;
// 模板执行
executeTemplate: (templateId: string, params: Record<string, unknown>) => Promise<unknown>;
executeScript: (script: string, args?: unknown[]) => Promise<unknown>;
// 状态更新
updateExecutionState: (state: Partial<ExecutionState>) => void;
addLog: (log: Omit<BrowserLog, 'id' | 'timestamp'>) => void;
// 截图
takeScreenshot: () => Promise<string>;
// UI 控制
openTemplateModal: () => void;
closeTemplateModal: () => void;
clearError: () => void;
}
```
### 3.2 Store 实现要点
```typescript
// 使用 Zustand 创建 store
export const useBrowserHandStore = create<BrowserHandState & BrowserHandActions>((set, get) => ({
// 初始状态
sessions: [],
activeSessionId: null,
execution: {
isRunning: false,
currentAction: null,
currentUrl: null,
lastScreenshot: null,
progress: 0,
startTime: null,
},
logs: [],
templates: BUILTIN_TEMPLATES,
recentTasks: [],
isTemplateModalOpen: false,
isLoading: false,
error: null,
// Actions 实现见详细设计
}));
```
---
## 四、任务模板系统
### 4.1 模板类型定义
```typescript
// components/BrowserHand/templates/types.ts
interface TaskTemplateParam {
key: string;
label: string;
type: 'text' | 'url' | 'number' | 'select' | 'textarea' | 'json';
required: boolean;
default?: unknown;
placeholder?: string;
options?: { value: string; label: string }[]; // for select type
description?: string;
}
interface TaskTemplate {
id: string;
name: string;
description: string;
category: 'basic' | 'scraping' | 'automation';
icon: string;
params: TaskTemplateParam[];
execute: (params: Record<string, unknown>, context: ExecutionContext) => Promise<unknown>;
}
interface ExecutionContext {
browser: Browser; // browser-client.ts 中的 Browser 类
onProgress: (action: string, progress: number) => void;
onLog: (level: BrowserLog['level'], message: string, details?: Record<string, unknown>) => void;
}
```
### 4.2 内置模板列表
#### 基础操作类 (Basic)
| ID | 名称 | 参数 | 说明 |
|----|------|------|------|
| `basic_navigate_screenshot` | 打开网页并截图 | `url` | 访问指定 URL 并截图 |
| `basic_fill_form` | 填写表单 | `url`, `fields[]` | 填写并可选提交表单 |
| `basic_click_navigate` | 点击导航 | `url`, `selector` | 点击指定元素 |
#### 数据采集类 (Scraping)
| ID | 名称 | 参数 | 说明 |
|----|------|------|------|
| `scrape_text` | 抓取页面文本 | `url`, `selectors[]` | 提取多个选择器的文本 |
| `scrape_list` | 提取列表数据 | `url`, `itemSelector`, `fieldMappings` | 批量提取结构化数据 |
| `scrape_images` | 下载图片 | `url`, `imageSelector`, `savePath` | 批量下载图片 |
#### 自动化流程类 (Automation)
| ID | 名称 | 参数 | 说明 |
|----|------|------|------|
| `auto_login_action` | 登录并操作 | `loginUrl`, `credentials`, `actions[]` | 登录后执行操作序列 |
| `auto_multi_page` | 多页面导航 | `urls[]`, `actions[]` | 遍历多个页面执行操作 |
| `auto_monitor` | 定时监控 | `url`, `checkCondition`, `interval` | 周期性检查页面状态 |
### 4.3 模板执行引擎
```typescript
// lib/browser-templates.ts
export async function executeTemplate(
template: TaskTemplate,
params: Record<string, unknown>,
browser: Browser,
onProgress: (action: string, progress: number) => void,
onLog: (level: BrowserLog['level'], message: string) => void
): Promise<unknown> {
const context: ExecutionContext = {
browser,
onProgress,
onLog: (level, message, details) => {
onLog(level, message);
console.log(`[BrowserHand] ${level}: ${message}`, details);
},
};
// 验证参数
validateParams(template.params, params);
// 执行模板
onProgress('启动浏览器', 0);
try {
const result = await template.execute(params, context);
onProgress('完成', 100);
return result;
} catch (error) {
onLog('error', `执行失败: ${error}`);
throw error;
}
}
```
---
## 五、UI 组件设计
### 5.1 BrowserHandCard
Browser Hand 的专用卡片组件,显示实时状态和截图预览。
```
┌────────────────────────────────────────────────────────────┐
│ 🌐 Browser Hand [●] 就绪/运行中 │
├────────────────────────────────────────────────────────────┤
│ 浏览器自动化能力 - 支持网页操作、数据采集、自动化流程 │
├────────────────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 截 图 预 览 │ │
│ │ (最近一次截图) │ │
│ └────────────────────────────────────────────────────────┘ │
│ 当前: https://example.com/page │
│ 操作: 正在填写表单... ████████░░ 80% │
├────────────────────────────────────────────────────────────┤
│ [📋 执行任务] [📸 截图] [🔄 刷新] [⚙️ 设置] │
└────────────────────────────────────────────────────────────┘
```
**Props**:
```typescript
interface BrowserHandCardProps {
hand: Hand;
onOpenSettings?: () => void;
}
```
**状态显示**:
- `idle`: 显示"就绪",截图区域显示占位符
- `running`: 显示进度条、当前操作、最新截图
- `error`: 显示错误信息、重试按钮
### 5.2 TaskTemplateModal
任务模板选择和参数填写模态框。
```
┌────────────────────────────────────────────────────────────┐
│ 选择任务模板 ✕ │
├────────────────────────────────────────────────────────────┤
│ [基础操作] [数据采集] [自动化流程] │
├────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 📸 打开截图 │ │ 📝 填写表单 │ │ 🖱️ 点击导航 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 📄 抓取文本 │ │ 📊 提取列表 │ │
│ └──────────────┘ └──────────────┘ │
├────────────────────────────────────────────────────────────┤
│ 已选: 📸 打开网页并截图 │
│ │
│ 网页地址 * │
│ ┌────────────────────────────────────────────────────────┐│
│ │ https://example.com ││
│ └────────────────────────────────────────────────────────┘│
├────────────────────────────────────────────────────────────┤
│ [取消] [▶ 执行任务] │
└────────────────────────────────────────────────────────────┘
```
**Props**:
```typescript
interface TaskTemplateModalProps {
isOpen: boolean;
onClose: () => void;
onSelect: (template: TaskTemplate, params: Record<string, unknown>) => void;
}
```
### 5.3 TaskRunner
任务执行中的状态展示组件(可嵌入 BrowserHandCard 或独立显示)。
```
┌────────────────────────────────────────────────────────────┐
│ 执行中: 打开网页并截图 │
├────────────────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 实 时 截 图 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ 当前 URL: https://example.com/page │
│ 操作: 等待页面加载... │
│ │
│ ████████████████████░░░░░░░░░░ 65% │
│ │
│ ┌─ 操作日志 ─────────────────────────────────────────────┐│
│ │ 10:23:01 [info] 创建浏览器会话 ││
│ │ 10:23:02 [info] 导航到 https://example.com ││
│ │ 10:23:05 [action] 等待页面加载 ││
│ └────────────────────────────────────────────────────────┘│
├────────────────────────────────────────────────────────────┤
│ [⏹ 停止] [📋 查看结果] │
└────────────────────────────────────────────────────────────┘
```
### 5.4 ScreenshotPreview
截图预览组件,支持缩放和全屏查看。
```typescript
interface ScreenshotPreviewProps {
base64: string | null;
isLoading?: boolean;
onRefresh?: () => void;
onClick?: () => void; // 点击放大
}
```
---
## 六、错误处理
### 6.1 错误类型
```typescript
enum BrowserHandErrorType {
WEBDRIVER_NOT_AVAILABLE = 'webdriver_not_available',
SESSION_CREATION_FAILED = 'session_creation_failed',
NAVIGATION_FAILED = 'navigation_failed',
ELEMENT_NOT_FOUND = 'element_not_found',
TIMEOUT = 'timeout',
SCRIPT_ERROR = 'script_error',
PERMISSION_DENIED = 'permission_denied',
}
```
### 6.2 错误处理策略
| 错误类型 | 处理方式 |
|---------|---------|
| WEBDRIVER_NOT_AVAILABLE | 显示安装指引,提供下载链接 |
| SESSION_CREATION_FAILED | 重试按钮,显示详细错误 |
| NAVIGATION_FAILED | 显示 URL提供重试 |
| ELEMENT_NOT_FOUND | 显示选择器,建议检查页面 |
| TIMEOUT | 提供增加超时时间选项 |
| SCRIPT_ERROR | 显示脚本错误位置和消息 |
---
## 七、测试策略
### 7.1 单元测试
- `browserHandStore` 状态管理测试
- 模板参数验证测试
- 错误处理测试
### 7.2 集成测试
- 模板执行流程测试mock Tauri commands
- UI 组件渲染测试
- 与 HandsPanel 集成测试
### 7.3 E2E 测试
- 完整任务执行流程
- 多模板顺序执行
- 错误恢复流程
---
## 八、实现优先级
### Phase 1: 核心框架
1. `browserHandStore` 状态管理
2. `BrowserHandCard` 基础组件
3. 集成到 `HandsPanel`
### Phase 2: 模板系统
4. 模板类型定义和注册
5. `TaskTemplateModal` 组件
6. 基础操作类模板实现
### Phase 3: 完整功能
7. 数据采集类模板
8. 自动化流程类模板
9. `TaskRunner` 实时状态展示
10. 截图预览功能
---
## 九、依赖
- `browser-client.ts` (已完成)
- Tauri browser commands (已完成)
- Fantoccini WebDriver (已完成)
- Zustand (已有)
- Lucide React icons (已有)
- Tailwind CSS (已有)
---
## 十、风险与缓解
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| WebDriver 未安装 | 无法使用 | 提供安装检测和指引 |
| 大量截图消耗内存 | 性能下降 | 限制截图历史数量,压缩图片 |
| 脚本执行安全 | 潜在危险操作 | Agent 层审批机制 |
| 复杂模板难以调试 | 用户体验差 | 详细日志,步骤高亮 |
---
## 十一、未来扩展
- [ ] 录制回放功能
- [ ] 模板自定义创建
- [ ] 多浏览器并行
- [ ] Chrome DevTools Protocol 直接集成
- [ ] WebMCP 支持 (Chrome 146+)