wlzboy
2026-03-24 6676a35122fd9c97d1b1679c211bc8a9b97f08f2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -8,9 +8,11 @@
import java.net.URL;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.event.TaskDispatchSyncEvent;
import com.ruoyi.system.event.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.TaskCodeGenerator;
@@ -19,24 +21,18 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.GpsDistanceUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.SysTaskVehicle;
import com.ruoyi.system.domain.SysTaskAttachment;
import com.ruoyi.system.domain.SysTaskLog;
import com.ruoyi.system.domain.SysTaskStatusHistory;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.domain.SysTaskWelfare;
import com.ruoyi.system.domain.SysTaskAssignee;
import com.ruoyi.system.domain.enums.TaskStatus;
import com.ruoyi.system.domain.VehicleInfo;
import com.ruoyi.system.event.TaskCreatedEvent;
import com.ruoyi.system.event.TaskAssignedEvent;
import com.ruoyi.system.event.TaskStatusChangedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -61,6 +57,9 @@
    
    @Autowired
    private SysTaskLogMapper sysTaskLogMapper;
    @Autowired
    private SysTaskStatusHistoryMapper sysTaskStatusHistoryMapper;
    
    @Autowired
    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
@@ -83,8 +82,13 @@
    @Autowired
    private ISysTaskAttachmentService sysTaskAttachmentService;
    @Autowired
    private SysUserMapper sysUserMapper;
    private ISysDeptService deptService;
    @Autowired
    private ISysUserService userService;
    @Autowired(required = false)
    private IMapService mapService;
