ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java
@@ -6,10 +6,15 @@ import com.ard.work.domain.dto.BoxHistoryDTO; import com.ard.work.domain.dto.BoxPhotosDTO; import com.ard.work.domain.dto.BoxSettingsDTO; import com.ard.work.domain.entity.ArdDroneInfo; import com.ard.work.domain.entity.ArdFlightTask; import com.ard.work.domain.entity.ArdMedia; import com.ard.work.domain.receiver.BoxHistoryReceiver; import com.ard.work.domain.receiver.BoxPhotosReceiver; import com.ard.work.domain.receiver.BoxInfoReceiver; import com.ard.work.domain.receiver.BoxStreamUrlReceiver; import com.ard.work.service.IArdFlightTaskService; import com.ard.work.service.IArdMediaService; import com.ard.work.service.ITyService; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSort; @@ -35,6 +40,10 @@ @Resource private ITyService tyService; @Resource private IArdFlightTaskService ardFlightTaskService; @Resource private IArdMediaService ardMediaService; @ApiOperation("获取边缘服务器token信息") @ApiOperationSupport(order = 1) @@ -61,6 +70,23 @@ List<BoxHistoryReceiver> boxHistory = tyService.getBoxHistory(boxHistoryDTO); return AjaxResult.success(boxHistory); } @ApiOperation("获取飞行架次") @ApiOperationSupport(order = 4) @GetMapping("/getFlightTask") public TableDataInfo getFlightTask(ArdFlightTask ardFlightTask) { startPage(); List<ArdFlightTask> list = ardFlightTaskService.selectArdFlightTask(ardFlightTask); return getDataTable(list); } @ApiOperation("获取媒体数据") @ApiOperationSupport(order = 4) @GetMapping("/getMediaList") public TableDataInfo getMediaList(ArdMedia ardMedia) { startPage(); List<ArdMedia> list = ardMediaService.selectArdMediaList(ardMedia); return getDataTable(list); } @ApiOperation("获取任务照片") @ApiOperationSupport(order = 5) ard-common/src/main/java/com/ard/common/utils/file/MimeTypeUtils.java
@@ -5,8 +5,9 @@ * * @author ard */ public class MimeTypeUtils { public class MimeTypeUtils { public static final String VIDEO_MP4 = "video/mp4"; public static final String IMAGE_PNG = "image/png"; public static final String IMAGE_JPG = "image/jpg"; @@ -43,10 +44,10 @@ "glb" }; public static String getExtension(String prefix) { switch (prefix) { public static String getExtension(String prefix) { switch (prefix) { case VIDEO_MP4: return "mp4"; case IMAGE_PNG: return "png"; case IMAGE_JPG: ard-oss/src/main/java/com/ard/oss/service/impl/OssServiceContext.java
@@ -12,6 +12,7 @@ import io.minio.PutObjectArgs; import lombok.Cleanup; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -167,7 +168,22 @@ throw new RuntimeException("Upload failed: " + e.getMessage(), e); } } @Async("threadPoolTaskExecutor") public String upload(String bucket, String objectKey, InputStream input, String contentType) { try { // 上传文件时指定 Content-Type this.ossService.putObject(bucket, objectKey, input, contentType); // ✅ 构建永久访问 URL String baseUrl = OssConfiguration.endpoint; if (!baseUrl.endsWith("/")) { baseUrl += "/"; } return baseUrl + bucket + "/" + objectKey; } catch (Exception e) { throw new RuntimeException("Upload failed: " + e.getMessage(), e); } } // 获取文件 MIME 类型 public String getMimeTypeByExtension(String fileName) { // 获取文件扩展名 ard-work/src/main/java/com/ard/work/domain/dto/BoxHistoryDTO.java
@@ -1,11 +1,14 @@ package com.ard.work.domain.dto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @Builder @AllArgsConstructor ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTask.java
New file @@ -0,0 +1,23 @@ package com.ard.work.domain.entity; import com.ard.common.core.domain.BaseEntity; import lombok.Data; import java.util.Date; import java.util.List; @Data public class ArdFlightTask extends BaseEntity { private Integer taskId; // 任务ID private String boxSn; // 飞行器序列号 private String boxName; // 飞行器名称 private String taskName; // 任务名称 private Integer photoCount; // 图片数量 private Integer videoCount; // 录像数量 private String videoPath; // 视频路径 private Date startTime; // 任务开始时间 private Date endTime; // 任务结束时间 private String serverId; // 服务器ID private List<ArdMedia> mediaList; // 媒体文件列表 } ard-work/src/main/java/com/ard/work/domain/entity/ArdMedia.java
New file @@ -0,0 +1,16 @@ package com.ard.work.domain.entity; import com.ard.common.core.domain.BaseEntity; import lombok.Data; @Data public class ArdMedia extends BaseEntity { private String id; // 媒体ID private Integer taskId; // 任务ID(外键关联飞行任务) private Integer mediaType; // 媒体类型(0"photo" 或 1"video") private Long fileSize; // 文件大小 private String fileMd5; // 文件MD5值 private String mediaUrl; // 地址 private String sourceUrl; // 源地址 } ard-work/src/main/java/com/ard/work/domain/receiver/BoxHistoryReceiver.java
@@ -37,6 +37,13 @@ @JsonProperty("endTime") private String endTime; private Integer flightDuration; private Integer flightMileage; private Float aveSpeed; private Float maxSpeed; @JsonProperty("videoPathList") private List<String> videoPathList; ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskMapper.java
New file @@ -0,0 +1,26 @@ package com.ard.work.mapper; import com.ard.work.domain.entity.ArdFlightTask; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; public interface ArdFlightTaskMapper { // 插入飞行任务 int insertArdFlightTask(ArdFlightTask task); // 根据任务ID获取飞行任务 ArdFlightTask getArdFlightTaskById(@Param("taskId") Integer taskId); // 获取所有飞行任务 List<ArdFlightTask> selectArdFlightTask(ArdFlightTask ardFlightTask); // 获取某个时间戳后的任务 List<ArdFlightTask> getTasksAfter(@Param("lastSyncTime") String lastSyncTime); // 获取最大 startTime Date findMaxStartTimeByServerId(String serverId); } ard-work/src/main/java/com/ard/work/mapper/ArdMediaMapper.java
New file @@ -0,0 +1,32 @@ package com.ard.work.mapper; import com.ard.work.domain.entity.ArdMedia; import org.apache.ibatis.annotations.Mapper; import java.util.List; public interface ArdMediaMapper { /** * 查询媒体数据列表 * * @param ardMedia 媒体数据 * @return 媒体数据集合 */ List<ArdMedia> selectArdMedia(ArdMedia ardMedia); // 动态查询 List<ArdMedia> selectArdMediaByTaskId(Integer taskId); // 根据任务ID查询 /** * 插入媒体数据记录 * * @param ardMedia 媒体数据 */ void insertArdMedia(ArdMedia ardMedia); // 插入单个记录 void insertArdMediaList(List<ArdMedia> ardMediaList); // 插入批量记录 void updateArdMedia(ArdMedia ardMedia); // 更新记录 void deleteArdMediaById(Integer id); // 根据ID删除记录 void deleteArdMediaByIds(List<Integer> mediaIds); // 批量删除记录 void deleteArdMediaByTaskId(Integer taskId); // 批量删除记录 } ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java
@@ -70,4 +70,10 @@ */ public int updateServerStatus(@Param("id") String id, @Param("status") String status); /** * 获取服务器ids * * @return 结果 */ List<String> getServerIdsList(); } ard-work/src/main/java/com/ard/work/service/IArdFlightTaskService.java
New file @@ -0,0 +1,19 @@ package com.ard.work.service; import com.ard.work.domain.entity.ArdFlightTask; import java.util.List; /** * Description: * Author: lsy * Date: 2025年11月18日12:31 **/ public interface IArdFlightTaskService { /** * 查询飞行架次列表 * * @param ardFlightTask 飞行架次 * @return 无人机飞行架次合 */ public List<ArdFlightTask> selectArdFlightTask(ArdFlightTask ardFlightTask); } ard-work/src/main/java/com/ard/work/service/IArdMediaService.java
New file @@ -0,0 +1,20 @@ package com.ard.work.service; import com.ard.work.domain.entity.ArdMedia; import java.util.List; /** * Description: * Author: lsy * Date: 2025年11月18日13:15 **/ public interface IArdMediaService { /** * 查询媒体数据列表 * * @param ardMedia 媒体数据 * @return 媒体数据集合 */ public List<ArdMedia> selectArdMediaList(ArdMedia ardMedia); } ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java
@@ -70,4 +70,9 @@ */ public int updateServerStatus(String id,String status); /** * 获取服务器ID列表 */ public List<String> getServerIdsList(); } ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskServiceServiceImpl.java
New file @@ -0,0 +1,273 @@ package com.ard.work.service.impl; import com.ard.common.utils.DateUtils; import com.ard.common.utils.StringUtils; import com.ard.common.utils.file.MimeTypeUtils; import com.ard.common.utils.uuid.IdUtils; import com.ard.oss.service.IOssService; import com.ard.oss.service.impl.OssServiceContext; import com.ard.work.component.forest.TyClient; import com.ard.work.domain.dto.BoxHistoryDTO; import com.ard.work.domain.dto.BoxPhotosDTO; import com.ard.work.domain.entity.ArdFlightTask; import com.ard.work.domain.entity.ArdMedia; import com.ard.work.domain.receiver.BoxHistoryReceiver; import com.ard.work.domain.receiver.BoxPhotosReceiver; import com.ard.work.domain.receiver.TyHttpCommonReceiver; import com.ard.work.mapper.ArdFlightTaskMapper; import com.ard.work.mapper.ArdMediaMapper; import com.ard.work.service.IArdFlightTaskService; import com.ard.work.service.IArdServerInfoService; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.net.ssl.*; import java.io.InputStream; import java.net.URL; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; @Service public class ArdFlightTaskServiceServiceImpl implements IArdFlightTaskService { @Resource private ArdFlightTaskMapper ardFlightTaskMapper; @Resource private ArdMediaMapper ardMediaMapper; @Resource private IArdServerInfoService ardServerInfoService; @Resource private TyClient tyClient; @Resource private OssServiceContext ossServiceContext; @Resource private ThreadPoolTaskExecutor threadPoolTaskExecutor; // 使用线程池执行异步任务 @Override public List<ArdFlightTask> selectArdFlightTask(ArdFlightTask ardFlightTask) { return ardFlightTaskMapper.selectArdFlightTask(ardFlightTask); } // 同步所有服务的飞行历史 @Scheduled(fixedDelay = 10000) public void syncAllFlightHistory() { List<String> serverIds = ardServerInfoService.getServerIdsList(); for (String serverId : serverIds) { // 获取上次同步的时间(即数据库中最大 startTime) Date lastSyncTime = getLastSyncTimeForServer(serverId); // 根据上次同步时间同步飞行历史 syncFlightHistory(serverId, lastSyncTime); } } // 获取上次同步时间(获取最大 startTime) private Date getLastSyncTimeForServer(String serverId) { Date maxStartTime = ardFlightTaskMapper.findMaxStartTimeByServerId(serverId); return maxStartTime != null ? maxStartTime : new Date(0); // 如果没有数据,返回 Unix 纪元时间作为起点 } // 调用接口获取飞行历史数据 // 根据上次同步时间同步飞行历史 public void syncFlightHistory(String serverId, Date lastSyncTime) { // 创建查询条件 BoxHistoryDTO,并设置 startTime 作为过滤条件 BoxHistoryDTO boxHistoryDTO = new BoxHistoryDTO(); boxHistoryDTO.setStartTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, lastSyncTime)); // 传递 lastSyncTime 参数 // 获取飞行历史 List<BoxHistoryReceiver> historyList = getBoxHistory(serverId, boxHistoryDTO); // 如果获取到数据,处理并同步到本地数据库 if (historyList != null && !historyList.isEmpty()) { for (BoxHistoryReceiver boxHistory : historyList) { syncToLocalDatabase(serverId, boxHistory); } } } // 调用接口获取飞行历史数据 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 ardFlightTaskById = ardFlightTaskMapper.getArdFlightTaskById(flightTask.getTaskId()); if (ardFlightTaskById != null) { return; } System.out.println("Syncing task " + boxHistoryReceiver.getTaskId()); // 插入新记录 int rows = ardFlightTaskMapper.insertArdFlightTask(flightTask); if (rows > 0) { // 删除旧的媒体记录,防止重复插入 ardMediaMapper.deleteArdMediaByTaskId(flightTask.getTaskId()); // 插入视频 syncVideoToDatabase(flightTask, boxHistoryReceiver.getVideoPathList()); // 插入图片 syncPhotoToDatabase(flightTask, serverId, boxHistoryReceiver.getBoxSn()); } } // 插入视频记录 private void syncVideoToDatabase(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); // 异步上传文件到OSS,并在上传完成后插入数据库 CompletableFuture.supplyAsync(() -> uploadFileToOss(flightTask.getBoxSn(), videoPath, "record", MimeTypeUtils.VIDEO_MP4), threadPoolTaskExecutor) .thenAccept(url -> { ardMedia.setMediaUrl(url); // 获取上传后的文件 URL ardMedia.setCreateTime(new Date()); ardMediaMapper.insertArdMedia(ardMedia); // 插入数据库 }); } } } // 插入图片记录 private void syncPhotoToDatabase(ArdFlightTask flightTask, String serverId, String boxSn) { // 查询图片 BoxPhotosDTO boxPhotosDTO = new BoxPhotosDTO(); boxPhotosDTO.setTaskId(flightTask.getTaskId()); boxPhotosDTO.setBoxSn(boxSn); boxPhotosDTO.setPageIndex(1); boxPhotosDTO.setPageSize(1000); TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(serverId, boxPhotosDTO); List<BoxPhotosReceiver> photoList = boxPhotos.getContent(); 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); // 插入数据库 }); } } } // 通用的上传方法,支持视频和图片等文件上传 public String uploadFileToOss(String boxSn, String fileUrl, String bucket, String contentType) { InputStream fileInputStream = null; String fileOssUrl = ""; try { // 创建信任所有证书的SSLContext TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // 创建所有主机名都信任的HostnameVerifier HostnameVerifier allHostsValid = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); // 现在可以正常访问 // 从URL创建InputStream URL url = new URL(fileUrl); fileInputStream = url.openStream(); // 文件名 String fileName = boxSn + "/" + IdUtils.fastSimpleUUID() + "." + MimeTypeUtils.getExtension(contentType); // 调用OSS服务上下文进行文件上传 fileOssUrl = ossServiceContext.upload(bucket, fileName, fileInputStream, contentType); } catch (Exception e) { e.printStackTrace(); // 异常处理,可以选择记录日志或者抛出业务异常 } finally { // 关闭InputStream if (fileInputStream != null) { try { fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); } } } return fileOssUrl; // 返回上传后的文件OSS URL } } ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java
@@ -150,6 +150,11 @@ return ardServerInfoMapper.updateServerStatus(id,status); } @Override public List<String> getServerIdsList() { return ardServerInfoMapper.getServerIdsList(); } private String getEncryptStr(ArdServerInfo serverInfo, long timeStamp) { String sb = serverInfo.getAccessKeyId() + serverInfo.getAccessKeySecret() + timeStamp; return DigestUtils.md5DigestAsHex(sb.getBytes()); ard-work/src/main/java/com/ard/work/service/impl/GimbalSpeedServiceImpl.java
File was renamed from ard-work/src/main/java/com/ard/work/service/impl/GimbalSpeedService.java @@ -25,7 +25,7 @@ */ @Service @Slf4j public class GimbalSpeedService implements IGimbalSpeedService { public class GimbalSpeedServiceImpl implements IGimbalSpeedService { private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private final Map<String, ScheduledFuture<?>> tasks = new ConcurrentHashMap<>(); ard-work/src/main/java/com/ard/work/service/impl/IArdMediaServiceImpl.java
New file @@ -0,0 +1,31 @@ package com.ard.work.service.impl; import com.ard.work.domain.entity.ArdMedia; import com.ard.work.mapper.ArdMediaMapper; import com.ard.work.service.IArdMediaService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; /** * Description: * Author: lsy * Date: 2025年11月18日13:17 **/ @Service public class IArdMediaServiceImpl implements IArdMediaService { @Resource private ArdMediaMapper ardMediaMapper; /** * 查询媒体数据列表 * * @param ardMedia 媒体数据 * @return 媒体数据集合 */ @Override public List<ArdMedia> selectArdMediaList(ArdMedia ardMedia) { return ardMediaMapper.selectArdMedia(ardMedia); } } ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml
New file @@ -0,0 +1,117 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ard.work.mapper.ArdFlightTaskMapper"> <!-- 结果映射 --> <resultMap id="ArdFlightTaskResult" type="ArdFlightTask"> <result property="taskId" column="task_id"/> <result property="boxSn" column="box_sn"/> <result property="boxName" column="box_name"/> <result property="taskName" column="task_name"/> <result property="videoCount" column="video_count"/> <result property="photoCount" column="photo_count"/> <result property="videoPath" column="video_path"/> <result property="startTime" column="start_time"/> <result property="endTime" column="end_time"/> <result property="serverId" column="server_id"/> <result property="createBy" column="create_by"/> <result property="createTime" column="create_time"/> <result property="updateBy" column="update_by"/> <result property="updateTime" column="update_time"/> <result property="remark" column="remark"/> </resultMap> <!-- 查询任务记录并联接图片和视频 --> <select id="selectArdFlightTask" resultMap="ArdFlightTaskResult"> SELECT aft.task_id, aft.box_sn, aft.box_name, aft.task_name, aft.video_count, aft.photo_count, aft.video_path, aft.start_time, aft.end_time, aft.server_id, aft.create_by, aft.create_time, aft.update_by, aft.update_time, aft.remark FROM ard_flight_task aft <where> <trim prefix="" suffix="" suffixOverrides="AND,OR"> <if test="taskId != null">AND aft.task_id = #{taskId}</if> <if test="boxSn != null">AND aft.box_sn = #{boxSn}</if> <if test="boxName != null">AND aft.box_name LIKE CONCAT('%', #{boxName}, '%')</if> <if test="taskName != null">AND aft.task_name LIKE CONCAT('%', #{taskName}, '%')</if> <if test="startTime != null">AND aft.start_time >= #{startTime}</if> <if test="endTime != null">AND aft.end_time <= #{endTime}</if> <if test="serverId != null">AND aft.server_id = #{serverId}</if> </trim> </where> ORDER BY aft.task_id DESC </select> <!-- 插入飞行任务 --> <insert id="insertArdFlightTask" parameterType="com.ard.work.domain.entity.ArdFlightTask"> insert into ard_flight_task <trim prefix="(" suffix=")" suffixOverrides=","> <if test="taskId != null">task_id,</if> <if test="boxSn != null">box_sn,</if> <if test="boxName != null">box_name,</if> <if test="taskName != null">task_name,</if> <if test="videoCount != null">video_count,</if> <if test="photoCount != null">photo_count,</if> <if test="videoPath != null">video_path,</if> <if test="startTime != null">start_time,</if> <if test="endTime != null">end_time,</if> <if test="serverId != null">server_id,</if> <if test="createBy != null">create_by,</if> <if test="createTime != null">create_time,</if> <if test="updateBy != null">update_by,</if> <if test="updateTime != null">update_time,</if> <if test="remark != null">remark,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="taskId != null">#{taskId},</if> <if test="boxSn != null">#{boxSn},</if> <if test="boxName != null">#{boxName},</if> <if test="taskName != null">#{taskName},</if> <if test="videoCount != null">#{videoCount},</if> <if test="photoCount != null">#{photoCount},</if> <if test="videoPath != null">#{videoPath},</if> <if test="startTime != null">#{startTime},</if> <if test="endTime != null">#{endTime},</if> <if test="serverId != null">#{serverId},</if> <if test="createBy != null">#{createBy},</if> <if test="createTime != null">#{createTime},</if> <if test="updateBy != null">#{updateBy},</if> <if test="updateTime != null">#{updateTime},</if> <if test="remark != null">#{remark},</if> </trim> </insert> <!-- 根据任务ID获取飞行任务 --> <select id="getArdFlightTaskById" resultType="ArdFlightTask"> SELECT * FROM ard_flight_task WHERE task_id = #{taskId} </select> <!-- 获取某个时间戳后的任务 --> <select id="getTasksAfter" resultType="ArdFlightTask"> SELECT * FROM ard_flight_task WHERE end_time > #{lastSyncTime} </select> <select id="findMaxStartTimeByServerId" resultType="java.util.Date"> SELECT MAX(start_time) FROM ard_flight_task WHERE server_id = #{serverId} </select> </mapper> ard-work/src/main/resources/mapper/ArdMediaMapper.xml
New file @@ -0,0 +1,140 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ard.work.mapper.ArdMediaMapper"> <!-- 结果映射 --> <resultMap id="ArdMediaResult" type="com.ard.work.domain.entity.ArdMedia"> <result property="id" column="id"/> <result property="taskId" column="task_id"/> <result property="mediaType" column="media_type"/> <result property="fileSize" column="file_size"/> <result property="fileMd5" column="file_md5"/> <result property="mediaUrl" column="media_url"/> <result property="sourceUrl" column="source_url"/> <result property="createTime" column="create_time"/> </resultMap> <!-- 查询媒体列表:根据条件动态生成SQL --> <select id="selectArdMedia" resultMap="ArdMediaResult"> SELECT id, task_id, media_type, file_size, file_md5, media_url, source_url,create_time FROM ard_media <where> <!-- 动态查询条件:任务ID --> <if test="taskId != null">AND task_id = #{taskId}</if> <!-- 动态查询条件:媒体类型 --> <if test="mediaType != null">AND media_type = #{mediaType}</if> <!-- 动态查询条件:文件大小 --> <if test="fileSize != null">AND file_size = #{fileSize}</if> <!-- 动态查询条件:文件MD5 --> <if test="fileMd5 != null">AND file_md5 = #{fileMd5}</if> <!-- 动态查询条件:媒体URL --> <if test="mediaUrl != null">AND media_url = #{mediaUrl}</if> <!-- 动态查询条件:时间戳 --> <if test="createTime != null">AND create_time = #{createTime}</if> </where> </select> <!-- 根据任务ID查询媒体 --> <select id="selectArdMediaByTaskId" resultMap="ArdMediaResult"> SELECT id, task_id, media_type, file_size, file_md5, media_url, create_time FROM ard_media WHERE task_id = #{taskId} </select> <!-- 插入媒体记录 --> <insert id="insertArdMedia" parameterType="com.ard.work.domain.entity.ArdMedia"> INSERT INTO ard_media <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="taskId != null">task_id,</if> <if test="mediaType != null">media_type,</if> <if test="fileSize != null">file_size,</if> <if test="fileMd5 != null">file_md5,</if> <if test="mediaUrl != null">media_url,</if> <if test="sourceUrl != null">source_url,</if> <if test="createTime != null">create_time,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null">#{id},</if> <if test="taskId != null">#{taskId},</if> <if test="mediaType != null">#{mediaType},</if> <if test="fileSize != null">#{fileSize},</if> <if test="fileMd5 != null">#{fileMd5},</if> <if test="mediaUrl != null">#{mediaUrl},</if> <if test="sourceUrl != null">#{sourceUrl},</if> <if test="createTime != null">#{createTime},</if> </trim> </insert> <!-- 批量插入媒体记录 --> <insert id="insertArdMediaList" parameterType="java.util.List"> INSERT INTO ard_media <trim prefix="(" suffix=")" suffixOverrides=","> <if test="list != null and !list.isEmpty()"> <foreach item="item" collection="list" separator=","> <trim prefix="(" suffix=")" suffixOverrides=","> <if test="item.taskId != null">task_id,</if> <if test="item.mediaType != null">media_type,</if> <if test="item.fileSize != null">file_size,</if> <if test="item.fileMd5 != null">file_md5,</if> <if test="item.mediaUrl != null">media_url,</if> <if test="item.sourceUrl != null">source_url,</if> <if test="item.createTime != null">create_time,</if> </trim> </foreach> </if> </trim> <trim prefix="values " suffix=")" suffixOverrides=","> <foreach item="item" collection="list" separator=","> <trim prefix="(" suffix=")" suffixOverrides=","> <if test="item.taskId != null">#{item.taskId},</if> <if test="item.mediaType != null">#{item.mediaType},</if> <if test="item.fileSize != null">#{item.fileSize},</if> <if test="item.fileMd5 != null">#{item.fileMd5},</if> <if test="item.mediaUrl != null">#{item.mediaUrl},</if> <if test="item.sourceUrl != null">#{item.sourceUrl},</if> <if test="item.createTime != null">#{item.createTime},</if> </trim> </foreach> </trim> </insert> <!-- 更新媒体记录 --> <update id="updateArdMedia" parameterType="com.ard.work.domain.entity.ArdMedia"> UPDATE ard_media <set> <if test="mediaType != null">media_type = #{mediaType},</if> <if test="fileSize != null">file_size = #{fileSize},</if> <if test="fileMd5 != null">file_md5 = #{fileMd5},</if> <if test="mediaUrl != null">media_url = #{mediaUrl},</if> <if test="createTime != null">create_time = #{createTime},</if> </set> WHERE id = #{id} </update> <!-- 删除媒体记录 --> <delete id="deleteArdMediaById" parameterType="Integer"> DELETE FROM ard_media WHERE id = #{id} </delete> <!-- 批量删除媒体记录 --> <delete id="deleteArdMediaByIds" parameterType="java.util.List"> DELETE FROM ard_media WHERE id IN <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </delete> <delete id="deleteArdMediaByTaskId" parameterType="java.lang.Integer"> DELETE FROM ard_media WHERE task_id = #{taskId} </delete> </mapper> ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml
@@ -148,4 +148,10 @@ #{id} </foreach> </delete> <select id="getServerIdsList" resultType="String"> SELECT id FROM ard_server where server_status = "1" </select> </mapper>