npm package: @nywqs/scada-engine
Description: 自研 SCADA 组态引擎 - 基于 AntV X6
Author: wqs
Latest version: 2.0.3
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.



# @nywqs/scada-engine

基于 AntV X6 + Vue 3 的自研 SCADA 组态引擎。旨在为工业物联网（IIoT）提供高性能、可扩展的可视化组态解决方案，支持拖拽式界面设计、实时数据绑定及复杂的流程编排。

## 特性

- 🛠 **可视化编辑器**：基于 AntV X6 构建的专业级图形编辑能力，支持节点拖拽、连线编排、框选复制等操作。
- 📦 **丰富组件库**：
  - **基础组件**：矩形、圆形、文本等基础矢量图形。
  - **IoT 组件**：支持 ECharts 图表（仪表盘、折线图）、3D 设备模型（电机、管道、阀门、储罐等）、指示灯、开关等工业控件。
- 🔗 **多源数据集成**：内置服务层，支持 WebSocket、MQTT、HTTP 请求及 SSE（Server-Sent Events）等多种实时数据接入方式。
- 🎨 **动画引擎**：内置独立的动画调度器（AnimationScheduler）与动画引擎（AnimationEngine），支持脉冲、闪烁、旋转等节点特效。
- ⚙️ **流程编排**：内置可视化工作流编辑器（Workflow Editor），支持通过逻辑节点（条件判断、定时器、HTTP 请求、自定义代码）编排复杂业务流程。
- 🔐 **授权与安全**：基于 ECDSA P-256 + SHA-256 的数字签名授权机制，保障软件使用安全。
- 🚀 **性能优化**：支持视口裁剪（Viewport Culling）技术，在保证视觉效果的同时优化大数据量场景下的渲染性能。

## 安装

### 环境要求

确保你的项目中已安装以下依赖：

```bash
npm install vue@^3.4.0 @antv/x6@^3.1.6 echarts@^5.5.0 pinia@^2.1.0 @vueuse/core@^10.0.0
```

### 安装引擎

```bash
npm install @nywqs/scada-engine
# 或
pnpm add @nywqs/scada-engine
# 或
yarn add @nywqs/scada-engine
```

## 快速开始

### 1. 全局注册

在你的应用入口文件（如 `main.ts`）中引入并注册组件：

```typescript
import { createApp } from 'vue'
import ScadaEngine from '@nywqs/scada-engine'
import '@nywqs/scada-engine/dist/scada-engine.css' // 引入样式
import App from './App.vue'

const app = createApp(App)
app.use(ScadaEngine)
app.mount('#app')
```

### 2. 在组件中使用

最核心的组件是 `ScadaCanvas`，它承载了画布编辑器和预览功能。

```vue
<template>
  <div class="scada-container" style="width: 100vw; height: 100vh;">
    <ScadaCanvas 
      ref="canvasRef"
      :auth-code="authCode"
      @node-click="handleNodeClick"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ScadaCanvas } from '@nywqs/scada-engine'

const canvasRef = ref()
const authCode = '你的授权码' // 商业版本需要

const handleNodeClick = (node) => {
  console.log('点击了节点:', node.id)
}

// 使用 API 方法
onMounted(() => {
  // 添加节点
  canvasRef.value?.addNode('rect')
  
  // 获取画布数据
  const data = canvasRef.value?.getCanvasData()
  console.log('画布数据:', data)
})
</script>

<style scoped>
.scada-container {
  position: relative;
}
</style>
```

### 3. 自定义组件注册

你可以注册自定义的 SCADA 组件：

```typescript
import { componentRegistry } from '@nywqs/scada-engine'

// 注册自定义组件
componentRegistry.register({
  type: 'custom-sensor',
  name: '自定义传感器',
  category: 'iot',
  icon: '🔌',
  defaultSize: { width: 100, height: 100 },
  props: {
    value: { type: 'number', default: 0 },
    unit: { type: 'string', default: '°C' }
  },
  component: () => import('./components/CustomSensor.vue')
})
```

### 4. 数据绑定与实时更新

```typescript
import { dataSourceManager } from '@nywqs/scada-engine'

// 配置 WebSocket 数据源
await dataSourceManager.addSource({
  id: 'ws-1',
  type: 'websocket',
  url: 'ws://localhost:8080',
  autoConnect: true
})

// 订阅数据更新
dataSourceManager.subscribe('device_01.temperature', (value) => {
  console.log('温度更新:', value)
})
```

