wlzboy
2 天以前 8cb5d3440208a3be3e772e65f1bd0ec63031ba62
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
@@ -11,29 +11,34 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import com.ruoyi.common.utils.MapValueUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.event.TaskDispatchSyncEvent;
import com.ruoyi.system.event.TaskServiceOrderSyncEvent;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.task.ITaskAttachmentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.config.LegacySystemConfig;
import com.ruoyi.common.utils.MapValueUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.domain.vo.TaskCreateVO;
import com.ruoyi.system.mapper.SysTaskMapper;
import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
import com.ruoyi.system.mapper.SysTaskVehicleMapper;
import com.ruoyi.system.mapper.SysTaskAssigneeMapper;
import com.ruoyi.system.mapper.VehicleInfoMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.utils.TaskStatusConverter;
import org.springframework.util.CollectionUtils;
/**
 * 旧系统同步Service业务层处理
@@ -51,6 +56,9 @@
    
    @Autowired
    private SysTaskMapper sysTaskMapper;
    @Autowired
    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
    
    @Autowired
    private SysUserMapper sysUserMapper;
@@ -81,12 +89,37 @@
    @Autowired
    private ITaskAttachmentService taskAttachmentService;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private LegacyTransferSyncMapper legacyTransferSyncMapper;
    public Map<String,Object> getLegacyDispatchByDispatchId(Long dispatchId) {
        List<Map<String, Object>> result = legacyTransferSyncMapper.selectByDispatchId(dispatchId);
        if(!CollectionUtils.isEmpty(result)){
            return result.get(0);
        }else{
            return null;
        }
    }
    private Map<String,Object> getLegacyByServiceOrdId(Long serviceOrdId) {
        List<Map<String, Object>> result = legacyTransferSyncMapper.selectByServiceOrdId(serviceOrdId);
        if(!CollectionUtils.isEmpty(result)){
            return result.get(0);
        }else{
            return null;
        }
    }
    /**
     * 同步急救转运任务到旧系统
     */
    @Override
    @Transactional
    public Long syncEmergencyTaskToLegacy(Long taskId) {
        if (!legacyConfig.isEnabled()) {
            log.info("旧系统同步已禁用,跳过任务ID: {}", taskId);
@@ -116,7 +149,7 @@
            
            // 如果已经同步过,不再重复同步
            if (emergency.getLegacyServiceOrdId() != null && emergency.getLegacyServiceOrdId() > 0) {
                log.info("任务已同步过,任务ID: {}, ServiceOrdID: {}", taskId, emergency.getLegacyServiceOrdId());
//                log.info("任务已同步过,任务ID: {}, ServiceOrdID: {}", taskId, emergency.getLegacyServiceOrdId());
                return emergency.getLegacyServiceOrdId();
            }
            
@@ -139,13 +172,27 @@
                emergency.setSyncStatus(2); // 同步成功
                emergency.setSyncTime(new Date());
                emergency.setSyncErrorMsg(null);
                Map<String, Object> legacy = getLegacyByServiceOrdId(serviceOrdId);
                String serviceOrdNo = MapValueUtils.getStringValue(legacy, "ServiceOrdNo");
                if(serviceOrdNo!=null) {
                    emergency.setLegacyServiceOrdNo(serviceOrdNo);
                }
                String serviceOrdClass = MapValueUtils.getStringValue(legacy, "ServiceOrdClass");
                if(serviceOrdClass!=null) {
                    emergency.setLegacyServiceOrdClass(serviceOrdClass);
                }
                Date serviceCCTime = MapValueUtils.getDateValue(legacy, "ServiceOrd_CC_Time");
                if(serviceCCTime!=null) {
                    emergency.setLegacyServiceNsTime(serviceCCTime);
                }
                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
                
                // 更新任务主表同步标记
                task.setLegacySynced(1);
                sysTaskMapper.updateSysTask(task);
                log.info("任务同步成功,任务ID: {}, ServiceOrdID: {}", taskId, serviceOrdId);
                eventPublisher.publishEvent(new TaskServiceOrderSyncEvent(this, taskId, task.getTaskCode(), serviceOrdId));
//                log.info("任务同步成功,任务ID: {}, ServiceOrdID: {}", taskId, serviceOrdId);
                return serviceOrdId;
            } else {
                // 同步失败
@@ -177,7 +224,13 @@
            return null;
        }
    }
    //在这里监听派发的事件
    @EventListener
    public void handleTaskServiceOrderSyncEvent(TaskServiceOrderSyncEvent event) {
//        log.info("收到任务服务单同步事件,任务ID:{},任务编号:{},服务单ID:{}", event.getTaskId(), event.getTaskCode(), event.getServiceOrderId());
        syncDispatchOrderToLegacy(event.getTaskId());
    }
    /**
     * 批量同步未同步的急救转运任务
     * 使用分页查询,确保所有符合条件的任务都能被同步
@@ -203,7 +256,7 @@
                    break; // 没有更多数据,退出循环
                }
                
                log.info("开始同步第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size());
//                log.info("开始同步第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size());
                
                int pageSuccessCount = 0;
                for (SysTaskEmergency emergency : pendingTasks) {
@@ -223,19 +276,19 @@
                }
                
                totalSuccessCount += pageSuccessCount;
                log.info("第 {} 页同步完成,总数: {}, 成功: {}",
                    (offset / pageSize) + 1, pendingTasks.size(), pageSuccessCount);
//                log.info("第 {} 页同步完成,总数: {}, 成功: {}",
//                    (offset / pageSize) + 1, pendingTasks.size(), pageSuccessCount);
                
                // 如果本页数据少于每页大小,说明已经是最后一页
                if (pendingTasks.size() < pageSize) {
                    log.info("已到达最后一页,同步结束");
//                    log.info("已到达最后一页,同步结束");
                    break;
                }
                
                offset += pageSize; // 下一页
            }
            
            log.info("批量同步完成,总成功数: {}", totalSuccessCount);
//            log.info("批量同步完成,总成功数: {}", totalSuccessCount);
            return totalSuccessCount;
            
        } catch (Exception e) {
@@ -247,8 +300,7 @@
    /**
     * 重新同步失败的任务
     */
    @Override
    @Transactional
    @Override
    public boolean retrySyncTask(Long taskId) {
        try {
            // 重置同步状态
@@ -294,7 +346,6 @@
     * 同步调度单到旧系统(admin_save_24.asp)
     */
    @Override
    @Transactional
    public Long syncDispatchOrderToLegacy(Long taskId) {
        if (!legacyConfig.isEnabled()) {
            log.info("旧系统同步已禁用,跳过调度单同步,任务ID: {}", taskId);
@@ -324,7 +375,7 @@
            
            // 如果已经同步过,不再重复同步
            if (emergency.getLegacyDispatchOrdId() != null && emergency.getLegacyDispatchOrdId() > 0) {
                log.info("调度单已同步过,任务ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
//                log.info("调度单已同步过,任务ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
                return emergency.getLegacyDispatchOrdId();
            }
@@ -335,8 +386,70 @@
                return null;
            }
            // ====== 前置校验:确保任务数据完整 ======
            // 1. 检查是否已分配车辆
            List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
            if (taskVehicles == null || taskVehicles.isEmpty()) {
                log.warn("任务未分配车辆,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            // 2. 检查是否已分配执行人员
            List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
            if (taskAssignees == null || taskAssignees.isEmpty()) {
                log.warn("任务未分配执行人员,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            // 3. 检查预约时间是否有效(必须大于1970年)
            if (task.getPlannedStartTime() == null) {
                log.warn("任务未设置预约时间,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            // 检查预约时间是否大于1970-01-01(时间戳0对应1970-01-01 00:00:00)
            long timestamp1970 = 0L;
            if (task.getPlannedStartTime().getTime() <= timestamp1970) {
                log.warn("任务预约时间无效(小于等于1970年),跳过调度单同步,任务ID: {}, 预约时间: {}",
                    taskId, task.getPlannedStartTime());
                return null;
            }
            // 4. 检查转出医院信息
            if (StringUtils.isEmpty(emergency.getHospitalOutName())) {
                log.warn("任务未设置转出医院,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            if (StringUtils.isEmpty(emergency.getHospitalOutAddress())) {
                log.warn("任务未设置转出医院地址,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            // 5. 检查转入医院信息
            if (StringUtils.isEmpty(emergency.getHospitalInName())) {
                log.warn("任务未设置转入医院,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            if (StringUtils.isEmpty(emergency.getHospitalInAddress())) {
                log.warn("任务未设置转入医院地址,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            // 6. 检查患者基本信息
            if (StringUtils.isEmpty(emergency.getPatientName())) {
                log.warn("任务未设置患者姓名,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            if (StringUtils.isEmpty(emergency.getPatientPhone())) {
                log.warn("任务未设置患者电话,跳过调度单同步,任务ID: {}", taskId);
                return null;
            }
            log.info("任务数据校验通过,开始同步调度单,任务ID: {}", taskId);
            // 更新同步状态为同步中
            emergency.setDispatchSyncStatus(1);
@@ -348,6 +461,7 @@
            // 构建请求参数
            Map<String, String> params = buildDispatchOrderParams(task, emergency);
            
            // 发送HTTP请求
            String response = sendHttpPost(legacyConfig.getDispatchCreateUrl(), params);
            
@@ -360,15 +474,20 @@
                emergency.setDispatchSyncStatus(2); // 同步成功
                emergency.setDispatchSyncTime(new Date());
                emergency.setDispatchSyncErrorMsg(null);
                //更新调度单信息开到新系统
                Map<String,Object> dispatchInfo = this.getLegacyDispatchByDispatchId(dispatchOrdId);
                if (dispatchInfo != null) {
                    emergency.setLegacyDispatchNsTime(MapValueUtils.getDateValue(dispatchInfo, "DispatchOrd_NS_Time")); // 同步成功
                    emergency.setLegacyDispatchOrdClass(MapValueUtils.getStringValue(dispatchInfo, "DispatchOrdClass")); // 同步成功
                    emergency.setLegacyDispatchOrdNo(MapValueUtils.getStringValue(dispatchInfo, "DispatchOrdNo")); // 同步成功
                    emergency.setLegacyServiceNsTime(MapValueUtils.getDateValue(dispatchInfo, "ServiceOrd_CC_Time")); // 同步成功
                    emergency.setLegacyServiceOrdClass(MapValueUtils.getStringValue(dispatchInfo, "ServiceOrdClass")); // 同步成功
                }
                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
                List<SysTaskAttachment> taskAttachments= sysTaskService.getAttachmentsByTaskId(taskId);
                if (taskAttachments != null && !taskAttachments.isEmpty()) {
                    //同步附件
                   this.syncAttachmentToLegacy(taskAttachments,serviceOrdId,dispatchOrdId,oaUserID);
                }
                eventPublisher.publishEvent(new TaskDispatchSyncEvent(this, taskId, task.getTaskCode(),serviceOrdId, dispatchOrdId, oaUserID));
                log.info("调度单同步成功,任务ID: {}, DispatchOrdID: {}", taskId, dispatchOrdId);
//                log.info("调度单同步成功,任务ID: {}, DispatchOrdID: {}", taskId, dispatchOrdId);
                return dispatchOrdId;
            } else {
                // 同步失败
@@ -400,7 +519,19 @@
            return null;
        }
    }
    @EventListener
    public void handleTaskDispatchSyncEvent(TaskDispatchSyncEvent event) {
        Long taskId = event.getTaskId();
        Long dispatchOrdId = event.getDispatchOrderId();
        Long serviceOrdId = event.getServiceOrderId();
        Integer oaUserID = event.getOaUserId();
        List<SysTaskAttachment> taskAttachments= sysTaskService.getAttachmentsByTaskId(taskId);
        if (taskAttachments != null && !taskAttachments.isEmpty()) {
            //同步附件
            this.syncAttachmentToLegacy(taskAttachments,serviceOrdId,dispatchOrdId,oaUserID);
        }
    }
    /**
     * 批量同步未同步的调度单
     * 使用分页查询,确保所有符合条件的任务都能被同步
@@ -420,17 +551,17 @@
            while (true) {
                // 分页查询已同步服务单但未同步调度单的任务
                List<SysTaskEmergency> pendingTasks = sysTaskEmergencyService.selectPendingDispatchSyncTasks(offset, pageSize);
                log.info("查询到未同步调度单的任务数量: {}", pendingTasks.size());
//                log.info("查询到未同步调度单的任务数量: {}", pendingTasks.size());
                if (pendingTasks == null || pendingTasks.isEmpty()) {
                    log.info("没有更多需要同步调度单的任务,offset: {}", offset);
                    break; // 没有更多数据,退出循环
                }
                
                log.info("开始同步调度单第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size());
//                log.info("开始同步调度单第 {} 页,任务数量: {}", (offset / pageSize) + 1, pendingTasks.size());
                
                int pageSuccessCount = 0;
                for (SysTaskEmergency emergency : pendingTasks) {
                    log.info("开始同步调度单,任务ID: {}", emergency.getTaskId());
//                    log.info("开始同步调度单,任务ID: {}", emergency.getTaskId());
                    Long dispatchOrdId = syncDispatchOrderToLegacy(emergency.getTaskId());
                    if (dispatchOrdId != null && dispatchOrdId > 0) {
@@ -448,19 +579,19 @@
                }
                
                totalSuccessCount += pageSuccessCount;
                log.info("调度单第 {} 页同步完成,总数: {}, 成功: {}",
                    (offset / pageSize) + 1, pendingTasks.size(), pageSuccessCount);
//                log.info("调度单第 {} 页同步完成,总数: {}, 成功: {}",
//                    (offset / pageSize) + 1, pendingTasks.size(), pageSuccessCount);
                
                // 如果本页数据少于每页大小,说明已经是最后一页
                if (pendingTasks.size() < pageSize) {
                    log.info("已到达最后一页,调度单同步结束");
//                    log.info("已到达最后一页,调度单同步结束");
                    break;
                }
                
                offset += pageSize; // 下一页
            }
            
            log.info("批量同步调度单完成,总成功数: {}", totalSuccessCount);
//            log.info("批量同步调度单完成,总成功数: {}", totalSuccessCount);
            return totalSuccessCount;
            
        } catch (Exception e) {
@@ -486,7 +617,7 @@
                SysDept dept = sysDeptMapper.selectDeptById(task.getDeptId());
                if (dept != null && StringUtils.isNotEmpty(dept.getDispatchOrderClass())) {
                    dispatchOrdClass = dept.getDispatchOrderClass();
                    log.info("获取任务所属部门的调度单编码成功,部门ID: {}, 调度单编码: {}", task.getDeptId(), dispatchOrdClass);
//                    log.info("获取任务所属部门的调度单编码成功,部门ID: {}, 调度单编码: {}", task.getDeptId(), dispatchOrdClass);
                }
            } catch (Exception e) {
                log.error("查询任务所属部门信息异常,部门ID: {}", task.getDeptId(), e);
@@ -516,7 +647,8 @@
        params.put("DispatchOrdCoPhone", StringUtils.nvl(emergency.getPatientPhone(), ""));
        params.put("ServiceOrdCoName", StringUtils.nvl(emergency.getPatientContact(), ""));
        params.put("ServiceOrdCoPhone", StringUtils.nvl(emergency.getPatientPhone(), ""));
        params.put("ServiceOrdPtName", StringUtils.nvl(emergency.getPatientName(), ""));
        params.put("ServiceOrdTraStreet",StringUtils.nvl(task.getDepartureAddress(), StringUtils.nvl(emergency.getHospitalOutAddress(), "")));
        // 地址信息
        params.put("DispatchOrdTraStreet", StringUtils.nvl(task.getDepartureAddress(), StringUtils.nvl(emergency.getHospitalOutAddress(), "")));
        params.put("DispatchOrdTraEnd", StringUtils.nvl(task.getDestinationAddress(), StringUtils.nvl(emergency.getHospitalInAddress(), "")));
@@ -525,8 +657,20 @@
        // 操作命令
        params.put("DispatchOrd_Check", "0"); // 3=直接强制完成
        
        // 绩效和费用
        params.put("DispatchOrdPerfomance", emergency.getTransferPrice() != null ? emergency.getTransferPrice().toString() : "0");
        // 绩效和费用:确保数值字段不为null
        String transferPrice = "0";
        if (emergency.getTransferPrice() != null) {
            try {
                transferPrice = emergency.getTransferPrice().toString();
                if (transferPrice.contains(".")) {
                    transferPrice = new java.math.BigDecimal(transferPrice).stripTrailingZeros().toPlainString();
                }
            } catch (Exception e) {
                log.warn("转换转运价格失败,任务ID: {}, 使用默认值0", task.getTaskId(), e);
                transferPrice = "0";
            }
        }
        params.put("DispatchOrdPerfomance", transferPrice);
        params.put("StretcherMoney", "0"); // 抬担架费
        params.put("AddMoneyType", ""); // 附加项目
        params.put("AddMoney", "0"); // 附加项目费用
@@ -559,7 +703,8 @@
        params.put("ServiceOrdPtDoctorPhone", ""); // 患者医生电话
        params.put("TransferModeID", ""); // 转运方式
        params.put("ServiceOrdVIP", "0"); // VIP客户
        params.put("ServiceOrdTraTxnPrice", emergency.getTransferPrice() != null ? emergency.getTransferPrice().toString() : "0"); // 成交价
        // 价格字段复用,确保一致性
        params.put("ServiceOrdTraTxnPrice", transferPrice); // 成交价
        params.put("ServiceOrdTraPrePayment", "0"); // 需预付款
        params.put("SettlementPrice", "0"); // 结算价
        params.put("ServiceOrdTraPriceReason", ""); // 差价原因
@@ -576,7 +721,21 @@
        params.put("ServiceOrdEstimatedOrderDate", ""); // 预计派单时间
        params.put("ServiceOrdEstimatedOrderDateOld", ""); // 原预计派单时间
        params.put("ServiceOrdViaDistance", "0"); // 中途距离
        params.put("ServiceOrdTraDistance", emergency.getTransferDistance() != null ? emergency.getTransferDistance().toString() : "0"); // 距离
        // 距离字段:确保不为空,避免旧系统接口报错
        String transferDistance = "0";
        if (emergency.getTransferDistance() != null) {
            try {
                transferDistance = emergency.getTransferDistance().toString();
                // 去除可能的小数点后多余的0
                if (transferDistance.contains(".")) {
                    transferDistance = new java.math.BigDecimal(transferDistance).stripTrailingZeros().toPlainString();
                }
            } catch (Exception e) {
                log.warn("转换转运距离失败,任务ID: {}, 使用默认值0", task.getTaskId(), e);
                transferDistance = "0";
            }
        }
        params.put("ServiceOrdTraDistance", transferDistance);
        params.put("OrderLevel", "0"); // 查看等级
        params.put("ServiceOrdDepartureType", "1"); // 预约类型
        params.put("ConditionLevel", "0"); // 病重级别
@@ -614,7 +773,9 @@
     */
    private void syncTaskAssignees(SysTask task, Map<String, String> params) {
        try {
            // 获取任务的执行人员信息列表(包含角色类型)
            // 获取任务的执行人员信息列表(包含角色类型) //TODO 如果有两个司机就要 设置 Entourage_1和Entourage_2
            //两个护士就要设置 Entourage_4和Entourage_6
            //两个医生要设置 Entourage_3和Entourage_5
            List<TaskCreateVO.AssigneeInfo> assignees = getTaskAssignees(task.getTaskId());
            
            if (assignees == null || assignees.isEmpty()) {
@@ -622,8 +783,12 @@
                // 设置默认空值
                params.put("EntourageLeadID", "");
                params.put("Entourage_1", ""); // 司机
                params.put("Entourage_2", ""); //司机
                params.put("Entourage_3", ""); // 医生
                params.put("Entourage_5", ""); //医生
                params.put("Entourage_4", ""); // 护士
                params.put("Entourage_6", ""); // 护士
                return;
            }
            
@@ -655,6 +820,11 @@
                if ("driver".equals(userType)) {
                    if (driverOaId.isEmpty()) {
                        driverOaId = oaUserId;
                        if(params.get("Entourage_1")==null) {
                            params.put("Entourage_1", oaUserId);
                        }else{
                            params.put("Entourage_2", oaUserId);
                        }
                        // 如果是第一个执行人员,设置为领队
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "1"; // 司机对应Entourage_1
@@ -663,6 +833,11 @@
                } else if ("doctor".equals(userType)) {
                    if (doctorOaId.isEmpty()) {
                        doctorOaId = oaUserId;
                        if(params.get("Entourage_3")==null) {
                            params.put("Entourage_3", oaUserId);
                        }else{
                            params.put("Entourage_5", oaUserId);
                        }
                        // 如果是第一个执行人员,设置为领队
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "3"; // 医生对应Entourage_3
@@ -671,6 +846,11 @@
                } else if ("nurse".equals(userType)) {
                    if (nurseOaId.isEmpty()) {
                        nurseOaId = oaUserId;
                        if(params.get("Entourage_4")==null) {
                            params.put("Entourage_4", oaUserId);
                        }else{
                            params.put("Entourage_6", oaUserId);
                        }
                        // 如果是第一个执行人员,设置为领队
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "4"; // 护士对应Entourage_4
@@ -681,12 +861,12 @@
            
            // 设置参数
            params.put("EntourageLeadID", leadEntourageId);
            params.put("Entourage_1", driverOaId);  // 司机
            params.put("Entourage_3", doctorOaId);  // 医生
            params.put("Entourage_4", nurseOaId);   // 护士
//            params.put("Entourage_1", driverOaId);  // 司机
//            params.put("Entourage_3", doctorOaId);  // 医生
//            params.put("Entourage_4", nurseOaId);   // 护士
            
            log.info("任务执行人员同步成功,任务ID: {}, 领队ID: {}, 司机: {}, 医生: {}, 护士: {}",
                task.getTaskId(), leadEntourageId, driverOaId, doctorOaId, nurseOaId);
//            log.info("任务执行人员同步成功,任务ID: {}, 领队ID: {}, 司机: {}, 医生: {}, 护士: {}",
//                task.getTaskId(), leadEntourageId, driverOaId, doctorOaId, nurseOaId);
            
        } catch (Exception e) {
            log.error("同步任务执行人员异常,任务ID: {}", task.getTaskId(), e);
@@ -726,7 +906,7 @@
            }
            
            // 如果数据库中没有执行人员信息,尝试从任务的主要执行人获取
            log.warn("数据库中未找到执行人员信息,尝试从任务主要执行人获取,任务ID: {}", taskId);
//            log.warn("数据库中未找到执行人员信息,尝试从任务主要执行人获取,任务ID: {}", taskId);
            SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
            if (task != null && task.getAssigneeId() != null) {
                SysUser user = sysUserMapper.selectUserById(task.getAssigneeId());
@@ -853,8 +1033,8 @@
                if (dept != null && StringUtils.isNotEmpty(dept.getServiceOrderClass())) {
                    // 使用部门的服务单编码作为ServiceOrdClass
                    serviceOrdClass = dept.getServiceOrderClass();
                    log.info("获取任务所属部门的服务单编码成功,部门ID: {}, 部门名称: {}, 服务单编码: {}",
                        task.getDeptId(), dept.getDeptName(), serviceOrdClass);
//                    log.info("获取任务所属部门的服务单编码成功,部门ID: {}, 部门名称: {}, 服务单编码: {}",
//                        task.getDeptId(), dept.getDeptName(), serviceOrdClass);
                } else {
                    log.warn("任务所属部门未配置服务单编码,部门ID: {}、部门名称: {},使用默认值", 
                        task.getDeptId(), dept != null ? dept.getDeptName() : "null");
@@ -870,7 +1050,7 @@
        String serviceOrdAreaType = "1"; // 默认值
        if (StringUtils.isNotEmpty(emergency.getDocumentTypeId())) {
            serviceOrdAreaType = emergency.getDocumentTypeId();
            log.info("获取单据类型ID成功,任务ID: {}, 单据类型ID: {}", task.getTaskId(), serviceOrdAreaType);
//            log.info("获取单据类型ID成功,任务ID: {}, 单据类型ID: {}", task.getTaskId(), serviceOrdAreaType);
        } else {
            log.warn("任务未配置单据类型ID,任务ID: {},使用默认值", task.getTaskId());
        }
@@ -883,7 +1063,7 @@
        String serviceOrdType = "1"; // 默认值
        if (StringUtils.isNotEmpty(emergency.getTaskTypeId())) {
            serviceOrdType = emergency.getTaskTypeId();
            log.info("获取任务类型ID成功,任务ID: {}, 任务类型ID: {}", taskId, serviceOrdType);
//            log.info("获取任务类型ID成功,任务ID: {}, 任务类型ID: {}", taskId, serviceOrdType);
        } else {
            log.warn("任务未配置任务类型ID,任务ID: {},使用默认值", taskId);
        }
@@ -932,7 +1112,7 @@
        // 地址信息
        params.put("province", ""); // 出发地省份
        params.put("city", ""); // 出发地城市
        params.put("ServiceOrdTraStreet", StringUtils.nvl(task.getDepartureAddress(), StringUtils.nvl(emergency.getHospitalOutAddress(), "")));
        params.put("ServiceOrdTraStreet",task.getDepartureAddress()); //派车地址
        params.put("ServiceOrdTraStreetCoo", ""); // 出发地坐标
        params.put("ServiceOrdTraEnd", StringUtils.nvl(task.getDestinationAddress(), StringUtils.nvl(emergency.getHospitalInAddress(), "")));
        params.put("ServiceOrdTraEndCoo", ""); // 目的地坐标
@@ -977,11 +1157,20 @@
    }
    
    /**
     * 发送HTTP POST请求
     * 发送HTTP/HTTPS POST请求
     * 支持HTTPS自签名证书
     */
    private String sendHttpPost(String urlString, Map<String, String> params) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        // 如果是HTTPS请求,配置SSL信任所有证书
        if (conn instanceof HttpsURLConnection) {
            HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
            httpsConn.setSSLSocketFactory(createTrustAllSSLContext().getSocketFactory());
            httpsConn.setHostnameVerifier((hostname, session) -> true); // 信任所有主机名
//            log.debug("配置HTTPS连接,信任所有SSL证书,URL: {}", urlString);
        }
        
        try {
            // 设置连接属性
@@ -1027,13 +1216,46 @@
                }
            } else {
                log.error("请求失败,请求URL {},参数 {}",urlString,postData);
                throw new Exception("HTTP请求失败,响应码: " + responseCode);
                throw new Exception("HTTP/HTTPS请求失败,响应码: " + responseCode);
            }
            
        } finally {
            conn.disconnect();
        }
    }
    /**
     * 创建信任所有SSL证书的SSLContext
     * 用于支持自签名证书的HTTPS请求
     *
     * 注意:此方法会信任所有SSL证书,包括自签名证书
     * 仅用于与旧系统的内部通信,生产环境建议使用正规CA证书
     */
    private SSLContext createTrustAllSSLContext() throws Exception {
        // 创建信任所有证书的TrustManager
        TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    // 信任所有客户端证书
                }
                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    // 信任所有服务器证书
                }
            }
        };
        // 安装信任所有证书的TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        return sslContext;
    }
    
    /**
@@ -1062,4 +1284,295 @@
            return null;
        }
    }
    // 删除下面的重复方法,因为我们将使用MapValueUtils工具类中的方法
    /*
    private String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString() : null;
    }
    private BigDecimal getBigDecimalValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        try {
            return new BigDecimal(value.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }
    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Long) {
            return (Long) value;
        }
        try {
            return Long.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }
    private Integer getIntegerValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        try {
            return Integer.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }
    private Date getDateValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Date) {
            return (Date) value;
        }
        // 如果是字符串,尝试解析
        if (value instanceof String) {
            try {
                return DateUtils.parseDate(value.toString());
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }
    private boolean isValidDateFormat(String dateStr, String format) {
        if (StringUtils.isEmpty(dateStr)) {
            return false;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            sdf.setLenient(false);
            sdf.parse(dateStr);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    */
    /**
     * 重新同步车辆和人员变更的任务到旧系统
     * 当任务的车辆信息或人员信息发生变更时,需要调用旧系统接口重新同步
     * 使用 admin_save_25.asp 接口,而不是 admin_save_24.gds
     */
    @Override
    @Transactional
    public boolean resyncDispatchOrderToLegacy(Long taskId) {
        if (!legacyConfig.isEnabled()) {
            log.info("旧系统同步已禁用,跳过调度单重新同步,任务ID: {}", taskId);
            return false;
        }
        try {
            // 查询任务信息
            SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
            if (task == null) {
                log.error("任务不存在,任务ID: {}", taskId);
                return false;
            }
            // 只同步急救转运任务
            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                log.info("非急救转运任务,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 查询急救转运扩展信息
            SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
            if (emergency == null) {
                log.error("急救转运扩展信息不存在,任务ID: {}", taskId);
                return false;
            }
            // 必须已经同步过调度单
            if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) {
                log.warn("调度单未同步,无法重新同步,任务ID: {}", taskId);
                return false;
            }
            Long serviceOrdId = emergency.getLegacyServiceOrdId();
            if (serviceOrdId == null || serviceOrdId <= 0) {
                log.warn("服务单未同步,无法重新同步调度单,任务ID: {}", taskId);
                return false;
            }
            // ====== 前置校验:确保任务数据完整 ======
            // 1. 检查是否已分配车辆
            List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
            if (taskVehicles == null || taskVehicles.isEmpty()) {
                log.warn("任务未分配车辆,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 2. 检查是否已分配执行人员
            List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
            if (taskAssignees == null || taskAssignees.isEmpty()) {
                log.warn("任务未分配执行人员,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 3. 检查预约时间是否有效
            if (task.getPlannedStartTime() == null || task.getPlannedStartTime().getTime() <= 0L) {
                log.warn("任务预约时间无效,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 4. 检查转出医院信息
            if (StringUtils.isEmpty(emergency.getHospitalOutName()) || StringUtils.isEmpty(emergency.getHospitalOutAddress())) {
                log.warn("任务转出医院信息不完整,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 5. 检查转入医院信息
            if (StringUtils.isEmpty(emergency.getHospitalInName()) || StringUtils.isEmpty(emergency.getHospitalInAddress())) {
                log.warn("任务转入医院信息不完整,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            // 6. 检查患者基本信息
            if (StringUtils.isEmpty(emergency.getPatientName()) || StringUtils.isEmpty(emergency.getPatientPhone())) {
                log.warn("任务患者信息不完整,跳过调度单重新同步,任务ID: {}", taskId);
                return false;
            }
            log.info("任务数据校验通过,开始重新同步调度单,任务ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
            // 构建请求参数(使用相同的参数构建方法)
            Map<String, String> params = buildDispatchOrderParams(task, emergency);
            params.put("DispatchOrdID", emergency.getLegacyDispatchOrdId().toString());
            params.put("ServiceOrdID", emergency.getLegacyServiceOrdId().toString());
            params.put("DispatchOrdState", "3");
            log.info("重新同步调度单到旧系统请求参数: {}", params);
            // 发送HTTP请求到旧系统(使用admin_save_25.asp接口)
            String response = sendHttpPost(legacyConfig.getDispatchUpdateUrl(), params);
//            log.info("重新同步调度单到旧系统响应: ServiceOrdID:{},DispatchOrdId:{},Result: {}",emergency.getLegacyServiceOrdId(),emergency.getLegacyDispatchOrdId(), response);
            // 解析响应
//            Long dispatchOrdId = parseResponse(response);
            if (response != null && response.equals("OK")) {
                // 重新同步成功,清除重新同步标记
                emergency.setNeedResync(0);
                emergency.setDispatchSyncTime(new Date());
                emergency.setDispatchSyncErrorMsg(null);
                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
//                log.info("调度单重新同步成功,任务ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
                return true;
            } else {
                // 重新同步失败
                emergency.setDispatchSyncErrorMsg("重新同步失败:" + response);
                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
                log.error("调度单重新同步失败,任务ID: {}, 响应: {}", taskId, response);
                return false;
            }
        } catch (Exception e) {
            log.error("重新同步调度单到旧系统异常,任务ID: {}", taskId, e);
            // 更新同步状态为失败
            try {
                SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
                if (emergency != null) {
                    emergency.setDispatchSyncErrorMsg("重新同步异常: " + e.getMessage());
                    sysTaskEmergencyService.updateSysTaskEmergency(emergency);
                }
            } catch (Exception ex) {
                log.error("更新调度单同步状态失败", ex);
            }
            return false;
        }
    }
    /**
     * 批量重新同步需要更新的调度单
     */
    @Override
    public int batchResyncPendingDispatchOrders() {
        if (!legacyConfig.isEnabled()) {
            log.info("旧系统同步已禁用");
            return 0;
        }
        try {
            int totalSuccessCount = 0;
            int pageSize = 100; // 每页100条
            int offset = 0;
            while (true) {
                // 分页查询需要重新同步的任务
                List<SysTaskEmergency> needResyncTasks = sysTaskEmergencyMapper.selectNeedResyncTasks(offset, pageSize);
//                log.info("查询到需要重新同步的任务数量: {}", needResyncTasks.size());
                if (needResyncTasks == null || needResyncTasks.isEmpty()) {
                    log.info("没有更多需要重新同步的任务,offset: {}", offset);
                    break; // 没有更多数据,退出循环
                }
//                log.info("开始重新同步调度单第 {} 页,任务数量: {}", (offset / pageSize) + 1, needResyncTasks.size());
                int pageSuccessCount = 0;
                for (SysTaskEmergency emergency : needResyncTasks) {
//                    log.info("开始重新同步调度单,任务ID: {}", emergency.getTaskId());
                    boolean success = resyncDispatchOrderToLegacy(emergency.getTaskId());
                    if (success) {
                        pageSuccessCount++;
                    }
                    // 避免过于频繁的请求
                    try {
                        Thread.sleep(1000); // 每个请求间隔1秒
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        log.warn("重新同步调度单被中断");
                        return totalSuccessCount + pageSuccessCount;
                    }
                }
                totalSuccessCount += pageSuccessCount;
//                log.info("调度单重新同步第 {} 页完成,总数: {}, 成功: {}",
//                    (offset / pageSize) + 1, needResyncTasks.size(), pageSuccessCount);
                // 如果本页数据少于每页大小,说明已经是最后一页
                if (needResyncTasks.size() < pageSize) {
//                    log.info("已到达最后一页,调度单重新同步结束");
                    break;
                }
                offset += pageSize; // 下一页
            }
//            log.info("批量重新同步调度单完成,总成功数: {}", totalSuccessCount);
            return totalSuccessCount;
        } catch (Exception e) {
            log.error("批量重新同步调度单异常", e);
            return 0;
        }
    }
}