news 2026/10/15 1:19:41

FUXA 组态屏:基于 Vue + Node 的 Web 工业 HMI 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FUXA 组态屏:基于 Vue + Node 的 Web 工业 HMI 实战指南

简介:Web组态设计器FUXA是一套面向工业控制领域的Web端组态开发工具,适合希望以低代码方式搭建监控与配置界面的工程师、前端开发者及自动化从业者。它基于Vue.js构建可视化视图层,借助Node.js处理后端逻辑与API交互,让不熟悉编程的用户也能通过拖放式图形界面完成控制逻辑编辑、远程配置与实时数据监控,并兼容OPC UA、MODBUS等常见工业协议。资源包共1195个文件,约13.92MB,以423个svg图标、271个ts脚本、117个html页面、107个js逻辑、96个css样式为主,另含字体、json配置、scss源码及dockerfile、yml部署文件,结构完整。目前已有2649人学习下载。通过该资源可了解组态设计器的前端组件组织、脚本编辑器与样式体系,掌握工业Web应用的界面搭建与数据交互思路,适合作为学习或二次开发的基础工程参考。

1. 组态屏不用装客户端了:FUXA 把工业 HMI 搬进浏览器

车间里那台老组态软件又弹授权到期了,产线停机等 IT 来插加密狗——这种场景做工业自动化的都懂。FUXA 就是冲着这个痛点来的:一个基于 Vue.js + Node.js 的纯 Web 组态设计器,打开浏览器就能画工艺流程、绑设备数据、跑实时监控,不用在每台 HMI 上装运行时。它把传统组态软件那套「拖控件、连变量、配动画」的交互逻辑搬到了前端框架里,底层用 Node.js 做数据网关,前端用 Vue 做渲染和编辑器。适合谁?做 SCADA/HMI 的自动化工程师、想给设备加远程看板的嵌入式开发者、以及需要快速搭工业可视化 Demo 的全栈。下面按「它怎么跑起来 → 编辑器怎么用 → 数据怎么接 → 坑在哪」的顺序拆一遍。

2. 跑起来之前:FUXA 的架构分层与本地启动

2.1 为什么是 Vue + Node 这套组合

传统组态软件(如某经典 HMI 组态工具)是 C/S 架构,设计器和运行时绑死,换台机器就得重装授权。FUXA 选 Vue.js 做前端不是赶时髦——组态编辑器本质是一个「画布 + 属性面板 + 图元库」的复杂状态管理场景,Vue 的响应式系统天然适合处理「拖一个阀门到画布,属性面板立刻刷新,绑定变量后动画实时联动」这类联动。Node.js 做后端则承担三件事:托管前端静态资源、提供 REST API 做项目文件的增删改查、以及通过 WebSocket 把设备数据推给前端。

这个分层的实际意义是:设计器可以在你的笔记本上跑,运行时可以部署到车间一台工控机上,两者通过项目文件(JSON)解耦。你画好的画面导出成一个工程文件,拷到现场机器导入就能跑,不需要重新组态。

常见做法是把 FUXA 部署在内网一台 Linux 工控机上,用 Node 进程常驻,浏览器访问http://工控机IP:1881即可。1881 是它的默认端口,改端口在配置文件里调。

2.2 从源码到可访问:启动步骤

FUXA 的源码结构大致是client/(Vue 前端)和server/(Node 后端)两部分。如果你拿到的是源码包,标准启动流程如下:

# 1. 确认 Node 版本,建议 16.x 或 18.x LTS node -v # 2. 安装依赖(在项目根目录) npm install # 3. 开发模式启动(前后端一起起) npm start

如果你拿到的是已经构建好的发布包,通常只需要:

# 进入 server 目录 cd server npm install --production node main.js

启动后浏览器访问http://localhost:1881,能看到登录页或直接进编辑器界面。默认账号密码一般在项目 README 或server/config里,首次登录后建议立刻改掉。

提示:如果 1881 端口被占用,改server/config/default.json里的port字段,重启生效。别去改前端代码里的硬编码端口,那是构建时写死的。

2.3 目录结构里哪些文件你迟早要动

路径作用什么时候动它
server/main.js后端入口,启动 HTTP + WebSocket改端口、加中间件
server/runtime/设备驱动与数据采集逻辑接 Modbus、OPC UA 等
client/src/Vue 前端源码改编辑器 UI、加自定义图元
server/config/配置文件改端口、数据库路径
_projects/工程文件存储目录备份、迁移项目