## 目录结构

项目采用了清晰的模块划分：

```
src/
├── components/              # 核心 UI 组件
│   ├── canvas/              # 画布组件
│   │   ├── ScadaCanvas.vue  # 核心画布组件
│   │   ├── composables/     # 画布组合式 API
│   │   ├── config/          # 画布配置
│   │   └── types/           # 画布类型定义
│   ├── configurators/       # 配置器组件
│   │   ├── BindingCard.vue  # 数据绑定配置
│   │   ├── EventCard.vue    # 事件配置
│   │   └── ...
│   ├── dialogs/             # 对话框组件
│   │   ├── AttributeConfigDialog.vue
│   │   ├── CustomCodeDialog.vue
│   │   └── ...
│   ├── layout/              # 布局组件
│   │   ├── Header.vue       # 顶部工具栏
│   │   └── Footer.vue       # 底部版权栏
│   ├── panels/              # 面板组件
│   │   ├── PropertyPanel.vue      # 属性面板
│   │   ├── ComponentLibrary.vue   # 组件库面板
│   │   ├── CanvasConfigPanel.vue  # 画布配置面板
│   │   └── ContextMenu.vue        # 右键菜单
│   └── property-tabs/       # 属性标签页
│       ├── BasicPropertiesTab.vue
│       ├── DataPropertiesTab.vue
│       └── EdgePropertiesTab.vue
├── scada-components/        # SCADA 组件库
│   ├── basic/               # 基础图形组件
│   │   ├── rect.ts          # 矩形组件
│   │   ├── circle.ts        # 圆形组件
│   │   └── text.ts          # 文本组件
│   ├── iot/                 # IoT 设备组件
│   │   ├── echarts-gauge/   # ECharts 仪表盘
│   │   ├── echarts-line/    # ECharts 折线图
│   │   └── model3d/         # 3D 设备模型
│   ├── svg/                 # SVG 组件系统
│   │   ├── core/            # SVG 核心（加载器、解析器）
│   │   ├── rendering/       # SVG 渲染引擎
│   │   ├── helpers/         # SVG 辅助工具
│   │   └── examples/        # SVG 示例组件
│   ├── canvas/              # 画布配置管理
│   │   ├── config.ts        # 预设配置
│   │   ├── manager.ts       # 配置管理器
│   │   └── types.ts         # 类型定义
│   ├── registry.ts          # 组件注册表
│   └── types.ts             # 组件类型定义
├── services/                # 数据服务层
│   ├── dataSourceManager.ts # 数据源管理器
│   ├── websocketService.ts  # WebSocket 服务
│   ├── mqttService.ts       # MQTT 服务
│   ├── httpService.ts       # HTTP 服务
│   ├── sseService.ts        # SSE 服务
│   └── dataParser.ts        # 数据解析器
├── utils/                   # 工具函数与引擎核心
│   ├── animation/           # 动画系统
│   │   ├── animation-engine.ts     # 动画引擎
│   │   └── animation-scheduler.ts  # 动画调度器
│   ├── canvas/              # 画布操作工具
│   │   ├── graph-operations.ts  # 画布操作
│   │   ├── node-operations.ts   # 节点操作
│   │   ├── edge-operations.ts   # 连线操作
│   │   └── layer-manager.ts     # 图层管理
│   ├── core/                # 核心工具
│   │   ├── common.ts        # 通用工具
│   │   ├── storage.ts       # 本地存储
│   │   ├── file.ts          # 文件操作
│   │   └── message.ts       # 消息提示
│   ├── data/                # 数据处理
│   │   ├── binding-service.ts   # 数据绑定服务
│   │   └── node-property.ts     # 节点属性管理
│   ├── events/              # 事件系统
│   │   ├── event-manager.ts     # 事件管理器
│   │   ├── event-utils.ts       # 事件工具
│   │   └── context-menu.ts      # 右键菜单
│   ├── integrations/        # 集成模块
│   │   ├── auth-crypto.ts       # 授权加密
│   │   └── draco-loader.ts      # 3D 模型加载
│   └── performance/         # 性能优化
│       ├── viewport-culling.ts  # 视口裁剪
│       └── worker-manager.ts    # Worker 管理
├── views/                   # 视图页面
│   ├── workflow/            # 流程编排模块
│   │   ├── WorkflowDialog.vue   # 流程编辑对话框
│   │   ├── components/          # 流程组件
│   │   ├── services/            # 流程服务
│   │   └── types/               # 流程类型
│   └── Preview.vue          # 预览页面
├── types/                   # 全局类型定义
│   ├── device.ts            # 设备类型
│   ├── binding.ts           # 绑定类型
│   ├── workflow.ts          # 流程类型
│   └── ...
├── constants/               # 常量定义
│   ├── theme.ts             # 主题常量
│   ├── layout.ts            # 布局常量
│   └── animation.ts         # 动画常量
├── workers/                 # Web Workers
│   └── dataProcessor.worker.ts  # 数据处理 Worker
├── styles/                  # 全局样式
│   ├── theme.css            # 主题样式
│   └── components/          # 组件样式
├── index.ts                 # 库入口文件
├── main.ts                  # 开发入口文件
└── App.vue                  # 根组件
```

