业务场景: SMT 车间,MES 里的"换料记录、异常单、首件确认"等表单需要选择经办人/确认人。人员主数据来自 HR 系统。后来 HR 把离职人员状态置为"离职",MES 人员下拉默认只取在职人员。结果新表单好用了,但历史表单上原经办人一旦离职,下拉框就空白,时间久了,使用人员在查看表单时,不知该表单的经办人、确认人为谁的问题。
涉及系统:
-
HR 系统:人员主数据权威源,维护员工在职/离职状态、部门、工号、姓名。
-
MES 系统:生产工单、换料记录、异常单、首件确认等表单,页面使用人员下拉,业务表存经办人 ID。
-
OA/BPM:审批流,审批记录里存了审批人姓名快照,所以历史审批人基本正常。
-
ERP:接收 MES 工单完工、库存扣料等数据,操作员字段多为文本,用于和 MES 对账。
**原始需求:**业务提了两个看似矛盾的诉求:新建表单时,人员下拉不要显示几千人,也不要让用户选到离职人员;但查看历史表单时,必须能看出当初是谁操作的,不能因为人离职了就空白。IT 之前为了满足第一个诉求,把下拉数据源一刀切过滤成"在职",结果历史单据经办人大量空白,SMT 质量追溯和 ERP 对账都受影响。
**排查/分析过程:**先从 MES 历史换料记录页面开始查。选一条确认人已离职的单据,页面确认人显示空白。打开浏览器网络请求,发现下拉调的是 HR 人员选项接口,参数是 status=active,返回数据里没有这个离职人员。再查 MES 业务表,发现只存了 handler_id,没有存姓名快照。查看页又复用了编辑页的下拉组件,用人员选项去匹配 ID 对应的 label,匹配不到就显示空。继续查 HR,发现人员没有物理删除,只是 status=inactive,姓名还在。OA 那边因为审批记录存了姓名快照,所以历史审批人正常。根因是:下拉数据源承担了历史回显职责,且过滤条件一刀切。
**方案设计:**考虑了三种方案。
方案 A:下拉恢复全量人员。历史能显示,但新建时列表太长,还可能选到离职人员,否决。
方案 B:每个页面单独改,查看时单独查 HR 详情。页面太多,工作量大,容易漏,风险高。
方案 C:公共人员下拉接口加 includeIds,默认只返回在职,但把当前表单已选人员 ID 作为例外带出来;离职人员标记"已离职",只用于回显,不能新选;查看页直接用姓名快照或文本显示。
最终选 C,因为改动集中在公共接口和公共下拉组件,大部分页面不用大调,能满足"正常显示"的目标。后续再补业务表姓名快照和提交校验放行原值。
技术实现:
1)表结构:HR 人员表保留软删除,字段如 employee_id、name、status、leave_date、dept_id。MES 业务表增加 handler_name、handler_dept_name 快照字段,保存时写入。
2)接口设计:
bash
GET /api/common/employee-options?status=active&includeIds=1001,1002
后端 SQL 伪代码:
bash
select * from hr_employee
where status = 'active'
or employee_id in (:includeIds)
order by status, name;
返回时对离职人员加 label:
bash
[
{ "id": 1, "name": "李四", "status": "active", "label": "李四" },
{ "id": 1001, "name": "张三", "status": "inactive", "label": "张三(已离职)", "disabled": true }
]
3)前端公共下拉组件:加载选项时自动把当前值塞进 includeIds:
bash
const includeIds = currentValue ? [currentValue] : [];
const options = await api.get('/common/employee-options', {
status: 'active',
includeIds: includeIds.join(',')
});
如果当前值还不在选项里,就用业务表快照或单独查人员详情补一个 option,至少显示"张三(已离职)",不能空白。
4)提交校验:新建时校验必须在职;编辑时如果经办人没变,即使已离职也允许提交;如果换了人,新选人员必须在职。
5)查看页:不再依赖下拉数据源,直接显示 handler_name,离职状态动态补充为"张三(已离职)";查不到就显示"已离职人员(ID:1001)"。
**上线效果:**新建工单下拉从 3000 多人降到 800 多在职人员,选择速度明显提升;历史换料记录、异常单中涉及离职经办人的 600 多条记录恢复显示,经办人空白率从约 5% 降到 0;编辑历史单据不改经办人时不再报"人员必须在职";SMT 质量和 ERP 对账能追溯到具体操作人,业务投诉下降。
**踩坑与反思:**一开始只改前端,把离职人员硬塞进下拉,结果新建时也能选到离职人员,被业务发现;后来加了 disabled 和后端校验才控制住。还遇到后端校验没放行原值,编辑历史单直接报错。另外只存 ID 不存姓名快照,人员改名或部门调整后,历史显示会和当初不一致,后来补了 handler_name 快照。如果重来,应该一开始就把"人员状态"和"可选性"分开,把"历史回显"和"新建选择"分开;人员主数据坚持软删除;业务表保存时冗余姓名快照;能改公共组件和公共接口,就不要逐页打补丁。