工程文件默认存在_projects/下,每个项目一个文件夹,里面是 JSON 描述的画面、变量、动画绑定。迁移时整个文件夹拷走即可,这是它比传统组态软件省事的地方——没有注册表、没有加密狗、没有机器绑定。

3. 编辑器实操:画一张能动的工艺画面

3.1 图元拖拽与画面组织

进编辑器后左侧是图元库,分基础形状(矩形、圆、线)、工业符号(泵、阀、罐、电机)、以及 SVG 导入的自定义图元。中间是画布,右侧是属性面板。操作逻辑和主流前端可视化工具类似:拖一个矩形到画布,右侧改填充色、边框、圆角;再拖一个文本标签叠上去显示数值。

画面组织用「图层」概念,但 FUXA 的图层比较轻量——本质是 SVG 元素的 z-index 排序。建议按功能分组:底层放管道和背景,中层放设备图元,顶层放数值标签和报警指示灯。这样后期改管道走向不会误动设备。

一个容易被忽略的点:画布尺寸要提前定好。FUXA 默认画布是 1920×1080,如果你现场 HMI 是 1024×768 的触摸屏,画布尺寸设错会导致运行时出现滚动条或元素被裁切。在项目设置里改canvasWidth和canvasHeight,改完所有图元按比例缩放,但文字大小不会自动缩,需要手动调。

3.2 变量绑定与动画配置

组态的核心是「图元属性绑变量」。在 FUXA 里,选中一个图元,右侧属性面板找到「动画」或「绑定」入口,把填充色、可见性、旋转角度等属性关联到一个变量上。

// 变量定义示例(在项目变量表里配置) { "name": "Tank1_Level", // 变量名,绑定时用这个 "type": "number", // 数据类型:number / boolean / string "address": "40001", // 设备寄存器地址 "driver": "modbus", // 驱动类型 "scale": 0.1, // 缩放系数,原始值 × 0.1 "unit": "%" // 单位,仅显示用 }

逻辑说明:address是设备侧的寄存器地址,driver决定用哪个采集驱动去读。scale这个参数血泪经验——很多液位计原始值是 0~10000 对应 0~100%,不设缩放的话画面上显示「8500%」这种离谱数值。type选错会导致动画不触发,比如布尔量绑了 number 类型,指示灯永远不变色。

动画配置里最常用的是「填充百分比」——把一个矩形的高度或填充区域绑到变量上,变量 0 时填充 0%,100 时填满。FUXA 支持用 SVG 的clip-path或直接改矩形高度来实现,前者性能更好,后者更直观。我一般用改高度,因为调试时一眼能看出绑没绑上。

3.3 画面切换与事件脚本

多画面项目需要导航按钮。FUXA 支持在按钮上绑「点击事件」,动作类型选「切换画面」,目标画面从下拉列表选。如果要做条件跳转(比如报警时强制跳到报警画面),需要写一小段脚本:

// 按钮点击事件脚本示例 // 检查报警变量,有报警则跳报警画面,否则跳主画面 if (vars.Alarm_Active === true) { navigateTo('alarm_page'); } else { navigateTo('main_page'); }

参数说明:vars是全局变量对象,navigateTo是内置的画面切换函数,参数是画面 ID(在画面属性里能看到)。注意变量名大小写敏感,Alarm_Active和alarm_active是两个变量。脚本执行是同步的,别在里面写延时逻辑,会卡住 UI 线程。

4. 数据接入:Modbus 驱动配置与实时刷新

4.1 驱动配置的四个关键参数

FUXA 内置了 Modbus TCP/RTU、OPC UA、MQTT 等常见驱动。以 Modbus TCP 为例,在「设备」管理里新增一个设备,填四个参数:

参数说明典型值
设备名称自定义标识PLC_Line1
驱动类型选 Modbus TCPmodbus-tcp
IP 地址PLC 的 IP192.168.1.10
端口Modbus 端口502
轮询间隔采集周期(ms)1000

轮询间隔别设太小。设 100ms 以下,Node 进程的 CPU 占用会明显上升,而且很多 PLC 的 Modbus 服务端扛不住高频请求,会出现连接被拒。我一般设 500~1000ms,对大多数工艺参数够用了。如果是快速变化的量(比如电机转速),再单独给那个设备设 200ms。