@@ -101,16 +105,23 @@
    @Autowired
    private ISysTaskVehicleService sysTaskVehicleService;
    @Autowired
    private ISysTaskAssigneeService assigneeService;
    @Override
    public Boolean dispatchSyncEvent(Long taskId) {
        SysTask task= sysTaskMapper.selectSysTaskByTaskId(taskId);
        SysUser user= sysUserMapper.selectUserById(task.getCreatorId());
        SysUser user= userService.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;
    }
    private Long getBranchCompanyId(Long userId) {
       return userService.getBranchCompanyIdByUserId(userId);
    }
    /**
     * 查询任务管理
     * 
@@ -121,6 +132,7 @@
    public SysTask selectSysTaskByTaskId(Long taskId) {
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task != null) {
            bindTaskAssign(task);
            // 加载急救转运扩展信息
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
@@ -135,6 +147,13 @@
        return task;
    }
    private void bindTaskAssign(SysTask task){
       List<SysTaskAssignee> assignees= assigneeService.getAssigneesByTaskId(task.getTaskId());
       if(assignees!=null && !assignees.isEmpty()) {
           task.setAssignees(assignees);
       }
    }
    /**
     * 查询任务管理列表
     * 
@@ -145,6 +164,7 @@
    public List<SysTask> selectSysTaskList(TaskQueryVO queryVO) {
        List<SysTask> tasks= sysTaskMapper.selectSysTaskList(queryVO);
        tasks.forEach(task -> {
            bindTaskAssign( task);
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId());
                task.setEmergencyInfo(emergencyInfo);
@@ -154,7 +174,26 @@
    }
    /**
     * 根据任务编号、调度单编号或服务单编号查询任务列表
     * 设置任务是总部推送的标记
     * @param taskCreatorId 任务创建人的用户ID
     * @param taskDeptId 任务中的归属机构ID
     */
    @Override
    public Boolean isTaskHeaderPush(Long taskCreatorId,Long taskDeptId){
        if(LongUtil.isEmpty(taskCreatorId))return false;
        if(LongUtil.isEmpty(taskDeptId))return false ;
        Long createrDeptId = getBranchCompanyId(taskCreatorId);
        if(createrDeptId !=null && !taskDeptId.equals(createrDeptId) && createrDeptId.equals(DeptUtil.GUANGZHOU_DEPT_ID)){
            //广州总部推送的任务
           return true;
        }else{
            return false;
        }
    }
    /**
     *根据任务编号、调度单编号或服务单编号查询任务列表(SQL算法下推优化版本)
     * 
     * @param queryVO 任务查询对象
     * @param taskCode 任务编号
@@ -162,49 +201,34 @@
     */
    @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 -> {
        // 设置任务码用于SQL查询
        queryVO.setTaskCode(taskCode);
        // 使用优化的查询方法,直接在SQL中关联sys_task_emergency表并计算匹配的dispatchCode和serviceCode
        List<SysTask> tasks = sysTaskMapper.selectSysTaskListByMultiCodeOptimized(queryVO);
        // 处理任务分配信息和急救转运扩展信息
        tasks.forEach(task -> {
            bindTaskAssign(task);
            // 对于急救转运任务,使用SQL查询中已计算并匹配好的dispatchCode和serviceCode
            if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId());
                task.setEmergencyInfo(emergencyInfo);
                // 创建一个临时的emergencyInfo对象,包含从SQL查询结果中获取的计算后的代码
//                SysTaskEmergency emergencyInfo = new SysTaskEmergency();
//                emergencyInfo.setDispatchCode(task.getDispatchCode());
//                emergencyInfo.setServiceCode(task.getServiceCode());
                // 加载完整的扩展信息
                SysTaskEmergency fullEmergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId());
                if (fullEmergencyInfo != null) {
                    // 保留完整信息,但确保dispatchCode和serviceCode是计算后的值
                    task.setEmergencyInfo(fullEmergencyInfo);
                }
            }
        });
        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());
        return tasks;
    }
    /**
@@ -214,23 +238,29 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int insertSysTask(TaskCreateVO createVO) {
    public Long insertSysTask(TaskCreateVO createVO) {
    // 获取当前用户名和用户ID
        String username = SecurityUtils.getUsername();
        Long userId = SecurityUtils.getUserId();
    // 校验用户ID是否为空或为0
        if(userId==null || userId==0){
            log.error("insertSysTask 用户ID为空 userName:{}",username);
            return 0;
            return 0L;
        }
        SysTask task = new SysTask();
    // 创建新的任务对象
        task.setTaskCode(generateTaskCode());
        task.setTaskType(createVO.getTaskType());
        task.setTaskStatus(TaskStatus.PENDING.getCode());
        task.setTaskDescription(createVO.getTaskDescription());
        task.setPlannedStartTime(createVO.getPlannedStartTime());
        task.setPlannedEndTime(createVO.getPlannedEndTime());
        task.setAssigneeId(createVO.getAssigneeId());
    // 设置任务基本信息
        task.setTaskType(createVO.getTaskType()); // 生成任务编码
        task.setTaskStatus(TaskStatus.PENDING.getCode()); // 设置任务类型
        task.setTaskDescription(createVO.getTaskDescription()); // 设置任务状态为待处理
        task.setPlannedStartTime(createVO.getPlannedStartTime()); // 设置任务描述
        task.setPlannedEndTime(createVO.getPlannedEndTime()); // 设置计划开始时间
        task.setAssigneeId(createVO.getAssigneeId()); // 设置计划结束时间
 // 设置指派人ID
        task.setCreatorId(userId);
    // 设置创建人信息
        // 优先使用前端传入的部门ID,如果没有则使用当前用户的部门ID
        task.setDeptId(createVO.getDeptId() != null ? createVO.getDeptId() : SecurityUtils.getDeptId());
        task.setCreateBy(username);
@@ -239,6 +269,7 @@
        task.setUpdateTime(DateUtils.getNowDate());
        task.setRemark(createVO.getRemark());
        task.setDelFlag("0");
        
        // 设置地址和坐标信息
        setAddressAndCoordinatesFromVO(task, createVO);
@@ -302,7 +333,7 @@
            }).start();
        }
        
        return result;
        return result > 0 ? task.getTaskId() : 0L;
    }
    /**
@@ -316,8 +347,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTask(TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo, Long userId,String userName, Long deptId, Date createTime, Date updateTime) {
    public Long insertTask(TaskCreateVO createVO,Long serviceOrderId,Long dispatchOrderId, String serviceOrdNo, Long userId,String userName, Long deptId, Date createTime, Date updateTime) {
        SysTask task = new SysTask();
        if(createVO.getTaskCode()!=null){
            task.setTaskCode(createVO.getTaskCode());
@@ -342,8 +372,6 @@
        task.setUpdateBy(userName);
        task.setRemark(createVO.getRemark());
        task.setDelFlag("0");
        
        // 设置地址和坐标信息
        setAddressAndCoordinatesFromVO(task, createVO);
@@ -363,9 +391,7 @@
        if (createVO.getEndAddress() != null) {
            task.setDestinationAddress(createVO.getEndAddress());
        }
        if (createVO.getDistance() != null) {
            task.setEstimatedDistance(createVO.getDistance());
        }
        // 自动填充缺失的GPS坐标
        autoFillMissingGpsCoordinates(task);
        
@@ -411,18 +437,19 @@
        }
        
        if(result>0) {
            this.sendEmeryTaskProcess(task, dispatchOrderId);
        }
        
        return result;
        return result > 0 ? task.getTaskId() : 0L;
    }
    private void sendTaskAssigneeEvent(TaskCreateVO createVO,SysTask task,Long userId,String userName){
        List<Long> assigneeIds = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserId())
                .map(TaskCreateVO.AssigneeInfo::getUserId)
                .collect(Collectors.toList());
        List<String> assigneeNames = createVO.getAssignees().stream()
                .map(assignee -> assignee.getUserName())
                .map(TaskCreateVO.AssigneeInfo::getUserName)
                .collect(Collectors.toList());
        eventPublisher.publishEvent(new TaskAssignedEvent(
@@ -443,16 +470,14 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int updateSysTask(TaskUpdateVO updateVO, Boolean updateFromLegacy) {
        SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(updateVO.getTaskId());
        if (oldTask == null) {
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(updateVO.getTaskId());
        if (task == null) {
            throw new RuntimeException("任务不存在");
        }
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getUsername();
        SysTask task = new SysTask();
        task.setTaskId(updateVO.getTaskId());
        task.setTaskDescription(updateVO.getTaskDescription());
        task.setPlannedStartTime(updateVO.getPlannedStartTime());
@@ -461,41 +486,32 @@
        task.setUpdateBy(userName);
        task.setUpdateTime(updateVO.getUpdateTime() != null ? updateVO.getUpdateTime() : DateUtils.getNowDate());
        task.setRemark(updateVO.getRemark());
        
        // 设置通用地址和坐标信息
        task.setDepartureAddress(updateVO.getDepartureAddress());
        task.setDestinationAddress(updateVO.getDestinationAddress());
        task.setDepartureLongitude(updateVO.getDepartureLongitude());
        task.setDepartureLatitude(updateVO.getDepartureLatitude());
        task.setDestinationLongitude(updateVO.getDestinationLongitude());
        task.setDestinationLatitude(updateVO.getDestinationLatitude());
        
        // 设置预计距离
        if (updateVO.getEstimatedDistance() != null) {
            task.setEstimatedDistance(updateVO.getEstimatedDistance());
        } else if (updateVO.getTransferDistance() != null) {
            // 兼容急救转运字段
        if (updateVO.getTransferDistance() != null) {
            task.setEstimatedDistance(updateVO.getTransferDistance());
        } else if (updateVO.getDistance() != null) {
            // 兼容福祉车字段
            task.setEstimatedDistance(updateVO.getDistance());
        }
        
        // 如果更新了部门ID
        if (updateVO.getDeptId() != null) {
            task.setDeptId(updateVO.getDeptId());
        }
        // 如果更新了任务编号
        if (updateVO.getTaskCode() != null) {
            task.setTaskCode(updateVO.getTaskCode());
        }
        Boolean hasSetDepartureFlag=false;
        //设置总部推送
        // 自动获取出发地GPS坐标(如果更新了地址但缺失坐标)
        if (updateVO.getDepartureAddress() != null && 
            (updateVO.getDepartureLongitude() == null || updateVO.getDepartureLatitude() == null) && 
            mapService != null) {
            if (!updateVO.getDepartureAddress().equals(oldTask.getDepartureAddress())) {
            if (!updateVO.getDepartureAddress().equals(task.getDepartureAddress())) {
                try {
                    Map<String, Double> coords = mapService.geocoding(
                        updateVO.getDepartureAddress(),
@@ -504,6 +520,7 @@
                    if (coords != null) {
                        task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                        task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                        hasSetDepartureFlag = true;
//                        log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
@@ -511,12 +528,20 @@
                }
            }
        }
        // 设置通用地址和坐标信息
        task.setDepartureAddress(updateVO.getDepartureAddress());
        if(!hasSetDepartureFlag) {
            task.setDepartureLongitude(updateVO.getDepartureLongitude());
            task.setDepartureLatitude(updateVO.getDepartureLatitude());
        }
        Boolean hasSetDestinationFlag=false;
        // 自动获取目的地GPS坐标(如果更新了地址但缺失坐标)
        if (updateVO.getDestinationAddress() != null && 
            (updateVO.getDestinationLongitude() == null || updateVO.getDestinationLatitude() == null) && 
            mapService != null) {
            if (!updateVO.getDestinationAddress().equals(oldTask.getDestinationAddress())) {
            if (!updateVO.getDestinationAddress().equals(task.getDestinationAddress())) {
                try {
                    Map<String, Double> coords = mapService.geocoding(
                        updateVO.getDestinationAddress(),
@@ -525,6 +550,7 @@
                    if (coords != null) {
                        task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                        task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                        hasSetDestinationFlag = true;
//                        log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                    }
                } catch (Exception e) {
@@ -532,8 +558,19 @@
                }
            }
        }
        task.setDestinationAddress(updateVO.getDestinationAddress());
        if(!hasSetDestinationFlag) {
            task.setDestinationLongitude(updateVO.getDestinationLongitude());
            task.setDestinationLatitude(updateVO.getDestinationLatitude());
        }
        if(updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty()){
           TaskCreateVO.AssigneeInfo assigneeInfo= updateVO.getAssignees().get(0);
            task.setAssigneeId(assigneeInfo.getUserId());
            task.setAssigneeName(assigneeInfo.getUserName());
        }
        // 用于跟踪是否需要重新同步(车辆、人员、地址、成交价变更)
        boolean needResync = false;
        boolean needResync = true;
        int result = sysTaskMapper.updateSysTask(task);
        
@@ -547,7 +584,8 @@
                needResync = true;
            }
        }
        // 更新执行人员(检测人员变更)
        if (result > 0 && updateVO.getAssignees() != null) {
            boolean assigneesChanged = sysTaskAssigneeService.updateTaskAssignees(
@@ -559,40 +597,52 @@
        }
        Long dispatchOrderId=0L;
        // 更新急救转运扩展信息(检测地址和成交价变更)
        if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType())) {
        if (result > 0 && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            SysTaskEmergency oldEmergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(updateVO.getTaskId());
            sysEmergencyTaskService.updateEmergencyInfoFromUpdateVO(oldEmergency, updateVO, userName);
          dispatchOrderId=  oldEmergency.getLegacyDispatchOrdId();
            sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
            markNeedSync(task,updateVO);
        }
        
        // 更新福祉车扩展信息
        if (result > 0 && "WELFARE".equals(oldTask.getTaskType())) {
        if (result > 0 && "WELFARE".equals(task.getTaskType())) {
            if (updateVO.getPassenger() != null || updateVO.getStartAddress() != null || updateVO.getEndAddress() != null) {
                sysWelfareTaskService.updateWelfareInfo(updateVO.getTaskId(), updateVO, userName);
            }
        }
        
        // 如果是急救转运任务且有变更,标记需要重新同步
        if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && needResync && !updateFromLegacy) {
            sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
        }
        
        // 记录操作日志
        if (result > 0) {
            recordTaskLog(updateVO.getTaskId(), "UPDATE", "更新任务",
                buildTaskDescription(oldTask), buildTaskDescription(task),
                buildTaskDescription(task), buildTaskDescription(task),
                userId, userName);
        }
        if(result > 0 && oldTask.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees() != null && !updateVO.getAssignees().isEmpty() && dispatchOrderId>0L){
        if(result > 0 && task.getTaskStatus().equals(TaskStatus.PENDING.getCode())
                && updateVO.getAssignees() != null
                && !updateVO.getAssignees().isEmpty()
                && LongUtil.isNotEmpty(dispatchOrderId)){
            this.sendTaskAssigneeEvent(updateVO,oldTask,userId,userName);
            this.sendTaskAssigneeEvent(updateVO,task,userId,userName);
        }
        return result;
    }
    private void markNeedSync(SysTask sysTask,TaskUpdateVO updateVO){
        // 如果是急救转运任务且有变更,标记需要重新同步
        if ( "EMERGENCY_TRANSFER".equals(sysTask.getTaskType()) ) {
            sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), sysTask, updateVO, true);
            eventPublisher.publishEvent(new TaskUpdateEvent(this,sysTask.getTaskId(),
                    sysTask.getTaskCode(),sysTask.getTaskType()));
        }
    }
    /**
     * 更新任务(用于旧系统同步)
     * 
@@ -608,15 +658,17 @@
     * @return 结果
     */
    @Override
    public int updateTask(TaskUpdateVO updateVO, String serviceOrderId, String dispatchOrderId, String serviceOrdNo,
    public int updateTask(TaskUpdateVO updateVO, Long serviceOrderId, Long 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));
        // 获取旧任务信息,用于判断地址是否变更
        SysTaskEmergency taskEmergency = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(serviceOrderId);
        Long taskId = taskEmergency.getTaskId();
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        updateVO.setTaskId(taskId);
        SysTask task = new SysTask();
        task.setTaskId(taskId);
        if(updateVO.getTaskStatus()!=null){
            task.setTaskStatus(updateVO.getTaskStatus());
        }
