微信小程序做 PDA 扫码出入库:库存并发控制与 4 个坑

面向场景:小微企业(10--200 人)的仓库。没有部署 PC、没有采购工业 PDA,仓管员手上只有一部手机。本文记录我们用微信小程序把「扫码出入库」这件跑通的过程------为什么不用工业 PDA、小程序当扫码枪够不够用、以及怎么让小程序安全地读到内网 ERP 的数据。

一、问题:仓库里没有电脑,台账靠纸和微信

先说清场景,不然选型会跑偏。

我们服务的是制造业和商贸流通企业,仓库通常长这样:

现状 具体表现 后果
没有 PC 仓库在车间旁或独立库房,拉网线、配电脑都嫌麻烦 出入库只能回办公室补录
靠纸质单 送货单签字 → 拿回办公室 → 二次录入 ERP 录一次,错一次的机会
靠 Excel 仓管员自建 Excel 台账,与 ERP 库存两本账 月底对不上,要盘一次
靠微信 出入库拍照发群里,办公室的人看着录 消息一刷就沉底,漏记是常态

核心矛盾是一句话:办公室里的 ERP 是准的,仓库现场是错的------而库存的真实变化发生在仓库现场。

二、选型:为什么不用工业 PDA,而是用微信小程序

按常规做法,这里应该采购工业 PDA。我们先算了账,最后放弃了。

方案 硬件成本 部署/维护 扫码能力 拍照 联网 打印标签
工业 PDA 2000--5000 元/台 每台装 APK、配 IP、逐台升级 强(激光/专业扫描头) 一般 需 Wi-Fi 覆盖 内置蓝牙打印,强
原生 App 零硬件 需分发安装包、iOS 还需签名 中(调摄像头) 好 手机网络即可 蓝牙打印支持较好
微信小程序 零硬件 零安装、零升级 中(wx.scanCode,够用) 好 手机网络即可 ⚠️ 能力受限

决定性理由有三条:

  1. 仓管员口袋里已经有扫码器了。 现在任何一部智能手机的摄像头,识别 Code128 料号标签、EAN-13 商品条码都毫无压力。为「扫码」单独买 3000 元的硬件,性价比说不通。

  2. 零安装、零维护。 这是小微企业最看重的。工业 PDA 最麻烦的不是买,是后面------设备坏了要换、系统升级要逐台操作、员工换人要重新配。小程序发个二维码扫一下就用,升级在服务端完成,客户端什么都不用做。

  3. 不用培训。 员工天天用微信,交互习惯是现成的。这一点在车间落地时特别重要------很多 ERP 项目不是功能不行,是员工不愿学。

代价也要说清楚 (见第六节):小程序在蓝牙标签打印 和长时间离线作业 上能力有限。这两块如果确实是刚需,工业 PDA 仍然更合适。我们的判断是:大多数小微仓库先解决「扫码准、数据实时」,打印可以后置。

三、整体链路

markdown 复制代码
手机(微信小程序)
   ├─ wx.scanCode     扫料号标签 / 商品条码
   ├─ 手动输入         扫不出来时的兜底(模糊搜索)
   └─ 拍照             送货单、票据
        ↓ HTTPS
   网关层(HTTP API)
        ↓ 复用既有业务逻辑
   ERP 库存 / 单据
        ↓
   实时库存回写(服务端事务处理)

一条设计原则贯穿始终:小程序只做「采集 + 展示」,一切计算和写入都在服务端。 原因在 4.3 说。

四、四个关键实现点

4.1 扫码:wx.scanCode 的实际配置

小程序的扫码能力来自 wx.scanCode,一次调用可指定码制与来源:

javascript 复制代码
wx.scanCode({
  onlyFromCamera: true,          // 仓库场景只用相机,禁止从相册选(防止选错图)
  scanType: ['barCode', 'qrCode'], // Code128/EAN13 属 barCode;二维码属 qrCode
  success(res) {
    // res.result  → 扫码内容(料号 / 条码)
    // res.scanType → 识别到的码制
    // res.charSet  → 字符集(中文码值需要关注)
    handleCode(res.result);
  },
  fail() {
    wx.showToast({ title: '未识别到条码,可手动输入', icon: 'none' });
  }
});

实操上有三个细节值得注意:

  • onlyFromCamera: true 一定要加。 不加的话相册里可能存着旧照片,员工顺手选错图,扫出来是另一个料号------这种错误极难查出。
  • scanType 按仓库实际码制收敛。 全放开会降低识别速度;只留实际在用的两类,识别更快更稳。
  • 中文料号要验证 charSet。 如果料号带中文,扫码结果的编码在不同安卓机型上可能不一致,建议料号设计时就用纯字母数字,从源头避开这个坑。

4.2 由条码反查物料:一次查询带出全部字段

扫码只是拿到一串字符。真正的价值是用它把整条物料信息拉出来,人不打字。