4.2 变量表与地址映射

设备建好后,在变量表里逐个添加变量,每个变量关联到设备和寄存器地址。Modbus 地址格式要注意:FUXA 里通常用「寄存器类型 + 偏移」的方式,比如 Holding Register 40001 写成hr:0或40001,取决于版本。这个翻车过——不同组态软件对 40001 的偏移处理不一样,有的从 0 开始算,有的从 1 开始。接上后读不到数据,先检查地址偏移。

// 批量导入变量的 CSV 格式示例 // name,type,address,driver,scale,unit Tank1_Level,number,hr:0,modbus-tcp,0.1,% Tank1_Temp,number,hr:1,modbus-tcp,0.1,℃ Pump1_Run,boolean,co:0,modbus-tcp,1,

逻辑说明:hr是 Holding Register,co是 Coil。批量导入比一个个手填快得多,尤其是变量上百个的项目。CSV 里scale填 1 表示不缩放,布尔量单位留空。

4.3 实时刷新与 WebSocket 推送

FUXA 后端采集到数据后,通过 WebSocket 推给前端。前端收到消息后更新变量值,Vue 的响应式系统自动触发绑定了该变量的图元重绘。这条链路是:设备 → Node 驱动 → 变量缓存 → WebSocket → Vue 组件 → SVG 属性更新。

如果画面数据不刷新,按这个顺序排查:先看后端日志有没有采集到数据(server控制台会打印驱动连接状态),再看浏览器开发者工具的 WebSocket 帧有没有收到消息,最后检查变量名是否和图元绑定的一致。常见情况是变量名拼错,或者变量没启用(变量表里有个enabled开关,默认可能是关的)。

5. 避坑与排查:那些让你加班到凌晨的细节

5.1 画面元素错位:画布缩放与坐标基准

现象:在 1920×1080 画布上排得好好的图元,换到 1366×768 的屏幕上跑,元素全挤在左上角或超出边界。

原因:FUXA 默认按画布原始尺寸渲染,不自动做响应式缩放。图元坐标是绝对像素值,屏幕变小后视口裁切,元素位置不变但可见区域变了。

解决:在项目设置里开启「自适应缩放」,或者手动把画布尺寸设成目标屏幕的分辨率。如果要做多分辨率适配,用 SVG 的viewBox属性做等比缩放,但文字会跟着缩,小屏幕上可能看不清。我一般直接按现场屏幕分辨率定画布,不做自适应,省事且可控。

5.2 变量读不到值:驱动连接与地址偏移

现象:设备配置显示「已连接」,但所有变量值都是 0 或 null。

原因:三种可能——地址偏移不对(40001 写成 40000 或 40002)、寄存器类型选错(把 Holding Register 选成 Input Register)、或者 PLC 侧没开放对应地址的读取权限。

解决:先用 Modbus 调试工具(如 Modbus Poll)单独测一下地址能不能读到值,确认地址和类型无误后再回 FUXA 配。如果调试工具能读、FUXA 读不到,检查 FUXA 的驱动日志,看它实际发出的请求地址是什么。地址偏移问题在 Modbus 里是玄学级别的常见,不同厂商的 PLC 对 40001 的起始定义不一样。

5.3 前端构建失败:Node 版本与依赖冲突

现象:npm install报错,或者npm run build卡在某个依赖的编译上。

原因:FUXA 的某些依赖(尤其是涉及串口或原生模块的)对 Node 版本敏感。Node 20+ 上跑老版本的node-sass或serialport经常编译失败。

解决:用 Node 16 或 18 LTS。如果必须用高版本 Node,把node-sass换成sass(dart-sass),把serialport升到最新版。package.json里的engines字段可以锁版本,但 npm 默认不强制,需要加.npmrc配engine-strict=true。

5.4 项目文件丢失:_projects 目录的备份

现象:重启服务后,之前画的画面全没了。

原因:FUXA 默认把工程存在_projects/下,如果你用 Docker 跑且没挂载卷,容器重启后数据丢失。或者手动清理时误删了该目录。

解决:生产环境必须把_projects/挂载到宿主机卷。Docker 启动时加-v /host/path/_projects:/app/_projects。另外定期导出项目文件(编辑器里有导出功能),导出的 JSON 可以存 Git,版本管理比传统组态软件的二进制工程文件友好得多。

