From 19763ebd20ad16435f3c1ccfdc8abd1518712cc1 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Wed, 24 Dec 2025 15:09:58 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java               |   14 +
 ard-work/src/main/java/com/ard/work/domain/receiver/BoxVideosReceiver.java         |   32 ++++
 ard-work/src/main/resources/mapper/ArdFlightTaskPartMapper.xml                     |   30 ++-
 ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java                |   27 +++
 ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml                         |   15 +-
 ard-admin/src/main/java/com/ard/web/controller/work/UavCameraController.java       |    7 +
 ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskPartServiceImpl.java |   36 +++-
 ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java    |   62 +++++++-
 ard-route/src/main/java/com/ard/route/service/IArdRouteInfoService.java            |    2 
 ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java         |   21 +-
 ard-admin/src/main/java/com/ard/web/controller/route/ArdRouteInfoController.java   |    7 
 ard-oss/src/main/java/com/ard/oss/service/impl/MinIOServiceImpl.java               |   21 ++
 ard-work/src/main/java/com/ard/work/component/forest/TyClient.java                 |   12 +
 ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml                         |    2 
 ard-work/src/main/java/com/ard/work/component/forest/TyConst.java                  |    1 
 ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java      |    2 
 ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTaskPart.java           |    5 
 ard-work/src/main/java/com/ard/work/domain/dto/BoxVideosDTO.java                   |   27 +++
 ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java     |   29 +++
 ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java   |   12 +
 ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskPartMapper.java            |    8 
 ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java             |    2 
 ard-work/src/main/java/com/ard/work/service/ITyService.java                        |   19 ++
 23 files changed, 315 insertions(+), 78 deletions(-)

diff --git a/ard-admin/src/main/java/com/ard/web/controller/route/ArdRouteInfoController.java b/ard-admin/src/main/java/com/ard/web/controller/route/ArdRouteInfoController.java
index 85d0068..2f4abf0 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/route/ArdRouteInfoController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/route/ArdRouteInfoController.java
@@ -143,9 +143,10 @@
      * 开始航线
      */
     @ApiOperation("开始航线")
-    @PostMapping("/routeBegins/{boxSn}")
-    public AjaxResult routeBegins(@PathVariable("boxSn") String boxSn) {
-        ardRouteInfoService.routeBegins(boxSn);
+    @PostMapping("/routeBegins/{id}/{boxSn}")
+    public AjaxResult routeBegins(@PathVariable("id") String id,
+                                  @PathVariable("boxSn") String boxSn) {
+        ardRouteInfoService.routeBegins(id,boxSn);
         return AjaxResult.success();
     }
 
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java b/ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java
index 8a531ba..7c14a8d 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java
@@ -51,6 +51,18 @@
     }
 
     /**
+     * 查询服务器管理列表
+     */
+    @ApiOperation("查询服务器管理列表")
+    @PreAuthorize("@ss.hasPermi('work:server:listNo')")
+    @GetMapping("/listNo")
+    public TableDataInfo listNo(ArdServerInfo ardServerInfo) {
+        startPage();
+        List<ArdServerInfo> list = ardServerInfoService.selectArdServerInfoListNo(ardServerInfo);
+        return getDataTable(list);
+    }
+
+    /**
      * 导出服务器管理列表
      */
     @ApiOperation("导出服务器管理列表")
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java b/ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java
index 626e421..bc41a9c 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java
@@ -3,18 +3,12 @@
 import com.ard.common.core.controller.BaseController;
 import com.ard.common.core.domain.AjaxResult;
 import com.ard.common.core.page.TableDataInfo;
-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.dto.UavFlightStateDTO;
+import com.ard.work.domain.dto.*;
 import com.ard.work.domain.dto.telemetry.TelemetryData;
 import com.ard.work.domain.entity.ArdFlightTask;
 import com.ard.work.domain.entity.ArdFlightTaskPart;
 import com.ard.work.domain.entity.ArdMedia;
-import com.ard.work.domain.receiver.BoxHistoryReceiver;
-import com.ard.work.domain.receiver.BoxInfoReceiver;
-import com.ard.work.domain.receiver.BoxPhotosReceiver;
-import com.ard.work.domain.receiver.BoxStreamUrlReceiver;
+import com.ard.work.domain.receiver.*;
 import com.ard.work.service.IArdFlightTaskPartService;
 import com.ard.work.service.IArdFlightTaskService;
 import com.ard.work.service.IArdMediaService;
@@ -77,6 +71,7 @@
         List<BoxHistoryReceiver> boxHistory = tyService.getBoxHistory(boxHistoryDTO);
         return AjaxResult.success(boxHistory);
     }
+
     @ApiOperation("获取飞行架次")
     @ApiOperationSupport(order = 4)
     @GetMapping("/getFlightTask")
@@ -89,7 +84,7 @@
     @ApiOperation("获取架次飞行轨迹")
     @ApiOperationSupport(order = 4)
     @GetMapping("/getCompleteFlightData")
