From 1ab85e9fd1b392d36c6f2b08754249e4574ea4e8 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Fri, 17 Oct 2025 16:22:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 ard-vtdu/pom.xml                                                                 |    1 
 ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java              |    7 
 ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyBox.java          |   15 
 ard-work/src/main/java/com/ard/work/service/impl/TyServiceImpl.java              |  100 ++---
 ard-system/src/main/java/com/ard/data/noflyzone/utils/GeoUtils.java              |  171 +++++++++
 ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java      |   97 +---
 ard-work/src/main/resources/mapper/ArdDroneInfoMapper.xml                        |   66 ++-
 pom.xml                                                                          |    8 
 ard-admin/src/main/java/com/ard/web/controller/work/UavBaseController.java       |   21 
 ard-vtdu/src/main/java/com/ard/vtdu/client/MediamtxAuthInterceptor.java          |   54 +++
 ard-work/src/main/java/com/ard/work/component/forest/TokenInterceptor.java       |   24 
 ard-admin/src/main/java/com/ard/web/controller/device/ArdCameraController.java   |   16 
 ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml                       |    6 
 ard-work/src/main/java/com/ard/work/service/IArdDroneInfoService.java            |    5 
 ard-work/src/main/java/com/ard/work/service/impl/ArdServerInfoServiceImpl.java   |    4 
 ard-admin/src/main/java/com/ard/web/controller/work/ArdServerInfoController.java |    6 
 ard-work/src/main/java/com/ard/work/util/UtilMethod.java                         |   35 +
 ard-system/src/main/java/com/ard/data/noflyzone/domain/Vertex.java               |   30 +
 ard-admin/src/main/java/com/ard/web/controller/data/ArdModelController.java      |   12 
 ard-work/src/main/java/com/ard/work/component/netty/TcpClientUtil.java           |   42 ++
 ard-admin/src/main/java/com/ard/web/controller/data/ArdTileController.java       |   12 
 ard-work/src/main/java/com/ard/work/domain/entity/ArdServerInfo.java             |    8 
 ard-work/pom.xml                                                                 |    1 
 ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java              |    3 
 /dev/null                                                                        |   38 --
 ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java    |  138 ++++++-
 ard-work/src/main/java/com/ard/work/component/netty/cache/TyTcpServerCache.java  |   68 +++
 ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyZone.java         |   24 +
 ard-admin/src/main/java/com/ard/web/controller/data/ArdMapController.java        |   12 
 ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java   |   10 
 ard-admin/src/main/java/com/ard/web/controller/work/ArdDroneInfoController.java  |   20 +
 ard-work/src/main/java/com/ard/work/service/IArdServerInfoService.java           |    2 
 ard-work/src/main/java/com/ard/work/service/ITyService.java                      |    9 
 33 files changed, 784 insertions(+), 281 deletions(-)

diff --git a/ard-admin/src/main/java/com/ard/web/controller/data/ArdMapController.java b/ard-admin/src/main/java/com/ard/web/controller/data/ArdMapController.java
index 66ae78e..5a97336 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/data/ArdMapController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/data/ArdMapController.java
@@ -42,7 +42,7 @@
      * 查询地图管理列表
      */
     @ApiOperation("查询地图管理列表")
