编辑 | blame | 历史 | 原始文档

调度单执行人员同步功能说明

功能概述

在同步急救转运任务到旧系统调度单时,将任务的执行人员信息同步到旧系统的随行人员参数中,并根据人员角色(司机/医生/护士)自动分配到对应的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
  1. 每个角色只取第一个匹配的人员
  • 如果有多个司机,只取第一个司机的OA_UserID
  • 医生和护士同理
  1. 角色判断规则
  • 根据用户的角色名称(roleName)判断
  • 角色名称包含"司机"的为司机
  • 角色名称包含"医生"的为医生
  • 角色名称包含"护士"的为护士
  • 其他角色默认作为司机处理

技术实现

1. 数据流程

新系统任务执行人员
    ↓
获取执行人员ID列表(assigneeId)
    ↓
查询每个人员的用户信息和角色
    ↓
判断人员类型(司机/医生/护士)
    ↓
获取OA_UserID
    ↓
分配到对应的Entourage参数
    ↓
第一个人员自动设置为领队
    ↓
传递给旧系统调度单接口

2. 核心方法实现

syncTaskAssignees方法

/**
 * 同步任务执行人员信息到调度单随行人员参数
 */
private void syncTaskAssignees(SysTask task, Map<String, String> params) {
    // 1. 获取任务的执行人员ID列表
    List<Long> 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方法

/**
 * 判断用户类型(司机/医生/护士/其他)
 */
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方法

/**
 * 获取任务的执行人员ID列表
 */
private List<Long> getTaskAssigneeIds(Long taskId) {
    List<Long> 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方法中,添加执行人员同步逻辑:

private Map<String, String> buildDispatchOrderParams(SysTask task, SysTaskEmergency emergency) {
    Map<String, String> 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行)接收参数后的处理:

'写入随行人员
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司机"
  1. 医生角色
  • 角色名称必须包含"医生"关键词
  • 例如:"医生"、"急诊医生"、"随车医生"
  1. 护士角色
  • 角色名称必须包含"护士"关键词
  • 例如:"护士"、"急诊护士"、"随车护士"

OA_UserID配置

每个用户必须配置对应的OA_UserID(旧系统用户ID):

-- 在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. 创建急救转运任务
  • 选择执行人员:张三(司机)、李四(护士)
  • 保存任务
  1. 检查新系统数据
    sql SELECT assignee_id FROM sys_task WHERE task_id = ? -- 预期:assignee_id = 101(张三的ID)

  2. 查看同步日志
    bash tail -f logs/sys-info.log | grep "任务执行人员同步"

预期日志
任务执行人员同步成功,任务ID: 10001, 领队ID: 1, 司机: 1001, 医生: , 护士: 1002

  1. 检查旧系统数据
    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表
  1. 未配置OA_UserID
  • 跳过该人员,不同步到旧系统
  • 记录警告日志
  1. 多个相同角色
  • 只取第一个匹配的人员
  • 其他人员被忽略
  1. 角色无法识别
  • 默认作为司机处理
  • 记录警告日志

注意事项

1. OA_UserID必须配置

所有参与急救转运任务的用户必须配置oa_user_id字段,否则无法同步到旧系统。

2. 角色名称规范

角色名称必须包含"司机"、"医生"或"护士"关键词,否则可能被错误分类。

3. 第一个人员优先级

第一个执行人员自动成为领队,创建任务时应注意人员顺序。

4. 单角色单人员

每个角色(司机/医生/护士)只会同步第一个匹配的人员到旧系统。

5. 异常处理

同步失败不影响任务创建,只会记录日志,后续可通过定时任务重新同步。

相关文档

更新记录

  • 2025-10-25:完成执行人员同步到调度单随行人员功能
  • 实现syncTaskAssignees方法
  • 实现getUserType角色判断方法
  • 支持司机/医生/护士的自动识别和分配
  • 第一个执行人员自动设置为领队
  • 完整的日志记录和异常处理