From 665747a8468497a7f0ad63f0c30991a86c0a5aea Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 15 Jun 2026 13:30:16 +0800 Subject: [PATCH] feat: standalone detection equipment API + task detail includes detections IScenarioService: AddDetection/DeleteDetection/GetDetections (independent of SaveDeployment overwrite). Repository: GetByTaskIdAndRole filters by equipment role. TaskFullConfig.Equipment already includes detections (GetTaskDetail.GetByTaskId returns all). Frontend filters by EquipmentRole.Detection or uses GetDetections. Tests: 4 detection CRUD tests. 212 total pass. --- .../EquipmentDeploymentRepository.cs | 8 ++ .../Services/IScenarioService.cs | 8 ++ .../Services/ScenarioService.cs | 20 +++++ .../ScenarioServiceTests.cs | 76 +++++++++++++++++++ 4 files changed, 112 insertions(+) diff --git a/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs b/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs index 555f124..7c77b2a 100644 --- a/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs +++ b/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs @@ -14,6 +14,14 @@ namespace CounterDrone.Core.Repository return Db.Table().Where(e => e.TaskId == taskId).ToList(); } + /// 按任务和角色查询装备(EquipmentRole: 0=Detection, 1=LaunchPlatform) + public List GetByTaskIdAndRole(string taskId, int equipmentRole) + { + return Db.Table() + .Where(e => e.TaskId == taskId && e.EquipmentRole == equipmentRole) + .ToList(); + } + public void DeleteByTaskId(string taskId) { var equips = GetByTaskId(taskId); diff --git a/src/CounterDrone.Core/Services/IScenarioService.cs b/src/CounterDrone.Core/Services/IScenarioService.cs index f57b9e5..f5c27db 100644 --- a/src/CounterDrone.Core/Services/IScenarioService.cs +++ b/src/CounterDrone.Core/Services/IScenarioService.cs @@ -15,6 +15,14 @@ namespace CounterDrone.Core.Services void SaveControlZones(string taskId, List zones); void SaveTarget(string taskId, TargetConfig target); void SaveDeployment(string taskId, List equips); + + /// 添加单个探测设备(独立于 SaveDeployment,不覆盖火力单元) + void AddDetection(string taskId, EquipmentDeployment detection); + /// 删除探测设备 + void DeleteDetection(string detectionId); + /// 获取任务的所有探测设备(EquipmentRole.Detection) + List GetDetections(string taskId); + void SaveCloudDispersal(string taskId, CloudDispersal cloud); void SaveRoute(string taskId, string groupId, RoutePlan route, List waypoints); void UpdateStep(string taskId, int step); diff --git a/src/CounterDrone.Core/Services/ScenarioService.cs b/src/CounterDrone.Core/Services/ScenarioService.cs index 5a1af41..d169592 100644 --- a/src/CounterDrone.Core/Services/ScenarioService.cs +++ b/src/CounterDrone.Core/Services/ScenarioService.cs @@ -158,6 +158,26 @@ namespace CounterDrone.Core.Services TouchTask(taskId); } + public void AddDetection(string taskId, EquipmentDeployment detection) + { + detection.TaskId = taskId; + detection.EquipmentRole = (int)EquipmentRole.Detection; + if (string.IsNullOrEmpty(detection.Id)) + detection.Id = Guid.NewGuid().ToString(); + _equipRepo.Insert(detection); + TouchTask(taskId); + } + + public void DeleteDetection(string detectionId) + { + _equipRepo.Delete(detectionId); + } + + public List GetDetections(string taskId) + { + return _equipRepo.GetByTaskIdAndRole(taskId, (int)EquipmentRole.Detection); + } + public void SaveCloudDispersal(string taskId, CloudDispersal cloud) { cloud.TaskId = taskId; diff --git a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs index 1e644ff..c0c876b 100644 --- a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs @@ -484,5 +484,81 @@ namespace CounterDrone.Core.Tests var searchResult = _service.SearchTasks("完整流程", null, null, 1, 10); Assert.Equal(1, searchResult.TotalCount); } + + // ═══════════════════════════════════════ + // 探测设备独立 CRUD + // ═══════════════════════════════════════ + + [Fact] + public void AddDetection_PersistsAndQueryable() + { + var task = _service.CreateTask("探测设备测试", ""); + _service.AddDetection(task.Id, new EquipmentDeployment + { + Quantity = 1, + PositionX = 5000, PositionY = 0, PositionZ = 0, + RadarRange = 8000, EORange = 4000, IRRange = 3000, + DetectionAccuracy = 50, + }); + + var detections = _service.GetDetections(task.Id); + Assert.Single(detections); + Assert.Equal((int)EquipmentRole.Detection, detections[0].EquipmentRole); + Assert.Equal(8000.0, detections[0].RadarRange); + Assert.Equal(50.0, detections[0].DetectionAccuracy); + } + + [Fact] + public void GetDetections_FiltersOutLaunchPlatforms() + { + var task = _service.CreateTask("探测过滤测试", ""); + // 一个火力单元 + _service.SaveDeployment(task.Id, new List + { + new EquipmentDeployment + { + EquipmentRole = (int)EquipmentRole.LaunchPlatform, + Quantity = 1, PositionX = 1000, + }, + }); + // 两个探测设备(独立添加) + _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 5000 }); + _service.AddDetection(task.Id, new EquipmentDeployment { EORange = 3000 }); + + var detections = _service.GetDetections(task.Id); + Assert.Equal(2, detections.Count); // 只有探测设备,不含火力单元 + } + + [Fact] + public void DeleteDetection_RemovesOnlyOne() + { + var task = _service.CreateTask("探测删除测试", ""); + _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 5000 }); + var det2 = new EquipmentDeployment { EORange = 3000 }; + _service.AddDetection(task.Id, det2); + + _service.DeleteDetection(det2.Id); + + var detections = _service.GetDetections(task.Id); + Assert.Single(detections); + Assert.Equal(5000.0, detections[0].RadarRange); + } + + [Fact] + public void GetTaskDetail_IncludesDetections() + { + var task = _service.CreateTask("想定含探测", ""); + _service.SaveDeployment(task.Id, new List + { + new EquipmentDeployment { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 1 }, + }); + _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 10000 }); + + var detail = _service.GetTaskDetail(task.Id); + // Equipment 包含火力单元 + 探测设备 + Assert.Equal(2, detail.Equipment.Count); + Assert.Contains(detail.Equipment, e => e.EquipmentRole == (int)EquipmentRole.Detection); + Assert.Contains(detail.Equipment, e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); + } } }