Skip to content

项目完整指南 ​

面向开发者与运维人员的综合参考:简介、快速开始、核心概念、模块详解与 FAQ。

目录 ​

  1. 项目简介
  2. 快速开始
  3. 核心概念
  4. 技术架构
  5. 模块详解
  6. 工作流设计
  7. 节点开发指南
  8. API 开发指南
  9. 数据库设计
  10. 常见问题

1. 项目简介 ​

1.1 什么是 Automa Agent? ​

Automa Agent 是一款企业级桌面自动化工具,专为企业 ERP 数据采集与流程自动化设计,主要能力包括:

  • 网页数据采集:页面 DOM 与接口数据的自动化抓取
  • 用户操作模拟:鼠标点击、键盘输入、表单填写
  • Excel 数据处理:读取、写入与批量转换
  • 可视化流程编排:拖拽式工作流设计,降低使用门槛
  • 定时调度:支持 Cron 表达式的无人值守执行
  • AI 工作台:多模型对话、BizApi 自动执行、钉钉/飞书通道、截图分析与自定义 OpenAI Provider

1.2 核心优势 ​

特性说明
脚本驱动脚本可以直接调用网站功能,如直接请求接口
流程隔离每个流程在独立的浏览器窗口中执行,互不干扰
并发执行支持多个流程同时运行
可视化编排拖拽式工作流设计,无需编程基础
原生能力基于 Rust 的原生模块,性能优异

1.3 应用场景 ​

  • 电商平台数据采集(生意参谋、店铺数据等)
  • ERP 系统数据同步
  • 批量表单填写
  • 定时报表下载
  • 网页自动化测试

2. 快速开始 ​

2.1 环境要求 ​

  • Node.js: >= 18.x
  • pnpm: >= 8.x
  • 操作系统: Windows 10+, macOS 10.15+, Linux

2.2 安装依赖 ​

bash
# 克隆项目
git clone git@codeup.aliyun.com:6627798cd833774c93cc0790/erp_automa.git

# 进入目录
cd erp_automa

# 安装依赖
pnpm install

# 重建原生模块(如果需要)
npm rebuild better-sqlite3 --runtime=electron --target=30.5.1

2.3 开发启动 ​

bash
# 启动开发服务器
pnpm dev

2.4 构建发布 ​

bash
# Windows
pnpm build:win

# macOS
pnpm build:mac

# Linux
pnpm build:linux

3. 核心概念 ​

3.1 工作流 (Workflow) ​

工作流是一系列自动化操作的集合,由节点和连线组成。

text
┌─────────┐     ┌─────────┐     ┌─────────┐
│ 触发器  │ ──▶ │ 打开窗口 │ ──▶ │ 点击按钮 │
└─────────┘     └─────────┘     └─────────┘
                                     │
                                     ▼
┌─────────┐     ┌─────────┐     ┌─────────┐
│  结束   │ ◀── │ 保存数据 │ ◀── │ 获取数据 │
└─────────┘     └─────────┘     └─────────┘

3.2 节点 (Node) ​

节点是工作流的基本执行单元,每个节点完成一个特定的操作。

节点分类:

分类说明示例
触发器工作流的入口手动触发、定时触发
鼠标键盘模拟用户输入鼠标点击、键盘输入
窗口自动化浏览器窗口操作打开窗口、执行脚本
数据处理数据转换和处理JSON解析、变量设置
流程控制控制执行流程条件判断、循环
文件操作文件读写读取文件、写入文件
网络请求HTTP 请求GET请求、POST请求

3.3 变量 (Variable) ​

变量用于在节点之间传递数据。

javascript
// 设置变量
await setVariable('userName', '张三');

// 使用变量(在配置中)
${userName}  // 输出: 张三

// 访问对象属性
${user.name}  // 访问嵌套属性
${list[0]}    // 访问数组元素

3.4 执行上下文 (ExecutionContext) ​

执行上下文包含工作流运行时的所有状态信息:

typescript
interface ExecutionContext {
    workflowId: string;      // 工作流 ID
    workerId: string;        // 执行器 ID
    variables: Record<string, unknown>;  // 变量存储
    logs: ExecutionLog[];    // 执行日志
    startTime: Date;         // 开始时间
}

4. 技术架构 ​