## 核心概念

### 画布 (ScadaCanvas)

画布是整个系统的核心，提供以下能力：
- **编辑模式**：用于设计组态画面。
- **预览模式**：用于运行展示，隐藏编辑 UI。
- **数据绑定**：支持将设备点位（Point）绑定到组件属性，实时更新显示。

### 组件注册系统 (ComponentRegistry)

引擎使用了懒加载注册机制来优化性能。
- 支持按分类（`basic`, `iot`）获取组件列表。
- 支持动态注册新组件。

### 数据服务 (Data Services)

引擎不强制绑定特定后端，提供了灵活的数据接入适配器：
- **WebSocket**：适用于高频实时数据。
- **MQTT**：适用于物联网消息订阅。
- **HTTP**：适用于请求-响应式查询。
- **SSE**：适用于服务器推送事件。

### 流程引擎 (Workflow Engine)

内置的可视化脚本系统，允许用户在画布上通过图形化节点编写逻辑，无需编写大量代码即可实现：
- 定时触发任务
- 条件判断分支
- HTTP 外部请求
- 自定义 JavaScript 代码执行

## API 参考

### ScadaCanvas 方法

通过 `ref` 可以直接调用画布的操作方法：

| 方法 | 说明 |
|------|------|
| **文件操作** | |
| `save()` | 保存当前画布数据到 LocalStorage |
| `exportFile()` | 导出当前画布为 JSON 文件 |
| `importFile()` | 触发文件选择器导入 JSON |
| **视图操作** | |
| `preview()` | 跳转到预览页面 |
| `workflow()` | 打开流程编排弹窗 |
| **画布操作** | |
| `zoomIn()` / `zoomOut()` | 放大/缩小画布 |
| `setZoom(scale)` | 设置画布缩放比例 |
| `clearAll()` | 清空画布所有元素 |
| **节点操作** | |
| `addNode(type)` | 添加指定类型的节点 |
| `updateNode(data)` | 更新节点数据 |
| `deleteNode()` | 删除当前选中的节点 |
| `getSelectedNode()` | 获取当前选中的节点 |
| `selectNode(nodeId)` | 选中指定节点 |
| `clearSelection()` | 取消选中 |
| **数据访问** | |
| `getGraph()` | 获取 X6 Graph 实例 |
| `getCanvasData()` | 获取画布完整数据（包含节点、连线和配置） |
| `loadCanvasData(data)` | 加载画布数据 |
| `getAllNodes()` | 获取所有节点 |
| `getNodeById(nodeId)` | 根据 ID 获取节点 |
| **画布配置** | |
| `getConfigManager()` | 获取画布配置管理器 |
| `updateCanvasConfig(config)` | 更新画布配置 |
| `setCanvasSize(width, height)` | 设置画布大小 |
| `setBackgroundColor(color)` | 设置背景颜色 |
| **动画控制** | |
| `getAnimationEngine()` | 获取动画引擎 |

### 数据结构示例

`getCanvasData()` 返回的结构大致如下：

```json
{
  "version": "1.0",
  "config": {
    "width": 1920,
    "height": 1080,
    "grid": true
  },
  "cells": [
    {
      "id": "node-1",
      "type": "rect",
      "x": 100,
      "y": 100,
      "label": "电机",
      "data": { "binding": "device_01_status" }
    }
  ]
}
```

## 许可证

本项目采用 MIT 许可证。内置的组件库和引擎功能可以免费用于学习和非商业项目。

**商业授权**：如需将本引擎用于商业产品并隐藏底部版权标识，请联系作者获取数字签名授权。

## 作者

- **nywqs**

如有问题或建议，欢迎提交 Issue 或联系作者。