记录一次在岗人数显示异常修复(2026-05-20)

在岗人数不是“最后一条记录的 worker_num”,而是“当前时刻还没有结束的那条记录”。

今天这台看板连续出两个问题:先是在岗人数全部显示成 1,查了半天发现 SQL 少了对时段的判断;修完没过多久,服务自己又退掉了。一天基本就在改查询和重启服务之间来回。

一、看板起来了,但依赖是补装的

先把看板重新拉起来,浏览器打开 http://localhost:8765/ 就能访问,PID 59140,端口 8765,自动连接 MySQL 实时数据,地址是 100.64.0.2:3306,30 秒自动刷新一次。

这里有个小插曲:新会话的 venv 被重置了,Python 依赖全丢。所以先把 flask、flask-cors、pymysql 补装完,服务才正常起来。当时没太在意,后面这个“会话重置”又出来刷了一次存在感。

二、在岗人数全为1:一眼就是时序问题

看板刚跑起来,就收到反馈:在岗人数逻辑不对,所有工位在岗人数都为 1,数据库里 worker_num 变成 0 也不显示 0。

我去翻查询,问题出在第 71-78 行:

1
WHERE (AREA, START_TIME) IN (SELECT AREA, MAX(START_TIME) FROM work_load GROUP BY AREA)

这条 SQL 取的是每个工位最后一条记录的 WORKER_NUM。但“最后一条”不等于“当前在岗”。如果这条记录的 END_TIME 早就过了当前时间,工人已经离场,数据库里那条记录的 WORKER_NUM 还是当时写进去的 1,程序就原样展示成 1。

根因:时段判断缺失。 查的是“最新记录”,不是“当前活跃记录”。

三、修改 SQL:CASE WHEN 判断结束时间

正确逻辑应该是:取当前时刻仍然活跃的记录,也就是 START_TIME <= NOW() 并且 END_TIME >= NOW() 或者 END_TIME 为空;如果没有任何活跃记录,在岗人数就是 0;如果数据库已经写入 WORKER_NUM = 0,就直接返回 0。

实际改法是在查询上做 CASE WHEN:

条件 显示人数
END_TIME >= NOW() 或为空 取数据库 WORKER_NUM 原值(时段仍活跃)
END_TIME < NOW() 强制返回 0(时段已结束,工人离场)
WORKER_NUM 本身为 0 返回 0

核心就一句话:先按 START_TIME 取每个工位最新一条,再看这条 END_TIME 有没有过期。过期了,在岗人数就是 0;没过期,才取 WORKER_NUM。

四、验证:5 个工位全部归零

改完直接看 API 返回,5 个工位的 worker_num 全部是 0,和实际情况对上了——上午 9 点多那段时段已经全部结束,本来就应该显示 0。

这个结果让我挺踏实,说明逻辑是对了。等下次数据库写入新时段(END_TIME 是将来时间或者为空),在岗人数会自动变回正确值,不用再手工干预。

五、访问不了:会话级进程的坑

人数问题刚解决,又有人反馈 http://localhost:8765/ 访问不了了。

看了一下,是 WorkBuddy 后台进程的机制:它是会话级别的,每次对话间隔时间一长,或者会话重置,后台跑的 Flask 进程就会自动退出。这跟 Python 依赖丢失是同一个根源——会话环境不是常驻的。

恢复也简单,手动重启服务就行。为了让进程不依赖当前会话,把启动方式换成了双击 start_dashboard.bat,路径是:

1
C:\Users\Administrator\WorkBuddy\2026-05-14-task-2\start_dashboard.bat

在文件管理器地址栏粘贴这个路径回车,然后双击 bat,服务就独立于会话跑起来了。

六、遗留

还有一个坑没填:现在每次会话重置还是得靠手工双击 bat 重启。后面打算把它注册成 Windows 服务,开机自启动,这样就不会因为会话断了把看板搞掉。

另外,这次验证是基于上午 9 点多已经结束的时段,等下一次真实的新时段写进 work_load 表,再确认一遍“活跃记录自动显示、结束后自动归零”这个闭环。