wlzboy
5 天以前 fe33646ee6e2d1e57f2b51812e94983a0e9efb04
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -7,9 +7,12 @@
import java.net.HttpURLConnection;
import java.net.URL;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.event.TaskDispatchSyncEvent;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.TaskCodeGenerator;
import com.ruoyi.common.config.ImageUrlConfig;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,11 +34,6 @@
import com.ruoyi.system.domain.SysTaskAssignee;
import com.ruoyi.system.domain.enums.TaskStatus;
import com.ruoyi.system.domain.VehicleInfo;
import com.ruoyi.system.service.ISysTaskService;
import com.ruoyi.system.service.ILegacySystemSyncService;
import com.ruoyi.system.service.ISysTaskEmergencyService;
import com.ruoyi.system.service.ITaskAttachmentSyncService;
import com.ruoyi.system.service.IMapService;
import com.ruoyi.system.event.TaskCreatedEvent;
import com.ruoyi.system.event.TaskAssignedEvent;
import com.ruoyi.system.event.TaskStatusChangedEvent;
@@ -59,9 +57,6 @@
    private SysTaskMapper sysTaskMapper;
    
    @Autowired
    private SysTaskVehicleMapper sysTaskVehicleMapper;
    @Autowired
    private SysTaskAttachmentMapper sysTaskAttachmentMapper;
    
    @Autowired
