liusuyi
2025-11-19 fadbcd1f76ec12d760b059018b8a37aaa64303de
ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java
@@ -24,6 +24,7 @@
import javax.annotation.Resource;
import javax.net.ssl.*;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
@@ -45,16 +46,24 @@
    private TyClient tyClient;
    @Resource
    private OssServiceContext ossServiceContext;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;  // 使用线程池执行异步任务
    /**
     * 查询飞行架次列表
     *
     * @param ardFlightTask 飞行架次
     * @return 飞行架次集合
     */
    @Override
    public List<ArdFlightTask> selectArdFlightTask(ArdFlightTask ardFlightTask) {
        return ardFlightTaskMapper.selectArdFlightTask(ardFlightTask);
    }
    // 同步所有服务的飞行历史
    /**
     * 同步所有服务的飞行历史
     *
     */
    @Scheduled(fixedDelay = 10000)
    public void syncAllFlightHistory() {
        List<String> serverIds = ardServerInfoService.getServerIdsList();
@@ -72,12 +81,12 @@
        return maxStartTime != null ? maxStartTime : new Date(0);  // 如果没有数据,返回 Unix 纪元时间作为起点
    }
    // 调用接口获取飞行历史数据
    // 根据上次同步时间同步飞行历史
    public void syncFlightHistory(String serverId, Date lastSyncTime) {
    public void syncFlightHistory(String serverId, Date startTime) {
        // 创建查询条件 BoxHistoryDTO,并设置 startTime 作为过滤条件
        BoxHistoryDTO boxHistoryDTO = new BoxHistoryDTO();
        boxHistoryDTO.setStartTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, lastSyncTime));  // 传递 lastSyncTime 参数
        BoxHistoryDTO boxHistoryDTO = BoxHistoryDTO.builder()
                .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTime))
                .build();
        // 获取飞行历史
        List<BoxHistoryReceiver> historyList = getBoxHistory(serverId, boxHistoryDTO);
