auto-account-machine/browser-automation-ts/docs/ARCHITECTURE.md
2025-11-21 17:59:49 +08:00

199 lines
6.5 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.

# 架构设计文档
## 核心设计原则
**分层原则:通用组件 vs Provider特定组件**
---
## 📐 架构图
```
┌─────────────────────────────────────────┐
│ 通用层 (Universal Layer) │
│ 不调用浏览器特定API所有Provider共享 │
├─────────────────────────────────────────┤
│ - WorkflowEngine │
│ - 接口定义 (IAction, ISmartSelector) │
│ - 类型定义 (Types) │
│ - 抽象基类 (BaseAction, BaseProvider) │
└──────────────┬──────────────────────────┘
↓ 依赖接口
┌─────────────────────────────────────────┐
│ Provider特定层 (Provider Layer) │
│ 调用浏览器特定API每个Provider独立实现 │
├─────────────────────────────────────────┤
│ - Actions (click, input, etc.) │
│ - SmartSelector │
│ - ActionFactory │
│ - BrowserProvider │
└─────────────────────────────────────────┘
```
---
## 🗂️ 目录结构
```
src/
├── core/ # 通用核心层 ✅
│ ├── interfaces/ # 接口定义
│ │ ├── IBrowserProvider.ts # Provider接口
│ │ ├── IAction.ts # Action接口
│ │ └── ISmartSelector.ts # SmartSelector接口
│ ├── base/ # 抽象基类
│ │ ├── BaseBrowserProvider.ts
│ │ └── BaseAction.ts
│ └── types/ # 类型定义
│ └── index.ts
├── workflow/ # 通用工作流 ✅
│ └── WorkflowEngine.ts # 工作流引擎(通用!)
├── factory/ # 工厂模式 ✅
│ └── BrowserFactory.ts
└── providers/ # Provider实现层 ❌
├── adspower/ # AdsPower (Puppeteer)
│ ├── AdsPowerProvider.ts # Provider实现
│ ├── actions/ # AdsPower专用Actions
│ │ ├── ClickAction.ts
│ │ ├── InputAction.ts
│ │ └── ...
│ └── core/ # AdsPower专用Core
│ ├── SmartSelector.ts # Puppeteer实现
│ └── ActionFactory.ts
└── playwright/ # Playwright (未来)
├── PlaywrightProvider.ts
├── actions/ # Playwright专用Actions
└── core/
├── SmartSelector.ts # Playwright实现
└── ActionFactory.ts
```
---
## 📊 组件分类
### ✅ 通用组件所有Provider共享
| 组件 | 位置 | 职责 |
|------|------|------|
| **WorkflowEngine** | `workflow/` | 执行工作流调用Action接口 |
| **接口定义** | `core/interfaces/` | 定义规范IAction, ISmartSelector等 |
| **类型定义** | `core/types/` | 配置、结果等类型 |
| **抽象基类** | `core/base/` | 通用实现逻辑 |
| **BrowserFactory** | `factory/` | 创建Provider实例 |
**特点:**
- ✅ 不调用浏览器特定API
- ✅ 只依赖接口,不依赖实现
- ✅ 所有Provider可以共享代码
---
### ❌ Provider特定组件
| 组件 | 位置 | 职责 | 原因 |
|------|------|------|------|
| **Actions** | `providers/*/actions/` | 执行具体操作 | 需要调用`page.click()`等API |
| **SmartSelector** | `providers/*/core/` | 查找元素 | 需要调用`page.waitForSelector()`等 |
| **ActionFactory** | `providers/*/core/` | 创建Action实例 | 返回Provider特定的Action类 |
| **Provider** | `providers/*/` | 管理浏览器 | 调用Puppeteer/Playwright等API |
**特点:**
- ❌ 调用浏览器特定API
- ❌ 每个Provider独立实现
- ❌ 不能跨Provider共享
---
## 💡 为什么这样设计?
### WorkflowEngine为什么是通用的
```typescript
// WorkflowEngine只调用接口不依赖具体实现
class WorkflowEngine {
async executeStep(step) {
// 从Factory获取Action多态
const ActionClass = this.actionFactory.getAction(step.action);
const action = new ActionClass(step, this.context);
// 执行通过接口调用不关心Puppeteer还是Playwright
await action.execute();
}
}
```
**关键:** 只依赖`IAction`接口,不知道是`PuppeteerClickAction`还是`PlaywrightClickAction`
---
### SmartSelector为什么是Provider特定的
```typescript
// Puppeteer版本
class PuppeteerSmartSelector {
async find(timeout) {
return await this.page.waitForSelector(selector, { timeout });
// ↑ Puppeteer特定API
}
}
// Playwright版本API不同
class PlaywrightSmartSelector {
async find(timeout) {
return await this.page.locator(selector).waitFor({ timeout });
// ↑ Playwright特定API
}
}
```
**关键:** 必须直接调用浏览器API无法抽象
---
## 🔄 工作流程
```
1. 用户创建Provider
BrowserFactory.create('adspower')
2. WorkflowEngine执行
new WorkflowEngine(workflow, context, actionFactory)
3. 执行每个步骤
actionFactory.getAction('click') // 获取AdsPower的ClickAction
action.execute() // 调用Puppeteer API
```
**关键:** WorkflowEngine不知道也不关心是哪个Provider
---
## ✅ 总结
| 层次 | 组件 | 通用/特定 | 原因 |
|------|------|----------|------|
| **业务层** | WorkflowEngine | ✅ 通用 | 只调用接口 |
| **接口层** | IAction, ISmartSelector | ✅ 通用 | 定义规范 |
| **实现层** | Actions, SmartSelector | ❌ Provider特定 | 调用浏览器API |
| **基础层** | Provider | ❌ Provider特定 | 管理浏览器 |
**设计原则:**
- 依赖倒置:上层依赖接口,不依赖实现
- 开闭原则添加新Provider不修改通用层
- 单一职责通用层负责流程Provider层负责实现
---
**创建时间:** 2025-11-21
**状态:** 已修正 ✅