-    public TableDataInfo getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart){
+    public TableDataInfo getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart) {
         List<UavFlightStateDTO> completeFlightData = ardFlightTaskPartService.getCompleteFlightData(ardFlightTaskPart);
         return getDataTable(completeFlightData);
     }
@@ -111,6 +106,14 @@
         return AjaxResult.success(boxPhotos);
     }
 
+    @ApiOperation("获取任务视频")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/getBoxVideos")
+    public AjaxResult getBoxVideos(@RequestBody BoxVideosDTO boxVideosDTO) {
+        List<BoxVideosReceiver> boxVideos = tyService.getBoxVideos(boxVideosDTO);
+        return AjaxResult.success(boxVideos);
+    }
+
     @ApiOperation("获取直播地址")
     @ApiOperationSupport(order = 6)
     @GetMapping("/getBoxLiveUrl/{boxSn}")
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/UavCameraController.java b/ard-admin/src/main/java/com/ard/web/controller/work/UavCameraController.java
index e613605..b47b862 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/UavCameraController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/UavCameraController.java
@@ -24,6 +24,13 @@
     @Resource
     private ITyService tyService;
 
+    @ApiOperation(value = "设置相机模式", notes = "actionParam值:1-拍照,2-录像")
+    @ApiOperationSupport(order = 1)
+    @PostMapping("/updateCameraMode")
+    public AjaxResult updateCameraMode(@RequestBody CameraModeDTO cameraModeDTO) {
+        tyService.updateCameraMode(cameraModeDTO);
+        return AjaxResult.success();
+    }
 
     @ApiOperation("拍照")
     @ApiOperationSupport(order = 1)
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java b/ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java
index f61d61c..12cd1de 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/UavControlController.java
@@ -4,6 +4,7 @@
 import com.ard.work.service.control.UavControlService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -20,6 +21,7 @@
      * 申请控制权(请求通过 WebSocket 发送给当前控制者)
      */
     @ApiOperation("申请控制权")
+    @PreAuthorize("@ss.hasPermi('uav:control:request')")
     @PostMapping("/request")
     public AjaxResult requestControl(@RequestParam String boxSn, @RequestParam String type) {
         return AjaxResult.success(uavControlService.requestControl(boxSn, type));
diff --git a/ard-oss/src/main/java/com/ard/oss/service/impl/MinIOServiceImpl.java b/ard-oss/src/main/java/com/ard/oss/service/impl/MinIOServiceImpl.java
index e9b3f96..2fe171d 100644
--- a/ard-oss/src/main/java/com/ard/oss/service/impl/MinIOServiceImpl.java
+++ b/ard-oss/src/main/java/com/ard/oss/service/impl/MinIOServiceImpl.java
@@ -9,7 +9,10 @@
 import io.minio.errors.*;
 import io.minio.http.Method;
 import lombok.extern.slf4j.Slf4j;
+import okhttp3.ConnectionPool;
+import okhttp3.ConnectionSpec;
 import okhttp3.OkHttpClient;
+import okhttp3.TlsVersion;
 import org.springframework.stereotype.Service;
 
 import javax.net.ssl.SSLContext;
@@ -25,7 +28,9 @@
 import java.security.ProviderException;
 import java.security.SecureRandom;
 import java.security.cert.X509Certificate;
+import java.util.Collections;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 
 import static com.ard.common.config.OssConfiguration.*;
 
@@ -74,9 +79,18 @@
             };
             SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
             sslContext.init(null, trustAllCerts, new SecureRandom());
+
+            ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
+                    .tlsVersions(TlsVersion.TLS_1_2)
+                    .allEnabledCipherSuites()
+                    .build();
+
             OkHttpClient httpClient = new OkHttpClient.Builder()
-                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
+                    .sslSocketFactory(sslContext.getSocketFactory(),
+                            (X509TrustManager) trustAllCerts[0])
                     .hostnameVerifier((hostname, session) -> true)
+                    .connectionSpecs(Collections.singletonList(spec)) // ⭐关键
+                    .connectionPool(new ConnectionPool(0, 1, TimeUnit.SECONDS)) // ⭐禁用复用
                     .build();
 
             // 构建 AssumeRoleProvider,使用自定义 httpClient
@@ -244,6 +258,11 @@
             OkHttpClient httpClient = new OkHttpClient.Builder()
                     .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
                     .hostnameVerifier((hostname, session) -> true)
+                    .connectionSpecs(Collections.singletonList(
+                            new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
+                                    .tlsVersions(TlsVersion.TLS_1_2)   // 强制 TLS1.2
+                                    .build()
+                    ))
                     .build();
 
             this.client = MinioClient.builder()
diff --git a/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java b/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
index b2746ad..3835f2c 100644
--- a/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
+++ b/ard-route/src/main/java/com/ard/route/domain/route/ArdRouteInfo.java
@@ -29,10 +29,6 @@
     @Excel(name = "文件路径")
     private String path;
 
-//    /** 文件路径1 */
-//    @Excel(name = "文件路径1")
-//    private String path1;
-
     /** 分组ID */
     @Excel(name = "分组ID")
     private String groupId;
