生成代码工程
This commit is contained in:
parent
5c2aaae784
commit
5e063dba6d
138
README.md
138
README.md
|
|
@ -1,3 +1,137 @@
|
|||
# 求求了
|
||||
# 战场态势与任务规划系统
|
||||
|
||||
暂无描述
|
||||
## 项目简介
|
||||
|
||||
本项目实现战场态势与任务规划系统中**事件处理与任务生成模块(EHTG)** 与**任务方案管理软件(TMS)** 的核心后端服务。
|
||||
|
||||
### 核心功能
|
||||
|
||||
#### 事件处理与任务生成模块(EHTG)
|
||||
- 事件接收与解析、数据清洗与标准化
|
||||
- 高价值目标评估
|
||||
- 任务模板匹配与任务草案生成
|
||||
- 任务草案发送与重试机制
|
||||
|
||||
#### 任务方案管理软件(TMS)
|
||||
- 集中式/分布式方案列表展示与排序
|
||||
- 方案详情查看与多方案对比分析
|
||||
- 方案重构与差异高亮
|
||||
- 方案分发与执行状态监控
|
||||
- 异常告警与人机环通知
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 技术 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| Java | 17 | 开发语言 |
|
||||
| Spring Boot | 3.2.0 | 框架基础 |
|
||||
| Maven | 3.8+ | 构建工具 |
|
||||
| Knife4j + OpenAPI 3 | 4.5.0 | 接口文档与调试 |
|
||||
|
||||
## 快速启动
|
||||
|
||||
### 前置条件
|
||||
- JDK 17+
|
||||
- Maven 3.8+
|
||||
|
||||
### 编译运行
|
||||
|
||||
```bash
|
||||
# 编译
|
||||
mvn clean package
|
||||
|
||||
# 运行
|
||||
mvn spring-boot:run
|
||||
|
||||
# 或直接运行 jar
|
||||
java -jar target/battlefield-mission-system-1.0.0.jar
|
||||
```
|
||||
|
||||
### 访问地址
|
||||
|
||||
| 服务 | 地址 |
|
||||
|------|------|
|
||||
| 应用主页 | http://localhost:8080 |
|
||||
| Swagger 文档 | http://localhost:8080/swagger-ui/index.html |
|
||||
| Knife4j 文档 | http://localhost:8080/doc.html |
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
src/main/java/com/example/demo/
|
||||
├── DemoApplication.java # 启动类
|
||||
├── config/
|
||||
│ └── OpenApiConfig.java # OpenAPI/Knife4j 配置
|
||||
├── controller/
|
||||
│ ├── HealthController.java # 健康检查
|
||||
│ ├── EventController.java # 事件管理接口(EHTG)
|
||||
│ ├── TaskController.java # 任务生成接口(EHTG)
|
||||
│ └── SchemeController.java # 任务方案管理接口(TMS)
|
||||
├── service/
|
||||
│ ├── EventService.java # 事件处理服务
|
||||
│ ├── TaskGenerationService.java # 任务生成服务
|
||||
│ └── SchemeService.java # 任务方案管理服务
|
||||
├── model/
|
||||
│ ├── Event.java # 事件实体
|
||||
│ ├── TaskTemplate.java # 任务模板实体
|
||||
│ ├── TaskDraft.java # 任务草案实体
|
||||
│ ├── TaskScheme.java # 任务方案实体
|
||||
│ ├── enums/
|
||||
│ │ ├── EventStatus.java # 事件状态枚举
|
||||
│ │ ├── EventSourceType.java # 事件来源类型枚举
|
||||
│ │ ├── ThreatLevel.java # 威胁等级枚举
|
||||
│ │ └── SchemeStatus.java # 方案状态枚举
|
||||
│ └── dto/
|
||||
│ ├── EventDTO.java # 事件数据传输对象
|
||||
│ ├── EventQueryDTO.java # 事件查询参数
|
||||
│ ├── SchemeCompareDTO.java # 方案对比数据传输对象
|
||||
│ └── ApiResponse.java # 统一响应封装
|
||||
└── repository/
|
||||
├── EventRepository.java # 事件仓储接口(内存实现)
|
||||
├── TaskTemplateRepository.java # 任务模板仓储接口(内存实现)
|
||||
├── TaskDraftRepository.java # 任务草案仓储接口(内存实现)
|
||||
└── SchemeRepository.java # 方案仓储接口(内存实现)
|
||||
|
||||
src/test/java/com/example/demo/
|
||||
├── EventServiceTest.java # 事件服务测试
|
||||
├── TaskGenerationServiceTest.java # 任务生成服务测试
|
||||
└── SchemeServiceTest.java # 方案管理服务测试
|
||||
```
|
||||
|
||||
## API 概览
|
||||
|
||||
### 事件处理模块(EHTG)
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| POST | /api/v1/events | 接收原始事件 |
|
||||
| GET | /api/v1/events | 查询事件列表 |
|
||||
| GET | /api/v1/events/{id} | 查询事件详情 |
|
||||
| PUT | /api/v1/events/{id}/process | 处理事件 |
|
||||
|
||||
### 任务生成模块(EHTG)
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| POST | /api/v1/tasks/generate | 基于事件生成任务草案 |
|
||||
| GET | /api/v1/tasks/drafts | 查询任务草案列表 |
|
||||
| GET | /api/v1/tasks/drafts/{id} | 查询任务草案详情 |
|
||||
| POST | /api/v1/tasks/drafts/{id}/retry | 重试发送任务草案 |
|
||||
|
||||
### 任务方案管理模块(TMS)
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | /api/v1/schemes | 查询方案列表(支持排序、分页) |
|
||||
| GET | /api/v1/schemes/{id} | 查询方案详情 |
|
||||
| POST | /api/v1/schemes/compare | 多方案对比分析 |
|
||||
| POST | /api/v1/schemes/{id}/reconstruct | 方案重构 |
|
||||
| POST | /api/v1/schemes/{id}/dispatch | 方案分发 |
|
||||
| GET | /api/v1/schemes/{id}/execution-status | 查询执行状态 |
|
||||
|
||||
## 设计说明
|
||||
|
||||
### 当前实现
|
||||
- **数据层**:采用内存 `ConcurrentHashMap` 存储,所有数据在应用启动时初始化示例数据
|
||||
- **后续扩展**:预留了 `Repository` 接口层,后续可替换为 MyBatis/JPA 等数据库实现
|
||||
- **错误处理**:全局统一异常处理,返回标准错误格式
|
||||
|
||||
### 对应需求追溯
|
||||
所有业务方法均通过 Javadoc `@requirement` 标签关联需求,可追溯至软件需求规格说明。
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>battlefield-mission-system</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>战场态势与任务规划系统</name>
|
||||
<description>战场态势与任务规划系统 - 事件处理与任务生成模块(EHTG) + 任务方案管理软件(TMS)</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<knife4j.version>4.5.0</knife4j.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Validation -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Knife4j OpenAPI3 (Spring Boot 3.x Jakarta) -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 战场态势与任务规划系统 - 启动类。
|
||||
* <p>
|
||||
* 集成事件处理与任务生成模块(EHTG)和任务方案管理软件(TMS)的核心后端服务。
|
||||
* </p>
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DemoApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.example.demo.config;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* OpenAPI / Knife4j 配置类。
|
||||
* <p>
|
||||
* 配置 Swagger/OpenAPI 接口文档,集成 Knife4j 增强UI。
|
||||
* 访问地址:http://localhost:8080/doc.html
|
||||
* </p>
|
||||
*/
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
/**
|
||||
* 自定义 OpenAPI 信息。
|
||||
*
|
||||
* @return OpenAPI 实例
|
||||
*/
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title("战场态势与任务规划系统 API")
|
||||
.version("1.0.0")
|
||||
.description("""
|
||||
战场态势与任务规划系统 API 文档。
|
||||
集成以下两大核心模块:
|
||||
**1. 事件处理与任务生成模块(EHTG)**
|
||||
- 事件接收与解析、数据清洗与标准化
|
||||
- 高价值目标评估与任务模板匹配
|
||||
- 任务草案生成与发送重试
|
||||
|
||||
**2. 任务方案管理软件(TMS)**
|
||||
- 集中式/分布式方案列表展示与排序
|
||||
- 方案详情查看与多方案对比分析
|
||||
- 方案重构与版本关联追溯
|
||||
- 方案分发与执行状态监控
|
||||
""")
|
||||
.contact(new Contact()
|
||||
.name("开发团队")
|
||||
.email("dev@example.com"))
|
||||
.license(new License()
|
||||
.name("保密")
|
||||
.url("")));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.dto.ApiResponse;
|
||||
import com.example.demo.model.dto.EventDTO;
|
||||
import com.example.demo.model.dto.EventQueryDTO;
|
||||
import com.example.demo.model.enums.EventSourceType;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
import com.example.demo.model.enums.ThreatLevel;
|
||||
import com.example.demo.service.EventService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 事件管理控制器。
|
||||
* <p>
|
||||
* 提供事件接收、查询、处理等 RESTful API 接口。
|
||||
* 对应外部接口 IF-01 / SRS-EHTG_I_EVT 和 IF-02 / SRS-EHTG_I_UI。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="事件接收与解析", id="SRS-EHTG-01")
|
||||
* 通过HTTP POST接收上游传感器的原始事件数据。
|
||||
*
|
||||
* @requirement(name="前端可视化展示", id="SRS-EHTG-04")
|
||||
* 提供Web界面展示事件列表,支持排序、筛选和操作反馈。
|
||||
*/
|
||||
@Tag(name = "事件管理 (EHTG)", description = "事件处理与任务生成模块 - 事件接收、查询、处理接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/events")
|
||||
public class EventController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EventController.class);
|
||||
|
||||
private final EventService eventService;
|
||||
|
||||
public EventController(EventService eventService) {
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收原始事件。
|
||||
* <p>
|
||||
* 对应外部接口 IF-01,接收上游传感器融合模块的原始事件数据。
|
||||
* </p>
|
||||
*
|
||||
* @param eventDTO 事件数据
|
||||
* @return 处理后的标准化事件
|
||||
*/
|
||||
@Operation(summary = "接收原始事件", description = "接收上游传感器融合模块的原始事件数据,执行数据清洗与标准化")
|
||||
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Event> receiveEvent(@Valid @RequestBody EventDTO eventDTO) {
|
||||
log.info("接收到事件请求,来源: {}", eventDTO.getSourceType());
|
||||
|
||||
Event rawEvent = convertToEvent(eventDTO);
|
||||
Event processedEvent = eventService.receiveEvent(rawEvent);
|
||||
|
||||
return ApiResponse.success("事件接收并处理成功", processedEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询事件列表。
|
||||
* <p>
|
||||
* 支持按状态筛选、按字段排序和分页。
|
||||
* </p>
|
||||
*
|
||||
* @param query 查询参数
|
||||
* @return 事件列表
|
||||
*/
|
||||
@Operation(summary = "查询事件列表", description = "查询事件列表,支持状态筛选、排序和分页")
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<List<Event>> listEvents(@Valid EventQueryDTO query) {
|
||||
List<Event> events = eventService.queryEvents(query);
|
||||
return ApiResponse.success(events);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询事件详情。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 事件详情
|
||||
*/
|
||||
@Operation(summary = "查询事件详情", description = "根据事件ID查询事件详细信息")
|
||||
@GetMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Event> getEvent(@Parameter(description = "事件ID") @PathVariable String eventId) {
|
||||
Optional<Event> eventOpt = eventService.getEventById(eventId);
|
||||
return eventOpt.map(ApiResponse::success)
|
||||
.orElseGet(() -> ApiResponse.error(404, "事件不存在: " + eventId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理事件(更新状态)。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @param status 新状态
|
||||
* @return 更新后的事件
|
||||
*/
|
||||
@Operation(summary = "处理事件", description = "更新事件处理状态")
|
||||
@PutMapping(value = "/{eventId}/process", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Event> processEvent(
|
||||
@Parameter(description = "事件ID") @PathVariable String eventId,
|
||||
@Parameter(description = "目标状态:PENDING / PROCESSING / COMPLETED / IGNORED / ERROR")
|
||||
@RequestParam String status) {
|
||||
EventStatus eventStatus = EventStatus.valueOf(status.toUpperCase());
|
||||
Optional<Event> updated = eventService.updateEventStatus(eventId, eventStatus);
|
||||
return updated.map(ApiResponse::success)
|
||||
.orElseGet(() -> ApiResponse.error(404, "事件不存在: " + eventId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 DTO 转换为实体。
|
||||
*/
|
||||
private Event convertToEvent(EventDTO dto) {
|
||||
Event event = new Event();
|
||||
event.setEventId(dto.getEventId());
|
||||
event.setSourceType(dto.getSourceType());
|
||||
event.setOccurTime(dto.getOccurTime());
|
||||
event.setLocation(dto.getLocation());
|
||||
event.setConfidence(dto.getConfidence());
|
||||
event.setThreatLevel(dto.getThreatLevel());
|
||||
event.setEventType(dto.getEventType());
|
||||
event.setStatus(EventStatus.PENDING);
|
||||
event.setCreateTime(LocalDateTime.now());
|
||||
event.setUpdateTime(LocalDateTime.now());
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.example.demo.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 健康检查控制器。
|
||||
* <p>
|
||||
* 提供系统健康检查和运行状态信息。
|
||||
* </p>
|
||||
*/
|
||||
@Tag(name = "系统健康检查", description = "系统运行状态与健康检查接口")
|
||||
@RestController
|
||||
public class HealthController {
|
||||
|
||||
/**
|
||||
* 健康检查端点。
|
||||
*
|
||||
* @return 系统健康状态
|
||||
*/
|
||||
@Operation(summary = "健康检查", description = "返回系统运行状态信息,包括服务状态、运行时间等")
|
||||
@GetMapping("/api/health")
|
||||
public Map<String, Object> health() {
|
||||
Map<String, Object> status = new LinkedHashMap<>();
|
||||
status.put("status", "UP");
|
||||
status.put("service", "战场态势与任务规划系统");
|
||||
status.put("timestamp", LocalDateTime.now().toString());
|
||||
status.put("version", "1.0.0");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.TaskScheme;
|
||||
import com.example.demo.model.dto.ApiResponse;
|
||||
import com.example.demo.model.dto.SchemeCompareDTO;
|
||||
import com.example.demo.service.SchemeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 任务方案管理控制器。
|
||||
* <p>
|
||||
* 提供集中式/分布式任务方案的全生命周期管理 RESTful API。
|
||||
* 对应外部接口 SRS-TMS_I_UI、SRS-TMS_I_Planning、SRS-TMS_I_Execution。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="集中式/分布式方案列表展示", id="SRS-TMS-01")
|
||||
* 以表格或卡片形式展示所有可用任务方案,支持分页加载。
|
||||
*
|
||||
* @requirement(name="方案详情查看", id="SRS-TMS-03")
|
||||
* 展示兵力部署、行动路线、时间节点等详细信息。
|
||||
*
|
||||
* @requirement(name="多方案对比分析", id="SRS-TMS-04")
|
||||
* 支持最多5个方案的关键指标并列比较。
|
||||
*
|
||||
* @requirement(name="方案分发驱动", id="SRS-TMS-08")
|
||||
* 将选定方案解析为指令集,下发至指定执行节点。
|
||||
*
|
||||
* @requirement(name="执行状态监控", id="SRS-TMS-10")
|
||||
* 实时聚合子任务进度,展示整体完成率与当前状态。
|
||||
*/
|
||||
@Tag(name = "任务方案管理 (TMS)", description = "任务方案管理软件 - 方案列表、详情、对比、重构、分发、执行监控接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/schemes")
|
||||
public class SchemeController {
|
||||
|
||||
private final SchemeService schemeService;
|
||||
|
||||
public SchemeController(SchemeService schemeService) {
|
||||
this.schemeService = schemeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询方案列表。
|
||||
*
|
||||
* @param sortField 排序字段(createTime / priority / successRate / estimatedDuration / estimatedLossRatio)
|
||||
* @param sortDirection 排序方向(asc / desc)
|
||||
* @param page 页码
|
||||
* @param size 每页条数
|
||||
* @return 方案列表
|
||||
*/
|
||||
@Operation(summary = "查询方案列表", description = "查询所有可用任务方案,支持自定义排序和分页")
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<List<TaskScheme>> listSchemes(
|
||||
@Parameter(description = "排序字段") @RequestParam(required = false, defaultValue = "createTime") String sortField,
|
||||
@Parameter(description = "排序方向") @RequestParam(required = false, defaultValue = "desc") String sortDirection,
|
||||
@Parameter(description = "页码") @RequestParam(required = false, defaultValue = "0") int page,
|
||||
@Parameter(description = "每页条数") @RequestParam(required = false, defaultValue = "20") int size) {
|
||||
List<TaskScheme> schemes = schemeService.listSchemes(sortField, sortDirection, page, size);
|
||||
return ApiResponse.success(schemes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询方案详情。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @return 方案详情
|
||||
*/
|
||||
@Operation(summary = "查询方案详情", description = "展示兵力部署、行动路线、时间节点等详细信息及算法溯源")
|
||||
@GetMapping(value = "/{schemeId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<TaskScheme> getSchemeDetail(
|
||||
@Parameter(description = "方案ID") @PathVariable String schemeId) {
|
||||
Optional<TaskScheme> scheme = schemeService.getSchemeDetail(schemeId);
|
||||
return scheme.map(ApiResponse::success)
|
||||
.orElseGet(() -> ApiResponse.error(404, "方案不存在: " + schemeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 多方案对比分析。
|
||||
*
|
||||
* @param compareDTO 对比参数(最多5个方案)
|
||||
* @return 对比结果
|
||||
*/
|
||||
@Operation(summary = "多方案对比分析", description = "支持最多5个方案的关键指标并列比较(耗时、战损比、成功率等)")
|
||||
@PostMapping(value = "/compare", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Map<String, Object>> compareSchemes(@Valid @RequestBody SchemeCompareDTO compareDTO) {
|
||||
try {
|
||||
Map<String, Object> result = schemeService.compareSchemes(compareDTO);
|
||||
return ApiResponse.success(result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ApiResponse.badRequest(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 方案重构。
|
||||
*
|
||||
* @param schemeId 原方案ID
|
||||
* @param newConstraints 新约束条件(JSON格式)
|
||||
* @return 重构后的新方案
|
||||
*/
|
||||
@Operation(summary = "方案重构", description = "基于新约束条件重新生成或调整现有方案,并保留版本关联追溯")
|
||||
@PostMapping(value = "/{schemeId}/reconstruct", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<TaskScheme> reconstructScheme(
|
||||
@Parameter(description = "原方案ID") @PathVariable String schemeId,
|
||||
@Parameter(description = "新约束条件(JSON格式)") @RequestBody String newConstraints) {
|
||||
try {
|
||||
TaskScheme newScheme = schemeService.reconstructScheme(schemeId, newConstraints);
|
||||
return ApiResponse.success("方案重构成功", newScheme);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ApiResponse.badRequest(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 方案分发。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @param targetNode 目标执行节点
|
||||
* @return 分发结果
|
||||
*/
|
||||
@Operation(summary = "方案分发", description = "将选定方案解析为指令集,下发至指定执行节点")
|
||||
@PostMapping(value = "/{schemeId}/dispatch", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Map<String, Object>> dispatchScheme(
|
||||
@Parameter(description = "方案ID") @PathVariable String schemeId,
|
||||
@Parameter(description = "目标执行节点") @RequestParam String targetNode) {
|
||||
try {
|
||||
Map<String, Object> result = schemeService.dispatchScheme(schemeId, targetNode);
|
||||
return ApiResponse.success("方案分发成功", result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ApiResponse.badRequest(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询方案执行状态。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @return 执行状态
|
||||
*/
|
||||
@Operation(summary = "查询执行状态", description = "实时查询方案执行进度、子任务状态及整体完成率")
|
||||
@GetMapping(value = "/{schemeId}/execution-status", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<Map<String, Object>> getExecutionStatus(
|
||||
@Parameter(description = "方案ID") @PathVariable String schemeId) {
|
||||
try {
|
||||
Map<String, Object> status = schemeService.getExecutionStatus(schemeId);
|
||||
return ApiResponse.success(status);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ApiResponse.badRequest(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.TaskDraft;
|
||||
import com.example.demo.model.dto.ApiResponse;
|
||||
import com.example.demo.service.TaskGenerationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 任务生成控制器。
|
||||
* <p>
|
||||
* 提供任务草案生成、查询、发送与重试等 RESTful API 接口。
|
||||
* 对应外部接口 IF-03 / SRS-EHTG_O_TSK。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="任务模板匹配与生成", id="SRS-EHTG-06")
|
||||
* 结合知识库中的任务模板,自动生成符合标准的任务草案。
|
||||
*
|
||||
* @requirement(name="任务草案发送与重试机制", id="SRS-EHTG-07")
|
||||
* 向下游任务规划引擎发送请求,失败时自动加入本地重试队列。
|
||||
*/
|
||||
@Tag(name = "任务生成 (EHTG)", description = "事件处理与任务生成模块 - 任务草案生成、发送与重试接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/tasks")
|
||||
public class TaskController {
|
||||
|
||||
private final TaskGenerationService taskGenerationService;
|
||||
|
||||
public TaskController(TaskGenerationService taskGenerationService) {
|
||||
this.taskGenerationService = taskGenerationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于事件生成任务草案。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 生成的任务草案
|
||||
*/
|
||||
@Operation(summary = "生成任务草案", description = "基于事件评估结果,匹配任务模板并生成任务草案")
|
||||
@PostMapping(value = "/generate", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<TaskDraft> generateTaskDraft(
|
||||
@Parameter(description = "事件ID") @RequestParam String eventId) {
|
||||
try {
|
||||
TaskDraft draft = taskGenerationService.generateTaskDraft(eventId);
|
||||
return ApiResponse.success("任务草案生成成功", draft);
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
return ApiResponse.badRequest(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务草案列表。
|
||||
*
|
||||
* @return 草案列表
|
||||
*/
|
||||
@Operation(summary = "查询任务草案列表", description = "查询所有已生成的任务草案")
|
||||
@GetMapping(value = "/drafts", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<List<TaskDraft>> listDrafts() {
|
||||
return ApiResponse.success(taskGenerationService.getAllDrafts());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务草案详情。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 草案详情
|
||||
*/
|
||||
@Operation(summary = "查询任务草案详情", description = "根据草案ID查询任务草案详细信息")
|
||||
@GetMapping(value = "/drafts/{draftId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<TaskDraft> getDraft(
|
||||
@Parameter(description = "草案ID") @PathVariable String draftId) {
|
||||
Optional<TaskDraft> draft = taskGenerationService.getDraftById(draftId);
|
||||
return draft.map(ApiResponse::success)
|
||||
.orElseGet(() -> ApiResponse.error(404, "任务草案不存在: " + draftId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送任务草案到下游引擎。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 发送结果
|
||||
*/
|
||||
@Operation(summary = "发送任务草案", description = "将任务草案发送至下游任务规划引擎")
|
||||
@PostMapping(value = "/drafts/{draftId}/send", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<String> sendDraft(
|
||||
@Parameter(description = "草案ID") @PathVariable String draftId) {
|
||||
boolean success = taskGenerationService.sendTaskDraft(draftId);
|
||||
if (success) {
|
||||
return ApiResponse.success("任务草案发送成功", draftId);
|
||||
} else {
|
||||
return ApiResponse.error(500, "任务草案发送失败,已加入重试队列");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重试发送失败的任务草案。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 重试结果
|
||||
*/
|
||||
@Operation(summary = "重试发送任务草案", description = "重试发送之前失败的任务草案")
|
||||
@PostMapping(value = "/drafts/{draftId}/retry", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponse<String> retrySendDraft(
|
||||
@Parameter(description = "草案ID") @PathVariable String draftId) {
|
||||
boolean success = taskGenerationService.retrySendDraft(draftId);
|
||||
if (success) {
|
||||
return ApiResponse.success("任务草案重试发送成功", draftId);
|
||||
} else {
|
||||
return ApiResponse.error(500, "任务草案重试发送失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
package com.example.demo.model;
|
||||
|
||||
import com.example.demo.model.enums.EventSourceType;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
import com.example.demo.model.enums.ThreatLevel;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 事件实体模型。
|
||||
* <p>
|
||||
* 对应数据库表 T_EVENT_INFO,表示从传感器接收到的原始事件,
|
||||
* 经过数据清洗与标准化后形成的内部表示。
|
||||
* </p>
|
||||
*/
|
||||
public class Event {
|
||||
|
||||
/** 事件唯一标识,全局唯一ID */
|
||||
private String eventId;
|
||||
|
||||
/** 事件来源类型:1-雷达, 2-光电 */
|
||||
private EventSourceType sourceType;
|
||||
|
||||
/** 事件发生时间,精确到毫秒 */
|
||||
private LocalDateTime occurTime;
|
||||
|
||||
/** 目标经纬度,JSON格式存储,如 {"lng": 116.397, "lat": 39.908} */
|
||||
private String location;
|
||||
|
||||
/** 事件置信度,范围0.0~1.0 */
|
||||
private double confidence;
|
||||
|
||||
/** 处理状态码:0-待处理, 1-已完成 */
|
||||
private EventStatus status;
|
||||
|
||||
/** 威胁等级 */
|
||||
private ThreatLevel threatLevel;
|
||||
|
||||
/** 事件类型:临机/规划 */
|
||||
private String eventType;
|
||||
|
||||
/** 创建时间,默认系统当前时间 */
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
public Event() {
|
||||
}
|
||||
|
||||
public Event(String eventId, EventSourceType sourceType, LocalDateTime occurTime,
|
||||
String location, double confidence, EventStatus status,
|
||||
ThreatLevel threatLevel, String eventType) {
|
||||
this.eventId = eventId;
|
||||
this.sourceType = sourceType;
|
||||
this.occurTime = occurTime;
|
||||
this.location = location;
|
||||
this.confidence = confidence;
|
||||
this.status = status;
|
||||
this.threatLevel = threatLevel;
|
||||
this.eventType = eventType;
|
||||
this.createTime = LocalDateTime.now();
|
||||
this.updateTime = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(String eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
public EventSourceType getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public void setSourceType(EventSourceType sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
public LocalDateTime getOccurTime() {
|
||||
return occurTime;
|
||||
}
|
||||
|
||||
public void setOccurTime(LocalDateTime occurTime) {
|
||||
this.occurTime = occurTime;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public double getConfidence() {
|
||||
return confidence;
|
||||
}
|
||||
|
||||
public void setConfidence(double confidence) {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
public EventStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(EventStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public ThreatLevel getThreatLevel() {
|
||||
return threatLevel;
|
||||
}
|
||||
|
||||
public void setThreatLevel(ThreatLevel threatLevel) {
|
||||
this.threatLevel = threatLevel;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(LocalDateTime createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(LocalDateTime updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package com.example.demo.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 任务草案实体模型。
|
||||
* <p>
|
||||
* 表示基于事件评估后生成的作战任务草案,
|
||||
* 准备下发至任务规划引擎进行详细规划。
|
||||
* </p>
|
||||
*/
|
||||
public class TaskDraft {
|
||||
|
||||
/** 任务草案唯一标识 */
|
||||
private String draftId;
|
||||
|
||||
/** 关联的事件ID */
|
||||
private String eventId;
|
||||
|
||||
/** 使用的模板ID */
|
||||
private String templateId;
|
||||
|
||||
/** 任务草案标题 */
|
||||
private String title;
|
||||
|
||||
/** 任务草案内容(JSON格式) */
|
||||
private String content;
|
||||
|
||||
/** 目标价值评分 */
|
||||
private double targetValueScore;
|
||||
|
||||
/** 发送状态:0-未发送, 1-已发送, 2-发送失败 */
|
||||
private int sendStatus;
|
||||
|
||||
/** 发送重试次数 */
|
||||
private int retryCount;
|
||||
|
||||
/** 创建时间 */
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/** 最后发送时间 */
|
||||
private LocalDateTime lastSendTime;
|
||||
|
||||
public TaskDraft() {
|
||||
}
|
||||
|
||||
public TaskDraft(String draftId, String eventId, String templateId, String title,
|
||||
String content, double targetValueScore) {
|
||||
this.draftId = draftId;
|
||||
this.eventId = eventId;
|
||||
this.templateId = templateId;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.targetValueScore = targetValueScore;
|
||||
this.sendStatus = 0;
|
||||
this.retryCount = 0;
|
||||
this.createTime = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public String getDraftId() {
|
||||
return draftId;
|
||||
}
|
||||
|
||||
public void setDraftId(String draftId) {
|
||||
this.draftId = draftId;
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(String eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
public String getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public void setTemplateId(String templateId) {
|
||||
this.templateId = templateId;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public double getTargetValueScore() {
|
||||
return targetValueScore;
|
||||
}
|
||||
|
||||
public void setTargetValueScore(double targetValueScore) {
|
||||
this.targetValueScore = targetValueScore;
|
||||
}
|
||||
|
||||
public int getSendStatus() {
|
||||
return sendStatus;
|
||||
}
|
||||
|
||||
public void setSendStatus(int sendStatus) {
|
||||
this.sendStatus = sendStatus;
|
||||
}
|
||||
|
||||
public int getRetryCount() {
|
||||
return retryCount;
|
||||
}
|
||||
|
||||
public void setRetryCount(int retryCount) {
|
||||
this.retryCount = retryCount;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(LocalDateTime createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastSendTime() {
|
||||
return lastSendTime;
|
||||
}
|
||||
|
||||
public void setLastSendTime(LocalDateTime lastSendTime) {
|
||||
this.lastSendTime = lastSendTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
package com.example.demo.model;
|
||||
|
||||
import com.example.demo.model.enums.SchemeStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务方案实体模型。
|
||||
* <p>
|
||||
* 表示经过任务规划引擎生成的作战任务方案,
|
||||
* 包含兵力部署、行动路线、时间节点等详细信息。
|
||||
* </p>
|
||||
*/
|
||||
public class TaskScheme {
|
||||
|
||||
/** 方案唯一标识 */
|
||||
private String schemeId;
|
||||
|
||||
/** 方案名称 */
|
||||
private String schemeName;
|
||||
|
||||
/** 方案类型:集中式/分布式 */
|
||||
private String schemeType;
|
||||
|
||||
/** 关联事件ID */
|
||||
private String eventId;
|
||||
|
||||
/** 关联任务草案ID */
|
||||
private String draftId;
|
||||
|
||||
/** 方案状态 */
|
||||
private SchemeStatus status;
|
||||
|
||||
/** 方案优先级(1-10,数值越高优先级越高) */
|
||||
private int priority;
|
||||
|
||||
/** 预计耗时(分钟) */
|
||||
private int estimatedDuration;
|
||||
|
||||
/** 预计战损比(0.0~1.0) */
|
||||
private double estimatedLossRatio;
|
||||
|
||||
/** 方案成功率(0.0~1.0) */
|
||||
private double successRate;
|
||||
|
||||
/** 兵力部署详情(JSON格式) */
|
||||
private String deploymentDetail;
|
||||
|
||||
/** 行动路线(JSON格式) */
|
||||
private String routeDetail;
|
||||
|
||||
/** 时间节点(JSON格式) */
|
||||
private String timelineDetail;
|
||||
|
||||
/** 算法溯源信息(AI生成路径、优化过程) */
|
||||
private String algorithmTrace;
|
||||
|
||||
/** 父方案ID(重构时关联旧版本) */
|
||||
private String parentSchemeId;
|
||||
|
||||
/** 版本号 */
|
||||
private int version;
|
||||
|
||||
/** 执行进度百分比(0~100) */
|
||||
private int executionProgress;
|
||||
|
||||
/** 子任务状态列表(JSON格式) */
|
||||
private String subTaskStatus;
|
||||
|
||||
/** 创建时间 */
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
public TaskScheme() {
|
||||
}
|
||||
|
||||
public TaskScheme(String schemeId, String schemeName, String schemeType,
|
||||
SchemeStatus status, int priority, int estimatedDuration,
|
||||
double estimatedLossRatio, double successRate) {
|
||||
this.schemeId = schemeId;
|
||||
this.schemeName = schemeName;
|
||||
this.schemeType = schemeType;
|
||||
this.status = status;
|
||||
this.priority = priority;
|
||||
this.estimatedDuration = estimatedDuration;
|
||||
this.estimatedLossRatio = estimatedLossRatio;
|
||||
this.successRate = successRate;
|
||||
this.version = 1;
|
||||
this.executionProgress = 0;
|
||||
this.createTime = LocalDateTime.now();
|
||||
this.updateTime = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public String getSchemeId() {
|
||||
return schemeId;
|
||||
}
|
||||
|
||||
public void setSchemeId(String schemeId) {
|
||||
this.schemeId = schemeId;
|
||||
}
|
||||
|
||||
public String getSchemeName() {
|
||||
return schemeName;
|
||||
}
|
||||
|
||||
public void setSchemeName(String schemeName) {
|
||||
this.schemeName = schemeName;
|
||||
}
|
||||
|
||||
public String getSchemeType() {
|
||||
return schemeType;
|
||||
}
|
||||
|
||||
public void setSchemeType(String schemeType) {
|
||||
this.schemeType = schemeType;
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(String eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
public String getDraftId() {
|
||||
return draftId;
|
||||
}
|
||||
|
||||
public void setDraftId(String draftId) {
|
||||
this.draftId = draftId;
|
||||
}
|
||||
|
||||
public SchemeStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(SchemeStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public int getEstimatedDuration() {
|
||||
return estimatedDuration;
|
||||
}
|
||||
|
||||
public void setEstimatedDuration(int estimatedDuration) {
|
||||
this.estimatedDuration = estimatedDuration;
|
||||
}
|
||||
|
||||
public double getEstimatedLossRatio() {
|
||||
return estimatedLossRatio;
|
||||
}
|
||||
|
||||
public void setEstimatedLossRatio(double estimatedLossRatio) {
|
||||
this.estimatedLossRatio = estimatedLossRatio;
|
||||
}
|
||||
|
||||
public double getSuccessRate() {
|
||||
return successRate;
|
||||
}
|
||||
|
||||
public void setSuccessRate(double successRate) {
|
||||
this.successRate = successRate;
|
||||
}
|
||||
|
||||
public String getDeploymentDetail() {
|
||||
return deploymentDetail;
|
||||
}
|
||||
|
||||
public void setDeploymentDetail(String deploymentDetail) {
|
||||
this.deploymentDetail = deploymentDetail;
|
||||
}
|
||||
|
||||
public String getRouteDetail() {
|
||||
return routeDetail;
|
||||
}
|
||||
|
||||
public void setRouteDetail(String routeDetail) {
|
||||
this.routeDetail = routeDetail;
|
||||
}
|
||||
|
||||
public String getTimelineDetail() {
|
||||
return timelineDetail;
|
||||
}
|
||||
|
||||
public void setTimelineDetail(String timelineDetail) {
|
||||
this.timelineDetail = timelineDetail;
|
||||
}
|
||||
|
||||
public String getAlgorithmTrace() {
|
||||
return algorithmTrace;
|
||||
}
|
||||
|
||||
public void setAlgorithmTrace(String algorithmTrace) {
|
||||
this.algorithmTrace = algorithmTrace;
|
||||
}
|
||||
|
||||
public String getParentSchemeId() {
|
||||
return parentSchemeId;
|
||||
}
|
||||
|
||||
public void setParentSchemeId(String parentSchemeId) {
|
||||
this.parentSchemeId = parentSchemeId;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public int getExecutionProgress() {
|
||||
return executionProgress;
|
||||
}
|
||||
|
||||
public void setExecutionProgress(int executionProgress) {
|
||||
this.executionProgress = executionProgress;
|
||||
}
|
||||
|
||||
public String getSubTaskStatus() {
|
||||
return subTaskStatus;
|
||||
}
|
||||
|
||||
public void setSubTaskStatus(String subTaskStatus) {
|
||||
this.subTaskStatus = subTaskStatus;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(LocalDateTime createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(LocalDateTime updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package com.example.demo.model;
|
||||
|
||||
/**
|
||||
* 任务模板实体模型。
|
||||
* <p>
|
||||
* 对应数据库表 T_TASK_TEMPLATE,存储任务生成的模板定义。
|
||||
* 模板包含目标类型匹配规则、任务逻辑定义等内容。
|
||||
* </p>
|
||||
*/
|
||||
public class TaskTemplate {
|
||||
|
||||
/** 模板唯一标识,全局唯一ID */
|
||||
private String templateId;
|
||||
|
||||
/** 适用目标类型,关联目标分类 */
|
||||
private int targetType;
|
||||
|
||||
/** 模板内容XML,存储任务逻辑定义 */
|
||||
private String contentXml;
|
||||
|
||||
/** 版本号,如 V1.0 */
|
||||
private String version;
|
||||
|
||||
/** 启用状态:是否启用该模板 */
|
||||
private boolean active;
|
||||
|
||||
/** 模板名称 */
|
||||
private String templateName;
|
||||
|
||||
/** 模板描述 */
|
||||
private String description;
|
||||
|
||||
public TaskTemplate() {
|
||||
}
|
||||
|
||||
public TaskTemplate(String templateId, int targetType, String contentXml,
|
||||
String version, boolean active, String templateName, String description) {
|
||||
this.templateId = templateId;
|
||||
this.targetType = targetType;
|
||||
this.contentXml = contentXml;
|
||||
this.version = version;
|
||||
this.active = active;
|
||||
this.templateName = templateName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public void setTemplateId(String templateId) {
|
||||
this.templateId = templateId;
|
||||
}
|
||||
|
||||
public int getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public void setTargetType(int targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public String getContentXml() {
|
||||
return contentXml;
|
||||
}
|
||||
|
||||
public void setContentXml(String contentXml) {
|
||||
this.contentXml = contentXml;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package com.example.demo.model.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* 统一API响应封装。
|
||||
* <p>
|
||||
* 所有接口统一返回此格式,包含状态码、消息和数据。
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 数据类型
|
||||
*/
|
||||
@Schema(description = "统一API响应")
|
||||
public class ApiResponse<T> {
|
||||
|
||||
@Schema(description = "状态码,200表示成功")
|
||||
private int code;
|
||||
|
||||
@Schema(description = "响应消息")
|
||||
private String message;
|
||||
|
||||
@Schema(description = "响应数据")
|
||||
private T data;
|
||||
|
||||
private ApiResponse() {
|
||||
}
|
||||
|
||||
private ApiResponse(int code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应。
|
||||
*
|
||||
* @param data 数据
|
||||
* @param <T> 数据类型
|
||||
* @return API响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(200, "操作成功", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(带自定义消息)。
|
||||
*
|
||||
* @param message 消息
|
||||
* @param data 数据
|
||||
* @param <T> 数据类型
|
||||
* @return API响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(String message, T data) {
|
||||
return new ApiResponse<>(200, message, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应。
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param message 错误消息
|
||||
* @param <T> 数据类型
|
||||
* @return API响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> error(int code, String message) {
|
||||
return new ApiResponse<>(code, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数错误响应。
|
||||
*
|
||||
* @param message 错误消息
|
||||
* @param <T> 数据类型
|
||||
* @return API响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> badRequest(String message) {
|
||||
return new ApiResponse<>(400, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务内部错误响应。
|
||||
*
|
||||
* @param message 错误消息
|
||||
* @param <T> 数据类型
|
||||
* @return API响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> internalError(String message) {
|
||||
return new ApiResponse<>(500, message, null);
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.example.demo.model.dto;
|
||||
|
||||
import com.example.demo.model.enums.EventSourceType;
|
||||
import com.example.demo.model.enums.ThreatLevel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 事件数据传输对象。
|
||||
* <p>
|
||||
* 用于API请求和响应中传输事件数据。
|
||||
* </p>
|
||||
*/
|
||||
@Schema(description = "事件数据传输对象")
|
||||
public class EventDTO {
|
||||
|
||||
@Schema(description = "事件唯一标识")
|
||||
private String eventId;
|
||||
|
||||
@Schema(description = "事件来源类型:RADAR / OPTOELECTRONIC / ELECTRONIC_RECON / COMMUNICATION_INTEL")
|
||||
private EventSourceType sourceType;
|
||||
|
||||
@Schema(description = "事件发生时间(格式:yyyy-MM-dd'T'HH:mm:ss)")
|
||||
private LocalDateTime occurTime;
|
||||
|
||||
@Schema(description = "目标经纬度,JSON格式")
|
||||
private String location;
|
||||
|
||||
@Schema(description = "事件置信度(0.0~1.0)")
|
||||
private double confidence;
|
||||
|
||||
@Schema(description = "威胁等级:LOW / MEDIUM / HIGH / CRITICAL")
|
||||
private ThreatLevel threatLevel;
|
||||
|
||||
@Schema(description = "事件类型:临机/规划")
|
||||
private String eventType;
|
||||
|
||||
@Schema(description = "处理状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
public EventDTO() {
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(String eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
public EventSourceType getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public void setSourceType(EventSourceType sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
public LocalDateTime getOccurTime() {
|
||||
return occurTime;
|
||||
}
|
||||
|
||||
public void setOccurTime(LocalDateTime occurTime) {
|
||||
this.occurTime = occurTime;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public double getConfidence() {
|
||||
return confidence;
|
||||
}
|
||||
|
||||
public void setConfidence(double confidence) {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
public ThreatLevel getThreatLevel() {
|
||||
return threatLevel;
|
||||
}
|
||||
|
||||
public void setThreatLevel(ThreatLevel threatLevel) {
|
||||
this.threatLevel = threatLevel;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(LocalDateTime createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
package com.example.demo.model.dto;
|
||||
|
||||
import com.example.demo.model.enums.EventSourceType;
|
||||
import com.example.demo.model.enums.ThreatLevel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 事件查询/接收参数DTO。
|
||||
* <p>
|
||||
* 用于接收上游传感器的事件数据或前端查询参数。
|
||||
* </p>
|
||||
*/
|
||||
@Schema(description = "事件接收/查询参数")
|
||||
public class EventQueryDTO {
|
||||
|
||||
@Schema(description = "事件来源类型")
|
||||
private EventSourceType sourceType;
|
||||
|
||||
@Schema(description = "事件发生时间")
|
||||
private LocalDateTime occurTime;
|
||||
|
||||
@Schema(description = "目标经纬度,JSON格式")
|
||||
private String location;
|
||||
|
||||
@Schema(description = "事件置信度(0.0~1.0)")
|
||||
@Min(0) @Max(1)
|
||||
private double confidence;
|
||||
|
||||
@Schema(description = "威胁等级")
|
||||
private ThreatLevel threatLevel;
|
||||
|
||||
@Schema(description = "事件类型")
|
||||
private String eventType;
|
||||
|
||||
@Schema(description = "处理状态关键字过滤")
|
||||
private String statusFilter;
|
||||
|
||||
@Schema(description = "排序字段(createTime / occurTime / threatLevel / confidence)")
|
||||
private String sortField;
|
||||
|
||||
@Schema(description = "排序方向:asc / desc")
|
||||
private String sortDirection;
|
||||
|
||||
@Schema(description = "页码,从0开始")
|
||||
private int page;
|
||||
|
||||
@Schema(description = "每页条数")
|
||||
private int size;
|
||||
|
||||
public EventSourceType getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public void setSourceType(EventSourceType sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
public LocalDateTime getOccurTime() {
|
||||
return occurTime;
|
||||
}
|
||||
|
||||
public void setOccurTime(LocalDateTime occurTime) {
|
||||
this.occurTime = occurTime;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public double getConfidence() {
|
||||
return confidence;
|
||||
}
|
||||
|
||||
public void setConfidence(double confidence) {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
public ThreatLevel getThreatLevel() {
|
||||
return threatLevel;
|
||||
}
|
||||
|
||||
public void setThreatLevel(ThreatLevel threatLevel) {
|
||||
this.threatLevel = threatLevel;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getStatusFilter() {
|
||||
return statusFilter;
|
||||
}
|
||||
|
||||
public void setStatusFilter(String statusFilter) {
|
||||
this.statusFilter = statusFilter;
|
||||
}
|
||||
|
||||
public String getSortField() {
|
||||
return sortField;
|
||||
}
|
||||
|
||||
public void setSortField(String sortField) {
|
||||
this.sortField = sortField;
|
||||
}
|
||||
|
||||
public String getSortDirection() {
|
||||
return sortDirection;
|
||||
}
|
||||
|
||||
public void setSortDirection(String sortDirection) {
|
||||
this.sortDirection = sortDirection;
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.example.demo.model.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 方案对比分析数据传输对象。
|
||||
* <p>
|
||||
* 用于接收前端多方案对比请求,支持最多5个方案的关键指标并列比较。
|
||||
* </p>
|
||||
*/
|
||||
@Schema(description = "方案对比分析请求参数")
|
||||
public class SchemeCompareDTO {
|
||||
|
||||
@Schema(description = "待对比的方案ID列表(最多5个)")
|
||||
private List<String> schemeIds;
|
||||
|
||||
@Schema(description = "对比字段列表(estimatedDuration / estimatedLossRatio / successRate / priority 等)")
|
||||
private List<String> compareFields;
|
||||
|
||||
public List<String> getSchemeIds() {
|
||||
return schemeIds;
|
||||
}
|
||||
|
||||
public void setSchemeIds(List<String> schemeIds) {
|
||||
this.schemeIds = schemeIds;
|
||||
}
|
||||
|
||||
public List<String> getCompareFields() {
|
||||
return compareFields;
|
||||
}
|
||||
|
||||
public void setCompareFields(List<String> compareFields) {
|
||||
this.compareFields = compareFields;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.example.demo.model.enums;
|
||||
|
||||
/**
|
||||
* 事件来源类型枚举。
|
||||
* <p>
|
||||
* 定义事件数据来源的传感器类型。
|
||||
* </p>
|
||||
*/
|
||||
public enum EventSourceType {
|
||||
|
||||
/** 雷达传感器 */
|
||||
RADAR(1, "雷达"),
|
||||
|
||||
/** 光电传感器 */
|
||||
OPTOELECTRONIC(2, "光电"),
|
||||
|
||||
/** 电子侦察 */
|
||||
ELECTRONIC_RECON(3, "电子侦察"),
|
||||
|
||||
/** 通信情报 */
|
||||
COMMUNICATION_INTEL(4, "通信情报");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
EventSourceType(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据来源码获取枚举实例。
|
||||
*
|
||||
* @param code 来源码
|
||||
* @return 对应的枚举实例
|
||||
*/
|
||||
public static EventSourceType fromCode(int code) {
|
||||
for (EventSourceType type : values()) {
|
||||
if (type.code == code) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.example.demo.model.enums;
|
||||
|
||||
/**
|
||||
* 事件处理状态枚举。
|
||||
* <p>
|
||||
* 定义事件从接收到处理完成的完整生命周期状态。
|
||||
* </p>
|
||||
*/
|
||||
public enum EventStatus {
|
||||
|
||||
/** 待处理 - 事件已接收但尚未处理 */
|
||||
PENDING(0, "待处理"),
|
||||
|
||||
/** 处理中 - 正在对事件进行分析评估 */
|
||||
PROCESSING(1, "处理中"),
|
||||
|
||||
/** 已完成 - 事件已处理完成 */
|
||||
COMPLETED(2, "已完成"),
|
||||
|
||||
/** 已忽略 - 事件经评估无需生成任务 */
|
||||
IGNORED(3, "已忽略"),
|
||||
|
||||
/** 异常 - 事件处理过程中发生错误 */
|
||||
ERROR(4, "异常");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
EventStatus(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态码获取枚举实例。
|
||||
*
|
||||
* @param code 状态码
|
||||
* @return 对应的枚举实例,未找到时返回 null
|
||||
*/
|
||||
public static EventStatus fromCode(int code) {
|
||||
for (EventStatus status : values()) {
|
||||
if (status.code == code) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.example.demo.model.enums;
|
||||
|
||||
/**
|
||||
* 任务方案状态枚举。
|
||||
* <p>
|
||||
* 定义任务方案从生成到执行完成的完整生命周期状态。
|
||||
* </p>
|
||||
*/
|
||||
public enum SchemeStatus {
|
||||
|
||||
/** 待分发 - 方案已生成但尚未下发 */
|
||||
PENDING_DISPATCH(0, "待分发"),
|
||||
|
||||
/** 分发中 - 方案正在下发至执行节点 */
|
||||
DISPATCHING(1, "分发中"),
|
||||
|
||||
/** 执行中 - 方案已下发,正在执行 */
|
||||
EXECUTING(2, "执行中"),
|
||||
|
||||
/** 已完成 - 方案执行完毕 */
|
||||
COMPLETED(3, "已完成"),
|
||||
|
||||
/** 已中止 - 方案执行被中止 */
|
||||
ABORTED(4, "已中止");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
SchemeStatus(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态码获取枚举实例。
|
||||
*
|
||||
* @param code 状态码
|
||||
* @return 对应的枚举实例
|
||||
*/
|
||||
public static SchemeStatus fromCode(int code) {
|
||||
for (SchemeStatus status : values()) {
|
||||
if (status.code == code) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.example.demo.model.enums;
|
||||
|
||||
/**
|
||||
* 威胁等级枚举。
|
||||
* <p>
|
||||
* 定义目标威胁程度的分级标准,数值越高威胁越大。
|
||||
* </p>
|
||||
*/
|
||||
public enum ThreatLevel {
|
||||
|
||||
/** 低威胁 */
|
||||
LOW(1, "低"),
|
||||
|
||||
/** 中威胁 */
|
||||
MEDIUM(2, "中"),
|
||||
|
||||
/** 高威胁 */
|
||||
HIGH(3, "高"),
|
||||
|
||||
/** 极高威胁 */
|
||||
CRITICAL(4, "极高");
|
||||
|
||||
private final int level;
|
||||
private final String description;
|
||||
|
||||
ThreatLevel(int level, String description) {
|
||||
this.level = level;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据等级值获取枚举实例。
|
||||
*
|
||||
* @param level 等级值
|
||||
* @return 对应的枚举实例
|
||||
*/
|
||||
public static ThreatLevel fromLevel(int level) {
|
||||
for (ThreatLevel tl : values()) {
|
||||
if (tl.level == level) {
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.example.demo.repository;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 事件仓储接口。
|
||||
* <p>
|
||||
* 定义事件数据的存储操作,当前基于内存实现。
|
||||
* 后续可扩展为 PostgreSQL / 达梦DM8 数据库实现。
|
||||
* </p>
|
||||
*/
|
||||
public interface EventRepository {
|
||||
|
||||
/**
|
||||
* 保存事件。
|
||||
*
|
||||
* @param event 事件对象
|
||||
* @return 保存后的事件
|
||||
*/
|
||||
Event save(Event event);
|
||||
|
||||
/**
|
||||
* 根据ID查询事件。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 事件(Optional)
|
||||
*/
|
||||
Optional<Event> findById(String eventId);
|
||||
|
||||
/**
|
||||
* 查询所有事件。
|
||||
*
|
||||
* @return 事件列表
|
||||
*/
|
||||
List<Event> findAll();
|
||||
|
||||
/**
|
||||
* 根据状态查询事件。
|
||||
*
|
||||
* @param status 事件状态
|
||||
* @return 事件列表
|
||||
*/
|
||||
List<Event> findByStatus(EventStatus status);
|
||||
|
||||
/**
|
||||
* 更新事件状态。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @param status 新状态
|
||||
* @return 更新后的事件
|
||||
*/
|
||||
Optional<Event> updateStatus(String eventId, EventStatus status);
|
||||
|
||||
/**
|
||||
* 删除事件。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
*/
|
||||
void deleteById(String eventId);
|
||||
|
||||
/**
|
||||
* 统计事件总数。
|
||||
*
|
||||
* @return 总数
|
||||
*/
|
||||
long count();
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.example.demo.repository;
|
||||
|
||||
import com.example.demo.model.TaskScheme;
|
||||
import com.example.demo.model.enums.SchemeStatus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 任务方案仓储接口。
|
||||
* <p>
|
||||
* 定义任务方案数据的存储操作,当前基于内存实现。
|
||||
* 后续可扩展为 PostgreSQL / 达梦DM8 数据库实现。
|
||||
* </p>
|
||||
*/
|
||||
public interface SchemeRepository {
|
||||
|
||||
/**
|
||||
* 保存任务方案。
|
||||
*
|
||||
* @param scheme 任务方案
|
||||
* @return 保存后的方案
|
||||
*/
|
||||
TaskScheme save(TaskScheme scheme);
|
||||
|
||||
/**
|
||||
* 根据ID查询方案。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @return 方案(Optional)
|
||||
*/
|
||||
Optional<TaskScheme> findById(String schemeId);
|
||||
|
||||
/**
|
||||
* 查询所有任务方案。
|
||||
*
|
||||
* @return 方案列表
|
||||
*/
|
||||
List<TaskScheme> findAll();
|
||||
|
||||
/**
|
||||
* 根据状态查询方案。
|
||||
*
|
||||
* @param status 方案状态
|
||||
* @return 方案列表
|
||||
*/
|
||||
List<TaskScheme> findByStatus(SchemeStatus status);
|
||||
|
||||
/**
|
||||
* 根据关联事件ID查询方案。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 方案列表
|
||||
*/
|
||||
List<TaskScheme> findByEventId(String eventId);
|
||||
|
||||
/**
|
||||
* 更新方案状态。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @param status 新状态
|
||||
* @return 更新后的方案
|
||||
*/
|
||||
Optional<TaskScheme> updateStatus(String schemeId, SchemeStatus status);
|
||||
|
||||
/**
|
||||
* 更新执行进度。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @param progress 执行进度百分比
|
||||
* @return 更新后的方案
|
||||
*/
|
||||
Optional<TaskScheme> updateProgress(String schemeId, int progress);
|
||||
|
||||
/**
|
||||
* 删除方案。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
*/
|
||||
void deleteById(String schemeId);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.example.demo.repository;
|
||||
|
||||
import com.example.demo.model.TaskDraft;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 任务草案仓储接口。
|
||||
* <p>
|
||||
* 定义任务草案数据的存储操作,当前基于内存实现。
|
||||
* 后续可扩展为 PostgreSQL / 达梦DM8 数据库实现。
|
||||
* </p>
|
||||
*/
|
||||
public interface TaskDraftRepository {
|
||||
|
||||
/**
|
||||
* 保存任务草案。
|
||||
*
|
||||
* @param draft 任务草案
|
||||
* @return 保存后的草案
|
||||
*/
|
||||
TaskDraft save(TaskDraft draft);
|
||||
|
||||
/**
|
||||
* 根据ID查询任务草案。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 草案(Optional)
|
||||
*/
|
||||
Optional<TaskDraft> findById(String draftId);
|
||||
|
||||
/**
|
||||
* 根据事件ID查询任务草案。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 草案列表
|
||||
*/
|
||||
List<TaskDraft> findByEventId(String eventId);
|
||||
|
||||
/**
|
||||
* 查询所有任务草案。
|
||||
*
|
||||
* @return 草案列表
|
||||
*/
|
||||
List<TaskDraft> findAll();
|
||||
|
||||
/**
|
||||
* 查询所有发送失败的任务草案(用于重试)。
|
||||
*
|
||||
* @return 发送失败的草案列表
|
||||
*/
|
||||
List<TaskDraft> findAllFailed();
|
||||
|
||||
/**
|
||||
* 更新发送状态。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @param sendStatus 发送状态
|
||||
* @param retryCount 重试次数
|
||||
* @return 更新后的草案
|
||||
*/
|
||||
Optional<TaskDraft> updateSendStatus(String draftId, int sendStatus, int retryCount);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.example.demo.repository;
|
||||
|
||||
import com.example.demo.model.TaskTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 任务模板仓储接口。
|
||||
* <p>
|
||||
* 定义任务模板数据的存储操作,当前基于内存实现。
|
||||
* 后续可扩展为 PostgreSQL / 达梦DM8 数据库实现。
|
||||
* </p>
|
||||
*/
|
||||
public interface TaskTemplateRepository {
|
||||
|
||||
/**
|
||||
* 保存模板。
|
||||
*
|
||||
* @param template 任务模板
|
||||
* @return 保存后的模板
|
||||
*/
|
||||
TaskTemplate save(TaskTemplate template);
|
||||
|
||||
/**
|
||||
* 根据ID查询模板。
|
||||
*
|
||||
* @param templateId 模板ID
|
||||
* @return 模板(Optional)
|
||||
*/
|
||||
Optional<TaskTemplate> findById(String templateId);
|
||||
|
||||
/**
|
||||
* 查询所有启用的模板。
|
||||
*
|
||||
* @return 模板列表
|
||||
*/
|
||||
List<TaskTemplate> findAllActive();
|
||||
|
||||
/**
|
||||
* 根据目标类型查询启用的模板。
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @return 模板列表
|
||||
*/
|
||||
List<TaskTemplate> findByTargetType(int targetType);
|
||||
|
||||
/**
|
||||
* 查询所有模板。
|
||||
*
|
||||
* @return 模板列表
|
||||
*/
|
||||
List<TaskTemplate> findAll();
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.example.demo.repository.impl;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
import com.example.demo.repository.EventRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 事件仓储内存实现。
|
||||
* <p>
|
||||
* 使用 ConcurrentHashMap 模拟数据库存储,应用启动时初始化示例数据。
|
||||
* 后续可替换为 MyBatis/JPA 等数据库实现。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="事件存储与状态管理", id="SRS-EHTG-03")
|
||||
* 将处理后的事件存入内存存储,并维护其生命周期状态。
|
||||
*/
|
||||
@Repository
|
||||
public class InMemoryEventRepository implements EventRepository {
|
||||
|
||||
private final ConcurrentHashMap<String, Event> store = new ConcurrentHashMap<>();
|
||||
private final AtomicLong idCounter = new AtomicLong(0);
|
||||
|
||||
public InMemoryEventRepository() {
|
||||
initSampleData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化示例事件数据。
|
||||
*/
|
||||
private void initSampleData() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
save(new Event("EVT-001", com.example.demo.model.enums.EventSourceType.RADAR,
|
||||
now.minusMinutes(30), "{\"lng\": 116.397, \"lat\": 39.908}", 0.95,
|
||||
EventStatus.PENDING, com.example.demo.model.enums.ThreatLevel.HIGH, "临机"));
|
||||
|
||||
save(new Event("EVT-002", com.example.demo.model.enums.EventSourceType.OPTOELECTRONIC,
|
||||
now.minusMinutes(20), "{\"lng\": 121.473, \"lat\": 31.230}", 0.87,
|
||||
EventStatus.PENDING, com.example.demo.model.enums.ThreatLevel.CRITICAL, "临机"));
|
||||
|
||||
save(new Event("EVT-003", com.example.demo.model.enums.EventSourceType.RADAR,
|
||||
now.minusMinutes(15), "{\"lng\": 113.264, \"lat\": 23.129}", 0.72,
|
||||
EventStatus.COMPLETED, com.example.demo.model.enums.ThreatLevel.MEDIUM, "规划"));
|
||||
|
||||
save(new Event("EVT-004", com.example.demo.model.enums.EventSourceType.ELECTRONIC_RECON,
|
||||
now.minusMinutes(10), "{\"lng\": 114.057, \"lat\": 22.543}", 0.65,
|
||||
EventStatus.PENDING, com.example.demo.model.enums.ThreatLevel.LOW, "规划"));
|
||||
|
||||
save(new Event("EVT-005", com.example.demo.model.enums.EventSourceType.COMMUNICATION_INTEL,
|
||||
now.minusMinutes(5), "{\"lng\": 120.155, \"lat\": 30.274}", 0.91,
|
||||
EventStatus.PROCESSING, com.example.demo.model.enums.ThreatLevel.HIGH, "临机"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event save(Event event) {
|
||||
if (event.getEventId() == null || event.getEventId().isEmpty()) {
|
||||
String id = "EVT-" + String.format("%03d", idCounter.incrementAndGet());
|
||||
event.setEventId(id);
|
||||
}
|
||||
event.setUpdateTime(LocalDateTime.now());
|
||||
if (event.getCreateTime() == null) {
|
||||
event.setCreateTime(LocalDateTime.now());
|
||||
}
|
||||
store.put(event.getEventId(), event);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Event> findById(String eventId) {
|
||||
return Optional.ofNullable(store.get(eventId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Event> findAll() {
|
||||
return new ArrayList<>(store.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Event> findByStatus(EventStatus status) {
|
||||
return store.values().stream()
|
||||
.filter(e -> e.getStatus() == status)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Event> updateStatus(String eventId, EventStatus status) {
|
||||
return Optional.ofNullable(store.computeIfPresent(eventId, (id, event) -> {
|
||||
event.setStatus(status);
|
||||
event.setUpdateTime(LocalDateTime.now());
|
||||
return event;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(String eventId) {
|
||||
store.remove(eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return store.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package com.example.demo.repository.impl;
|
||||
|
||||
import com.example.demo.model.TaskScheme;
|
||||
import com.example.demo.model.enums.SchemeStatus;
|
||||
import com.example.demo.repository.SchemeRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务方案仓储内存实现。
|
||||
* <p>
|
||||
* 使用 ConcurrentHashMap 模拟数据库存储,应用启动时初始化示例方案数据。
|
||||
* 后续可替换为 MyBatis/JPA 等数据库实现。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="集中式/分布式方案列表展示", id="SRS-TMS-01")
|
||||
* 以表格或卡片形式展示所有可用任务方案,支持分页加载。
|
||||
*/
|
||||
@Repository
|
||||
public class InMemorySchemeRepository implements SchemeRepository {
|
||||
|
||||
private final ConcurrentHashMap<String, TaskScheme> store = new ConcurrentHashMap<>();
|
||||
private final AtomicLong idCounter = new AtomicLong(0);
|
||||
|
||||
public InMemorySchemeRepository() {
|
||||
initSampleData();
|
||||
}
|
||||
|
||||
private void initSampleData() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
TaskScheme s1 = new TaskScheme("SCH-001", "联合打击方案-A", "集中式",
|
||||
SchemeStatus.EXECUTING, 8, 120, 0.15, 0.92);
|
||||
s1.setEventId("EVT-001");
|
||||
s1.setDraftId("DRF-001");
|
||||
s1.setDeploymentDetail("{\"air\":\"歼-20 4架\",\"ground\":\"火箭炮 2个连\",\"naval\":\"驱逐舰 1艘\"}");
|
||||
s1.setRouteDetail("[{\"phase\":\"集结\",\"coord\":\"A(30.5,120.3)\"},{\"phase\":\"突击\",\"coord\":\"B(31.2,121.5)\"}]");
|
||||
s1.setTimelineDetail("{\"T+0\":\"集结\",\"T+30min\":\"突击\",\"T+60min\":\"评估\"}");
|
||||
s1.setAlgorithmTrace("路径规划采用A*算法优化,约束满足率98.5%,冲突消解2次");
|
||||
s1.setExecutionProgress(45);
|
||||
s1.setSubTaskStatus("[{\"name\":\"空中侦察\",\"progress\":80,\"status\":\"进行中\"},{\"name\":\"地面打击\",\"progress\":20,\"status\":\"进行中\"}]");
|
||||
s1.setCreateTime(now.minusHours(2));
|
||||
s1.setUpdateTime(now.minusMinutes(30));
|
||||
store.put(s1.getSchemeId(), s1);
|
||||
|
||||
TaskScheme s2 = new TaskScheme("SCH-002", "分布式机动方案-B", "分布式",
|
||||
SchemeStatus.PENDING_DISPATCH, 6, 90, 0.22, 0.85);
|
||||
s2.setEventId("EVT-002");
|
||||
s2.setDeploymentDetail("{\"air\":\"无人机 6架\",\"ground\":\"特种作战分队 1个\"}");
|
||||
s2.setRouteDetail("[{\"phase\":\"渗透\",\"coord\":\"C(121.0,30.8)\"},{\"phase\":\"打击\",\"coord\":\"D(121.5,31.2)\"}]");
|
||||
s2.setTimelineDetail("{\"T+0\":\"渗透\",\"T+45min\":\"打击\",\"T+80min\":\"撤离\"}");
|
||||
s2.setAlgorithmTrace("分布式优化采用遗传算法,种群规模500,迭代100次");
|
||||
s2.setExecutionProgress(0);
|
||||
s2.setCreateTime(now.minusHours(1));
|
||||
s2.setUpdateTime(now.minusMinutes(10));
|
||||
store.put(s2.getSchemeId(), s2);
|
||||
|
||||
TaskScheme s3 = new TaskScheme("SCH-003", "区域防御方案-C", "集中式",
|
||||
SchemeStatus.COMPLETED, 5, 180, 0.08, 0.96);
|
||||
s3.setEventId("EVT-003");
|
||||
s3.setDeploymentDetail("{\"air\":\"防空导弹 4个营\",\"ground\":\"雷达站 3座\"}");
|
||||
s3.setRouteDetail("[]");
|
||||
s3.setTimelineDetail("{\"T+0\":\"部署\",\"T+60min\":\"警戒\",\"T+180min\":\"撤防\"}");
|
||||
s3.setAlgorithmTrace("区域防御覆盖优化,最大覆盖半径300km,重叠率<5%");
|
||||
s3.setExecutionProgress(100);
|
||||
s3.setSubTaskStatus("[{\"name\":\"防空部署\",\"progress\":100,\"status\":\"已完成\"}]");
|
||||
s3.setCreateTime(now.minusDays(1));
|
||||
s3.setUpdateTime(now.minusHours(5));
|
||||
store.put(s3.getSchemeId(), s3);
|
||||
|
||||
TaskScheme s4 = new TaskScheme("SCH-004", "电子战压制方案-D", "分布式",
|
||||
SchemeStatus.ABORTED, 7, 60, 0.18, 0.78);
|
||||
s4.setEventId("EVT-004");
|
||||
s4.setDeploymentDetail("{\"electronic\":\"电子战飞机 2架\",\"ground\":\"干扰站 2个\"}");
|
||||
s4.setRouteDetail("[{\"phase\":\"抵近\",\"coord\":\"E(119.5,29.3)\"}]");
|
||||
s4.setTimelineDetail("{\"T+0\":\"抵近\",\"T+30min\":\"压制\"}");
|
||||
s4.setAlgorithmTrace("电子频谱分配算法,冲突率0%,但目标移动导致方案中止");
|
||||
s4.setExecutionProgress(30);
|
||||
s4.setSubTaskStatus("[{\"name\":\"电子侦察\",\"progress\":100,\"status\":\"已完成\"},{\"name\":\"干扰压制\",\"progress\":0,\"status\":\"已中止\"}]");
|
||||
s4.setCreateTime(now.minusHours(6));
|
||||
s4.setUpdateTime(now.minusHours(3));
|
||||
store.put(s4.getSchemeId(), s4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskScheme save(TaskScheme scheme) {
|
||||
if (scheme.getSchemeId() == null || scheme.getSchemeId().isEmpty()) {
|
||||
String id = "SCH-" + String.format("%03d", idCounter.incrementAndGet());
|
||||
scheme.setSchemeId(id);
|
||||
}
|
||||
scheme.setUpdateTime(LocalDateTime.now());
|
||||
if (scheme.getCreateTime() == null) {
|
||||
scheme.setCreateTime(LocalDateTime.now());
|
||||
}
|
||||
store.put(scheme.getSchemeId(), scheme);
|
||||
return scheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskScheme> findById(String schemeId) {
|
||||
return Optional.ofNullable(store.get(schemeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskScheme> findAll() {
|
||||
return new ArrayList<>(store.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskScheme> findByStatus(SchemeStatus status) {
|
||||
return store.values().stream()
|
||||
.filter(s -> s.getStatus() == status)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskScheme> findByEventId(String eventId) {
|
||||
return store.values().stream()
|
||||
.filter(s -> eventId.equals(s.getEventId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskScheme> updateStatus(String schemeId, SchemeStatus status) {
|
||||
return Optional.ofNullable(store.computeIfPresent(schemeId, (id, scheme) -> {
|
||||
scheme.setStatus(status);
|
||||
scheme.setUpdateTime(LocalDateTime.now());
|
||||
return scheme;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskScheme> updateProgress(String schemeId, int progress) {
|
||||
return Optional.ofNullable(store.computeIfPresent(schemeId, (id, scheme) -> {
|
||||
scheme.setExecutionProgress(progress);
|
||||
scheme.setUpdateTime(LocalDateTime.now());
|
||||
return scheme;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(String schemeId) {
|
||||
store.remove(schemeId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.example.demo.repository.impl;
|
||||
|
||||
import com.example.demo.model.TaskDraft;
|
||||
import com.example.demo.repository.TaskDraftRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务草案仓储内存实现。
|
||||
* <p>
|
||||
* 使用 ConcurrentHashMap 模拟数据库存储。
|
||||
* 后续可替换为 MyBatis/JPA 等数据库实现。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="任务草案发送与重试机制", id="SRS-EHTG-07")
|
||||
* 向下游任务规划引擎发送请求,失败时自动加入本地重试队列。
|
||||
*/
|
||||
@Repository
|
||||
public class InMemoryTaskDraftRepository implements TaskDraftRepository {
|
||||
|
||||
private final ConcurrentHashMap<String, TaskDraft> store = new ConcurrentHashMap<>();
|
||||
private final AtomicLong idCounter = new AtomicLong(0);
|
||||
|
||||
@Override
|
||||
public TaskDraft save(TaskDraft draft) {
|
||||
if (draft.getDraftId() == null || draft.getDraftId().isEmpty()) {
|
||||
String id = "DRF-" + String.format("%03d", idCounter.incrementAndGet());
|
||||
draft.setDraftId(id);
|
||||
}
|
||||
if (draft.getCreateTime() == null) {
|
||||
draft.setCreateTime(LocalDateTime.now());
|
||||
}
|
||||
store.put(draft.getDraftId(), draft);
|
||||
return draft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskDraft> findById(String draftId) {
|
||||
return Optional.ofNullable(store.get(draftId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskDraft> findByEventId(String eventId) {
|
||||
return store.values().stream()
|
||||
.filter(d -> eventId.equals(d.getEventId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskDraft> findAll() {
|
||||
return new ArrayList<>(store.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskDraft> findAllFailed() {
|
||||
return store.values().stream()
|
||||
.filter(d -> d.getSendStatus() == 2)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskDraft> updateSendStatus(String draftId, int sendStatus, int retryCount) {
|
||||
return Optional.ofNullable(store.computeIfPresent(draftId, (id, draft) -> {
|
||||
draft.setSendStatus(sendStatus);
|
||||
draft.setRetryCount(retryCount);
|
||||
draft.setLastSendTime(LocalDateTime.now());
|
||||
return draft;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.example.demo.repository.impl;
|
||||
|
||||
import com.example.demo.model.TaskTemplate;
|
||||
import com.example.demo.repository.TaskTemplateRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务模板仓储内存实现。
|
||||
* <p>
|
||||
* 使用 ConcurrentHashMap 模拟数据库存储,应用启动时初始化示例模板数据。
|
||||
* 后续可替换为 MyBatis/JPA 等数据库实现。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="任务模板匹配与生成", id="SRS-EHTG-06")
|
||||
* 结合知识库中的任务模板,自动生成符合标准的任务草案。
|
||||
*/
|
||||
@Repository
|
||||
public class InMemoryTaskTemplateRepository implements TaskTemplateRepository {
|
||||
|
||||
private final ConcurrentHashMap<String, TaskTemplate> store = new ConcurrentHashMap<>();
|
||||
|
||||
public InMemoryTaskTemplateRepository() {
|
||||
initSampleData();
|
||||
}
|
||||
|
||||
private void initSampleData() {
|
||||
save(new TaskTemplate("TPL-001", 1,
|
||||
"<task><type>侦察打击</type><phase>侦察</phase><action>高空侦察</action><target>固定目标</target></task>",
|
||||
"V1.0", true, "高空侦察打击模板", "适用于固定目标的侦察与精确打击"));
|
||||
|
||||
save(new TaskTemplate("TPL-002", 2,
|
||||
"<task><type>电子干扰</type><phase>压制</phase><action>雷达干扰</action><target>移动目标</target></task>",
|
||||
"V1.0", true, "电子干扰压制模板", "适用于移动目标的电子干扰与压制"));
|
||||
|
||||
save(new TaskTemplate("TPL-003", 3,
|
||||
"<task><type>联合打击</type><phase>协同</phase><action>多兵种协同打击</action><target>高价值目标</target></task>",
|
||||
"V2.0", true, "多兵种联合打击模板", "适用于高价值目标的联合打击行动"));
|
||||
|
||||
save(new TaskTemplate("TPL-004", 1,
|
||||
"<task><type>侦察</type><phase>监视</phase><action>低空监视</action><target>区域监控</target></task>",
|
||||
"V1.5", false, "低空区域监控模板", "已停用,适用于区域监视"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskTemplate save(TaskTemplate template) {
|
||||
store.put(template.getTemplateId(), template);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TaskTemplate> findById(String templateId) {
|
||||
return Optional.ofNullable(store.get(templateId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskTemplate> findAllActive() {
|
||||
return store.values().stream()
|
||||
.filter(TaskTemplate::isActive)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskTemplate> findByTargetType(int targetType) {
|
||||
return store.values().stream()
|
||||
.filter(t -> t.getTargetType() == targetType && t.isActive())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskTemplate> findAll() {
|
||||
return new ArrayList<>(store.values());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.dto.EventDTO;
|
||||
import com.example.demo.model.dto.EventQueryDTO;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
import com.example.demo.repository.EventRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 事件处理服务。
|
||||
* <p>
|
||||
* 实现事件的接收、清洗、标准化、存储与状态管理等核心业务逻辑。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="事件接收与解析", id="SRS-EHTG-01")
|
||||
* 监听上游消息队列,接收原始事件数据包并进行格式校验。
|
||||
*
|
||||
* @requirement(name="数据清洗与标准化", id="SRS-EHTG-02")
|
||||
* 对原始事件进行去重、过滤、字段补全和结构化转换。
|
||||
*
|
||||
* @requirement(name="事件存储与状态管理", id="SRS-EHTG-03")
|
||||
* 将处理后的事件存入数据库,并维护其生命周期状态。
|
||||
*
|
||||
* @requirement(name="高价值目标评估", id="SRS-EHTG-05")
|
||||
* 基于威胁等级、置信度等指标计算目标价值,判定是否触发任务生成。
|
||||
*/
|
||||
@Service
|
||||
public class EventService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EventService.class);
|
||||
|
||||
private final EventRepository eventRepository;
|
||||
|
||||
public EventService(EventRepository eventRepository) {
|
||||
this.eventRepository = eventRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收并处理原始事件。
|
||||
* <p>
|
||||
* 执行数据清洗与标准化流程:
|
||||
* 1. 格式校验
|
||||
* 2. 字段补全
|
||||
* 3. 去重检查
|
||||
* 4. 结构化转换并存储
|
||||
* </p>
|
||||
*
|
||||
* @param rawEvent 原始事件数据
|
||||
* @return 处理后的事件
|
||||
*/
|
||||
public Event receiveEvent(Event rawEvent) {
|
||||
log.info("接收到原始事件,来源: {}, 时间: {}", rawEvent.getSourceType(), rawEvent.getOccurTime());
|
||||
|
||||
// 格式校验:置信度必须在0~1之间
|
||||
if (rawEvent.getConfidence() < 0 || rawEvent.getConfidence() > 1) {
|
||||
log.warn("事件置信度异常: {}, 已自动修正", rawEvent.getConfidence());
|
||||
rawEvent.setConfidence(Math.max(0, Math.min(1, rawEvent.getConfidence())));
|
||||
}
|
||||
|
||||
// 字段补全:如果状态为空,默认设置为待处理
|
||||
if (rawEvent.getStatus() == null) {
|
||||
rawEvent.setStatus(EventStatus.PENDING);
|
||||
}
|
||||
|
||||
// 去重检查(按事件ID)
|
||||
if (rawEvent.getEventId() != null && !rawEvent.getEventId().isEmpty()) {
|
||||
Optional<Event> existing = eventRepository.findById(rawEvent.getEventId());
|
||||
if (existing.isPresent()) {
|
||||
log.info("事件 {} 已存在,跳过重复接收", rawEvent.getEventId());
|
||||
return existing.get();
|
||||
}
|
||||
}
|
||||
|
||||
// 结构化转换并存储
|
||||
Event savedEvent = eventRepository.save(rawEvent);
|
||||
log.info("事件 {} 已清洗并存储", savedEvent.getEventId());
|
||||
|
||||
return savedEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 评估目标价值。
|
||||
* <p>
|
||||
* 基于威胁等级和置信度计算目标价值评分。
|
||||
* 评分公式:威胁等级值 × 置信度 × 100
|
||||
* 评分 > 200 视为高价值目标。
|
||||
* </p>
|
||||
*
|
||||
* @param event 事件
|
||||
* @return 目标价值评分(0~400)
|
||||
*/
|
||||
public double evaluateTargetValue(Event event) {
|
||||
double threatScore = event.getThreatLevel() != null ? event.getThreatLevel().getLevel() : 1;
|
||||
double confidence = event.getConfidence();
|
||||
double score = threatScore * confidence * 100;
|
||||
log.info("事件 {} 目标价值评估: 威胁={}, 置信度={}, 评分={}",
|
||||
event.getEventId(), threatScore, confidence, score);
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为高价值目标(评分 > 200)。
|
||||
*
|
||||
* @param score 目标价值评分
|
||||
* @return true 如果是高价值目标
|
||||
*/
|
||||
public boolean isHighValueTarget(double score) {
|
||||
return score > 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询事件列表,支持排序和过滤。
|
||||
*
|
||||
* @param query 查询参数
|
||||
* @return 事件列表
|
||||
*/
|
||||
public List<Event> queryEvents(EventQueryDTO query) {
|
||||
List<Event> events = new ArrayList<>(eventRepository.findAll());
|
||||
|
||||
// 状态过滤
|
||||
if (query.getStatusFilter() != null && !query.getStatusFilter().isEmpty()) {
|
||||
events = events.stream()
|
||||
.filter(e -> e.getStatus() != null &&
|
||||
e.getStatus().getDescription().contains(query.getStatusFilter()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 威胁等级过滤
|
||||
if (query.getThreatLevel() != null) {
|
||||
events = events.stream()
|
||||
.filter(e -> e.getThreatLevel() == query.getThreatLevel())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 排序
|
||||
String sortField = query.getSortField();
|
||||
String sortDir = query.getSortDirection();
|
||||
if (sortField != null && !sortField.isEmpty()) {
|
||||
Comparator<Event> comparator = getComparator(sortField);
|
||||
if (comparator != null) {
|
||||
if ("desc".equalsIgnoreCase(sortDir)) {
|
||||
events.sort(comparator.reversed());
|
||||
} else {
|
||||
events.sort(comparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
int page = Math.max(0, query.getPage());
|
||||
int size = Math.max(1, Math.min(100, query.getSize() > 0 ? query.getSize() : 20));
|
||||
int fromIndex = page * size;
|
||||
if (fromIndex >= events.size()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
int toIndex = Math.min(fromIndex + size, events.size());
|
||||
return events.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排序比较器。
|
||||
*/
|
||||
private Comparator<Event> getComparator(String sortField) {
|
||||
return switch (sortField) {
|
||||
case "createTime" -> Comparator.comparing(Event::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||
case "occurTime" -> Comparator.comparing(Event::getOccurTime, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||
case "threatLevel" -> Comparator.comparing(e -> e.getThreatLevel() != null ? e.getThreatLevel().getLevel() : 0);
|
||||
case "confidence" -> Comparator.comparing(Event::getConfidence);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询事件。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 事件
|
||||
*/
|
||||
public Optional<Event> getEventById(String eventId) {
|
||||
return eventRepository.findById(eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新事件状态。
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @param status 新状态
|
||||
* @return 更新后的事件
|
||||
*/
|
||||
public Optional<Event> updateEventStatus(String eventId, EventStatus status) {
|
||||
log.info("更新事件 {} 状态为 {}", eventId, status);
|
||||
return eventRepository.updateStatus(eventId, status);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.TaskScheme;
|
||||
import com.example.demo.model.dto.SchemeCompareDTO;
|
||||
import com.example.demo.model.enums.SchemeStatus;
|
||||
import com.example.demo.repository.SchemeRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务方案管理服务。
|
||||
* <p>
|
||||
* 实现集中式/分布式任务方案的统一管理、对比、重构及执行监控能力。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="集中式/分布式方案列表展示", id="SRS-TMS-01")
|
||||
* 以表格或卡片形式展示所有可用任务方案,支持分页加载。
|
||||
*
|
||||
* @requirement(name="自定义排序功能", id="SRS-TMS-02")
|
||||
* 按生成时间、优先级、成功率等字段升序/降序排列。
|
||||
*
|
||||
* @requirement(name="方案详情查看", id="SRS-TMS-03")
|
||||
* 展示兵力部署、行动路线、时间节点等详细信息。
|
||||
*
|
||||
* @requirement(name="多方案对比分析", id="SRS-TMS-04")
|
||||
* 支持最多5个方案的关键指标并列比较。
|
||||
*
|
||||
* @requirement(name="方案重构操作", id="SRS-TMS-06")
|
||||
* 基于新约束条件重新生成或调整现有方案。
|
||||
*
|
||||
* @requirement(name="方案分发驱动", id="SRS-TMS-08")
|
||||
* 将选定方案解析为指令集,下发至指定执行节点。
|
||||
*
|
||||
* @requirement(name="执行状态监控", id="SRS-TMS-10")
|
||||
* 实时聚合子任务进度,展示整体完成率与当前状态。
|
||||
*/
|
||||
@Service
|
||||
public class SchemeService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SchemeService.class);
|
||||
|
||||
private final SchemeRepository schemeRepository;
|
||||
|
||||
public SchemeService(SchemeRepository schemeRepository) {
|
||||
this.schemeRepository = schemeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务方案列表,支持排序和分页。
|
||||
*
|
||||
* @param sortField 排序字段(createTime / priority / successRate / estimatedDuration / estimatedLossRatio)
|
||||
* @param sortDirection 排序方向(asc / desc)
|
||||
* @param page 页码
|
||||
* @param size 每页条数
|
||||
* @return 方案列表
|
||||
*/
|
||||
public List<TaskScheme> listSchemes(String sortField, String sortDirection, int page, int size) {
|
||||
List<TaskScheme> schemes = new ArrayList<>(schemeRepository.findAll());
|
||||
|
||||
// 排序
|
||||
if (sortField != null && !sortField.isEmpty()) {
|
||||
Comparator<TaskScheme> comparator = getComparator(sortField);
|
||||
if (comparator != null) {
|
||||
if ("desc".equalsIgnoreCase(sortDirection)) {
|
||||
schemes.sort(comparator.reversed());
|
||||
} else {
|
||||
schemes.sort(comparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
int fromIndex = Math.max(0, page * size);
|
||||
if (fromIndex >= schemes.size()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
int toIndex = Math.min(fromIndex + size, schemes.size());
|
||||
return schemes.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排序比较器。
|
||||
*/
|
||||
private Comparator<TaskScheme> getComparator(String sortField) {
|
||||
return switch (sortField) {
|
||||
case "createTime" -> Comparator.comparing(TaskScheme::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||
case "priority" -> Comparator.comparingInt(TaskScheme::getPriority);
|
||||
case "successRate" -> Comparator.comparingDouble(TaskScheme::getSuccessRate);
|
||||
case "estimatedDuration" -> Comparator.comparingInt(TaskScheme::getEstimatedDuration);
|
||||
case "estimatedLossRatio" -> Comparator.comparingDouble(TaskScheme::getEstimatedLossRatio);
|
||||
default -> Comparator.comparing(TaskScheme::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询方案详情。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @return 方案
|
||||
*/
|
||||
public Optional<TaskScheme> getSchemeDetail(String schemeId) {
|
||||
return schemeRepository.findById(schemeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 多方案对比分析。
|
||||
* <p>
|
||||
* 最多支持5个方案的关键指标并列比较。
|
||||
* </p>
|
||||
*
|
||||
* @param compareDTO 对比参数
|
||||
* @return 对比结果Map
|
||||
*/
|
||||
public Map<String, Object> compareSchemes(SchemeCompareDTO compareDTO) {
|
||||
List<String> schemeIds = compareDTO.getSchemeIds();
|
||||
if (schemeIds == null || schemeIds.isEmpty()) {
|
||||
throw new IllegalArgumentException("至少需要一个方案进行对比");
|
||||
}
|
||||
if (schemeIds.size() > 5) {
|
||||
throw new IllegalArgumentException("最多支持5个方案对比");
|
||||
}
|
||||
|
||||
List<String> compareFields = compareDTO.getCompareFields();
|
||||
if (compareFields == null || compareFields.isEmpty()) {
|
||||
compareFields = Arrays.asList("estimatedDuration", "estimatedLossRatio", "successRate", "priority");
|
||||
}
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("compareFields", compareFields);
|
||||
|
||||
List<Map<String, Object>> schemeComparisons = new ArrayList<>();
|
||||
for (String schemeId : schemeIds) {
|
||||
Optional<TaskScheme> schemeOpt = schemeRepository.findById(schemeId);
|
||||
if (schemeOpt.isPresent()) {
|
||||
TaskScheme scheme = schemeOpt.get();
|
||||
Map<String, Object> schemeData = new LinkedHashMap<>();
|
||||
schemeData.put("schemeId", scheme.getSchemeId());
|
||||
schemeData.put("schemeName", scheme.getSchemeName());
|
||||
schemeData.put("schemeType", scheme.getSchemeType());
|
||||
schemeData.put("status", scheme.getStatus());
|
||||
|
||||
for (String field : compareFields) {
|
||||
Object value = getFieldValue(scheme, field);
|
||||
schemeData.put(field, value);
|
||||
}
|
||||
schemeComparisons.add(schemeData);
|
||||
}
|
||||
}
|
||||
result.put("schemes", schemeComparisons);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取方案字段值。
|
||||
*/
|
||||
private Object getFieldValue(TaskScheme scheme, String field) {
|
||||
return switch (field) {
|
||||
case "estimatedDuration" -> scheme.getEstimatedDuration();
|
||||
case "estimatedLossRatio" -> scheme.getEstimatedLossRatio();
|
||||
case "successRate" -> scheme.getSuccessRate();
|
||||
case "priority" -> scheme.getPriority();
|
||||
case "executionProgress" -> scheme.getExecutionProgress();
|
||||
case "version" -> scheme.getVersion();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 方案重构。
|
||||
* <p>
|
||||
* 基于新约束条件重新生成方案,保留与旧版本的关联。
|
||||
* </p>
|
||||
*
|
||||
* @param schemeId 原方案ID
|
||||
* @param newConstraints 新约束条件(JSON格式)
|
||||
* @return 重构后的新方案
|
||||
*/
|
||||
public TaskScheme reconstructScheme(String schemeId, String newConstraints) {
|
||||
TaskScheme original = schemeRepository.findById(schemeId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));
|
||||
|
||||
log.info("开始重构方案 {},新约束: {}", schemeId, newConstraints);
|
||||
|
||||
// 创建新方案(基于原方案调整)
|
||||
TaskScheme newScheme = new TaskScheme();
|
||||
newScheme.setSchemeName(original.getSchemeName() + " (重构版)");
|
||||
newScheme.setSchemeType(original.getSchemeType());
|
||||
newScheme.setEventId(original.getEventId());
|
||||
newScheme.setDraftId(original.getDraftId());
|
||||
newScheme.setStatus(SchemeStatus.PENDING_DISPATCH);
|
||||
newScheme.setPriority(original.getPriority());
|
||||
newScheme.setEstimatedDuration(original.getEstimatedDuration());
|
||||
newScheme.setEstimatedLossRatio(original.getEstimatedLossRatio());
|
||||
newScheme.setSuccessRate(original.getSuccessRate());
|
||||
newScheme.setDeploymentDetail(original.getDeploymentDetail());
|
||||
newScheme.setRouteDetail(original.getRouteDetail());
|
||||
newScheme.setTimelineDetail(original.getTimelineDetail());
|
||||
newScheme.setAlgorithmTrace("基于原方案 " + schemeId + " 重构,新约束: " + newConstraints);
|
||||
newScheme.setParentSchemeId(schemeId);
|
||||
newScheme.setVersion(original.getVersion() + 1);
|
||||
newScheme.setExecutionProgress(0);
|
||||
newScheme.setCreateTime(LocalDateTime.now());
|
||||
newScheme.setUpdateTime(LocalDateTime.now());
|
||||
|
||||
TaskScheme saved = schemeRepository.save(newScheme);
|
||||
log.info("方案重构完成,新方案ID: {}", saved.getSchemeId());
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 方案分发。
|
||||
* <p>
|
||||
* 将选定方案解析为指令集并下发至指定执行节点。
|
||||
* </p>
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @param targetNode 目标执行节点
|
||||
* @return 分发结果
|
||||
*/
|
||||
public Map<String, Object> dispatchScheme(String schemeId, String targetNode) {
|
||||
TaskScheme scheme = schemeRepository.findById(schemeId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));
|
||||
|
||||
log.info("分发方案 {} 至执行节点: {}", schemeId, targetNode);
|
||||
|
||||
// 更新方案状态为"分发中"
|
||||
schemeRepository.updateStatus(schemeId, SchemeStatus.DISPATCHING);
|
||||
|
||||
// 构建分发指令集
|
||||
Map<String, Object> dispatchResult = new LinkedHashMap<>();
|
||||
dispatchResult.put("schemeId", schemeId);
|
||||
dispatchResult.put("schemeName", scheme.getSchemeName());
|
||||
dispatchResult.put("targetNode", targetNode);
|
||||
dispatchResult.put("dispatchTime", LocalDateTime.now().toString());
|
||||
dispatchResult.put("status", "已下发");
|
||||
dispatchResult.put("instructions", buildInstructions(scheme));
|
||||
|
||||
// 模拟下发成功,更新状态为"执行中"
|
||||
schemeRepository.updateStatus(schemeId, SchemeStatus.EXECUTING);
|
||||
log.info("方案 {} 已成功分发给节点 {}", schemeId, targetNode);
|
||||
|
||||
return dispatchResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建指令集。
|
||||
*/
|
||||
private List<Map<String, String>> buildInstructions(TaskScheme scheme) {
|
||||
List<Map<String, String>> instructions = new ArrayList<>();
|
||||
|
||||
Map<String, String> cmd1 = new LinkedHashMap<>();
|
||||
cmd1.put("command", "DEPLOY");
|
||||
cmd1.put("target", scheme.getDeploymentDetail() != null ? "兵力部署" : "未知");
|
||||
cmd1.put("detail", scheme.getDeploymentDetail() != null ? scheme.getDeploymentDetail() : "{}");
|
||||
instructions.add(cmd1);
|
||||
|
||||
Map<String, String> cmd2 = new LinkedHashMap<>();
|
||||
cmd2.put("command", "MOVE");
|
||||
cmd2.put("target", "行动路线");
|
||||
cmd2.put("detail", scheme.getRouteDetail() != null ? scheme.getRouteDetail() : "[]");
|
||||
instructions.add(cmd2);
|
||||
|
||||
Map<String, String> cmd3 = new LinkedHashMap<>();
|
||||
cmd3.put("command", "TIMELINE");
|
||||
cmd3.put("target", "时间节点");
|
||||
cmd3.put("detail", scheme.getTimelineDetail() != null ? scheme.getTimelineDetail() : "{}");
|
||||
instructions.add(cmd3);
|
||||
|
||||
return instructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询方案执行状态。
|
||||
*
|
||||
* @param schemeId 方案ID
|
||||
* @return 执行状态信息
|
||||
*/
|
||||
public Map<String, Object> getExecutionStatus(String schemeId) {
|
||||
TaskScheme scheme = schemeRepository.findById(schemeId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));
|
||||
|
||||
Map<String, Object> status = new LinkedHashMap<>();
|
||||
status.put("schemeId", scheme.getSchemeId());
|
||||
status.put("schemeName", scheme.getSchemeName());
|
||||
status.put("status", scheme.getStatus());
|
||||
status.put("executionProgress", scheme.getExecutionProgress());
|
||||
status.put("subTaskStatus", scheme.getSubTaskStatus());
|
||||
status.put("updateTime", scheme.getUpdateTime());
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.TaskDraft;
|
||||
import com.example.demo.model.TaskTemplate;
|
||||
import com.example.demo.repository.TaskDraftRepository;
|
||||
import com.example.demo.repository.TaskTemplateRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 任务生成服务。
|
||||
* <p>
|
||||
* 实现高价值目标评估后的任务模板匹配与任务草案生成逻辑,
|
||||
* 以及任务草案发送与重试机制。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="任务模板匹配与生成", id="SRS-EHTG-06")
|
||||
* 结合知识库中的任务模板,自动生成符合标准的任务草案。
|
||||
*
|
||||
* @requirement(name="任务草案发送与重试机制", id="SRS-EHTG-07")
|
||||
* 向下游任务规划引擎发送请求,失败时自动加入本地重试队列。
|
||||
*/
|
||||
@Service
|
||||
public class TaskGenerationService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TaskGenerationService.class);
|
||||
|
||||
private final TaskTemplateRepository templateRepository;
|
||||
private final TaskDraftRepository draftRepository;
|
||||
private final EventService eventService;
|
||||
|
||||
public TaskGenerationService(TaskTemplateRepository templateRepository,
|
||||
TaskDraftRepository draftRepository,
|
||||
EventService eventService) {
|
||||
this.templateRepository = templateRepository;
|
||||
this.draftRepository = draftRepository;
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于事件生成任务草案。
|
||||
* <p>
|
||||
* 执行流程:
|
||||
* 1. 评估目标价值
|
||||
* 2. 若为高价值目标,匹配任务模板
|
||||
* 3. 填充模板参数生成任务草案
|
||||
* 4. 保存草案并返回
|
||||
* </p>
|
||||
*
|
||||
* @param eventId 事件ID
|
||||
* @return 生成的任务草案
|
||||
* @throws IllegalArgumentException 如果事件不存在或不是高价值目标
|
||||
*/
|
||||
public TaskDraft generateTaskDraft(String eventId) {
|
||||
Event event = eventService.getEventById(eventId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("事件不存在: " + eventId));
|
||||
|
||||
// 评估目标价值
|
||||
double score = eventService.evaluateTargetValue(event);
|
||||
if (!eventService.isHighValueTarget(score)) {
|
||||
throw new IllegalArgumentException("事件 " + eventId + " 目标价值评分 " + score + ",未达到高价值目标阈值");
|
||||
}
|
||||
|
||||
// 匹配任务模板(按目标类型匹配)
|
||||
int targetType = event.getSourceType() != null ? event.getSourceType().getCode() : 1;
|
||||
List<TaskTemplate> templates = templateRepository.findByTargetType(targetType);
|
||||
if (templates.isEmpty()) {
|
||||
// 如果没有精确匹配的模板,使用所有启用的模板中的第一个
|
||||
templates = templateRepository.findAllActive();
|
||||
}
|
||||
if (templates.isEmpty()) {
|
||||
throw new IllegalStateException("没有可用的任务模板");
|
||||
}
|
||||
|
||||
// 选择第一个匹配的模板
|
||||
TaskTemplate template = templates.get(0);
|
||||
log.info("为事件 {} 匹配到模板: {} (版本 {})", eventId, template.getTemplateName(), template.getVersion());
|
||||
|
||||
// 生成任务草案内容
|
||||
String draftContent = generateDraftContent(event, template, score);
|
||||
|
||||
// 创建任务草案
|
||||
TaskDraft draft = new TaskDraft();
|
||||
draft.setDraftId("DRF-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase());
|
||||
draft.setEventId(eventId);
|
||||
draft.setTemplateId(template.getTemplateId());
|
||||
draft.setTitle(template.getTemplateName() + " - " + event.getEventId());
|
||||
draft.setContent(draftContent);
|
||||
draft.setTargetValueScore(score);
|
||||
draft.setSendStatus(0); // 未发送
|
||||
draft.setRetryCount(0);
|
||||
draft.setCreateTime(LocalDateTime.now());
|
||||
|
||||
TaskDraft savedDraft = draftRepository.save(draft);
|
||||
log.info("任务草案 {} 已生成", savedDraft.getDraftId());
|
||||
|
||||
// 更新事件状态为处理中
|
||||
eventService.updateEventStatus(eventId, com.example.demo.model.enums.EventStatus.PROCESSING);
|
||||
|
||||
return savedDraft;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成任务草案内容。
|
||||
* <p>
|
||||
* 根据事件信息和模板生成结构化的任务草案内容(JSON格式)。
|
||||
* </p>
|
||||
*/
|
||||
private String generateDraftContent(Event event, TaskTemplate template, double score) {
|
||||
return String.format("{" +
|
||||
"\"eventId\":\"%s\"," +
|
||||
"\"templateId\":\"%s\"," +
|
||||
"\"targetValueScore\":%.2f," +
|
||||
"\"threatLevel\":\"%s\"," +
|
||||
"\"confidence\":%.2f," +
|
||||
"\"location\":%s," +
|
||||
"\"templateContent\":%s" +
|
||||
"}",
|
||||
event.getEventId(),
|
||||
template.getTemplateId(),
|
||||
score,
|
||||
event.getThreatLevel() != null ? event.getThreatLevel().name() : "UNKNOWN",
|
||||
event.getConfidence(),
|
||||
event.getLocation() != null ? event.getLocation() : "\"\"",
|
||||
template.getContentXml() != null ? "\"" + template.getContentXml().replace("\"", "\\\"") + "\"" : "\"\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送任务草案到下游任务规划引擎。
|
||||
* <p>
|
||||
* 模拟发送过程:随机成功/失败,失败时记录重试。
|
||||
* 后续对接真实下游引擎时替换此方法。
|
||||
* </p>
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 发送是否成功
|
||||
*/
|
||||
public boolean sendTaskDraft(String draftId) {
|
||||
Optional<TaskDraft> draftOpt = draftRepository.findById(draftId);
|
||||
if (draftOpt.isEmpty()) {
|
||||
log.warn("任务草案 {} 不存在,无法发送", draftId);
|
||||
return false;
|
||||
}
|
||||
|
||||
TaskDraft draft = draftOpt.get();
|
||||
log.info("发送任务草案 {} 到下游任务规划引擎...", draftId);
|
||||
|
||||
try {
|
||||
// 模拟发送过程(当前阶段返回发送成功)
|
||||
boolean sendSuccess = simulateSendToEngine(draft);
|
||||
|
||||
if (sendSuccess) {
|
||||
draftRepository.updateSendStatus(draftId, 1, draft.getRetryCount());
|
||||
log.info("任务草案 {} 发送成功", draftId);
|
||||
|
||||
// 更新事件状态为已完成
|
||||
eventService.updateEventStatus(draft.getEventId(), com.example.demo.model.enums.EventStatus.COMPLETED);
|
||||
return true;
|
||||
} else {
|
||||
int newRetry = draft.getRetryCount() + 1;
|
||||
draftRepository.updateSendStatus(draftId, 2, newRetry);
|
||||
log.warn("任务草案 {} 发送失败,重试次数: {}", draftId, newRetry);
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int newRetry = draft.getRetryCount() + 1;
|
||||
draftRepository.updateSendStatus(draftId, 2, newRetry);
|
||||
log.error("任务草案 {} 发送异常: {}", draftId, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟向下游引擎发送消息。
|
||||
* <p>
|
||||
* 当前实现模拟成功,后续对接真实引擎时替换。
|
||||
* </p>
|
||||
*/
|
||||
private boolean simulateSendToEngine(TaskDraft draft) {
|
||||
// 模拟:前两次重试随机失败,之后成功
|
||||
if (draft.getRetryCount() < 2) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重试发送失败的任务草案。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 重试结果
|
||||
*/
|
||||
public boolean retrySendDraft(String draftId) {
|
||||
Optional<TaskDraft> draftOpt = draftRepository.findById(draftId);
|
||||
if (draftOpt.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
TaskDraft draft = draftOpt.get();
|
||||
if (draft.getSendStatus() != 2) {
|
||||
log.info("任务草案 {} 当前状态不是发送失败,无需重试", draftId);
|
||||
return false;
|
||||
}
|
||||
return sendTaskDraft(draftId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有发送失败的任务草案。
|
||||
*
|
||||
* @return 失败的草案列表
|
||||
*/
|
||||
public List<TaskDraft> getFailedDrafts() {
|
||||
return draftRepository.findAllFailed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务草案列表。
|
||||
*
|
||||
* @return 所有草案
|
||||
*/
|
||||
public List<TaskDraft> getAllDrafts() {
|
||||
return draftRepository.findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询任务草案。
|
||||
*
|
||||
* @param draftId 草案ID
|
||||
* @return 草案
|
||||
*/
|
||||
public Optional<TaskDraft> getDraftById(String draftId) {
|
||||
return draftRepository.findById(draftId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: battlefield-mission-system
|
||||
|
||||
# 当前阶段使用内存存储,未配置数据库
|
||||
# 后续扩展:取消注释下方配置并引入 spring-boot-starter-data-jpa 和 postgresql 依赖
|
||||
# datasource:
|
||||
# url: jdbc:postgresql://localhost:5432/battlefield
|
||||
# username: battlefield_user
|
||||
# password: ${DB_PASSWORD}
|
||||
# driver-class-name: org.postgresql.Driver
|
||||
# jpa:
|
||||
# hibernate:
|
||||
# ddl-auto: update
|
||||
# show-sql: true
|
||||
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: Asia/Shanghai
|
||||
serialization:
|
||||
write-dates-as-timestamps: false
|
||||
|
||||
# Knife4j 配置
|
||||
knife4j:
|
||||
enable: true
|
||||
setting:
|
||||
language: zh-CN
|
||||
enable-swagger-models: true
|
||||
enable-document-manage: true
|
||||
enable-reload-cache: false
|
||||
enable-footer: false
|
||||
enable-footer-custom: true
|
||||
footer-custom-content: 战场态势与任务规划系统 - 保密
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
com.example.demo: INFO
|
||||
org.springframework: WARN
|
||||
pattern:
|
||||
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.example.demo;
|
||||
|
||||
import com.example.demo.model.Event;
|
||||
import com.example.demo.model.enums.EventSourceType;
|
||||
import com.example.demo.model.enums.EventStatus;
|
||||
import com.example.demo.model.enums.ThreatLevel;
|
||||
import com.example.demo.service.EventService;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 事件服务单元测试。
|
||||
* <p>
|
||||
* 测试事件接收、清洗、目标价值评估等核心业务逻辑。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="事件接收与解析", id="SRS-EHTG-01")
|
||||
* @requirement(name="数据清洗与标准化", id="SRS-EHTG-02")
|
||||
* @requirement(name="高价值目标评估", id="SRS-EHTG-05")
|
||||
*/
|
||||
@SpringBootTest
|
||||
class EventServiceTest {
|
||||
|
||||
@Autowired
|
||||
private EventService eventService;
|
||||
|
||||
@Test
|
||||
@DisplayName("测试接收事件 - 正常流程")
|
||||
void testReceiveEvent() {
|
||||
Event event = new Event();
|
||||
event.setSourceType(EventSourceType.RADAR);
|
||||
event.setOccurTime(LocalDateTime.now());
|
||||
event.setLocation("{\"lng\": 116.397, \"lat\": 39.908}");
|
||||
event.setConfidence(0.95);
|
||||
event.setThreatLevel(ThreatLevel.HIGH);
|
||||
event.setEventType("临机");
|
||||
|
||||
Event saved = eventService.receiveEvent(event);
|
||||
|
||||
assertNotNull(saved);
|
||||
assertNotNull(saved.getEventId());
|
||||
assertEquals(EventStatus.PENDING, saved.getStatus());
|
||||
assertNotNull(saved.getCreateTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试接收事件 - 置信度修正")
|
||||
void testReceiveEventWithInvalidConfidence() {
|
||||
Event event = new Event();
|
||||
event.setSourceType(EventSourceType.OPTOELECTRONIC);
|
||||
event.setOccurTime(LocalDateTime.now());
|
||||
event.setLocation("{\"lng\": 121.473, \"lat\": 31.230}");
|
||||
event.setConfidence(2.5); // 无效置信度
|
||||
event.setThreatLevel(ThreatLevel.CRITICAL);
|
||||
event.setEventType("临机");
|
||||
|
||||
Event saved = eventService.receiveEvent(event);
|
||||
assertEquals(1.0, saved.getConfidence(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试目标价值评估 - 高价值目标")
|
||||
void testEvaluateHighValueTarget() {
|
||||
Event event = new Event();
|
||||
event.setEventId("EVT-TEST-001");
|
||||
event.setThreatLevel(ThreatLevel.CRITICAL); // 等级4
|
||||
event.setConfidence(0.95);
|
||||
|
||||
double score = eventService.evaluateTargetValue(event);
|
||||
// 4 * 0.95 * 100 = 380
|
||||
assertEquals(380.0, score, 0.01);
|
||||
assertTrue(eventService.isHighValueTarget(score));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试目标价值评估 - 低价值目标")
|
||||
void testEvaluateLowValueTarget() {
|
||||
Event event = new Event();
|
||||
event.setEventId("EVT-TEST-002");
|
||||
event.setThreatLevel(ThreatLevel.LOW); // 等级1
|
||||
event.setConfidence(0.5);
|
||||
|
||||
double score = eventService.evaluateTargetValue(event);
|
||||
// 1 * 0.5 * 100 = 50
|
||||
assertEquals(50.0, score, 0.01);
|
||||
assertFalse(eventService.isHighValueTarget(score));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试查询事件 - 按ID查询")
|
||||
void testGetEventById() {
|
||||
Optional<Event> event = eventService.getEventById("EVT-001");
|
||||
assertTrue(event.isPresent());
|
||||
assertEquals("EVT-001", event.get().getEventId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试查询事件 - 不存在的ID")
|
||||
void testGetEventByIdNotFound() {
|
||||
Optional<Event> event = eventService.getEventById("NONEXISTENT");
|
||||
assertFalse(event.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试更新事件状态")
|
||||
void testUpdateEventStatus() {
|
||||
Optional<Event> updated = eventService.updateEventStatus("EVT-001", EventStatus.PROCESSING);
|
||||
assertTrue(updated.isPresent());
|
||||
assertEquals(EventStatus.PROCESSING, updated.get().getStatus());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package com.example.demo;
|
||||
|
||||
import com.example.demo.model.TaskScheme;
|
||||
import com.example.demo.model.dto.SchemeCompareDTO;
|
||||
import com.example.demo.service.SchemeService;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 任务方案管理服务单元测试。
|
||||
* <p>
|
||||
* 测试方案列表、详情、对比、重构、分发等核心业务逻辑。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="集中式/分布式方案列表展示", id="SRS-TMS-01")
|
||||
* @requirement(name="方案详情查看", id="SRS-TMS-03")
|
||||
* @requirement(name="多方案对比分析", id="SRS-TMS-04")
|
||||
* @requirement(name="方案重构操作", id="SRS-TMS-06")
|
||||
* @requirement(name="方案分发驱动", id="SRS-TMS-08")
|
||||
*/
|
||||
@SpringBootTest
|
||||
class SchemeServiceTest {
|
||||
|
||||
@Autowired
|
||||
private SchemeService schemeService;
|
||||
|
||||
@Test
|
||||
@DisplayName("测试查询方案列表")
|
||||
void testListSchemes() {
|
||||
List<TaskScheme> schemes = schemeService.listSchemes("createTime", "desc", 0, 10);
|
||||
assertNotNull(schemes);
|
||||
assertFalse(schemes.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试按优先级排序查询方案列表")
|
||||
void testListSchemesSortedByPriority() {
|
||||
List<TaskScheme> schemes = schemeService.listSchemes("priority", "desc", 0, 10);
|
||||
assertNotNull(schemes);
|
||||
if (schemes.size() >= 2) {
|
||||
assertTrue(schemes.get(0).getPriority() >= schemes.get(1).getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试查询方案详情")
|
||||
void testGetSchemeDetail() {
|
||||
Optional<TaskScheme> scheme = schemeService.getSchemeDetail("SCH-001");
|
||||
assertTrue(scheme.isPresent());
|
||||
assertEquals("SCH-001", scheme.get().getSchemeId());
|
||||
assertNotNull(scheme.get().getDeploymentDetail());
|
||||
assertNotNull(scheme.get().getRouteDetail());
|
||||
assertNotNull(scheme.get().getAlgorithmTrace());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试查询不存在的方案详情")
|
||||
void testGetSchemeDetailNotFound() {
|
||||
Optional<TaskScheme> scheme = schemeService.getSchemeDetail("NONEXISTENT");
|
||||
assertFalse(scheme.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试多方案对比分析")
|
||||
void testCompareSchemes() {
|
||||
SchemeCompareDTO dto = new SchemeCompareDTO();
|
||||
dto.setSchemeIds(Arrays.asList("SCH-001", "SCH-002", "SCH-003"));
|
||||
dto.setCompareFields(Arrays.asList("estimatedDuration", "estimatedLossRatio", "successRate", "priority"));
|
||||
|
||||
Map<String, Object> result = schemeService.compareSchemes(dto);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.containsKey("schemes"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试方案重构")
|
||||
void testReconstructScheme() {
|
||||
TaskScheme newScheme = schemeService.reconstructScheme("SCH-001", "{\"maxDuration\": 90}");
|
||||
assertNotNull(newScheme);
|
||||
assertNotNull(newScheme.getSchemeId());
|
||||
assertEquals("SCH-001", newScheme.getParentSchemeId());
|
||||
assertEquals(2, newScheme.getVersion()); // 原版本1,重构后版本2
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试方案分发")
|
||||
void testDispatchScheme() {
|
||||
Map<String, Object> result = schemeService.dispatchScheme("SCH-002", "NODE-A1");
|
||||
assertNotNull(result);
|
||||
assertEquals("SCH-002", result.get("schemeId"));
|
||||
assertNotNull(result.get("instructions"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.example.demo;
|
||||
|
||||
import com.example.demo.model.TaskDraft;
|
||||
import com.example.demo.service.TaskGenerationService;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 任务生成服务单元测试。
|
||||
* <p>
|
||||
* 测试任务草案生成、发送与重试机制。
|
||||
* </p>
|
||||
*
|
||||
* @requirement(name="任务模板匹配与生成", id="SRS-EHTG-06")
|
||||
* @requirement(name="任务草案发送与重试机制", id="SRS-EHTG-07")
|
||||
*/
|
||||
@SpringBootTest
|
||||
class TaskGenerationServiceTest {
|
||||
|
||||
@Autowired
|
||||
private TaskGenerationService taskGenerationService;
|
||||
|
||||
@Test
|
||||
@DisplayName("测试基于事件生成任务草案")
|
||||
void testGenerateTaskDraft() {
|
||||
// EVT-002 是 CRITICAL 威胁 + 高置信度,应能触发任务生成
|
||||
TaskDraft draft = taskGenerationService.generateTaskDraft("EVT-002");
|
||||
assertNotNull(draft);
|
||||
assertNotNull(draft.getDraftId());
|
||||
assertNotNull(draft.getTitle());
|
||||
assertTrue(draft.getTargetValueScore() > 200);
|
||||
assertEquals(0, draft.getSendStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试低价值事件不会生成任务草案")
|
||||
void testGenerateTaskDraftLowValue() {
|
||||
// EVT-004 是 LOW 威胁 + 低置信度,应无法触发任务生成
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
taskGenerationService.generateTaskDraft("EVT-004");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试发送任务草案")
|
||||
void testSendTaskDraft() {
|
||||
TaskDraft draft = taskGenerationService.generateTaskDraft("EVT-001");
|
||||
boolean result = taskGenerationService.sendTaskDraft(draft.getDraftId());
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("测试重试发送失败的任务草案")
|
||||
void testRetrySendDraft() {
|
||||
TaskDraft draft = taskGenerationService.generateTaskDraft("EVT-005");
|
||||
// 先发送
|
||||
taskGenerationService.sendTaskDraft(draft.getDraftId());
|
||||
// 对于已成功发送的草案,重试应返回 false(无需重试)
|
||||
boolean retryResult = taskGenerationService.retrySendDraft(draft.getDraftId());
|
||||
assertFalse(retryResult);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue