# 调度单执行人员同步功能说明 ## 功能概述 在同步急救转运任务到旧系统调度单时,将任务的执行人员信息同步到旧系统的随行人员参数中,并根据人员角色(司机/医生/护士)自动分配到对应的Entourage参数。 ## 实现时间 2025-10-25 ## 业务背景 ### 旧系统随行人员参数说明 旧系统(admin_save_24.gds)通过以下参数管理随行人员: - **Entourage_1**:司机的OA_UserID - **Entourage_3**:医生的OA_UserID - **Entourage_4**:护士的OA_UserID - **EntourageLeadID**:领队的EntourageID(1/3/4之一) ### 业务规则 1. **第一个执行人员自动成为领队**: - 如果第一个人是司机,`EntourageLeadID = 1` - 如果第一个人是医生,`EntourageLeadID = 3` - 如果第一个人是护士,`EntourageLeadID = 4` 2. **每个角色只取第一个匹配的人员**: - 如果有多个司机,只取第一个司机的OA_UserID - 医生和护士同理 3. **角色判断规则**: - 根据用户的角色名称(`roleName`)判断 - 角色名称包含"司机"的为司机 - 角色名称包含"医生"的为医生 - 角色名称包含"护士"的为护士 - 其他角色默认作为司机处理 ## 技术实现 ### 1. 数据流程 ``` 新系统任务执行人员 ↓ 获取执行人员ID列表(assigneeId) ↓ 查询每个人员的用户信息和角色 ↓ 判断人员类型(司机/医生/护士) ↓ 获取OA_UserID ↓ 分配到对应的Entourage参数 ↓ 第一个人员自动设置为领队 ↓ 传递给旧系统调度单接口 ``` ### 2. 核心方法实现 #### syncTaskAssignees方法 ```java /** * 同步任务执行人员信息到调度单随行人员参数 */ private void syncTaskAssignees(SysTask task, Map params) { // 1. 获取任务的执行人员ID列表 List assigneeIds = getTaskAssigneeIds(task.getTaskId()); // 2. 初始化变量 String leadEntourageId = ""; // 领队的EntourageID String driverOaId = ""; // 司机的OA_UserID String doctorOaId = ""; // 医生的OA_UserID String nurseOaId = ""; // 护士的OA_UserID // 3. 遍历执行人员 for (int i = 0; i < assigneeIds.size(); i++) { Long userId = assigneeIds.get(i); SysUser user = sysUserMapper.selectUserById(userId); if (user == null || user.getOaUserId() == null) { continue; } String oaUserId = user.getOaUserId().toString(); String userType = getUserType(user); // 4. 根据用户类型分配到对应的Entourage参数 if ("driver".equals(userType)) { if (driverOaId.isEmpty()) { driverOaId = oaUserId; if (i == 0) leadEntourageId = "1"; // 第一个人且是司机 } } else if ("doctor".equals(userType)) { if (doctorOaId.isEmpty()) { doctorOaId = oaUserId; if (i == 0) leadEntourageId = "3"; // 第一个人且是医生 } } else if ("nurse".equals(userType)) { if (nurseOaId.isEmpty()) { nurseOaId = oaUserId; if (i == 0) leadEntourageId = "4"; // 第一个人且是护士 } } } // 5. 设置参数 params.put("EntourageLeadID", leadEntourageId); params.put("Entourage_1", driverOaId); params.put("Entourage_3", doctorOaId); params.put("Entourage_4", nurseOaId); } ``` #### getUserType方法 ```java /** * 判断用户类型(司机/医生/护士/其他) */ private String getUserType(SysUser user) { String roleName = ""; // 从用户的角色列表中获取角色名称 if (user.getRoles() != null && !user.getRoles().isEmpty()) { roleName = user.getRoles().get(0).getRoleName(); } // 判断是否为司机 if (roleName != null && roleName.contains("司机")) { return "driver"; } // 判断是否为医生 if (roleName != null && roleName.contains("医生")) { return "doctor"; } // 判断是否为护士 if (roleName != null && roleName.contains("护士")) { return "nurse"; } // 其他类型,默认为司机(保证至少有一个人员) return "driver"; } ``` #### getTaskAssigneeIds方法 ```java /** * 获取任务的执行人员ID列表 */ private List getTaskAssigneeIds(Long taskId) { List assigneeIds = new ArrayList<>(); // 从任务表获取主要执行人 SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId); if (task != null && task.getAssigneeId() != null) { assigneeIds.add(task.getAssigneeId()); } // TODO: 未来如果有sys_task_assignee关联表,可以从表中查询所有执行人员 return assigneeIds; } ``` ### 3. 调用位置 在`buildDispatchOrderParams`方法中,添加执行人员同步逻辑: ```java private Map buildDispatchOrderParams(SysTask task, SysTaskEmergency emergency) { Map params = new HashMap<>(); // ... 其他参数设置 // 执行人员信息(随行人员) syncTaskAssignees(task, params); return params; } ``` ## 数据示例 ### 场景1:司机+护士 **新系统数据**: ``` 执行人员: 1. 张三(用户ID=101, OA_UserID=1001, 角色=司机) 2. 李四(用户ID=102, OA_UserID=1002, 角色=护士) ``` **同步参数**: ``` EntourageLeadID = 1 // 第一个人是司机,领队为Entourage_1 Entourage_1 = 1001 // 司机:张三 Entourage_3 = // 医生:无 Entourage_4 = 1002 // 护士:李四 ``` ### 场景2:医生+司机+护士 **新系统数据**: ``` 执行人员: 1. 王五(用户ID=103, OA_UserID=1003, 角色=医生) 2. 赵六(用户ID=104, OA_UserID=1004, 角色=司机) 3. 孙七(用户ID=105, OA_UserID=1005, 角色=护士) ``` **同步参数**: ``` EntourageLeadID = 3 // 第一个人是医生,领队为Entourage_3 Entourage_1 = 1004 // 司机:赵六 Entourage_3 = 1003 // 医生:王五 Entourage_4 = 1005 // 护士:孙七 ``` ### 场景3:只有司机 **新系统数据**: ``` 执行人员: 1. 张三(用户ID=101, OA_UserID=1001, 角色=司机) ``` **同步参数**: ``` EntourageLeadID = 1 // 领队为司机 Entourage_1 = 1001 // 司机:张三 Entourage_3 = // 医生:无 Entourage_4 = // 护士:无 ``` ### 场景4:无执行人员 **同步参数**: ``` EntourageLeadID = // 无领队 Entourage_1 = // 无司机 Entourage_3 = // 无医生 Entourage_4 = // 无护士 ``` ## 旧系统处理逻辑 旧系统(admin_save_24.gds 第168-206行)接收参数后的处理: ```vbscript '写入随行人员 EntourageLeadID = SafeRequest(Request.form("EntourageLeadID")) '领队ID '循环处理所有EntourageID(从dictionary表查询) sql="select vID from dictionary where vType=1 and vtitle='DispatchOrdEntourage' order by vOrder" rs.open sql,objConn,1,1 do while not rs.Eof EntourageID = rs("vID") EntourageOAid = SafeRequest(Request.form("Entourage_"&EntourageID)) If EntourageOAid<>"" And EntourageOAid<>"0" Then EntourageLead = 0 If CStr(EntourageLeadID) = CStr(EntourageID) Then EntourageLead = 1 '插入到DispatchOrd_Entourage表 sql="insert into DispatchOrd_Entourage (...) values (...)" objConn.Execute sql End If rs.movenext loop ``` **数据库写入结果**(DispatchOrd_Entourage表): | DispatchOrdIDDt | EntourageID | EntourageOAid | EntourageLead | |-----------------|-------------|---------------|---------------| | 10001 | 1 | 1001 | 1 | | 10001 | 4 | 1002 | 0 | ## 角色配置要求 ### 系统角色配置 为了正确识别人员类型,需要在系统中配置以下角色: 1. **司机角色**: - 角色名称必须包含"司机"关键词 - 例如:"司机"、"急救车司机"、"120司机" 2. **医生角色**: - 角色名称必须包含"医生"关键词 - 例如:"医生"、"急诊医生"、"随车医生" 3. **护士角色**: - 角色名称必须包含"护士"关键词 - 例如:"护士"、"急诊护士"、"随车护士" ### OA_UserID配置 每个用户必须配置对应的OA_UserID(旧系统用户ID): ```sql -- 在sys_user表中添加oa_user_id字段(如果还没有) ALTER TABLE sys_user ADD COLUMN oa_user_id INT COMMENT '旧系统OA用户ID'; -- 为每个用户配置OA_UserID UPDATE sys_user SET oa_user_id = 1001 WHERE user_id = 101; -- 张三 UPDATE sys_user SET oa_user_id = 1002 WHERE user_id = 102; -- 李四 ``` ## 日志记录 系统会记录详细的日志信息,便于排查问题: ``` INFO: 任务执行人员同步成功,任务ID: 10001, 领队ID: 1, 司机: 1001, 医生: , 护士: 1002 WARN: 任务无执行人员,任务ID: 10002 WARN: 执行人员信息不存在或未配置OA_UserID,用户ID: 103 WARN: 用户角色无法判断类型,默认为司机,用户ID: 104, 角色: 普通员工 ERROR: 同步任务执行人员异常,任务ID: 10005 ``` ## 测试验证 ### 测试步骤 1. **创建急救转运任务**: - 选择执行人员:张三(司机)、李四(护士) - 保存任务 2. **检查新系统数据**: ```sql SELECT assignee_id FROM sys_task WHERE task_id = ? -- 预期:assignee_id = 101(张三的ID) ``` 3. **查看同步日志**: ```bash tail -f logs/sys-info.log | grep "任务执行人员同步" ``` **预期日志**: ``` 任务执行人员同步成功,任务ID: 10001, 领队ID: 1, 司机: 1001, 医生: , 护士: 1002 ``` 4. **检查旧系统数据**: ```sql -- 查询DispatchOrd_Entourage表 SELECT EntourageID, EntourageOAid, EntourageLead FROM DispatchOrd_Entourage WHERE DispatchOrdIDDt = [对应的DispatchOrdID] ``` **预期结果**: | EntourageID | EntourageOAid | EntourageLead | |-------------|---------------|---------------| | 1 | 1001 | 1 | | 4 | 1002 | 0 | ### 边界测试 1. **无执行人员**: - 参数全部为空字符串 - 旧系统不写入DispatchOrd_Entourage表 2. **未配置OA_UserID**: - 跳过该人员,不同步到旧系统 - 记录警告日志 3. **多个相同角色**: - 只取第一个匹配的人员 - 其他人员被忽略 4. **角色无法识别**: - 默认作为司机处理 - 记录警告日志 ## 注意事项 ### 1. OA_UserID必须配置 所有参与急救转运任务的用户必须配置`oa_user_id`字段,否则无法同步到旧系统。 ### 2. 角色名称规范 角色名称必须包含"司机"、"医生"或"护士"关键词,否则可能被错误分类。 ### 3. 第一个人员优先级 第一个执行人员自动成为领队,创建任务时应注意人员顺序。 ### 4. 单角色单人员 每个角色(司机/医生/护士)只会同步第一个匹配的人员到旧系统。 ### 5. 异常处理 同步失败不影响任务创建,只会记录日志,后续可通过定时任务重新同步。 ## 相关文档 - [执行人员assignee_id字段填充功能说明](./执行人员assignee_id字段填充功能说明.md) - [急救转运任务人员选择功能说明](./急救转运任务人员选择功能说明.md) - [旧系统同步机制说明](../oldCode/README.md) ## 更新记录 - 2025-10-25:完成执行人员同步到调度单随行人员功能 - 实现syncTaskAssignees方法 - 实现getUserType角色判断方法 - 支持司机/医生/护士的自动识别和分配 - 第一个执行人员自动设置为领队 - 完整的日志记录和异常处理