工业产线上的扫码枪大多通过RS232转USB芯片(如FTDI、CH340)接入工控机,操作系统将其枚举为标准HID键盘设备。这意味着枪体扫出的条码字符会模拟人工打字,一个一个按键事件流向当前获得焦点的页面元素。如果前端只用jQuery监听某个输入框的change或input事件,往往会因为输入过快、焦点丢失或浏览器自动补全干扰,造成数据截断或填错行。理解这一底层机制,是写出稳定捕获逻辑的前提。

扫码枪的HID键盘模拟原理与常见坑点
当RS232转USB扫码枪工作时,串口侧收到的ASCII流被转换芯片封装成USB HID报表,主机端无需驱动即当作键盘处理。每扫一个条码,设备先发可配置的引导前缀(如~或CR),随后逐字节发送字符,最后以回车或Tab收尾。由于发送间隔极短(通常几毫秒),浏览器会把这一串keydown/keypress合并进同一个输入框,但若是页面在扫描中途弹窗或失焦,后续字符就丢进系统其他地方。
很多团队在jQuery里直接写$('#code').on('input', handler),这在枪速低于人工敲击时看似正常,一旦产线换用高速枪或长条码,就会偶发末尾几位缺失。另一个隐患是浏览器的快捷键:若扫码内容含字母组合,恰巧命中Ctrl类组合,会触发页面保存或打印。因此必须在捕获层屏蔽特定按键的默认行为,而不是等填完再校验。
还有一类情况是枪被配置为“串口模式”而非“键盘模式”,此时它不模拟键盘,而是在设备管理器生成虚拟COM口。这种形态下jQuery无法在页面内直接读取,需要本地中间件轮询串口再向页面推送消息,这部分我们在文末讨论。先解决最普遍的HID键盘型接入。
基于jQuery的全局缓冲捕获与表单填充实现
核心思路是在document上挂jQuery的keydown监听,用一个缓冲区数组收集字符,遇到结束符(如Enter)就拼成完整条码,再根据业务规则填入对应表单域。这样既不受焦点限制,也能统一做前缀校验和去重。下面代码展示基础骨架:
$(function () {
var buffer = [];
var endTime = 0;
var MAX_GAP = 30; // 毫秒,相邻字符最大间隔
$(document).on('keydown', function (e) {
// 屏蔽可能的浏览器组合键干扰
if (e.ctrlKey || e.metaKey || e.altKey) {
return;
}
var now = new Date().getTime();
if (now - endTime > MAX_GAP && buffer.length > 0) {
buffer = []; // 超时断开,视为新扫描
}
if (e.key === 'Enter') {
var code = buffer.join('');
buffer = [];
endTime = 0;
if (code.indexOf('~') === 0) {
fillForm(code.substring(1));
}
e.preventDefault();
return;
}
if (e.key && e.key.length === 1) {
buffer.push(e.key);
endTime = now;
}
});
function fillForm(code) {
// 假设业务单号填A栏,序列号填B栏
$('#orderNo').val(code.split('|')[0]);
$('#sn').val(code.split('|')[1] || '');
$('#scanTip').text('已捕获: ' + code);
}
});
上述逻辑把扫描收尾与填充分离,buffer在超时后即清空,能应对两次扫描间有人工敲击的混杂场景。注意e.preventDefault()对Enter的调用,可阻止表单意外提交。若页面有多个录入区块,可在fillForm内按当前业务状态路由到不同容器,而不是写死选择器。
与“隐藏input获焦接收”的方案相比,全局document监听不必强迫用户点击某个框,也不会因Tab切换丢失数据;但代价是要小心过滤真实人工键盘输入。实践里可要求产线枪配置独有前缀(如~),代码里只认该前缀后的串,大幅降低误触。下表列出两种前端接收方式差异:
| 方案 | 抗干扰性 | 实现复杂度 | 适用场景 |
|---|---|---|---|
| 隐藏域直填 | 弱,依赖焦点 | 低 | 单一扫码台式机 |
| jQuery全局缓冲 | 强,可前缀校验 | 中 | 多表单ERP录入 |
串口模式下的中间件桥接与jQuery接收
当RS232转USB枪工作在虚拟COM口模式,jQuery无法突破浏览器沙箱读串口,此时可在工控机跑一个Node服务,用serialport库监听COM3,解析后通过WebSocket推给页面。前端jQuery只需监听socket消息并填表,彻底与硬件解耦,也方便集中管理多把枪。
// Node端示意
const SerialPort = require('serialport');
const port = new SerialPort('COM3', { baudRate: 9600 });
port.on('data', function (chunk) {
const str = chunk.toString().trim();
if (str.indexOf('~') === 0) {
wsServer.clients.forEach(function (c) { c.send(str); });
}
});
// 前端jQuery
$(function () {
var ws = new WebSocket('ws://127.0.0.1:8080');
ws.onmessage = function (ev) {
var code = ev.data.substring(1);
$('#orderNo').val(code.split('|')[0]);
$('#sn').val(code.split('|')[1] || '');
};
});
这种架构把解析规则从浏览器挪到本地服务,若后期枪协议变更只需改Node端,页面jQuery几乎不动。需要注意的是WebSocket地址在产线环境应绑定内网IP而非公网,且Node服务要以开机自启方式部署在Windows计划任务里,路径可写为 C:scanserver.js 并通过 C:WindowsSystem32cmd.exe 调用,保证断电重启后自动恢复。
综合来看,HID键盘型优先用jQuery全局缓冲,开发快、零客户端;串口型用中间件桥接,扩展性更好。无论哪种,都应在填充前做长度与校验位判断,防止脏数据进业务系统。产线调试时建议打开浏览器控制台观察keydown序列,确认枪的实际结束符是回车还是Tab,再对应调整代码里的结束判断分支。