第 10 章:综合项目:RPA 桌面助手

本章将综合运用前面所有章节的知识,从零构建一个模仿影刀 RPA 的桌面自动化助手。 项目包含可视化流程编辑器、操作录制与回放、数据管理等核心功能,是一个完整的生产级 Electron 应用。

10.1 项目需求分析

影刀 RPA 是一款流行的桌面自动化工具,核心功能包括:可视化流程编排、鼠标键盘录制、 自动化任务执行、数据表格管理等。我们将实现一个简化但功能完整的版本。

功能清单

模块功能技术点
流程编辑器拖拽式节点编排Vue3 + 自定义拖拽
操作录制记录鼠标/键盘操作@nut-tree/nut.js
任务回放执行录制的操作序列IPC + 工作线程
数据管理变量、数据表格Pinia + SQLite
截图识别屏幕截图 + OCRdesktopCapturer + Tesseract
任务调度定时执行、循环执行Node.js 定时器

10.2 架构设计

好的架构是项目成功的一半。我们采用分层设计,将核心自动化逻辑放在主进程,UI 层放在渲染进程。

text
┌─────────────────────────────────────────────────────────┐
│                    RPA Desktop Assistant                 │
├─────────────────────────────────────────────────────────┤
│  渲染进程 (Renderer)                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │ 流程编辑器    │  │ 任务列表      │  │ 数据表格      │  │
│  │ (Vue3)       │  │ (Vue3)       │  │ (Vue3)       │  │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  │
│         │                 │                 │          │
│         └─────────────────┼─────────────────┘          │
│                           │                            │
│  ┌────────────────────────┴────────────────────────┐   │
│  │              IPC (contextBridge)                 │   │
│  └────────────────────────┬────────────────────────┘   │
├───────────────────────────┼─────────────────────────────┤
│  主进程 (Main)            │                              │
│  ┌────────────────────────┴────────────────────────┐   │
│  │              自动化引擎 (Automation Engine)       │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐        │   │
│  │  │ 录制器    │ │ 执行器    │ │ 调度器    │        │   │
│  │  │ Recorder │ │ Executor │ │ Scheduler│        │   │
│  │  └──────────┘ └──────────┘ └──────────┘        │   │
│  └─────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────┐   │
│  │              数据层 (Data Layer)                 │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐        │   │
│  │  │ electron-│ │  SQLite  │ │ 文件系统  │        │   │
│  │  │ store    │ │          │ │          │        │   │
│  │  └──────────┘ └──────────┘ └──────────┘        │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

10.3 项目初始化

使用 electron-vite 创建项目,并安装必要的依赖。

bash
# 创建项目
npm create electron-vite@latest rpa-assistant --template vue-ts

# 进入项目目录
cd rpa-assistant

# 安装核心依赖
npm install @nut-tree/nut-js tesseract.js electron-store pinia vue-router element-plus

# 安装开发依赖
npm install -D @types/node electron-builder electron-updater

# 安装 Sentry(可选)
npm install @sentry/electron

10.4 核心模块实现

自动化引擎(主进程)

javascript
// main/automation/engine.js
const { mouse, keyboard, screen, clipboard } = require('@nut-tree/nut-js');
const { ipcMain } = require('electron');

class AutomationEngine {
  constructor() {
    this.isRecording = false;
    this.isPlaying = false;
    this.actions = [];
    this.setupIPC();
  }

  setupIPC() {
    // 开始录制
    ipcMain.handle('automation:start-record', () => {
      this.startRecording();
      return { success: true };
    });

    // 停止录制
    ipcMain.handle('automation:stop-record', () => {
      const actions = this.stopRecording();
      return { success: true, actions };
    });

    // 执行流程
    ipcMain.handle('automation:execute', async (event, actions) => {
      try {
        await this.executeActions(actions, (progress) => {
          event.sender.send('automation:progress', progress);
        });
        return { success: true };
      } catch (error) {
        return { success: false, error: error.message };
      }
    });
  }

  startRecording() {
    this.isRecording = true;
    this.actions = [];
    
    // 监听鼠标移动
    mouse.config.mouseSpeed = 500;
    
    // 记录初始状态
    this.recordAction({
      type: 'start',
      timestamp: Date.now()
    });
  }

  stopRecording() {
    this.isRecording = false;
    return this.actions;
  }

  recordAction(action) {
    if (this.isRecording) {
      this.actions.push(action);
    }
  }