4.1 整体架构 ​

text
┌────────────────────────────────────────────────────────────┐
│                     渲染进程 (Renderer)                      │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ 工作流设计器  │  │   配置面板   │  │   节点组件   │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└────────────────────────────┬───────────────────────────────┘
                             │ IPC
┌────────────────────────────┴───────────────────────────────┐
│                      预加载脚本 (Preload)                    │
│                    contextBridge / ipcRenderer              │
└────────────────────────────┬───────────────────────────────┘
                             │ IPC
┌────────────────────────────┴───────────────────────────────┐
│                      主进程 (Main)                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   控制器层   │  │   引擎层     │  │   Bean 层    │      │
│  │ Controllers  │  │ WorkflowEngine│ │ DesktopNative│      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└────────────────────────────┬───────────────────────────────┘
                             │
┌────────────────────────────┴───────────────────────────────┐
│                     原生模块 (Native)                       │
│                  Rust: desktop-native             │
└────────────────────────────────────────────────────────────┘

4.2 进程模型 ​

进程职责技术
主进程应用生命周期、窗口管理、工作流执行Node.js + Electron
渲染进程UI 界面、工作流设计器Vue 3 + TypeScript
预加载脚本进程通信桥接、安全 API 暴露contextBridge
BrowserWindow自动化目标窗口Chromium

4.3 IoC 容器 (Summer) ​

项目使用自研的 IoC 容器框架,提供依赖注入能力:

typescript
// 定义 Bean
@Bean()
export class MyService {
    @Autowired()
    private readonly db: Db;
    
    @PreConstruct()
    async init() {
        // 初始化逻辑
    }
}

// 使用 Bean
@Bean()
export class MyController {
    @Autowired()
    private readonly myService: MyService;
}

5. 模块详解 ​

5.1 工作流引擎 (WorkflowEngine) ​

位置: src/main/engine/WorkflowEngine.ts

工作流引擎负责解析和执行工作流定义。

核心方法:

typescript
class WorkflowEngine {
    // 注册节点执行器
    registerExecutor(executor: INodeExecutor): void;
    
    // 执行工作流
    async execute(workflow: WorkflowDefinition, input?: Record<string, unknown>): Promise<WorkflowExecutionResult>;
    
    // 暂停执行
    pause(): void;
    
    // 继续执行
    resume(): void;
    
    // 停止执行
    stop(): void;
}

执行流程:

  1. 查找 Trigger 节点作为入口
  2. 初始化执行上下文
  3. 循环执行节点,直到没有下一个节点
  4. 返回执行结果

5.2 节点执行器 (BaseNodeExecutor) ​

位置: src/main/engine/BaseNodeExecutor.ts

所有节点执行器的基类,提供通用功能。

核心 API:

方法说明
execute(node, context)执行节点(抽象方法)
success(output?, nextNodeId?)创建成功结果
failure(error)创建失败结果
getConfig<T>(node, key, defaultValue?)获取节点配置
getVariable<T>(context, name, defaultValue?)获取变量
setVariable(context, name, value)设置变量
resolveExpression(expression, context)解析变量表达式
delay(ms)延时

5.3 原生功能 (DesktopNative) ​

位置: src/main/beans/DesktopNative.ts

封装 Rust 原生模块,提供桌面自动化能力。

主要功能:

typescript
class DesktopNative {
    // 截图
    captureScreen(rect?: Rect): ScreenshotResult;
    captureRegion(rect: Rect): ScreenshotResult;
    
    // 鼠标操作
    mouseMove(x: number, y: number): void;
    mouseClick(button: 'left' | 'right' | 'middle'): void;
    mouseScroll(deltaX: number, deltaY: number): void;
    
    // 键盘操作
    keyboardType(text: string): void;
    keyboardPress(key: string, modifiers?: string[]): void;
    
    // 元素定位
    getElementAtPosition(x: number, y: number): AXElement;
    findElementBySelector(selector: string): AXElement[];
}

5.4 数据库 (Db) ​

位置: src/main/beans/Db.ts

使用 SQLite + TypeORM 进行数据持久化。

实体列表:

实体说明
WorkflowEntity工作流定义
WorkflowWorkerEntity工作流执行实例
WorkflowVariablesEntity工作流变量
WorkflowLogEntity执行日志
CapturedElementEntity捕获的元素
ScreenshotEntity截图
FolderEntity文件夹

