package com.ruoyi.web.controller.robot; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.support.CronTrigger; import org.springframework.scheduling.support.SimpleTriggerContext; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; 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.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.robot.domain.LdTask; import com.ruoyi.robot.domain.LdTaskExecutionLog; import com.ruoyi.robot.service.ILdTaskExecutionLogService; import com.ruoyi.robot.service.ILdTaskService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; /** * LD导航系统任务管理接口 * 提供任务的增删改查及定时任务执行功能 * * 接口前缀: /v1 */ @Api(tags = "LD导航系统任务管理接口") @RestController @RequestMapping("/v1") public class LdTaskController extends BaseController { @Autowired private ILdTaskService ldTaskService; @Autowired private ILdTaskExecutionLogService ldTaskExecutionLogService; /** * 1.1 获取任务列表 * GET /v1/path/list?map=地图名 */ @ApiOperation("获取任务列表") @GetMapping("/path/list") public ResponseEntity> getTaskList( @ApiParam("地图名称") @RequestParam(value = "map", required = false) String mapName) { try { Map response = new HashMap<>(); List taskList; if (mapName != null && !mapName.isEmpty()) { taskList = ldTaskService.selectLdTaskListByMapName(mapName); } else { taskList = ldTaskService.selectLdTaskList(new LdTask()); } List> paths = taskList.stream().map(task -> { Map path = new HashMap<>(); path.put("taskId", task.getId()); path.put("taskName", task.getTaskName()); path.put("status", task.getStatus()); path.put("cron", task.getCronExpression()); path.put("executeTime", task.getExecuteTime()); path.put("executeWeekdays", task.getExecuteWeekdays()); path.put("repeatCount", task.getRepeatCount()); // 解析目标点坐标 if (task.getWaypointCoords() != null && !task.getWaypointCoords().isEmpty()) { try { path.put("coord", JSON.parse(task.getWaypointCoords())); } catch (Exception e) { path.put("coord", new java.util.ArrayList<>()); } } else { path.put("coord", new java.util.ArrayList<>()); } // 解析目标点类型 if (task.getWaypointTypes() != null && !task.getWaypointTypes().isEmpty()) { try { path.put("plan", JSON.parse(task.getWaypointTypes())); } catch (Exception e) { path.put("plan", new java.util.ArrayList<>()); } } else { path.put("plan", new java.util.ArrayList<>()); } // 解析目标点动作 if (task.getWaypointActions() != null && !task.getWaypointActions().isEmpty()) { try { path.put("action", JSON.parse(task.getWaypointActions())); } catch (Exception e) { path.put("action", new java.util.ArrayList<>()); } } else { path.put("action", new java.util.ArrayList<>()); } path.put("map", task.getMapName()); path.put("lastExecuteTime", task.getLastExecuteTime()); path.put("totalExecuteCount", task.getTotalExecuteCount()); return path; }).collect(Collectors.toList()); response.put("status", true); response.put("paths", paths); response.put("total", paths.size()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("获取任务列表异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.2 获取任务详情 * GET /v1/path?map=地图名&path=任务名 */ @ApiOperation("获取任务详情") @GetMapping("/path") public ResponseEntity> getTask( @ApiParam("地图名称") @RequestParam("map") String mapName, @ApiParam("任务名称") @RequestParam("path") String taskName) { try { LdTask task = ldTaskService.selectLdTaskByMapAndName(mapName, taskName); if (task == null) { return buildErrorResponse(2, "任务不存在"); } Map response = new HashMap<>(); response.put("status", true); response.put("taskId", task.getId()); response.put("taskName", task.getTaskName()); response.put("taskDesc", task.getTaskDesc()); response.put("status", task.getStatus()); response.put("cron", task.getCronExpression()); response.put("executeTime", task.getExecuteTime()); response.put("executeWeekdays", task.getExecuteWeekdays()); response.put("repeatCount", task.getRepeatCount()); response.put("coord_type", task.getCoordType()); response.put("map", task.getMapName()); // 解析目标点坐标 if (task.getWaypointCoords() != null && !task.getWaypointCoords().isEmpty()) { response.put("coord", JSON.parse(task.getWaypointCoords())); } else { response.put("coord", new java.util.ArrayList<>()); } // 解析目标点类型 if (task.getWaypointTypes() != null && !task.getWaypointTypes().isEmpty()) { response.put("plan", JSON.parse(task.getWaypointTypes())); } else { response.put("plan", new java.util.ArrayList<>()); } // 解析目标点动作 if (task.getWaypointActions() != null && !task.getWaypointActions().isEmpty()) { response.put("action", JSON.parse(task.getWaypointActions())); } else { response.put("action", new java.util.ArrayList<>()); } // 解析目标点ID if (task.getWaypointIds() != null && !task.getWaypointIds().isEmpty()) { response.put("waypointIds", JSON.parse(task.getWaypointIds())); } else { response.put("waypointIds", new java.util.ArrayList<>()); } response.put("lastExecuteTime", task.getLastExecuteTime()); response.put("lastExecuteStatus", task.getLastExecuteStatus()); response.put("nextExecuteTime", task.getNextExecuteTime()); response.put("totalExecuteCount", task.getTotalExecuteCount()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("获取任务详情异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.3 创建任务 * POST /v1/path */ @ApiOperation("创建任务") @PostMapping("/path") public ResponseEntity> createTask(@RequestBody JSONObject taskData) { try { String mapName = taskData.getString("map"); String pathName = taskData.getString("path"); if (mapName == null || mapName.isEmpty() || pathName == null || pathName.isEmpty()) { return buildErrorResponse(1, "请求参数不合法:缺少map或path参数"); } // 检查任务是否已存在 LdTask existingTask = ldTaskService.selectLdTaskByMapAndName(mapName, pathName); if (existingTask != null) { return buildErrorResponse(2, "任务已存在"); } // 构建任务对象 LdTask task = new LdTask(); task.setMapName(mapName); task.setTaskName(pathName); task.setTaskDesc(taskData.getString("desc")); task.setCronExpression(taskData.getString("cron")); task.setExecuteTime(taskData.getString("executeTime")); task.setExecuteWeekdays(taskData.getString("executeWeekdays")); task.setRepeatCount(taskData.getInteger("repeate") != null ? taskData.getInteger("repeate") : 1); task.setCoordType(taskData.getString("coord_type") != null ? taskData.getString("coord_type") : "local"); task.setStatus("idle"); task.setTotalExecuteCount(0); // 保存目标点坐标 Object coordObj = taskData.get("coord"); if (coordObj != null) { task.setWaypointCoords(JSON.toJSONString(coordObj)); } // 保存目标点类型 Object planObj = taskData.get("plan"); if (planObj != null) { task.setWaypointTypes(JSON.toJSONString(planObj)); } // 保存目标点动作 Object actionObj = taskData.get("action"); if (actionObj != null) { task.setWaypointActions(JSON.toJSONString(actionObj)); } // 保存目标点ID Object waypointIdsObj = taskData.get("waypointIds"); if (waypointIdsObj != null) { task.setWaypointIds(JSON.toJSONString(waypointIdsObj)); } // 计算下次执行时间 if (task.getCronExpression() != null && !task.getCronExpression().isEmpty()) { task.setNextExecuteTime(calculateNextExecuteTime(task.getCronExpression())); } int result = ldTaskService.insertLdTask(task); Map response = new HashMap<>(); if (result > 0) { response.put("status", true); response.put("taskId", task.getId()); response.put("msg", "任务创建成功"); } else { response.put("status", false); response.put("msg", "任务创建失败"); } return ResponseEntity.ok(response); } catch (Exception e) { logger.error("创建任务异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.4 更新任务 * PUT /v1/path */ @ApiOperation("更新任务") @PutMapping("/path") public ResponseEntity> updateTask(@RequestBody JSONObject taskData) { try { Long taskId = taskData.getLong("taskId"); String mapName = taskData.getString("map"); String pathName = taskData.getString("path"); if (taskId == null && (mapName == null || mapName.isEmpty() || pathName == null || pathName.isEmpty())) { return buildErrorResponse(1, "请求参数不合法:缺少taskId或map/path参数"); } LdTask task; if (taskId != null) { task = ldTaskService.selectLdTaskById(taskId); } else { task = ldTaskService.selectLdTaskByMapAndName(mapName, pathName); } if (task == null) { return buildErrorResponse(2, "任务不存在"); } // 更新字段 if (taskData.containsKey("taskName")) { String newTaskName = taskData.getString("taskName"); if (!newTaskName.equals(task.getTaskName())) { // 检查新名称是否已存在 LdTask existingTask = ldTaskService.selectLdTaskByMapAndName(task.getMapName(), newTaskName); if (existingTask != null) { return buildErrorResponse(2, "任务名称已存在"); } task.setTaskName(newTaskName); } } task.setTaskDesc(taskData.getString("desc")); task.setCronExpression(taskData.getString("cron")); task.setExecuteTime(taskData.getString("executeTime")); task.setExecuteWeekdays(taskData.getString("executeWeekdays")); if (taskData.containsKey("repeate")) { task.setRepeatCount(taskData.getInteger("repeate")); } // 更新目标点数据 Object coordObj = taskData.get("coord"); if (coordObj != null) { task.setWaypointCoords(JSON.toJSONString(coordObj)); } Object planObj = taskData.get("plan"); if (planObj != null) { task.setWaypointTypes(JSON.toJSONString(planObj)); } Object actionObj = taskData.get("action"); if (actionObj != null) { task.setWaypointActions(JSON.toJSONString(actionObj)); } Object waypointIdsObj = taskData.get("waypointIds"); if (waypointIdsObj != null) { task.setWaypointIds(JSON.toJSONString(waypointIdsObj)); } // 重新计算下次执行时间 if (task.getCronExpression() != null && !task.getCronExpression().isEmpty()) { task.setNextExecuteTime(calculateNextExecuteTime(task.getCronExpression())); } int result = ldTaskService.updateLdTask(task); Map response = new HashMap<>(); response.put("status", result > 0); response.put("msg", result > 0 ? "任务更新成功" : "任务更新失败"); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("更新任务异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.5 删除任务 * DELETE /v1/path */ @ApiOperation("删除任务") @DeleteMapping("/path") public ResponseEntity> deleteTask(@RequestBody JSONObject params) { try { String mapName = params.getString("map"); String taskName = params.getString("path"); Long taskId = params.getLong("taskId"); if (taskId == null && (mapName == null || taskName == null)) { return buildErrorResponse(1, "请求参数不合法:缺少taskId或map/path参数"); } LdTask task; if (taskId != null) { task = ldTaskService.selectLdTaskById(taskId); } else { task = ldTaskService.selectLdTaskByMapAndName(mapName, taskName); } if (task == null) { return buildErrorResponse(2, "任务不存在"); } int result = ldTaskService.deleteLdTaskById(task.getId()); Map response = new HashMap<>(); response.put("status", result > 0); response.put("msg", result > 0 ? "任务删除成功" : "任务删除失败"); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("删除任务异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.6 更新任务状态 * PUT /v1/path/status */ @ApiOperation("更新任务状态") @PutMapping("/path/status") public ResponseEntity> updateTaskStatus( @ApiParam("任务ID") @RequestParam("taskId") Long taskId, @ApiParam("新状态") @RequestParam("status") String status) { try { LdTask task = ldTaskService.selectLdTaskById(taskId); if (task == null) { return buildErrorResponse(2, "任务不存在"); } int result = ldTaskService.updateTaskStatus(taskId, status); Map response = new HashMap<>(); response.put("status", result > 0); response.put("msg", result > 0 ? "状态更新成功" : "状态更新失败"); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("更新任务状态异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.7 获取任务执行记录 * GET /v1/path/logs */ @ApiOperation("获取任务执行记录") @GetMapping("/path/logs") public ResponseEntity> getTaskLogs( @ApiParam("任务ID") @RequestParam(value = "taskId", required = false) Long taskId, @ApiParam("设备ID") @RequestParam(value = "deviceId", required = false) String deviceId, @ApiParam("地图名称") @RequestParam(value = "map", required = false) String mapName) { try { LdTaskExecutionLog logQuery = new LdTaskExecutionLog(); if (taskId != null) { logQuery.setTaskId(taskId); } if (deviceId != null) { logQuery.setDeviceId(deviceId); } if (mapName != null) { logQuery.setMapName(mapName); } List logs = ldTaskExecutionLogService.selectLdTaskExecutionLogList(logQuery); List> logList = logs.stream().map(log -> { Map logMap = new HashMap<>(); logMap.put("id", log.getId()); logMap.put("taskId", log.getTaskId()); logMap.put("taskName", log.getTaskName()); logMap.put("mapName", log.getMapName()); logMap.put("executeTime", log.getExecuteTime()); logMap.put("endTime", log.getEndTime()); logMap.put("status", log.getStatus()); logMap.put("startWaypoint", log.getStartWaypoint()); logMap.put("endWaypoint", log.getEndWaypoint()); logMap.put("completedWaypoints", log.getCompletedWaypoints()); logMap.put("totalWaypoints", log.getTotalWaypoints()); logMap.put("errorCode", log.getErrorCode()); logMap.put("errorMessage", log.getErrorMessage()); logMap.put("deviceId", log.getDeviceId()); return logMap; }).collect(Collectors.toList()); Map response = new HashMap<>(); response.put("status", true); response.put("logs", logList); response.put("total", logList.size()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("获取任务执行记录异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 1.8 获取设备今日执行记录 * GET /v1/path/logs/today */ @ApiOperation("获取设备今日执行记录") @GetMapping("/path/logs/today") public ResponseEntity> getTodayExecutionLogs( @ApiParam("设备ID") @RequestParam("deviceId") String deviceId) { try { List logs = ldTaskExecutionLogService.selectTodayExecutionLogsByDeviceId(deviceId); Map response = new HashMap<>(); response.put("status", true); response.put("logs", logs); response.put("total", logs.size()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("获取今日执行记录异常", e); return buildErrorResponse(4, "内部错误: " + e.getMessage()); } } /** * 辅助方法:根据Cron表达式计算下次执行时间 */ private java.util.Date calculateNextExecuteTime(String cronExpression) { try { CronTrigger cronTrigger = new CronTrigger(cronExpression); SimpleTriggerContext triggerContext = new SimpleTriggerContext(); return cronTrigger.nextExecutionTime(triggerContext); } catch (Exception e) { logger.warn("解析Cron表达式失败: {}", cronExpression, e); return null; } } /** * 构建错误响应 */ private ResponseEntity> buildErrorResponse(int code, String msg) { Map response = new HashMap<>(); response.put("status", false); response.put("code", code); response.put("msg", msg); return ResponseEntity.ok(response); } }