一、项目背景与目标
1.1 业务背景
速分设备是一款适用于轻量级分拣场景的小型分拣机,支持 1 分 2 / 1 分 4 多流向配置。当前业务完全依赖供应商提供的客户端软件与 WCS(Warehouse Control System,仓库控制系统),导致设备运维、迭代效率均受限于第三方,难以快速响应业务需求。
1.2 核心痛点
| 痛点类别 | 具体问题 | 业务影响 |
|---|---|---|
| 设备安全风险 | 供应商掌控 WCS 与桌面应用,存在后门控制风险 | 可能被限制设备效率,导致业务中断 |
| 迭代依赖 | 业务变更需依赖供应商迭代,且收取高额服务费 | 迭代周期不可控,某项目升级曾花费数万元 |
| 采购成本高 | 需额外采购供应商 WCS 与桌面应用 | 设备整体采购成本上升 |
| 质量不可控 | 新版本软件运行效率较旧版下降 | 收货作业效率受损 |
1.3 阶段建设目标
| 阶段 | 业务目标 | 技术目标 |
|---|---|---|
| 第 1 阶段 | 1. 实现包裹分拣桌面客户端 2. 完成指定仓库所有速分设备适配验证 | 1. 搭建通用壳工程模版 2. 实现脚手架工具 3. 集成 DMS 发布流程 4. 完成版本更新流程 5. 落地容器化架构设计与部分实现 |
| 第 2 阶段 | 完成指定仓库所有速分设备替换 | 提供技术支持与维护优化 |
| 第 3 阶段 | 1. 扩展支持其他业务速分设备替换 2. 覆盖更多工业软件自研替换 | 兼容多供应商工业能力 SDK |
1.4 长期技术目标
- 低成本快速创建桌面富应用,降低工业软件自研门槛
- 复用基础组件、工业设备调用、硬件通信、版本更新等通用能力
- 支撑更多工业软件的自研替换,构建自主可控的工业客户端生态
二、整体技术架构
2.1 架构分层设计
本方案采用 4 层架构设计,实现能力复用与业务解耦,同时配套工程化、文档化、平台化能力保障体系,确保项目可维护、可扩展。
能力保障体系
平台化
组件外化平台
工程化
壳工程模板
CLI 脚手架
代码覆盖率
代码规范
共享模块包
文档化
基础组件文档管理
业务组件文档管理
容器层
容器标准化
本地化日志
错误处理
调试组件
HTTP
拦截器
进程管理组件
多语言
版本更新
UI 组件库
基础组件层
公司组件
APMS
CDN
内部工具
远程日志
基础能力
串口通信组件
DLL 通信组件
条形码解码组件
业务组件层
TWS 业务组件
摄像头画面采集
电机驱动模块
体积采集模块
SLDS 业务组件
公共业务组件
应用层
SLDS
SDK 接入标准化
WMS
TWS
架构各层说明:
- 应用层:对接 SLDS(自建物流配送服务)、WMS(仓库管理系统)、TWS(转运仓系统)3 大业务系统,通过"SDK 接入标准化"模块统一接入,屏蔽底层技术差异,实现业务与底层组件的无缝衔接。
- 业务组件层:按业务场景封装专属组件,包括 TWS 业务组件(摄像头采集、电机驱动、体积采集)、SLDS 业务组件及公共业务组件,组件独立维护、按需调用,提升复用性与开发效率。
- 基础组件层:拆解通用基础能力,分为基础能力(串口通信、DLL 通信、条形码解码)、内部工具(远程日志)、公司组件(APMS、CDN),为上层业务提供标准化支撑,复用现有成熟能力。
- 容器层:以"容器标准化"为核心,提供客户端运行所需基础能力(本地化日志、错误处理、调试、版本更新等),是通用壳工程的核心模板,保障客户端稳定运行。
- 能力保障体系:贯穿各层级,由工程化(壳工程、脚手架等)、文档化(组件文档管理)、平台化(组件外化)组成,保障开发规范、组件复用与交付效率。
三、核心技术选型
3.1 客户端框架选型
因硬件通信限制(无法使用 HTTP 协议),纯网页方案不可行,故选择 exe 客户端形式。主流框架对比及选型如下:
| 框架 | 技术栈 | 优点 | 缺点 | 更新机制 | 维护成本 |
|---|---|---|---|---|---|
| Electron | 前端 + Node.js | 社区成熟、易于使用、Node 调用 C++ SDK 方便 | 体积较大、性能略低于原生 | 内置 electron-updater,成熟稳定 | 低(前端团队可直接维护) |
| Tauri | 前端 + Rust | 轻量、性能高、沙箱安全 | 社区小、功能受限 | 需自定义实现 | 高(需学习 Rust 语言) |
| Wails | 前端 + Golang | 简单易用、性能高 | 社区有限、需额外学习 Golang | 需手动建设 | 高(需学习新语言) |
| 选型结论:选用 Electron,核心原因如下: |
- 团队技能匹配:前端团队可直接维护,无需额外学习新语言,降低学习成本。
- 更新机制成熟:内置 electron-updater,可快速实现客户端自动更新,无需自定义开发。
- SDK 调用友好:工业 SDK 多为 C++ 编写,Node.js 调用 C++ 生态完善,适配硬件通信需求。
- 性能满足需求:本地部署场景无高并发请求,Electron 性能完全覆盖业务需求。
3.2 工业硬件通信方案
3.2.1 电子称重机通信方案
核心流程:通过串口连接获取电子秤重量数据,经数据校验后在前端展示,最终将有效数据上报至业务后台,保障称重数据准确可用。
通信核心配置
- 通信方式:COM 口(台式计算机/电子设备上的 D-SUB 串行通信口)。
- 通信协议:RS-232 工业标准串口协议,保障数据传输稳定性,适配工业场景需求。
- 串口通信工具:采用 serialport.io 方案,该方案广泛应用于物联网、工业控制等场景,支持 Electron 从原型快速落地生产,完美适配多种串口设备通信需求。
NodeSerialPort 通信参数
| 连接参数 | 参数含义 | 默认参数值 | 是否可配置 |
|---|---|---|---|
path |
串口路径 | COM3 | 支持 JSON 配置,界面下拉可选 |
baudRate |
波特率 | 9600 | 可配置,通常为固定值 |
parity |
校验位 | none | 不可配置 |
dataBits |
数据位 | 8 | 不可配置 |
stopBits |
停止位 | 1 | 不可配置 |
flowCtl |
流控 | XONOFF | 不可配置 |
通信流程图
Electron-Main(运行于 Electron 内置 NodeJS 环境) contextBridge Electron-Web Electron-Main(运行于 Electron 内置 NodeJS 环境) contextBridge Electron-Web IPC 通信频率:13 次/秒 App.ready() → createWindow → InitSerialPort(初始化串口) 1. 注册 on-update-weight 事件 2. ipcRender.on('update-weight') 3. 监听串口消息 port.on('data') 4. webContents.send('update-weight') 5. 触发 on-update-weight 事件 6. RenderUI,显示重量数据 7. 按称重标准设置 N 大小队列 8. 队列数据一致则判定为最终数据,上报后台
3.2.2 直流无刷电机(皮带驱动)通信
核心目标:根据包裹流向指令,精准驱动皮带转动,实现包裹分拣的自动化控制。
- 通信方式:RS485 串口通信,适配工业设备远距离、抗干扰通信需求。
- 业务流程 :扫描包裹 → 请求后台获取包裹流向 → 下发指令驱动电机转动 → 完成分拣。
通信时序图:
Electron-Main(主进程, 运行于 Electron 内置 NodeJS 环境) contextBridge UI 渲染进程 Electron-Main(主进程, 运行于 Electron 内置 NodeJS 环境) contextBridge UI 渲染进程 alt [回包返回 OK] [回包返回 Error] App.ready() → createWindow → InitSerialPort(初始化串口) 1. 业务发起指令:向左转动 2. dispatchEvent: turnLeft 3. ipcRender.invoke('turnLeft') 4. 触发电机转动事件 5. 调用串口操作方法 6. 给串口发送参数帧 7. 解析参数帧回包 8. 给串口发送数据帧(广播) 9. 电机执行转动操作 10. return errorCode 11. return errorCode 12. 弹出报错弹窗,提示异常
3.2.3 工业相机通信
核心目标:实时采集包裹画面、识别条形码,通过高性能渲染保障分拣效率,满足工业场景实时性需求。
- 技术方案:相机回调取流 + Electron 多窗口渲染 + WebGL 渲染,兼顾实时性与渲染性能。
- 渲染性能 :WebGL 渲染耗时 5-8 ms,GPU 渲染耗时 25 ms,整体响应速度满足实时分拣需求。
多窗口渲染时序图:
CameraWindows(UIRender 列) CameraWindows(JS 列) Electron-Main(C++ SDK 列) Electron-Main(Main 列) MainWindows(ChromeJS) CameraWindows(UIRender 列) CameraWindows(JS 列) Electron-Main(C++ SDK 列) Electron-Main(Main 列) MainWindows(ChromeJS) 帧率可达 18 帧/秒 总耗时约 30 ms WebGL 渲染耗时 5 ms~8 ms GPU 渲染耗时 25 ms alt [画面延迟 > IPC 通信时间] [上一帧宽高匹配 & 延迟 < IPC 通信时间] App.ready() → createWindow 1. 注册取流回调(初始化 C++ SDK) 2. return ok 3. 触发取流回调 → 解码数据为 JS 对象 4. 传递解码后 JS 数据 5. 处理 JS 数据 6. 设置监听函数 onUpdateImageData 7. 设置电子秤监听函数 8. 电子秤 IPC 通信 webContents.send(data) 9. 渲染重量数据 10. 设置条形码监听函数 11. 条形码 IPC 通信 webContents.send(data) 12. 渲染条形码数据 13. 响应用户操作 14. 调用相机渲染接口 15. IPC 通信[webContents.send(data)] 16. return void 17 定义图片/线条着色器程序 18. 传递着色器程序 19. 创建着色器与程序 20. 绘制图片(Mono8) + 线条 21. UI Render 线程同步绘制 22. 绘制完毕
3.3 Electron 进程通信与开发流程
3.3.1 进程通信模型
Electron 采用"主进程 + 渲染进程"分离架构,通过 preload 脚本与 contextBridge 实现安全通信,避免渲染进程直接访问 Node.js API 带来的安全风险。
Renderer Process (BrowserWindow)
Main Process(Electron-Main, 运行于 Electron 内置 NodeJS 环境)
IPC
ContextBridge
Node.js API
index.ts
Electron Main Process Modules
preload.ts
Node.js API
DOM API
Electron Renderer Process Modules
index.html
index.ts
Web Frameworks (Vue/React/...)
3.3.2 electron-vite 开发流程
采用 electron-vite 作为构建工具,基于 Vite 优化开发体验与打包效率,支持热重载(HMR),大幅提升开发迭代速度。
Output(输出结果)
electron-vite dev(开发阶段)
HMR 热重载
打包主进程代码
打包 preload 脚本
启动渲染进程开发服务器
启动 Electron 应用
main.js(主进程输出)
preload.js(桥接层输出)
localhost:3000(渲染进程开发服务)
CommonJS 规范
CommonJS 规范
Native ESM 规范
四、通用壳工程与工程化建设
4.1 通用壳工程模版
4.1.1 工程目录结构
Plain
工程目录结构
.
├── README.md # 项目说明文档
├── build/ # 构建资源(图标、签名文件等)
├── dev-app-update.yml # 开发环境更新配置
├── electron-builder.yml # 打包配置文件
├── electron.vite.config.ts # electron-vite 构建配置
├── out/ # 构建输出目录
├── package.json # 项目依赖与配置
├── pnpm-lock.yaml # 依赖锁文件
├── resources/ # 公共资源(图标、可执行文件等)
├── src/
│ ├── main/ # 主进程代码(Node.js 环境)
│ ├── preload/ # 桥接层代码(主进程与渲染进程通信)
│ └── renderer/ # UI 层(React + TypeScript 项目)
├── tsconfig.json # TypeScript 全局配置
├── tsconfig.node.json # Node 环境 TypeScript 配置
└── tsconfig.web.json # Web 环境 TypeScript 配置
4.1.2 开发规范
| 规范项 | 选型 | 说明 |
|---|---|---|
| 构建工具 | electron-vite | 基于 Vite,支持 HMR 热重载,构建速度快,适配 Electron 开发 |
| UI 框架 | React + TypeScript | 类型安全,组件复用性高,贴合前端团队技术栈 |
| UI 组件库 | 内部 React 组件库 | 统一 UI 规范,提升开发效率与界面一致性 |
| 代码规范 | ESLint + husky + lint-staged | 规范代码风格,拦截不合规提交,保障代码质量 |
| 打包工具 | electron-builder | 配置简单,支持多平台打包,适配 Windows 工业设备部署 |
4.1.3 离线化方案
Electron 天然支持离线运行,结合工业场景需求,额外保障以下 3 点,确保设备断网时正常工作:
- 静态资源本地化:所有图片、脚本等静态资源打包进客户端,不依赖 CDN 加载。
- 本地数据存储:采用 SQLite 或 txt 文件存储用户配置、操作日志等数据,断网时不丢失。
- 配置文件本地化:使用 JSON 文件存储可修改配置(如串口路径),支持离线调整。
4.2 脚手架工具(create-electron-app)
开发脚手架工具 create-electron-app,用于快速生成符合项目规范的 Electron 项目模版,核心能力如下:
- 一键生成可直接运行的 Demo 项目,无需手动配置基础环境。
- 集成 UI 组件库、代码规范、构建/打包配置,开箱即用。
- 支持自定义配置扩展,适配不同工业场景的客户端开发需求。
4.3 PC 桌面端打包方案
基于 Electron 技术栈,结合 Windows 工业设备部署需求,选定 electron-builder 作为打包工具,制定标准化打包及发布流程,衔接 DMS 发布服务,保障打包效率与部署适配性。
4.3.1 打包工具选型
对比 Electron 官方维护的 2 种主流打包工具,结合项目"降低学习成本、提升打包效率"核心需求,确定最优方案:
| 方案 | 特点 | 优势 | 劣势 |
|---|---|---|---|
| electron-builder | 综合 Forge 和 Packager 优点 | 配置简单、支持多平台、可视化配置、易上手 | 部分场景需手动配置(如 Windows 签名) |
| Electron Forge | Electron 官方推荐方案 | CLI 与插件生态完善,便于项目创建发布 | 配置复杂、学习成本高,需配合 Packager 使用 |
| 选型结论:选用 electron-builder,适配团队前端技术栈、降低学习成本,其丰富的打包选项可完美满足 Windows 工业设备部署需求。 |
4.3.2 核心打包配置
核心配置集中在项目根目录 electron-builder.yml,贴合业务与硬件适配需求,关键配置如下:
YAML
electron-builder.yml 核心配置
# 基础标识配置
appId: "com.kuaijian.client"
productName: "速分客户端"
copyright: "Copyright © 2024 速分项目组"
# 输出与资源配置
directories:
output: ./out # 打包输出目录
buildResources: ./build# 构建资源(图标、签名文件)
# Windows 适配配置(核心)
win:
icon: ./build/icon.ico # 应用图标
target: [nsis] # 生成 exe 安装包,支持静默安装
arch: [x64] # 适配 64 位 Windows 工业设备
publisherName: "速分项目组"
# 资源打包规则
files:
- ./dist/**/* # 编译后代码
- ./resources/**/* # 公共资源
- package.json
- !node_modules/**/* # 排除开发依赖,精简包体
4.3.3 多场景打包策略
集成至 DMS 打包服务,实现一键触发,适配测试与生产双场景,满足不同阶段部署需求:
- 开发测试包 :开启调试模式、保留日志与调试工具,便于问题排查,打包命令:
npm run build:test。 - 生产发布包 :关闭调试、压缩代码、集成自动更新,适配工业设备离线运行,打包命令:
npm run build:prod。
4.3.4 打包优化策略
针对 Electron 包体大、启动慢的痛点,结合工业设备配置特点,实施以下优化措施,保障运行流畅性:
- 依赖精简:通过 electron-vite tree-shaking 移除无用依赖,排除开发依赖,将安装包体积控制在 100 MB 以内。
- 资源压缩:压缩静态资源(图标、模板文件),UI 组件库按需引入,减少冗余资源。
- 硬件适配:打包时嵌入串口、相机驱动等依赖,实现"一键安装、开箱即用",无需额外部署依赖。
- 缓存优化:配置打包缓存,重复打包时复用已编译资源,缩减打包时间,提升迭代效率。
4.3.5 注意事项
- 打包前需核对
electron-builder.yml与package.json中的更新配置(如 publish.url)一致,避免影响客户端自动更新。 - 生产包打包完成后,需上传至 S3 存储(与 DMS 发布流程衔接),生成唯一 md5 码,用于安装包校验,防止文件篡改。
4.3.6 打包与发布流程
衔接 DMS 打包服务,实现打包、发布全流程自动化,整体流程与内部服务联动,分为 2 步:
(1)整体发布流程
打包服务 dms-jagent jmaster dms-saturn dms-api dms-client(前端) 用户 打包服务 dms-jagent jmaster dms-saturn dms-api dms-client(前端) 用户 点击打包 发起打包请求 创建 build/step 记录,检查未完成任务 下发创建 parent job 指令 下发打包请求 执行打包 返回打包结果 上报日志与报告 创建 pack 记录,展示打包状态 同步 job 状态,完成后发送通知
(2)打包服务内部流程
s3 harbor gitlab 打包服务 dms-jagent s3 harbor gitlab 打包服务 dms-jagent 下发打包请求 等待前置打包任务完成 更新本地 docker 镜像 拉取分支代码 基于 docker 镜像打包 压缩相关文件 上传文件与安装包 返回下载链接 返回结果(链接、大小、md5 码)
4.4 桌面端自动更新流程
使用 electron-updater 实现客户端自动更新,支持强制更新与非强制更新,适配工业场景灵活需求。
4.4.1 更新流程图
有更新
否
是
无更新
启动程序
检查更新
自动下载安装包
下载完成
询问用户是否更新
程序退出后静默安装
立即重启安装更新
正常启动程序
更新完成,启动程序
4.4.2 更新核心说明
- 更新触发:程序启动时自动触发更新检查,也可在设置界面手动触发,适配工业设备无人值守场景。
- 更新模式:强制更新(重大版本、安全补丁)会弹窗强制重启安装;非强制更新(小版本优化)可选择稍后更新,不影响当前作业。
- 异常处理:下载中断时自动断点续传,下载失败则弹窗提示,同时保留旧版本可正常使用,避免影响业务运行。
五、客户端监控方案
5.1 监控实现思路
| 监控类型 | 实现方式 |
|---|---|
| 内存、CPU 监控 | 通过 Electron API 获取进程 ID、进程类型、CPU 占用率及内存占用数据,通过子进程定时上报至监控平台,适配工业设备运行监控需求。 |
| 程序 Crash 监控 | 利用 Electron 自带的崩溃报告上报能力,配置 HTTPS API 接收崩溃报告,确保崩溃信息可追溯、可排查。 |
| JS Error 监控 | 采用前端错误监控方案,捕获客户端运行过程中的 JS 错误,同步上报至监控平台,及时发现前端异常。 |
5.2 数据存储方式
- 本地存储:将详细监控日志写入系统本地,留存完整监控记录,便于后续人工介入排查问题时调取查看。
- 平台上报:申请上报接口并设置站点白名单,将核心监控数据(CPU/内存占用、崩溃信息、JS 错误)同步上报至监控平台,实现实时监控与告警。
六、方案价值与总结
6.1 方案核心价值
- 自主可控:摆脱对供应商的依赖,实现客户端与 WCS 系统自主开发、自主迭代,消除安全后门风险,掌握业务主动权。
- 成本优化:省去供应商软件采购与升级服务费,自研方案可复用通用组件,降低后续同类工业软件开发成本。
- 效率提升:业务需求迭代周期缩短,打包效率、设备运行效率均有优化,适配工业分拣场景的高效作业需求。
- 可扩展性强:通用壳工程与脚手架工具可支撑更多工业软件自研替换,构建自主可控的工业客户端生态。
- 运维便捷:简洁高效的监控方案实现异常实时感知、快速排查,降低运维成本,保障业务连续运行。
6.2 总结与展望
本方案通过 Electron 框架搭建速分客户端,基于分层架构设计实现业务与底层能力解耦,结合工程化建设保障开发效率与交付质量,配套简洁的监控方案保障客户端稳定运行,成功解决了依赖供应商的核心痛点,实现了从"依赖外部"到"自主可控"的转变。
后续将重点推进第 3 阶段建设,兼容多供应商工业能力 SDK,扩展至更多业务场景的速分设备替换;同时持续优化客户端性能、完善组件生态,为工业软件自研提供更高效、更低成本的解决方案。