5.5 定时任务 (CronManager) ​

位置: src/main/beans/CronManager.ts

管理定时触发的工作流。

typescript
class CronManager {
    // 启动定时任务管理
    async start(): Promise<void>;
    
    // 添加定时任务
    addJob(workflowId: string, cronExpression: string): void;
    
    // 移除定时任务
    removeJob(workflowId: string): void;
}

6. 工作流设计 ​

6.1 设计器界面 ​

工作流设计器基于 Vue Flow 实现,主要组件:

组件位置说明
WorkflowDesigner.vuesrc/renderer/pages/workflow/设计器主组件
ConfigPanel/src/renderer/pages/workflow/components/配置面板
nodes/src/renderer/pages/workflow/nodes/节点 UI 组件
edges/src/renderer/pages/workflow/edges/连线组件

6.2 节点配置 ​

每个节点都有对应的配置表单,定义在 src/automa/types/node-config.ts:

typescript
export const mouseClickFormConfig: DynamicFormI = {
    showSide: false,
    cols: 1,
    fields: [
        {
            label: '点击类型',
            key: 'clickType',
            type: 'select',
            span: 1,
            tooltip: '单击、双击或右键点击',
            options: [
                { label: '单击', value: 'single' },
                { label: '双击', value: 'double' },
                { label: '右键', value: 'right' },
            ],
        },
        // ... 更多字段
    ],
};

6.3 工作流定义 ​

工作流以 JSON 格式存储:

typescript
interface WorkflowDefinition {
    id: string;
    name: string;
    nodes: NodeDefinition[];
    edges: EdgeDefinition[];
    variables?: Record<string, unknown>;
}

interface NodeDefinition {
    id: string;
    type: NodeKey;
    name: string;
    position: { x: number; y: number };
    config: Record<string, unknown>;
}

interface EdgeDefinition {
    id: string;
    source: string;
    target: string;
    sourceHandle?: string;
    targetHandle?: string;
}

7. 节点开发指南 ​

7.1 开发步骤 ​

开发新节点需要完成以下 10 个步骤:

步骤 1: 添加命令定义 ​

文件: src/automa/types/command-types.ts

typescript
export const CommandCategories = [
    {
        key: 'custom',
        label: '自定义',
        icon: 'icon-custom',
        commands: [
            {
                id: 'my-node',
                name: '我的节点',
                type: NodeKey.MY_NODE,
                icon: 'icon-custom',
                desc: '节点描述'
            }
        ],
    },
];

步骤 2: 添加节点键 ​

文件: src/automa/types/node-config.ts

typescript
export enum NodeKey {
    // ... 其他节点
    MY_NODE = 'my-node',
}

步骤 3: 添加节点 UI 配置 ​

文件: src/automa/types/node-config.ts

typescript
export const NodeTypesConfig: Record<NodeKey, NodeTypeConfig> = {
    // ... 其他节点
    [NodeKey.MY_NODE]: {
        label: '我的节点',
        icon: 'icon-custom',
        color: '#1890ff',
        category: 'custom',
    },
};

步骤 4: 定义表单配置 ​

文件: src/automa/types/node-config.ts

typescript
export const myNodeFormConfig: DynamicFormI = {
    showSide: false,
    cols: 1,
    fields: [
        {
            label: '参数1',
            key: 'param1',
            type: 'text',
            span: 1,
            required: true,
            tooltip: '参数说明',
        },
    ],
};

步骤 5: 定义节点类型 ​

文件: src/automa/types/node-types.ts

typescript
export interface MyNodeDefinition extends BaseNodeDefinition {
    type: NodeKey.MY_NODE;
    config: {
        param1: string;
        // ... 其他配置
    };
}

步骤 6: 添加到联合类型 ​

文件: src/automa/types/node-types.ts

typescript
export type SpecificNodeDefinition =
    | TriggerNodeDefinition
    | MyNodeDefinition  // 添加这行
    // ... 其他节点
    ;

步骤 7: 添加到映射 ​

文件: src/automa/types/node-types.ts

typescript
export interface NodeDefinitionMap {
    [NodeKey.MY_NODE]: MyNodeDefinition;
    // ... 其他节点
}

