进入工业自动化行业后,我接触到了OQC环节。在为 要求非常高的海外科技企业 做项目过程中,我总结出以下几个问题:
- 客户节奏快,压缩交付周期,代码质量容易失控
- 初级工程师能力不足,导致对高级软件工程师依赖过重,被迫长期承担基础性支持工作
- 开发周期长,人力投入大,有些项目需要全程驻场,随时响应
为了应对这些问题,我设计了一个专注于OQC的低代码平台。
这个低代码 OQC 项目的目标是降低软件工程师的直接参与度,让售后工程师、客户技术负责人等非软件背景人员,通过简单培训,就能使用图形界面完成测试流程配置。复杂流程或定制化功能可由软件工程师通过插件形式提供支持,如算法模块、定制报表等。
核心设计理念是职责解耦,提升效率,让工程师聚焦在更有价值的任务上。
它的核心目标是:
- 尽可能减少修改代码的工作量 —— 减少流程中代码变更的频率和范围,降低引入新错误的风险,缩短测试上线周期
- 可以让初级工程师承担更多任务,减少对高级工程师的依赖 —— 实现人员能力结构的优化,使高阶人力聚焦在架构设计与复杂逻辑实现,释放更多产测支持能力给初级岗位
- 可以减少软件工程师常年驻场的情况,释放人力资源 —— 降低一线响应对高成本人力的依赖,使工程师能并行支持更多项目,提升团队整体产能
架构设计总览 Link to heading
本架构遵循关注点分离(Separation of Concerns, SoC)与依赖倒置原则(Dependency Inversion Principle, DIP)。上层策略(如流程管理)不依赖于下层具体实现(如HTTP请求发送),二者都依赖于抽象的统一接口和共享数据上下文。
界面原型与交互验证 (UI Prototype & Interaction Validation) Link to heading
为了验证低代码平台的关键理念——即便是非技术人员也能通过直观的UI进行测试流程配置,我使用 Electron 快速开发了一个用户界面原型。虽然此原型仅包含前端交互逻辑,未集成后端业务,但已充分展示了我们设想的配置体验。
工作台界面 (Workbench UI) Link to heading
该界面旨在提供测试槽位(Slot)的实时状态监控,以便用户直观了解每个测试工位的运行情况和结果。

图1:工作台界面,展示测试槽位实时状态
流程设计界面 (Flow Design UI) Link to heading
在最初的设计构想中,我们曾考虑采用传统的流程图(Flowchart)形式进行配置。但在深入考量用户体验、实现复杂度和后期维护成本后,我们调整了策略,计划通过 Compose Multiplatform 实现一种可拖拽的列表式配置界面。这种方式能更高效地管理线性或简单分支流程,同时降低用户的学习曲线和开发难度。