@@ -50,7 +46,7 @@
     private String payload;
 
     /**
-     * 是否只读 是否只读
+     * 是否只读
      * 0:否
      * 1:是
      */
@@ -66,6 +62,14 @@
     private String orderByTime;
 
     /**
+     * 是否循环 isLoop
+     * 0:否
+     * 1:是
+     */
+    @Excel(name = "是否循环")
+    private String isLoop;
+
+    /**
      * 生成kmz文件实体类
      */
     private UavRouteReq uavRouteReq;
diff --git a/ard-route/src/main/java/com/ard/route/service/IArdRouteInfoService.java b/ard-route/src/main/java/com/ard/route/service/IArdRouteInfoService.java
index 19e0e1e..65e911c 100644
--- a/ard-route/src/main/java/com/ard/route/service/IArdRouteInfoService.java
+++ b/ard-route/src/main/java/com/ard/route/service/IArdRouteInfoService.java
@@ -114,7 +114,7 @@
      * @param boxSn 云盒SN编号
      * @return 结果
      */
-    public Boolean routeBegins(String boxSn);
+    public Boolean routeBegins(String id, String boxSn);
 
     /**
      * 暂停航线
diff --git a/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java b/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
index 97f5cd3..5a0b49c 100644
--- a/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
+++ b/ard-route/src/main/java/com/ard/route/service/impl/ArdRouteInfoServiceImpl.java
@@ -25,8 +25,10 @@
 import com.ard.route.mapper.ArdRouteInfoMapper;
 import com.ard.route.service.IArdRouteInfoService;
 import com.ard.route.service.UavRouteService;
+import com.ard.work.domain.cache.UavTelemetryDataCache;
 import com.ard.work.domain.cache.UavWaylineCache;
 import com.ard.work.domain.dto.state.PointData;
+import com.ard.work.domain.dto.telemetry.TelemetryData;
 import com.ard.work.domain.dto.wayline.*;
 import com.ard.work.service.ITyService;
 import org.slf4j.Logger;
@@ -86,17 +88,26 @@
             throw new RuntimeException(e);
         }
 
-        // 主逻辑优化
-        double altitudeOffset = getDoublePoint(ardRouteInfo.getUavRouteReq().getTakeOffRefPoint(), "alt");
+        // 如果参考起飞点不为空,将每个航点高度进行加工。
+        if (ardRouteInfo.getUavRouteReq().getTakeOffRefPoint() != null){
 
-        for (RoutePointReq routePointReq : ardRouteInfo.getUavRouteReq().getRoutePointList()) {
-            // 调整航点高度
-            adjustRoutePointHeight(routePointReq, altitudeOffset);
+            double altitudeOffset = getDoublePoint(ardRouteInfo.getUavRouteReq().getTakeOffRefPoint(), "alt");
+
+            for (RoutePointReq routePointReq : ardRouteInfo.getUavRouteReq().getRoutePointList()) {
+                // 调整每个航点高度
+                adjustRoutePointHeight(routePointReq, altitudeOffset);
+            }
+        }else {
+            // 如果没有设置参考起飞点,将第一个航点设置为参考起飞点。
+            ardRouteInfo.getUavRouteReq().setTakeOffRefPoint(
+                    ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getLatitude().toString() +"," +
+                    ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getLongitude().toString()+","+
+                    ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getHeight().toString());
         }
+
         return ardRouteInfo;
     }
 
-    // 提取航点高度调整逻辑到方法中
     private void adjustRoutePointHeight(RoutePointReq routePointReq, double altitudeOffset) {
         routePointReq.setHeight(routePointReq.getHeight() + altitudeOffset);
     }
@@ -234,6 +245,9 @@
      */
     @Override
     public int deleteArdRouteInfoById(String id) {
+        // 删除航线(kmz)文件
+        ArdRouteInfo information = ardRouteInfoMapper.selectArdRouteInfoById(id);
+        delOssService(information);
         return ardRouteInfoMapper.deleteArdRouteInfoById(id);
     }
 
@@ -332,7 +346,6 @@
 
     /**
      * 上传航线到边缘服务器
-     *
      * ardNoflyDto
      * @return 结果
      */
@@ -346,6 +359,34 @@
         } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeException(e);
         }
