wlzboy
2026-02-05 57e98ac3f59e9ca12d3fdbc6f89c9c0b1f86be4d
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
@@ -1,7 +1,19 @@
package com.ruoyi.web.controller.task;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.ILegacySystemSyncService;
import com.ruoyi.system.service.ITaskDispatchSyncService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -16,6 +28,8 @@
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.SysTaskLog;
@@ -25,10 +39,9 @@
import com.ruoyi.system.domain.vo.TaskUpdateVO;
import com.ruoyi.system.domain.vo.TaskStatisticsVO;
import com.ruoyi.system.domain.enums.TaskStatus;
import com.ruoyi.system.service.ISysTaskService;
import com.ruoyi.system.service.IVehicleInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
/**
 * 任务管理Controller
@@ -42,9 +55,32 @@
    
    @Autowired
    private ISysTaskService sysTaskService;
    @Autowired
    private ISysTaskEmergencyService sysTaskEmergencyService;
    
    @Autowired
    private IVehicleInfoService vehicleInfoService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    @Qualifier("tiandituMapService")
    private IMapService mapService;
    @Autowired
    private ILegacySystemSyncService legacySystemSyncService;
    @Autowired
    private ITaskDispatchSyncService taskDispatchSyncService;
    @Autowired
    private ITaskStatusPushService taskStatusPushService;
    /**
     * 查询任务管理列表(后台管理端)
@@ -54,27 +90,69 @@
    @GetMapping("/admin/list")
    public TableDataInfo adminList(TaskQueryVO queryVO) {
        startPage();
        List<SysTask> list = sysTaskService.selectSysTaskList(queryVO);
        // Handle multi-field task code search
        String searchTaskCode = queryVO.getTaskCode();
        List<SysTask> list;
        if(searchTaskCode != null && !searchTaskCode.trim().isEmpty()){
            // Search across task_code, emergency_info.dispatch_code, and emergency_info.service_code
            list = sysTaskService.selectSysTaskListByMultiCode(queryVO, searchTaskCode);
        } else {
            queryVO.setTaskCode(null);
            list = sysTaskService.selectSysTaskList(queryVO);
        }
        return getDataTable(list);
    }
    /**
     * 查询任务列表(APP端)
     * 仅显示当前用户相关的任务:
     * 1. 当前用户所在机构的任务
     * 2. 当前用户创建的任务
     * 3. 分配给当前用户的任务
     * 根据用户权限返回不同范围的任务:
     * 1. 有查看所有咨询单权限(canViewAllConsult='1'):返回该用户管理所有分公司下的所有任务单
     * 2. 无权限(canViewAllConsult='0'):只返回分配给该用户的单或该用户创建的单
     */
    @GetMapping("/list")
    public TableDataInfo appList(TaskQueryVO queryVO) {
        // 在后端自动获取当前用户信息,实现综合查询
        // 获取当前用户信息
        Long currentUserId = getUserId();
        Long currentDeptId = getDeptId();
        SysUser currentUser = userService.selectUserById(currentUserId);
        
        // APP端强制使用当前登录用户信息进行过滤
        queryVO.setDeptId(currentDeptId);
        queryVO.setCreatorId(currentUserId);
        queryVO.setAssigneeId(currentUserId);
        if (currentUser == null) {
            return getDataTable(new java.util.ArrayList<>());
        }
        // 判断用户是否有查看所有咨询单的权限
        String canViewAllConsult = currentUser.getCanViewAllConsult();
        if ("1".equals(canViewAllConsult)) {
            // 有权限:返回该用户管理所有分公司下的所有任务单
            // 1. 获取用户管理的分公司列表
            List<SysDept> branchCompanies = deptService.computeBranchCompaniesForUser(currentUser);
            if (branchCompanies != null && !branchCompanies.isEmpty()) {
                // 2. 提取所有分公司ID
                List<Long> deptIds = new java.util.ArrayList<>();
                for (SysDept dept : branchCompanies) {
                    deptIds.add(dept.getDeptId());
                }
                // 3. 设置查询条件为分公司ID列表(SQL会自动包含所有子部门)
                queryVO.setDeptIds(deptIds);
                // 清空创建人和执行人过滤条件,返回这些分公司下的所有任务
                queryVO.setCreatorId(null);
                queryVO.setAssigneeId(null);
            } else {
                // 如果没有找到分公司,返回空列表
                return getDataTable(new java.util.ArrayList<>());
            }
        } else {
            // 无权限:只返回分配给该用户的单或该用户创建的单
            // 清空deptId和deptIds,使用creatorId和assigneeId进行OR查询
            queryVO.setDeptId(null);
            queryVO.setDeptIds(null);
            queryVO.setCreatorId(currentUserId);
            queryVO.setAssigneeId(currentUserId);
        }
        
        startPage();
        List<SysTask> list = sysTaskService.selectSysTaskList(queryVO);
@@ -117,7 +195,8 @@
    @Log(title = "任务管理", businessType = BusinessType.INSERT)
    @PostMapping("/admin")
    public AjaxResult adminAdd(@RequestBody TaskCreateVO createVO) {
        return toAjax(sysTaskService.insertSysTask(createVO));
        Long taskId = sysTaskService.insertSysTask(createVO);
        return taskId > 0 ? AjaxResult.success("新增成功").put("taskId", taskId) : AjaxResult.error("新增失败");
    }
    /**
@@ -126,7 +205,32 @@
    @Log(title = "任务创建", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult appAdd(@RequestBody TaskCreateVO createVO) {
        return toAjax(sysTaskService.insertSysTask(createVO));
        Long taskId = sysTaskService.insertSysTask(createVO);
        return taskId > 0 ? AjaxResult.success("新增成功").put("taskId", taskId) : AjaxResult.error("新增失败");
    }
    /**
     * 检查任务是否重复(根据联系人电话和创建日期)
     * @param phone 联系人电话
     * @param createDate 任务创建日期(格式:YYYY-MM-DD)
     * @return 是否存在重复任务
     */
    @GetMapping("/checkDuplicate")
    public AjaxResult checkDuplicate(
            @RequestParam("phone") String phone,
            @RequestParam("createDate") String createDate) {
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(createDate)) {
            return AjaxResult.error("参数不能为空");
        }
        boolean isDuplicate = sysTaskService.checkTaskDuplicate(phone, createDate);
        if (isDuplicate) {
            return AjaxResult.error("该联系电话在该日期已有任务,不能重复提交");
        }
        return AjaxResult.success("未发现重复任务");
    }
    /**
@@ -136,7 +240,7 @@
    @Log(title = "任务管理", businessType = BusinessType.UPDATE)
    @PutMapping("/admin")
    public AjaxResult adminEdit(@RequestBody TaskUpdateVO updateVO) {
        return toAjax(sysTaskService.updateSysTask(updateVO));
        return toAjax(sysTaskService.updateSysTask(updateVO,false));
    }
    /**
@@ -145,7 +249,7 @@
    @Log(title = "任务修改", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult appEdit(@RequestBody TaskUpdateVO updateVO) {
        return toAjax(sysTaskService.updateSysTask(updateVO));
        return toAjax(sysTaskService.updateSysTask(updateVO,false));
    }
    /**
@@ -212,24 +316,53 @@
            return error("无效的任务状态");
        }
        
        // 如果包含GPS位置信息,使用带位置的方法
        if (request.getLatitude() != null && request.getLongitude() != null) {
            SysTaskLog locationLog = new SysTaskLog();
            locationLog.setLatitude(request.getLatitude());
            locationLog.setLongitude(request.getLongitude());
            locationLog.setLocationAddress(request.getLocationAddress());
            locationLog.setLocationProvince(request.getLocationProvince());
            locationLog.setLocationCity(request.getLocationCity());
            locationLog.setLocationDistrict(request.getLocationDistrict());
            locationLog.setGpsAccuracy(request.getGpsAccuracy());
            locationLog.setAltitude(request.getAltitude());
            locationLog.setSpeed(request.getSpeed());
            locationLog.setHeading(request.getHeading());
            return toAjax(sysTaskService.changeTaskStatusWithLocation(taskId, newStatus, request.getRemark(), locationLog));
        // 如果是取消状态,保存取消原因
        if (newStatus == TaskStatus.CANCELLED && StringUtils.isNotEmpty(request.getCancelReason())) {
            sysTaskService.saveCancelInfo(taskId, request.getCancelReason());
        }
        
        // 如果是强制完成,更新实际开始时间和结束时间
        if (newStatus == TaskStatus.COMPLETED && request.getActualStartTime() != null && request.getActualEndTime() != null) {
            SysTask task = new SysTask();
            task.setTaskId(taskId);
            task.setTaskStatus(newStatus.getCode());
            //将String转成Date
            task.setActualStartTime(DateUtils.parseDate(request.getActualStartTime()));
            task.setActualEndTime(DateUtils.parseDate(request.getActualEndTime()));
            task.setRemark(request.getRemark());
            task.setUpdateBy(SecurityUtils.getUsername());
            task.setUpdateTime(DateUtils.getNowDate());
            int result = sysTaskService.forceCompleteTask(task);
            return toAjax(result);
        }
        // 如果包含GPS位置信息,使用带位置的方法
        if (request.getLatitude() != null && request.getLongitude() != null) {
           String address= mapService.reverseGeocoding(request.getLongitude(), request.getLatitude());
           request.setLocationAddress(address);
            SysTaskLog locationLog = getLocationLog(request);
            return toAjax(sysTaskService.changeTaskStatusWithLocation(taskId, newStatus, request.getRemark(), locationLog));
        }
        return toAjax(sysTaskService.changeTaskStatus(taskId, newStatus, request.getRemark()));
    }
    private static SysTaskLog getLocationLog(ChangeStatusRequest request) {
        SysTaskLog locationLog = new SysTaskLog();
        locationLog.setLatitude(request.getLatitude());
        locationLog.setLongitude(request.getLongitude());
        locationLog.setLocationAddress(request.getLocationAddress());
        locationLog.setLocationProvince(request.getLocationProvince());
        locationLog.setLocationCity(request.getLocationCity());
        locationLog.setLocationDistrict(request.getLocationDistrict());
        locationLog.setGpsAccuracy(request.getGpsAccuracy());
        locationLog.setAltitude(request.getAltitude());
        locationLog.setSpeed(request.getSpeed());
        locationLog.setHeading(request.getHeading());
        return locationLog;
    }
    /**
@@ -290,6 +423,38 @@
    }
    /**
     * 检查任务是否可以出发(APP端)
     * 检查:
     * 1. 车辆是否有未完成的任务
     * 2. 执行人员是否有未完成的任务
     *
     * @param taskId 任务ID
     * @return 校验结果
     */
    @GetMapping("/{taskId}/check-depart")
    public AjaxResult checkTaskCanDepart(@PathVariable Long taskId) {
        return sysTaskService.checkTaskCanDepart(taskId);
    }
    /**
     * 执行人点击就绪(APP端)
     */
    @PostMapping("/{taskId}/assignee/ready")
    public AjaxResult setAssigneeReady(@PathVariable Long taskId) {
        Long userId = getUserId();
        return sysTaskService.setAssigneeReady(taskId, userId);
    }
    /**
     * 执行人取消就绪(APP端)
     */
    @PostMapping("/{taskId}/assignee/cancel-ready")
    public AjaxResult cancelAssigneeReady(@PathVariable Long taskId) {
        Long userId = getUserId();
        return sysTaskService.cancelAssigneeReady(taskId, userId);
    }
    /**
     * 分配任务请求对象
     */
    public static class AssignTaskRequest {
@@ -331,6 +496,15 @@
        private Double altitude;
        private Double speed;
        private Double heading;
        // 取消相关字段
        private String cancelReason;  // 取消原因(关联数据字典task_cancel_reason)
        // 强制完成相关字段
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
        private String actualStartTime;  // 实际开始时间
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
        private String actualEndTime;    // 实际结束时间
        public String getTaskStatus() {
            return taskStatus;
@@ -427,5 +601,156 @@
        public void setHeading(Double heading) {
            this.heading = heading;
        }
        public String getCancelReason() {
            return cancelReason;
        }
        public void setCancelReason(String cancelReason) {
            this.cancelReason = cancelReason;
        }
        public String getActualStartTime() {
            return actualStartTime;
        }
        public void setActualStartTime(String actualStartTime) {
            this.actualStartTime = actualStartTime;
        }
        public String getActualEndTime() {
            return actualEndTime;
        }
        public void setActualEndTime(String actualEndTime) {
            this.actualEndTime = actualEndTime;
        }
    }
    /**
     * 手动同步服务单到旧系统
     * 当服务单同步失败或未同步时,可以通过此接口手动触发同步
     */
    @PreAuthorize("@ss.hasPermi('task:general:edit')")
    @Log(title = "手动同步服务单", businessType = BusinessType.UPDATE)
    @PostMapping("/syncServiceOrder/{taskId}")
    public AjaxResult syncServiceOrder(@PathVariable Long taskId) {
        try {
            // 查询任务信息
            SysTask task = sysTaskService.selectSysTaskByTaskId(taskId);
            if (task == null) {
                return error("任务不存在");
            }
            // 只支持急救转运任务
            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                return error("只有急救转运任务才能同步到旧系统");
            }
            // 调用同步服务
            Long serviceOrdId = legacySystemSyncService.syncEmergencyTaskToLegacy(taskId);
            if (serviceOrdId != null && serviceOrdId > 0) {
                return success("服务单同步成功,ServiceOrdID: " + serviceOrdId);
            } else {
                return error("服务单同步失败,请查看同步错误信息");
            }
        } catch (Exception e) {
            logger.error("手动同步服务单异常,taskId: {}", taskId, e);
            return error("同步异常: " + e.getMessage());
        }
    }
    /**
     * 手动同步调度单到旧系统
     * 当调度单同步失败或未同步时,可以通过此接口手动触发同步
     */
    @PreAuthorize("@ss.hasPermi('task:general:edit')")
    @Log(title = "手动同步调度单", businessType = BusinessType.UPDATE)
    @PostMapping("/syncDispatchOrder/{taskId}")
    public AjaxResult syncDispatchOrder(@PathVariable Long taskId) {
        try {
            // 查询任务信息
            SysTask task = sysTaskService.selectSysTaskByTaskId(taskId);
            if (task == null) {
                return error("任务不存在");
            }
            // 只支持急救转运任务
            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                return error("只有急救转运任务才能同步到旧系统");
            }
            // 查询急救转运扩展信息
            SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
            if (emergency == null) {
                return error("急救转运扩展信息不存在");
            }
            // 必须先有服务单
            if (emergency.getLegacyServiceOrdId() == null || emergency.getLegacyServiceOrdId() <= 0) {
                return error("请先同步服务单");
            }
            // 调用同步服务
            Long dispatchOrdId = taskDispatchSyncService.syncDispatch(taskId);
            if (dispatchOrdId != null && dispatchOrdId > 0) {
                return success("调度单同步成功,DispatchOrdID: " + dispatchOrdId);
            } else {
                return error("调度单同步失败,请查看同步错误信息");
            }
        } catch (Exception e) {
            logger.error("手动同步调度单异常,taskId: {}", taskId, e);
            return error("同步异常: " + e.getMessage());
        }
    }
    /**
     * 手动同步任务状态到旧系统
     * 当任务状态变更后由于网络等原因未同步到旧系统时,可以通过此接口手动触发同步
     */
//    @PreAuthorize("@ss.hasPermi('task:general:edit')")
    @Log(title = "手动同步任务状态", businessType = BusinessType.UPDATE)
    @PostMapping("/syncTaskStatus/{taskId}")
    public AjaxResult syncTaskStatus(@PathVariable Long taskId) {
        try {
            // 查询任务信息
            SysTask task = sysTaskService.selectSysTaskByTaskId(taskId);
            if (task == null) {
                return error("任务不存在");
            }
            // 只支持急救转运任务
            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                return error("只有急救转运任务才能同步到旧系统");
            }
            // 查询急救转运扩展信息
            SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
            if (emergency == null) {
                return error("急救转运扩展信息不存在");
            }
            // 必须先有调度单
            if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) {
                return error("请先同步调度单,任务状态信息同步到旧系统的调度单中");
            }
            // 调用状态同步服务
            boolean success = taskStatusPushService.pushTaskStatusToLegacy(taskId);
            if (success) {
                return success("任务状态同步成功");
            } else {
                return error("任务状态同步失败,请查看日志获取详细信息");
            }
        } catch (Exception e) {
            logger.error("手动同步任务状态异常,taskId: {}", taskId, e);
            return error("同步异常: " + e.getMessage());
        }
    }
}