-    @PreAuthorize("@ss.hasPermi('system:map:list')")
+    @PreAuthorize("@ss.hasPermi('data:map:list')")
     @GetMapping("/list")
     public TableDataInfo list(ArdMap ardMap) {
         startPage();
@@ -54,7 +54,7 @@
      * 导出地图管理列表
      */
     @ApiOperation("导出地图管理列表")
-    @PreAuthorize("@ss.hasPermi('system:map:export')")
+    @PreAuthorize("@ss.hasPermi('data:map:export')")
     @Log(title = "地图管理", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, ArdMap ardMap) {
@@ -67,7 +67,7 @@
      * 获取地图管理详细信息
      */
     @ApiOperation("获取地图管理详细信息")
-    @PreAuthorize("@ss.hasPermi('system:map:query')")
+    @PreAuthorize("@ss.hasPermi('data:map:query')")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") String id) {
         return success(ardMapService.selectArdMapById(id));
@@ -77,7 +77,7 @@
      * 新增地图管理
      */
     @ApiOperation("新增地图管理")
-    @PreAuthorize("@ss.hasPermi('system:map:add')")
+    @PreAuthorize("@ss.hasPermi('data:map:add')")
     @Log(title = "地图管理", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody ArdMap ardMap) {
@@ -88,7 +88,7 @@
      * 修改地图管理
      */
     @ApiOperation("修改地图管理")
-    @PreAuthorize("@ss.hasPermi('system:map:edit')")
+    @PreAuthorize("@ss.hasPermi('data:map:edit')")
     @Log(title = "地图管理", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody ArdMap ardMap) {
@@ -99,7 +99,7 @@
      * 删除地图管理
      */
     @ApiOperation("删除地图管理")
-    @PreAuthorize("@ss.hasPermi('system:map:remove')")
+    @PreAuthorize("@ss.hasPermi('data:map:remove')")
     @Log(title = "地图管理", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable String[] ids) {
diff --git a/ard-admin/src/main/java/com/ard/web/controller/data/ArdModelController.java b/ard-admin/src/main/java/com/ard/web/controller/data/ArdModelController.java
index fec8c9d..d9e6612 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/data/ArdModelController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/data/ArdModelController.java
@@ -42,7 +42,7 @@
      * 查询模型管理列表
      */
     @ApiOperation("查询模型管理列表")
-    @PreAuthorize("@ss.hasPermi('system:model:list')")
+    @PreAuthorize("@ss.hasPermi('data:model:list')")
     @GetMapping("/list")
     public TableDataInfo list(ArdModel ardModel) {
         startPage();
@@ -54,7 +54,7 @@
      * 导出模型管理列表
      */
     @ApiOperation("导出模型管理列表")
-    @PreAuthorize("@ss.hasPermi('system:model:export')")
+    @PreAuthorize("@ss.hasPermi('data:model:export')")
     @Log(title = "模型管理", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, ArdModel ardModel) {
@@ -67,7 +67,7 @@
      * 获取模型管理详细信息
      */
     @ApiOperation("获取模型管理详细信息")
-    @PreAuthorize("@ss.hasPermi('system:model:query')")
+    @PreAuthorize("@ss.hasPermi('data:model:query')")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") String id) {
         return success(ardModelService.selectArdModelById(id));
@@ -77,7 +77,7 @@
      * 新增模型管理
      */
     @ApiOperation("新增模型管理")
-    @PreAuthorize("@ss.hasPermi('system:model:add')")
+    @PreAuthorize("@ss.hasPermi('data:model:add')")
     @Log(title = "模型管理", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody ArdModel ardModel) {
@@ -88,7 +88,7 @@
      * 修改模型管理
      */
     @ApiOperation("修改模型管理")
-    @PreAuthorize("@ss.hasPermi('system:model:edit')")
+    @PreAuthorize("@ss.hasPermi('data:model:edit')")
     @Log(title = "模型管理", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody ArdModel ardModel) {
@@ -99,7 +99,7 @@
      * 删除模型管理
      */
     @ApiOperation("删除模型管理")
-    @PreAuthorize("@ss.hasPermi('system:model:remove')")
+    @PreAuthorize("@ss.hasPermi('data:model:remove')")
     @Log(title = "模型管理", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable String[] ids) {
diff --git a/ard-admin/src/main/java/com/ard/web/controller/data/ArdTileController.java b/ard-admin/src/main/java/com/ard/web/controller/data/ArdTileController.java
index 7ae8091..dc69330 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/data/ArdTileController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/data/ArdTileController.java
@@ -42,7 +42,7 @@
      * 查询tile管理列表
      */
     @ApiOperation("查询tile管理列表")
-    @PreAuthorize("@ss.hasPermi('system:tile:list')")
+    @PreAuthorize("@ss.hasPermi('data:tile:list')")
     @GetMapping("/list")
     public TableDataInfo list(ArdTile ardTile) {
         startPage();
@@ -54,7 +54,7 @@
      * 导出tile管理列表
      */
     @ApiOperation("导出tile管理列表")
-    @PreAuthorize("@ss.hasPermi('system:tile:export')")
+    @PreAuthorize("@ss.hasPermi('data:tile:export')")
     @Log(title = "tile管理", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, ArdTile ardTile) {
@@ -67,7 +67,7 @@
      * 获取tile管理详细信息
      */
     @ApiOperation("获取tile管理详细信息")
-    @PreAuthorize("@ss.hasPermi('system:tile:query')")
+    @PreAuthorize("@ss.hasPermi('data:tile:query')")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") String id) {
         return success(ardTileService.selectArdTileById(id));
@@ -77,7 +77,7 @@
      * 新增tile管理
      */
     @ApiOperation("新增tile管理")
-    @PreAuthorize("@ss.hasPermi('system:tile:add')")
+    @PreAuthorize("@ss.hasPermi('data:tile:add')")
     @Log(title = "tile管理", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody ArdTile ardTile) {
@@ -88,7 +88,7 @@
      * 修改tile管理
      */
     @ApiOperation("修改tile管理")
-    @PreAuthorize("@ss.hasPermi('system:tile:edit')")
+    @PreAuthorize("@ss.hasPermi('data:tile:edit')")
     @Log(title = "tile管理", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody ArdTile ardTile) {
@@ -99,7 +99,7 @@
      * 删除tile管理
      */
     @ApiOperation("删除tile管理")
-    @PreAuthorize("@ss.hasPermi('system:tile:remove')")
+    @PreAuthorize("@ss.hasPermi('data:tile:remove')")
     @Log(title = "tile管理", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable String[] ids) {
diff --git a/ard-admin/src/main/java/com/ard/web/controller/device/ArdCameraController.java b/ard-admin/src/main/java/com/ard/web/controller/device/ArdCameraController.java
index 821df96..d017422 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/device/ArdCameraController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/device/ArdCameraController.java
@@ -29,7 +29,7 @@
  */
 @Slf4j
 @RestController
-@RequestMapping("/device/cameras")
+@RequestMapping("/device/camera")
 @Api(tags = "相机管理接口")
 public class ArdCameraController extends BaseController {
 
@@ -39,7 +39,7 @@
     /**
      * 查询相机设备列表
      */
-    @PreAuthorize("@ss.hasPermi('device:cameras:list')")
+    @PreAuthorize("@ss.hasPermi('device:camera:list')")
     @GetMapping("/list")
     @ApiOperation("查询相机设备列表")
     public TableDataInfo list(ArdCamera ardCamera) {
@@ -53,7 +53,7 @@
      * 导出相机设备列表
      */
     @ApiOperation("导出相机设备列表")
-    @PreAuthorize("@ss.hasPermi('device:cameras:export')")
+    @PreAuthorize("@ss.hasPermi('device:camera:export')")
     @Log(title = "相机设备", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, ArdCamera ardCamera) {
@@ -66,7 +66,7 @@
      * 获取相机设备详细信息
      */
     @ApiOperation("获取相机设备详细信息")
-    @PreAuthorize("@ss.hasPermi('device:cameras:query')")
+    @PreAuthorize("@ss.hasPermi('device:camera:query')")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") String id) {
         return success(ardCameraService.selectArdCameraById(id));
@@ -76,7 +76,7 @@
      * 新增相机设备
      */
     @ApiOperation("新增相机设备")
-    @PreAuthorize("@ss.hasPermi('device:cameras:add')")
+    @PreAuthorize("@ss.hasPermi('device:camera:add')")
     @Log(title = "相机设备", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody ArdCamera camera) {
@@ -90,7 +90,7 @@
      * 修改相机设备
      */
     @ApiOperation("修改相机设备")
-    @PreAuthorize("@ss.hasPermi('device:cameras:edit')")
+    @PreAuthorize("@ss.hasPermi('device:camera:edit')")
     @Log(title = "相机设备", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody ArdCamera camera) {
@@ -104,7 +104,7 @@
      * 删除相机设备
      */
     @ApiOperation("删除相机设备")
-    @PreAuthorize("@ss.hasPermi('device:cameras:remove')")
+    @PreAuthorize("@ss.hasPermi('device:camera:remove')")
     @Log(title = "相机设备", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable String[] ids) {
@@ -113,7 +113,7 @@
 
 
     @Log(title = "导入相机设备", businessType = BusinessType.IMPORT)
-    @PreAuthorize("@ss.hasPermi('device:cameras:import')")
+    @PreAuthorize("@ss.hasPermi('device:camera:import')")
     @PostMapping("/importData")
     @ApiOperation("导入相机设备")
     public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
diff --git a/ard-admin/src/main/java/com/ard/web/controller/work/ArdDroneInfoController.java b/ard-admin/src/main/java/com/ard/web/controller/work/ArdDroneInfoController.java
index 8fa7b74..7bfe313 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/work/ArdDroneInfoController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/work/ArdDroneInfoController.java
@@ -106,4 +106,24 @@
         return toAjax(ardDroneInfoService.deleteArdDroneByIds(ids));
     }
 
+    /**
+     * 批量新增无人机盒子
+     */
+    @ApiOperation("批量新增无人机盒子")
+    @PreAuthorize("@ss.hasPermi('work:drone:insertArdDroneLs')")
+    @Log(title = "无人机管理", businessType = BusinessType.DELETE)
+    @PostMapping("insertArdDroneLs/{boxSn}/{deptId}")
+    public AjaxResult insertArdDroneLs(@PathVariable String[] boxSn, @PathVariable Long deptId) {
+        try {
+            int result = ardDroneInfoService.insertArdDroneLs(boxSn, deptId);
+            if (result > 0) {
+                return AjaxResult.success("成功新增 " + result + " 个无人机盒子");
+            } else {
+                return AjaxResult.success("没有需要新增的无人机盒子");
+            }
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
 }
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 1f616a4..8a531ba 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
@@ -112,9 +112,9 @@
     @ApiOperation("修改服务器状态")
     @PreAuthorize("@ss.hasPermi('work:server:updateStatus')")
     @Log(title = "服务器管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/{id}")
-    public AjaxResult updateServerStatus(@PathVariable("id") String id) {
-        return toAjax(ardServerInfoService.updateServerStatus(id));
+    @PutMapping("/{id}/{status}")
+    public AjaxResult updateServerStatus(@PathVariable("id") String id,@PathVariable("status") String status) {
+        return toAjax(ardServerInfoService.updateServerStatus(id,status));
     }
 
 }
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 4373dd7..165711a 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
@@ -43,16 +43,19 @@
         return AjaxResult.success(tyService.getAccessToken(serverId));
     }
 
-    @ApiOperation("获取六合盒子列表")
+    @ApiOperation("获取盒子列表")
     @ApiOperationSupport(order = 2)
     @GetMapping("/getBoxList")
-    public AjaxResult getBoxList() {
-        List<BoxInfoReceiver> boxList = tyService.getBoxList();
-        return AjaxResult.success(boxList);
+    public AjaxResult getBoxList(@RequestParam(required = false) String serverId) {
+        if (serverId == null) {
+            return AjaxResult.success(tyService.getBoxList());
+        } else {
+            return AjaxResult.success(tyService.getBoxList(serverId));
+        }
     }
 
     @ApiOperation("获取飞行历史")
-    @ApiOperationSupport(order = 3)
+    @ApiOperationSupport(order = 4)
     @PostMapping("/getBoxHistory")
     public AjaxResult getBoxHistory(@RequestBody BoxHistoryDTO boxHistoryDTO) {
         List<BoxHistoryReceiver> boxHistory = tyService.getBoxHistory(boxHistoryDTO);
@@ -60,7 +63,7 @@
     }
 
     @ApiOperation("获取任务照片")
-    @ApiOperationSupport(order = 4)
+    @ApiOperationSupport(order = 5)
     @PostMapping("/getBoxPhotos")
     public AjaxResult getBoxPhotos(@RequestBody BoxPhotosDTO boxPhotosDTO) {
         List<BoxPhotosReceiver> boxPhotos = tyService.getBoxPhotos(boxPhotosDTO);
@@ -68,7 +71,7 @@
     }
 
     @ApiOperation("获取直播地址")
-    @ApiOperationSupport(order = 5)
+    @ApiOperationSupport(order = 6)
     @GetMapping("/getBoxList/{boxSn}")
     public AjaxResult getBoxLiveUrl(@PathVariable("boxSn") String boxSn) {
         BoxStreamUrlReceiver boxLiveUrl = tyService.getBoxLiveUrl(boxSn);
@@ -76,7 +79,7 @@
     }
 
     @ApiOperation("修改云盒设置")
-    @ApiOperationSupport(order = 6)
+    @ApiOperationSupport(order = 7)
     @PostMapping("/updateBoxSettings")
     public AjaxResult updateBoxSettings(@RequestBody BoxSettingsDTO boxSettingsDTO) {
         Boolean state = tyService.updateBoxSettings(boxSettingsDTO);
@@ -84,7 +87,7 @@
     }
 
     @ApiOperation("根据[服务器id]获取六合盒子列表")
-    @ApiOperationSupport(order = 7)
+    @ApiOperationSupport(order = 8)
     @GetMapping("/getBoxSnToList/{id}")
     public TableDataInfo getBoxSnToList(@PathVariable("id") String id) {
         startPage();
diff --git a/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyBox.java b/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyBox.java
new file mode 100644
index 0000000..9d5ecf1
--- /dev/null
+++ b/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyBox.java
@@ -0,0 +1,15 @@
+package com.ard.data.noflyzone.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ArdNoFlyBox {
+    private double minx;
+    private double miny;
+    private double maxx;
+    private double maxy;
+}
diff --git a/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyZone.java b/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyZone.java
index ea87870..477377e 100644
--- a/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyZone.java
+++ b/ard-system/src/main/java/com/ard/data/noflyzone/domain/ArdNoFlyZone.java
@@ -1,10 +1,13 @@
 package com.ard.data.noflyzone.domain;
 
+import com.ard.data.noflyzone.utils.GeoUtils;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import com.ard.common.annotation.Excel;
 import com.ard.common.core.domain.BaseEntity;
+
+import java.util.List;
 
 /**
  * 禁飞区管理对象 ard_no_fly_zone
@@ -29,4 +32,25 @@
     /** 数据json */
     @Excel(name = "数据json")
     private FeatureCollection geojson;
+
+    /** 禁飞区外接矩形 */
+    private ArdNoFlyBox ardNoFlyBox;
+
+    private List<Vertex> vertices;
+
+    // 懒加载 / 动态计算
+    public ArdNoFlyBox getArdNoFlyBox() {
+        if (ardNoFlyBox == null && geojson != null) {
+            ardNoFlyBox = GeoUtils.getArdNoFlyBox(geojson);
+        }
+        return ardNoFlyBox;
+    }
+
+    public List<Vertex> getVertices() {
+        if (vertices == null && geojson != null) {
+            vertices = GeoUtils.toVertexes(geojson);
+        }
+        return vertices;
+    }
+
 }
diff --git a/ard-system/src/main/java/com/ard/data/noflyzone/domain/Vertex.java b/ard-system/src/main/java/com/ard/data/noflyzone/domain/Vertex.java
new file mode 100644
index 0000000..eae5166
--- /dev/null
+++ b/ard-system/src/main/java/com/ard/data/noflyzone/domain/Vertex.java
@@ -0,0 +1,30 @@
+package com.ard.data.noflyzone.domain;
+
+public class Vertex {
+	public double x;
+	public double y;
+
+	public Vertex() {
+
+	}
+
+	public Vertex(double x, double y) {
+		this.x = x;
+		this.y = y;
+	}
+
+	// 判断这个点是不是和另外一个点重合(允许极小的误差,算作同一个点
+	public boolean IsSame(Vertex anotherV) {
+		double almostZero = 0.00000001;
+		if ((Math.abs(x - anotherV.x) < almostZero) && (Math.abs(y - anotherV.y) < almostZero)) {
+            return true;
+        } else {
+            return false;
+        }
+	}
+
+	// 直线距离
+	public double Distance(Vertex anotherV) {
+		return Math.sqrt(Math.pow(x - anotherV.x, 2) + Math.pow(y - anotherV.y, 2));
+	}
+}
\ No newline at end of file
diff --git a/ard-system/src/main/java/com/ard/data/noflyzone/utils/GeoUtils.java b/ard-system/src/main/java/com/ard/data/noflyzone/utils/GeoUtils.java
new file mode 100644
index 0000000..0c8e045
--- /dev/null
+++ b/ard-system/src/main/java/com/ard/data/noflyzone/utils/GeoUtils.java
@@ -0,0 +1,171 @@
+package com.ard.data.noflyzone.utils;
+
+import com.ard.data.noflyzone.domain.ArdNoFlyBox;
+import com.ard.data.noflyzone.domain.FeatureCollection;
+import com.ard.data.noflyzone.domain.Vertex;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 几何工具类
+ */
+public class GeoUtils {
+    /**
+     * 根据 GeoJSON(FeatureCollection)计算外接矩形
+     */
+    @SuppressWarnings("unchecked")
+    public static ArdNoFlyBox getArdNoFlyBox(FeatureCollection featureCollection) {
+        if (featureCollection == null || featureCollection.getFeatures() == null) {
+            return null;
+        }
+
+        double minx = Double.MAX_VALUE;
+        double miny = Double.MAX_VALUE;
+        double maxx = Double.MIN_VALUE;
+        double maxy = Double.MIN_VALUE;
+
+        for (FeatureCollection.Feature feature : featureCollection.getFeatures()) {
+            FeatureCollection.Geometry geometry = feature.getGeometry();
+            if (geometry == null || geometry.getCoordinates() == null) {
+                continue;
+            }
+
+            String type = geometry.getType();
+            Object coords = geometry.getCoordinates();
+
+            if ("Polygon".equalsIgnoreCase(type)) {
+                // Polygon: [[[lon, lat], [lon, lat], ...]]
+                List<List<List<Double>>> rings = (List<List<List<Double>>>) coords;
+                for (List<List<Double>> ring : rings) {
+                    for (List<Double> point : ring) {
+                        if (point.size() < 2) {
+                            continue;
+                        }
+                        double x = point.get(0);
+                        double y = point.get(1);
+                        minx = Math.min(minx, x);
+                        miny = Math.min(miny, y);
+                        maxx = Math.max(maxx, x);
+                        maxy = Math.max(maxy, y);
+                    }
+                }
+            }
+            else if ("MultiPolygon".equalsIgnoreCase(type)) {
+                // MultiPolygon: [[[[lon, lat], ...]], ...]
+                List<List<List<List<Double>>>> polygons = (List<List<List<List<Double>>>>) coords;
+                for (List<List<List<Double>>> polygon : polygons) {
+                    for (List<List<Double>> ring : polygon) {
+                        for (List<Double> point : ring) {
+                            if (point.size() < 2) {
+                                continue;
+                            }
+                            double x = point.get(0);
+                            double y = point.get(1);
+                            minx = Math.min(minx, x);
+                            miny = Math.min(miny, y);
+                            maxx = Math.max(maxx, x);
+                            maxy = Math.max(maxy, y);
+                        }
+                    }
+                }
+            }
+        }
+
+        return new ArdNoFlyBox(minx, miny, maxx, maxy);
+    }
+    /**
+     * 判断点是否在多边形内(包括边界)
+     * 射线法:从该点向右发射水平射线,计算交点个数
+     *
+     * @param vertex 点对象
+     * @param vertexes 多边形顶点列表(按顺序闭合)
+     * @return true 表示点在多边形内或在边上
+     */
+    public static boolean isVertexInPoly(Vertex vertex, List<Vertex> vertexes) {
+        if (vertex == null || vertexes == null || vertexes.size() < 3) {
+            return false; // 无效输入
+        }
+
+        int count = 0;
+        int n = vertexes.size();
+
+        for (int i = 0; i < n; i++) {
+            Vertex v1 = vertexes.get(i);
+            Vertex v2 = vertexes.get((i + 1) % n);
+
+            // 1. 点就是多边形的顶点
+            if (v1.IsSame(vertex)) {
+                return true;
+            }
+
+            // 2. 点在线段上
+            double minX = Math.min(v1.x, v2.x);
+            double maxX = Math.max(v1.x, v2.x);
+            double minY = Math.min(v1.y, v2.y);
+            double maxY = Math.max(v1.y, v2.y);
+
+            // 水平线段
+            if (minY == maxY) {
+                if (vertex.y == minY && vertex.x >= minX && vertex.x <= maxX) {
+                    return true;
+                } else {
+                    continue; // 不计入交点
+                }
+            }
+
+            // 点在线段纵向范围外
+            if (vertex.y < minY || vertex.y > maxY) {
+                continue;
+            }
+
+            // 计算射线交点的 X 坐标
+            double xIntersect = v1.x + (vertex.y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y);
+
+            // 交点在点左侧,不计入
+            if (xIntersect < vertex.x) {
+                continue;
+            }
+
+            // 交点就在点上,认为在边界
+            if (xIntersect == vertex.x) {
+                return true;
+            }
+
+            // 避免射线穿过线段下端点重复计数
+            if (vertex.y == minY) {
+                continue;
+            }
+
+            // 其它情况,交点计数
+            count++;
+        }
+
+        // 奇数交点 → 点在多边形内
+        return count % 2 != 0;
+    }
+
+    /**
+     * 将 GeoJSON Polygon 的外环坐标转换成 Vertex 列表
+     */
+    public static List<Vertex> toVertexes(FeatureCollection featureCollection) {
+        List<Vertex> vertexes = new ArrayList<>();
+        if (featureCollection == null || featureCollection.getFeatures() == null || featureCollection.getFeatures().isEmpty()) {
+            return vertexes;
+        }
+        FeatureCollection.Feature feature = featureCollection.getFeatures().get(0);
+        if (feature.getGeometry() != null) {
+            List<List<List<Double>>> coords = feature.getGeometry().getCoordinates();
+            if (coords != null && !coords.isEmpty()) {
+                List<List<Double>> outerRing = coords.get(0);
+                for (List<Double> point : outerRing) {
+                    if (point.size() >= 2) {
+                        vertexes.add(new Vertex(point.get(0), point.get(1)));
+                    }
+                }
+            }
+        }
+        return vertexes;
+    }
+
+}
diff --git a/ard-vtdu/pom.xml b/ard-vtdu/pom.xml
index 883d275..e7397f1 100644
--- a/ard-vtdu/pom.xml
+++ b/ard-vtdu/pom.xml
@@ -26,7 +26,6 @@
         <dependency>
             <groupId>com.dtflys.forest</groupId>
             <artifactId>forest-spring-boot-starter</artifactId>
-            <version>1.5.33</version>
         </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
diff --git a/ard-vtdu/src/main/java/com/ard/vtdu/client/MediamtxAuthInterceptor.java b/ard-vtdu/src/main/java/com/ard/vtdu/client/MediamtxAuthInterceptor.java
new file mode 100644
index 0000000..8104be7
--- /dev/null
+++ b/ard-vtdu/src/main/java/com/ard/vtdu/client/MediamtxAuthInterceptor.java
@@ -0,0 +1,54 @@
+package com.ard.vtdu.client;
+
+import com.ard.vtdu.config.MediamtxConfig;
+import com.dtflys.forest.http.ForestRequest;
+import com.dtflys.forest.interceptor.ForestInterceptor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import java.util.Base64;
+
+/**
+ * 这个拦截器暂时先不使用,需要时在启用
+ * 用于mediaMtx流媒体接口安全请求
+ *
+ * @author lsy
+ * @date 2025/10/16
+ */
+
+@Component
+@Slf4j
+public class MediamtxAuthInterceptor implements ForestInterceptor {
+
+    /**
+     * 该方法在请求发送之前被调用, 若返回false则不会继续发送请求
+     *
+     * @Param request Forest请求对象
+     */
+    @Override
+    public boolean beforeExecute(ForestRequest req) {
+        try {
+
+            String username = "admin";
+            String password = "mypass";
+            //对应mediamtx.yml
+            //- user: argon2:$argon2id$v=19$m=4096,t=3,p=1$c2FsdEl0V2l0aFNhbHQ$Mi4H+feNHQk/E0sm46PEz3dnHPTzZMNWV5LVdDD/4SI
+            //  pass: argon2:$argon2id$v=19$m=4096,t=3,p=1$c2FsdEl0V2l0aFNhbHQ$5VEdlOBG/er50vvc4GZO4uA3juhk/uvUzYOzTMv6RiQ
+
+            // 拼接用户名和密码
+            String authString = username + ":" + password;
+
+            // Base64 编码
+            String encodedAuth = Base64.getEncoder().encodeToString(authString.getBytes());
+
+            // 最终的 Authorization 头
+            String authorizationHeader = "Basic " + encodedAuth;
+
+            log.debug("Authorization header: " + authorizationHeader);
+            req.addHeader("Authorization", authorizationHeader);
+        } catch (Exception e) {
+            log.error("TokenInterceptor 处理异常:{}", e.getMessage());
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/ard-work/pom.xml b/ard-work/pom.xml
index 46c325c..24d7824 100644
--- a/ard-work/pom.xml
+++ b/ard-work/pom.xml
@@ -29,7 +29,6 @@
         <dependency>
             <groupId>com.dtflys.forest</groupId>
             <artifactId>forest-spring-boot-starter</artifactId>
-            <version>1.8.0</version>
         </dependency>
 
         <!-- netty依赖 springboot2.x自动导入版本 -->
diff --git a/ard-work/src/main/java/com/ard/work/component/forest/TokenInterceptor.java b/ard-work/src/main/java/com/ard/work/component/forest/TokenInterceptor.java
index 207fbce..2145b5e 100644
--- a/ard-work/src/main/java/com/ard/work/component/forest/TokenInterceptor.java
+++ b/ard-work/src/main/java/com/ard/work/component/forest/TokenInterceptor.java
@@ -3,14 +3,14 @@
 import com.ard.work.domain.receiver.AccessTokenReceiver;
 import com.ard.work.service.IArdServerInfoService;
 import com.dtflys.forest.http.ForestRequest;
-import com.dtflys.forest.interceptor.Interceptor;
+import com.dtflys.forest.interceptor.ForestInterceptor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import javax.annotation.Resource;
 
 @Component
 @Slf4j
-public class TokenInterceptor<T> implements Interceptor<T> {
+public class TokenInterceptor implements ForestInterceptor {
     @Resource
     private IArdServerInfoService ardServerService;
 
@@ -21,11 +21,19 @@
      */
     @Override
     public boolean beforeExecute(ForestRequest req) {
-        log.debug("invoke Simple beforeExecute");
-        String serverId = (String) req.getVariableValue("serverId");
-        AccessTokenReceiver accessToken = ardServerService.getAccessToken(serverId);
-        req.addHeader("x-cid", accessToken.getCompanyId());
-        req.addHeader("x-token", accessToken.getAccessToken());
-        return true;  // 继续执行请求返回true
+        try {
+            String serverId = (String) req.getVariableValue("serverId");
+            AccessTokenReceiver accessToken = ardServerService.getAccessToken(serverId);
+            if (accessToken == null) {
+                log.warn("AccessToken 为 null, serverId={}", serverId);
+                return false; // 阻止请求继续
+            }
+            req.addHeader("x-cid", accessToken.getCompanyId());
+            req.addHeader("x-token", accessToken.getAccessToken());
+        } catch (Exception e) {
+            log.error("TokenInterceptor 处理异常:{}", e.getMessage());
+            return false;
+        }
+        return true;
     }
 }
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/TcpClientSession.java b/ard-work/src/main/java/com/ard/work/component/netty/TcpClientSession.java
deleted file mode 100644
index 3ae32c8..0000000
--- a/ard-work/src/main/java/com/ard/work/component/netty/TcpClientSession.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ard.work.component.netty;
-
-import io.netty.channel.ChannelFuture;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class TcpClientSession {
-
-    private String serverId;
-
-    private String host;
-
-    private Integer port;
-
-    public String ClientId;
-
-    public ChannelFuture channelFuture;
-
-    public Boolean isReConnect;
-
-}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/TcpClientUtil.java b/ard-work/src/main/java/com/ard/work/component/netty/TcpClientUtil.java
new file mode 100644
index 0000000..d886bba
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/component/netty/TcpClientUtil.java
@@ -0,0 +1,42 @@
+package com.ard.work.component.netty;
+
+import com.ard.work.component.netty.command.BaseCmd;
+import com.ard.work.component.netty.cache.TyTcpServerCache;
+import io.netty.channel.Channel;
+import lombok.extern.slf4j.Slf4j;
+import java.net.InetSocketAddress;
+
+/**
+ * Description:
+ * Author: lsy
+ * Date: 2025年10月17日14:27
+ **/
+@Slf4j
+public class TcpClientUtil {
+
+    /**
+     * 向指定边缘服务器发送消息
+     */
+    public static void sendMessage(String serverId, BaseCmd msg) {
+        try {
+            Channel channel = TyTcpServerCache.getChannel(serverId);
+            if (channel == null) {
+                log.error("未找到边缘服务器 [{}] 的连接", serverId);
+                return;
+            }
+
+            if (!channel.isActive()) {
+                log.warn("边缘服务器 [{}] 连接未激活,无法发送消息", serverId);
+                return;
+            }
+
+            InetSocketAddress remote = (InetSocketAddress) channel.remoteAddress();
+            channel.writeAndFlush(msg);
+            log.warn("→ 向边缘服务器 [{}] ({}:{}) 发送消息,命令码:0x{}",
+                    serverId, remote.getHostString(), remote.getPort(),
+                    String.format("%02X", msg.getCmdCode() & 0xFF));
+        } catch (Exception e) {
+            log.error("发送消息到边缘服务器 [{}] 异常:{}", serverId, e.getMessage());
+        }
+    }
+}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java b/ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java
index b161c81..2060ae7 100644
--- a/ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java
+++ b/ard-work/src/main/java/com/ard/work/component/netty/TyTcpClientManager.java
@@ -1,11 +1,10 @@
 package com.ard.work.component.netty;
 
-import com.ard.work.component.netty.command.BaseCmd;
 import com.ard.work.component.netty.command.register.HeartbeatCmd;
 import com.ard.work.component.netty.handler.ClientHandler;
 import com.ard.work.component.netty.handler.MessageProtocolDecoder;
 import com.ard.work.component.netty.handler.MessageProtocolEncoder;
-import com.ard.work.domain.cache.TyTcpServerCache;
+import com.ard.work.component.netty.cache.TyTcpServerCache;
 import com.ard.work.domain.entity.ArdServerInfo;
 import com.ard.work.service.IArdServerInfoService;
 import io.netty.bootstrap.Bootstrap;
@@ -18,20 +17,16 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
+
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
-import java.net.InetSocketAddress;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
+
 
 @Component
 @Slf4j
 public class TyTcpClientManager {
-    /**
-     * 以 serverId 作为唯一 key
-     */
-    public static final Map<String, TcpClientSession> channels = new ConcurrentHashMap<>();
+
 
     private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
 
@@ -63,7 +58,9 @@
         return bootstrap;
     }
 
-    /** 新增或重连服务器 */
+    /**
+     * 新增或重连服务器
+     */
     public void connectServer(ArdServerInfo serverInfo) {
         String serverId = serverInfo.getId();
         String host = serverInfo.getHost();
@@ -73,66 +70,42 @@
         disconnectServer(serverId);
 
         Bootstrap bootstrap = getBootstrap();
-        ChannelFuture future = bootstrap.connect(host, port).addListener((ChannelFuture f) -> {
+        bootstrap.connect(host, port).addListener((ChannelFuture f) -> {
             if (f.isSuccess()) {
                 log.info("✅ 服务器 [{}] 连接成功", serverId);
                 Channel channel = f.channel();
                 channel.attr(AttributeKey.valueOf("serverId")).set(serverId);
                 TyTcpServerCache.putTcpServerCache(serverId, true);
+                // 断开服务器,修改状态为: 0 - 在线
+                ardServerService.updateServerStatus(serverId, "1");
+
+                // 成功后再加入 channels
+                TyTcpServerCache.putChannel(serverId, channel);
+
             } else {
                 log.warn("❌ 服务器 [{}] 连接失败", serverId);
                 TyTcpServerCache.putTcpServerCache(serverId, false);
+                // 断开服务器,修改状态为: 0 - 离线
+                ardServerService.updateServerStatus(serverId, "0");
             }
         });
-
-        TcpClientSession session = TcpClientSession.builder()
-                .ClientId("TY_" + serverId)
-                .channelFuture(future)
-                .isReConnect(true)
-                .serverId(serverId)
-                .host(host)
-                .port(port)
-                .build();
-
-        channels.put(serverId, session);
     }
 
-    /** 断开服务器连接 */
+    /**
+     * 断开服务器连接
+     */
     public void disconnectServer(String serverId) {
-        TcpClientSession session = channels.remove(serverId);
-        if (session != null && session.getChannelFuture() != null) {
-            session.getChannelFuture().channel().close();
+        Channel channel = TyTcpServerCache.getChannel(serverId);
+        if (channel != null) {
+            channel.close();
             log.info("断开服务器 [{}] 连接", serverId);
+            // 断开服务器,修改状态为: 0 - 离线
+            ardServerService.updateServerStatus(serverId, "0");
+            TyTcpServerCache.removeChannel(serverId);
         }
         TyTcpServerCache.removeTcpServerCache(serverId);
     }
 
-    /**
-     * 向指定边缘服务器发送消息
-     */
-    public void sendMessage(Long serverId, BaseCmd msg) {
-        try {
-            TcpClientSession session = channels.get(serverId);
-            if (session == null) {
-                log.error("未找到六合服务器 [{}] 的连接", serverId);
-                return;
-            }
-
-            ChannelFuture future = session.getChannelFuture();
-            if (future == null || !future.channel().isActive()) {
-                log.warn("六合服务器 [{}] 连接未激活,无法发送消息", serverId);
-                return;
-            }
-
-            InetSocketAddress remote = (InetSocketAddress) future.channel().remoteAddress();
-            future.channel().writeAndFlush(msg);
-            log.debug("→ 向六合服务器 [{}] ({}:{}) 发送消息,命令码:0x{}",
-                    serverId, remote.getHostString(), remote.getPort(),
-                    String.format("%02X", msg.getCmdCode() & 0xFF));
-        } catch (Exception e) {
-            log.error("发送消息到六合服务器 [{}] 异常:{}", serverId, e.getMessage());
-        }
-    }
 
     /**
      * 启动时从数据库加载所有边缘服务器并建立 TCP 连接
@@ -162,6 +135,7 @@
             if (Boolean.FALSE.equals(state)) { // 连接失败的服务器
                 ArdServerInfo serverInfo = ardServerService.selectArdServerInfoById(key);
                 if (serverInfo != null) {
+                    log.warn("服务器 [{}] 连接失败,尝试重连", key);
                     connectServer(serverInfo);
                 }
             }
@@ -174,19 +148,14 @@
     @Scheduled(fixedRate = 5000) // 每5秒执行一次
     public void sendHeartBeat() {
         long timestamp = System.currentTimeMillis();
-        channels.values().stream()
-                .filter(session -> {
-                    ChannelFuture future = session.getChannelFuture();
-                    // 只保留活跃连接
-                    return future != null && future.channel().isActive();
-                })
-                .forEach(session -> {
+        TyTcpServerCache.getChannels().stream()
+                // 过滤出仍然活跃的连接
+                .filter(channel -> channel != null && channel.isActive())
+                .forEach(channel -> {
+                    String serverId = (String) channel.attr(AttributeKey.valueOf("serverId")).get();
                     HeartbeatCmd heartbeat = new HeartbeatCmd(timestamp);
-                    ChannelFuture future = session.getChannelFuture();
-                    future.channel().writeAndFlush(heartbeat);
-                    log.info("→ 向边缘服务器 [{}] ({}:{}) 发送心跳,时间戳={}",
-                            session.getServerId(), session.getHost(), session.getPort(), timestamp);
+                    channel.writeAndFlush(heartbeat);
+                    log.info("→ 向边缘服务器 [{}]发送心跳,时间戳={}", serverId, timestamp);
                 });
     }
-
 }
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/cache/TyTcpServerCache.java b/ard-work/src/main/java/com/ard/work/component/netty/cache/TyTcpServerCache.java
new file mode 100644
index 0000000..aec481d
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/work/component/netty/cache/TyTcpServerCache.java
@@ -0,0 +1,68 @@
+package com.ard.work.component.netty.cache;
+
+import io.netty.channel.Channel;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 六合tcp服务器缓存
+ *
+ * @author liusuyi
+ * @date 2024年11月01日13:53
+ **/
+public class TyTcpServerCache {
+    /**
+     * 以 serverId 作为唯一 key 存储 Channel
+     */
+    private static Map<String, Channel> channels = new ConcurrentHashMap<>();
+
+    //存储通道
+    public static void putChannel(String serverId, Channel channel) {
+        channels.put(serverId, channel);
+    }
+
+    //获取通道
+    public static Channel getChannel(String serverId) {
+        return channels.get(serverId);
+    }
+
+    //删除通道
+    public static void removeChannel(String serverId) {
+        channels.remove(serverId);
+    }
+
+    //获取所有
+    public static Collection<Channel> getChannels() {
+        return Collections.unmodifiableCollection(channels.values());
+    }
+
+
+    /**
+     * 以 serverId 作为唯一 key 存储 连接状态
+     */
+    private static final ConcurrentHashMap<String, Boolean> tcpServerCache = new ConcurrentHashMap<>();
+
+    // 存储TCP服务连接状态到缓存
+    public static void putTcpServerCache(String serverId, Boolean state) {
+        tcpServerCache.put(serverId, state);
+    }
+
+    // 从缓存中获取TCP服务连接状态
+    public static Boolean getTcpServerCache(String serverId) {
+        return tcpServerCache.getOrDefault(serverId, false);
+    }
+
+    // 删除缓存中的TCP服务连接状态
+    public static void removeTcpServerCache(String serverId) {
+        tcpServerCache.remove(serverId);
+    }
+
+    public static Map<String, Boolean> getTcpServerCacheMap() {
+        return new HashMap<>(tcpServerCache); // 返回一个副本,避免外部修改原始缓存
+    }
+
+}
diff --git a/ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java b/ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java
index 86f6795..afc3752 100644
--- a/ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java
+++ b/ard-work/src/main/java/com/ard/work/component/netty/handler/ClientHandler.java
@@ -1,22 +1,19 @@
 package com.ard.work.component.netty.handler;
 
-import com.ard.work.component.netty.TyTcpClientManager;
-import com.ard.work.component.netty.command.register.HeartbeatCmd;
-import com.ard.work.domain.cache.TyTcpServerCache;
 import com.ard.work.component.netty.command.BaseCmd;
+import com.ard.work.component.netty.command.register.HeartbeatCmd;
+import com.ard.work.component.netty.cache.TyTcpServerCache;
 import com.ard.work.service.ITyService;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
 import io.netty.util.AttributeKey;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import javax.annotation.Resource;
 import java.net.InetSocketAddress;
-import java.util.concurrent.TimeUnit;
 
 
 @Component
@@ -26,9 +23,6 @@
 
     @Resource
     private ITyService tyService;
-
-    @Resource
-    private TyTcpClientManager tyTcpClientManager;
 
     @Override
     public void channelRead0(ChannelHandlerContext ctx, BaseCmd command) {
diff --git a/ard-work/src/main/java/com/ard/work/domain/cache/TyTcpServerCache.java b/ard-work/src/main/java/com/ard/work/domain/cache/TyTcpServerCache.java
deleted file mode 100644
index e03a482..0000000
--- a/ard-work/src/main/java/com/ard/work/domain/cache/TyTcpServerCache.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ard.work.domain.cache;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 六合tcp服务器缓存
- *
- * @author liusuyi
- * @date 2024年11月01日13:53
- **/
-public class TyTcpServerCache {
-    // 使用 ConcurrentHashMap 来缓存TCP服务连接状态,key 是 ip:port(服务器地址) value 是连接状态
-    private static final ConcurrentHashMap<String, Boolean> tcpServerCache = new ConcurrentHashMap<>();
-
-    // 存储TCP服务连接状态到缓存
-    public static void putTcpServerCache(String serverId,Boolean state) {
-        tcpServerCache.put(serverId, state);
-    }
-
-    // 从缓存中获取TCP服务连接状态
-    public static Boolean getTcpServerCache(String serverId) {
-        return tcpServerCache.getOrDefault(serverId,false);
-    }
-
-    // 删除缓存中的TCP服务连接状态
-    public static void removeTcpServerCache(String serverId) {
-        tcpServerCache.remove(serverId);
-    }
-
-    public static Map<String, Boolean> getTcpServerCacheMap() {
-        return new HashMap<>(tcpServerCache); // 返回一个副本,避免外部修改原始缓存
-    }
-
-}
diff --git a/ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java b/ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java
index 1d74cb6..81763ac 100644
--- a/ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java
+++ b/ard-work/src/main/java/com/ard/work/domain/entity/ArdDroneInfo.java
@@ -3,7 +3,7 @@
 import com.ard.common.annotation.Excel;
 import com.ard.common.core.domain.BaseEntity;
 import com.ard.work.domain.receiver.BoxInfoReceiver;
-import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.*;
 
 import java.util.Date;
@@ -39,6 +39,7 @@
     private String boxVersion;
 
     /** 启动时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "启动时间")
     private Date startTime;
 
@@ -70,6 +71,10 @@
     @Excel(name = "服务器管理ID")
     private String serverId;
 
+    /** 盒子别名 */
+    @Excel(name = "盒子别名")
+    private String boxAliasName;
+
     /**
      * 服务器实体对象
      */
diff --git a/ard-work/src/main/java/com/ard/work/domain/entity/ArdServerInfo.java b/ard-work/src/main/java/com/ard/work/domain/entity/ArdServerInfo.java
index e46879f..ce3d01d 100644
--- a/ard-work/src/main/java/com/ard/work/domain/entity/ArdServerInfo.java
+++ b/ard-work/src/main/java/com/ard/work/domain/entity/ArdServerInfo.java
@@ -52,8 +52,12 @@
     /** 部门ID */
     private Long deptId;
 
-    /** 服务器状态 */
-    private Long serverStatus;
+    /**
+     * 服务器状态
+     * 0:离线
+     * 1:在线
+     */
+    private String serverStatus;
 
     private List<ArdDroneInfo> ardDroneInfoList;
 
diff --git a/ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java b/ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java
index ebf01ee..3956cb8 100644
--- a/ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java
+++ b/ard-work/src/main/java/com/ard/work/mapper/ArdServerInfoMapper.java
@@ -1,5 +1,6 @@
 package com.ard.work.mapper;
 import com.ard.work.domain.entity.ArdServerInfo;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -65,6 +66,6 @@
      * @param id 服务器管理主键
      * @return 结果
      */
-    public int updateServerStatus(String id);
+    public int updateServerStatus(@Param("id") String id, @Param("status") String status);
 
 }
diff --git a/ard-work/src/main/java/com/ard/work/service/IArdDroneInfoService.java b/ard-work/src/main/java/com/ard/work/service/IArdDroneInfoService.java
index c5bb6e3..81766f3 100644
--- a/ard-work/src/main/java/com/ard/work/service/IArdDroneInfoService.java
+++ b/ard-work/src/main/java/com/ard/work/service/IArdDroneInfoService.java
@@ -73,9 +73,10 @@
     /**
      * 批量新增无人机盒子
      *
-     * @param ids 无人机盒子主键集合
+     * @param boxSn 盒子编码
+     * @param deptId 部门ID
      * @return 结果
      */
-    public int insertArdDroneLs(String[] ids);
+    public int insertArdDroneLs(String[] boxSn,Long deptId);
 
 }
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 2dbb6cc..f6ab3d7 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
@@ -68,6 +68,6 @@
     /**
      * 修改服务器状态
      */
-    public int updateServerStatus(String id);
+    public int updateServerStatus(String id,String status);
 
 }
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 f6bcf3d..5828e4e 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
@@ -38,12 +38,19 @@
 
 
     /**
-     * 获取云盒列表
+     * 获取全部服务器云盒列表
      * @return
      */
     List<BoxInfoReceiver> getBoxList();
 
     /**
+     * 获取指定服务器云盒列表
+     *
+     * @return List<BoxInfoReceiver>
+     */
+    List<BoxInfoReceiver> getBoxList(String serverId);
+
+    /**
      * 获取直播地址
      * @return
      */
diff --git a/ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java b/ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java
index 22bb36e..9128c2a 100644
--- a/ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/work/service/impl/ArdDroneInfoServiceImpl.java
@@ -1,6 +1,7 @@
 package com.ard.work.service.impl;
 
 import com.alibaba.fastjson2.JSONObject;
+import com.ard.common.exception.ServiceException;
 import com.ard.common.utils.DateUtils;
 import com.ard.common.utils.uuid.IdUtils;
 import com.ard.system.authorize.service.AuthorizeService;
@@ -10,14 +11,12 @@
 import com.ard.work.service.IArdDroneInfoService;
 import com.ard.work.service.ITyService;
 import com.ard.work.util.UtilMethod;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -26,6 +25,7 @@
  * @author ruoyi
  * @date 2025-03-04
  */
+@Slf4j
 @Service
 public class ArdDroneInfoServiceImpl implements IArdDroneInfoService {
 
@@ -34,6 +34,9 @@
 
     @Resource
     private ITyService tyService;
+
+    @Resource
+    private AuthorizeService authorizeService;
 
     UtilMethod utilMethod = new UtilMethod();
 
@@ -120,24 +123,123 @@
     /**
      * 批量新增无人机盒子
      *
-     * @param ids 无人机盒子主键集合
-     * @return 结果
+     * @param boxSn 盒子编码数组
+     * @param deptId 部门ID
+     * @return 成功插入的记录数
      */
     @Override
-    public int insertArdDroneLs(String[] ids) {
-        // 获取无人机盒子信息
-        List<ArdDroneInfo> drone = new ArrayList<>();
-        for (String id : ids) {
-            ArdDroneInfo ardDrone = ArdDroneInfoMapper.selectArdDroneById(id);
-            drone.add(ardDrone);
+    public int insertArdDroneLs(String[] boxSn, Long deptId) {
+        // 参数校验
+        if (boxSn == null || boxSn.length == 0) {
+            log.warn("传入的盒子编码为空");
+            return 1;
         }
-        // 检验数量droneNum是否合规。
-        utilMethod.authorizationVerification(drone.size());
-        // 插入
-        if (!drone.isEmpty()) {
-            return ArdDroneInfoMapper.insertArdDroneLs(drone);
+        if (deptId == null) {
+            throw new IllegalArgumentException("部门ID不能为空");
         }
-        return 0;
+        try {
+            // 1. 检查已存在的无人机盒子
+            List<ArdDroneInfo> existingDrones = getExistingDrones(boxSn);
+            // 2. 授权数量验证
+            validateAuthorization(existingDrones.size(), boxSn.length);
+            // 3. 获取并组装新的无人机信息
+            List<ArdDroneInfo> newDrones = assembleNewDrones(boxSn, deptId);
+            // 4. 批量插入
+            return batchInsertDrones(newDrones);
+        } catch (Exception e) {
+            log.error("批量新增无人机盒子失败, boxSn: {}, deptId: {}", Arrays.toString(boxSn), deptId, e);
+            throw new ServiceException("批量新增无人机盒子失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取已存在的无人机信息
+     */
+    private List<ArdDroneInfo> getExistingDrones(String[] boxSn) {
+        return Arrays.stream(boxSn)
+                .map(ArdDroneInfoMapper::selectArdDroneByBoxSn)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 验证授权数量
+     */
+    private void validateAuthorization(int existingCount, int newCount) {
+        int totalCount = existingCount + newCount;
+
+        JSONObject authInfo = authorizeService.getAuthorizationInfo();
+        String authType = authInfo.getString("Type");
+
+        switch (authType) {
+            case "normal":
+                int allowedDroneNum = authInfo.getIntValue("droneNum");
+                if (totalCount > allowedDroneNum) {
+                    throw new RuntimeException(String.format(
+                            "授权数量%d,当前操作将导致总数达到%d,超过授权限制",
+                            allowedDroneNum, totalCount));
+                }
+                break;
+            case "expired":
+                throw new RuntimeException("授权文件已过期");
+            case "mismatch":
+                throw new RuntimeException("授权文件不匹配");
+            default:
+                throw new RuntimeException("未知的授权类型: " + authType);
+        }
+    }
+
+    /**
+     * 组装新的无人机信息
+     */
+    private List<ArdDroneInfo> assembleNewDrones(String[] boxSn, Long deptId) {
+        List<BoxInfoReceiver> allBoxes = tyService.getBoxList();
+        Set<String> targetBoxSnSet = new HashSet<>(Arrays.asList(boxSn));
+        return allBoxes.stream()
+                .filter(box -> targetBoxSnSet.contains(box.getBoxSn()))
+                .map(box -> createDroneInfo(box, deptId))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 创建无人机信息对象
+     */
+    private ArdDroneInfo createDroneInfo(BoxInfoReceiver box, Long deptId) {
+        ArdDroneInfo drone = new ArdDroneInfo();
+        drone.setId(IdUtils.simpleUUID());
+        drone.setBoxSn(box.getBoxSn());
+        drone.setBoxName(box.getBoxName());
+        drone.setBoxAliasName(box.getBoxName());
+        drone.setStartTime(new Date());
+        drone.setOnLine(box.getOnLine());
+        drone.setVideoServer(box.getVideoServer());
+        drone.setVideoPort(box.getVideoPort());
+        drone.setLastTaskId(box.getLastTaskId());
+        drone.setDeptId(deptId);
+
+        // 设置创建信息和更新信息
+        setCreateAndUpdateInfo(drone);
+
+        return drone;
+    }
+
+    /**
+     * 设置创建和更新信息
+     */
+    private void setCreateAndUpdateInfo(ArdDroneInfo drone) {
+        Date currentTime = new Date();
+        drone.setCreateTime(currentTime);
+        drone.setUpdateTime(currentTime);
+    }
+
+    /**
+     * 批量插入无人机信息
+     */
+    private int batchInsertDrones(List<ArdDroneInfo> drones) {
+        if (drones.isEmpty()) {
+            return 0;
+        }
+        return ArdDroneInfoMapper.insertArdDroneLs(drones);
     }
 
     /**
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 247b335..636696e 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
@@ -144,8 +144,8 @@
      * 修改服务器状态
      */
     @Override
-    public int updateServerStatus(String id) {
-        return ardServerInfoMapper.updateServerStatus(id);
+    public int updateServerStatus(String id,String status) {
+        return ardServerInfoMapper.updateServerStatus(id,status);
     }
 
     private String getEncryptStr(ArdServerInfo serverInfo, long timeStamp) {
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 af0f6ca..6f849c0 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
@@ -1,66 +1,61 @@
 package com.ard.work.service.impl;
 
 import com.ard.common.utils.ByteUtils;
-import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
 import com.ard.work.aspect.annotation.CheckControlRight;
+import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
+import com.ard.work.component.forest.TyClient;
+import com.ard.work.component.netty.TcpClientUtil;
 import com.ard.work.component.netty.command.BaseCmd;
 import com.ard.work.component.netty.command.camera.*;
-import com.ard.work.component.netty.command.manual.*;
-import com.ard.work.component.netty.command.register.*;
-import com.ard.work.component.netty.command.settings.*;
-import com.ard.work.component.netty.command.speaker.*;
-import com.ard.work.component.netty.command.wayline.*;
-import com.ard.work.domain.dto.camera.*;
-import com.ard.work.domain.dto.manual.*;
-import com.ard.work.domain.dto.speaker.*;
-import com.ard.work.domain.dto.wayline.*;
-import com.ard.work.domain.entity.ArdDroneInfo;
-import com.ard.work.domain.entity.ArdServerInfo;
-import com.ard.work.domain.receiver.*;
-import com.ard.work.component.forest.TyClient;
-import com.ard.work.domain.cache.UavSignalInfoCache;
-import com.ard.work.domain.cache.UavStateCache;
-import com.ard.work.domain.cache.UavTelemetryDataCache;
-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.control.AbsAngleControlDTO;
-import com.ard.work.domain.dto.control.AngleControlDTO;
-import com.ard.work.domain.dto.control.SpeedControlDTO;
-import com.ard.work.domain.dto.converter.wayline.PlanLineDataConverter;
-import com.ard.work.domain.dto.settings.ReturnHeightSettingDTO;
-import com.ard.work.domain.dto.settings.ReturnPointSettingDTO;
-import com.ard.work.domain.dto.settings.VideoStreamSettingDTO;
-import com.ard.work.domain.dto.signal.SignalInfo;
-import com.ard.work.domain.dto.state.UavState;
-import com.ard.work.domain.dto.telemetry.TelemetryData;
 import com.ard.work.component.netty.command.control.AbsAngleControlCmd;
 import com.ard.work.component.netty.command.control.AngleControlCmd;
 import com.ard.work.component.netty.command.control.SpeedControlCmd;
+import com.ard.work.component.netty.command.manual.*;
 import com.ard.work.component.netty.command.notice.BoxPowerStatusReplyCmd;
 import com.ard.work.component.netty.command.notice.FlyWayEndReplyCmd;
 import com.ard.work.component.netty.command.notice.UavReadyReplyCmd;
 import com.ard.work.component.netty.command.real.SignalInfoCmd;
 import com.ard.work.component.netty.command.real.UavStateCmd;
 import com.ard.work.component.netty.command.real.UavTelemetryDataCmd;
+import com.ard.work.component.netty.command.register.*;
+import com.ard.work.component.netty.command.settings.*;
+import com.ard.work.component.netty.command.speaker.*;
+import com.ard.work.component.netty.command.wayline.*;
 import com.ard.work.component.netty.handler.ErrorCodeEnum;
 import com.ard.work.component.netty.protobuf.TelemetryDataPB;
+import com.ard.work.domain.cache.UavSignalInfoCache;
+import com.ard.work.domain.cache.UavStateCache;
+import com.ard.work.domain.cache.UavTelemetryDataCache;
+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.camera.*;
+import com.ard.work.domain.dto.control.AbsAngleControlDTO;
+import com.ard.work.domain.dto.control.AngleControlDTO;
+import com.ard.work.domain.dto.control.SpeedControlDTO;
+import com.ard.work.domain.dto.converter.wayline.PlanLineDataConverter;
+import com.ard.work.domain.dto.manual.*;
+import com.ard.work.domain.dto.settings.ReturnHeightSettingDTO;
+import com.ard.work.domain.dto.settings.ReturnPointSettingDTO;
+import com.ard.work.domain.dto.settings.VideoStreamSettingDTO;
+import com.ard.work.domain.dto.signal.SignalInfo;
+import com.ard.work.domain.dto.speaker.*;
+import com.ard.work.domain.dto.state.UavState;
+import com.ard.work.domain.dto.telemetry.TelemetryData;
+import com.ard.work.domain.dto.wayline.*;
+import com.ard.work.domain.entity.ArdDroneInfo;
+import com.ard.work.domain.entity.ArdServerInfo;
+import com.ard.work.domain.message.UavControlType;
+import com.ard.work.domain.receiver.*;
 import com.ard.work.service.IArdDroneInfoService;
 import com.ard.work.service.IArdServerInfoService;
 import com.ard.work.service.ITyService;
-import com.ard.work.domain.message.UavControlType;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
-
 import javax.annotation.Resource;
-import java.net.InetSocketAddress;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
-import static com.ard.work.component.netty.TyTcpClientManager.channels;
 
 /**
  * TyServiceImpl
@@ -89,7 +84,7 @@
     }
 
     /**
-     * 获取云盒列表
+     * 获取全部云盒列表
      *
      * @return List<BoxInfoReceiver>
      */
@@ -98,7 +93,16 @@
         List<ArdServerInfo> ardServerInfos = ardServerService.selectArdServerInfoList(new ArdServerInfo());
         return getBoxList(ardServerInfos);
     }
-
+    /**
+     * 获取指定服务器云盒列表
+     *
+     * @return List<BoxInfoReceiver>
+     */
+    @Override
+    public List<BoxInfoReceiver> getBoxList(String serverId) {
+        TyHttpCommonReceiver<List<BoxInfoReceiver>> boxList = tyClient.getBoxList(serverId);
+        return boxList.getContent();
+    }
     /**
      * 获取直播地址
      *
@@ -873,6 +877,7 @@
 
     private List<BoxInfoReceiver> getBoxList(List<ArdServerInfo> ls) {
         return ls.stream()
+                .filter(ardServerInfo -> ardServerInfo.getServerStatus().equals("1"))
                 .flatMap(ardServerInfo -> {
                     try {
                         List<BoxInfoReceiver> boxes = tyClient.getBoxList(ardServerInfo.getId()).getContent();
@@ -899,25 +904,12 @@
                 ErrorCodeEnum.getDescByCode(errorCode));
     }
 
+
     /**
      * 发送消息
      */
     private void sendMessage(String key, BaseCmd msg) {
-        try {
-            ChannelFuture future = channels.get(key).getChannelFuture();
-            Channel channel = future.channel();
-            if (channel.isActive()) {
-                InetSocketAddress ipSocket = (InetSocketAddress) channel.remoteAddress();
-                String host = ipSocket.getHostString();
-                int port = ipSocket.getPort();
-                channel.writeAndFlush(msg); // 发送编码后的数据
-                log.debug("向六合服务器【{}:{}】发送数据,命令码:{}", host, port, String.format("0x%02X", msg.getCmdCode() & 0xFF));
-            } else {
-                log.error("与六合服务器链接断开,无法发送数据!");
-            }
-        } catch (Exception e) {
-            log.error("发送消息异常:{}", e.getMessage());
-        }
+        TcpClientUtil.sendMessage(key, msg);
     }
 
 }
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/work/util/UtilMethod.java b/ard-work/src/main/java/com/ard/work/util/UtilMethod.java
index 69388ef..fe26e6c 100644
--- a/ard-work/src/main/java/com/ard/work/util/UtilMethod.java
+++ b/ard-work/src/main/java/com/ard/work/util/UtilMethod.java
@@ -2,6 +2,9 @@
 
 import com.alibaba.fastjson2.JSONObject;
 import com.ard.system.authorize.service.AuthorizeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 
@@ -10,25 +13,35 @@
  * @date: 2025/3/4
  * @description:
  */
+@Service
 public class UtilMethod {
 
-    @Resource
+    @Autowired
     private AuthorizeService authorizeService;
 
     /**
      * 根据授权数量,验证授权信息是否合规
      */
     public void authorizationVerification(int ls){
-        JSONObject data = authorizeService.getAuthorizationInfo();
-        if ("normal".equals(data.get("Type"))){
-            int droneNum = (int) data.get("droneNum");
-            if (ls > droneNum){
-                throw new RuntimeException("添加无人机数量超过当前授权数量!!!");
-            }
-        }else if ("expired".equals(data.get("Type"))){
-            throw new RuntimeException("授权文件过期!!!");
-        }else if ("mismatch".equals(data.get("Type"))){
-            throw new RuntimeException("授权文件不匹配!!!");
+
+        JSONObject authInfo = authorizeService.getAuthorizationInfo();
+        String authType = authInfo.getString("Type");
+
+        switch (authType) {
+            case "normal":
+                int allowedDroneNum = authInfo.getIntValue("droneNum");
+                if (ls > allowedDroneNum) {
+                    throw new RuntimeException(String.format(
+                            "授权数量%d,当前操作将导致总数达到%d,超过授权限制",
+                            allowedDroneNum, ls));
+                }
+                break;
+            case "expired":
+                throw new RuntimeException("授权文件已过期");
+            case "mismatch":
+                throw new RuntimeException("授权文件不匹配");
+            default:
+                throw new RuntimeException("未知的授权类型: " + authType);
         }
     }
 
diff --git a/ard-work/src/main/resources/mapper/ArdDroneInfoMapper.xml b/ard-work/src/main/resources/mapper/ArdDroneInfoMapper.xml
index a5451d5..dafd26d 100644
--- a/ard-work/src/main/resources/mapper/ArdDroneInfoMapper.xml
+++ b/ard-work/src/main/resources/mapper/ArdDroneInfoMapper.xml
@@ -16,6 +16,7 @@
         <result property="lastTaskId"    column="last_task_id"    />
         <result property="userId"    column="user_id"    />
         <result property="deptId"    column="dept_id"    />
+        <result property="boxAliasName"    column="box_alias_name"    />
         <result property="createBy"    column="create_by"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
@@ -37,24 +38,25 @@
 
     <sql id="selectArdDroneVo">
         select id,
-            box_sn,
-            box_name,
-            box_version,
-            start_time,
-            on_line,
-            video_server,
-            video_port,
-            last_task_id,
-            server_id,
-            user_id,
-            dept_id
+               box_sn,
+               box_name,
+               box_version,
+               start_time,
+               on_line,
+               video_server,
+               video_port,
+               last_task_id,
+               server_id,
+               user_id,
+               dept_id,
+               box_alias_name
         from ard_drone_info
     </sql>
 
     <select id="selectArdDroneList" parameterType="ArdDroneInfo" resultMap="ArdDroneInfoResult">
         <include refid="selectArdDroneVo"/>
-        <where>  
-            <if test="boxSn != null  and boxSn != ''"> and box_sn = #{boxSn}</if>
+        <where>
+            <if test="boxSn != null  and boxSn != ''"> and box_sn like concat('%', #{boxSn}, '%')</if>
             <if test="boxName != null  and boxName != ''"> and box_name like concat('%', #{boxName}, '%')</if>
             <if test="boxVersion != null  and boxVersion != ''"> and box_version = #{boxVersion}</if>
             <if test="onLine != null "> and onLine = #{onLine}</if>
@@ -84,8 +86,10 @@
             <if test="videoServer != null">video_server,</if>
             <if test="videoPort != null">video_port,</if>
             <if test="lastTaskId != null">last_task_id,</if>
+            <if test="serverId != null">server_id,</if>
             <if test="userId != null">user_id,</if>
             <if test="deptId != null">dept_id,</if>
+            <if test="boxAliasName != null">box_alias_name,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
@@ -102,8 +106,10 @@
             <if test="videoServer != null">#{videoServer},</if>
             <if test="videoPort != null">#{videoPort},</if>
             <if test="lastTaskId != null">#{lastTaskId},</if>
+            <if test="serverId != null">#{serverId},</if>
             <if test="userId != null">#{userId},</if>
             <if test="deptId != null">#{deptId},</if>
+            <if test="boxAliasName != null">#{boxAliasName},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
@@ -123,8 +129,10 @@
             <if test="videoServer != null">video_server = #{videoServer},</if>
             <if test="videoPort != null">video_port = #{videoPort},</if>
             <if test="lastTaskId != null">last_task_id = #{lastTaskId},</if>
+            <if test="serverId != null">server_id = #{serverId},</if>
             <if test="userId != null">user_id = #{userId},</if>
             <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="boxAliasName != null">box_alias_name = #{boxAliasName},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
@@ -145,7 +153,7 @@
         </foreach>
     </delete>
 
-    <insert id="insertArdDroneLs">
+    <insert id="insertArdDroneLs" parameterType="java.util.List">
         insert into ard_drone_info(
             id,
             box_sn,
@@ -159,6 +167,7 @@
             server_id,
             user_id,
             dept_id,
+            box_alias_name,
             create_by,
             create_time,
             update_by,
@@ -167,19 +176,22 @@
         ) values
         <foreach item="item" index="index" collection="list" separator=",">
             (#{item.id},
-            #{item.boxSn}),
-            #{item.boxName}),
-            #{item.boxVersion}),
-            #{item.startTime}),
-            #{item.videoServer}),
-            #{item.videoPort}),
-            #{item.lastTaskId}),
-            #{item.userId}),
-            #{item.deptId}),
-            #{item.createBy}),
-            #{item.createTime}),
-            #{item.updateBy}),
-            #{item.updateTime}),
+            #{item.boxSn},
+            #{item.boxName},
+            #{item.boxVersion},
+            #{item.startTime},
+            #{item.onLine},
+            #{item.videoServer},
+            #{item.videoPort},
+            #{item.lastTaskId},
+            #{item.serverId},
+            #{item.userId},
+            #{item.deptId},
+            #{item.boxAliasName},
+            #{item.createBy},
+            #{item.createTime},
+            #{item.updateBy},
+            #{item.updateTime},
             #{item.remark})
         </foreach>
     </insert>
diff --git a/ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml b/ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml
index 6029346..385990f 100644
--- a/ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml
+++ b/ard-work/src/main/resources/mapper/ArdServerInfoMapper.xml
@@ -43,7 +43,7 @@
         <include refid="selectArdServerInfoVo"/>
         <where>
             <if test="id != null and id != ''"> and c.id = #{id}</if>
-            <if test="serverName != null and serverName != ''"> and server_name like c.concat('%', #{serverName}, '%')</if>
+            <if test="serverName != null and serverName != ''"> and c.server_name like concat('%', #{serverName}, '%')</if>
             <if test="accessKeyId != null and accessKeyId != ''"> and c.access_key_id = #{accessKeyId}</if>
             <if test="accessKeySecret != null and accessKeySecret != ''"> and c.access_key_secret = #{accessKeySecret}</if>
             <if test="serverStatus != null and serverStatus != ''"> and c.server_status = #{serverStatus}</if>
@@ -113,10 +113,10 @@
         where id = #{id}
     </update>
 
-    <update id="updateServerStatus" parameterType="String">
+    <update id="updateServerStatus">
         update ard_server_info
         <trim prefix="SET" suffixOverrides=",">
-            <if test="serverStatus != null">server_status = #{serverStatus},</if>
+            <if test="status != null">server_status = #{status},</if>
         </trim>
         where id = #{id}
     </update>
diff --git a/pom.xml b/pom.xml
index 1acab07..2bc5699 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
         <okhttp.version>4.8.1</okhttp.version>
         <mqtt.version>5.5.5</mqtt.version>
         <minio.version>8.3.7</minio.version>
+        <forest.version>1.8.0</forest.version>
         <spring-boot-admin.version>2.5.1</spring-boot-admin.version>
     </properties>
 
@@ -240,6 +241,13 @@
                 <version>${minio.version}</version>
             </dependency>
 
+            <!-- Forest -->
+            <dependency>
+                <groupId>com.dtflys.forest</groupId>
+                <artifactId>forest-spring-boot-starter</artifactId>
+                <version>${forest.version}</version>
+            </dependency>
+
             <!-- SpringBootAdmin管控台 -->
             <dependency>
                 <groupId>de.codecentric</groupId>

--
Gitblit v1.9.3