@@ -90,44 +99,28 @@
        }
    }
    // 调用接口获取飞行历史数据
    private List<BoxHistoryReceiver> getBoxHistory(String serverId, BoxHistoryDTO boxHistoryDTO) {
        TyHttpCommonReceiver<List<BoxHistoryReceiver>> boxHistory = tyClient.getBoxHistory(serverId, boxHistoryDTO);
        return boxHistory.getContent();
    }
    // 将数据同步到本地数据库
    private void syncToLocalDatabase(String serverId, BoxHistoryReceiver boxHistoryReceiver) {
        // 创建FlightTask实体对象并填充数据
        ArdFlightTask flightTask = new ArdFlightTask();
        flightTask.setTaskId(boxHistoryReceiver.getTaskId());
        flightTask.setBoxSn(boxHistoryReceiver.getBoxSn());
        flightTask.setBoxName(boxHistoryReceiver.getBoxName());
        flightTask.setTaskName(boxHistoryReceiver.getTaskName());
        Integer photoCount = Integer.parseInt(boxHistoryReceiver.getPhotoCount());
        flightTask.setPhotoCount(photoCount);
        Integer videoCount = (boxHistoryReceiver.getVideoPathList() != null) ?
                boxHistoryReceiver.getVideoPathList().size() : 0;
        flightTask.setVideoCount(videoCount);
        flightTask.setVideoPath(boxHistoryReceiver.getVideoPath());
        flightTask.setServerId(serverId);
        Date startTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getStartTime());
        flightTask.setStartTime(startTime);
        Date endTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getEndTime());
        flightTask.setEndTime(endTime);
        flightTask.setCreateTime(DateUtils.getNowDate());
        // 检查是否已经存在相同任务ID的记录
        ArdFlightTask ardFlightTask = ardFlightTaskMapper.getArdFlightTaskById(flightTask.getTaskId());
        ArdFlightTask ardFlightTask = ardFlightTaskMapper.getArdFlightTaskById(boxHistoryReceiver.getTaskId());
        if (ardFlightTask == null) {
            // 如果不存在,则插入新记录
            log.info("Syncing task {}", boxHistoryReceiver.getTaskId());
            log.debug("insert task {}", boxHistoryReceiver.getTaskId());
            // 创建FlightTask实体对象并填充数据
            ArdFlightTask flightTask = ArdFlightTask.builder()
                    .taskId(boxHistoryReceiver.getTaskId())
                    .boxSn(boxHistoryReceiver.getBoxSn())
                    .boxName(boxHistoryReceiver.getBoxName())
                    .taskName(boxHistoryReceiver.getTaskName())
                    .photoCount(Integer.parseInt(boxHistoryReceiver.getPhotoCount()))
                    .videoCount((boxHistoryReceiver.getVideoPathList() != null) ?
                            boxHistoryReceiver.getVideoPathList().size() : 0)
                    .videoPath(boxHistoryReceiver.getVideoPath())
                    .serverId(serverId)
                    .startTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getStartTime()))
                    .endTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, boxHistoryReceiver.getEndTime()))
                    .build();
            flightTask.setCreateTime(DateUtils.getNowDate());
            // 插入新记录
            int rows = ardFlightTaskMapper.insertArdFlightTask(flightTask);
            if (rows > 0) {
@@ -135,14 +128,14 @@
                ardMediaMapper.deleteArdMediaByTaskId(flightTask.getTaskId());
                // 插入视频
                syncVideoToDatabase(flightTask, boxHistoryReceiver.getVideoPathList());
                insertVideoToDatabase(flightTask, boxHistoryReceiver.getVideoPathList());
                // 插入图片
                syncPhotoToDatabase(flightTask, serverId, boxHistoryReceiver.getBoxSn());
                insertPhotoToDatabase(flightTask, serverId, boxHistoryReceiver.getBoxSn());
            }
        } else {
            // 如果存在,则更新记录
            log.info("Updating task {}", boxHistoryReceiver.getTaskId());
            log.debug("Updating task {}", boxHistoryReceiver.getTaskId());
            // 增量更新
            updateVideoToDatabase(ardFlightTask, boxHistoryReceiver.getVideoPathList());
            // 增量更新图片
@@ -151,18 +144,33 @@
        }
    }
    // 调用接口获取飞行历史数据
    private List<BoxHistoryReceiver> getBoxHistory(String serverId, BoxHistoryDTO boxHistoryDTO) {
        TyHttpCommonReceiver<List<BoxHistoryReceiver>> boxHistory = tyClient.getBoxHistory(serverId, boxHistoryDTO);
        return boxHistory.getContent();
    }
    //调用接口获取架次图片
    private List<BoxPhotosReceiver> getBoxPhotos(String serverId, BoxPhotosDTO boxPhotosDTO) {
        TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(serverId, boxPhotosDTO);
        return boxPhotos.getContent();
    }
    // 插入视频记录
    private void syncVideoToDatabase(ArdFlightTask flightTask, List<String> videoPathList) {
    private void insertVideoToDatabase(ArdFlightTask flightTask, List<String> videoPathList) {
        if (videoPathList != null && !videoPathList.isEmpty()) {
            for (String videoPath : videoPathList) {
                ArdMedia ardMedia = new ArdMedia();
                ardMedia.setId(IdUtils.simpleUUID());
                ardMedia.setTaskId(flightTask.getTaskId());
                ardMedia.setMediaType(1); // 1表示视频
                ardMedia.setSourceUrl(videoPath);
                ArdMedia ardMedia =  ArdMedia.builder()
                        .id(IdUtils.simpleUUID())
                        .taskId(flightTask.getTaskId())
                        .mediaType(1) // 1表示视频
                        .sourceUrl(videoPath)
                        .fileSize(getFileSizeByUrl(videoPath))
                        .build();
                // 异步上传文件到OSS,并在上传完成后插入数据库
                CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), videoPath, "record",
                CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), videoPath, "record1",
                                MimeTypeUtils.VIDEO_MP4), threadPoolTaskExecutor)
                        .thenAccept(url -> {
                            ardMedia.setMediaUrl(url);  // 获取上传后的文件 URL
@@ -182,19 +190,28 @@
        if (count != null && size > count) {
            log.info("录像数量不一致,需要更新数据库");
            // 需要插入新的视频
            // 获取本地数据库中已存在的视频记录
            List<ArdMedia> existingVideos = ardMediaMapper.selectArdMediaByTaskIdAndType(flightTask.getTaskId(), 1);
            List<String> newVideos = getNewVideos(existingVideos, videoPathList);
            // 提取现有的视频路径
            List<String> existingVideoPaths = existingVideos.stream()
                    .map(ArdMedia::getSourceUrl) // 获取每个视频的 URL
                    .collect(Collectors.toList());
            // 从接口返回的视频路径中找出新的视频
            List<String> newVideos = videoPathList.stream()
                    .filter(videoPath -> !existingVideoPaths.contains(videoPath)) // 过滤出新的视频
                    .collect(Collectors.toList());
            if (!newVideos.isEmpty()) {
                // 插入新的视频记录
                for (String videoPath : newVideos) {
                    ArdMedia ardMedia = new ArdMedia();
                    ardMedia.setId(IdUtils.simpleUUID());
                    ardMedia.setTaskId(flightTask.getTaskId());
                    ardMedia.setMediaType(1); // 1表示视频
                    ardMedia.setSourceUrl(videoPath);
                    ArdMedia ardMedia =  ArdMedia.builder()
                            .id(IdUtils.simpleUUID())
                            .taskId(flightTask.getTaskId())
                            .mediaType(1) // 1表示视频
                            .fileSize(getFileSizeByUrl(videoPath))
                            .sourceUrl(videoPath)
                            .build();
                    // 异步上传文件到OSS,并在上传完成后插入数据库
                    CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), videoPath, "record",
                    CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), videoPath, "record1",
                                    MimeTypeUtils.VIDEO_MP4), threadPoolTaskExecutor)
                            .thenAccept(url -> {
                                ardMedia.setMediaUrl(url);  // 获取上传后的文件 URL
@@ -210,62 +227,30 @@
        }
    }
    // 获取需要插入的新视频路径
    private List<String> getNewVideos(List<ArdMedia> existingVideos, List<String> videoPathList) {
        // 提取现有的视频路径
        List<String> existingVideoPaths = existingVideos.stream()
                .map(ArdMedia::getSourceUrl) // 获取每个视频的 URL
                .collect(Collectors.toList());
        // 从接口返回的视频路径中找出新的视频
        List<String> newVideos = videoPathList.stream()
                .filter(videoPath -> !existingVideoPaths.contains(videoPath)) // 过滤出新的视频
                .collect(Collectors.toList());
        return newVideos;
    }
    // 插入图片记录
    private void syncPhotoToDatabase(ArdFlightTask flightTask, String serverId, String boxSn) {
    private void insertPhotoToDatabase(ArdFlightTask flightTask, String serverId, String boxSn) {
        // 查询图片
        BoxPhotosDTO boxPhotosDTO = new BoxPhotosDTO();
        boxPhotosDTO.setTaskId(flightTask.getTaskId());
        boxPhotosDTO.setBoxSn(boxSn);
        boxPhotosDTO.setPageIndex(1);
        boxPhotosDTO.setPageSize(500);
        TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(serverId, boxPhotosDTO);
        List<BoxPhotosReceiver> photoList = boxPhotos.getContent();
        List<BoxPhotosReceiver> photoList = getBoxPhotos(serverId, boxPhotosDTO);
        if (photoList != null && !photoList.isEmpty()) {
            for (BoxPhotosReceiver photo : photoList) {
                ArdMedia ardMedia = new ArdMedia();
                ardMedia.setId(IdUtils.simpleUUID());
                ardMedia.setTaskId(flightTask.getTaskId());
                ardMedia.setMediaType(0); // 0表示图片
                ardMedia.setFileSize(photo.getFileSize());
                ardMedia.setFileMd5(photo.getFileMd5());
                ardMedia.setSourceUrl(photo.getImgUrl());
                // 异步上传文件到OSS,并在上传完成后插入数据库
                CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), photo.getImgUrl(), "pic",
                                MimeTypeUtils.IMAGE_JPG), threadPoolTaskExecutor)
                        .thenAccept(url -> {
                            ardMedia.setMediaUrl(url);  // 获取上传后的文件 URL
                            ardMedia.setCreateTime(new Date());
                            ardMediaMapper.insertArdMedia(ardMedia);  // 插入数据库
                        });
            }
            addPhotos(flightTask, photoList);
        }
    }
    private void updatePhotoToDatabase(ArdFlightTask flightTask, String serverId, String boxSn) {
        int count = flightTask.getPhotoCount(); //获取本地库图片数量
        // 查询图片
        BoxPhotosDTO boxPhotosDTO = new BoxPhotosDTO();
        boxPhotosDTO.setTaskId(flightTask.getTaskId());
        boxPhotosDTO.setBoxSn(boxSn);
        boxPhotosDTO.setPageIndex(1);
        boxPhotosDTO.setPageSize(500);
        BoxPhotosDTO boxPhotosDTO =  BoxPhotosDTO.builder()
                .taskId(flightTask.getTaskId())
                .boxSn(boxSn)
                .pageIndex(1)
                .pageSize(500)
                .build();
        TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(serverId, boxPhotosDTO);
        List<BoxPhotosReceiver> photoList = boxPhotos.getContent();
        int size = photoList.size();
@@ -275,26 +260,18 @@
            // 获取本地数据库中已存在的图片记录(类型为 0 表示图片)
            List<ArdMedia> existingPhotos = ardMediaMapper.selectArdMediaByTaskIdAndType(flightTask.getTaskId(), 0);
            // 需要插入新的视频
            List<BoxPhotosReceiver> newPhotos = getNewPhotos(existingPhotos, photoList);
            // 提取现有的图片路径(根据 imgUrl 来判断是否重复)
            List<String> existingPhotoUrls = existingPhotos.stream()
                    .map(ArdMedia::getSourceUrl) // 提取 ArdMedia 中的图片 URL
                    .collect(Collectors.toList());
            // 筛选出 photoList 中没有出现在 existingPhotos 中的新图片
            List<BoxPhotosReceiver> newPhotos = photoList.stream()
                    .filter(photo -> !existingPhotoUrls.contains(photo.getImgUrl())) // 过滤出新图片
                    .collect(Collectors.toList());
            if (!newPhotos.isEmpty()) {
                // 插入新的视频记录
                for (BoxPhotosReceiver photo : newPhotos) {
                    ArdMedia ardMedia = new ArdMedia();
                    ardMedia.setId(IdUtils.simpleUUID());
                    ardMedia.setTaskId(flightTask.getTaskId());
                    ardMedia.setMediaType(0); // 0表示图片
                    ardMedia.setFileSize(photo.getFileSize());
                    ardMedia.setFileMd5(photo.getFileMd5());
                    ardMedia.setSourceUrl(photo.getImgUrl());
                    // 异步上传文件到OSS,并在上传完成后插入数据库
                    CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), photo.getImgUrl(), "pic",
                                    MimeTypeUtils.IMAGE_JPG), threadPoolTaskExecutor)
                            .thenAccept(url -> {
                                ardMedia.setMediaUrl(url);  // 获取上传后的文件 URL
                                ardMedia.setCreateTime(new Date());
                                ardMediaMapper.insertArdMedia(ardMedia);  // 插入数据库
                            });
                }
                addPhotos(flightTask, newPhotos);
                // 更新任务的视频数量
                flightTask.setPhotoCount(flightTask.getPhotoCount() + newPhotos.size());
