重构任务接口展示无人车实际任务信息

- 移除内存任务库,改为从 activeMovingObjectsCache 获取无人车任务数据
- 新增 DataCollectorService.getActiveMovingObjectsCache() 公共方法
- 修复 missionStatus 空指针异常,添加空值检查
- 支持按任务状态筛选和分页查询
- 返回完整的任务上下文信息(任务ID、类型、状态、进度、路径点等)
- 修正 getObjectType() 方法调用
This commit is contained in:
shan 2026-01-23 09:19:18 +08:00
parent 8347eae959
commit b23ca99916
2 changed files with 143 additions and 78 deletions

View File

@ -3,18 +3,18 @@ package com.qaup.collision.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.qaup.common.constant.HttpStatus;
import com.qaup.common.core.domain.AjaxResult;
import com.qaup.collision.task.InMemoryTaskStore;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import com.qaup.collision.common.model.MovingObject;
import com.qaup.collision.common.model.UnmannedVehicle;
import com.qaup.collision.datacollector.service.DataCollectorService;
import com.qaup.collision.datacollector.service.VehicleManagerCacheService;
import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@RestController
@ -23,30 +23,107 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class VehicleTaskController {
private final InMemoryTaskStore taskStore;
private final VehicleManagerCacheService cacheService;
private final DataCollectorService dataCollectorService;
@Data
public static class TaskUpsertRequest {
@NotBlank
private String name;
@Builder
public static class VehicleTaskDTO {
private String vehicleId;
private String vehicleType;
private String missionId;
private String missionType;
private String missionStatus;
private Long missionStartTime;
private Long estimatedEndTime;
private Double progress;
private Double totalMileage;
private List<WaypointDTO> waypoints;
private Long lastSeenAt;
}
@NotBlank
private String type;
private Integer priority;
private JsonNode payload;
@Data
@Builder
public static class WaypointDTO {
private String waypointId;
private Double latitude;
private Double longitude;
private String status;
}
@GetMapping
public AjaxResult list(@RequestParam(required = false, defaultValue = "1") int pageNum,
@RequestParam(required = false, defaultValue = "10") int pageSize) {
List<InMemoryTaskStore.Task> all = taskStore.listAll();
int total = all.size();
@RequestParam(required = false, defaultValue = "10") int pageSize,
@RequestParam(required = false) String status) {
Map<String, MovingObject> activeMovingObjectsCache = dataCollectorService.getActiveMovingObjectsCache();
List<VehicleTaskDTO> allTasks = new ArrayList<>();
for (MovingObject movingObject : activeMovingObjectsCache.values()) {
if (!(movingObject instanceof UnmannedVehicle vehicle)) {
continue;
}
String vehicleId = vehicle.getObjectId();
String missionId = vehicle.getMissionId();
// 如果没有任务ID跳过
if (missionId == null || missionId.isBlank()) {
continue;
}
String missionStatus = vehicle.getMissionStatus() != null ? vehicle.getMissionStatus().name() : "UNKNOWN";
// 状态筛选
if (status != null && !status.isEmpty() && !status.equalsIgnoreCase(missionStatus)) {
continue;
}
// 获取车辆类型
String vehicleType = vehicle.getObjectType().name();
// 获取路径点
List<WaypointDTO> waypoints = new ArrayList<>();
if (vehicle.getWaypoints() != null) {
for (UnmannedVehicle.WaypointInfo wp : vehicle.getWaypoints()) {
WaypointDTO waypoint = WaypointDTO.builder()
.waypointId(wp.getWaypointId())
.latitude(wp.getLatitude())
.longitude(wp.getLongitude())
.status(wp.getStatus().name())
.build();
waypoints.add(waypoint);
}
}
VehicleTaskDTO task = VehicleTaskDTO.builder()
.vehicleId(vehicleId)
.vehicleType(vehicleType)
.missionId(missionId)
.missionType(vehicle.getMissionType())
.missionStatus(missionStatus)
.missionStartTime(vehicle.getMissionStartTime())
.estimatedEndTime(vehicle.getEstimatedEndTime())
.progress(vehicle.getProgress())
.totalMileage(vehicle.getTotalMileage())
.waypoints(waypoints)
.lastSeenAt(null) // 暂时设为null后续可以从缓存获取
.build();
allTasks.add(task);
}
// 按任务开始时间倒序排序
allTasks.sort((a, b) -> {
if (a.getMissionStartTime() == null && b.getMissionStartTime() == null) return 0;
if (a.getMissionStartTime() == null) return 1;
if (b.getMissionStartTime() == null) return -1;
return Long.compare(b.getMissionStartTime(), a.getMissionStartTime());
});
int total = allTasks.size();
int fromIndex = Math.max(0, (pageNum - 1) * pageSize);
int toIndex = Math.min(total, fromIndex + pageSize);
List<InMemoryTaskStore.Task> page = fromIndex >= total ? List.of() : all.subList(fromIndex, toIndex);
List<VehicleTaskDTO> page = fromIndex >= total ? List.of() : allTasks.subList(fromIndex, toIndex);
Map<String, Object> data = new HashMap<>();
data.put("total", total);
@ -57,69 +134,50 @@ public class VehicleTaskController {
return AjaxResult.success(data).put("timestamp", System.currentTimeMillis());
}
@GetMapping("/{id}")
public AjaxResult get(@PathVariable long id) {
InMemoryTaskStore.Task task = taskStore.get(id);
if (task == null) {
return AjaxResult.error(HttpStatus.NOT_FOUND, "任务不存在").put("timestamp", System.currentTimeMillis());
@GetMapping("/{vehicleId}")
public AjaxResult get(@PathVariable String vehicleId) {
Map<String, MovingObject> activeMovingObjectsCache = dataCollectorService.getActiveMovingObjectsCache();
MovingObject movingObject = activeMovingObjectsCache.get(vehicleId);
if (!(movingObject instanceof UnmannedVehicle vehicle)) {
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆不存在或无任务").put("timestamp", System.currentTimeMillis());
}
return AjaxResult.success(task).put("timestamp", System.currentTimeMillis());
}
@PostMapping
public AjaxResult create(@Valid @RequestBody TaskUpsertRequest request) {
InMemoryTaskStore.Task task = taskStore.create(
request.getName(),
request.getType(),
request.getPriority(),
request.getPayload()
);
return AjaxResult.success(task).put("timestamp", System.currentTimeMillis());
}
String missionId = vehicle.getMissionId();
@PutMapping("/{id}")
public AjaxResult update(@PathVariable long id, @Valid @RequestBody TaskUpsertRequest request) {
InMemoryTaskStore.Task task = taskStore.update(
id,
request.getName(),
request.getType(),
request.getPriority(),
request.getPayload()
);
if (task == null) {
return AjaxResult.error(HttpStatus.NOT_FOUND, "任务不存在").put("timestamp", System.currentTimeMillis());
if (missionId == null || missionId.isBlank()) {
return AjaxResult.error(HttpStatus.NOT_FOUND, "车辆无任务").put("timestamp", System.currentTimeMillis());
}
return AjaxResult.success(task).put("timestamp", System.currentTimeMillis());
}
@DeleteMapping("/{ids}")
public AjaxResult delete(@PathVariable String ids) {
List<Long> idList = parseIds(ids);
int removed = taskStore.deleteMany(idList);
String vehicleType = vehicle.getObjectType().name();
Map<String, Object> data = new HashMap<>();
data.put("removed", removed);
data.put("requested", idList.size());
return AjaxResult.success(data).put("timestamp", System.currentTimeMillis());
}
private List<Long> parseIds(String ids) {
if (ids == null || ids.isBlank()) {
return List.of();
List<WaypointDTO> waypoints = new ArrayList<>();
if (vehicle.getWaypoints() != null) {
for (UnmannedVehicle.WaypointInfo wp : vehicle.getWaypoints()) {
WaypointDTO waypoint = WaypointDTO.builder()
.waypointId(wp.getWaypointId())
.latitude(wp.getLatitude())
.longitude(wp.getLongitude())
.status(wp.getStatus().name())
.build();
waypoints.add(waypoint);
}
}
return List.of(ids.split(","))
.stream()
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(s -> {
try {
return Long.parseLong(s);
} catch (NumberFormatException e) {
return null;
}
})
.filter(v -> v != null)
.collect(Collectors.toList());
VehicleTaskDTO task = VehicleTaskDTO.builder()
.vehicleId(vehicleId)
.vehicleType(vehicleType)
.missionId(missionId)
.missionType(vehicle.getMissionType())
.missionStatus(vehicle.getMissionStatus() != null ? vehicle.getMissionStatus().name() : "UNKNOWN")
.missionStartTime(vehicle.getMissionStartTime())
.estimatedEndTime(vehicle.getEstimatedEndTime())
.progress(vehicle.getProgress())
.totalMileage(vehicle.getTotalMileage())
.waypoints(waypoints)
.lastSeenAt(null) // 暂时设为null
.build();
return AjaxResult.success(task).put("timestamp", System.currentTimeMillis());
}
}

View File

@ -108,6 +108,13 @@ public class DataCollectorService {
// 用于缓存所有活跃的MovingObject的最新状态
private final Map<String, MovingObject> activeMovingObjectsCache = new ConcurrentHashMap<>();
/**
* 获取活跃的移动对象缓存供外部访问
*/
public Map<String, MovingObject> getActiveMovingObjectsCache() {
return activeMovingObjectsCache;
}
// 航班通知缓存Key=flightNo:type, Value=最新的航班通知
private final Map<String, FlightNotification> flightNotificationCache = new ConcurrentHashMap<>();