图2:流程设计界面概念原型,基于可拖拽列表
跨平台技术选型考量 (Cross-Platform Technology Selection) Link to heading
为了确保未来实现能够满足工业领域对跨平台、高性能和部署便捷性的需求,我对多种主流的跨平台技术方案进行了深入对比和评估。
我们对比分析了 Electron、Flutter、Tauri 以及 Compose Multiplatform 等主流方案。最终,我们决定采用 Compose Multiplatform 作为前端UI框架,搭配 Rust 作为高性能的后端逻辑和计算引擎。这一组合的核心优势在于:
- Compose Multiplatform (前端): 提供了现代化的声明式UI范式,能够以接近原生的性能,高效构建适用于桌面(macOS、Windows、Linux)、Android甚至iOS的界面,大幅提升开发效率和一致性。
- Rust (后端): 凭借其出色的内存安全、并发性能和与底层硬件的紧密结合能力,非常适合处理工业自动化中对稳定性、实时性和数据吞吐量有高要求的核心逻辑,且能编译为跨平台的原生可执行文件。
- 整体优势: 该组合不仅能完美支持项目对macOS、Windows、Linux多平台(包括ARM和x86架构)的兼容性要求,还在开发效率、运行时性能和长期可维护性之间取得了最佳平衡。
更多关于跨平台框架的详细对比和选择 Compose Multiplatform 的原因,请参考我的另一篇文章:《跨平台开发框架对比:Compose Multiplatform, Flutter, Tauri, Electron》。
组件职责详解 Link to heading
1. ExecutionContext
(执行上下文)
Link to heading
- 别名:
The Cipher
、ValueHolder
、FlowContext
- 核心职责:作为单个测试流程实例的 单一事实来源(Single Source of Truth),独立、隔离地承载流程的全部动态数据。
- 生命周期:随
Flow Controller
创建而创建,随其销毁而销毁,一一对应,完全隔离。 - 结构设想:
global
:只读,全局信息,例如产品SN、工位编号、操作员ID。steps
:Map类型,键为节点ID,值为对应节点的输出结果,用于结果追溯与引用。transient
:临时变量区,例如循环计数器、内部标记。
- 工作机制:
- 写入:模块执行完毕后由
Flow Controller
写入至steps[currentNodeId]
。 - 读取:模块通过路径表达式(如
steps.node-123.voltage
)访问所需数据。 - 变量插值:例如
context.interpolate("http://.../${global.sn}")
,用于动态填充字符串。
- 写入:模块执行完毕后由
- 设计目的:
- 解耦节点间数据依赖,各节点仅依赖统一上下文接口。
- 可调试性强:可完整序列化为JSON,回溯流程状态。
- 可恢复性高:支持持久化至数据库或Redis,实现断点续传。
2. Module Interpreter
(模块解释器)
Link to heading
- 别名:
Module
、NodeHandler
、Adapter
- 核心职责:执行一项原子任务,包括外设通信、计算、条件判断等。
- 统一接口定义:
run(config, context) -> Promise<ResultObject>
config
:节点静态配置项(如串口号、URL等)。context
:流程上下文引用,用于数据读取与写入。ResultObject
:标准输出格式{ status, output, error }
。
- 工作机制:
- 被
Interpreter
调用。 - 读取
config
及context
所需参数。 - 执行任务。
- 输出结果封装为
ResultObject
。
- 被
- 设计目的:
- 实现功能的模块化与可插拔性。
- 将外部I/O与逻辑实现隔离,核心系统不涉底层实现。
- 模块可复用:可在不同流程中重复使用而无需改写。
3. Interpreter
(解释器)
Link to heading
- 核心职责:根据节点类型将任务委托至对应模块执行。
- 内部结构:类型注册表(如
{ 'http': HttpModuleInstance }
)。 - 工作机制:
- 接收
Flow Controller
指令execute(node, context)
。 - 解析
node.type
,定位注册模块。 - 调用相应模块的
run(config, context)
方法。 - 返回标准化结果给
Flow Controller
。
- 接收
- 设计目的:
- 解耦流程控制器与模块类型,控制器不处理模块映射。
- 所有节点执行通过统一入口,便于加入日志、性能监控、错误处理等通用逻辑。
4. Flow Controller
(流程控制器)
Link to heading
- 核心职责:驱动单个测试流程实例的调度执行。
- 生命周期:由
Slot Manager
创建,完成任务后返回结果并自行销毁。 - 工作机制:
- 初始化:接收
FlowTemplate
与初始数据(如SN)。 - 创建专属
ExecutionContext
。 - 解析流程图,生成执行计划(线性或拓扑序)。
- 执行循环:
- 将节点与
context
传入Interpreter
执行。 - 接收
ResultObject
,分析status
。 - 若成功:写入
ExecutionContext
并继续。 - 若失败:根据流程定义跳转、重试或中止。
- 若为判断节点:基于
output
选择下一路径。
- 将节点与
- 终结流程后,提取最终数据,上报
Slot Manager
。
- 初始化:接收
- 设计目的:
- 控制层逻辑封装完整,包括顺序、分支、循环与错误处理。
- 每个实例独立运行,支持高并发任务分发与调度。
5. Slot Manager
(槽位管理器)
Link to heading
- 核心职责:统一管理所有测试流程实例,维护
Slot
资源与状态。 - 工作机制:
- 监听测试请求(来自用户或设备)。
- 分配空闲
Slot
,记录其状态。 - 创建并启动
Flow Controller
,传入模板与初始数据。 - 接收任务完成信号,记录并处理结果。
- 清理流程实例,释放
Slot
资源。
- 设计目的:
- 作为执行引擎与外部交互的分界线,避免系统耦合UI或协议层。
- 提供并发控制与
Slot
状态管理能力,支撑大规模任务运行。