@@ -303,23 +280,35 @@
        }
    }
    // 获取需要插入的新图片
    private List<BoxPhotosReceiver> getNewPhotos(List<ArdMedia> existingPhotos, List<BoxPhotosReceiver> photoList) {
        // 提取现有的图片路径(根据 imgUrl 来判断是否重复)
        List<String> existingPhotoUrls = existingPhotos.stream()
                .map(ArdMedia::getSourceUrl) // 提取 ArdMedia 中的图片 URL
                .collect(Collectors.toList());
        // 筛选出 photoList 中没有出现在 existingPhotos 中的新图片
        List<BoxPhotosReceiver> newPhotos = photoList.stream()
                .filter(photo -> !existingPhotoUrls.contains(photo.getImgUrl())) // 过滤出新图片
                .collect(Collectors.toList());
        return newPhotos; // 返回新增的图片列表
    private void addPhotos(ArdFlightTask flightTask, List<BoxPhotosReceiver> photoList) {
        for (BoxPhotosReceiver photo : photoList) {
            ArdMedia ardMedia = ArdMedia.builder()
                    .id(IdUtils.simpleUUID())
                    .taskId(flightTask.getTaskId())
                    .mediaType(0) // 0表示图片
                    .fileSize(photo.getFileSize())
                    .fileMd5(photo.getFileMd5())
                    .sourceUrl(photo.getImgUrl())
                    .photoId(photo.getPhotoId())
                    .longitude(photo.getLng())
                    .latitude(photo.getLat())
                    .height(photo.getHeight())
                    .captureTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, photo.getTimeStamp()))
                    .build();
            // 异步上传文件到OSS,并在上传完成后插入数据库
            CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), photo.getImgUrl(), "pic1",
                            MimeTypeUtils.IMAGE_JPG), threadPoolTaskExecutor)
                    .thenAccept(url -> {
                        ardMedia.setMediaUrl(url);  // 获取上传后的文件 URL
                        ardMedia.setCreateTime(new Date());
                        ardMediaMapper.insertArdMedia(ardMedia);  // 插入数据库
                    });
        }
    }
    // 通用的上传方法,支持视频和图片等文件上传
    public String uploadFileToOss(String boxSn, String fileUrl, String bucket, String contentType) {
    private String uploadFileToOss(String boxSn, String fileUrl, String bucket, String contentType) {
        InputStream fileInputStream = null;
        String fileOssUrl = "";
        try {
@@ -385,4 +374,17 @@
        return fileOssUrl; // 返回上传后的文件OSS URL
    }
    //获取文件大小
    private long getFileSizeByUrl(String fileUrl) {
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.connect();
            return conn.getContentLengthLong(); // 返回字节大小
        } catch (Exception e) {
            return -1;
        }
    }
}