  // 执行操作序列
  async executeActions(actions, onProgress) {
    this.isPlaying = true;
    const total = actions.length;

    for (let i = 0; i < actions.length; i++) {
      if (!this.isPlaying) break;

      const action = actions[i];
      await this.executeAction(action);
      
      onProgress?.({
        current: i + 1,
        total,
        percent: Math.round(((i + 1) / total) * 100)
      });
    }

    this.isPlaying = false;
  }

  async executeAction(action) {
    switch (action.type) {
      case 'mouse-move':
        await mouse.move({ x: action.x, y: action.y });
        break;
      
      case 'mouse-click':
        await mouse.click();
        break;
      
      case 'mouse-double-click':
        await mouse.doubleClick();
        break;
      
      case 'mouse-right-click':
        await mouse.rightClick();
        break;
      
      case 'key-press':
        await keyboard.type(action.key);
        break;
      
      case 'key-combination':
        await keyboard.type(action.keys);
        break;
      
      case 'wait':
        await new Promise(resolve => setTimeout(resolve, action.duration));
        break;
      
      case 'clipboard-set':
        await clipboard.copy(action.text);
        break;
      
      case 'screenshot':
        const screenshot = await screen.capture();
        // 保存截图...
        break;
    }
  }

  stopExecution() {
    this.isPlaying = false;
  }
}

module.exports = { AutomationEngine };

可视化流程编辑器(Vue3)

vue





10.5 Preload 脚本配置

为项目配置完整的 Preload 脚本,暴露所有需要的 API。

javascript
// preload/index.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  // ===== 自动化 API =====
  automation: {
    startRecord: () => ipcRenderer.invoke('automation:start-record'),
    stopRecord: () => ipcRenderer.invoke('automation:stop-record'),
    execute: (actions) => ipcRenderer.invoke('automation:execute', actions),
    onProgress: (callback) => ipcRenderer.on('automation:progress', callback),
    offProgress: (callback) => ipcRenderer.removeListener('automation:progress', callback)
  },

  // ===== 文件 API =====
  file: {
    open: (options) => ipcRenderer.invoke('dialog:openFile', options),
    save: (options, content) => ipcRenderer.invoke('dialog:saveFile', options, content),
    read: (path) => ipcRenderer.invoke('file:read', path)
  },

  // ===== 屏幕 API =====
  screen: {
    capture: () => ipcRenderer.invoke('screen:capture'),
    getSize: () => ipcRenderer.invoke('screen:getSize')
  },

  // ===== 系统 API =====
  system: {
    getVersion: () => ipcRenderer.invoke('app:getVersion'),
    getPlatform: () => process.platform
  },

  // ===== 更新 API =====
  update: {
    check: () => ipcRenderer.invoke('update:check'),
    install: () => ipcRenderer.invoke('update:install'),
    onAvailable: (callback) => ipcRenderer.on('update-available', callback),
    onProgress: (callback) => ipcRenderer.on('update-progress', callback)
  }
});

10.6 打包与发布

完成开发后,使用 electron-builder 打包应用并发布。

yaml
# electron-builder.yml
appId: com.yourcompany.rpa-assistant
productName: "RPA Desktop Assistant"

directories:
  output: release
  buildResources: build

files:
  - "out/**/*"
  - "node_modules/**/*"
  - "package.json"

asarUnpack:
  - "node_modules/@nut-tree/**/*"
  - "node_modules/tesseract.js/**/*"

win:
  target:
    - nsis
  icon: build/icon.ico

mac:
  target:
    - dmg
  icon: build/icon.icns
  category: public.app-category.productivity

publish:
  provider: github
  owner: your-username
  repo: rpa-assistant

10.7 项目总结

通过这个综合项目,我们实践了 Electron 桌面应用开发的完整流程:

  1. 环境搭建

    使用 electron-vite 快速搭建 Vue3 + Electron 工程化项目

  2. 核心功能

    实现了录制、回放、可视化编辑等 RPA 核心功能

  3. 系统交互

    使用 @nut-tree/nut-js 实现鼠标键盘控制,使用 desktopCapturer 实现截图

  4. 数据管理

    使用 Pinia 管理应用状态,使用 electron-store 持久化配置

  5. 打包发布

    使用 electron-builder 打包为 Windows 和 macOS 安装包

🎉 congratulations!

你已经完成了 Electron 桌面应用开发的系统学习!从前端开发者到桌面应用工程师, 你现在具备了构建跨平台桌面应用的完整能力。继续深入某个方向(如更复杂的自动化、 AI 集成、企业级功能),或者开始你的下一个项目吧!