步骤 8: 创建执行器 ​

文件: src/main/engine/executors/MyNodeExecutor.ts

typescript
import { BaseNodeExecutor } from '../BaseNodeExecutor';
import type { ExecutionContext, NodeExecutionResult } from '@automa/types/engine-types';
import type { MyNodeDefinition } from '@automa/types/node-types';
import { NodeKey } from '@automa/types/node-config';

export default class MyNodeExecutor extends BaseNodeExecutor {
    type = NodeKey.MY_NODE;

    async execute(node: MyNodeDefinition, context: ExecutionContext): Promise<NodeExecutionResult> {
        try {
            // 获取配置
            const param1 = this.getConfig<string>(node, 'param1', '');
            
            // 解析变量
            const resolvedParam1 = this.resolveExpression(param1, context);
            
            // 执行逻辑
            const result = await this.doSomething(resolvedParam1);
            
            // 保存结果到变量
            await this.setVariable(context, 'myResult', result);
            
            return this.success({ result });
        } catch (error) {
            return this.failure(`执行失败: ${error}`);
        }
    }
    
    private async doSomething(param: string): Promise<string> {
        // 实现具体逻辑
        return `处理结果: ${param}`;
    }
}

步骤 9: 创建节点 UI 组件 ​

文件: src/renderer/pages/workflow/nodes/MyNodeNode.vue

vue
<template>
    <div class="my-node">
        <div class="node-header">
            <i class="erpfont icon-custom"></i>
            <span>{{ data.name || '我的节点' }}</span>
        </div>
        <div class="node-content">
            <div class="param-item">
                <span class="label">参数1:</span>
                <span class="value">{{ data.config?.param1 || '-' }}</span>
            </div>
        </div>
        <Handle type="target" :position="Position.Left" />
        <Handle type="source" :position="Position.Right" />
    </div>
</template>

<script setup lang="ts">
import { Handle, Position } from '@vue-flow/core';

defineProps<{
    data: {
        name?: string;
        config?: {
            param1?: string;
        };
    };
}>();
</script>

<style lang="scss" scoped>
@import './node-styles.scss';
</style>

步骤 10: 注册表单配置 ​

文件: src/renderer/pages/workflow/components/ConfigPanel/ConfigPanel.vue

typescript
import { myNodeFormConfig } from '@automa/types/node-config';

// 在 switch 语句中添加
case NodeKey.MY_NODE:
    return myNodeFormConfig;

7.2 执行器模板 ​

typescript
import { BaseNodeExecutor } from '../BaseNodeExecutor';
import type { ExecutionContext, NodeExecutionResult } from '@automa/types/engine-types';
import type { CustomNodeDefinition } from '@automa/types/node-types';
import { NodeKey } from '@automa/types/node-config';

export default class CustomNodeExecutor extends BaseNodeExecutor {
    type = NodeKey.CUSTOM_NODE;

    async execute(node: CustomNodeDefinition, context: ExecutionContext): Promise<NodeExecutionResult> {
        try {
            // 1. 获取配置
            const config1 = this.getConfig<string>(node, 'config1', '');
            
            // 2. 解析变量表达式
            const resolved = this.resolveExpression(config1, context);
            
            // 3. 获取上下文变量
            const existingVar = await this.getVariable<string>(context, 'someVar', '');
            
            // 4. 执行业务逻辑
            const result = await this.doBusinessLogic(resolved);
            
            // 5. 设置输出变量
            await this.setVariable(context, 'outputVar', result);
            
            // 6. 返回成功结果
            return this.success({ result });
        } catch (error) {
            // 7. 返回失败结果
            return this.failure(`执行失败: ${error}`);
        }
    }
}

8. API 开发指南 ​

8.1 API 架构 ​

text
Renderer (apiService.ts)
    ↓ IPC
Main (Controller)
    ↓
Service / Bean
    ↓
Native / Database

8.2 添加新 API ​

步骤 1: 定义类型 ​

文件: src/main/controller/NativeApiTypes.ts

typescript
export interface MyApiParams {
    param1: string;
    param2: number;
}

export interface MyApiResult {
    success: boolean;
    data?: any;
    error?: string;
}

步骤 2: 实现 Controller 方法 ​