@@ -629,20 +681,25 @@
        if(updateVO.getActualEndTime() != null) {
            task.setActualEndTime(updateVO.getActualEndTime());
        }
        task.setAssigneeId(updateVO.getAssigneeId());
        if(deptId!=null){
            task.setDeptId(deptId);
        }
//        task.setAssigneeId(updateVO.getAssigneeId());
        task.setUpdateBy(userName);
        task.setUpdateTime(DateUtils.getNowDate());
        task.setRemark(updateVO.getRemark());
        
        // 设置地址和坐标信息
        task.setDepartureAddress(updateVO.getDepartureAddress());
        task.setDestinationAddress(updateVO.getDestinationAddress());
        task.setDepartureLongitude(updateVO.getDepartureLongitude());
        task.setDepartureLatitude(updateVO.getDepartureLatitude());
        task.setDestinationLongitude(updateVO.getDestinationLongitude());
        task.setDestinationLatitude(updateVO.getDestinationLatitude());
        if(updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty()){
            TaskCreateVO.AssigneeInfo assigneeInfo= updateVO.getAssignees().get(0);
            task.setAssigneeId(assigneeInfo.getUserId());
            task.setAssigneeName(assigneeInfo.getUserName());
        }
        // 如果更新了部门ID
        if (updateVO.getDeptId() != null) {
            task.setDeptId(updateVO.getDeptId());
@@ -652,13 +709,11 @@
        if (updateVO.getTaskCode() != null) {
            task.setTaskCode(updateVO.getTaskCode());
        }
        // 获取旧任务信息,用于判断地址是否变更
        SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(taskId);
        Boolean modifyOutLongLat = false;
        // 自动获取出发地GPS坐标(如果地址变更且缺失坐标)
        if (oldTask != null && updateVO.getDepartureAddress() != null
            && !updateVO.getDepartureAddress().equals(oldTask.getDepartureAddress())
        if (task != null && updateVO.getDepartureAddress() != null
            && !updateVO.getDepartureAddress().equals(task.getDepartureAddress())
            && (updateVO.getDepartureLongitude() == null || updateVO.getDepartureLatitude() == null)
            && mapService != null) {
            try {
@@ -669,16 +724,23 @@
                if (coords != null) {
                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
                    modifyOutLongLat = true;
//                    log.info("出发地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取出发地GPS坐标失败", e);
            }
        }
        task.setDepartureAddress(updateVO.getDepartureAddress());
        if(!modifyOutLongLat){
            task.setDepartureLongitude(updateVO.getDepartureLongitude());
            task.setDepartureLatitude(updateVO.getDepartureLatitude());
        }
        Boolean modifyInLongLat = false;
        // 自动获取目的地GPS坐标(如果地址变更且缺失坐标)
        if (oldTask != null && updateVO.getDestinationAddress() != null
            && !updateVO.getDestinationAddress().equals(oldTask.getDestinationAddress())
        if (task != null && updateVO.getDestinationAddress() != null
            && !updateVO.getDestinationAddress().equals(task.getDestinationAddress())
            && (updateVO.getDestinationLongitude() == null || updateVO.getDestinationLatitude() == null)
            && mapService != null) {
            try {
@@ -689,11 +751,17 @@
                if (coords != null) {
                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
                    modifyInLongLat = true;
//                    log.info("目的地GPS坐标自动获取成功: {}, {}", coords.get("lng"), coords.get("lat"));
                }
            } catch (Exception e) {
                log.error("自动获取目的地GPS坐标失败", e);
            }
        }
        task.setDestinationAddress(updateVO.getDestinationAddress());
        if(!modifyInLongLat){
            task.setDestinationLongitude(updateVO.getDestinationLongitude());
            task.setDestinationLatitude(updateVO.getDestinationLatitude());
        }
        
        int result = sysTaskMapper.updateSysTask(task);
@@ -713,14 +781,14 @@
//            log.info("更新执行人员 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId);
            sysTaskAssigneeService.updateTaskAssignees(taskId, updateVO.getAssignees(), userName);
        }
        Long dispatchOrderIdLong = 0L;
        // 更新急救转运扩展信息
        if (result > 0) {
            // 更新旧系统ID
            taskEmergency.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
            if (dispatchOrderId != null) {
                dispatchOrderIdLong = Long.parseLong(dispatchOrderId);
                taskEmergency.setLegacyDispatchOrdId(dispatchOrderIdLong);
            taskEmergency.setLegacyServiceOrdId(serviceOrderId);
            if (LongUtil.isNotEmpty(dispatchOrderId)) {
                taskEmergency.setLegacyDispatchOrdId(dispatchOrderId);
                taskEmergency.setDispatchSyncStatus(2);
                taskEmergency.setDispatchSyncTime(new Date());
                taskEmergency.setDispatchSyncErrorMsg("旧系统同步过来");
@@ -730,24 +798,43 @@
            }
            taskEmergency.setUpdateTime(DateUtils.getNowDate());
            Boolean hasEmergencyInfo = updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null;
            Boolean hasEmergencyInfo = updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null
                    || updateVO.getPrice() != null || updateVO.getTransferDistance() != null;
//            Boolean isHeadPush=isTaskHeaderPush(task.getCreatorId(),task.getDeptId());
//            updateVO.setFromHQ2_is(isHeadPush?"1":"0");
            // 使用TaskCreateVO的字段来更新急救转运信息
            if (hasEmergencyInfo) {
                sysEmergencyTaskService.updateEmergencyInfoFromCreateVO(taskEmergency, updateVO, userName);
            }
           SysTaskEmergency emergency= sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId);
            dispatchOrderIdLong = emergency.getLegacyDispatchOrdId();
            dispatchOrderId = emergency.getLegacyDispatchOrdId();
        }
        if(updateVO.getTaskStatus()!=null && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty() && dispatchOrderIdLong>0L){
        if(updateVO.getTaskStatus()!=null
                && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode())
                && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty()
                && LongUtil.isNotEmpty(dispatchOrderId)){
            this.sendTaskAssigneeEvent(updateVO,task,userId,userName);
        }
        return result;
    }
    private void sendEmeryTaskProcess(SysTask task,Long dispatchOrderId){
        Long taskId = task.getTaskId();
        String taskCode = task.getShowTaskCode();
        if(task.getTaskStatus()!=null && task.getTaskStatus().equals(TaskStatus.PENDING.getCode())){
            //如果没有分配人员,且没有调度单,不是广州总公司的就需要发送通知跟进
            if(LongUtil.isEmpty(dispatchOrderId)){
                if(!task.getDeptId().equals(DeptUtil.GUANGZHOU_DEPT_ID) && (task.getAssignees()==null  || task.getAssignees().isEmpty())){
                    //发送通知
                    eventPublisher.publishEvent(new TaskOnlyServerOrderSyncEvent(this, taskId, taskCode));
                }
            }
        }
    }
    /**
     * 批量删除任务管理
     * 
@@ -755,7 +842,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteSysTaskByTaskIds(Long[] taskIds) {
        int result = 0;
        for (Long taskId : taskIds) {
@@ -776,7 +863,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int assignTask(Long taskId, Long assigneeId, String remark) {
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task == null) {
@@ -831,6 +918,76 @@
    }
    /**
     * 强制完成任务(指定实际开始时间和结束时间)
     *
     * @param task 任务信息
     * @return 结果
     */
    @Override
    public int forceCompleteTask(SysTask task) {
        if (task == null || task.getTaskId() == null) {
            throw new RuntimeException("任务信息不能为空");
        }
        SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(task.getTaskId());
        if (oldTask == null) {
            throw new RuntimeException("任务不存在");
        }
        // 校验开始时间和结束时间
        if (task.getActualStartTime() == null || task.getActualEndTime() == null) {
            throw new RuntimeException("实际开始时间和结束时间不能为空");
        }
        if (task.getActualStartTime().after(task.getActualEndTime())) {
            throw new RuntimeException("结束时间必须大于开始时间");
        }
        // 记录旧状态
        String oldStatus = oldTask.getTaskStatus();
        TaskStatus oldTaskStatus = TaskStatus.getByCode(oldStatus);
        // 更新任务
        int result = sysTaskMapper.updateTaskStatus(task);
        // 记录操作日志
        if (result > 0) {
            recordTaskLog(task.getTaskId(), "FORCE_COMPLETE", "强制完成任务",
                         oldStatus, task.getTaskStatus(),
                         SecurityUtils.getUserId(), SecurityUtils.getUsername());
            // 写入状态变更历史记录
            recordStatusHistory(oldTask, oldStatus,
                    oldTaskStatus != null ? oldTaskStatus.getInfo() : oldStatus,
                    task.getTaskStatus(),
                    TaskStatus.getByCode(task.getTaskStatus()) != null ? TaskStatus.getByCode(task.getTaskStatus()).getInfo() : task.getTaskStatus(),
                    task.getRemark(),
                    SysTaskStatusHistory.SOURCE_APP,
                    SecurityUtils.getUserId(), SecurityUtils.getUsername(),
                    null);
            // 发布任务状态变更事件
            TaskStatus newTaskStatus = TaskStatus.getByCode(task.getTaskStatus());
            eventPublisher.publishEvent(new TaskStatusChangedEvent(
                this,
                task.getTaskId(),
                oldTask.getTaskCode(),
                oldStatus,
                task.getTaskStatus(),
                oldTaskStatus != null ? oldTaskStatus.getInfo() : "未知",
                newTaskStatus != null ? newTaskStatus.getInfo() : "未知",
                null, // assigneeIds
                SecurityUtils.getUserId(),
                SecurityUtils.getUserId(),
                null, // longitude
                null, // latitude
                null  // address
            ));
        }
        return result;
    }
    /**
     * 变更任务状态(含GPS位置信息)
     * 
     * @param taskId 任务ID
@@ -879,6 +1036,12 @@
                         "状态:" + newStatus.getInfo() + ",备注:" + remark, 
                         SecurityUtils.getUserId(), SecurityUtils.getUsername(),
                         locationLog);
            // 写入状态变更历史记录
            recordStatusHistory(oldTask, oldTaskStatus.getCode(), oldTaskStatus.getInfo(),
                    newStatus.getCode(), newStatus.getInfo(), remark,
                    SysTaskStatusHistory.SOURCE_APP,
                    SecurityUtils.getUserId(), SecurityUtils.getUsername(),
                    locationLog);
        }
        
        // 发布任务状态变更事件
@@ -916,6 +1079,71 @@
    }
    /**
     * 保存任务取消信息(仅限转运任务)
     *
     * @param taskId 任务ID
     * @param cancelReason 取消原因(数据字典task_cancel_reason的value)
     * @return 结果
     */
    @Override
    public int saveCancelInfo(Long taskId, String cancelReason) {
        // 获取任务信息
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在");
        }
        // 只有转运任务才保存取消信息
        if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            return 0;
        }
        // 获取转运任务扩展信息
        SysTaskEmergency emergency = sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId);
        if (emergency == null) {
            return 0;
        }
        // 设置取消信息
        emergency.setCancelReason(cancelReason);
        emergency.setCancelBy(SecurityUtils.getNickName());
        emergency.setCancelTime(DateUtils.getNowDate());
        emergency.setUpdateBy(SecurityUtils.getUsername());
        emergency.setUpdateTime(DateUtils.getNowDate());
        // 更新数据库
        return sysTaskEmergencyMapper.updateSysTaskEmergency(emergency);
    }
    @Override
    public int saveCancel(Long taskId, String cancelReason, String cancelBy,Date cancelTime) {
        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在");
        }
        // 只有转运任务才保存取消信息
        if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            return 0;
        }
        // 获取转运任务扩展信息
        SysTaskEmergency emergency = sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId);
        if (emergency == null) {
            return 0;
        }
        // 设置取消信息
        emergency.setCancelReason(cancelReason);
        emergency.setCancelBy(cancelBy);
        emergency.setCancelTime(cancelTime);
        emergency.setUpdateTime(DateUtils.getNowDate());
        // 更新数据库
        return sysTaskEmergencyMapper.updateSysTaskEmergency(emergency);
    }
    /**
     * 上传任务附件
     * 
     * @param taskId 任务ID
@@ -924,7 +1152,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
        return sysTaskAttachmentService.uploadAttachment(taskId, file, category);
    }
@@ -939,7 +1167,7 @@
     * @return 返回附件ID
     */
    @Override
    @Transactional
    public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
        return sysTaskAttachmentService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
    }