@@ -71,19 +66,13 @@
    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
    
    @Autowired
    private SysTaskWelfareMapper sysTaskWelfareMapper;
    @Autowired
    private SysTaskAssigneeMapper sysTaskAssigneeMapper;
    
    @Autowired
    private VehicleInfoMapper vehicleInfoMapper;
    @Autowired(required = false)
    private ILegacySystemSyncService legacySystemSyncService;
    
    @Autowired
    private ISysTaskEmergencyService sysTaskEmergencyService;
    private ISysEmergencyTaskService sysEmergencyTaskService;
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
@@ -91,14 +80,36 @@
    @Autowired
    private ImageUrlConfig imageUrlConfig;
    
    @Autowired(required = false)
    private ITaskAttachmentSyncService taskAttachmentSyncService;
    @Autowired
    private ISysTaskAttachmentService sysTaskAttachmentService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired(required = false)
    private IMapService mapService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private ISysTaskAssigneeService sysTaskAssigneeService;
    @Autowired
    private ISysWelfareTaskService sysWelfareTaskService;
    @Autowired
    private ISysTaskVehicleService sysTaskVehicleService;
    @Override
    public Boolean dispatchSyncEvent(Long taskId) {
        SysTask task= sysTaskMapper.selectSysTaskByTaskId(taskId);
        SysUser user= sysUserMapper.selectUserById(task.getCreatorId());
        Integer oaUser=user.getOaUserId();
        SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
        eventPublisher.publishEvent(new TaskDispatchSyncEvent(this, taskId, task.getTaskCode(),emergency.getLegacyServiceOrdId(), emergency.getLegacyDispatchOrdId(),oaUser));
        return true;
    }
    /**
     * 查询任务管理
@@ -117,7 +128,7 @@
            }
            // 加载福祉车扩展信息
            else if ("WELFARE".equals(task.getTaskType())) {
                SysTaskWelfare welfareInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
                SysTaskWelfare welfareInfo = sysWelfareTaskService.getWelfareInfoByTaskId(taskId);
                task.setWelfareInfo(welfareInfo);
            }
        }
@@ -132,7 +143,68 @@
     */
    @Override
    public List<SysTask> selectSysTaskList(TaskQueryVO queryVO) {
        return sysTaskMapper.selectSysTaskList(queryVO);
        List<SysTask> tasks= sysTaskMapper.selectSysTaskList(queryVO);
        tasks.forEach(task -> {
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId());
                task.setEmergencyInfo(emergencyInfo);
            }
        });
        return tasks;
    }
    /**
     * 根据任务编号、调度单编号或服务单编号查询任务列表
     *
     * @param queryVO 任务查询对象
     * @param taskCode 任务编号
     * @return 任务管理集合
     */
    @Override
    public List<SysTask> selectSysTaskListByMultiCode(TaskQueryVO queryVO, String taskCode) {
        // Create a new query object without the taskCode filter
        TaskQueryVO newQuery = new TaskQueryVO();
        // Copy all properties except taskCode
        try {
            org.springframework.beans.BeanUtils.copyProperties(queryVO, newQuery, "taskCode");
        } catch (Exception e) {
            // If copy fails, manually copy the important fields
            newQuery.setTaskType(queryVO.getTaskType());
            newQuery.setTaskStatus(queryVO.getTaskStatus());
            newQuery.setVehicleNo(queryVO.getVehicleNo());
            newQuery.setCreatorId(queryVO.getCreatorId());
            newQuery.setAssigneeId(queryVO.getAssigneeId());
            newQuery.setDeptId(queryVO.getDeptId());
            newQuery.setDeptIds(queryVO.getDeptIds());
            newQuery.setPlannedStartTimeBegin(queryVO.getPlannedStartTimeBegin());
            newQuery.setPlannedStartTimeEnd(queryVO.getPlannedStartTimeEnd());
            newQuery.setPlannedEndTimeBegin(queryVO.getPlannedEndTimeBegin());
            newQuery.setPlannedEndTimeEnd(queryVO.getPlannedEndTimeEnd());
            newQuery.setOverdue(queryVO.getOverdue());
        }
        // Get all tasks matching the other criteria
        List<SysTask> allTasks = sysTaskMapper.selectSysTaskList(newQuery);
        allTasks.stream().forEach(task -> {
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId());
                task.setEmergencyInfo(emergencyInfo);
            }
        });
        return allTasks.stream().filter(task -> {
            if (task.getTaskCode() != null && task.getTaskCode().contains(taskCode)) {
                return true;
            }
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType()) && task.getEmergencyInfo() != null) {
                String dispatchCode = task.getEmergencyInfo().getDispatchCode();
                String serviceCode = task.getEmergencyInfo().getServiceCode();
                return (dispatchCode != null && dispatchCode.contains(taskCode)) ||
                        (serviceCode != null && serviceCode.contains(taskCode));
            }
            return false;
        }).collect(Collectors.toList());
    }
    /**
@@ -145,6 +217,11 @@
    @Transactional
    public int insertSysTask(TaskCreateVO createVO) {
        String username = SecurityUtils.getUsername();
        Long userId = SecurityUtils.getUserId();
        if(userId==null || userId==0){
            log.error("insertSysTask 用户ID为空 userName:{}",username);
            return 0;
        }
        SysTask task = new SysTask();
        task.setTaskCode(generateTaskCode());
        task.setTaskType(createVO.getTaskType());
@@ -153,7 +230,7 @@
        task.setPlannedStartTime(createVO.getPlannedStartTime());
        task.setPlannedEndTime(createVO.getPlannedEndTime());
        task.setAssigneeId(createVO.getAssigneeId());
        task.setCreatorId(SecurityUtils.getUserId());
        task.setCreatorId(userId);
        // 优先使用前端传入的部门ID,如果没有则使用当前用户的部门ID
        task.setDeptId(createVO.getDeptId() != null ? createVO.getDeptId() : SecurityUtils.getDeptId());
        task.setCreateBy(username);
@@ -163,123 +240,33 @@
        task.setRemark(createVO.getRemark());
        task.setDelFlag("0");
        
        // 设置通用地址和坐标信息
        if (createVO.getDepartureAddress() != null) {
            task.setDepartureAddress(createVO.getDepartureAddress());
        }
        if (createVO.getDestinationAddress() != null) {
            task.setDestinationAddress(createVO.getDestinationAddress());
        }
        if (createVO.getDepartureLongitude() != null) {
            task.setDepartureLongitude(createVO.getDepartureLongitude());
        }
        if (createVO.getDepartureLatitude() != null) {
            task.setDepartureLatitude(createVO.getDepartureLatitude());
        }
        if (createVO.getDestinationLongitude() != null) {
            task.setDestinationLongitude(createVO.getDestinationLongitude());
        }
        if (createVO.getDestinationLatitude() != null) {
            task.setDestinationLatitude(createVO.getDestinationLatitude());
        }
        if (createVO.getEstimatedDistance() != null) {
            task.setEstimatedDistance(createVO.getEstimatedDistance());
        }
        // 设置急救转运特定信息
        if (createVO.getTransferTime() != null) {
            task.setPlannedStartTime(createVO.getTransferTime());
        }
        if (createVO.getTransferDistance() != null) {
            task.setEstimatedDistance(createVO.getTransferDistance());
        }
        // 设置福祉车特定信息
        if (createVO.getServiceTime() != null) {
            task.setPlannedStartTime(createVO.getServiceTime());
        }
        if (createVO.getStartAddress() != null) {
            task.setDepartureAddress(createVO.getStartAddress());
        }
        if (createVO.getEndAddress() != null) {
            task.setDestinationAddress(createVO.getEndAddress());
        }
        // 设置福祉车公里数
        if (createVO.getDistance() != null) {
            task.setEstimatedDistance(createVO.getDistance());
        }
        // 自动获取出发地GPS坐标(如果缺失)
        if (task.getDepartureAddress() != null &&
            (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDepartureAddress(),
                    extractCityFromAddress(task.getDepartureAddress())
                );
                if (coords != null) {
                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取出发地GPS坐标失败", e);
            }
        }
        // 自动获取目的地GPS坐标(如果缺失)
        if (task.getDestinationAddress() != null &&
            (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDestinationAddress(),
                    extractCityFromAddress(task.getDestinationAddress())
                );
                if (coords != null) {
                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取目的地GPS坐标失败", e);
            }
        }
        // 设置地址和坐标信息
        setAddressAndCoordinatesFromVO(task, createVO);
        // 设置任务类型特定信息
        setTaskTypeSpecificInfo(task, createVO);
        // 自动填充缺失的GPS坐标
        autoFillMissingGpsCoordinates(task);
        
        int result = sysTaskMapper.insertSysTask(task);
        
        // 保存车辆关联信息
        if (result > 0 && createVO.getVehicleIds() != null && !createVO.getVehicleIds().isEmpty()) {
            for (Long vehicleId : createVO.getVehicleIds()) {
                SysTaskVehicle taskVehicle = new SysTaskVehicle();
                taskVehicle.setTaskId(task.getTaskId());
                taskVehicle.setVehicleId(vehicleId);
                taskVehicle.setAssignTime(DateUtils.getNowDate());
                taskVehicle.setAssignBy(username);
                taskVehicle.setStatus("ASSIGNED");
                taskVehicle.setCreateBy(username);
                taskVehicle.setCreateTime(DateUtils.getNowDate());
                taskVehicle.setUpdateBy(username);
                taskVehicle.setUpdateTime(DateUtils.getNowDate());
                sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
            }
            sysTaskVehicleService.saveTaskVehicles(task.getTaskId(), createVO.getVehicleIds(), username);
        }
        
        // 保存执行人员信息(包含角色类型)
        if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
            saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),username);
            sysTaskAssigneeService.saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),username);
        }
        
        // 保存急救转运扩展信息
        if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
            saveEmergencyInfo(task.getTaskId(),username, createVO,null,null,null);
            sysEmergencyTaskService.saveEmergencyInfo(task.getTaskId(), username, createVO, null, null, null);
        }
        
        // 保存福祉车扩展信息
        if (result > 0 && "WELFARE".equals(createVO.getTaskType())) {
            saveWelfareInfo(task.getTaskId(),SecurityUtils.getUsername(), createVO);
            sysWelfareTaskService.saveWelfareInfo(task.getTaskId(), SecurityUtils.getUsername(), createVO);
        }
        
        // 记录操作日志
@@ -300,25 +287,7 @@
            ));
        }
        
        // 发布任务分配事件
        if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
            List<Long> assigneeIds = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserId())
                .collect(Collectors.toList());
            List<String> assigneeNames = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserName())
                .collect(Collectors.toList());
            eventPublisher.publishEvent(new TaskAssignedEvent(
                this,
                task.getTaskId(),
                task.getTaskCode(),
                assigneeIds,
                assigneeNames,
                SecurityUtils.getUserId(),
                SecurityUtils.getUsername()
            ));
        }
        
        // 异步同步急救转运任务到旧系统
        if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType()) && legacySystemSyncService != null) {
@@ -376,38 +345,15 @@
        
        // 设置通用地址和坐标信息
        if (createVO.getDepartureAddress() != null) {
            task.setDepartureAddress(createVO.getDepartureAddress());
        }
        if (createVO.getDestinationAddress() != null) {
            task.setDestinationAddress(createVO.getDestinationAddress());
        }
        if (createVO.getDepartureLongitude() != null) {
            task.setDepartureLongitude(createVO.getDepartureLongitude());
        }
        if (createVO.getDepartureLatitude() != null) {
            task.setDepartureLatitude(createVO.getDepartureLatitude());
        }
        if (createVO.getDestinationLongitude() != null) {
            task.setDestinationLongitude(createVO.getDestinationLongitude());
        }
        if (createVO.getDestinationLatitude() != null) {
            task.setDestinationLatitude(createVO.getDestinationLatitude());
        }
        if (createVO.getEstimatedDistance() != null) {
            task.setEstimatedDistance(createVO.getEstimatedDistance());
        }
        // 设置急救转运特定信息
        // 设置地址和坐标信息
        setAddressAndCoordinatesFromVO(task, createVO);
        // 设置任务类型特定信息(注:insertTask使用plannedStartTime而非serviceTime)
        if (createVO.getTransferTime() != null) {
            task.setPlannedStartTime(createVO.getTransferTime());
        }
        if (createVO.getTransferDistance() != null) {
            task.setEstimatedDistance(createVO.getTransferDistance());
        }
        // 设置福祉车特定信息
        if (createVO.getPlannedStartTime() != null) {
            task.setPlannedStartTime(createVO.getPlannedStartTime());
        }
@@ -417,82 +363,33 @@
        if (createVO.getEndAddress() != null) {
            task.setDestinationAddress(createVO.getEndAddress());
        }
        // 设置福祉车公里数
        if (createVO.getDistance() != null) {
            task.setEstimatedDistance(createVO.getDistance());
        }
        // 自动获取出发地GPS坐标(如果缺失)
        if (task.getDepartureAddress() != null &&
            (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDepartureAddress(),
                    extractCityFromAddress(task.getDepartureAddress())
                );
                if (coords != null) {
                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取出发地GPS坐标失败", e);
            }
        }
        // 自动获取目的地GPS坐标(如果缺失)
        if (task.getDestinationAddress() != null &&
            (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDestinationAddress(),
                    extractCityFromAddress(task.getDestinationAddress())
                );
                if (coords != null) {
                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取目的地GPS坐标失败", e);
            }
        }
        // 自动填充缺失的GPS坐标
        autoFillMissingGpsCoordinates(task);
        
        int result = sysTaskMapper.insertSysTask(task);
        
        // 保存车辆关联信息
        if (result > 0 && createVO.getVehicleIds() != null && !createVO.getVehicleIds().isEmpty()) {
            for (Long vehicleId : createVO.getVehicleIds()) {
                SysTaskVehicle taskVehicle = new SysTaskVehicle();
                taskVehicle.setTaskId(task.getTaskId());
                taskVehicle.setVehicleId(vehicleId);
                taskVehicle.setAssignTime(updateTime);
                taskVehicle.setAssignBy(userName);
                taskVehicle.setStatus("ASSIGNED");
                taskVehicle.setCreateBy(userName);
                taskVehicle.setCreateTime(createTime);
                taskVehicle.setUpdateBy(userName);
                taskVehicle.setUpdateTime(updateTime);
                sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
            }
            sysTaskVehicleService.saveTaskVehicles(task.getTaskId(), createVO.getVehicleIds(), userName,
                updateTime, createTime, updateTime);
        }
        
        // 保存执行人员信息(包含角色类型)
        if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
            saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),userName);
            sysTaskAssigneeService.saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),userName);
        }
        
        // 保存急救转运扩展信息
        if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
            saveEmergencyInfo(task.getTaskId(),userName, createVO, serviceOrderId, dispatchOrderId, serviceOrdNo);
            sysEmergencyTaskService.saveEmergencyInfo(task.getTaskId(), userName, createVO, serviceOrderId, dispatchOrderId, serviceOrdNo);
        }
        
        // 保存福祉车扩展信息
        if (result > 0 && "WELFARE".equals(createVO.getTaskType())) {
            saveWelfareInfo(task.getTaskId(),userName, createVO);
            sysWelfareTaskService.saveWelfareInfo(task.getTaskId(), userName, createVO);
        }
        
        // 记录操作日志
@@ -513,16 +410,22 @@
            ));
        }
        
        // 发布任务分配事件
        if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
            List<Long> assigneeIds = createVO.getAssignees().stream()
        return result;
    }
    private void sendTaskAssigneeEvent(TaskCreateVO createVO,SysTask task,Long userId,String userName){
        List<Long> assigneeIds = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserId())
                .collect(Collectors.toList());
            List<String> assigneeNames = createVO.getAssignees().stream()
        List<String> assigneeNames = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserName())
                .collect(Collectors.toList());
            eventPublisher.publishEvent(new TaskAssignedEvent(
        eventPublisher.publishEvent(new TaskAssignedEvent(
                this,
                task.getTaskId(),
                task.getTaskCode(),
@@ -530,12 +433,7 @@
                assigneeNames,
                userId,
                userName
            ));
        }
        return result;
        ));
    }
    /**
@@ -551,6 +449,7 @@
        if (oldTask == null) {
            throw new RuntimeException("任务不存在");
        }
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getUsername();
        
        SysTask task = new SysTask();
@@ -605,7 +504,7 @@
                    if (coords != null) {
                        task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                        task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                        log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
//                        log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
                    log.error("自动获取出发地GPS坐标失败", e);
@@ -626,7 +525,7 @@
                    if (coords != null) {
                        task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                        task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                        log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
//                        log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
                    log.error("自动获取目的地GPS坐标失败", e);
@@ -634,40 +533,16 @@
            }
        }
        // 用于跟踪是否需要重新同步(车辆、人员、地址、成交价变更)
        boolean needResync = true;
        boolean needResync = false;
        int result = sysTaskMapper.updateSysTask(task);
        
        
        // 更新车辆关联
        if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
            // 查询现有的车辆关联
            List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(updateVO.getTaskId());
            List<Long> existingVehicleIds = existingVehicles.stream()
                .map(SysTaskVehicle::getVehicleId)
                .collect(Collectors.toList());
            // 比较新旧车辆ID列表,判断是否有变化
            boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(updateVO.getVehicleIds()));
            // 只有车辆发生变化时才更新
            boolean vehiclesChanged = sysTaskVehicleService.updateTaskVehicles(
                updateVO.getTaskId(), updateVO.getVehicleIds(), userName);
            if (vehiclesChanged) {
                // 删除旧的车辆关联
                sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(updateVO.getTaskId());
                // 添加新的车辆关联
                Date now = DateUtils.getNowDate();
                String currentUser = userName;
                for (Long vehicleId : updateVO.getVehicleIds()) {
                    SysTaskVehicle taskVehicle = new SysTaskVehicle();
                    taskVehicle.setTaskId(updateVO.getTaskId());
                    taskVehicle.setVehicleId(vehicleId);
                    taskVehicle.setAssignTime(now);
                    taskVehicle.setAssignBy(currentUser);
                    taskVehicle.setCreateTime(now);
                    sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
                }
                // 标记需要重新同步(车辆变更)
                needResync = true;
            }
@@ -675,100 +550,46 @@
        
        // 更新执行人员(检测人员变更)
        if (result > 0 && updateVO.getAssignees() != null) {
            // 查询现有的执行人员
            List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(updateVO.getTaskId());
            List<Long> existingAssigneeIds = existingAssignees.stream()
                .map(SysTaskAssignee::getUserId)
                .collect(Collectors.toList());
            List<Long> newAssigneeIds = updateVO.getAssignees().stream()
                .map(TaskCreateVO.AssigneeInfo::getUserId)
                .collect(Collectors.toList());
            // 比较新旧执行人员ID列表,判断是否有变化
            boolean assigneesChanged = !new HashSet<>(existingAssigneeIds).equals(new HashSet<>(newAssigneeIds));
            // 只有执行人员发生变化时才更新
            boolean assigneesChanged = sysTaskAssigneeService.updateTaskAssignees(
                updateVO.getTaskId(), updateVO.getAssignees(), userName);
            if (assigneesChanged) {
                // 删除旧的执行人员关联
                sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(updateVO.getTaskId());
                // 添加新的执行人员关联
                if (!updateVO.getAssignees().isEmpty()) {
                    saveTaskAssignees(updateVO.getTaskId(), updateVO.getAssignees(), userName);
                }
                // 标记需要重新同步(人员变更)
                needResync = true;
            }
        }
        Long dispatchOrderId=0L;
        // 更新急救转运扩展信息(检测地址和成交价变更)
        if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType())) {
            // 获取旧的急救转运信息
            SysTaskEmergency oldEmergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(updateVO.getTaskId());
            // 检测转出医院地址变更
            boolean hospitalOutAddressChanged = false;
            if (updateVO.getHospitalOut() != null && updateVO.getHospitalOut().getAddress() != null
                && oldEmergency != null
                && !updateVO.getHospitalOut().getAddress().equals(oldEmergency.getHospitalOutAddress())) {
                hospitalOutAddressChanged = true;
            }
            // 检测转入医院地址变更
            boolean hospitalInAddressChanged = false;
            if (updateVO.getHospitalIn() != null && updateVO.getHospitalIn().getAddress() != null
                && oldEmergency != null
                && !updateVO.getHospitalIn().getAddress().equals(oldEmergency.getHospitalInAddress())) {
                hospitalInAddressChanged = true;
            }
            // 检测成交价变更
            boolean transferPriceChanged = false;
            if (updateVO.getPrice() != null
                && oldEmergency != null
                && oldEmergency.getTransferPrice() != null
                && updateVO.getPrice().compareTo(oldEmergency.getTransferPrice()) != 0) {
                transferPriceChanged = true;
            }
            ;
            // 更新急救转运信息
            if (updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null) {
                updateEmergencyInfoFromCreateVO(updateVO.getTaskId(), updateVO, userName);
            }
            // 如果地址或成交价发生变更,标记需要重新同步
            if (hospitalOutAddressChanged || hospitalInAddressChanged || transferPriceChanged) {
                needResync = true;
            }
            sysEmergencyTaskService.updateEmergencyInfoFromUpdateVO(oldEmergency, updateVO, userName);
          dispatchOrderId=  oldEmergency.getLegacyDispatchOrdId();
            sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
        }
        
        // 更新福祉车扩展信息
        if (result > 0 && "WELFARE".equals(oldTask.getTaskType())) {
            if (updateVO.getPassenger() != null || updateVO.getStartAddress() != null || updateVO.getEndAddress() != null) {
                updateWelfareInfoFromCreateVO(updateVO.getTaskId(), updateVO, userName);
                sysWelfareTaskService.updateWelfareInfo(updateVO.getTaskId(), updateVO, userName);
            }
        }
        
        // 如果是急救转运任务且有变更,标记需要重新同步
        if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && needResync && !updateFromLegacy) {
            try {
                sysTaskEmergencyService.markNeedResync(updateVO.getTaskId());
            } catch (Exception e) {
                // 标记失败不影响主流程
            }
            sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
        }
        
        // 记录操作日志
        if (result > 0) {
            recordTaskLog(updateVO.getTaskId(), "UPDATE", "更新任务",
                buildTaskDescription(oldTask), buildTaskDescription(task),
                SecurityUtils.getUserId(), userName);
                userId, userName);
        }
        if(result > 0 && oldTask.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees() != null && !updateVO.getAssignees().isEmpty() && dispatchOrderId>0L){
            this.sendTaskAssigneeEvent(updateVO,oldTask,userId,userName);
        }
        return result;
    }
@@ -789,15 +610,25 @@
    @Override
    public int updateTask(TaskUpdateVO updateVO, String serviceOrderId, String dispatchOrderId, String serviceOrdNo,
                         Long userId, String userName, Long deptId, Date createTime, Date updateTime) {
//        log.info("开始更新任务 ServiceOrdID: {} , dispatchOrdId:{}", serviceOrderId,dispatchOrderId);
        // 通过旧系统服务单ID查找任务
        SysTaskEmergency taskEmergency = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(Long.parseLong(serviceOrderId));
        Long taskId = taskEmergency.getTaskId();
        updateVO.setTaskId(taskId);
        SysTask task = new SysTask();
        task.setTaskId(taskId);
        if(updateVO.getTaskStatus()!=null){
            task.setTaskStatus(updateVO.getTaskStatus());
        }
        task.setTaskDescription(updateVO.getTaskDescription());
        task.setPlannedStartTime(updateVO.getPlannedStartTime());
        task.setPlannedEndTime(updateVO.getPlannedEndTime());
        if(updateVO.getActualStartTime() != null) {
            task.setActualStartTime(updateVO.getActualStartTime());
        }
        if(updateVO.getActualEndTime() != null) {
            task.setActualEndTime(updateVO.getActualEndTime());
        }
        task.setAssigneeId(updateVO.getAssigneeId());
        task.setUpdateBy(userName);
        task.setUpdateTime(DateUtils.getNowDate());
@@ -838,7 +669,7 @@
                if (coords != null) {
                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
//                    log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取出发地GPS坐标失败", e);
@@ -858,7 +689,7 @@
                if (coords != null) {
                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                    log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
//                    log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取目的地GPS坐标失败", e);
@@ -866,81 +697,52 @@
        }
        
        int result = sysTaskMapper.updateSysTask(task);
//        log.info("更新转运任务,ServiceOrdID:{},dispatchOrderId:{},result:{}",serviceOrderId,dispatchOrderId,result);
//        log.info("更新任务车辆 ServiceOrdID: {} , dispatchOrdId:{},VehicleIds:{}", serviceOrderId,dispatchOrderId,updateVO.getVehicleIds());
        // 更新车辆关联
        if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
            // 查询现有的车辆关联
            List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
            List<Long> existingVehicleIds = existingVehicles.stream()
                .map(SysTaskVehicle::getVehicleId)
                .collect(Collectors.toList());
            // 比较新旧车辆ID列表,判断是否有变化
            boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(updateVO.getVehicleIds()));
            // 只有车辆发生变化时才更新
            if (vehiclesChanged) {
                // 删除旧的车辆关联
                sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
                // 添加新的车辆关联
                Date now = DateUtils.getNowDate();
                for (Long vehicleId : updateVO.getVehicleIds()) {
                    SysTaskVehicle taskVehicle = new SysTaskVehicle();
                    taskVehicle.setTaskId(taskId);
                    taskVehicle.setVehicleId(vehicleId);
                    taskVehicle.setAssignTime(now);
                    taskVehicle.setAssignBy(userName);
                    taskVehicle.setCreateTime(now);
                    sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
                }
            }
//            log.info("更新车辆关联 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId);
            sysTaskVehicleService.updateTaskVehicles(taskId, updateVO.getVehicleIds(), userName);
        }
        Boolean hasAssignee = updateVO.getAssigneeId() != null && !updateVO.getAssignees().isEmpty() ;
//        log.info("更新转运任务,ServiceOrdID:{},dispatchOrderId:{},result:{}, hasAssignee:{}",serviceOrderId,dispatchOrderId,result,hasAssignee);
        // 更新执行人员(检测人员变更)
        if (result > 0 && updateVO.getAssignees() != null) {
            // 查询现有的执行人员
            List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
            List<Long> existingAssigneeIds = existingAssignees.stream()
                .map(SysTaskAssignee::getUserId)
                .collect(Collectors.toList());
            List<Long> newAssigneeIds = updateVO.getAssignees().stream()
                .map(TaskCreateVO.AssigneeInfo::getUserId)
                .collect(Collectors.toList());
            // 比较新旧执行人员ID列表,判断是否有变化
            boolean assigneesChanged = !new HashSet<>(existingAssigneeIds).equals(new HashSet<>(newAssigneeIds));
            // 只有执行人员发生变化时才更新
            if (assigneesChanged) {
                // 删除旧的执行人员关联
                sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(taskId);
                // 添加新的执行人员关联
                if (!updateVO.getAssignees().isEmpty()) {
                    saveTaskAssignees(taskId, updateVO.getAssignees(), userName);
                }
            }
        if (result > 0 && hasAssignee) {
//            log.info("更新执行人员 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId);
            sysTaskAssigneeService.updateTaskAssignees(taskId, updateVO.getAssignees(), userName);
        }
        Long dispatchOrderIdLong = 0L;
        // 更新急救转运扩展信息
        if (result > 0) {
            // 更新旧系统ID
            if (serviceOrderId != null) {
                taskEmergency.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
            }
            taskEmergency.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
            if (dispatchOrderId != null) {
                taskEmergency.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
                dispatchOrderIdLong = Long.parseLong(dispatchOrderId);
                taskEmergency.setLegacyDispatchOrdId(dispatchOrderIdLong);
                taskEmergency.setDispatchSyncStatus(2);
                taskEmergency.setDispatchSyncTime(new Date());
                taskEmergency.setDispatchSyncErrorMsg("旧系统同步过来");
            }
            if (serviceOrdNo != null) {
                taskEmergency.setLegacyServiceOrdNo(serviceOrdNo);
            }
            taskEmergency.setUpdateTime(DateUtils.getNowDate());
            Boolean hasEmergencyInfo = updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null;
            // 使用TaskCreateVO的字段来更新急救转运信息
            if (updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null) {
                updateEmergencyInfoFromCreateVO(taskId, updateVO, userName);
            if (hasEmergencyInfo) {
                sysEmergencyTaskService.updateEmergencyInfoFromCreateVO(taskEmergency, updateVO, userName);
            }
           SysTaskEmergency emergency= sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId);
            dispatchOrderIdLong = emergency.getLegacyDispatchOrdId();
        }
        if(updateVO.getTaskStatus()!=null && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty() && dispatchOrderIdLong>0L){
            this.sendTaskAssigneeEvent(updateVO,task,userId,userName);
        }
        
        return result;
@@ -1024,7 +826,6 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int changeTaskStatus(Long taskId, TaskStatus newStatus, String remark) {
        return changeTaskStatusWithLocation(taskId, newStatus, remark, null);
    }
@@ -1039,7 +840,6 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int changeTaskStatusWithLocation(Long taskId, TaskStatus newStatus, String remark, SysTaskLog locationLog) {
        SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (oldTask == null) {
@@ -1091,7 +891,10 @@
                    .map(SysTaskAssignee::getUserId)
                    .collect(Collectors.toList());
            }
            Long userId=SecurityUtils.getUserId();
            Double lng=locationLog==null?null: locationLog.getLongitude();
            Double lat=locationLog==null?null: locationLog.getLatitude();
            String address=locationLog==null?null: locationLog.getLocationAddress();
            eventPublisher.publishEvent(new TaskStatusChangedEvent(
                this,
                oldTask.getTaskId(),
@@ -1101,7 +904,11 @@
                oldTaskStatus.getInfo(),
                newStatus.getInfo(),
                assigneeIds,
                oldTask.getCreatorId()
                oldTask.getCreatorId(),
                userId,
                    lng, lat,
                    address
            ));
        }
        
@@ -1119,39 +926,7 @@
    @Override
    @Transactional
    public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
        try {
            // 上传文件,返回相对路径(如:/task/2025/01/15/xxx.jpg)
            String fileName = category+"_"+System.currentTimeMillis()+"_"+file.getOriginalFilename();
            fileName=saveLocalPath(fileName,file.getInputStream());
            SysTaskAttachment attachment = new SysTaskAttachment();
            attachment.setTaskId(taskId);
            attachment.setFileName(file.getOriginalFilename());
            // 保存相对路径,不包含 baseDir
            attachment.setFilePath(fileName);
            attachment.setFileSize(file.getSize());
            attachment.setFileType(getFileType(file.getOriginalFilename()));
            attachment.setAttachmentCategory(category);
            attachment.setUploadTime(DateUtils.getNowDate());
            attachment.setUploadBy(SecurityUtils.getUsername());
            Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
            // 记录操作日志
            if (result > 0) {
                String categoryDesc = getCategoryDesc(category);
                recordTaskLog(taskId, "UPDATE", "上传附件", null,
                             "上传文件:" + file.getOriginalFilename() + "(分类:" + categoryDesc + ")",
                             SecurityUtils.getUserId(), SecurityUtils.getUsername());
            }
            return attachment.getAttachmentId();
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败:" + e.getMessage());
        }
        return sysTaskAttachmentService.uploadAttachment(taskId, file, category);
    }
    
    /**
@@ -1166,132 +941,9 @@
    @Override
    @Transactional
    public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
        try {
            // 从微信服务器下载文件
            String wechatUrl = String.format(
                "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
                accessToken, mediaId
            );
            byte[] fileBytes = downloadFromUrl(wechatUrl);
            if (fileBytes == null || fileBytes.length == 0) {
                throw new RuntimeException("从微信下载文件失败");
            }
            // 生成文件名(使用mediaId作为文件名的一部分)
            String fileName = "wx_" + mediaId.substring(0, Math.min(20, mediaId.length())) + "_" + System.currentTimeMillis() + ".jpg";
            // 保存到本地
            String relativeFilePath = saveLocalPath(fileName, fileBytes);
            // 保存附件记录
            SysTaskAttachment attachment = new SysTaskAttachment();
            attachment.setTaskId(taskId);
            attachment.setFileName(fileName);
            // 保存相对路径
            attachment.setFilePath(relativeFilePath);
            attachment.setFileSize((long) fileBytes.length);
            attachment.setFileType("jpg");
            attachment.setAttachmentCategory(category);
            attachment.setUploadTime(DateUtils.getNowDate());
            attachment.setUploadBy(SecurityUtils.getUsername());
            Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
            // 记录操作日志
            if (result > 0) {
                String categoryDesc = getCategoryDesc(category);
                recordTaskLog(taskId, "UPDATE", "上传附件", null,
                             "通过微信上传文件:" + fileName + "(分类:" + categoryDesc + ")",
                             SecurityUtils.getUserId(), SecurityUtils.getUsername());
            }
            return attachment.getAttachmentId();
        } catch (Exception e) {
            throw new RuntimeException("从微信上传文件失败:" + e.getMessage());
        }
        return sysTaskAttachmentService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
    }
    private static String saveLocalPath(String fileName, byte[] fileBytes) throws IOException {
        String baseDir = FileUploadUtils.getDefaultBaseDir();
        String datePath = DateUtils.datePath();
        String uploadDir = baseDir + "/task/" + datePath;
        // 创建目录
        File uploadPath = new File(uploadDir);
        if (!uploadPath.exists()) {
            uploadPath.mkdirs();
        }
        // 保存文件
        String filePath = uploadDir + "/" + fileName;
        File file = new File(filePath);
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(fileBytes);
        }
        // 生成相对路径(不包含baseDir)
        String relativeFilePath = "/task/" + datePath + "/" + fileName;
        return relativeFilePath;
    }
    private String saveLocalPath(String fileName,InputStream stream){
        String baseDir = FileUploadUtils.getDefaultBaseDir();
        String datePath = DateUtils.datePath();
        String uploadDir = baseDir + "/task/" + datePath;
        // 创建目录
        File uploadPath = new File(uploadDir);
        if (!uploadPath.exists()) {
            uploadPath.mkdirs();
        }
        // 保存文件
        String filePath = uploadDir + "/" + fileName;
       //将inputstream写入文件
        try (OutputStream os = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[1024]; // 缓冲区,减少 IO 次数
            int bytesRead;
            // 循环读取输入流中的数据,写入输出流
            while ((bytesRead = stream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush(); // 强制刷新缓冲区,确保数据写入文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 生成相对路径(不包含baseDir)
        String relativeFilePath = "/task/" + datePath + "/" + fileName;
        return relativeFilePath;
    }
    /**
     * 从 URL 下载文件
     */
    private byte[] downloadFromUrl(String fileUrl) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(10000);
        connection.setReadTimeout(30000);
        try (InputStream inputStream = connection.getInputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            return outputStream.toByteArray();
        } finally {
            connection.disconnect();
        }
    }
    /**
     * 删除任务附件
@@ -1302,28 +954,7 @@
    @Override
    @Transactional
    public int deleteAttachment(Long attachmentId) {
        SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
        if (attachment == null) {
            throw new RuntimeException("附件不存在");
        }
        // 删除物理文件
        try {
            FileUtils.deleteFile(attachment.getFilePath());
        } catch (Exception e) {
            // 忽略文件删除失败
        }
        int result = sysTaskAttachmentMapper.deleteSysTaskAttachmentByAttachmentId(attachmentId);
        // 记录操作日志
        if (result > 0) {
            recordTaskLog(attachment.getTaskId(), "UPDATE", "删除附件",
                         "删除文件:" + attachment.getFileName(), null,
                         SecurityUtils.getUserId(), SecurityUtils.getUsername());
        }
        return result;
        return sysTaskAttachmentService.deleteAttachment(attachmentId);
    }
    
    /**
@@ -1334,17 +965,12 @@
     */
    @Override
    public SysTaskAttachment getAttachmentById(Long attachmentId) {
        SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
        if (attachment != null) {
            // 拼接完整URL
            buildAttachmentUrl(attachment);
        }
        return attachment;
        return sysTaskAttachmentService.getAttachmentById(attachmentId);
    }
    @Override
    public List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId) {
        return sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
        return sysTaskAttachmentService.getAttachmentsByTaskId(taskId);
    }
    /**
@@ -1358,21 +984,7 @@
    @Override
    @Transactional
    public int assignVehicleToTask(Long taskId, Long vehicleId, String remark,Long userId,String userName) {
        // 检查是否已经分配
        int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
        if (exists > 0) {
            throw new RuntimeException("车辆已经分配给该任务");
        }
        SysTaskVehicle taskVehicle = new SysTaskVehicle();
        taskVehicle.setTaskId(taskId);
        taskVehicle.setVehicleId(vehicleId);
        taskVehicle.setAssignTime(DateUtils.getNowDate());
        taskVehicle.setAssignBy(userName);
        taskVehicle.setStatus("ASSIGNED");
        taskVehicle.setRemark(remark);
        int result = sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
        int result = sysTaskVehicleService.assignVehicleToTask(taskId, vehicleId, remark, userId, userName);
        
        // 记录操作日志
        if (result > 0) {
@@ -1394,7 +1006,7 @@
    @Override
    @Transactional
    public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
        int result = sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
        int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId);
        
        // 记录操作日志
        if (result > 0) {
@@ -1417,35 +1029,13 @@
    @Override
    @Transactional
    public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,Long userId,String userName) {
        List<SysTaskVehicle> taskVehicles = new ArrayList<>();
        Date now = DateUtils.getNowDate();
        String assignBy = userName;
        for (Long vehicleId : vehicleIds) {
            // 检查是否已经分配
            int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
            if (exists == 0) {
                SysTaskVehicle taskVehicle = new SysTaskVehicle();
                taskVehicle.setTaskId(taskId);
                taskVehicle.setVehicleId(vehicleId);
                taskVehicle.setAssignTime(now);
                taskVehicle.setAssignBy(assignBy);
                taskVehicle.setStatus("ASSIGNED");
                taskVehicle.setRemark(remark);
                taskVehicles.add(taskVehicle);
            }
        }
        int result = 0;
        if (!taskVehicles.isEmpty()) {
            result = sysTaskVehicleMapper.batchInsertSysTaskVehicle(taskVehicles);
        }
        int result = sysTaskVehicleService.assignMultipleVehiclesToTask(taskId, vehicleIds, remark, userId, userName);
        
        // 记录操作日志
        if (result > 0) {
            recordTaskLog(taskId, "ASSIGN", "批量分配车辆", null, 
                         "分配车辆数量:" + result + ",备注:" + remark, 
                         userId,userName);
                         userId, userName);
        }
        
        return result;
@@ -1459,7 +1049,7 @@
     */
    @Override
    public List<SysTaskVehicle> getTaskVehicles(Long taskId) {
        return sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
        return sysTaskVehicleService.getTaskVehicles(taskId);
    }
    /**
@@ -1471,34 +1061,7 @@
     */
    @Override
    public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
        List<SysTaskVehicle> availableVehicles = new ArrayList<>();
        try {
            // 查询所有状态为正常的车辆(不限制部门)
            VehicleInfo queryParam = new VehicleInfo();
            queryParam.setStatus("0"); // 0表示正常状态
            // 不设置deptId,查询所有部门的车辆
            queryParam.setDeptId(deptId);
            List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
            // 转换为SysTaskVehicle对象
            for (VehicleInfo vehicle : vehicles) {
                SysTaskVehicle taskVehicle = new SysTaskVehicle();
                taskVehicle.setVehicleId(vehicle.getVehicleId());
                taskVehicle.setVehicleNo(vehicle.getVehicleNo());
                taskVehicle.setVehicleType(vehicle.getVehicleType());
                taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
                taskVehicle.setVehicleModel(vehicle.getVehicleModel());
                taskVehicle.setDeptName(vehicle.getDeptName()); // 添加部门名称
                availableVehicles.add(taskVehicle);
            }
        } catch (Exception e) {
            // 如果查询失败,记录日志并返回空列表
            System.err.println("查询可用车辆失败: " + e.getMessage());
        }
        return availableVehicles;
        return sysTaskVehicleService.getAvailableVehicles(deptId, taskType);
    }
    /**
@@ -1529,7 +1092,13 @@
     */
    @Override
    public List<SysTask> selectMyTasks(Long userId) {
        return sysTaskMapper.selectMyTasks(userId);
        List<SysTask> list = sysTaskMapper.selectMyTasks(userId);
        list.stream().forEach(task -> {
            if(task.getTaskType().equals("EMERGENCY_TRANSFER")){
                task.setEmergencyInfo(sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId()));
            }
        });
        return list;
    }
    /**
@@ -1543,14 +1112,9 @@
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task != null) {
            // 查询关联车辆
            task.setAssignedVehicles(sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId));
            // 查询附件
            List<SysTaskAttachment> attachments = sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
            // 为每个附件拼接完整URL
            if (attachments != null && !attachments.isEmpty()) {
                attachments.forEach(this::buildAttachmentUrl);
            }
            task.setAttachments(attachments);
            task.setAssignedVehicles(sysTaskVehicleService.getTaskVehicles(taskId));
            // 查询附件(已自动拼接完整URL)
            task.setAttachments(sysTaskAttachmentService.getAttachmentsByTaskId(taskId));
            // 查询操作日志
            task.setOperationLogs(sysTaskLogMapper.selectSysTaskLogByTaskId(taskId));
            // 查询执行人员列表
@@ -1562,7 +1126,7 @@
            }
            // 加载福祉车扩展信息
            else if ("WELFARE".equals(task.getTaskType())) {
                SysTaskWelfare welfareInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
                SysTaskWelfare welfareInfo = sysWelfareTaskService.getWelfareInfoByTaskId(taskId);
                task.setWelfareInfo(welfareInfo);
            }
        }
@@ -1589,13 +1153,7 @@
     */
    @Override
    public boolean hasLegacyServiceOrdId(Long taskId) {
        // 只有急救转运任务才有旧系统ID
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
            return emergencyInfo != null && emergencyInfo.getLegacyServiceOrdId() != null;
        }
        return false;
        return sysEmergencyTaskService.hasLegacyServiceOrdId(taskId);
    }
    /**
@@ -1606,13 +1164,7 @@
     */
    @Override
    public boolean hasLegacyDispatchOrdId(Long taskId) {
        // 只有急救转运任务才有旧系统ID
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
            return emergencyInfo != null && emergencyInfo.getLegacyDispatchOrdId() != null;
        }
        return false;
        return sysEmergencyTaskService.hasLegacyDispatchOrdId(taskId);
    }
    /**
@@ -1623,11 +1175,7 @@
     */
    @Override
    public boolean existsByLegacyServiceOrdId(Long legacyServiceOrdId) {
        if (legacyServiceOrdId == null) {
            return false;
        }
        SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(legacyServiceOrdId);
        return emergencyInfo != null;
        return sysEmergencyTaskService.existsByLegacyServiceOrdId(legacyServiceOrdId);
    }
    /**
@@ -1638,11 +1186,7 @@
     */
    @Override
    public boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId) {
        if (legacyDispatchOrdId == null) {
            return false;
        }
        SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyDispatchOrdId(legacyDispatchOrdId);
        return emergencyInfo != null;
        return sysEmergencyTaskService.existsByLegacyDispatchOrdId(legacyDispatchOrdId);
    }
    @Autowired