+
+        // 获取第一个点
+        double firstPointLng = route.getUavRouteReq().getRoutePointList().get(0).getLongitude();
+        double firstPointLat = route.getUavRouteReq().getRoutePointList().get(0).getLatitude();
+
+        // 获取最后一个点
+        double lastPointLng = route.getUavRouteReq().getRoutePointList().get(route.getUavRouteReq().getRoutePointList().size()-1).getLongitude();
+        double lastPointLat = route.getUavRouteReq().getRoutePointList().get(route.getUavRouteReq().getRoutePointList().size()-1).getLatitude();
+
+        // 无人机遥测数据,用于校验真实起飞点和第一个点是否在禁飞区
+        TelemetryData telemetryData = UavTelemetryDataCache.get(boxSn);
+        double telemetryDataLng = 0;
+        double telemetryDataLat = 0;
+        if (telemetryData != null){
+            telemetryDataLng = telemetryData.getLng();
+            telemetryDataLat = telemetryData.getLat();
+        }
+
+        ArdNoflyDto dto1 = new ArdNoflyDto();
+        dto1.setCurrent(new Vertex(telemetryDataLng,telemetryDataLat));
+        dto1.setTarget(new Vertex(firstPointLng,firstPointLat));
+        verifyNoFlyZone(dto1);
+
+        ArdNoflyDto dto2 = new ArdNoflyDto();
+        dto2.setCurrent(new Vertex(lastPointLng,lastPointLat));
+        dto2.setTarget(new Vertex(telemetryDataLng,telemetryDataLat));
+        verifyNoFlyZone(dto2);
+
         // 判断禁飞区
         arrayWithinNoFlyZone(route.getUavRouteReq().getRoutePointList());
         // 1.2通过minio获取航线信息
@@ -369,7 +410,12 @@
      * @return 结果
      */
     @Override
