做这套系统之前,我一度以为最难的是人脸识别,真正把“微信小程序+Web+PC三端”扛上线之后才发现,人脸识别反而是最省心的,被磨掉最多时间的是库存流水、批次追溯和三端数据一致性的边角问题。
先说结论:这套A仓库管理系统最终实现了小程序端、Web管理后台、PC端收发货台三端共用一套数据,人脸识别贯穿“领料、入库、出库、交接”四个核心动作,进销存部分覆盖了采购入库、销售出库、调拨、盘点、库存预警。投入到一个月吞吐量约两万单的中型仓后,单笔出入库的确认时间从原来填单子的七八分钟压缩到三十秒以内,而且责任人和操作记录全部自动留痕。
整篇文章我会把架构怎么分、人脸识别流程怎么接线、进销存数据模型怎么设计、三端联调时踩过的坑都摊开讲,适合正在做仓库类管理系统的后端、全栈同学,也适合想给自家仓库做数字化的小团队参考。
1. 三种客户端同时存在的背后,是三类完全不同的使用场景
很多团队拿到需求后第一反应是“做个管理后台就行了”,实际到仓库里待一天就会发现,这个想法根本不成立。仓管员站着扫码、叉车司机开着车等指令、老板坐在办公室盯数据,这三类人的操作频率、设备形态、网络环境完全不一样。
1.1 仓库现场的三类角色,决定了三端不能互相替代
仓库现场最核心的角色是仓管员和搬运工。这类人不坐办公室,手上一股机油味,不可能让他们抱着一台电脑走来走去,最好的终端是手机,而且是以微信小程序为载体。不用安装App、扫码即开、用完就退,遇到货品搬运时揣兜里方便。这一端承担的是快速作业:扫码、拍单、签字确认、查询库位。我们当时给仓管员配的是几百块的扫码枪加手机,成本比给每人配PDA低很多。
第二类角色是前台开单员和调度员。他们在仓库门口或办公室,干的是批量录入、货单审核、打印标签订单这类活。手机小程序对这种场景太吃力,键盘鼠标更顺手。他们用的就是Web端管理后台,负责基础资料、单据审核、报表查看。
第三类角色是收货员、盘点员和叉车司机,可能在零下十几度的冷库、雨水淋湿的月台、信号很差的货架深处,手上没空理手机。这些人需要“刷脸通过”和快捷确认,PC端设备往往直接放在闸口或月台上,搭配人脸识别摄像头完成半自动交接。司机不用动手,对着镜头看一眼,仓管员在后台看到人脸比对通过后按确认放行,效率高,责任也清晰。
三类角色分工清楚了,三端自然就都缺不了。这不是产品经理拍脑袋,而是仓库里真的同时存在这三种工作形态。
1.2 技术选型:小程序、Web、PC到底各用什么框架
技术选型上,我们一开始考虑过用一套跨端方案通吃,后来放弃了。三个月内要交付,跨端方案在三端差异较大、人脸识别SDK适配不好的情况下,坑太多了。
小程序端用的是原生微信小程序框架,没有上重型轮子。原因很直接——小程序讲究启动速度和包体积,仓库现场的人用手机性能普遍不高,原生写法可控性最好,遇到扫码API、蓝牙打印、相机调用都比较稳。人脸识别在小程序上我们用“摄像头采集人脸图片并上传后台比对”的方案,不在端上做活体检测。这样模型统一在服务端,端上逻辑就是一个拍照上传的动作,开发成本省了一大半。
Web端我们用Vue3加Element Plus,这些组件生态成熟,表格、表单、弹窗都能快速搭。真正要花心思的是出入库单据的批量操作和权限菜单的细分,这部分后面单独说。
PC端其实也是浏览器跑的,做成包着壳的Web应用,好处是部署简单、升级不用让人去每台电脑装客户端。PC端是人脸识别的主力地方,所以摄像头适配是重点。我们用了HTML5的摄像头调用能力,兼容常见的USB摄像头,给现场提示“光线不足”“请摘下口罩”这些反馈。
三端技术栈完全统一是不现实的,我们选择统一的是API和数据层。无论哪个端,最终打的都是同一套后端接口,权限、库存、单据的逻辑全部在服务端收敛。
2. 人脸识别不是噱头,它解决的是一线交接里最头疼的“人和单对不上”
仓库类系统做人脸识别,很多外行会觉得是炫技。但你真去过现场就明白:仓库里最怕的不是账算错,而是“货发了半天,签收人找不到”“某个单子是谁领的说不清”。传统纸笔签名很容易代签,监控录像查起来费时。人脸识别挡的是这个口子。
2.1 出入库流程里,人脸识别到底嵌在哪几个环节
我们最终在四个环节调用人脸识别通过闸机:领料、入库交接、出库交接、夜班巡检。设计原则只有一个——人脸识别不单独作为一种登录方式,而是作为“动作确认”和“工牌替代”。
拿领料来说,流程是这样的:仓管员在小程序里扫码填写领料单,提交后领料人到现场,在摄像头前站定,PC端调用人脸识别后台服务,返回“识别成功,匹配到张三,工号A1023”之后,PC自动弹出确认按钮,确认后领料流程才真正完成。这种设计避免了有人声称“我没领过物料”的扯皮现场。
入库交接是另一个关键点。供应商送货过来,收货员先扫码确认货品,再让送货人在人脸识别机器前留个底。这样以后翻旧账时,不只看到“某日某单收到某货”,还能看到当时是谁送的货、是谁验的货,责任链完整。
2.2 人脸识别方案选型:不做本地模型,统一走后端
说实话,我们只有两个人,端上部署自研人脸模型根本不现实。我们选的是某云服务商的现成API,服务端保存注册人脸的特征值,每次上传一张现场照片,API返回匹配到的用户ID和置信度。
这里有个关键设计:人脸照片只作为匹配依据,不在库里留存原始大图作长期保存。我们只存储特征值和匹配时间,合规压力小很多,用户也更容易接受。准确率上用现成API大概是万分之一误识率之下,仓库这种垂直场景足够用。
至于活体检测,我们采用了一个朴素但有实效的组合:现场照片必须拍到完整头部、识别过程中需要做轻微点头或张口的动作提示。云API本身带活体检测参数,开启后照片出现明显翻拍时会被拒绝。这比完全不做强得多,也能挡住大部分拿手机照片冒签的情况。
如果你是自建人脸识别,同等效果至少需要一个好一点的模型训练集和GPU服务器,至少多出两名算法工程师的工作量,小团队根本没这个余力。所以我的建议很明确:能用云API就别自研。
2.3 识别失败时的兜底流程,比识别本身更重要
人脸识别再准,总有失败的时候:工人戴着口罩、帽子,冷库进门眼镜起雾,夜班光线不足。如果识别失败就卡死流程,现场马上会吵起来。
我们的兜底逻辑很简单——人脸识别失败后允许人工干预,但必须留痕。比如输入工号后调出注册照片,现场仓管员在PC端看到照片与本人一致后点击“人工通过”,系统记录“人脸匹配失败,由某某做人工确认”。这个兜底动作保留了责任链,也比强制识别通过更灵活。
还有一类特殊情况是临时人员,比如快递员、临时搬运工,仓库不一定给他们注册人脸。这时候走访客模式:登记姓名电话,现场拍一张照片存档,不参与人脸比对。客户来了以后如果投诉某批货出了问题,至少能根据照片辅助排查。
3. 进销存的核心不是加减乘除,而是每一次变动都能说清来龙去脉
库存账看似就是加加减减,但仓库真正怕的是“账面负数还找不到原因”“某个批号坏了却说不出是哪批进的货”。我们拆解进销存业务时,把重点放在了三个模型上:商品、批次、库位。
3.1 商品表、批次表、库位表:三个维度组合出精确库存
先看商品表。它存的是SKU基本信息:编码、名称、规格、单位、分类、默认供应商。这部分不复杂,真正困难的是同一款商品有多个批次的情况,比如一批食品保质期不同,或同一型号但采购价不同的物料。这时候如果只做总库存加减,后面做保质期预警和先进先出根本无从谈起。
所以我们加了批次表。每一批货入库时生成一个批号,批号绑定生产日期、保质期、入库时间、采购价。这样库存不再是单一商品的一个总数,而是“某个商品在某库位、某批次有多少件”的记录。做先进先出时,系统自动按批号到期时间排序,提示先发早批次的货。算毛利时也能精确到每批货的采购成本,不靠平均成本大概估算。
库位表解决的是“货到底在哪”的问题。库位编码一般从区到排到位,例如A-03-02代表A区第3排第2个库位。我们要求入库时必须扫描或选择库位,出库时如果没有指定库位,系统会按先进先出和批次到期时间智能推荐。
三表配合后,库存查询就变成这样一句简单但要清晰的逻辑:某个SKU在某库位、某批次,当前可用数量是多少。未来想扩展多仓,只需要再加一个仓库维度,所有逻辑全部可以平移。
3.2 库存流水和操作日志:数据准确性的最后防线
进销存系统最危险的设计,是直接在库存表上做加减。一旦有人修改错了或并发重复提交,账面直接就脏了,而且说不清是谁改的。我们从第一天起就坚持“库存表只做冗余汇总,流水表才是依据”。
每一次变动——入库、出库、调拨、盘点、报损——都会生成一条流水记录,至少包含这些字段:
| 字段 | 含义 |
|---|---|
| 流水号 | 唯一编号,格式:类型+日期+序号 |
| 来源单号 | 从哪张单触发,可追溯到采购单/销售单/盘点单 |
| 商品SKU | 商品维度 |
| 批次号 | 批次维度 |
| 库位编码 | 位置维度 |
| 变动数量 | 正数或负数 |
| 变动前结存、变动后结存 | 当前记录该时刻的结存快照 |
| 操作人ID | 实际是谁做的 |
| 创建时间 | 时间戳,精确到秒 |
有了流水表,退款、退货、补单都只做追加,不修改历史。某一天账对不上,只要按流水反推就能定位到具体哪一笔出了问题,再看那一笔的输入单据、审批记录和拍照留底,基本能还原现场。这个做法听着笨,但它是仓库系统稳定运行的核心保障。
库存汇总表仍然保留,但只作为列表展示和库存预警的加速查询。每次业务发生完,在同一个事务里更新汇总表。如果某个极端情况下汇总和流水不同步,以流水为准,第二天定时任务会扫描修复汇总值,并记录修复日志。
3.3 盘点与差异流程:临时锁库还是允许误差
仓库每个月必须盘点,但盘点最怕影响正常出入库。我们用的策略是“盘点期间只锁被盘点库位,不锁整个仓库”。盘点开始后,该库位不允许出库操作,但入库可以先登记到临时待检区,等盘点结束再入位。
盘点差异的处理逻辑值得说一下。我们设计了三种差异确认方式:盘亏、盘盈、货位移位。盘亏要人工选择原因(丢失、错发、未录单等),盘盈也要选来源(漏录单、供应商多发等),货位移位则直接更新库位绑定。所有这些差异确认必须有两个人的权限:一个人提交,另一个人审核,防止盘点的仓管员自己把差异悄悄抹平。
盘点单生成差异明细后,系统自动生成对应的库存调整单,再走一遍流水记录,这样就保证了库存表、流水表、单据表三者始终一致。
4. 三端联动的核心工程:API层设计和状态同步,踩过的坑比想象中多
三端做出来后,真正折磨人的不在业务,而在联调。小程序、Web、PC每端都有自己的网络环境和操作节奏,稍不注意就会出现“一端改了数据,另一端还是旧值”“同样的接口三端传的参数不一致”这种低级但致命的bug。
4.1 统一API规范:接口返回结构、鉴权、幂等
我们定下的接口返回结构是固定三层:code、message、data。code为0表示成功,非0为业务错误码。前端不用猜,拿到code直接弹message提示。这块看起来是小事,但三端各自写一套返回解析时,你才知道什么叫“同一个错误码三种表现形式”。
鉴权方面,小程序端使用用户授权后的免登令牌。Web端和PC端用账号密码登录发放令牌,令牌有效期八小时。但仓库场景很特殊——仓管员可能一整天只打开一次小程序,如果中途令牌过期,让他在冷库里重新输密码会想骂人。所以我们给小程序端做了刷新机制:每次调用接口时如果检测到令牌快过期,自动用refresh_token换新token。这个过程对用户无感。
幂等性在三端里很关键。小程序网络差的时候,用户点了一次“提交入库单”,结果超时,又点一次,结果重复提交了两张单。我们要在接口层做防重。方案是前端每次打开一个新单就生成一个前端操作ID,后端保存这个ID,同一ID的重复请求直接返回上一次的处理结果。这个设计让所有“请求超时后重试”的场景都变得安全。
下面这个例子是出库单创建接口的伪代码示意,展示了幂等和大字段传递:
// 出库单创建请求(简化) POST /api/stockout/create { "operationId": "c8f9a2c1-3d91-4e5f-9b71-1234567890ab", "warehouseId": "wh001", "outType": "SALE", "goodsList": [ { "sku": "SP1001", "batchCode": "PC20240912-A1", "qty": 50, "location": "A-03-02" } ], "receiver": { "name": "张三", "workerId": "A1023", "faceMatched": true } } // 返回:{ code: 0, message: "ok", data: { stockOutNo: "SO20241012001" } }4.2 三端数据实时性:推送、轮询与刷新策略
PC端和Web端在同一办公室时,数据即时性要求高。如果仓库里刚接到一批货,管理员在Web端马上要看新库存,不可能等用户刷新页面。
我们用了轻量方案:小程序端每次提交成功后,把变更动作写入一张事件表;Web端和PC端通过轮询接口每30秒拉一次事件表,有新变更则主动刷新当前页面或提示用户“库存已更新”。不要上复杂的WebSocket推送,仓库内网环境不稳定,轮询虽然延迟有一点但不至于错乱,分担给三端同步足够。
跨端状态变化最大的场景是“人脸识别人员与PC端单据确认”。送货员在小程序提交入库单后,PC端收货员需要在同一单据上补充称重数据。我们在Web端的事件中心里提醒“有一张入库单等待称重”,PC端页面则聚焦待办列表。这种基于任务的同步比单纯的库存数字同步更有用。
4.3 PC端硬件的接入细节:扫码枪、摄像头、电子秤
PC端一定要接入各种外设。扫码枪其实是模拟键盘输入,接上USB后焦点落在输入框里,扫码就自动打字,这时候要注意失焦问题。我们在页面里只要聚焦到扫码框,就禁止其他全局键盘事件抢焦点。否则扫着扫着货品编码被截断成两半,是最典型的坑。
摄像头适配是另一大坑。不同厂商摄像头对分辨率、驱动支持不一样,还都是免驱的最好。我们要求摄像头至少支持720P,初始化时通过媒体设备API枚举设备并让用户手动选择要用的那个。因为有些电脑同时接了摄像头和视频采集卡,不手动选,画面直接黑屏。
电子秤通过串口或USB HID读取重量。我们处理的方式是PC端页面开启“称重”按钮后,后端接口轮询读取电子秤模块,称重稳定后自动填入净重字段。这里有个稳妥经验:不要尝试实时连续读数,只取那个稳定到第三位小数后等待两秒不变的值,才是可靠的。连续读数会因为抖动导致入库数量虚高。
5. 跑真库之后才暴露的问题:搜索、批号、拍照的三次教训
我们开发期自测加模拟数据,一切顺滑,真正上到现场才知道系统哪里反人类,哪里会让人偷偷绕开。这里说三个最典型的教训。
5.1 键盘快捷键没有平滑移动:PC端录入效率不如纸单
PC端表单上来就是各种输入框,看起来没毛病,但仓库老师傅用电脑的习惯是能不打字就不打字,能按回车就不摸鼠标。第一版表单结束后,所有新增行的确认都要鼠标点按钮,老师傅宁可拿纸记下来再集中录入。我们后来把所有高频操作都加了快捷键:扫码后自动提交、方向键移动选中、F2保存、F3打印。快捷键影响的不是功能完整性,而是用户愿不愿意用你的系统。这种体验问题往往比功能bug更致命。
5.2 批号手输容易错:配置扫码解析规则才彻底解决
商品批次号有时是二维码,有时是一维码,各种编码规则都有。第一版让仓管员用扫码枪扫一下再手输批号,结果错得离谱,因为有些供应商的条码包含了很多前缀,仓管员自己也不知道哪些是有效位。
后来我们做了“扫码解析规则配置”功能。管理员在Web端维护每个供应商的条码正则规则,例如从条码的第3位到第10位截取作为批号,或者匹配某一正则表达式提取数字。仓管员在前端扫码后,系统自动提取正确批号,不再需要人眼手动识别。这个改进直接影响准确率,从之前每月错三四十条下降到近零。
5.3 拍照留底发现拍不清:改为自动对焦加全景拼接
系统里要求入库时拍几张现场照片,本意是留证。结果仓管员嫌麻烦,随手一拍,有些照片糊得完全看不清货物编号。我们先是让他们用拍照辅助线对准条形码,效果一般,后来发现手机摄像头自动对焦到清晰的时候拍照完全可行。于是小程序端做了一个“连续拍三张选清晰一张”的动作,同时界面提示“请对准货物编号区域”,数据库里存的清晰率明显提高。
在PC端月台拍照,我们用了定时连拍,每0.5秒拍一张,用户点击停止后选最清晰的一张,这比让人反复对准再拍更靠谱。这些拍的照片都关联到对应单据和批次,作为仓储审计的证据链的一部分。
6. 上线后的持续运营:人脸注册率、库存准确率、用户习惯
系统开发完只完成了一半,另一半在推广和数据治理。这里分享三个运营层面的体会,给准备做这类系统的团队打个预防针。
6.1 一线工人对“刷脸上班”天然抵触,注册率需要运营技巧
我们上线人脸识别后,第一周注册率只有六成。不是技术问题,是大家心里有疙瘩。后来我们做了两件事:一是把注册流程改成“领料时必须顺便注册”,理由是人脸注册就是个20秒动作,不额外占用时间;二是管理员在晨会上明确人脸识别的作用是保护仓管员自己——以后再有人不认账说他没领过料,这个记录就是证据。两周后注册率到了百分之九十八。
6.2 库存准确率不是上线后自动变准,而是一个清理过程
上线之前,老系统里的库存数据其实已经不干净了。我们不指望数据凭空变准,而是上线当天做了一次全仓大盘点,把账面数和实物数全部校正一次。之后每月根据盘点的差异率和差异明细,反向去找是哪个环节漏了流水。坚持三个月后,库存准确率稳定在99.6%以上。这个数字不是系统带来的,是“核对—纠错—追责—优化流程”的循环带来的。
6.3 小步快跑,别指望一次性把所有功能做完
很多团队做仓储系统最怕漏功能,总想什么都做。我们当时砍掉了预约排队、自动补货、运输管理这些听起来很好但暂时用不上的模块,一心只稳固“进得明白、出得清楚、存得可查”这条主线。上线三个月内收到的反馈集中在“打印标签太慢”“调拨单无法批量编辑”这些很具体的点上。二期的优先级自然就清楚了。
最后再分享一个我个人的感受:仓库管理系统最讽刺的地方在于,它表面是一套软件,实际交付的是管理秩序。人脸识别、三端同步、进销存流水都只是工具,真正让仓库变顺的是帮现场把责任链理顺了。如果之后你想做二期的多仓调度或智能补货,沿用当前这套“以流水为准、以批次追溯、以任务联动”的思路,扩展麻烦事会比自己拍脑袋重做一遍少得多。