@@ -1748,21 +1292,109 @@
        return sb.toString();
    }
    /**
     * 获取文件类型
     * 从TaskCreateVO设置地址和坐标信息到任务对象
     * 
     * @param fileName 文件名
     * @return 文件类型
     * @param task 任务对象
     * @param createVO 创建VO
     */
    private String getFileType(String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return "";
    private void setAddressAndCoordinatesFromVO(SysTask task, TaskCreateVO createVO) {
        // 设置通用地址和坐标信息
        if (createVO.getDepartureAddress() != null) {
            task.setDepartureAddress(createVO.getDepartureAddress());
        }
        int lastDotIndex = fileName.lastIndexOf(".");
        if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
            return fileName.substring(lastDotIndex + 1).toLowerCase();
        if (createVO.getDestinationAddress() != null) {
            task.setDestinationAddress(createVO.getDestinationAddress());
        }
        return "";
        if (createVO.getDepartureLongitude() != null) {
            task.setDepartureLongitude(createVO.getDepartureLongitude());
        }
        if (createVO.getDepartureLatitude() != null) {
            task.setDepartureLatitude(createVO.getDepartureLatitude());
        }
        if (createVO.getDestinationLongitude() != null) {
            task.setDestinationLongitude(createVO.getDestinationLongitude());
        }
        if (createVO.getDestinationLatitude() != null) {
            task.setDestinationLatitude(createVO.getDestinationLatitude());
        }
        if (createVO.getEstimatedDistance() != null) {
            task.setEstimatedDistance(createVO.getEstimatedDistance());
        }
    }
    /**
     * 设置任务类型特定信息(急救转运/福祉车)
     *
     * @param task 任务对象
     * @param createVO 创建VO
     */
    private void setTaskTypeSpecificInfo(SysTask task, TaskCreateVO createVO) {
        // 设置急救转运特定信息
        if (createVO.getTransferTime() != null) {
            task.setPlannedStartTime(createVO.getTransferTime());
        }
        if (createVO.getTransferDistance() != null) {
            task.setEstimatedDistance(createVO.getTransferDistance());
        }
        // 设置福祉车特定信息
        if (createVO.getServiceTime() != null) {
            task.setPlannedStartTime(createVO.getServiceTime());
        }
        if (createVO.getStartAddress() != null) {
            task.setDepartureAddress(createVO.getStartAddress());
        }
        if (createVO.getEndAddress() != null) {
            task.setDestinationAddress(createVO.getEndAddress());
        }
        if (createVO.getDistance() != null) {
            task.setEstimatedDistance(createVO.getDistance());
        }
    }
    /**
     * 自动填充缺失的GPS坐标
     *
     * @param task 任务对象
     */
    private void autoFillMissingGpsCoordinates(SysTask task) {
        // 自动获取出发地GPS坐标(如果缺失)
        if (task.getDepartureAddress() != null &&
            (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDepartureAddress(),
                    extractCityFromAddress(task.getDepartureAddress())
                );
                if (coords != null) {
                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                }
            } catch (Exception e) {
                log.error("自动获取出发地GPS坐标失败", e);
            }
        }
        // 自动获取目的地GPS坐标(如果缺失)
        if (task.getDestinationAddress() != null &&
            (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
            mapService != null) {
            try {
                Map<String, Double> coords = mapService.geocoding(
                    task.getDestinationAddress(),
                    extractCityFromAddress(task.getDestinationAddress())
                );
                if (coords != null) {
                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                }
            } catch (Exception e) {
                log.error("自动获取目的地GPS坐标失败", e);
            }
        }
    }
    /**
@@ -1796,471 +1428,130 @@
    }
    /**
     * 保存任务执行人员信息(包含角色类型)
     * 检查任务是否可以出发
     * 检查:
     * 1. 车辆是否有未完成的任务
     * 2. 执行人员是否有未完成的任务
     * 
     * @param taskId 任务ID
     * @param assignees 执行人员信息列表
     * @return AjaxResult 校验结果
     */
    private void saveTaskAssignees(Long taskId, java.util.List<TaskCreateVO.AssigneeInfo> assignees,String userName) {
        if (assignees == null || assignees.isEmpty()) {
            return;
    @Override
    public AjaxResult checkTaskCanDepart(Long taskId) {
        // 获取任务详情
        SysTask task = this.getTaskDetail(taskId);
        if (task == null) {
            return AjaxResult.error("任务不存在");
        }
        
        java.util.List<SysTaskAssignee> taskAssignees = new java.util.ArrayList<>();
        Date now = DateUtils.getNowDate();
        String currentUser = userName;
        List<Map<String, Object>> conflicts = new ArrayList<>();
        
        for (int i = 0; i < assignees.size(); i++) {
            TaskCreateVO.AssigneeInfo assigneeInfo = assignees.get(i);
            SysTaskAssignee taskAssignee = new SysTaskAssignee();
            taskAssignee.setTaskId(taskId);
            taskAssignee.setUserId(assigneeInfo.getUserId());
            taskAssignee.setUserName(assigneeInfo.getUserName());
            taskAssignee.setUserType(assigneeInfo.getUserType());
            // 第一个执行人员为主要执行人
            taskAssignee.setIsPrimary(i == 0 ? "1" : "0");
            taskAssignee.setSortOrder(i);
            taskAssignee.setCreateTime(now);
            taskAssignee.setCreateBy(currentUser);
            taskAssignee.setUpdateTime(now);
            taskAssignee.setUpdateBy(currentUser);
            taskAssignees.add(taskAssignee);
        }
        // 批量保存
        if (!taskAssignees.isEmpty()) {
            sysTaskAssigneeMapper.batchInsertSysTaskAssignee(taskAssignees);
        }
    }
    /**
     * 保存急救转运任务扩展信息
     *
     * @param taskId 任务ID
     * @param createVO 任务创建对象
     */
    private void saveEmergencyInfo(Long taskId,String createUserName, TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo) {
        SysTaskEmergency emergencyInfo = new SysTaskEmergency();
        emergencyInfo.setTaskId(taskId);
        // 设置患者信息
        if (createVO.getPatient() != null) {
            emergencyInfo.setPatientContact(createVO.getPatient().getContact());
            emergencyInfo.setPatientPhone(createVO.getPatient().getPhone());
            emergencyInfo.setPatientName(createVO.getPatient().getName());
            emergencyInfo.setPatientGender(createVO.getPatient().getGender());
            emergencyInfo.setPatientIdCard(createVO.getPatient().getIdCard());
            emergencyInfo.setPatientCondition(createVO.getPatient().getCondition());
        }
        // 设置转出医院信息
        if (createVO.getHospitalOut() != null) {
            emergencyInfo.setHospitalOutId(createVO.getHospitalOut().getId());
            emergencyInfo.setHospitalOutName(createVO.getHospitalOut().getName());
            emergencyInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
            emergencyInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
            emergencyInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
            emergencyInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
            // GPS坐标:优先使用前端传入的,否则后端自动获取
            if (createVO.getHospitalOut().getLongitude() != null && createVO.getHospitalOut().getLatitude() != null) {
                emergencyInfo.setHospitalOutLongitude(createVO.getHospitalOut().getLongitude());
                emergencyInfo.setHospitalOutLatitude(createVO.getHospitalOut().getLatitude());
            } else if (mapService != null && createVO.getHospitalOut().getAddress() != null) {
                // 后端自动获取GPS坐标
                try {
                    Map<String, Double> coords = mapService.geocoding(
                        createVO.getHospitalOut().getAddress(),
                        extractCityFromAddress(createVO.getHospitalOut().getAddress())
                    );
                    if (coords != null) {
                        emergencyInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
                        emergencyInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
                        log.info("转出医院GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
                    log.error("自动获取转出医院GPS坐标失败", e);
                }
            }
        }
        // 设置转入医院信息
        if (createVO.getHospitalIn() != null) {
            emergencyInfo.setHospitalInId(createVO.getHospitalIn().getId());
            emergencyInfo.setHospitalInName(createVO.getHospitalIn().getName());
            emergencyInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
            emergencyInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
            emergencyInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
            emergencyInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
            // GPS坐标:优先使用前端传入的,否则后端自动获取
            if (createVO.getHospitalIn().getLongitude() != null && createVO.getHospitalIn().getLatitude() != null) {
                emergencyInfo.setHospitalInLongitude(createVO.getHospitalIn().getLongitude());
                emergencyInfo.setHospitalInLatitude(createVO.getHospitalIn().getLatitude());
            } else if (mapService != null && createVO.getHospitalIn().getAddress() != null) {
                // 后端自动获取GPS坐标
                try {
                    Map<String, Double> coords = mapService.geocoding(
                        createVO.getHospitalIn().getAddress(),
                        extractCityFromAddress(createVO.getHospitalIn().getAddress())
                    );
                    if (coords != null) {
                        emergencyInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
                        emergencyInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
                        log.info("转入医院GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
                    log.error("自动获取转入医院GPS坐标失败", e);
                    }
                }
        }
        // 设置费用信息
        emergencyInfo.setTransferDistance(createVO.getTransferDistance());
        emergencyInfo.setTransferPrice(createVO.getPrice());
        // 设置单据类型ID
        emergencyInfo.setDocumentTypeId(createVO.getDocumentTypeId());
        // 设置任务类型ID
        emergencyInfo.setTaskTypeId(createVO.getTaskTypeId());
        // 设置病情ID列表(将List<Long>转换为逗号分隔的字符串)
        if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
            String diseaseIdsStr = createVO.getDiseaseIds().stream()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
            emergencyInfo.setDiseaseIds(diseaseIdsStr);
        }
        if(serviceOrderId!=null){
            emergencyInfo.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
            emergencyInfo.setSyncStatus(2);
            emergencyInfo.setSyncTime(new Date());
            emergencyInfo.setSyncErrorMsg("旧系统同步过来");
        }
        if(dispatchOrderId!=null){
            emergencyInfo.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
            emergencyInfo.setDispatchSyncStatus(2);
            emergencyInfo.setDispatchSyncTime(new Date());
            emergencyInfo.setDispatchSyncErrorMsg("旧系统同步过来");
        }
        if(serviceOrdNo!=null){
            emergencyInfo.setLegacyServiceOrdNo(serviceOrdNo);
        }
        // 系统字段
        emergencyInfo.setCreateTime(DateUtils.getNowDate());
        emergencyInfo.setUpdateTime(DateUtils.getNowDate());
        emergencyInfo.setCreateBy(createUserName);
        emergencyInfo.setUpdateBy(createUserName);
        sysTaskEmergencyMapper.insertSysTaskEmergency(emergencyInfo);
    }
    /**
     * 从 TaskCreateVO 更新急救转运任务扩展信息
     *
     * @param taskId 任务ID
     * @param createVO 任务创建/更新对象
     * @param userName 操作人名
     */
    private void updateEmergencyInfoFromCreateVO(Long taskId, TaskCreateVO createVO, String userName) {
        // 查询现有的扩展信息
        SysTaskEmergency existingInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
        if (existingInfo == null) {
            // 如果不存在,则创建新的
            existingInfo = new SysTaskEmergency();
            existingInfo.setTaskId(taskId);
            existingInfo.setCreateTime(DateUtils.getNowDate());
            existingInfo.setCreateBy(userName);
        }
        // 更新患者信息
        if (createVO.getPatient() != null) {
            if (createVO.getPatient().getContact() != null) {
                existingInfo.setPatientContact(createVO.getPatient().getContact());
            }
            if (createVO.getPatient().getPhone() != null) {
                existingInfo.setPatientPhone(createVO.getPatient().getPhone());
            }
            if (createVO.getPatient().getName() != null) {
                existingInfo.setPatientName(createVO.getPatient().getName());
            }
            if (createVO.getPatient().getGender() != null) {
                existingInfo.setPatientGender(createVO.getPatient().getGender());
            }
            if (createVO.getPatient().getIdCard() != null) {
                existingInfo.setPatientIdCard(createVO.getPatient().getIdCard());
            }
            if (createVO.getPatient().getCondition() != null) {
                existingInfo.setPatientCondition(createVO.getPatient().getCondition());
            }
        }
        // 更新转出医院信息
        if (createVO.getHospitalOut() != null) {
            if (createVO.getHospitalOut().getId() != null) {
                existingInfo.setHospitalOutId(createVO.getHospitalOut().getId());
            }
            if (createVO.getHospitalOut().getName() != null) {
                existingInfo.setHospitalOutName(createVO.getHospitalOut().getName());
            }
            if (createVO.getHospitalOut().getDepartment() != null) {
                existingInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
            }
            if (createVO.getHospitalOut().getDepartmentId() != null) {
                existingInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
            }
            if (createVO.getHospitalOut().getBedNumber() != null) {
                existingInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
            }
            if (createVO.getHospitalOut().getAddress() != null && !createVO.getHospitalOut().getAddress().equals(existingInfo.getHospitalOutAddress())) {
                existingInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
        // 1. 检查车辆是否有未完成的任务
        List<SysTaskVehicle> taskVehicles = task.getAssignedVehicles();
        if (taskVehicles != null && !taskVehicles.isEmpty()) {
            for (SysTaskVehicle taskVehicle : taskVehicles) {
                Long vehicleId = taskVehicle.getVehicleId();
                List<SysTask> vehicleActiveTasks = this.checkVehicleActiveTasks(vehicleId);
                
                // 如枟更新了地址但没有GPS坐标,后端自动获取
                if (createVO.getHospitalOut().getLongitude() == null && createVO.getHospitalOut().getLatitude() == null && mapService != null) {
                    try {
                        Map<String, Double> coords = mapService.geocoding(
                            createVO.getHospitalOut().getAddress(),
                            extractCityFromAddress(createVO.getHospitalOut().getAddress())
                        );
                        if (coords != null) {
                            existingInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
                            existingInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
                            log.info("转出医院GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                        }
                    } catch (Exception e) {
                        log.error("自动获取转出医院GPS坐标失败", e);
                    }
                }
            }
        }
        // 更新转入医院信息
        if (createVO.getHospitalIn() != null) {
            if (createVO.getHospitalIn().getId() != null) {
                existingInfo.setHospitalInId(createVO.getHospitalIn().getId());
            }
            if (createVO.getHospitalIn().getName() != null) {
                existingInfo.setHospitalInName(createVO.getHospitalIn().getName());
            }
            if (createVO.getHospitalIn().getDepartment() != null) {
                existingInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
            }
            if (createVO.getHospitalIn().getDepartmentId() != null) {
                existingInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
            }
            if (createVO.getHospitalIn().getBedNumber() != null) {
                existingInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
            }
            if (createVO.getHospitalIn().getAddress() != null && !createVO.getHospitalIn().getAddress().equals(existingInfo.getHospitalInAddress())) {
                existingInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
                // 过滤掉当前任务本身
                vehicleActiveTasks = vehicleActiveTasks.stream()
                    .filter(t -> !t.getTaskId().equals(taskId))
                    .collect(Collectors.toList());
                
                // 如果更新了地址但没有GPS坐标,后端自动获取
                if (createVO.getHospitalIn().getLongitude() == null && createVO.getHospitalIn().getLatitude() == null && mapService != null) {
                    try {
                        Map<String, Double> coords = mapService.geocoding(
                            createVO.getHospitalIn().getAddress(),
                            extractCityFromAddress(createVO.getHospitalIn().getAddress())
                        );
                        if (coords != null) {
                            existingInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
                            existingInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
                            log.info("转入医院GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                        }
                    } catch (Exception e) {
                        log.error("自动获取转入医院GPS坐标失败", e);
                if (!vehicleActiveTasks.isEmpty()) {
                    for (SysTask activeTask : vehicleActiveTasks) {
                        Map<String, Object> conflict = new HashMap<>();
                        conflict.put("type", "vehicle");
                        conflict.put("vehicleNo", taskVehicle.getVehicleNo());
                        conflict.put("taskId", activeTask.getTaskId());
                        conflict.put("taskCode", activeTask.getTaskCode());
                        conflict.put("taskStatus", activeTask.getTaskStatus());
                        conflict.put("message", String.format("车辆 %s 尚有未完成的任务 %s,请先完成",
                            taskVehicle.getVehicleNo(), activeTask.getTaskCode()));
                        conflicts.add(conflict);
                    }
                }
            }
        }
        
        // 更新费用信息
        if (createVO.getTransferDistance() != null) {
            existingInfo.setTransferDistance(createVO.getTransferDistance());
        }
        if (createVO.getPrice() != null) {
            existingInfo.setTransferPrice(createVO.getPrice());
        }
        // 更新单据类型ID
        if (createVO.getDocumentTypeId() != null) {
            existingInfo.setDocumentTypeId(createVO.getDocumentTypeId());
        }
        // 更新任务类型ID
        if (createVO.getTaskTypeId() != null) {
            existingInfo.setTaskTypeId(createVO.getTaskTypeId());
        }
        // 更新病情ID列表
        if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
            String diseaseIdsStr = createVO.getDiseaseIds().stream()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
            existingInfo.setDiseaseIds(diseaseIdsStr);
        }
        // 系统字段
        existingInfo.setUpdateTime(DateUtils.getNowDate());
        existingInfo.setUpdateBy(userName);
        // 执行更新
        sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo);
    }
    /**
     * 从 TaskCreateVO 更新福祉车任务扩展信息
     *
     * @param taskId 任务ID
     * @param createVO 任务创建/更新对象
     * @param userName 操作人名
     */
    private void updateWelfareInfoFromCreateVO(Long taskId, TaskCreateVO createVO, String userName) {
        // 查询现有的扩展信息
        SysTaskWelfare existingInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
        if (existingInfo == null) {
            // 如果不存在,则创建新的
            existingInfo = new SysTaskWelfare();
            existingInfo.setTaskId(taskId);
            existingInfo.setCreateTime(DateUtils.getNowDate());
            existingInfo.setCreateBy(userName);
        }
        // 更新乘客信息
        if (createVO.getPassenger() != null) {
            if (createVO.getPassenger().getContact() != null) {
                existingInfo.setPassengerContact(createVO.getPassenger().getContact());
            }
            if (createVO.getPassenger().getPhone() != null) {
                existingInfo.setPassengerPhone(createVO.getPassenger().getPhone());
        // 2. 检查执行人员是否有未完成的任务
        List<SysTaskAssignee> assignees = task.getAssignees();
        if (assignees != null && !assignees.isEmpty()) {
            for (SysTaskAssignee assignee : assignees) {
                Long userId = assignee.getUserId();
                // 查询该执行人的所有正在进行中的任务(排除PENDING、COMPLETED、CANCELLED)
                List<SysTask> userActiveTasks = this.selectMyTasks(userId).stream()
                    .filter(t -> !TaskStatus.PENDING.getCode().equals(t.getTaskStatus())
                              && !TaskStatus.COMPLETED.getCode().equals(t.getTaskStatus())
                              && !TaskStatus.CANCELLED.getCode().equals(t.getTaskStatus())
                              && !t.getTaskId().equals(taskId)) // 过滤掉当前任务
                    .collect(Collectors.toList());
                if (!userActiveTasks.isEmpty()) {
                    for (SysTask activeTask : userActiveTasks) {
                        Map<String, Object> conflict = new HashMap<>();
                        conflict.put("type", "assignee");
                        conflict.put("userName", assignee.getUserName());
                        conflict.put("taskId", activeTask.getTaskId());
                        conflict.put("taskCode", activeTask.getTaskCode());
                        conflict.put("taskStatus", activeTask.getTaskStatus());
                        conflict.put("message", String.format("执行人 %s 尚有正在进行中的任务 %s,请先完成",
                            assignee.getUserName(), activeTask.getTaskCode()));
                        conflicts.add(conflict);
                    }
                }
            }
        }
        
        // 更新地址信息
        if (createVO.getStartAddress() != null) {
            existingInfo.setPickupAddress(createVO.getStartAddress());
        }
        if (createVO.getEndAddress() != null) {
            existingInfo.setDestinationAddress(createVO.getEndAddress());
        // 3. 检查执行人是否全部就绪(受配置开关控制)
        String readyCheckEnabled = configService.selectConfigByKey("task.assignee.ready.check.enabled");
        if ("true".equalsIgnoreCase(readyCheckEnabled)) {
             assignees = task.getAssignees();
            if (assignees != null && !assignees.isEmpty()) {
                boolean allReady = assignees.stream()
                    .allMatch(a -> "1".equals(a.getIsReady()));
                if (!allReady) {
                    Map<String, Object> conflict = new HashMap<>();
                    conflict.put("type", "assigneeReady");
                    conflict.put("message", "存在未就绪的执行人,请等待所有执行人点击就绪后再出车");
                    conflicts.add(conflict);
                }
            }
        }
        
        // 更新GPS坐标
        if (createVO.getDepartureLongitude() != null) {
            existingInfo.setPickupLongitude(createVO.getDepartureLongitude());
        }
        if (createVO.getDepartureLatitude() != null) {
            existingInfo.setPickupLatitude(createVO.getDepartureLatitude());
        }
        if (createVO.getDestinationLongitude() != null) {
            existingInfo.setDestinationLongitude(createVO.getDestinationLongitude());
        }
        if (createVO.getDestinationLatitude() != null) {
            existingInfo.setDestinationLatitude(createVO.getDestinationLatitude());
        }
        // 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("valid", conflicts.isEmpty());
        result.put("conflicts", conflicts);
        
        // 更新距离和费用
        if (createVO.getDistance() != null) {
            existingInfo.setServiceDistance(createVO.getDistance());
        } else if (createVO.getEstimatedDistance() != null) {
            existingInfo.setServiceDistance(createVO.getEstimatedDistance());
        }
        if (createVO.getPrice() != null) {
            existingInfo.setServicePrice(createVO.getPrice());
        }
        // 系统字段
        existingInfo.setUpdateTime(DateUtils.getNowDate());
        existingInfo.setUpdateBy(userName);
        // 执行更新
        sysTaskWelfareMapper.updateSysTaskWelfare(existingInfo);
        return AjaxResult.success(result);
    }
    /**
     * 保存福祉车任务扩展信息
     * 执行人点击就绪
     * 
     * @param taskId 任务ID
     * @param createVO 任务创建对象
     * @param userId 用户ID
     * @return 结果
     */
    private void saveWelfareInfo(Long taskId,String userName, TaskCreateVO createVO) {
        SysTaskWelfare welfareInfo = new SysTaskWelfare();
        welfareInfo.setTaskId(taskId);
        // 设置乘客信息
        if (createVO.getPassenger() != null) {
            welfareInfo.setPassengerContact(createVO.getPassenger().getContact());
            welfareInfo.setPassengerPhone(createVO.getPassenger().getPhone());
        }
        // 设置地址信息
        welfareInfo.setPickupAddress(createVO.getStartAddress());
        welfareInfo.setDestinationAddress(createVO.getEndAddress());
        // 设置GPS坐标
        welfareInfo.setPickupLongitude(createVO.getDepartureLongitude());
        welfareInfo.setPickupLatitude(createVO.getDepartureLatitude());
        welfareInfo.setDestinationLongitude(createVO.getDestinationLongitude());
        welfareInfo.setDestinationLatitude(createVO.getDestinationLatitude());
        // 设置距离和费用
        // 优先使用福祉车专用的distance字段,如果没有则使用通用的estimatedDistance
        BigDecimal serviceDistance = createVO.getDistance() != null ? createVO.getDistance() : createVO.getEstimatedDistance();
        welfareInfo.setServiceDistance(serviceDistance);
        welfareInfo.setServicePrice(createVO.getPrice());
        // 系统字段
        welfareInfo.setCreateTime(DateUtils.getNowDate());
        welfareInfo.setUpdateTime(DateUtils.getNowDate());
        welfareInfo.setCreateBy(userName);
        welfareInfo.setUpdateBy(userName);
        sysTaskWelfareMapper.insertSysTaskWelfare(welfareInfo);
    @Override
    @Transactional
    public AjaxResult setAssigneeReady(Long taskId, Long userId) {
        return sysTaskAssigneeService.setAssigneeReady(taskId, userId);
    }
    /**
     * 获取附件分类描述
     * 取消执行人就绪
     * 
     * @param category 附件分类代码
     * @return 分类描述
     * @param taskId 任务ID
     * @param userId 用户ID
     * @return 结果
     */
    private String getCategoryDesc(String category) {
        if (category == null || category.isEmpty()) {
            return "未分类";
        }
        switch (category) {
            case "1": return "知情同意书";
            case "2": return "病人资料";
            case "3": return "操作记录";
            case "4": return "出车前";
            case "5": return "出车后";
            case "6": return "系安全带";
            default: return "其他";
        }
    @Override
    @Transactional
    public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
        return sysTaskAssigneeService.cancelAssigneeReady(taskId, userId);
    }
    /**
     * 构建附件的完整URL
     *
     * @param attachment 附件对象
     */
    private void buildAttachmentUrl(SysTaskAttachment attachment) {
        if (attachment != null && StringUtils.isNotEmpty(attachment.getFilePath())) {
            String imageUrl = imageUrlConfig.getImageUrl();
            if (StringUtils.isNotEmpty(imageUrl)) {
                // 拼接完整URL:域名 + 相对路径
                attachment.setFileUrl(imageUrl + attachment.getFilePath());
            } else {
                // 如果未配置域名,直接使用相对路径
                attachment.setFileUrl(attachment.getFilePath());
            }
        }
    }
   
}