-    public Boolean routeBegins(String boxSn) {
+    public Boolean routeBegins(String id,String boxSn) {
+        ArdRouteInfo route = ardRouteInfoMapper.selectArdRouteInfoById(id);
+        // 判断是否循环航线
+        if ("1".equals(route.getIsLoop())) {
+            deleteArdRouteInfoById(id);
+        }
         WayLineBeginDTO wayLineBeginDTO = new WayLineBeginDTO(boxSn);
         tyService.wayLineBegin(wayLineBeginDTO);
         return true;
diff --git a/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml b/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
index 94af829..658cfeb 100644
--- a/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
+++ b/ard-route/src/main/resources/mapper/ArdRouteInfoMapper.xml
@@ -8,7 +8,6 @@
         <result property="id"    column="id"    />
         <result property="name"    column="name"    />
         <result property="path"    column="path"    />
-<!--        <result property="path1"    column="path1"    />-->
         <result property="groupId"    column="group_id"    />
         <result property="type"    column="type"    />
         <result property="aircraft"    column="aircraft"    />
@@ -20,13 +19,13 @@
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
         <result property="pointCount"    column="point_count"    />
+        <result property="isLoop"    column="is_loop"    />
     </resultMap>
 
     <sql id="selectArdRouteInfoVo">
         select id,
                name,
                path,
-<!--               path1,-->
                group_id,
                type,
                aircraft,
@@ -37,7 +36,8 @@
                create_time,
                update_by,
                update_time,
-               point_count
+               point_count,
+               is_loop
         from ard_route_info
     </sql>
 
@@ -50,6 +50,7 @@
             <if test="type != null  and type != ''"> and type = #{type}</if>
             <if test="path != null  and path != ''"> and path = #{path}</if>
             <if test="groupId != null"> and group_id = #{groupId}</if>
+            <if test="isLoop != null"> and is_loop = #{isLoop}</if>
         </where>
         <if test="orderByTime == null and orderByTime == ''">
             ORDER BY update_time DESC
@@ -71,7 +72,6 @@
             <if test="id != null">id,</if>
             <if test="name != null">name,</if>
             <if test="path != null">path,</if>
-<!--            <if test="path1 != null">path1,</if>-->
             <if test="groupId != null">group_id,</if>
             <if test="type != null">type,</if>
             <if test="aircraft != null">aircraft,</if>
@@ -83,12 +83,12 @@
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="pointCount != null">point_count,</if>
+            <if test="isLoop != null">is_loop,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="name != null">#{name},</if>
             <if test="path != null">#{path},</if>
-<!--            <if test="path1 != null">#{path1},</if>-->
             <if test="groupId != null">#{groupId},</if>
             <if test="type != null">#{type},</if>
             <if test="aircraft != null">#{aircraft},</if>
@@ -100,6 +100,7 @@
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="pointCount != null">#{pointCount},</if>
+            <if test="isLoop != null">#{isLoop},</if>
          </trim>
     </insert>
 
@@ -108,7 +109,6 @@
         <trim prefix="SET" suffixOverrides=",">
             <if test="name != null">name = #{name},</if>
             <if test="path != null">path = #{path},</if>
-<!--            <if test="path1 != null">path1 = #{path1},</if>-->
             <if test="groupId != null">group_id = #{groupId},</if>
             <if test="type != null">type = #{type},</if>
             <if test="aircraft != null">aircraft = #{aircraft},</if>
@@ -120,6 +120,7 @@
             <if test="updateBy != null">update_by = #{updateBy},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="pointCount != null">point_count = #{pointCount},</if>
+            <if test="isLoop != null">is_loop = #{isLoop},</if>
         </trim>
         where id = #{id}
     </update>
@@ -148,7 +149,7 @@
     </delete>
 
     <select id="selectArdRouteInfoByGroupId" parameterType="String" resultMap="ArdRouteInfoResult">
-        select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time,point_count from ard_route_info
+        select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time,point_count,is_loop from ard_route_info
         <where>
             <if test="groupId != null "> and group_id = #{groupId}</if>
         </where>
diff --git a/ard-work/src/main/java/com/ard/work/component/forest/TyClient.java b/ard-work/src/main/java/com/ard/work/component/forest/TyClient.java
index 928ea74..badc96f 100644
--- a/ard-work/src/main/java/com/ard/work/component/forest/TyClient.java
+++ b/ard-work/src/main/java/com/ard/work/component/forest/TyClient.java
@@ -1,9 +1,6 @@
 package com.ard.work.component.forest;
 
-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.dto.TokenDTO;
+import com.ard.work.domain.dto.*;
 import com.ard.work.domain.receiver.*;
 import com.dtflys.forest.annotation.*;
 
@@ -43,13 +40,18 @@
     @Post(value = TyConst.POST_BOX_HISTORY, interceptor = TokenInterceptor.class)
     TyHttpCommonReceiver<List<BoxHistoryReceiver>> getBoxHistory(@Var("serverId") String serverId,
                                                                  @JSONBody BoxHistoryDTO boxHistoryDTO);
-
     /**
      * 获取任务照片
      */
     @Post(value = TyConst.POST_BOX_PHOTOS, interceptor = TokenInterceptor.class)
     TyHttpCommonReceiver<List<BoxPhotosReceiver>> getBoxPhotos(@Var("serverId") String serverId,
                                                                @JSONBody BoxPhotosDTO boxPhotosDTO);
+    /**
+     * 获取任务视频
+     */
+    @Post(value = TyConst.POST_BOX_VIDEOS, interceptor = TokenInterceptor.class)
+    TyHttpCommonReceiver<List<BoxVideosReceiver>> getBoxVideos(@Var("serverId") String serverId,
+                                                               @JSONBody BoxVideosDTO boxVideosDTO);
 
     /**
      * 修改云盒设置
diff --git a/ard-work/src/main/java/com/ard/work/component/forest/TyConst.java b/ard-work/src/main/java/com/ard/work/component/forest/TyConst.java
index dba5e71..4d7f49c 100644
--- a/ard-work/src/main/java/com/ard/work/component/forest/TyConst.java
+++ b/ard-work/src/main/java/com/ard/work/component/forest/TyConst.java
@@ -8,6 +8,7 @@
     public static final String POST_UPDATE_LIVE = "/eapi/update/live";
     public static final String GET_BOX_LIVE_URL = "/eapi/box/pullUrl/{boxSn}";
     public static final String POST_BOX_PHOTOS = "/eapi/box/photos";
+    public static final String POST_BOX_VIDEOS = "/eapi/box/videos";
     public static final String GET_OPEN_LIVE = "/eapi/box/openlive/{boxSn}";
     public static final String GET_CLOSE_LIVE = "/eapi/box/closelive/{boxSn}";
 }
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/work/domain/dto/BoxVideosDTO.java b/ard-work/src/main/java/com/ard/work/domain/dto/BoxVideosDTO.java
new file mode 100644
index 0000000..5dfe819
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/domain/dto/BoxVideosDTO.java
@@ -0,0 +1,27 @@
+package com.ard.work.domain.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class BoxVideosDTO {
+
+    @JsonProperty("boxSn")
+    private String boxSn;
+
+    @JsonProperty("taskId")
+    private Integer taskId;
+
+    @JsonProperty("pageIndex")
+    private Integer pageIndex;
+
+    @JsonProperty("pageSize")
+    private Integer pageSize;
+
+}
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTaskPart.java b/ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTaskPart.java
index 7f18ee1..a5991cc 100644
--- a/ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTaskPart.java
+++ b/ard-work/src/main/java/com/ard/work/domain/entity/ArdFlightTaskPart.java
@@ -3,6 +3,8 @@
 import com.ard.common.core.domain.BaseEntity;
 import lombok.*;
 
+import java.util.Date;
+
 @EqualsAndHashCode(callSuper = true)
 @Data
 @Builder
@@ -13,4 +15,7 @@
     private String boxSn;
     private Integer count;
     private byte[] dataPart;
+    private Date startTime;
+    private Date endTime;
+
 }
diff --git a/ard-work/src/main/java/com/ard/work/domain/receiver/BoxVideosReceiver.java b/ard-work/src/main/java/com/ard/work/domain/receiver/BoxVideosReceiver.java
new file mode 100644
index 0000000..704d9fd
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/domain/receiver/BoxVideosReceiver.java
@@ -0,0 +1,32 @@
+package com.ard.work.domain.receiver;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class BoxVideosReceiver {
+
+    @JsonProperty("id")
+    private Long id;
+
+    @JsonProperty("taskId")
+    private Long taskId;
+
+    @JsonProperty("name")
+    private String name;
+
+    @JsonProperty("spanSeconds")
+    private String spanSeconds;
+
+    @JsonProperty("uri")
+    private String imgUrl;
+
+    @JsonProperty("startTime")
+    private String startTime;
+
+    @JsonProperty("endTime")
+    private String endTime;
+
+}
diff --git a/ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskPartMapper.java b/ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskPartMapper.java
index db94cd2..787e567 100644
--- a/ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskPartMapper.java
+++ b/ard-work/src/main/java/com/ard/work/mapper/ArdFlightTaskPartMapper.java
@@ -13,14 +13,10 @@
 public interface ArdFlightTaskPartMapper {
 
     /**
-     * 根据 taskId 查询分片
-     */
-    List<ArdFlightTaskPart> selectByTaskId(int taskId);
-    /**
-     * 根据 boxSn 和航线开始结束时间查询分片
+     * 根据开始结束时间查询分片
      * @return 对应时间段的分片列表
      */
-    List<ArdFlightTaskPart> selectByTaskStartTime(ArdFlightTaskPart ardFlightTaskPart);
+    List<ArdFlightTaskPart> selectByTimeRange(ArdFlightTaskPart ardFlightTaskPart);
 
     int insert(ArdFlightTaskPart entity);
 }
diff --git a/ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java b/ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java
index 78b1125..2e25e77 100644
--- a/ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java
+++ b/ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java
@@ -28,6 +28,8 @@
      */
     public List<ArdServerInfo> selectArdServerInfoList(ArdServerInfo ardServerInfo);
 
+    public List<ArdServerInfo> selectArdServerInfoListNo(ArdServerInfo ardServerInfo);
+
     /**
      * 新增服务器管理
      * 
diff --git a/ard-work/src/main/java/com/ard/work/service/ITyService.java b/ard-work/src/main/java/com/ard/work/service/ITyService.java
index 9f40e9a..18db889 100644
--- a/ard-work/src/main/java/com/ard/work/service/ITyService.java
+++ b/ard-work/src/main/java/com/ard/work/service/ITyService.java
@@ -3,6 +3,7 @@
 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.dto.BoxVideosDTO;
 import com.ard.work.domain.dto.camera.*;
 import com.ard.work.domain.dto.manual.*;
 import com.ard.work.domain.dto.speaker.*;
@@ -32,12 +33,14 @@
 
     /**
      * 获取边缘服务器token信息
+     *
      * @return
      */
     AccessTokenReceiver getAccessToken(String ServerId);
 
     /**
      * 获取全部服务器云盒列表
+     *
      * @return
      */
     List<BoxInfoReceiver> getBoxList();
@@ -51,42 +54,56 @@
 
     /**
      * 获取直播地址
+     *
      * @return
      */
     BoxStreamUrlReceiver getBoxLiveUrl(@Var("boxSn") String boxSn);
 
     /**
      * 获取飞行历史
+     *
      * @return
      */
     List<BoxHistoryReceiver> getBoxHistory(BoxHistoryDTO boxHistoryDTO);
 
     /**
-     * 获取盒子图片
+     * 获取任务图片
+     *
      * @return
      */
     List<BoxPhotosReceiver> getBoxPhotos(BoxPhotosDTO boxPhotosDTO);
 
     /**
+     * 获取任务视频
+     *
+     * @return
+     */
+    List<BoxVideosReceiver> getBoxVideos(BoxVideosDTO boxVideosDTO);
+
+    /**
      * 修改云盒设置
+     *
      * @return
      */
     Boolean updateBoxSettings(BoxSettingsDTO boxSettingsDTO);
 
     /**
      * 设置返航高度
+     *
      * @return
      */
     Boolean updateReturnHeight(ReturnHeightSettingDTO returnHeightSettingDTO);
 
     /**
      * 设置视频码流
+     *
      * @return
      */
     Boolean updateVideoStream(VideoStreamSettingDTO videoStreamSettingDTO);
 
     /**
      * 设置返航点
+     *
      * @return
      */
     Boolean updateReturnPoint(ReturnPointSettingDTO returnPointSettingDTO);
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskPartServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskPartServiceImpl.java
index 46c0ef5..0917724 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskPartServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/ArdFlightTaskPartServiceImpl.java
@@ -14,11 +14,13 @@
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
+
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * 轨迹分片处理业务
  */
@@ -28,7 +30,8 @@
 public class ArdFlightTaskPartServiceImpl implements IArdFlightTaskPartService {
 
     private final ArdFlightTaskPartMapper ardflightTaskPartMapper;
-
+    // 上一次飞行状态缓存
+    private final ConcurrentHashMap<String, Integer> lastFlightStatusMap = new ConcurrentHashMap<>();
     /**
      * 缓存:boxSn -> 当前分片数据
      */
@@ -60,12 +63,20 @@
                 return; // 超过 3 秒没有新遥测 → 认为已离线或冻结,不记录
             }
 
-            // 3️⃣ 飞行状态必须是飞行中
-            if(uavState.getFlightControllerState().getFlightStatus()!=2)
-            {
-                return; // 飞行状态不是飞行中,不记录
-            }
+            int currentStatus = uavState.getFlightControllerState().getFlightStatus();
+            Integer lastStatus = lastFlightStatusMap.get(boxSn);
 
+            // 仅在“飞行中 → 非飞行中”状态变化时 flush
+            if (lastStatus != null && lastStatus == 2 && currentStatus != 2) {
+                flushRemaining(boxSn);
+            }
+            lastFlightStatusMap.put(boxSn, currentStatus);
+
+            // 只有飞行中才添加缓存
+            if (currentStatus == 2) {
+                UavFlightStateDTO dto = new UavFlightStateDTO(uavState, telemetryData, dataTs);
+                addTelemetryData(dto);
+            }
             UavFlightStateDTO dto = new UavFlightStateDTO(
                     uavState,
                     telemetryData,
@@ -102,16 +113,17 @@
 
         try {
             byte[] blobData = SerializeUtil.serialize(dataList);
-
+            // 取第一个和最后一个状态时间
+            long startTs = dataList.get(0).getTimestamp();
+            long endTs = dataList.get(dataList.size() - 1).getTimestamp();
             ArdFlightTaskPart part = ArdFlightTaskPart.builder()
                     .boxSn(boxSn)
                     .count(dataList.size())
                     .dataPart(blobData)
+                    .startTime(new Date(startTs))
+                    .endTime(new Date(endTs))
                     .build();
-            // 使用 list 中第一条数据的时间作为 createTime
-            long firstTimeMillis = dataList.get(0).getTimestamp();
-            Date createTime = new Date(firstTimeMillis);
-            part.setCreateTime(createTime);
+            part.setCreateTime(new Date());
             ardflightTaskPartMapper.insert(part);
 
             log.info("设备 {} 分片保存 {} 条飞行数据到数据库成功", boxSn, dataList.size());
@@ -143,7 +155,7 @@
     public List<UavFlightStateDTO> getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart) {
         List<UavFlightStateDTO> allData = new ArrayList<>();
         String boxSn = ardFlightTaskPart.getBoxSn();
-        List<ArdFlightTaskPart> parts = ardflightTaskPartMapper.selectByTaskStartTime(ardFlightTaskPart);
+        List<ArdFlightTaskPart> parts = ardflightTaskPartMapper.selectByTimeRange(ardFlightTaskPart);
         for (ArdFlightTaskPart part : parts) {
             try {
                 List<UavFlightStateDTO> partData = SerializeUtil.deserialize(part.getDataPart());
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java
index d4063de..ad2e534 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java
@@ -5,9 +5,11 @@
 import com.ard.work.component.forest.TyClient;
 import com.ard.work.component.netty.TyTcpClientManager;
 import com.ard.work.domain.dto.TokenDTO;
+import com.ard.work.domain.entity.ArdDroneInfo;
 import com.ard.work.domain.entity.ArdServerInfo;
 import com.ard.work.domain.receiver.AccessTokenReceiver;
 import com.ard.work.domain.receiver.TyHttpCommonReceiver;
+import com.ard.work.mapper.ArdDroneInfoMapper;
 import com.ard.work.mapper.ArdServerInfoMapper;
 import com.ard.work.service.IArdServerInfoService;
 import com.dtflys.forest.exceptions.ForestRuntimeException;
@@ -30,11 +32,16 @@
 public class ArdServerInfoServiceImpl implements IArdServerInfoService {
 
     @Resource
-    private ArdServerInfoMapper ardServerInfoMapper;
-    @Resource
     private TyClient tyClient;
+
+    @Resource
+    private ArdServerInfoMapper ardServerInfoMapper;
+
     @Resource
     private TyTcpClientManager tyTcpClientManager;
+
+    @Resource
+    private ArdDroneInfoMapper ArdDroneInfoMapper;
 
     /**
      * 查询服务器管理
@@ -59,6 +66,24 @@
         return ardServerInfoMapper.selectArdServerInfoList(ardServerInfo);
     }
 
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public List<ArdServerInfo> selectArdServerInfoListNo(ArdServerInfo ardServerInfo) {
+
+//        List<ArdDroneInfo> ardDroneInfos = ArdDroneInfoMapper.selectArdDroneList(new ArdDroneInfo());
+//        for (ArdDroneInfo ardDroneInfo : ardDroneInfos) {
+//            ardDroneInfo.getBoxSn();
+//        }
+//        List<ArdServerInfo> servers = ardServerInfoMapper.selectArdServerInfoList(ardServerInfo);
+//        for (ArdServerInfo server : servers) {
+//            for (ArdDroneInfo ardDroneInfo : server.getArdDroneInfoList()) {
+//                ardDroneInfo.getBoxSn();
+//            }
+//        }
+
+        return ardServerInfoMapper.selectArdServerInfoList(ardServerInfo);
+    }
+
     /**
      * 新增服务器管理
      *
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
index a2eba51..c6a0d66 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java
@@ -33,6 +33,7 @@
 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.dto.BoxVideosDTO;
 import com.ard.work.domain.dto.camera.*;
 import com.ard.work.domain.dto.control.AbsAngleControlDTO;
 import com.ard.work.domain.dto.control.AngleControlDTO;
@@ -157,7 +158,7 @@
     }
 
     /**
-     * 获取盒子图片
+     * 获取任务图片
      *
      * @return List<BoxPhotosReceiver>
      */
@@ -172,7 +173,22 @@
                 boxPhotosDTO);
         return boxPhotos == null ? null : boxPhotos.getContent();
     }
-
+    /**
+     * 获取任务视频
+     *
+     * @return List<BoxVideosReceiver>
+     */
+    @Override
+    public List<BoxVideosReceiver> getBoxVideos(BoxVideosDTO boxVideosDTO) {
+        String boxSn = boxVideosDTO.getBoxSn();
+        ArdDroneInfo ardDroneInfo = ardDroneService.selectArdDroneByboxSn(boxSn);
+        if (ardDroneInfo == null) {
+            throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn);
+        }
+        TyHttpCommonReceiver<List<BoxVideosReceiver>> boxVideos = tyClient.getBoxVideos(ardDroneInfo.getServerId(),
+                boxVideosDTO);
+        return boxVideos == null ? null : boxVideos.getContent();
+    }
     /**
      * 修改云盒设置
      */
@@ -336,9 +352,10 @@
             throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn);
         }
         //设置相机模式为拍照模式
-        updateCameraMode(CameraModeDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build());
+        //updateCameraMode(CameraModeDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build());
         //设置拍照回传
-        photoReturnToggle(PhotoReturnToggleDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build());
+        //photoReturnToggle(PhotoReturnToggleDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01)
+        // .build());
 
         CapturePicCmd capturePicCommand = new CapturePicCmd(capturePicDto);
         this.sendMessage(ardDroneInfo.getServerId(), capturePicCommand);
@@ -358,7 +375,7 @@
         }
         BaseCmd baseCmd;
         if (recordDto.getIsRecord()) {
-            updateCameraMode(CameraModeDTO.builder().boxSn(recordDto.getBoxSn()).actionParam((byte) 0x02).build());
+            //updateCameraMode(CameraModeDTO.builder().boxSn(recordDto.getBoxSn()).actionParam((byte) 0x02).build());
             baseCmd = new RecordStartCmd(recordDto);
         } else {
             baseCmd = new RecordStopCmd(recordDto);
diff --git a/ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml b/ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml
index 5f7bd31..a231ccf 100644
--- a/ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml
+++ b/ard-work/src/main/resources/mapper/ArdFlightTaskMapper.xml
@@ -61,7 +61,7 @@
                     AND aft.create_time &gt;= #{params.beginTime}
                 </if>
                 <if test="params.endTime != null"><!-- 结束时间检索 -->
-                    ANDaft.create_time &lt;= #{params.endTime}
+                    AND aft.create_time &lt;= #{params.endTime}
                 </if>
             </trim>
         </where>
diff --git a/ard-work/src/main/resources/mapper/ArdFlightTaskPartMapper.xml b/ard-work/src/main/resources/mapper/ArdFlightTaskPartMapper.xml
index c11cad7..1416f31 100644
--- a/ard-work/src/main/resources/mapper/ArdFlightTaskPartMapper.xml
+++ b/ard-work/src/main/resources/mapper/ArdFlightTaskPartMapper.xml
@@ -8,21 +8,27 @@
     <!-- 插入一条分片数据 -->
     <insert id="insert" parameterType="ArdFlightTaskPart" useGeneratedKeys="true" keyProperty="id">
         INSERT INTO ard_flight_task_part
-            (box_sn, count, data_part, create_time)
-        VALUES
-            (#{boxSn}, #{count}, #{dataPart}, #{createTime})
+            (box_sn, count, data_part, start_time, end_time, create_time)
+        VALUES (#{boxSn}, #{count}, #{dataPart}, #{startTime}, #{endTime}, #{createTime})
     </insert>
-    <select id="selectByTaskStartTime" resultType="ArdFlightTaskPart">
+    <select id="selectByTimeRange" resultType="ArdFlightTaskPart">
         SELECT *
         FROM ard_flight_task_part u
-        WHERE u.box_sn = #{boxSn}
-        <if test="params.beginTime != null"><!-- 开始时间检索 -->
-            AND u.create_time &gt;= #{params.beginTime}
-        </if>
-        <if test="params.endTime != null"><!-- 结束时间检索 -->
-            AND u.create_time &lt;= #{params.endTime}
-        </if>
-        ORDER BY u.create_time asc
+        <where>
+            u.box_sn = #{boxSn}
+            <!-- 动态参数中的开始时间 -->
+            <if test="params.beginTime != null">
+                AND u.end_time &gt;= #{params.beginTime}  <!-- blob 内最后状态 >= 架次起飞 -->
+            </if>
+            <!-- 动态参数中的结束时间 -->
+            <if test="params.endTime != null">
+                AND u.start_time &lt;= #{params.endTime}  <!-- blob 内第一状态 <= 架次降落 -->
+            </if>
+        </where>
+        ORDER BY u.start_time ASC
     </select>
 
+
+
+
 </mapper>

--
Gitblit v1.9.3