markdown 复制代码
扫码 → 条码 → 调 query 接口(按条码查物料)
     → 返回:料号、名称、规格、单位、当前库存
     → 人只输入「数量」

这里的体验差异非常大:手工录入要在料号、名称、规格、单位四个字段上打字并逐字核对;扫码后只需要敲一个数量。

这一条也顺带解决了「多套编码」的现实问题------很多工厂同时存在客户的料号 和自己的料号 ,送货单上印的是客户的。我们的做法是维护一张对照关系,任一侧条码都能反查到内部物料(这也是真实客户反馈里最早见效的功能:仅上线料号对照一项,就节省了 1 名专职对账人员的工作量,详见第七节)。

4.3 库存扣减必须在服务端,且要做并发控制

这一条踩过坑,单独说。

错误做法:小程序读到库存 100,界面上算「100 - 出库 10 = 90」,然后把 90 提交上去。看起来逻辑没问题,实际上------

css 复制代码
仓管员 A:读到 100,准备出库 30
仓管员 B:读到 100,准备出库 20
        两者几乎同时提交
最终库存 = 70(正确应为 50)   ← 丢了一次更新

这就是典型的并发覆盖 。仓库里多人同时作业是常态,一旦丢更新,账实不符,且不会有任何报错------最坏的那种 bug。

正确做法:

  1. 前端只提交「动作 + 数量」(出库 10),不提交算好的结果值
  2. 服务端在事务里做增减,并对库存行加锁或用版本号做乐观锁:
sql 复制代码
-- 事务内执行,先校验版本,再更新
UPDATE stock
   SET qty = qty - @outQty, version = version + 1
 WHERE item_id = @itemId
   AND version = @expectedVersion;   -- 版本不符则影响行数为 0,说明被人改过

-- 影响行数 = 0 → 回滚并提示「库存已变化,请刷新重试」
  1. 库存不足要拦、要提示,而不是允许负库存(除非业务上确实允许,那也要留痕)

经验总结 :涉及数量增减的操作,永远不要用「读出来 → 算一下 → 写回去」的模式。这不是小程序的问题,是任何多端系统都会遇到的经典陷阱。

4.4 网关层:小程序不直连数据库,走泛化接口

这是整个方案里最影响长期维护成本的一节。

核心约束 :微信小程序只能访问 HTTPS 合法域名 (需备案、需在小程序后台配置白名单),不能直连内网数据库。所以中间必须有一层网关。

微信小程序 → HTTPS 网关 → 复用既有业务逻辑 → 数据库

我们没有 为小程序新写一套接口,而是把网关做成 6 个泛化接口:

接口 作用
login 登录换会话标识
menu 取当前账号可见的菜单(按权限过滤)
meta 取列表/单据的字段元数据
query 通用查询(传模板 ID + 参数,而不是写死 SQL)
save 通用保存(主表/明细/子明细三层负载)
exec 执行动作(提交、审核等)

为什么这六个就够了 :所有查询和保存都由「模板」驱动------服务端维护一张模板表,每个模板包含它对应的查询语句、可见字段、列宽等元信息。小程序端只认模板 ID:

ini 复制代码
/query?template=xxx&params=yyy

带来的好处非常实际:

  • 新增一个查询页,后端零改动 → 只加一条模板配置。这正是「没有专职 IT 人员也能维护」的技术前提
  • 客户端不出现 SQL → 权限与数据范围在服务端统一控制,不会因为客户端被反编译而泄露
  • 桌面端和手机端共用同一套逻辑 → 不会出现「电脑上查得到、手机上查不到」这类账不对齐的问题

顺带说一句:这套东西能成立的前提是既有系统已经把 SQL 集中管理。如果 SQL 散在各处,做网关时会非常痛苦------这一步的投入回报在后期才显现。

五、四个踩过的坑

坑 1:开发时好好的,上线后所有请求全失败

现象:本地调试一切正常,提交审核上线后,接口全部请求失败。

原因 :微信小程序的网络请求有硬性约束------必须是 HTTPS,且域名必须提前在小程序后台配置为合法域名。开发期可以勾「不校验合法域名」,所以本地看不出问题。

排查清单:

  1. 接口域名是否为 HTTPS(自签证书不算,必须是可信 CA 签发的)
  2. 域名是否已完成 ICP 备案(未备案域名无法加入白名单)
  3. 是否已在小程序后台 → 开发管理 → 服务器域名里配置(请求域名、上传域名要分别配)
  4. 域名是否带端口号(带端口需一并写清,且部分场景受限)
  5. 换域名后要重新提交审核------白名单变更不影响已发布版本,需重新发版

经验总结 :这类问题必须在第一次提审前就验证,不要等审核通过后才发现。上线流程里应该有一条「先配域名白名单,再提审」。

坑 2:扫一次码就退一层页面,连扫十次要退十次

现象 :wx.scanCode 是「打开一个全屏扫码界面 → 返回结果」的模型。如果在页面里连续调用,容易变成「扫完一次,页面被退掉了」。

