ard-admin/src/main/java/com/ard/web/controller/sample/wayline/WaylineTrajectoryController.java
New file @@ -0,0 +1,40 @@ package com.ard.web.controller.sample.wayline; import com.ard.sample.common.model.ResponseResult; import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO; import com.ard.sample.manage.service.IWaylineTrajectoryService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Optional; @Api(tags = "航线历史任务轨迹") @RequestMapping("/dock/waylineTrajectory") @RestController public class WaylineTrajectoryController { @Autowired private IWaylineTrajectoryService _waylineTrajectoryService; @ApiOperation("获取航线任务轨迹") @GetMapping("/flight-id") public ResponseResult<WaylineTrajectoryDTO> getJob(@RequestParam(name = "job_id") String jobId) { try { if(jobId == null){ return ResponseResult.error(98,"任务ID不能为空"); } WaylineTrajectoryDTO waylineJobDTO = _waylineTrajectoryService.getWayLineTrajectorybyJobID(jobId); if(waylineJobDTO==null) { return ResponseResult.error(99,"任务不存在"); } return ResponseResult.success(waylineJobDTO); } catch (Exception e) { return ResponseResult.error(97, "获取航线轨迹发生异常:"+e.getMessage()); } } } ard-sample/src/main/java/com/ard/sample/manage/mapper/IWaylineTrajectoryMapper.java
New file @@ -0,0 +1,12 @@ package com.ard.sample.manage.mapper; import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Select; import java.util.List; public interface IWaylineTrajectoryMapper extends BaseMapper<WaylineTrajectoryEntity> { } ard-sample/src/main/java/com/ard/sample/manage/model/dto/WaylineTrajectoryDTO.java
New file @@ -0,0 +1,69 @@ package com.ard.sample.manage.model.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor @Builder public class WaylineTrajectoryDTO { /** * 主建 * */ private Integer id; /** * 计划任务id * */ private String jobId; /** * 计划任务名称 * */ private String name; /** * 用于此任务的航线文件id。 * */ private String fileId; /** * 航线文件名称 * */ private String fileName; /** * 执行此任务的机场sn。 * */ private String dockSn; /** * 进度为ok时,为一次轨迹的结束 * */ private String progress; /** * 创建时间 * */ private Long createTime; /** * 更新时间 * */ private Long updateTime; /** * 飞行轨迹list * */ private List<String> trajectoryList; /** * 任务状态list * */ private List<String> taskList; } ard-sample/src/main/java/com/ard/sample/manage/model/entity/WaylineTrajectoryEntity.java
New file @@ -0,0 +1,83 @@ package com.ard.sample.manage.model.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @Builder @NoArgsConstructor @AllArgsConstructor @TableName(value = "wayline_trajectory") public class WaylineTrajectoryEntity implements Serializable { /** * 主建 * */ @TableId(type = IdType.AUTO) private Integer id; /** * 计划任务id * */ @TableField(value = "job_id") private String jobId; /** * 计划任务名称 * */ @TableField("name") private String name; /** * 用于此任务的航线文件id。 * */ @TableField("file_id") private String fileId; /** * 航线文件名称 * */ @TableField("file_name") private String fileName; /** * 执行此任务的机场sn。 * */ @TableField("dock_sn") private String dockSn; /** * 进度为ok时,为一次轨迹的结束 * */ @TableField("progress") private String progress; /** * 创建时间 * */ @TableField(value = "create_time", fill = FieldFill.INSERT) private Long createTime; /** * 更新时间 * */ @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) private Long updateTime; /** * 飞行轨迹list * */ @TableField("trajectory_list") private byte[] trajectoryList; /** * 任务状态list * */ @TableField("task_list") private byte[] taskList; } ard-sample/src/main/java/com/ard/sample/manage/service/IWaylineTrajectoryService.java
New file @@ -0,0 +1,24 @@ package com.ard.sample.manage.service; import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO; import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity; import java.util.List; public interface IWaylineTrajectoryService { /** * 增加list数据,type为:0时,表示轨迹点列表;type为:1时,表示任务状态数据。 * @param sn 设备序列号 * @param type 类型 * @param dataJson json数据 * */ void setList(String sn, String type, String dataJson); /** * 返回航线轨迹完整的数据,拼接的轨迹点列表和任务状态数据。 * @param jobId 任务ID * @return 航线轨迹完整的数据 * */ WaylineTrajectoryDTO getWayLineTrajectorybyJobID(String jobId); } ard-sample/src/main/java/com/ard/sample/manage/service/impl/DeviceOSDServiceImpl.java
@@ -17,6 +17,7 @@ import com.ard.sample.manage.model.receiver.OsdPayloadReceiver; import com.ard.sample.manage.model.receiver.OsdSubDeviceReceiver; import com.ard.sample.manage.service.IDeviceService; import com.ard.sample.manage.service.IWaylineTrajectoryService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -41,6 +42,9 @@ @Autowired private IDeviceService _deviceService; @Autowired private IWaylineTrajectoryService _waylineTrajectoryService; @Autowired private DockWebSocketHandler _dockWebSocketHandler; @@ -118,6 +122,9 @@ // 发送给websocket客户端 _dockWebSocketHandler.sendMessageToSubscribers(device.getDeviceSn(), MessageType.STATUS.getType(), dockOsd, ""); // 将飞行器的OSD数据dockOsd入库; _waylineTrajectoryService.setList(device.getDeviceSn(),"0", dockOsd); sendMessageService.sendBatch(webSessions, wsMessage); this.pushTelemetryData(data, device.getDeviceSn()); } ard-sample/src/main/java/com/ard/sample/manage/service/impl/WaylineTrajectoryServiceImpl.java
New file @@ -0,0 +1,213 @@ package com.ard.sample.manage.service.impl; import cn.hutool.core.util.SerializeUtil; import com.ard.common.core.text.Convert; import com.ard.sample.component.mqtt.model.EventsReceiver; import com.ard.sample.manage.mapper.IWaylineTrajectoryMapper; import com.ard.sample.manage.model.dto.WaylineTrajectoryDTO; import com.ard.sample.manage.model.entity.WaylineTrajectoryEntity; import com.ard.sample.manage.service.IWaylineTrajectoryService; import com.ard.sample.wayline.model.dto.WaylineJobDTO; import com.ard.sample.wayline.model.dto.WaylineTaskProgressReceiver; import com.ard.sample.wayline.service.IWaylineJobService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @Service @Slf4j public class WaylineTrajectoryServiceImpl implements IWaylineTrajectoryService { @Resource private IWaylineTrajectoryMapper _waylineTrajectoryMapper; @Autowired private IWaylineJobService _waylineJobService; @Autowired protected ObjectMapper mapper; /** * 轨迹点列表缓存 */ private final ConcurrentHashMap<String, List<String>> cacheTrajectoryMap = new ConcurrentHashMap<>(); /** * 任务状态数据缓存 */ private final ConcurrentHashMap<String, List<String>> cacheTaskMap = new ConcurrentHashMap<>(); /** * 给数据加个进度 */ private final ConcurrentHashMap<String, String> cacheProgress = new ConcurrentHashMap<>(); /** * 分片保存阈值条数 */ private static final int CHUNK_SIZE = 300; /** * 增加list数据,type为:0时,表示轨迹点列表;type为:1时,表示任务状态数据。 * @param sn 设备序列号 * @param type 类型 * @param dataJson json数据 */ @Override public void setList(String sn, String type, String dataJson) { List<String> listTrajectory = cacheTrajectoryMap.computeIfAbsent(sn, k -> new ArrayList<>()); List<String> listTask = cacheTaskMap.computeIfAbsent(sn, k -> new ArrayList<>()); String progress = cacheProgress.computeIfAbsent(sn, k -> "0"); // 取进度值,就为了判断ok一个任务的结束 Integer pro = Convert.toInt(cacheProgress.get(sn)); // 取jobid、status字段值 String jobId = ""; String isOK = ""; if (type.equals("0")) { // 飞行轨迹数据 listTrajectory.add(dataJson); log.info("轨迹点数据添加到列表缓存,当前列表数量:{}", listTrajectory.size()); } if (type.equals("1")) { // 任务状态数据 listTask.add(dataJson); log.info("任务状态数据添加到列表缓存,当前列表数量:{}", listTask.size()); } // jobid、status字段赋值 if (!listTask.isEmpty()) { String json = listTask.get(listTask.size() - 1); EventsReceiver<WaylineTaskProgressReceiver> eventsReceiver = mapper.convertValue(json, new TypeReference<EventsReceiver<WaylineTaskProgressReceiver>>() { }); jobId = eventsReceiver.getOutput().getExt().getFlightId(); isOK = eventsReceiver.getOutput().getStatus(); log.info("当前任务jobId:{},任务执行进度isOK:{}", jobId, isOK); } if (listTrajectory.size() >= CHUNK_SIZE || listTask.size() >= CHUNK_SIZE) { progress = Convert.toStr(pro + 1); // 分片保存 save(sn, jobId); log.info("当前任务保存成功,jobId:{},进度:{}",jobId , progress); } else { // 判断任务状态json中的status字段,如果为OK,则保存数据,一条完整的航线数据结束。 try { if (isOK.equals("ok")) { progress = "ok"; if (getWaylineTrajectoryByProgress(jobId, progress)) { log.info("当前任务已完成,不再保存数据!jobId:{},progress:{}", jobId, progress); return; } save(sn, jobId); log.info("当前任务保存成功,jobId:{},进度:{}",jobId , progress); } } catch (Exception e) { log.error("json解析异常!{}", e.getMessage()); } } } @Async public void save(String sn, String JobId) { List<String> trajectoryList = cacheTrajectoryMap.get(sn); List<String> taskList = cacheTaskMap.get(sn); String progress = cacheProgress.get(sn); if (trajectoryList.isEmpty() && taskList.isEmpty()) { return; } try { byte[] blobTrajectory = SerializeUtil.serialize(trajectoryList); byte[] blobTask = SerializeUtil.serialize(taskList); Optional<WaylineJobDTO> waylineJobDTO = _waylineJobService.getJobByJobId(JobId); WaylineTrajectoryEntity TrajectoryEntity = new WaylineTrajectoryEntity(); TrajectoryEntity.setJobId(JobId); TrajectoryEntity.setName(waylineJobDTO.get().getJobName()); TrajectoryEntity.setFileId(waylineJobDTO.get().getFileId()); TrajectoryEntity.setFileName(waylineJobDTO.get().getFileName()); TrajectoryEntity.setDockSn(sn); TrajectoryEntity.setProgress(progress); TrajectoryEntity.setCreateTime(System.currentTimeMillis()); TrajectoryEntity.setUpdateTime(System.currentTimeMillis()); TrajectoryEntity.setTrajectoryList(blobTrajectory); TrajectoryEntity.setTaskList(blobTask); // 保存轨迹点列表数据 int i = _waylineTrajectoryMapper.insert(TrajectoryEntity); if (i > 0) { log.info("保存轨迹点列表数据成功!jobId:{}", JobId); // 清空缓存 cacheTrajectoryMap.put(sn, new ArrayList<>()); cacheTaskMap.put(sn, new ArrayList<>()); if (progress.equals("ok")) { cacheProgress.put(sn, "0"); } } } catch (Exception e) { log.error("保存轨迹点列表数据失败!jobId:{}.{}", JobId, e.getMessage()); } } /** * 返回航线轨迹完整的数据,拼接的轨迹点列表和任务状态数据。 * * @param jobId 任务ID * @return 航线轨迹完整的数据 */ @Override public WaylineTrajectoryDTO getWayLineTrajectorybyJobID(String jobId) { List<WaylineTrajectoryEntity> waylineTrajectoryEntityList = new ArrayList<>(_waylineTrajectoryMapper.selectList(new LambdaQueryWrapper<WaylineTrajectoryEntity>() .eq(jobId != null, WaylineTrajectoryEntity::getJobId, jobId) .orderByAsc(WaylineTrajectoryEntity::getId))); return TrajectoryEntityConvertToDTO(waylineTrajectoryEntityList); } /** * 根据作业ID和进度获取航线轨迹 * * @param jobId 作业ID,可为null * @param progress 进度值,可为null * @return 当存在符合条件的航线轨迹时返回true,否则返回false */ public Boolean getWaylineTrajectoryByProgress(String jobId, String progress) { List<WaylineTrajectoryEntity> waylineTrajectoryEntityList = new ArrayList<>(_waylineTrajectoryMapper.selectList(new LambdaQueryWrapper<WaylineTrajectoryEntity>() .eq(jobId != null, WaylineTrajectoryEntity::getJobId, jobId) .eq(progress != null, WaylineTrajectoryEntity::getProgress, progress) .orderByAsc(WaylineTrajectoryEntity::getId))); return !waylineTrajectoryEntityList.isEmpty(); } public WaylineTrajectoryDTO TrajectoryEntityConvertToDTO(List<WaylineTrajectoryEntity> entity) { if (entity == null) { return null; } WaylineTrajectoryDTO dto = new WaylineTrajectoryDTO(); dto.setId(entity.get(0).getId()); dto.setJobId(entity.get(0).getJobId()); dto.setName(entity.get(0).getName()); dto.setFileId(entity.get(0).getFileId()); dto.setFileName(entity.get(0).getFileName()); dto.setDockSn(entity.get(0).getDockSn()); dto.setProgress(entity.get(0).getProgress()); dto.setCreateTime(entity.get(0).getCreateTime()); dto.setUpdateTime(entity.get(0).getUpdateTime()); for (WaylineTrajectoryEntity e : entity) { dto.getTrajectoryList().addAll(SerializeUtil.deserialize(e.getTrajectoryList(), List.class)); dto.getTaskList().addAll(SerializeUtil.deserialize(e.getTaskList(), List.class)); } return dto; } } ard-sample/src/main/java/com/ard/sample/wayline/mapper/IWaylineJobHistoryMapper.java
New file @@ -0,0 +1,10 @@ package com.ard.sample.wayline.mapper; import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * 任务历史信息 * */ public interface IWaylineJobHistoryMapper extends BaseMapper<WaylineJobHistoryEntity> { } ard-sample/src/main/java/com/ard/sample/wayline/model/entity/WaylineJobHistoryEntity.java
New file @@ -0,0 +1,94 @@ package com.ard.sample.wayline.model.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @Builder @NoArgsConstructor @AllArgsConstructor @TableName("wayline_job_history") public class WaylineJobHistoryEntity implements Serializable { @TableId(type = IdType.AUTO) private Integer id; @TableField("job_id") private String jobId; @TableField("name") private String name; @TableField("file_id") private String fileId; @TableField("file_name") private String filename; @TableField("dock_sn") private String dockSn; @TableField("workspace_id") private String workspaceId; @TableField("task_type") private Integer taskType; @TableField("wayline_type") private Integer waylineType; @TableField("username") private String username; /** * 实际开始时间 * */ @TableField("execute_time") private Long executeTime; /** * 计划结束时间 * */ @TableField("end_time") private Long endTime; @TableField("error_code") private Integer errorCode; @TableField("status") private Integer status; @TableField("rth_altitude") private Integer rthAltitude; @TableField("rth_mode") private Integer rthMode; @TableField("out_of_control") private Integer outOfControlAction; @TableField("media_count") private Integer mediaCount; @TableField(value = "create_time", fill = FieldFill.INSERT) private Long createTime; @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) private Long updateTime; @TableField("begin_time") private Long beginTime; @TableField("completed_time") private Long completedTime; @TableField("parent_id") private String parentId; @TableField("loop_sum") private Integer loopSum; } ard-sample/src/main/java/com/ard/sample/wayline/service/IWaylineJobHistoryService.java
New file @@ -0,0 +1,57 @@ package com.ard.sample.wayline.service; import com.ard.sample.common.model.PaginationData; import com.ard.sample.wayline.model.dto.WaylineJobDTO; import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity; import java.util.Optional; /** * 计划库历史表 * */ public interface IWaylineJobHistoryService { /** * 在数据库中创建任务历史数据。 * @param entity * @return */ Optional<WaylineJobDTO> createWaylineJob(WaylineJobHistoryEntity entity); /** * 更新历史数据任务数据。 * @param dto * @return */ Boolean updateJob(WaylineJobDTO dto); /** * 查询历史任务列表 * @param page * @param pageSize * @param status * @param startTime * @param endTime * @param taskType * @param name * @param isComplete * */ PaginationData<WaylineJobDTO> getJobsList(long page, long pageSize, Integer status, Long startTime, Long endTime, Integer taskType, String name, Boolean isComplete); /** * 根据任务ID查询历史数据任务信息。 * @param jobId * @return job 信息 */ Optional<WaylineJobDTO> getJobByJobId(String jobId); /** * 将WaylineJobDTO对象转换为WaylineJobHistoryEntity对象 * * @param dto WaylineJobDTO对象 * @return WaylineJobHistoryEntity对象 */ WaylineJobHistoryEntity dto2Entity(WaylineJobDTO dto); } ard-sample/src/main/java/com/ard/sample/wayline/service/impl/FlightTaskServiceImpl.java
@@ -15,12 +15,15 @@ import com.ard.sample.component.websocket.service.IWebSocketManageService; import com.ard.sample.manage.model.dto.DeviceDTO; import com.ard.sample.manage.model.enums.UserTypeEnum; import com.ard.sample.manage.service.IWaylineTrajectoryService; import com.ard.sample.media.model.MediaFileCountDTO; import com.ard.sample.wayline.model.dto.WaylineJobDTO; import com.ard.sample.wayline.model.dto.WaylineTaskProgressExt; import com.ard.sample.wayline.model.dto.WaylineTaskProgressReceiver; import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity; import com.ard.sample.wayline.model.enums.WaylineJobStatusEnum; import com.ard.sample.wayline.service.IFlightTaskService; import com.ard.sample.wayline.service.IWaylineJobHistoryService; import com.ard.sample.wayline.service.IWaylineJobService; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -66,6 +69,12 @@ @Autowired private IWaylineJobService waylineJobService; @Autowired private IWaylineTrajectoryService _waylineTrajectoryService; @Autowired private IWaylineJobHistoryService _waylineJobHistoryService; @Override @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS, outputChannel = ChannelName.OUTBOUND) @@ -143,6 +152,9 @@ // if (eventsReceiver.getOutput().getProgress().getPercent() >= 95) { // return; // } String json = ""; try { json = mapper.writeValueAsString(eventsReceiver); @@ -150,6 +162,27 @@ e.printStackTrace(); } _dockWebSocketHandler.sendMessageToSubscribers(dockSn, MessageType.STATUS.getType(), json, ""); _waylineTrajectoryService.setList(dockSn,"1",json); // 计划任务成功后,保存计划任务到历史记录 String status = eventsReceiver.getOutput().getStatus(); String jobId = eventsReceiver.getOutput().getExt().getFlightId(); if(status.equals("ok") && jobId != null) { Optional<WaylineJobDTO> job = waylineJobService.getJobByJobId(jobId); if(job.isPresent()) { if (_waylineJobHistoryService.getJobByJobId(jobId).isPresent()) { return; } WaylineJobHistoryEntity waylineJobHistoryEntity = _waylineJobHistoryService.dto2Entity(job.get()); Optional<WaylineJobDTO> jobHistory = _waylineJobHistoryService.createWaylineJob(waylineJobHistoryEntity); if(jobHistory.isPresent()) { log.info("任务执行成功,保存到历史记录。 {}", jobHistory); } } } } /** ard-sample/src/main/java/com/ard/sample/wayline/service/impl/WaylineJobHistoryServiceImpl.java
New file @@ -0,0 +1,235 @@ package com.ard.sample.wayline.service.impl; import com.ard.route.service.IArdRouteInfoService; import com.ard.sample.common.model.Pagination; import com.ard.sample.common.model.PaginationData; import com.ard.sample.manage.model.dto.DeviceDTO; import com.ard.sample.manage.service.IDeviceService; import com.ard.sample.media.service.IFileService; import com.ard.sample.wayline.mapper.IWaylineJobHistoryMapper; import com.ard.sample.wayline.model.dto.WaylineJobDTO; import com.ard.sample.wayline.model.entity.WaylineJobEntity; import com.ard.sample.wayline.model.entity.WaylineJobHistoryEntity; import com.ard.sample.wayline.model.enums.WaylineJobStatusEnum; import com.ard.sample.wayline.service.IWaylineJobHistoryService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @Service @Transactional @Slf4j @SuppressWarnings("all") public class WaylineJobHistoryServiceImpl implements IWaylineJobHistoryService { @Autowired private IWaylineJobHistoryMapper mapper; @Autowired private IFileService fileService; @Autowired private IDeviceService deviceService; @Override public Optional<WaylineJobDTO> createWaylineJob(WaylineJobHistoryEntity entity) { int id = mapper.insert(entity); if (id <= 0) { return Optional.empty(); } return Optional.ofNullable(this.entity2Dto(entity)); } @Override public Boolean updateJob(WaylineJobDTO dto) { int id = mapper.update(dto2Entity(dto), new LambdaQueryWrapper<WaylineJobHistoryEntity>() .eq(WaylineJobHistoryEntity::getJobId, dto.getJobId() )); return id>0; } @Override public PaginationData<WaylineJobDTO> getJobsList(long page, long pageSize, Integer status, Long startTime, Long endTime, Integer taskType, String name, Boolean isComplete) { Page<WaylineJobHistoryEntity> pageData = mapper.selectPage( new Page<WaylineJobHistoryEntity>(page, pageSize), new LambdaQueryWrapper<WaylineJobHistoryEntity>() .isNull(WaylineJobHistoryEntity::getParentId) // 实际开始时间筛选,允许为空,为空则不进行筛选 .ge(startTime != null, WaylineJobHistoryEntity::getBeginTime, startTime) .le(endTime != null, WaylineJobHistoryEntity::getBeginTime, endTime) // 任务类型筛选,允许为空,为空则不进行筛选 .eq(taskType != null, WaylineJobHistoryEntity::getTaskType, taskType) // 任务名称筛选,允许为空,为空则不进行筛选;....模糊查询 .like(name != null, WaylineJobHistoryEntity::getName, "%" + name + "%") // 根据是否完成筛选,允许为空,为空则不进行筛选 .eq(isComplete != null && isComplete, WaylineJobHistoryEntity::getStatus, 3) .ne(isComplete != null && !isComplete, WaylineJobHistoryEntity::getStatus, 3) // 任务状态筛选,允许为空,为空则不进行筛选 .eq(status != null, WaylineJobHistoryEntity::getStatus, status) .orderByDesc(WaylineJobHistoryEntity::getBeginTime)); List<WaylineJobDTO> records = pageData.getRecords() .stream() .map(this::entity2Dto) .peek(job -> { List<WaylineJobDTO> childOpt = this.getJobByJobParentId(job.getJobId()); job.setChildren(childOpt); }) .collect(Collectors.toList()); return new PaginationData<WaylineJobDTO>(records, new Pagination(pageData)); } public List<WaylineJobDTO> getJobByJobParentId(String parentId) { List<WaylineJobHistoryEntity> jobEntities = mapper.selectList( new LambdaQueryWrapper<WaylineJobHistoryEntity>() .eq(WaylineJobHistoryEntity::getParentId, parentId)); if (CollectionUtils.isEmpty(jobEntities)) { return Collections.emptyList(); // 返回不可变空列表,更安全 } return jobEntities.stream() .map(this::entity2Dto) // 调用原有的单个转换方法 .collect(Collectors.toList()); } @Override public Optional<WaylineJobDTO> getJobByJobId(String jobId) { WaylineJobHistoryEntity jobEntities = mapper.selectOne( new LambdaQueryWrapper<WaylineJobHistoryEntity>() .eq(WaylineJobHistoryEntity::getJobId, jobId)); return Optional.ofNullable(this.entity2Dto(jobEntities)); } /** * 将WaylineJobDTO对象转换为WaylineJobHistoryEntity对象 * * @param dto WaylineJobDTO对象 * @return WaylineJobHistoryEntity对象 */ @Override public WaylineJobHistoryEntity dto2Entity(WaylineJobDTO dto) { WaylineJobHistoryEntity.WaylineJobHistoryEntityBuilder builder = WaylineJobHistoryEntity.builder(); if (dto == null) { return builder.build(); } if (Objects.nonNull(dto.getBeginTime())) { builder.beginTime(dto.getBeginTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); } if (Objects.nonNull(dto.getEndTime())) { builder.endTime(dto.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); } if (Objects.nonNull(dto.getExecuteTime())) { builder.executeTime(dto.getExecuteTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); } if (Objects.nonNull(dto.getCompletedTime())) { builder.completedTime(dto.getCompletedTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); } return builder.status(dto.getStatus()) .mediaCount(dto.getMediaCount()) .name(dto.getJobName()) .errorCode(dto.getCode()) .jobId(dto.getJobId()) .fileId(dto.getFileId()) .filename(dto.getFileName()) .dockSn(dto.getDockSn()) .taskType(dto.getTaskType()) .waylineType(dto.getWaylineType()) .username(dto.getUsername()) .rthAltitude(dto.getRthAltitude()) .outOfControlAction(dto.getOutOfControlAction()) .parentId(dto.getParentId()) .loopSum(dto.getLoopSum()) .build(); } /** * 将实体对象转换为数据传输对象 * * @param entity WaylineJobEntity 实体对象 * @return WaylineJobDTO 数据传输对象 */ private WaylineJobDTO entity2Dto(WaylineJobHistoryEntity entity) { if (entity == null) { return null; } // 修改航线文件名称,从ard_route_info航线表中取; String fileId = entity.getFileId(); WaylineJobDTO.WaylineJobDTOBuilder builder = WaylineJobDTO.builder() .jobId(entity.getJobId()) .jobName(entity.getName()) .fileId(entity.getFileId()) .fileName(entity.getFilename()) .dockSn(entity.getDockSn()) .dockName(deviceService.getDeviceBySn(entity.getDockSn()) .orElse(DeviceDTO.builder().build()).getNickname()) .username(entity.getUsername()) .status(entity.getStatus()) .code(entity.getErrorCode()) .beginTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getBeginTime()), ZoneId.systemDefault())) .endTime(Objects.nonNull(entity.getEndTime()) ? LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault()) : null) .executeTime(Objects.nonNull(entity.getExecuteTime()) ? LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getExecuteTime()), ZoneId.systemDefault()) : null) .completedTime(WaylineJobStatusEnum.find(entity.getStatus()).getEnd() ? LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getUpdateTime()), ZoneId.systemDefault()) : null) .taskType(entity.getTaskType()) .waylineType(entity.getWaylineType()) .rthAltitude(entity.getRthAltitude()) .rthMode(entity.getRthMode()) .outOfControlAction(entity.getOutOfControlAction()) .mediaCount(entity.getMediaCount()) .loopSum(entity.getLoopSum()); // if (Objects.nonNull(entity.getEndTime())) { // builder.endTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getEndTime()), ZoneId.systemDefault())); // } // if (WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && RedisOpsUtils.getExpire(entity.getJobId()) > 0) { // EventsReceiver<WaylineTaskProgressReceiver> taskProgress = (EventsReceiver<WaylineTaskProgressReceiver>) RedisOpsUtils.get(RedisConst.WAYLINE_JOB_RUNNING_PREFIX + entity.getDockSn()); // if (Objects.nonNull(taskProgress.getOutput()) && Objects.nonNull(taskProgress.getOutput().getProgress())) { // builder.progress(taskProgress.getOutput().getProgress().getPercent()); // } // } // // if (entity.getMediaCount() == 0) { // return builder.build(); // } // // // sync the number of media files // String key = RedisConst.MEDIA_HIGHEST_PRIORITY_PREFIX + entity.getDockSn(); // String countKey = RedisConst.MEDIA_FILE_PREFIX + entity.getDockSn(); // Object mediaFileCount = RedisOpsUtils.hashGet(countKey, entity.getJobId()); // if (Objects.nonNull(mediaFileCount)) { // builder.uploadedCount(((MediaFileCountDTO) mediaFileCount).getUploadedCount()) // .uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(((MediaFileCountDTO) RedisOpsUtils.get(key)).getJobId())); // return builder.build(); // } // int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getJobId()).size(); // // All media for this job have been uploaded. // if (uploadedSize >= entity.getMediaCount()) { // return builder.uploadedCount(uploadedSize).build(); // } // RedisOpsUtils.hashSet(countKey, entity.getJobId(), // MediaFileCountDTO.builder() // .jobId(entity.getJobId()) // .mediaCount(entity.getMediaCount()) // .uploadedCount(uploadedSize).build()); return builder.build(); } }