记录一次车间看板的搭建(2026-05-14)

需求很简单:让工时自己说话,别再靠人抄

车间里的工时数据是有的——机器一直在采,落在 MySQL 里。问题是没人看。数据躺在表里,要问产量就得有人去查、去汇总、去做表。信息在,但不在需要它的人眼前。

这块看板就是为了把这句话反过来:数据在哪儿产生,就在哪儿显示。


先看数据长什么样

第一步永远是看表结构,而不是先想界面。

表是 work_load,在一台早期的 MySQL 上(100.64.0.2:3306,库叫 m3_ai_data)。字段不复杂:

字段 含义
START_TIME / END_TIME 一段工作的起止
WORKER_NUM 工位编号
WORKTIME 工时,单位秒
WORKLOAD 工作量,单位人·秒
AREA / MAIN_AREA 区域 / 主区域

两个细节后来证明很关键:工时是秒不是分钟,**工作量是"人·秒"**。也就是说,同是一小时,两个人干出来的是一个人的两倍——这一条决定了后面所有图表的口径。

还有一点,这几个字段都是 varchar。数值存成字符串,意味着不能在 SQL 里直接 sum,要么在 SQL 里 cast,要么在 Python 里转。这不是设计失误,是这类采集表的常态,习惯了就好。

五个工位,一条流水线

工位一共五个:

  • SCBX —— 上层布线
  • SCZZ —— 上层组装
  • DCZZBX —— 底层组装布线
  • GJQ —— 工具区
  • ZCZZ —— 中层组装

它们的 MAIN_AREA 都是 TST1,也就是 M3 手工流水线。

这一步看起来只是"抄了个字典",但实际上它把后面所有的展示都定死了:看板不是按人看,是按工位看。因为产线上真正需要被比较的,是工位之间的负载差异,而不是某个人某天干了多久。

界面:四块内容,两种主题

看板最终是四个 Tab:

  1. 总览 —— 当前整体情况
  2. 实时 —— 正在发生什么
  3. 时间轴 —— 一段时间的走势
  4. 分析 —— 对比和异常

刷新是 30 秒一次。这个数字没什么玄机,就是"人站在屏幕前能感觉到它在活,又不至于把数据库打爆"之间的一个折中。

配色上我做了深色和浅色两套,可以切换,切换状态存在 localStorage 里,下次打开还是上次选的那套:

  • 深色:页面 #0E1116、卡片 #161B22、描边 #30363D
  • 浅色:页面 #FFF、卡片 #F6F8FA、描边 #D0D7DE

五个工位各有一个颜色:蓝 #539BF5、绿 #57AB5A、橙 #E0744B、紫 #B083F0、琥珀 #E6B422(深色下另有一套对应值)。顶部 header 的底边用品牌红 #D50030——这一条后来成了我所有工业界面的固定动作。

深色是给车间大屏用的,浅色是给办公电脑看的。同一份数据,两种场合,两套皮肤。

启动方式

一条命令就能跑起来:start_dashboard.bat,或者直接 python factory_api_server.py,然后打开 http://localhost:8765/。

写 .bat 不是为了好看,是因为这块看板的目标用户不是我。要别人能自己双击打开,就不能要求对方先打开终端、切目录、敲命令。


最后

这块看板本身不复杂,但它确立了一个习惯:先把数据看清楚,再决定显示什么。

很多人做可视化是反过来的——先想一个漂亮的图,再去找数据往上套。结果就是图很漂亮,但看的人不知道该从里面读出什么。而只要老老实实从表结构出发,"按工位比负载"这件事就会自己浮现出来,根本不用设计。

后来这套东西迁移到了工厂内网(库和表名都变了,成了 10.103.50.147 上的 work_load_0521,采样间隔压到 10 秒),但口径和原则一个字没改:秒还是秒,人·秒还是人·秒,还是按工位比。这也算是那天留下的、最有价值的部分——不是代码,是口径。