面向场景:小微企业(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,够用) |
好 | 手机网络即可 | ⚠️ 能力受限 |
决定性理由有三条:
-
仓管员口袋里已经有扫码器了。 现在任何一部智能手机的摄像头,识别 Code128 料号标签、EAN-13 商品条码都毫无压力。为「扫码」单独买 3000 元的硬件,性价比说不通。
-
零安装、零维护。 这是小微企业最看重的。工业 PDA 最麻烦的不是买,是后面------设备坏了要换、系统升级要逐台操作、员工换人要重新配。小程序发个二维码扫一下就用,升级在服务端完成,客户端什么都不用做。
-
不用培训。 员工天天用微信,交互习惯是现成的。这一点在车间落地时特别重要------很多 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。
正确做法:
- 前端只提交「动作 + 数量」(出库 10),不提交算好的结果值
- 服务端在事务里做增减,并对库存行加锁或用版本号做乐观锁:
sql
-- 事务内执行,先校验版本,再更新
UPDATE stock
SET qty = qty - @outQty, version = version + 1
WHERE item_id = @itemId
AND version = @expectedVersion; -- 版本不符则影响行数为 0,说明被人改过
-- 影响行数 = 0 → 回滚并提示「库存已变化,请刷新重试」
- 库存不足要拦、要提示,而不是允许负库存(除非业务上确实允许,那也要留痕)
经验总结 :涉及数量增减的操作,永远不要用「读出来 → 算一下 → 写回去」的模式。这不是小程序的问题,是任何多端系统都会遇到的经典陷阱。
4.4 网关层:小程序不直连数据库,走泛化接口
这是整个方案里最影响长期维护成本的一节。
核心约束 :微信小程序只能访问 HTTPS 合法域名 (需备案、需在小程序后台配置白名单),不能直连内网数据库。所以中间必须有一层网关。
微信小程序 → HTTPS 网关 → 复用既有业务逻辑 → 数据库
我们没有 为小程序新写一套接口,而是把网关做成 6 个泛化接口:
| 接口 | 作用 |
|---|---|
login |
登录换会话标识 |
menu |
取当前账号可见的菜单(按权限过滤) |
meta |
取列表/单据的字段元数据 |
query |
通用查询(传模板 ID + 参数,而不是写死 SQL) |
save |
通用保存(主表/明细/子明细三层负载) |
exec |
执行动作(提交、审核等) |
为什么这六个就够了 :所有查询和保存都由「模板」驱动------服务端维护一张模板表,每个模板包含它对应的查询语句、可见字段、列宽等元信息。小程序端只认模板 ID:
ini
/query?template=xxx¶ms=yyy
带来的好处非常实际:
- 新增一个查询页,后端零改动 → 只加一条模板配置。这正是「没有专职 IT 人员也能维护」的技术前提
- 客户端不出现 SQL → 权限与数据范围在服务端统一控制,不会因为客户端被反编译而泄露
- 桌面端和手机端共用同一套逻辑 → 不会出现「电脑上查得到、手机上查不到」这类账不对齐的问题
顺带说一句:这套东西能成立的前提是既有系统已经把 SQL 集中管理。如果 SQL 散在各处,做网关时会非常痛苦------这一步的投入回报在后期才显现。
五、四个踩过的坑
坑 1:开发时好好的,上线后所有请求全失败
现象:本地调试一切正常,提交审核上线后,接口全部请求失败。
原因 :微信小程序的网络请求有硬性约束------必须是 HTTPS,且域名必须提前在小程序后台配置为合法域名。开发期可以勾「不校验合法域名」,所以本地看不出问题。
排查清单:
- 接口域名是否为 HTTPS(自签证书不算,必须是可信 CA 签发的)
- 域名是否已完成 ICP 备案(未备案域名无法加入白名单)
- 是否已在小程序后台 → 开发管理 → 服务器域名里配置(请求域名、上传域名要分别配)
- 域名是否带端口号(带端口需一并写清,且部分场景受限)
- 换域名后要重新提交审核------白名单变更不影响已发布版本,需重新发版
经验总结 :这类问题必须在第一次提审前就验证,不要等审核通过后才发现。上线流程里应该有一条「先配域名白名单,再提审」。
坑 2:扫一次码就退一层页面,连扫十次要退十次
现象 :wx.scanCode 是「打开一个全屏扫码界面 → 返回结果」的模型。如果在页面里连续调用,容易变成「扫完一次,页面被退掉了」。
原因:扫码是独立页面,返回时的页面栈处理不当会导致层级混乱。安卓上尤其明显。
处理方式:
- 扫码结果用回调处理,不要依赖页面返回事件
- 扫码页面自己维护「连续扫码」状态,不要每次重新调栈
- 返回按钮常驻------仓管员扫错码要能一键回到列表。不要只依赖系统返回手势,车间戴手套操作时手势经常划不出来
第 3 条是真实反馈里改出来的:任何需要员工戴手套、单手操作的界面,系统手势都不能作为唯一返回路径。
坑 3:条码识别率不稳定,尤其是自己打印的标签
现象:商品原厂条码一扫就过,自己用标签机打的料号标签经常扫不出来。
根因基本都在标签本身,不在扫码代码:
| 原因 | 处理 |
|---|---|
| 打印分辨率低、条码边缘发虚 | 提高打印 dpi,条码尺寸别缩太小 |
| 标签贴在弧面(如线材盘、圆罐) | 换小尺寸标签,避免跨弧面 |
| 覆膜反光 / 油污遮挡 | 提示改用「手动输入 + 模糊搜索」兜底 |
| 标签太小,相机对不上焦 | 小程序端提供「放大取景」提示 |
最重要的一条 :一定要提供手动输入 + 模糊搜索的兜底路径。 扫码是效率工具,不是唯一入口。如果扫码失败就完全走不通,员工会直接放弃整个系统------这是很多仓库系统上线失败的真实原因。
坑 4:多人共用账号导致数据串账
现象:为了省事,仓库几个人共用一个账号,结果出入库记录的经办人全是同一个人。
问题不在技术,在权限设计 :ERP 的单据要留经办人痕迹,共用账号等于审计链断裂------出了问题查不出是谁操作的。
处理方式 :一人一号,成本极低。ERP 的用户数计费下,仓库岗多开几个账号远比一次盘点差异的损失小。同时配合权限收敛:
markdown
仓管员账号 → 只看得到:出入库、库存查询
→ 看不到:财务、采购价格、客户信息
这条不只是管理要求,也是多端系统必须做的数据隔离------手机丢了、账号被盗,能造成的损失范围要可控。
六、边界:什么场景小程序 PDA 并不合适
必须说清楚,否则容易给出错误预期。
| 场景 | 小程序是否合适 | 说明 |
|---|---|---|
| 扫码出入库、库存查询 | ✅ 很合适 | 本文的场景 |
| 拍照录单(送货单、票据) | ✅ 合适 | 与 OCR 识别天然衔接 |
| 单人低频作业(每天几十次) | ✅ 合适 | 手机完全够 |
| 大仓高频分拣(每天数千次) | ❌ 不合适 | 工业 PDA 的物理按键与专业扫描头效率高得多 |
| 无信号的库房(地下室/冷库) | ⚠️ 需额外设计 | 要做本地缓存 + 恢复后补传,复杂度明显上升 |
| 现场打标签 | ⚠️ 能力受限 | 小程序对蓝牙打印机的支持不如原生,建议用云打印机或保留 PC |
一句话:小程序适合「轻量、多人、需要实时」的仓库现场作业,不适合「高频、重载、强离线」的分拣中心。
七、效果
跑通之后,实际改善主要在三个层面:
| 环节 | 之前 | 之后 |
|---|---|---|
| 扫码工具 | 无(或采购工业 PDA,2000--5000 元/台) | 员工自己的手机,零硬件成本 |
| 数据时效 | 回办公室补录,延迟半天到一天 | 现场即时,库存实时准确 |
| 录入字段 | 料号、名称、规格、单位、数量逐个手填 | 扫码带出前四个,只需填数量 |
| 维护成本 | 装 APK、逐台升级 | 零安装,服务端升级 |
真实客户反馈里,见效最快的往往不是「省了多少时间」,而是账实不符消失了:
已有客户(50 人规模电子企业)在 1 个月内完成全流程上线。其中仅「客户料号反查自有料号」这一项功能,就节省了 1 名专职人员的对账工作量------因为以前对账要人工把送货单上的客户料号翻译成内部料号,现在扫码自动完成。