@@ -952,7 +1180,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteAttachment(Long attachmentId) {
        return sysTaskAttachmentService.deleteAttachment(attachmentId);
    }
@@ -982,7 +1210,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int assignVehicleToTask(Long taskId, Long vehicleId, String remark,Long userId,String userName) {
        int result = sysTaskVehicleService.assignVehicleToTask(taskId, vehicleId, remark, userId, userName);
        
@@ -1004,7 +1232,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
        int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId);
        
@@ -1027,7 +1255,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,Long userId,String userName) {
        int result = sysTaskVehicleService.assignMultipleVehiclesToTask(taskId, vehicleIds, remark, userId, userName);
        
@@ -1094,6 +1322,7 @@
    public List<SysTask> selectMyTasks(Long userId) {
        List<SysTask> list = sysTaskMapper.selectMyTasks(userId);
        list.stream().forEach(task -> {
            bindTaskAssign(task);
            if(task.getTaskType().equals("EMERGENCY_TRANSFER")){
                task.setEmergencyInfo(sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(task.getTaskId()));
            }
@@ -1276,6 +1505,51 @@
    }
    /**
     * 记录任务状态变更历史
     *
     * @param task            任务对象(取 task_id / task_code)
     * @param fromStatus      变更前状态码
     * @param fromStatusName  变更前状态名称
     * @param toStatus        变更后状态码
     * @param toStatusName    变更后状态名称
     * @param changeReason    变更原因/备注
     * @param changeSource    触发来源(APP / ADMIN / SYSTEM / LEGACY)
     * @param operatorId      操作人 ID
     * @param operatorName    操作人姓名
     * @param locationLog     GPS 位置信息(可为 null)
     */
    private void recordStatusHistory(SysTask task,
                                     String fromStatus, String fromStatusName,
                                     String toStatus, String toStatusName,
                                     String changeReason, String changeSource,
                                     Long operatorId, String operatorName,
                                     SysTaskLog locationLog) {
        try {
            SysTaskStatusHistory history = new SysTaskStatusHistory();
            history.setTaskId(task.getTaskId());
            history.setTaskCode(task.getTaskCode());
            history.setFromStatus(fromStatus);
            history.setFromStatusName(fromStatusName);
            history.setToStatus(toStatus);
            history.setToStatusName(toStatusName);
            history.setChangeReason(changeReason);
            history.setChangeSource(changeSource != null ? changeSource : SysTaskStatusHistory.SOURCE_APP);
            history.setOperatorId(operatorId);
            history.setOperatorName(operatorName);
            history.setChangeTime(DateUtils.getNowDate());
            history.setIpAddress("127.0.0.1");
            if (locationLog != null) {
                history.setLongitude(locationLog.getLongitude());
                history.setLatitude(locationLog.getLatitude());
                history.setLocationAddress(locationLog.getLocationAddress());
            }
            sysTaskStatusHistoryMapper.insert(history);
        } catch (Exception e) {
            log.error("记录任务状态变更历史失败, taskId={}", task.getTaskId(), e);
        }
    }
    /**
     * 构建任务描述
     * 
     * @param task 任务对象
@@ -1319,8 +1593,8 @@
        if (createVO.getDestinationLatitude() != null) {
            task.setDestinationLatitude(createVO.getDestinationLatitude());
        }
        if (createVO.getEstimatedDistance() != null) {
            task.setEstimatedDistance(createVO.getEstimatedDistance());
        if (createVO.getTransferDistance() != null) {
            task.setEstimatedDistance(createVO.getTransferDistance());
        }
    }
@@ -1349,9 +1623,7 @@
        if (createVO.getEndAddress() != null) {
            task.setDestinationAddress(createVO.getEndAddress());
        }
        if (createVO.getDistance() != null) {
            task.setEstimatedDistance(createVO.getDistance());
        }
    }
    /**
@@ -1427,6 +1699,13 @@
        }
    }
    private AjaxResult getCheckCanSuccess(){
        List<Map<String, Object>> conflicts = new ArrayList<>();
        Map<String, Object> result = new HashMap<>();
        result.put("valid", conflicts.isEmpty());
        result.put("conflicts", conflicts);
        return AjaxResult.success(result);
    }
    /**
     * 检查任务是否可以出发
     * 检查:
@@ -1438,13 +1717,18 @@
     */
    @Override
    public AjaxResult checkTaskCanDepart(Long taskId) {
        return getCheckCanSuccess();
    }
    public AjaxResult checkTaskCanDepartOld(Long taskId) {
        List<Map<String, Object>> conflicts = new ArrayList<>();
        Map<String, Object> result = new HashMap<>();
        // 获取任务详情
        SysTask task = this.getTaskDetail(taskId);
        if (task == null) {
            return AjaxResult.error("任务不存在");
        }
        List<Map<String, Object>> conflicts = new ArrayList<>();
        
        // 1. 检查车辆是否有未完成的任务
        List<SysTaskVehicle> taskVehicles = task.getAssignedVehicles();
@@ -1520,8 +1804,7 @@
            }
        }
        
        // 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("valid", conflicts.isEmpty());
        result.put("conflicts", conflicts);
        
@@ -1536,7 +1819,7 @@
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult setAssigneeReady(Long taskId, Long userId) {
        return sysTaskAssigneeService.setAssigneeReady(taskId, userId);
    }
@@ -1549,9 +1832,24 @@
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
        return sysTaskAssigneeService.cancelAssigneeReady(taskId, userId);
    }
    /**
     * 检查任务是否重复(根据联系人电话和创建日期)
     *
     * @param phone 联系人电话
     * @param createDate 任务创建日期(格式:YYYY-MM-DD)
     * @return true-存在重复,false-不重复
     */
    @Override
    public boolean checkTaskDuplicate(String phone, String createDate) {
        int count = sysTaskMapper.countTaskByPhoneAndDate(phone, createDate);
        return count > 0;
    }
   
}