文件: src/main/controller/NativeApiController.ts

typescript
@Bean()
export class NativeApiController {
    @Autowired()
    private readonly myService: MyService;
    
    public myApi(params: MyApiParams): ApiResultType<MyApiResult> {
        return this.wrapAsync(async () => {
            const result = await this.myService.doSomething(params);
            return { success: true, data: result };
        });
    }
}

步骤 3: 渲染进程调用 ​

typescript
import { execNativeCommand } from '@renderer/common/apiService';

const result = await execNativeCommand('myApi', {
    param1: 'value1',
    param2: 123,
});

8.3 API 命名规范 ​

类型命名示例
获取数据getXxxApigetWorkflowApi
执行操作xxxApiexecuteWorkflowApi
启动功能startXxxApistartRecordingApi
停止功能stopXxxApistopRecordingApi

9. 数据库设计 ​

9.1 实体关系 ​

text
FolderEntity (文件夹)
    │
    └── WorkflowEntity (工作流)
            │
            ├── WorkflowWorkerEntity (执行实例)
            │       │
            │       └── WorkflowLogEntity (执行日志)
            │
            ├── WorkflowVariablesEntity (变量)
            │
            ├── WorkflowCookieEntity (Cookie)
            │
            └── WorkflowStatisticsEntity (统计)

CapturedElementEntity (捕获元素) - 独立

ScreenshotEntity (截图) - 独立

9.2 主要实体 ​

WorkflowEntity ​

typescript
@Entity('workflow')
export class WorkflowEntity extends BaseEntity {
    @Column() name: string;
    @Column() folderId: string;
    @Column('simple-json') definition: WorkflowDefinition;
    @Column() enabled: boolean;
}

WorkflowWorkerEntity ​

typescript
@Entity('workflow_worker')
export class WorkflowWorkerEntity extends BaseEntity {
    @Column() workflowId: string;
    @Column() status: WorkerStatus;
    @Column() currentNodeId: string;
    @Column('simple-json') variables: Record<string, unknown>;
    @Column() startTime: Date;
    @Column() endTime: Date;
    @Column() error: string;
}

9.3 数据库操作 ​

typescript
// 获取 Repository
const repo = this.db.ds.getRepository(WorkflowEntity);

// 查询
const workflow = await repo.findOne({ where: { id } });
const workflows = await repo.find({ where: { folderId } });

// 保存
await repo.save(workflow);

// 删除
await repo.delete({ id });

10. 常见问题 ​

10.1 开发相关 ​

Q: 如何调试主进程?

A: 在 VSCode 中使用 Electron 调试配置,或在代码中使用 console.log,日志会输出到终端。

Q: 如何调试渲染进程?

A: 使用 Chrome DevTools,在应用窗口中按 Ctrl+Shift+I (Windows) 或 Cmd+Option+I (macOS)。

Q: 原生模块编译失败?

A: 运行以下命令重新编译:

bash
npm rebuild better-sqlite3 --runtime=electron --target=30.5.1

10.2 运行相关 ​

Q: 工作流执行失败怎么排查?

A:

  1. 查看执行日志(数据库 workflow_log 表)
  2. 查看系统日志(config/logs/automa_agent.log)
  3. 检查变量值是否正确

Q: 定时任务不执行?

A:

  1. 检查 Cron 表达式是否正确
  2. 确认工作流已启用
  3. 查看 CronManager 日志

Q: 浏览器窗口无法打开?

A:

  1. 检查 URL 是否正确
  2. 检查网络连接
  3. 查看是否有安全策略阻止

10.3 部署相关 ​

Q: 打包后应用无法启动?

A:

  1. 检查原生模块是否正确打包
  2. 检查配置文件路径
  3. 查看应用日志

Q: 如何配置开机自启?

A: 应用默认配置了开机自启,可在代码中修改:

typescript
app.setLoginItemSettings({
    openAtLogin: true,
    openAsHidden: true,
});

附录 ​

A. 组件库文档 ​

B. 相关资源 ​

C. Git 规范 ​

bash
# 查看最近提交
git --no-pager log --oneline -20

# 查看当前分支提交
git --no-pager log $(git merge-base HEAD origin/master)..HEAD --no-merges --oneline

企业级桌面 RPA 自动化平台 · 联系我们