5.5 脚本不执行:事件绑定与作用域

现象:按钮上写的脚本没反应,控制台也没报错。

原因:事件类型选错了(比如该用onClick选了onMouseDown),或者脚本里引用了不存在的变量导致静默失败。

解决:先在脚本第一行加console.log('script triggered'),确认事件有没有触发。如果触发了但后续逻辑没跑,逐步注释排查。FUXA 的脚本沙箱对未定义变量不报错,直接返回 undefined,所以变量名拼错很难发现。建议脚本里所有变量引用前先做存在性判断。

6. 进阶:自定义图元与 SVG 导入的实用技巧

当你把基础画面跑通后,迟早会遇到「图元库里的泵长得不像我们厂的泵」这种需求。FUXA 支持导入 SVG 作为自定义图元,这是它比传统组态软件灵活的地方——传统组态软件的自定义图元往往要用它自带的绘图工具画,丑且难维护;FUXA 可以直接用 Illustrator 或 Inkscape 画好导出 SVG,导入后绑变量。

导入 SVG 时注意几点:第一,SVG 里的元素 ID 不要重复,否则绑定时会绑到错误的元素上;第二,把需要动态改的属性(比如填充色、旋转)对应的元素单独打组,绑定时选组而不是选整个 SVG;第三,SVG 的viewBox要和 FUXA 画布坐标系匹配,否则导入后尺寸不对。

<!-- 自定义泵图元的 SVG 结构示例 --> <svg viewBox="0 0 100 100"> <!-- 泵体,填充色绑变量 Pump1_Status --> <circle id="pump_body" cx="50" cy="50" r="30" fill="#ccc"/> <!-- 叶轮,旋转角度绑变量 Pump1_Speed --> <g id="impeller" transform="rotate(0,50,50)"> <line x1="50" y1="50" x2="50" y2="25" stroke="#333" stroke-width="3"/> </g> </svg>

逻辑说明:pump_body的fill属性绑到Pump1_Status,运行时根据布尔值切换颜色(运行绿、停止灰)。impeller组的transform绑到Pump1_Speed,变量值映射到旋转角度,实现叶轮转动动画。注意transform的旋转中心要设对,rotate(角度, cx, cy)里的 cx、cy 是旋转中心坐标,不设的话默认绕 SVG 原点转,叶轮会飞出去。

另一个实用技巧是「图元模板」——把一组常用的图元组合(比如一个完整的泵+进出口阀门+状态灯)存成模板,下次直接拖出来用。FUXA 的模板功能在右键菜单里,存的时候注意把变量绑定也一起存,但变量名要改成相对引用,否则新画面里会绑到旧变量上。

从那以后我每次导入 SVG 图元,都强制先在 Inkscape 里把元素 ID 改成有意义的名字,再检查一遍 viewBox 和旋转中心,最后才导入 FUXA 绑变量。这个习惯帮我省了至少三次「图元飞出去找不到」的排查时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 1:19:25

RTC6715驱动实战:基于STM32的5.8G图传自动扫频实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 1:19:01

Streamsets数据接入实战:从可视化管道到数据漂移处理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 1:18:55

Python类设计中的私有变量与公有变量:名称改写机制详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 1:18:23

eLockViolation锁冲突与Form无关

结论先说&#xff1a;不行。UserControl本身不能独立悬浮&#xff0c;而且就算不套Form&#xff0c;锁冲突问题依然存在&#xff0c;根源不是“有没有外层Form” 1. 为什么UserControl不能脱离Form单独悬浮 UserControl 本质只是控件容器&#xff0c;不是顶层窗口&#xff0c;W…

作者头像 李华
网站建设 2026/10/15 1:16:59

OpenCV静态编译实战:从依赖链到单文件交付

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 1:16:07

OSGBTool实战:搞定OSGB转换、坐标偏移与瓦片轻量化

简介&#xff1a;OSGBTool.rar是一份基于C、无需额外环境配置的倾斜摄影测量模型查看器工程包&#xff0c;面向GIS三维开发者和倾斜摄影数据处理人员&#xff0c;解决OSGB格式三维模型的高效查看与解析学习需求。OSGB格式由英国国家测绘局推出&#xff0c;广泛用于存储倾斜摄影…

作者头像 李华