原因:扫码是独立页面,返回时的页面栈处理不当会导致层级混乱。安卓上尤其明显。

处理方式:

  1. 扫码结果用回调处理,不要依赖页面返回事件
  2. 扫码页面自己维护「连续扫码」状态,不要每次重新调栈
  3. 返回按钮常驻------仓管员扫错码要能一键回到列表。不要只依赖系统返回手势,车间戴手套操作时手势经常划不出来

第 3 条是真实反馈里改出来的:任何需要员工戴手套、单手操作的界面,系统手势都不能作为唯一返回路径。

坑 3:条码识别率不稳定,尤其是自己打印的标签

现象:商品原厂条码一扫就过,自己用标签机打的料号标签经常扫不出来。

根因基本都在标签本身,不在扫码代码:

原因 处理
打印分辨率低、条码边缘发虚 提高打印 dpi,条码尺寸别缩太小
标签贴在弧面(如线材盘、圆罐) 换小尺寸标签,避免跨弧面
覆膜反光 / 油污遮挡 提示改用「手动输入 + 模糊搜索」兜底
标签太小,相机对不上焦 小程序端提供「放大取景」提示

最重要的一条 :一定要提供手动输入 + 模糊搜索的兜底路径。 扫码是效率工具,不是唯一入口。如果扫码失败就完全走不通,员工会直接放弃整个系统------这是很多仓库系统上线失败的真实原因。

坑 4:多人共用账号导致数据串账

现象:为了省事,仓库几个人共用一个账号,结果出入库记录的经办人全是同一个人。

问题不在技术,在权限设计 :ERP 的单据要留经办人痕迹,共用账号等于审计链断裂------出了问题查不出是谁操作的。

处理方式 :一人一号,成本极低。ERP 的用户数计费下,仓库岗多开几个账号远比一次盘点差异的损失小。同时配合权限收敛:

markdown 复制代码
仓管员账号 → 只看得到:出入库、库存查询
           → 看不到:财务、采购价格、客户信息

这条不只是管理要求,也是多端系统必须做的数据隔离------手机丢了、账号被盗,能造成的损失范围要可控。

六、边界:什么场景小程序 PDA 并不合适

必须说清楚,否则容易给出错误预期。

场景 小程序是否合适 说明
扫码出入库、库存查询 ✅ 很合适 本文的场景
拍照录单(送货单、票据) ✅ 合适 与 OCR 识别天然衔接
单人低频作业(每天几十次) ✅ 合适 手机完全够
大仓高频分拣(每天数千次) ❌ 不合适 工业 PDA 的物理按键与专业扫描头效率高得多
无信号的库房(地下室/冷库) ⚠️ 需额外设计 要做本地缓存 + 恢复后补传,复杂度明显上升
现场打标签 ⚠️ 能力受限 小程序对蓝牙打印机的支持不如原生,建议用云打印机或保留 PC

一句话:小程序适合「轻量、多人、需要实时」的仓库现场作业,不适合「高频、重载、强离线」的分拣中心。

七、效果

跑通之后,实际改善主要在三个层面:

环节 之前 之后
扫码工具 无(或采购工业 PDA,2000--5000 元/台) 员工自己的手机,零硬件成本
数据时效 回办公室补录,延迟半天到一天 现场即时,库存实时准确
录入字段 料号、名称、规格、单位、数量逐个手填 扫码带出前四个,只需填数量
维护成本 装 APK、逐台升级 零安装,服务端升级

真实客户反馈里,见效最快的往往不是「省了多少时间」,而是账实不符消失了:

已有客户(50 人规模电子企业)在 1 个月内完成全流程上线。其中仅「客户料号反查自有料号」这一项功能,就节省了 1 名专职人员的对账工作量------因为以前对账要人工把送货单上的客户料号翻译成内部料号,现在扫码自动完成。

相关推荐
IPIPD39 分钟前
Proxifier规则为什么没有生效?从连接日志定位规则命中与DNS路径
前端
ZoeLandia40 分钟前
React6:组件通信
前端·react.js·typescript
爱勇宝40 分钟前
AI 都这么强了,咱们程序员以后还能干点啥?
前端·后端·程序员
FPGA小徐1 小时前
【一生一芯 / PA】AM 核心文件逐行解析(上):从 start.S 到 gpu.c
前端·算法
三十而立洋1 小时前
知枝 · MindSprout:可以直接将 markdown 转换为思维导图的 vscode 插件
前端·visual studio code
兔子零10241 小时前
架构师最危险的能力:用正确的技术,做出错误的架构决策
前端·javascript·后端
Bug收容所1 小时前
Vue+js Day2
前端·javascript·vue.js
掘金酱2 小时前
带着作品来,坐下来聊|掘金 X-lab · Coffee Talk 邀请你来见一面
前端·javascript·后端
CoovallyAIHub3 小时前
用 AI 做 PPT 被辞退,法院判公司赔:员工贴进对话框的数据,到底谁负责?
前端·agent