Compare commits
No commits in common. "dev" and "dev_529" have entirely different histories.
249
README.md
249
README.md
@ -1,249 +0,0 @@
|
||||
# cmvr-iot
|
||||
|
||||
cmvr-iot 是一个基于 Java 8 和 Spring Boot 2.5 的多模块后端工程,提供设备管理、边缘机器人控制、测试编排、巡检、TTS、AIMA、VI/TI 等业务能力。工程入口在 `cmvr-iot-admin`,其余模块按业务和基础能力拆分。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- Java 8
|
||||
- Spring Boot 2.5.15
|
||||
- Spring Security
|
||||
- MyBatis Plus / MyBatis Plus Join
|
||||
- MySQL / Redis
|
||||
- Druid
|
||||
- Quartz
|
||||
- Knife4j / Swagger
|
||||
- gRPC Java 1.58.0
|
||||
- Protobuf / protoc-maven-plugin
|
||||
- MinIO
|
||||
|
||||
## 模块说明
|
||||
|
||||
| 模块 | 说明 |
|
||||
| --- | --- |
|
||||
| `cmvr-iot-admin` | Web 启动模块,包含 REST Controller、启动类和运行配置 |
|
||||
| `cmvr-iot-framework` | Web、安全、配置、通用框架能力 |
|
||||
| `cmvr-iot-common` | 公共工具、通用响应、基础常量和通用能力 |
|
||||
| `cmvr-iot-system` | 系统管理、用户、角色、菜单、字典等基础业务 |
|
||||
| `cmvr-iot-quartz` | 定时任务模块 |
|
||||
| `cmvr-iot-generator` | 代码生成模块 |
|
||||
| `cmvr-iot-device` | 设备领域模型与设备相关能力 |
|
||||
| `cmvr-iot-test` | 测试任务、编排、执行实例等业务 |
|
||||
| `cmvr-iot-vi` | VI 相关业务 |
|
||||
| `cmvr-iot-ti` | TI 相关业务 |
|
||||
| `cmvr-iot-evaluation` | 评测相关业务 |
|
||||
| `cmvr-iot-inspection` | 巡检机器人、地图、任务、告警等业务 |
|
||||
| `cmvr-iot-aima` | AIMA 相关业务 |
|
||||
| `cmvr-iot-tts` | TTS 语音合成相关业务 |
|
||||
| `cmvr-iot-api` | API 聚合模块 |
|
||||
| `cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-lib` | gRPC proto 与生成代码模块 |
|
||||
| `cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client` | 边缘设备 gRPC 客户端、设备控制服务和请求 VO |
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
cmvr-iot
|
||||
├── cmvr-iot-admin # Spring Boot 启动模块
|
||||
├── cmvr-iot-common # 公共模块
|
||||
├── cmvr-iot-framework # 框架模块
|
||||
├── cmvr-iot-system # 系统管理模块
|
||||
├── cmvr-iot-device # 设备模块
|
||||
├── cmvr-iot-test # 测试业务模块
|
||||
├── cmvr-iot-api
|
||||
│ └── cmvr-iot-edge
|
||||
│ ├── cmvr-iot-grpc-lib # proto 与 gRPC 生成代码
|
||||
│ └── cmvr-iot-grpc-client # gRPC 客户端与边缘控制服务
|
||||
├── sql # 增量 SQL
|
||||
├── Dockerfile
|
||||
├── Jenkinsfile
|
||||
└── pom.xml # Maven 父工程
|
||||
```
|
||||
|
||||
## 环境要求
|
||||
|
||||
- JDK 1.8
|
||||
- Maven 3.6+
|
||||
- MySQL 5.7+/8.x
|
||||
- Redis
|
||||
- 可访问的 gRPC 机器人/边缘终端服务
|
||||
- 可选:MinIO、外部大模型/TTS/评测服务
|
||||
|
||||
注意:`application-*.yml` 中包含环境相关地址、账号和密钥配置。实际部署或本地开发时,应使用本机配置、环境变量或配置中心覆盖,不要直接复用生产/测试环境敏感配置。
|
||||
|
||||
## 配置文件
|
||||
|
||||
主配置文件位于:
|
||||
|
||||
```text
|
||||
cmvr-iot-admin/src/main/resources/application.yml
|
||||
```
|
||||
|
||||
环境配置文件位于:
|
||||
|
||||
```text
|
||||
cmvr-iot-admin/src/main/resources/application-dev.yml
|
||||
cmvr-iot-admin/src/main/resources/application-test.yml
|
||||
cmvr-iot-admin/src/main/resources/application-prod.yml
|
||||
```
|
||||
|
||||
当前 `application.yml` 默认激活:
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
profiles:
|
||||
active: test
|
||||
```
|
||||
|
||||
如需切换环境,可以修改 `spring.profiles.active`,或启动时指定:
|
||||
|
||||
```bash
|
||||
java -jar cmvr-iot-admin-dev.jar --spring.profiles.active=dev
|
||||
```
|
||||
|
||||
## 构建
|
||||
|
||||
在项目根目录执行:
|
||||
|
||||
```bash
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
只编译启动模块及其依赖:
|
||||
|
||||
```bash
|
||||
mvn -pl cmvr-iot-admin -am compile -DskipTests
|
||||
```
|
||||
|
||||
只重新生成并编译 gRPC 代码:
|
||||
|
||||
```bash
|
||||
mvn -pl cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-lib -am compile -DskipTests
|
||||
```
|
||||
|
||||
## 启动
|
||||
|
||||
启动类:
|
||||
|
||||
```text
|
||||
cmvr-iot-admin/src/main/java/com/cmvr/CmvrIotApplication.java
|
||||
```
|
||||
|
||||
IDE 中直接运行 `CmvrIotApplication` 即可。
|
||||
|
||||
打包后运行:
|
||||
|
||||
```bash
|
||||
java -jar cmvr-iot-admin/target/cmvr-iot-admin-dev.jar --spring.profiles.active=dev
|
||||
```
|
||||
|
||||
默认开发端口以当前 profile 配置为准,例如 `application-dev.yml` 中为:
|
||||
|
||||
```yaml
|
||||
server:
|
||||
port: 13080
|
||||
```
|
||||
|
||||
## 接口文档
|
||||
|
||||
项目集成 Knife4j / Swagger。服务启动后可访问:
|
||||
|
||||
```text
|
||||
http://localhost:13080/doc.html
|
||||
```
|
||||
|
||||
如果端口或上下文路径被 profile 覆盖,请以实际配置为准。
|
||||
|
||||
## 数据库脚本
|
||||
|
||||
增量脚本位于:
|
||||
|
||||
```text
|
||||
sql/
|
||||
```
|
||||
|
||||
当前包含:
|
||||
|
||||
- `aima_module.sql`
|
||||
- `inspection_module.sql`
|
||||
- `tts_corpus_module.sql`
|
||||
|
||||
初始化数据库时,需要结合目标环境的基础库结构和增量脚本执行。
|
||||
|
||||
## gRPC 与边缘设备
|
||||
|
||||
边缘设备相关代码集中在:
|
||||
|
||||
```text
|
||||
cmvr-iot-api/cmvr-iot-edge/
|
||||
```
|
||||
|
||||
proto 文件位于:
|
||||
|
||||
```text
|
||||
cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-lib/src/main/proto/
|
||||
```
|
||||
|
||||
gRPC 客户端服务位于:
|
||||
|
||||
```text
|
||||
cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client/src/main/java/com/cmvr/edge/client/
|
||||
```
|
||||
|
||||
边缘控制器位于:
|
||||
|
||||
```text
|
||||
cmvr-iot-admin/src/main/java/com/cmvr/web/controller/api/
|
||||
```
|
||||
|
||||
新增或修改 proto 后,执行 Maven compile 会触发 `protoc-maven-plugin` 生成 Java 和 gRPC Stub 代码。业务代码应复用现有 gRPC 客户端管理工具获取 Stub,避免在业务层重复创建底层 `ManagedChannel`。
|
||||
|
||||
## 实时语音对讲
|
||||
|
||||
当前实时语音对讲链路为:
|
||||
|
||||
```text
|
||||
浏览器 WebSocket Binary PCM <-> Java 后端 <-> gRPC 双向流 <-> 机器人终端
|
||||
```
|
||||
|
||||
约定音频格式:
|
||||
|
||||
- PCM_S16LE
|
||||
- 48000 Hz
|
||||
- 单声道
|
||||
- 16 bit
|
||||
- 10 ms 一帧
|
||||
- 960 bytes/帧
|
||||
|
||||
相关文件:
|
||||
|
||||
- WebSocket 控制器:`cmvr-iot-admin/src/main/java/com/cmvr/web/controller/api/WebRtcSignalingController.java`
|
||||
- 业务会话管理:`cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client/src/main/java/com/cmvr/edge/client/service/AudioService.java`
|
||||
- gRPC 音频适配:`cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client/src/main/java/com/cmvr/edge/client/adapter/RobotAudioGrpcAdapter.java`
|
||||
- proto:`cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-lib/src/main/proto/cmvr/api/robot_audio.proto`
|
||||
|
||||
说明:历史 WebRTC 相关类可能仍保留在源码中,但当前浏览器音频传输链路使用 WebSocket 二进制 PCM。
|
||||
|
||||
## 开发约定
|
||||
|
||||
- Controller 层只做参数接收、基础校验和响应封装。
|
||||
- POST 控制类接口优先使用单个 `@RequestBody VO` 承载完整请求参数。
|
||||
- GET 查询类接口可以使用 query 参数绑定 VO。
|
||||
- 不建议在同一个接口中同时声明通用 VO 和零散业务参数。
|
||||
- gRPC 调用统一通过现有客户端管理类获取 Stub。
|
||||
- proto 修改后必须重新编译并确认生成代码已更新。
|
||||
- 不要提交本地日志、崩溃 dump、临时音频文件和包含真实密钥的配置。
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
# 编译全部模块
|
||||
mvn clean compile -DskipTests
|
||||
|
||||
# 编译启动模块及依赖
|
||||
mvn -pl cmvr-iot-admin -am compile -DskipTests
|
||||
|
||||
# 打包
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 运行指定 profile
|
||||
java -jar cmvr-iot-admin/target/cmvr-iot-admin-dev.jar --spring.profiles.active=dev
|
||||
```
|
||||
@ -77,24 +77,6 @@
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-evaluation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 智能巡检-->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-inspection</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 爱玛电动车测试-->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-aima</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 智能座舱语音语料采集-->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-tts</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<env>dev</env>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.cmvr;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
@ -12,7 +11,6 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
* @author cmvr-iot
|
||||
*/
|
||||
@EnableScheduling
|
||||
@MapperScan("com.cmvr.**.mapper")
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
public class CmvrIotApplication
|
||||
{
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaAlarm;
|
||||
import com.cmvr.aima.service.IAimaAlarmService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/alarm")
|
||||
@Api(tags = "爱玛电动车--告警管理")
|
||||
public class AimaAlarmController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaAlarmService aimaAlarmService;
|
||||
|
||||
@ApiOperation("查询告警列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaAlarm aimaAlarm) {
|
||||
startPage();
|
||||
List<AimaAlarm> list = aimaAlarmService.selectAimaAlarmList(aimaAlarm);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出告警列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:export')")
|
||||
@Log(title = "告警管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaAlarm aimaAlarm) {
|
||||
List<AimaAlarm> list = aimaAlarmService.selectAimaAlarmList(aimaAlarm);
|
||||
ExcelUtil<AimaAlarm> util = new ExcelUtil<>(AimaAlarm.class);
|
||||
util.exportExcel(response, list, "告警数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取告警详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaAlarmService.selectAimaAlarmById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增告警")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:add')")
|
||||
@Log(title = "告警管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaAlarm aimaAlarm) {
|
||||
return toAjax(aimaAlarmService.insertAimaAlarm(aimaAlarm));
|
||||
}
|
||||
|
||||
@ApiOperation("修改告警")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:edit')")
|
||||
@Log(title = "告警管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaAlarm aimaAlarm) {
|
||||
return toAjax(aimaAlarmService.updateAimaAlarm(aimaAlarm));
|
||||
}
|
||||
|
||||
@ApiOperation("删除告警")
|
||||
@PreAuthorize("@ss.hasPermi('aima:alarm:remove')")
|
||||
@Log(title = "告警管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaAlarmService.deleteAimaAlarmByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaPhone;
|
||||
import com.cmvr.aima.service.IAimaPhoneService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 爱玛手机管理Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/aima/phone")
|
||||
@Api(tags = "爱玛电动车--手机管理")
|
||||
public class AimaPhoneController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IAimaPhoneService aimaPhoneService;
|
||||
|
||||
/**
|
||||
* 查询爱玛手机管理列表
|
||||
*/
|
||||
@ApiOperation("查询爱玛手机管理列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaPhone aimaPhone)
|
||||
{
|
||||
startPage();
|
||||
List<AimaPhone> list = aimaPhoneService.selectAimaPhoneList(aimaPhone);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出爱玛手机管理列表
|
||||
*/
|
||||
@ApiOperation("导出爱玛手机管理列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:export')")
|
||||
@Log(title = "爱玛手机管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaPhone aimaPhone)
|
||||
{
|
||||
List<AimaPhone> list = aimaPhoneService.selectAimaPhoneList(aimaPhone);
|
||||
ExcelUtil<AimaPhone> util = new ExcelUtil<>(AimaPhone.class);
|
||||
util.exportExcel(response, list, "爱玛手机管理数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取爱玛手机管理详细信息
|
||||
*/
|
||||
@ApiOperation("获取爱玛手机管理详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(aimaPhoneService.selectAimaPhoneById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增爱玛手机管理
|
||||
*/
|
||||
@ApiOperation("新增爱玛手机管理")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:add')")
|
||||
@Log(title = "爱玛手机管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaPhone aimaPhone)
|
||||
{
|
||||
return toAjax(aimaPhoneService.insertAimaPhone(aimaPhone));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改爱玛手机管理
|
||||
*/
|
||||
@ApiOperation("修改爱玛手机管理")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:edit')")
|
||||
@Log(title = "爱玛手机管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaPhone aimaPhone)
|
||||
{
|
||||
return toAjax(aimaPhoneService.updateAimaPhone(aimaPhone));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除爱玛手机管理
|
||||
*/
|
||||
@ApiOperation("删除爱玛手机管理")
|
||||
@PreAuthorize("@ss.hasPermi('aima:phone:remove')")
|
||||
@Log(title = "爱玛手机管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(aimaPhoneService.deleteAimaPhoneByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaTask;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskVo;
|
||||
import com.cmvr.aima.service.IAimaTaskService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/task")
|
||||
@Api(tags = "爱玛电动车--任务管理")
|
||||
public class AimaTaskController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaTaskService aimaTaskService;
|
||||
|
||||
@ApiOperation("查询任务列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaTask aimaTask) {
|
||||
startPage();
|
||||
List<AimaTaskVo> list = aimaTaskService.selectAimaTaskVoList(aimaTask);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出任务列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:export')")
|
||||
@Log(title = "任务管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaTask aimaTask) {
|
||||
List<AimaTaskVo> list = aimaTaskService.selectAimaTaskVoList(aimaTask);
|
||||
ExcelUtil<AimaTaskVo> util = new ExcelUtil<>(AimaTaskVo.class);
|
||||
util.exportExcel(response, list, "任务数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取任务详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaTaskService.selectAimaTaskById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增任务")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:add')")
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaTask aimaTask) {
|
||||
return toAjax(aimaTaskService.insertAimaTask(aimaTask));
|
||||
}
|
||||
|
||||
@ApiOperation("修改任务")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:edit')")
|
||||
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaTask aimaTask) {
|
||||
return toAjax(aimaTaskService.updateAimaTask(aimaTask));
|
||||
}
|
||||
|
||||
@ApiOperation("删除任务")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:remove')")
|
||||
@Log(title = "任务管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaTaskService.deleteAimaTaskByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定测试用例到任务
|
||||
*/
|
||||
@ApiOperation("绑定测试用例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:edit')")
|
||||
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/bindTestCases/{taskId}")
|
||||
public AjaxResult bindTestCases(@PathVariable("taskId") String taskId, @RequestBody List<String> testCaseIds) {
|
||||
aimaTaskService.bindTestCases(taskId, testCaseIds);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务的测试用例列表
|
||||
*/
|
||||
@ApiOperation("获取任务测试用例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:task:query')")
|
||||
@GetMapping("/testCases/{taskId}")
|
||||
public AjaxResult getTestCases(@PathVariable String taskId) {
|
||||
return success(aimaTaskService.getTestCaseIds(taskId));
|
||||
}
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaTaskInstance;
|
||||
import com.cmvr.aima.domain.dto.AimaTaskInstanceQuery;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskInstanceVo;
|
||||
import com.cmvr.aima.service.IAimaTaskInstanceService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/taskinstance")
|
||||
@Api(tags = "爱玛电动车--任务执行实例")
|
||||
public class AimaTaskInstanceController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaTaskInstanceService aimaTaskInstanceService;
|
||||
|
||||
@ApiOperation("查询任务实例列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaTaskInstanceQuery query) {
|
||||
startPage();
|
||||
List<AimaTaskInstanceVo> list = aimaTaskInstanceService.selectAimaTaskInstanceVoList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出任务实例列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:export')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaTaskInstanceQuery query) {
|
||||
List<AimaTaskInstanceVo> list = aimaTaskInstanceService.selectAimaTaskInstanceVoList(query);
|
||||
ExcelUtil<AimaTaskInstanceVo> util = new ExcelUtil<>(AimaTaskInstanceVo.class);
|
||||
util.exportExcel(response, list, "任务实例数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取任务实例详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaTaskInstanceService.selectAimaTaskInstanceById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:add')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaTaskInstance aimaTaskInstance) {
|
||||
return toAjax(aimaTaskInstanceService.insertAimaTaskInstance(aimaTaskInstance));
|
||||
}
|
||||
|
||||
@ApiOperation("修改任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:edit')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaTaskInstance aimaTaskInstance) {
|
||||
return toAjax(aimaTaskInstanceService.updateAimaTaskInstance(aimaTaskInstance));
|
||||
}
|
||||
|
||||
@ApiOperation("删除任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:remove')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaTaskInstanceService.deleteAimaTaskInstanceByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行任务实例
|
||||
*/
|
||||
@ApiOperation("开始执行任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:edit')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/start/{id}")
|
||||
public AjaxResult start(@PathVariable("id") String id) {
|
||||
return toAjax(aimaTaskInstanceService.startInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务实例
|
||||
*/
|
||||
@ApiOperation("暂停任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:edit')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/pause/{id}")
|
||||
public AjaxResult pause(@PathVariable("id") String id) {
|
||||
return toAjax(aimaTaskInstanceService.pauseInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务实例
|
||||
*/
|
||||
@ApiOperation("终止任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:edit')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/stop/{id}")
|
||||
public AjaxResult stop(@PathVariable("id") String id) {
|
||||
return toAjax(aimaTaskInstanceService.stopInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务实例
|
||||
*/
|
||||
@ApiOperation("恢复任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:taskinstance:edit')")
|
||||
@Log(title = "任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/resume/{id}")
|
||||
public AjaxResult resume(@PathVariable("id") String id) {
|
||||
return toAjax(aimaTaskInstanceService.resumeInstance(id));
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.domain.vo.AimaTestCaseVo;
|
||||
import com.cmvr.aima.service.IAimaTestCaseService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/testcase")
|
||||
@Api(tags = "爱玛电动车--测试用例管理")
|
||||
public class AimaTestCaseController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaTestCaseService aimaTestCaseService;
|
||||
|
||||
@ApiOperation("查询测试用例列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaTestCase aimaTestCase) {
|
||||
startPage();
|
||||
List<AimaTestCaseVo> list = aimaTestCaseService.selectAimaTestCaseVoList(aimaTestCase);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出测试用例列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:export')")
|
||||
@Log(title = "测试用例管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaTestCase aimaTestCase) {
|
||||
List<AimaTestCaseVo> list = aimaTestCaseService.selectAimaTestCaseVoList(aimaTestCase);
|
||||
ExcelUtil<AimaTestCaseVo> util = new ExcelUtil<>(AimaTestCaseVo.class);
|
||||
util.exportExcel(response, list, "测试用例数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取测试用例详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaTestCaseService.selectAimaTestCaseById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增测试用例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:add')")
|
||||
@Log(title = "测试用例管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaTestCase aimaTestCase) {
|
||||
return toAjax(aimaTestCaseService.insertAimaTestCase(aimaTestCase));
|
||||
}
|
||||
|
||||
@ApiOperation("修改测试用例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:edit')")
|
||||
@Log(title = "测试用例管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaTestCase aimaTestCase) {
|
||||
return toAjax(aimaTestCaseService.updateAimaTestCase(aimaTestCase));
|
||||
}
|
||||
|
||||
@ApiOperation("删除测试用例")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testcase:remove')")
|
||||
@Log(title = "测试用例管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaTestCaseService.deleteAimaTestCaseByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaTestLog;
|
||||
import com.cmvr.aima.service.IAimaTestLogService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/testlog")
|
||||
@Api(tags = "爱玛电动车--测试日志管理")
|
||||
public class AimaTestLogController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaTestLogService aimaTestLogService;
|
||||
|
||||
@ApiOperation("查询测试日志列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaTestLog aimaTestLog) {
|
||||
startPage();
|
||||
List<AimaTestLog> list = aimaTestLogService.selectAimaTestLogList(aimaTestLog);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出测试日志列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:export')")
|
||||
@Log(title = "测试日志管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaTestLog aimaTestLog) {
|
||||
List<AimaTestLog> list = aimaTestLogService.selectAimaTestLogList(aimaTestLog);
|
||||
ExcelUtil<AimaTestLog> util = new ExcelUtil<>(AimaTestLog.class);
|
||||
util.exportExcel(response, list, "测试日志数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取测试日志详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaTestLogService.selectAimaTestLogById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增测试日志")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:add')")
|
||||
@Log(title = "测试日志管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaTestLog aimaTestLog) {
|
||||
return toAjax(aimaTestLogService.insertAimaTestLog(aimaTestLog));
|
||||
}
|
||||
|
||||
@ApiOperation("修改测试日志")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:edit')")
|
||||
@Log(title = "测试日志管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaTestLog aimaTestLog) {
|
||||
return toAjax(aimaTestLogService.updateAimaTestLog(aimaTestLog));
|
||||
}
|
||||
|
||||
@ApiOperation("删除测试日志")
|
||||
@PreAuthorize("@ss.hasPermi('aima:testlog:remove')")
|
||||
@Log(title = "测试日志管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaTestLogService.deleteAimaTestLogByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package com.cmvr.web.controller.aima;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.aima.domain.AimaVehicle;
|
||||
import com.cmvr.aima.service.IAimaVehicleService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/aima/vehicle")
|
||||
@Api(tags = "爱玛电动车--车辆管理")
|
||||
public class AimaVehicleController extends BaseController {
|
||||
@Autowired
|
||||
private IAimaVehicleService aimaVehicleService;
|
||||
|
||||
@ApiOperation("查询车辆列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AimaVehicle aimaVehicle) {
|
||||
startPage();
|
||||
List<AimaVehicle> list = aimaVehicleService.selectAimaVehicleList(aimaVehicle);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出车辆列表")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:export')")
|
||||
@Log(title = "车辆管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AimaVehicle aimaVehicle) {
|
||||
List<AimaVehicle> list = aimaVehicleService.selectAimaVehicleList(aimaVehicle);
|
||||
ExcelUtil<AimaVehicle> util = new ExcelUtil<>(AimaVehicle.class);
|
||||
util.exportExcel(response, list, "车辆数据");
|
||||
}
|
||||
|
||||
@ApiOperation("获取车辆详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(aimaVehicleService.selectAimaVehicleById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增车辆")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:add')")
|
||||
@Log(title = "车辆管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody AimaVehicle aimaVehicle) {
|
||||
return toAjax(aimaVehicleService.insertAimaVehicle(aimaVehicle));
|
||||
}
|
||||
|
||||
@ApiOperation("修改车辆")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:edit')")
|
||||
@Log(title = "车辆管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody AimaVehicle aimaVehicle) {
|
||||
return toAjax(aimaVehicleService.updateAimaVehicle(aimaVehicle));
|
||||
}
|
||||
|
||||
@ApiOperation("删除车辆")
|
||||
@PreAuthorize("@ss.hasPermi('aima:vehicle:remove')")
|
||||
@Log(title = "车辆管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(aimaVehicleService.deleteAimaVehicleByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,315 +0,0 @@
|
||||
package com.cmvr.web.controller.api;
|
||||
|
||||
import cmvr.msgs.Agv;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvMapNameVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvNavigateToPoseVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvNavigateToStationVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvStartMappingVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvUploadMapVO;
|
||||
import com.cmvr.edge.client.model.agv.EdgeAgvVelocityVO;
|
||||
import com.cmvr.edge.client.service.EdgeAgvService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 边缘系统 AGV 控制器。
|
||||
*
|
||||
* <p>接口入参约定:
|
||||
* GET 查询类接口使用 query 参数绑定 VO;POST 控制类接口只接收一个 JSON 请求体 VO,
|
||||
* 避免一个接口同时出现通用 VO 和零散业务参数,保证前端调用、Swagger 文档和后端绑定规则一致。</p>
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-02
|
||||
*/
|
||||
@Api(tags = "边缘--AGV")
|
||||
@RestController
|
||||
@RequestMapping("/api/agv")
|
||||
@RequiredArgsConstructor
|
||||
public class EdgeAgvController {
|
||||
|
||||
private final EdgeAgvService edgeAgvService;
|
||||
|
||||
/**
|
||||
* 获取 AGV 运行时状态。
|
||||
*/
|
||||
@ApiOperation("获取AGV运行时状态")
|
||||
@GetMapping("/getRuntimeState")
|
||||
public AjaxResult getRuntimeState(@Validated EdgeCommonVO vo) {
|
||||
Agv.AgvRuntimeState state = edgeAgvService.getRuntimeState(vo);
|
||||
return AjaxResult.ok(toRuntimeStateMap(state));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 AGV 当前导航状态。
|
||||
*/
|
||||
@ApiOperation("获取导航状态")
|
||||
@GetMapping("/getNavigationStatus")
|
||||
public AjaxResult getNavigationStatus(@Validated EdgeCommonVO vo) {
|
||||
Agv.AgvNavigationStatus status = edgeAgvService.getNavigationStatus(vo);
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("state", status.getState());
|
||||
resultMap.put("type", status.getType());
|
||||
resultMap.put("progress", status.getProgress());
|
||||
resultMap.put("message", status.getMessage());
|
||||
return AjaxResult.ok(resultMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* AGV 紧急停止。
|
||||
*/
|
||||
@ApiOperation("紧急停止")
|
||||
@PostMapping("/emergencyStop")
|
||||
public AjaxResult emergencyStop(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.emergencyStop(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除 AGV 故障。
|
||||
*/
|
||||
@ApiOperation("清除故障")
|
||||
@PostMapping("/clearFault")
|
||||
public AjaxResult clearFault(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.clearFault(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航到指定坐标。
|
||||
*/
|
||||
@ApiOperation("导航到指定位置")
|
||||
@PostMapping("/navigateToPose")
|
||||
public AjaxResult navigateToPose(@RequestBody @Validated EdgeAgvNavigateToPoseVO vo) {
|
||||
Agv.AgvPose2d pose = Agv.AgvPose2d.newBuilder()
|
||||
.setX(vo.getX())
|
||||
.setY(vo.getY())
|
||||
.setTheta(vo.getTheta())
|
||||
.build();
|
||||
edgeAgvService.navigateToPose(vo, pose);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航到指定站点。
|
||||
*/
|
||||
@ApiOperation("导航到站点")
|
||||
@PostMapping("/navigateToStation")
|
||||
public AjaxResult navigateToStation(@RequestBody @Validated EdgeAgvNavigateToStationVO vo) {
|
||||
edgeAgvService.navigateToStation(vo, vo.getStationId());
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停当前导航任务。
|
||||
*/
|
||||
@ApiOperation("暂停导航")
|
||||
@PostMapping("/pauseNavigation")
|
||||
public AjaxResult pauseNavigation(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.pauseNavigation(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复当前导航任务。
|
||||
*/
|
||||
@ApiOperation("恢复导航")
|
||||
@PostMapping("/resumeNavigation")
|
||||
public AjaxResult resumeNavigation(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.resumeNavigation(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消当前导航任务。
|
||||
*/
|
||||
@ApiOperation("取消导航")
|
||||
@PostMapping("/cancelNavigation")
|
||||
public AjaxResult cancelNavigation(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.cancelNavigation(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 AGV 速度。
|
||||
*/
|
||||
@ApiOperation("设置速度")
|
||||
@PostMapping("/setVelocity")
|
||||
public AjaxResult setVelocity(@RequestBody @Validated EdgeAgvVelocityVO vo) {
|
||||
Agv.AgvVelocity velocity = Agv.AgvVelocity.newBuilder()
|
||||
.setVx(vo.getVx())
|
||||
.setVy(vo.getVy())
|
||||
.setWz(vo.getWz())
|
||||
.build();
|
||||
edgeAgvService.setVelocity(vo, velocity);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止速度控制。
|
||||
*/
|
||||
@ApiOperation("停止速度控制")
|
||||
@PostMapping("/stopVelocityControl")
|
||||
public AjaxResult stopVelocityControl(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.stopVelocityControl(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询机器人本地所有地图。
|
||||
*/
|
||||
@ApiOperation("列出所有地图")
|
||||
@GetMapping("/listMaps")
|
||||
public AjaxResult listMaps(@Validated EdgeCommonVO vo) {
|
||||
List<String> maps = edgeAgvService.listMaps(vo);
|
||||
return AjaxResult.ok(maps);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询机器人本地所有站点。
|
||||
*/
|
||||
@ApiOperation("列出所有站点")
|
||||
@GetMapping("/listStations")
|
||||
public AjaxResult listStations(@Validated EdgeCommonVO vo) {
|
||||
List<Agv.AgvStation> stations = edgeAgvService.listStations(vo);
|
||||
List<Map<String, Object>> stationList = new ArrayList<>();
|
||||
for (Agv.AgvStation station : stations) {
|
||||
stationList.add(toStationMap(station));
|
||||
}
|
||||
return AjaxResult.ok(stationList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换机器人当前地图。
|
||||
*/
|
||||
@ApiOperation("切换地图")
|
||||
@PostMapping("/switchMap")
|
||||
public AjaxResult switchMap(@RequestBody @Validated EdgeAgvMapNameVO vo) {
|
||||
edgeAgvService.switchMap(vo, vo.getMapName());
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传地图内容到机器人。
|
||||
*/
|
||||
@ApiOperation("上传地图")
|
||||
@PostMapping("/uploadMap")
|
||||
public AjaxResult uploadMap(@RequestBody @Validated EdgeAgvUploadMapVO vo) {
|
||||
edgeAgvService.uploadMap(vo, vo.getMapName(), vo.getContent());
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载指定地图内容。
|
||||
*/
|
||||
@ApiOperation("下载地图")
|
||||
@GetMapping("/downloadMap")
|
||||
public AjaxResult downloadMap(@Validated EdgeAgvMapNameVO vo) {
|
||||
String content = edgeAgvService.downloadMap(vo, vo.getMapName());
|
||||
return AjaxResult.ok(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始建图。
|
||||
*/
|
||||
@ApiOperation("开始建图")
|
||||
@PostMapping("/startMapping")
|
||||
public AjaxResult startMapping(@RequestBody @Validated EdgeAgvStartMappingVO vo) {
|
||||
Agv.AgvMapDimension mapDimension = Agv.AgvMapDimension.forNumber(vo.getDimension());
|
||||
if (mapDimension == null) {
|
||||
return AjaxResult.error("建图维度不合法,允许值:0=未指定,1=2D,2=3D,3=2D+3D");
|
||||
}
|
||||
|
||||
String sessionId = edgeAgvService.startMapping(vo, mapDimension, vo.getMapName(), vo.isRealTime());
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("sessionId", sessionId);
|
||||
return AjaxResult.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止建图。
|
||||
*/
|
||||
@ApiOperation("停止建图")
|
||||
@PostMapping("/stopMapping")
|
||||
public AjaxResult stopMapping(@RequestBody @Validated EdgeCommonVO vo) {
|
||||
edgeAgvService.stopMapping(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 protobuf 运行时状态转换为前端友好的 Map,避免直接暴露 protobuf 对象结构。
|
||||
*/
|
||||
private Map<String, Object> toRuntimeStateMap(Agv.AgvRuntimeState state) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("timestamp", state.getTimestamp());
|
||||
resultMap.put("mode", state.getMode());
|
||||
resultMap.put("connected", state.getConnected());
|
||||
resultMap.put("localized", state.getLocalized());
|
||||
resultMap.put("moving", state.getMoving());
|
||||
resultMap.put("fault", state.getFault());
|
||||
resultMap.put("emergencyStopped", state.getEmergencyStopped());
|
||||
|
||||
if (state.hasPose()) {
|
||||
resultMap.put("pose", toPoseMap(state.getPose()));
|
||||
}
|
||||
if (state.hasVelocity()) {
|
||||
Map<String, Object> velocityMap = new HashMap<>();
|
||||
velocityMap.put("vx", state.getVelocity().getVx());
|
||||
velocityMap.put("vy", state.getVelocity().getVy());
|
||||
velocityMap.put("wz", state.getVelocity().getWz());
|
||||
resultMap.put("velocity", velocityMap);
|
||||
}
|
||||
if (state.hasBattery()) {
|
||||
Map<String, Object> batteryMap = new HashMap<>();
|
||||
batteryMap.put("percentage", state.getBattery().getPercentage());
|
||||
batteryMap.put("voltage", state.getBattery().getVoltage());
|
||||
batteryMap.put("current", state.getBattery().getCurrent());
|
||||
batteryMap.put("temperature", state.getBattery().getTemperature());
|
||||
batteryMap.put("charging", state.getBattery().getCharging());
|
||||
resultMap.put("battery", batteryMap);
|
||||
}
|
||||
|
||||
resultMap.put("currentMap", state.getCurrentMap());
|
||||
resultMap.put("currentStation", state.getCurrentStation());
|
||||
resultMap.put("lastError", state.getLastError());
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 protobuf 站点对象转换为普通 Map。
|
||||
*/
|
||||
private Map<String, Object> toStationMap(Agv.AgvStation station) {
|
||||
Map<String, Object> stationMap = new HashMap<>();
|
||||
stationMap.put("id", station.getId());
|
||||
stationMap.put("type", station.getType());
|
||||
stationMap.put("description", station.getDescription());
|
||||
if (station.hasPose()) {
|
||||
stationMap.put("pose", toPoseMap(station.getPose()));
|
||||
}
|
||||
return stationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 protobuf 二维位姿转换为普通 Map。
|
||||
*/
|
||||
private Map<String, Object> toPoseMap(Agv.AgvPose2d pose) {
|
||||
Map<String, Object> poseMap = new HashMap<>();
|
||||
poseMap.put("x", pose.getX());
|
||||
poseMap.put("y", pose.getY());
|
||||
poseMap.put("theta", pose.getTheta());
|
||||
return poseMap;
|
||||
}
|
||||
}
|
||||
@ -1,232 +0,0 @@
|
||||
package com.cmvr.web.controller.api;
|
||||
|
||||
import cmvr.api.ArmCommand;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import com.cmvr.edge.client.model.arm.*;
|
||||
import com.cmvr.edge.client.service.EdgeArmService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 边缘系统机械臂控制器
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Api(tags = "边缘--机械臂")
|
||||
@RestController
|
||||
@RequestMapping("/api/arm")
|
||||
@RequiredArgsConstructor
|
||||
public class EdgeArmController {
|
||||
|
||||
private final EdgeArmService edgeArmService;
|
||||
|
||||
@ApiOperation("关闭力矩")
|
||||
@GetMapping("/torqueOff")
|
||||
public AjaxResult torqueOff(EdgeCommonVO vo) {
|
||||
edgeArmService.torqueOff(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("开启力矩")
|
||||
@GetMapping("/torqueOn")
|
||||
public AjaxResult torqueOn(EdgeCommonVO vo) {
|
||||
edgeArmService.torqueOn(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除机械臂故障状态。
|
||||
*/
|
||||
@ApiOperation("清除故障")
|
||||
@GetMapping("/clearFault")
|
||||
public AjaxResult clearFault(EdgeCommonVO vo) {
|
||||
edgeArmService.clearFault(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("关节空间运动")
|
||||
@PostMapping("/moveJ")
|
||||
public AjaxResult moveJ(@RequestBody EdgeArmMoveJVO moveJVO) {
|
||||
edgeArmService.moveJ(
|
||||
moveJVO,
|
||||
moveJVO.getTarget(),
|
||||
moveJVO.getVelocity(),
|
||||
moveJVO.getAcceleration(),
|
||||
moveJVO.getBlendRadius(),
|
||||
moveJVO.getJointVelocityLimits(),
|
||||
moveJVO.getAsynchronous()
|
||||
);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("笛卡尔空间直线运动")
|
||||
@PostMapping("/moveL")
|
||||
public AjaxResult moveL(@RequestBody EdgeArmMoveLVO moveLVO) {
|
||||
edgeArmService.moveL(
|
||||
moveLVO,
|
||||
moveLVO.getX(),
|
||||
moveLVO.getY(),
|
||||
moveLVO.getZ(),
|
||||
moveLVO.getRx(),
|
||||
moveLVO.getRy(),
|
||||
moveLVO.getRz(),
|
||||
moveLVO.getFrame(),
|
||||
moveLVO.getVelocity(),
|
||||
moveLVO.getAcceleration(),
|
||||
moveLVO.getBlendRadius()
|
||||
);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("关节速度控制")
|
||||
@PostMapping("/speedJ")
|
||||
public AjaxResult speedJ(@RequestBody EdgeArmSpeedJVO speedJVO) {
|
||||
edgeArmService.speedJ(
|
||||
speedJVO,
|
||||
speedJVO.getVelocities(),
|
||||
speedJVO.getAcceleration(),
|
||||
speedJVO.getDuration()
|
||||
);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("笛卡尔速度控制")
|
||||
@PostMapping("/speedL")
|
||||
public AjaxResult speedL(@RequestBody EdgeArmSpeedLVO speedLVO) {
|
||||
edgeArmService.speedL(
|
||||
speedLVO,
|
||||
speedLVO.getVx(),
|
||||
speedLVO.getVy(),
|
||||
speedLVO.getVz(),
|
||||
speedLVO.getWx(),
|
||||
speedLVO.getWy(),
|
||||
speedLVO.getWz(),
|
||||
speedLVO.getFrame(),
|
||||
speedLVO.getAcceleration(),
|
||||
speedLVO.getDuration()
|
||||
);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("伺服关节控制")
|
||||
@PostMapping("/servoJ")
|
||||
public AjaxResult servoJ(@RequestBody EdgeArmServoJVO servoJVO) {
|
||||
edgeArmService.servoJ(servoJVO, servoJVO.getTarget());
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("停止运动")
|
||||
@GetMapping("/stopMotion")
|
||||
public AjaxResult stopMotion(EdgeCommonVO vo) {
|
||||
edgeArmService.stopMotion(vo);
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("获取关节状态")
|
||||
@GetMapping("/getJointState")
|
||||
public AjaxResult getJointState(EdgeCommonVO vo) {
|
||||
ArmCommand.JointResponse result = edgeArmService.getJointState(vo);
|
||||
ArmCommand.JointState state = result.getState();
|
||||
|
||||
// 转换为VO
|
||||
EdgeArmJointStateVO jointStateVO = new EdgeArmJointStateVO();
|
||||
jointStateVO.setName(state.getNameList());
|
||||
jointStateVO.setPosition(state.getPositionList());
|
||||
jointStateVO.setVelocity(state.getVelocityList());
|
||||
jointStateVO.setEffort(state.getEffortList());
|
||||
jointStateVO.setTimestamp(state.getTimestamp());
|
||||
|
||||
return AjaxResult.ok(jointStateVO);
|
||||
}
|
||||
|
||||
@ApiOperation("获取末端位姿")
|
||||
@GetMapping("/getPose")
|
||||
public AjaxResult getPose(@Validated EdgeArmPoseQueryVO vo) {
|
||||
ArmCommand.GetPose.Response result = edgeArmService.getPose(vo, vo.getBaseLink(), vo.getEeLink());
|
||||
ArmCommand.CartesianPose pose = result.getPose();
|
||||
|
||||
// 转换为VO
|
||||
EdgeArmCartesianPoseVO poseVO = new EdgeArmCartesianPoseVO();
|
||||
poseVO.setX(pose.getX());
|
||||
poseVO.setY(pose.getY());
|
||||
poseVO.setZ(pose.getZ());
|
||||
poseVO.setRx(pose.getRx());
|
||||
poseVO.setRy(pose.getRy());
|
||||
poseVO.setRz(pose.getRz());
|
||||
|
||||
return AjaxResult.ok(poseVO);
|
||||
}
|
||||
|
||||
@ApiOperation("标定零点")
|
||||
@GetMapping("/calibrateZeroQ")
|
||||
public AjaxResult calibrateZeroQ(@Validated EdgeArmCalibrateZeroQVO vo) {
|
||||
edgeArmService.calibrateZeroQ(vo, vo.getJointName());
|
||||
return AjaxResult.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("获取位姿矩阵")
|
||||
@GetMapping("/getPoseMatrix")
|
||||
public AjaxResult getPoseMatrix(@Validated EdgeArmPoseQueryVO vo) {
|
||||
ArmCommand.GetPoseMatrix.Response result = edgeArmService.getPoseMatrix(vo, vo.getBaseLink(), vo.getEeLink());
|
||||
// 将TransformMatrix4x4转换为Map
|
||||
ArmCommand.TransformMatrix4x4 matrix = result.getMatrix();
|
||||
java.util.Map<String, Object> matrixMap = new java.util.HashMap<>();
|
||||
matrixMap.put("m00", matrix.getM00());
|
||||
matrixMap.put("m01", matrix.getM01());
|
||||
matrixMap.put("m02", matrix.getM02());
|
||||
matrixMap.put("m03", matrix.getM03());
|
||||
matrixMap.put("m10", matrix.getM10());
|
||||
matrixMap.put("m11", matrix.getM11());
|
||||
matrixMap.put("m12", matrix.getM12());
|
||||
matrixMap.put("m13", matrix.getM13());
|
||||
matrixMap.put("m20", matrix.getM20());
|
||||
matrixMap.put("m21", matrix.getM21());
|
||||
matrixMap.put("m22", matrix.getM22());
|
||||
matrixMap.put("m23", matrix.getM23());
|
||||
matrixMap.put("m30", matrix.getM30());
|
||||
matrixMap.put("m31", matrix.getM31());
|
||||
matrixMap.put("m32", matrix.getM32());
|
||||
matrixMap.put("m33", matrix.getM33());
|
||||
return AjaxResult.ok(matrixMap);
|
||||
}
|
||||
|
||||
@ApiOperation("计算正向运动学")
|
||||
@PostMapping("/computeForwardKinematics")
|
||||
public AjaxResult computeForwardKinematics(@RequestBody EdgeArmForwardKinematicsVO fkVO) {
|
||||
ArmCommand.ComputeForwardKinematics.Response result = edgeArmService.computeForwardKinematics(
|
||||
fkVO,
|
||||
fkVO.getJoints(),
|
||||
fkVO.getBaseLink(),
|
||||
fkVO.getEeLink()
|
||||
);
|
||||
// 将TransformMatrix4x4转换为Map
|
||||
ArmCommand.TransformMatrix4x4 matrix = result.getMatrix();
|
||||
java.util.Map<String, Object> matrixMap = new java.util.HashMap<>();
|
||||
matrixMap.put("m00", matrix.getM00());
|
||||
matrixMap.put("m01", matrix.getM01());
|
||||
matrixMap.put("m02", matrix.getM02());
|
||||
matrixMap.put("m03", matrix.getM03());
|
||||
matrixMap.put("m10", matrix.getM10());
|
||||
matrixMap.put("m11", matrix.getM11());
|
||||
matrixMap.put("m12", matrix.getM12());
|
||||
matrixMap.put("m13", matrix.getM13());
|
||||
matrixMap.put("m20", matrix.getM20());
|
||||
matrixMap.put("m21", matrix.getM21());
|
||||
matrixMap.put("m22", matrix.getM22());
|
||||
matrixMap.put("m23", matrix.getM23());
|
||||
matrixMap.put("m30", matrix.getM30());
|
||||
matrixMap.put("m31", matrix.getM31());
|
||||
matrixMap.put("m32", matrix.getM32());
|
||||
matrixMap.put("m33", matrix.getM33());
|
||||
return AjaxResult.ok(matrixMap);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.cmvr.web.controller.api;
|
||||
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
|
||||
import com.cmvr.edge.client.model.humanoid.EdgeSpeedJVO;
|
||||
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Api(tags = "边缘--机械臂")
|
||||
@RestController
|
||||
@RequestMapping("/api/humanoid")
|
||||
@RequiredArgsConstructor
|
||||
public class EdgeHumanoidRobotController {
|
||||
|
||||
private final EdgeHumanoidRobotService edgeHumanoidRobotService;
|
||||
|
||||
@ApiOperation("moveJ")
|
||||
@PostMapping("/moveJ")
|
||||
public AjaxResult moveJ(@RequestBody EdgeMoveJVO moveJVO) {
|
||||
return AjaxResult.ok(edgeHumanoidRobotService.moveJ(moveJVO));
|
||||
}
|
||||
|
||||
@ApiOperation("speedJ")
|
||||
@PostMapping("/speedJ")
|
||||
public AjaxResult speedJ(@RequestBody EdgeSpeedJVO speedJVO) {
|
||||
return AjaxResult.ok(edgeHumanoidRobotService.speedJ(speedJVO));
|
||||
}
|
||||
|
||||
@ApiOperation("获取关节状态")
|
||||
@GetMapping("/getJointState")
|
||||
public AjaxResult status(EdgeCommonVO vo) {
|
||||
return AjaxResult.ok(edgeHumanoidRobotService.getJointState(vo));
|
||||
}
|
||||
|
||||
@ApiOperation("使能开")
|
||||
@GetMapping("/torqueOn")
|
||||
public AjaxResult torqueOn(EdgeCommonVO vo) {
|
||||
return AjaxResult.ok(edgeHumanoidRobotService.torqueOn(vo));
|
||||
}
|
||||
|
||||
@ApiOperation("使能关")
|
||||
@GetMapping("/torqueOff")
|
||||
public AjaxResult torqueOff(EdgeCommonVO vo) {
|
||||
return AjaxResult.ok(edgeHumanoidRobotService.torqueOff(vo));
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,10 +6,12 @@ import com.cmvr.edge.client.model.microphone.EdgeMicrophoneVolumeVO;
|
||||
import com.cmvr.edge.client.service.EdgeMicrophoneService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 麦克风管理
|
||||
@ -25,17 +27,14 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("获取麦克风状态")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:query')")
|
||||
@GetMapping("/status")
|
||||
public AjaxResult getStatus(@ApiParam(value = "终端设备ID", required = true) @RequestParam String terminalId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
public AjaxResult getStatus(EdgeCommonVO edgeCommonVO) {
|
||||
return AjaxResult.success(microphoneService.getStatus(edgeCommonVO));
|
||||
}
|
||||
|
||||
@ApiOperation("开始录音")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:record')")
|
||||
@PostMapping("/start")
|
||||
public AjaxResult startRecord(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
public AjaxResult startRecord(EdgeCommonVO edgeCommonVO) {
|
||||
String filePath = microphoneService.startRecord(edgeCommonVO);
|
||||
return AjaxResult.success(filePath);
|
||||
}
|
||||
@ -43,7 +42,7 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("停止录音")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:stop')")
|
||||
@PostMapping("/stop")
|
||||
public AjaxResult stopRecord(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
public AjaxResult stopRecord(EdgeCommonVO edgeCommonVO) {
|
||||
microphoneService.stopRecord(edgeCommonVO);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
@ -51,7 +50,7 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("暂停录音")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:pause')")
|
||||
@PostMapping("/pause")
|
||||
public AjaxResult pauseRecord(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
public AjaxResult pauseRecord(EdgeCommonVO edgeCommonVO) {
|
||||
microphoneService.pauseRecord(edgeCommonVO);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
@ -59,7 +58,7 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("恢复录音")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:resume')")
|
||||
@PostMapping("/resume")
|
||||
public AjaxResult resumeRecord(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
public AjaxResult resumeRecord(EdgeCommonVO edgeCommonVO) {
|
||||
microphoneService.resumeRecord(edgeCommonVO);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
@ -67,7 +66,7 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("设置音量")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:volume')")
|
||||
@PostMapping("/volume")
|
||||
public AjaxResult setVolume(@RequestBody EdgeMicrophoneVolumeVO edgeMicrophoneVolumeVO) {
|
||||
public AjaxResult setVolume(EdgeMicrophoneVolumeVO edgeMicrophoneVolumeVO) {
|
||||
microphoneService.setVolume(edgeMicrophoneVolumeVO);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
@ -75,10 +74,7 @@ public class EdgeMicrophoneController {
|
||||
@ApiOperation("获取音量")
|
||||
@PreAuthorize("@ss.hasPermi('system:microphone:volume')")
|
||||
@GetMapping("/volume")
|
||||
public AjaxResult getVolume(@ApiParam(value = "终端设备ID", required = true) @RequestParam String terminalId, @ApiParam (value = "设备ID", required = true) @RequestParam String deviceId) {
|
||||
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||
edgeCommonVO.setTerminalId(terminalId);
|
||||
edgeCommonVO.setDeviceId(deviceId);
|
||||
public AjaxResult getVolume(EdgeCommonVO edgeCommonVO) {
|
||||
return AjaxResult.success(microphoneService.getVolume(edgeCommonVO));
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,6 @@
|
||||
package com.cmvr.web.controller.api;
|
||||
|
||||
import cmvr.api.SpeakerCommand;
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import com.cmvr.edge.client.model.microphone.EdgeMicrophoneVolumeVO;
|
||||
import com.cmvr.edge.client.model.speaker.EdgeSpeakerPlayAudioVO;
|
||||
import com.cmvr.edge.client.service.EdgeSpeakerService;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -72,8 +69,14 @@ public class EdgeSpeakerController {
|
||||
@ApiOperation("播放音频")
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:play')")
|
||||
@PostMapping("/play")
|
||||
public AjaxResult playAudio(@RequestBody EdgeSpeakerPlayAudioVO edgeSpeakerPlayAudioVO) {
|
||||
speakerService.playAudio(edgeSpeakerPlayAudioVO.getTerminalId(), edgeSpeakerPlayAudioVO.getDeviceId(), edgeSpeakerPlayAudioVO.getAudioPath());
|
||||
public AjaxResult playAudio(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId,
|
||||
@ApiParam(value = "音频文件路径", required = true)
|
||||
@RequestParam String audioPath) {
|
||||
speakerService.playAudio(terminalId, deviceId, audioPath);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -83,8 +86,12 @@ public class EdgeSpeakerController {
|
||||
@ApiOperation("停止播放")
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:stop')")
|
||||
@PostMapping("/stop")
|
||||
public AjaxResult stopPlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.stopPlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
public AjaxResult stopPlayback(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId) {
|
||||
speakerService.stopPlayback(terminalId, deviceId);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -94,8 +101,12 @@ public class EdgeSpeakerController {
|
||||
@ApiOperation("暂停播放")
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:pause')")
|
||||
@PostMapping("/pause")
|
||||
public AjaxResult pausePlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.pausePlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
public AjaxResult pausePlayback(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId) {
|
||||
speakerService.pausePlayback(terminalId, deviceId);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -105,8 +116,12 @@ public class EdgeSpeakerController {
|
||||
@ApiOperation("恢复播放")
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:resume')")
|
||||
@PostMapping("/resume")
|
||||
public AjaxResult resumePlayback(@RequestBody EdgeCommonVO edgeCommonVO) {
|
||||
speakerService.resumePlayback(edgeCommonVO.getTerminalId(), edgeCommonVO.getDeviceId());
|
||||
public AjaxResult resumePlayback(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId) {
|
||||
speakerService.resumePlayback(terminalId, deviceId);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -116,8 +131,14 @@ public class EdgeSpeakerController {
|
||||
@ApiOperation("设置音量")
|
||||
@PreAuthorize("@ss.hasPermi('system:speaker:volume')")
|
||||
@PostMapping("/volume")
|
||||
public AjaxResult setVolume(@RequestBody EdgeMicrophoneVolumeVO edgeMicrophoneVolumeVO) {
|
||||
speakerService.setVolume(edgeMicrophoneVolumeVO.getTerminalId(), edgeMicrophoneVolumeVO.getDeviceId(), edgeMicrophoneVolumeVO.getVolume());
|
||||
public AjaxResult setVolume(
|
||||
@ApiParam(value = "终端设备ID", required = true)
|
||||
@RequestParam String terminalId,
|
||||
@ApiParam(value = "设备ID", required = true)
|
||||
@RequestParam String deviceId,
|
||||
@ApiParam(value = "音量大小(0-100)", required = true)
|
||||
@RequestParam int volume) {
|
||||
speakerService.setVolume(terminalId, deviceId, volume);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
package com.cmvr.web.controller.api;
|
||||
|
||||
import com.cmvr.edge.client.service.AudioService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
|
||||
|
||||
/**
|
||||
* WebRTC 信令 WebSocket 入口。
|
||||
*
|
||||
* 路径:/ws/signaling
|
||||
*
|
||||
* 约束:
|
||||
* 1. WebSocket 只传 JSON 信令:join、offer、answer、candidate、heartbeat、stop;
|
||||
* 2. WebSocket 禁止传输 PCM 音频;
|
||||
* 3. PCM 音频由 WebRTC 媒体通道进入 Java 后端,再由 AudioService 转 gRPC 双向流。
|
||||
*/
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class WebRtcSignalingController implements WebSocketConfigurer {
|
||||
|
||||
private final AudioService audioService;
|
||||
|
||||
@Override
|
||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||
registry.addHandler(new SignalingWebSocketHandler(audioService), "/ws/signaling")
|
||||
.setAllowedOrigins("*");
|
||||
registry.addHandler(new SignalingWebSocketHandler(audioService), "/ws/audio")
|
||||
.setAllowedOrigins("*");
|
||||
}
|
||||
|
||||
/**
|
||||
* 信令处理器。这里只处理文本 JSON,不处理二进制音频。
|
||||
*/
|
||||
private static class SignalingWebSocketHandler extends AbstractWebSocketHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SignalingWebSocketHandler.class);
|
||||
|
||||
private final AudioService audioService;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private SignalingWebSocketHandler(AudioService audioService) {
|
||||
this.audioService = audioService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(@NotNull WebSocketSession session) {
|
||||
log.info("WebRTC信令连接建立,wsSessionId={}", session.getId());
|
||||
sendConnected(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(@NotNull WebSocketSession session, @NotNull TextMessage message) {
|
||||
try {
|
||||
audioService.handleSignalingMessage(session, message.getPayload());
|
||||
} catch (Exception e) {
|
||||
log.error("处理WebRTC信令异常,wsSessionId={}", session.getId(), e);
|
||||
sendError(session, "处理WebRTC信令异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleBinaryMessage(@NotNull WebSocketSession session, @NotNull BinaryMessage message) {
|
||||
try {
|
||||
audioService.handleBrowserAudioMessage(session, message.getPayload());
|
||||
} catch (Exception e) {
|
||||
log.error("处理WebSocket音频二进制帧失败,wsSessionId={}", session.getId(), e);
|
||||
sendError(session, "audio binary frame failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable exception) {
|
||||
log.error("WebRTC信令连接传输异常,wsSessionId={}", session.getId(), exception);
|
||||
audioService.handleWebSocketClosed(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus status) {
|
||||
log.info("WebRTC信令连接关闭,wsSessionId={},status={}", session.getId(), status);
|
||||
audioService.handleWebSocketClosed(session);
|
||||
}
|
||||
|
||||
private void sendConnected(WebSocketSession session) {
|
||||
ObjectNode node = objectMapper.createObjectNode();
|
||||
node.put("type", "connected");
|
||||
node.put("timestamp", System.currentTimeMillis());
|
||||
sendJson(session, node);
|
||||
}
|
||||
|
||||
private void sendError(WebSocketSession session, String message) {
|
||||
ObjectNode node = objectMapper.createObjectNode();
|
||||
node.put("type", "error");
|
||||
node.put("message", message);
|
||||
node.put("timestamp", System.currentTimeMillis());
|
||||
sendJson(session, node);
|
||||
}
|
||||
|
||||
private void sendJson(WebSocketSession session, ObjectNode node) {
|
||||
if (session == null || !session.isOpen()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
synchronized (session) {
|
||||
session.sendMessage(new TextMessage(objectMapper.writeValueAsString(node)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送WebRTC信令响应失败,wsSessionId={}", session.getId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,114 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionAlarm;
|
||||
import com.cmvr.inspection.domain.vo.InspectionAlarmVo;
|
||||
import com.cmvr.inspection.service.IInspectionAlarmService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检告警Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-05-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/alarm")
|
||||
@Api(tags = "智能巡检--告警管理")
|
||||
public class InspectionAlarmController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionAlarmService inspectionAlarmService;
|
||||
|
||||
/**
|
||||
* 查询巡检告警列表
|
||||
*/
|
||||
@ApiOperation("查询巡检告警列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionAlarm inspectionAlarm)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionAlarmVo> list = inspectionAlarmService.selectInspectionAlarmList(inspectionAlarm);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检告警列表
|
||||
*/
|
||||
@ApiOperation("导出巡检告警列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:export')")
|
||||
@Log(title = "巡检告警", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionAlarm inspectionAlarm)
|
||||
{
|
||||
List<InspectionAlarmVo> list = inspectionAlarmService.selectInspectionAlarmList(inspectionAlarm);
|
||||
ExcelUtil<InspectionAlarmVo> util = new ExcelUtil<>(InspectionAlarmVo.class);
|
||||
util.exportExcel(response, list, "巡检告警数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检告警详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检告警详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionAlarmService.selectInspectionAlarmById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检告警
|
||||
*/
|
||||
@ApiOperation("新增巡检告警")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:add')")
|
||||
@Log(title = "巡检告警", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionAlarm inspectionAlarm)
|
||||
{
|
||||
return toAjax(inspectionAlarmService.insertInspectionAlarm(inspectionAlarm));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检告警
|
||||
*/
|
||||
@ApiOperation("修改巡检告警")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:edit')")
|
||||
@Log(title = "巡检告警", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionAlarm inspectionAlarm)
|
||||
{
|
||||
return toAjax(inspectionAlarmService.updateInspectionAlarm(inspectionAlarm));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检告警
|
||||
*/
|
||||
@ApiOperation("删除巡检告警")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:alarm:remove')")
|
||||
@Log(title = "巡检告警", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionAlarmService.deleteInspectionAlarmByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import com.cmvr.common.annotation.Anonymous;
|
||||
import com.cmvr.inspection.domain.dto.alert.AlertEnvelope;
|
||||
import com.cmvr.inspection.exception.DetectionAlertBadRequestException;
|
||||
import com.cmvr.inspection.service.IInspectionDetectionAlertService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* cmvr_edge_ai 检测报警推送入口。
|
||||
*
|
||||
* 该接口由边缘服务主动调用,使用HTTP状态码表达处理结果,不使用项目通用AjaxResult包装。
|
||||
*/
|
||||
@Slf4j
|
||||
@Anonymous
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "智能巡检--PPE报警接收")
|
||||
public class InspectionDetectionAlertController
|
||||
{
|
||||
/** 包含Base64图片的JSON请求最大允许20MB,防止异常请求耗尽服务端内存。 */
|
||||
private static final int MAX_REQUEST_BYTES = 20 * 1024 * 1024;
|
||||
|
||||
private final IInspectionDetectionAlertService detectionAlertService;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 接收PPE违规报警。重复事件视为已处理,仍返回204,避免边缘端持续重试。
|
||||
*/
|
||||
@ApiOperation("接收边缘AI的PPE违规报警")
|
||||
@PostMapping(value = "/v1/detection-alerts", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<Void> receive(
|
||||
@RequestHeader(value = "Idempotency-Key", required = false) String idempotencyKey,
|
||||
HttpServletRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
String requestBody = readRequestBody(request);
|
||||
AlertEnvelope envelope = objectMapper.readValue(requestBody, AlertEnvelope.class);
|
||||
detectionAlertService.receive(envelope, idempotencyKey);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
catch (JsonProcessingException | DetectionAlertBadRequestException ex)
|
||||
{
|
||||
log.warn("拒绝不合法的PPE报警请求,idempotencyKey={},原因={}", idempotencyKey, ex.getMessage());
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
catch (DuplicateKeyException ex)
|
||||
{
|
||||
// 预查与插入之间仍可能发生并发,由数据库唯一索引完成最终幂等。
|
||||
log.info("忽略并发重复的PPE报警,idempotencyKey={}", idempotencyKey);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("读取PPE报警请求失败,idempotencyKey={},原因={}", idempotencyKey, ex.getMessage());
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.error("PPE报警处理暂时失败,idempotencyKey={}", idempotencyKey, ex);
|
||||
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
|
||||
}
|
||||
}
|
||||
|
||||
private String readRequestBody(HttpServletRequest request) throws IOException
|
||||
{
|
||||
long contentLength = request.getContentLengthLong();
|
||||
if (contentLength > MAX_REQUEST_BYTES)
|
||||
{
|
||||
throw new DetectionAlertBadRequestException("请求体不能超过20MB");
|
||||
}
|
||||
|
||||
try (ServletInputStream inputStream = request.getInputStream();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(initialCapacity(contentLength)))
|
||||
{
|
||||
byte[] buffer = new byte[8192];
|
||||
int total = 0;
|
||||
int length;
|
||||
while ((length = inputStream.read(buffer)) != -1)
|
||||
{
|
||||
total += length;
|
||||
if (total > MAX_REQUEST_BYTES)
|
||||
{
|
||||
throw new DetectionAlertBadRequestException("请求体不能超过20MB");
|
||||
}
|
||||
outputStream.write(buffer, 0, length);
|
||||
}
|
||||
if (total == 0)
|
||||
{
|
||||
throw new DetectionAlertBadRequestException("请求体不能为空");
|
||||
}
|
||||
return new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private int initialCapacity(long contentLength)
|
||||
{
|
||||
if (contentLength <= 0 || contentLength > MAX_REQUEST_BYTES)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
return (int) contentLength;
|
||||
}
|
||||
}
|
||||
@ -1,114 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionMap;
|
||||
import com.cmvr.inspection.domain.vo.InspectionMapVo;
|
||||
import com.cmvr.inspection.service.IInspectionMapService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检地图Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-05-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/map")
|
||||
@Api(tags = "智能巡检--地图管理")
|
||||
public class InspectionMapController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionMapService inspectionMapService;
|
||||
|
||||
/**
|
||||
* 查询巡检地图列表
|
||||
*/
|
||||
@ApiOperation("查询巡检地图列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionMap inspectionMap)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionMapVo> list = inspectionMapService.selectInspectionMapList(inspectionMap);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检地图列表
|
||||
*/
|
||||
@ApiOperation("导出巡检地图列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:export')")
|
||||
@Log(title = "巡检地图", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionMap inspectionMap)
|
||||
{
|
||||
List<InspectionMapVo> list = inspectionMapService.selectInspectionMapList(inspectionMap);
|
||||
ExcelUtil<InspectionMapVo> util = new ExcelUtil<>(InspectionMapVo.class);
|
||||
util.exportExcel(response, list, "巡检地图数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检地图详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检地图详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionMapService.selectInspectionMapById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检地图
|
||||
*/
|
||||
@ApiOperation("新增巡检地图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:add')")
|
||||
@Log(title = "巡检地图", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionMap inspectionMap)
|
||||
{
|
||||
return toAjax(inspectionMapService.insertInspectionMap(inspectionMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检地图
|
||||
*/
|
||||
@ApiOperation("修改巡检地图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:edit')")
|
||||
@Log(title = "巡检地图", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionMap inspectionMap)
|
||||
{
|
||||
return toAjax(inspectionMapService.updateInspectionMap(inspectionMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检地图
|
||||
*/
|
||||
@ApiOperation("删除巡检地图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:map:remove')")
|
||||
@Log(title = "巡检地图", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionMapService.deleteInspectionMapByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,126 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.inspection.domain.dto.InspectionResultQuery;
|
||||
import com.cmvr.inspection.domain.dto.InspectionResultReviewRequest;
|
||||
import com.cmvr.inspection.domain.vo.InspectionResultVo;
|
||||
import com.cmvr.inspection.service.IInspectionResultService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 巡检结果、人工复核和任务报表接口。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/result")
|
||||
@Api(tags = "智能巡检--巡检结果", description = "巡检结果查询、人工复核、三级告警统计和报表导出")
|
||||
@ApiResponses({
|
||||
@ApiResponse(code = 200, message = "请求处理成功"),
|
||||
@ApiResponse(code = 400, message = "请求参数或状态不合法"),
|
||||
@ApiResponse(code = 401, message = "未登录或登录已失效"),
|
||||
@ApiResponse(code = 403, message = "无接口权限"),
|
||||
@ApiResponse(code = 500, message = "系统内部异常")
|
||||
})
|
||||
@RequiredArgsConstructor
|
||||
public class InspectionResultController extends BaseController
|
||||
{
|
||||
private final IInspectionResultService inspectionResultService;
|
||||
|
||||
@ApiOperation(value = "查询巡检结果列表",
|
||||
notes = "分页查询PPE、仪表读数和人工判断结果;查询条件均为可选,结果按检测时间倒序。"
|
||||
+ "返回rows元素为InspectionResultVo,包含taskName任务名称和evidenceType主要证据类型;"
|
||||
+ "完整mediaList仅在详情接口返回")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "pageNum", value = "页码,从1开始", dataType = "int", paramType = "query", example = "1"),
|
||||
@ApiImplicitParam(name = "pageSize", value = "每页数量", dataType = "int", paramType = "query", example = "10"),
|
||||
@ApiImplicitParam(name = "taskInstanceId", value = "巡检任务实例数据库ID", dataType = "string", paramType = "query"),
|
||||
@ApiImplicitParam(name = "taskId", value = "巡检任务ID", dataType = "string", paramType = "query"),
|
||||
@ApiImplicitParam(name = "itemId", value = "检测项ID", dataType = "string", paramType = "query"),
|
||||
@ApiImplicitParam(name = "resultType", value = "结果类型:PPE、METER、MANUAL", dataType = "string", paramType = "query"),
|
||||
@ApiImplicitParam(name = "resultStatus", value = "状态:PENDING、NORMAL、ABNORMAL、RECOGNIZE_FAILED", dataType = "string", paramType = "query"),
|
||||
@ApiImplicitParam(name = "alarmLevel", value = "告警级别:1提示、2警告、3严重", dataType = "int", paramType = "query"),
|
||||
@ApiImplicitParam(name = "resultName", value = "检查名称,支持模糊查询", dataType = "string", paramType = "query")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermi('inspection:result:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(@ApiParam("巡检结果查询条件") InspectionResultQuery query)
|
||||
{
|
||||
startPage();
|
||||
return getDataTable(inspectionResultService.selectResultList(query));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询巡检结果详情",
|
||||
notes = "返回结构化巡检结果及按顺序排列的全部图片、视频证据",
|
||||
response = InspectionResultVo.class)
|
||||
@PreAuthorize("@ss.hasPermi('inspection:result:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getInfo(@ApiParam(value = "巡检结果ID", required = true)
|
||||
@PathVariable String id)
|
||||
{
|
||||
return success(inspectionResultService.selectResultById(id));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "提交人工复核结果",
|
||||
notes = "仅PENDING或RECOGNIZE_FAILED状态可复核。ABNORMAL必须传alarmLevel;reviewVersion用于并发控制")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:result:review')")
|
||||
@Log(title = "巡检结果人工复核", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{id}/review")
|
||||
public AjaxResult review(@ApiParam(value = "巡检结果ID", required = true)
|
||||
@PathVariable String id,
|
||||
@ApiParam(value = "人工复核内容", required = true)
|
||||
@Validated @RequestBody InspectionResultReviewRequest request)
|
||||
{
|
||||
return success(inspectionResultService.review(id, request));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询巡检任务报表汇总",
|
||||
notes = "返回summary统计和results明细。reviewCompleted=false表示仍有待复核或识别失败结果")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:result:report')")
|
||||
@GetMapping("/report/{taskInstanceId}")
|
||||
public AjaxResult report(@ApiParam(value = "巡检任务实例数据库ID", required = true)
|
||||
@PathVariable String taskInstanceId)
|
||||
{
|
||||
AjaxResult result = AjaxResult.success();
|
||||
result.put("summary", inspectionResultService.buildReportSummary(taskInstanceId));
|
||||
InspectionResultQuery query = new InspectionResultQuery();
|
||||
query.setTaskInstanceId(taskInstanceId);
|
||||
result.put("results", inspectionResultService.selectResultList(query));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ApiOperation(value = "导出巡检结果报表",
|
||||
notes = "按查询条件导出Excel;不传条件时导出全部巡检结果")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:result:export')")
|
||||
@Log(title = "巡检结果", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response,
|
||||
@ApiParam("导出筛选条件") InspectionResultQuery query)
|
||||
{
|
||||
List<InspectionResultVo> list = inspectionResultService.selectResultList(query);
|
||||
ExcelUtil<InspectionResultVo> util = new ExcelUtil<>(InspectionResultVo.class);
|
||||
util.exportExcel(response, list, "巡检结果数据");
|
||||
}
|
||||
}
|
||||
@ -1,241 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cmvr.msgs.Agv;
|
||||
import com.cmvr.inspection.domain.vo.InspectionRobotVo;
|
||||
import io.swagger.annotations.*;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionRobot;
|
||||
import com.cmvr.inspection.service.IInspectionRobotService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检机器人Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-05-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/robot")
|
||||
@Api(tags = "智能巡检--机器人管理")
|
||||
public class InspectionRobotController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionRobotService inspectionRobotService;
|
||||
|
||||
/**
|
||||
* 查询巡检机器人列表
|
||||
*/
|
||||
@ApiOperation("查询巡检机器人列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionRobot inspectionRobot)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionRobotVo> list = inspectionRobotService.selectInspectionRobotList(inspectionRobot);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检机器人列表
|
||||
*/
|
||||
@ApiOperation("导出巡检机器人列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:export')")
|
||||
@Log(title = "巡检机器人", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionRobot inspectionRobot)
|
||||
{
|
||||
List<InspectionRobotVo> list = inspectionRobotService.selectInspectionRobotList(inspectionRobot);
|
||||
ExcelUtil<InspectionRobotVo> util = new ExcelUtil<>(InspectionRobotVo.class);
|
||||
util.exportExcel(response, list, "巡检机器人数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检机器人详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检机器人详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionRobotService.selectInspectionRobotById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检机器人
|
||||
*/
|
||||
@ApiOperation("新增巡检机器人")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:add')")
|
||||
@Log(title = "巡检机器人", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionRobot inspectionRobot)
|
||||
{
|
||||
return toAjax(inspectionRobotService.insertInspectionRobot(inspectionRobot));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检机器人
|
||||
*/
|
||||
@ApiOperation("修改巡检机器人")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "巡检机器人", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionRobot inspectionRobot)
|
||||
{
|
||||
return toAjax(inspectionRobotService.updateInspectionRobot(inspectionRobot));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检机器人
|
||||
*/
|
||||
@ApiOperation("删除巡检机器人")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:remove')")
|
||||
@Log(title = "巡检机器人", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionRobotService.deleteInspectionRobotByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取机器人地图列表(从AGV获取)
|
||||
*/
|
||||
@ApiOperation("获取机器人地图列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:query')")
|
||||
@GetMapping("/{robotId}/maps")
|
||||
public AjaxResult getRobotMapList(@PathVariable String robotId)
|
||||
{
|
||||
List<String> robotMapList = inspectionRobotService.getRobotMapList(robotId);
|
||||
return success(robotMapList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定机器人地图
|
||||
*/
|
||||
@ApiOperation("绑定机器人地图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "绑定机器人地图", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/{robotId}/bind-map/{mapId}")
|
||||
public AjaxResult bindRobotMap(@PathVariable String robotId,
|
||||
@PathVariable String mapId)
|
||||
{
|
||||
return toAjax(inspectionRobotService.bindRobotMap(robotId, mapId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从机器人下载地图
|
||||
*/
|
||||
@ApiOperation("从机器人下载地图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:add')")
|
||||
@Log(title = "从机器人下载地图", businessType = BusinessType.INSERT)
|
||||
@GetMapping("/{robotId}/download-map")
|
||||
public AjaxResult downloadMapFromRobot(
|
||||
@PathVariable @ApiParam("机器人ID") String robotId,
|
||||
@RequestParam(value = "mapName") @ApiParam("地图名称") String mapName
|
||||
)
|
||||
{
|
||||
Object mapId = inspectionRobotService.downloadMapFromRobot(robotId, mapName);
|
||||
return success(mapId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传地图(从源机器人下载到目标机器人)
|
||||
*/
|
||||
@ApiOperation("上传地图到机器人")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "上传地图到机器人", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/{robotId}/upload-map-from-source")
|
||||
public AjaxResult uploadMapFromSource(@PathVariable String robotId)
|
||||
{
|
||||
String result = inspectionRobotService.uploadMapFromSource(robotId);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步机器人状态
|
||||
*/
|
||||
@ApiOperation("同步机器人状态")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "同步机器人状态", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/{robotId}/sync-status")
|
||||
public AjaxResult syncRobotStatus(@PathVariable String robotId)
|
||||
{
|
||||
return success(inspectionRobotService.syncRobotStatus(robotId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取机器人实时位置
|
||||
*/
|
||||
@ApiOperation("获取机器人实时位置")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:query')")
|
||||
@GetMapping("/{robotId}/location")
|
||||
public AjaxResult getRobotRealtimeLocation(@PathVariable String robotId)
|
||||
{
|
||||
Agv.AgvPose2d location = inspectionRobotService.getRobotRealtimeLocation(robotId);
|
||||
return success(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航到指定位置(坐标)
|
||||
*/
|
||||
@ApiOperation("导航到指定位置")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "导航到指定位置", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/{robotId}/navigate-to-position")
|
||||
public AjaxResult navigateToPosition(
|
||||
@PathVariable @ApiParam("机器人ID") String robotId,
|
||||
@RequestParam @ApiParam("X坐标(米)") Double x,
|
||||
@RequestParam @ApiParam("Y坐标(米)") Double y,
|
||||
@RequestParam(required = false) @ApiParam("朝向角(弧度)") Double theta
|
||||
)
|
||||
{
|
||||
inspectionRobotService.navigateToPosition(
|
||||
robotId, x, y, theta
|
||||
);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始建图
|
||||
*/
|
||||
@ApiOperation("开始建图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "开始建图", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/{robotId}/start-mapping")
|
||||
public AjaxResult startMapping(
|
||||
@PathVariable @ApiParam("机器人ID") String robotId,
|
||||
@RequestParam @ApiParam("建图维度(0:未指定 1:2D 2:3D 3:2D+3D)") int dimension,
|
||||
@RequestParam(required = false) @ApiParam("地图名称(可选)") String mapName,
|
||||
@RequestParam(defaultValue = "true") @ApiParam("是否实时建图") boolean realTime
|
||||
)
|
||||
{
|
||||
String sessionId = inspectionRobotService.startMapping(robotId, dimension, mapName, realTime);
|
||||
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
||||
result.put("sessionId", sessionId);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止建图
|
||||
*/
|
||||
@ApiOperation("停止建图")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:robot:edit')")
|
||||
@Log(title = "停止建图", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/{robotId}/stop-mapping")
|
||||
public AjaxResult stopMapping(@PathVariable @ApiParam("机器人ID") String robotId)
|
||||
{
|
||||
inspectionRobotService.stopMapping(robotId);
|
||||
return success();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionTask;
|
||||
import com.cmvr.inspection.domain.InspectionWaypoint;
|
||||
import com.cmvr.inspection.domain.vo.InspectionTaskVo;
|
||||
import com.cmvr.inspection.service.IInspectionTaskService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检任务Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-05-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/task")
|
||||
@Api(tags = "智能巡检--任务管理")
|
||||
public class InspectionTaskController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionTaskService inspectionTaskService;
|
||||
|
||||
/**
|
||||
* 查询巡检任务列表
|
||||
*/
|
||||
@ApiOperation("查询巡检任务列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionTask inspectionTask)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionTaskVo> list = inspectionTaskService.selectInspectionTaskList(inspectionTask);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检任务列表
|
||||
*/
|
||||
@ApiOperation("导出巡检任务列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:export')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionTask inspectionTask)
|
||||
{
|
||||
List<InspectionTaskVo> list = inspectionTaskService.selectInspectionTaskList(inspectionTask);
|
||||
ExcelUtil<InspectionTaskVo> util = new ExcelUtil<>(InspectionTaskVo.class);
|
||||
util.exportExcel(response, list, "巡检任务数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检任务详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检任务详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionTaskService.selectInspectionTaskById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检任务
|
||||
*/
|
||||
@ApiOperation("新增巡检任务")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:add')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionTask inspectionTask)
|
||||
{
|
||||
return toAjax(inspectionTaskService.insertInspectionTask(inspectionTask));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检任务
|
||||
*/
|
||||
@ApiOperation("修改巡检任务")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:edit')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionTask inspectionTask)
|
||||
{
|
||||
return toAjax(inspectionTaskService.updateInspectionTask(inspectionTask));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检任务
|
||||
*/
|
||||
@ApiOperation("删除巡检任务")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:remove')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionTaskService.deleteInspectionTaskByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务关联的点位列表
|
||||
*/
|
||||
@ApiOperation("查询任务关联的点位列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:query')")
|
||||
@GetMapping("/{taskId}/waypoints")
|
||||
public AjaxResult getWaypoints(@PathVariable("taskId") String taskId)
|
||||
{
|
||||
List<InspectionWaypoint> list = inspectionTaskService.selectWaypointsByTaskId(taskId);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定点位到任务
|
||||
*/
|
||||
@ApiOperation("绑定点位到任务")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:edit')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/{taskId}/waypoints")
|
||||
public AjaxResult bindWaypoints(@PathVariable("taskId") String taskId, @RequestBody String[] waypointIds)
|
||||
{
|
||||
return toAjax(inspectionTaskService.bindWaypoints(taskId, waypointIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑任务的点位
|
||||
*/
|
||||
@ApiOperation("解绑任务的点位")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:task:edit')")
|
||||
@Log(title = "巡检任务", businessType = BusinessType.UPDATE)
|
||||
@DeleteMapping("/{taskId}/waypoints")
|
||||
public AjaxResult unbindWaypoints(@PathVariable("taskId") String taskId)
|
||||
{
|
||||
return toAjax(inspectionTaskService.unbindWaypoints(taskId));
|
||||
}
|
||||
}
|
||||
@ -1,164 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.cmvr.inspection.domain.dto.InspectionTaskInstanceQuery;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionTaskInstance;
|
||||
import com.cmvr.inspection.domain.vo.InspectionTaskInstanceVo;
|
||||
import com.cmvr.inspection.service.IInspectionTaskInstanceService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检任务执行实例Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-01
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/taskInstance")
|
||||
@Api(tags = "智能巡检--任务执行实例管理")
|
||||
public class InspectionTaskInstanceController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionTaskInstanceService inspectionTaskInstanceService;
|
||||
|
||||
/**
|
||||
* 查询巡检任务执行实例列表
|
||||
*/
|
||||
@ApiOperation("查询巡检任务执行实例列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionTaskInstanceQuery inspectionTaskInstanceQuery)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionTaskInstanceVo> list = inspectionTaskInstanceService.selectInspectionTaskInstanceList(inspectionTaskInstanceQuery);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检任务执行实例列表
|
||||
*/
|
||||
@ApiOperation("导出巡检任务执行实例列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:export')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionTaskInstanceQuery inspectionTaskInstanceQuery)
|
||||
{
|
||||
List<InspectionTaskInstanceVo> list = inspectionTaskInstanceService.selectInspectionTaskInstanceList(inspectionTaskInstanceQuery);
|
||||
ExcelUtil<InspectionTaskInstanceVo> util = new ExcelUtil<>(InspectionTaskInstanceVo.class);
|
||||
util.exportExcel(response, list, "巡检任务执行实例数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检任务执行实例详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检任务执行实例详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionTaskInstanceService.selectInspectionTaskInstanceVoById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检任务执行实例
|
||||
*/
|
||||
@ApiOperation("新增巡检任务执行实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:add')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionTaskInstance inspectionTaskInstance)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.insertInspectionTaskInstance(inspectionTaskInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检任务执行实例
|
||||
*/
|
||||
@ApiOperation("修改巡检任务执行实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:edit')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionTaskInstance inspectionTaskInstance)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.updateInspectionTaskInstance(inspectionTaskInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检任务执行实例
|
||||
*/
|
||||
@ApiOperation("删除巡检任务执行实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:remove')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.deleteInspectionTaskInstanceByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行任务实例
|
||||
*/
|
||||
@ApiOperation("开始执行任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:edit')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/start/{id}")
|
||||
public AjaxResult start(@PathVariable("id") String id)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.startInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务实例
|
||||
*/
|
||||
@ApiOperation("暂停任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:edit')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/pause/{id}")
|
||||
public AjaxResult pause(@PathVariable("id") String id)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.pauseInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务实例
|
||||
*/
|
||||
@ApiOperation("终止任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:edit')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/stop/{id}")
|
||||
public AjaxResult stop(@PathVariable("id") String id)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.stopInstance(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务实例
|
||||
*/
|
||||
@ApiOperation("恢复任务实例")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:taskInstance:edit')")
|
||||
@Log(title = "巡检任务执行实例", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/resume/{id}")
|
||||
public AjaxResult resume(@PathVariable("id") String id)
|
||||
{
|
||||
return toAjax(inspectionTaskInstanceService.resumeInstance(id));
|
||||
}
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
import com.cmvr.inspection.domain.InspectionTaskLog;
|
||||
import com.cmvr.inspection.service.IInspectionTaskLogService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 巡检任务执行日志Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-05
|
||||
*/
|
||||
@Api(tags = "智能巡检-巡检任务执行日志管理")
|
||||
@RestController
|
||||
@RequestMapping("/inspection/taskLog")
|
||||
public class InspectionTaskLogController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionTaskLogService inspectionTaskLogService;
|
||||
|
||||
/**
|
||||
* 查询巡检任务执行日志列表
|
||||
*/
|
||||
@ApiOperation("查询巡检任务执行日志列表")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(@ApiParam("任务实例ID") @RequestParam String taskInstanceId) {
|
||||
List<InspectionTaskLog> list = inspectionTaskLogService.selectInspectionTaskLogList(taskInstanceId);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检任务执行日志详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检任务执行日志详细信息")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@ApiParam("日志ID") @PathVariable("id") String id) {
|
||||
return success(inspectionTaskLogService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检任务执行日志
|
||||
*/
|
||||
@ApiOperation("新增巡检任务执行日志")
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionTaskLog inspectionTaskLog) {
|
||||
return toAjax(inspectionTaskLogService.insertInspectionTaskLog(inspectionTaskLog));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增巡检任务执行日志
|
||||
*/
|
||||
@ApiOperation("批量新增巡检任务执行日志")
|
||||
@PostMapping("/batch")
|
||||
public AjaxResult batchAdd(@RequestBody List<InspectionTaskLog> logList) {
|
||||
return toAjax(inspectionTaskLogService.batchInsertInspectionTaskLog(logList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检任务执行日志
|
||||
*/
|
||||
@ApiOperation("修改巡检任务执行日志")
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionTaskLog inspectionTaskLog) {
|
||||
return toAjax(inspectionTaskLogService.updateById(inspectionTaskLog));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检任务执行日志
|
||||
*/
|
||||
@ApiOperation("删除巡检任务执行日志")
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@ApiParam("日志ID数组") @PathVariable String[] ids) {
|
||||
return toAjax(inspectionTaskLogService.removeByIds(java.util.Arrays.asList(ids)));
|
||||
}
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
package com.cmvr.web.controller.inspection;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.inspection.domain.InspectionWaypoint;
|
||||
import com.cmvr.inspection.domain.vo.InspectionWaypointVo;
|
||||
import com.cmvr.inspection.service.IInspectionWaypointService;
|
||||
import com.cmvr.common.utils.poi.ExcelUtil;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 巡检点位Controller
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-05-29
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/inspection/waypoint")
|
||||
@Api(tags = "智能巡检--点位管理")
|
||||
public class InspectionWaypointController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IInspectionWaypointService inspectionWaypointService;
|
||||
|
||||
/**
|
||||
* 查询巡检点位列表
|
||||
*/
|
||||
@ApiOperation("查询巡检点位列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InspectionWaypoint inspectionWaypoint)
|
||||
{
|
||||
startPage();
|
||||
List<InspectionWaypointVo> list = inspectionWaypointService.selectInspectionWaypointList(inspectionWaypoint);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出巡检点位列表
|
||||
*/
|
||||
@ApiOperation("导出巡检点位列表")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:export')")
|
||||
@Log(title = "巡检点位", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, InspectionWaypoint inspectionWaypoint)
|
||||
{
|
||||
List<InspectionWaypointVo> list = inspectionWaypointService.selectInspectionWaypointList(inspectionWaypoint);
|
||||
ExcelUtil<InspectionWaypointVo> util = new ExcelUtil<>(InspectionWaypointVo.class);
|
||||
util.exportExcel(response, list, "巡检点位数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取巡检点位详细信息
|
||||
*/
|
||||
@ApiOperation("获取巡检点位详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(inspectionWaypointService.selectInspectionWaypointById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增巡检点位
|
||||
*/
|
||||
@ApiOperation("新增巡检点位")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:add')")
|
||||
@Log(title = "巡检点位", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody InspectionWaypoint inspectionWaypoint)
|
||||
{
|
||||
return toAjax(inspectionWaypointService.insertInspectionWaypoint(inspectionWaypoint));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改巡检点位
|
||||
*/
|
||||
@ApiOperation("修改巡检点位")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:edit')")
|
||||
@Log(title = "巡检点位", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody InspectionWaypoint inspectionWaypoint)
|
||||
{
|
||||
return toAjax(inspectionWaypointService.updateInspectionWaypoint(inspectionWaypoint));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除巡检点位
|
||||
*/
|
||||
@ApiOperation("删除巡检点位")
|
||||
@PreAuthorize("@ss.hasPermi('inspection:waypoint:remove')")
|
||||
@Log(title = "巡检点位", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(inspectionWaypointService.deleteInspectionWaypointByIds(ids));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,12 +1,8 @@
|
||||
package com.cmvr.web.controller.test;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cmvr.common.annotation.Anonymous;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.llm.service.LLMAiAgentPlatformService;
|
||||
import com.cmvr.test.flow.context.TaskContextManager;
|
||||
import com.cmvr.test.flow.control.FlowControlService;
|
||||
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
|
||||
@ -30,15 +26,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@Api(tags = "测试--流程服务")
|
||||
@RestController
|
||||
@ -46,21 +36,6 @@ import java.util.concurrent.Future;
|
||||
@RequiredArgsConstructor
|
||||
public class TeFlowController extends BaseController {
|
||||
|
||||
/**
|
||||
* TTS 播放接口,当前按需求固定写死在 Controller 中。
|
||||
*/
|
||||
private static final String TTS_PLAY_URL = "http://localhost:8080/tts/play";
|
||||
|
||||
/**
|
||||
* TTS 停止接口,停止智能体输出时同步调用。
|
||||
*/
|
||||
private static final String TTS_STOP_URL = "http://localhost:8080/tts/stop";
|
||||
|
||||
/**
|
||||
* 商道智能体 AppKey,当前按需求固定写死,不放入配置文件。
|
||||
*/
|
||||
private static final String AI_AGENT_API_KEY = "d9etum54shheenol3apg";
|
||||
|
||||
private final ITeDetectionItemService teDetectionItemService;
|
||||
private final ITeNodeInstService nodeInstService;
|
||||
private final FlowTaskRuntimeService flowTaskRuntimeService;
|
||||
@ -68,38 +43,23 @@ public class TeFlowController extends BaseController {
|
||||
private final FlowControlService flowControlService;
|
||||
private final FlowActionExecutorService flowActionExecutorService;
|
||||
private final TiTouchOperateService tiTouchOperateService;
|
||||
private final LLMAiAgentPlatformService llmAiAgentPlatformService;
|
||||
private final List<String> taskInstIdList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 智能体调用是阻塞式 query,这里用单线程保存当前任务句柄,便于 stop 接口中断当前请求。
|
||||
*/
|
||||
private final ExecutorService aiAgentExecutor = Executors.newSingleThreadExecutor(runnable -> {
|
||||
Thread thread = new Thread(runnable, "flow-ai-agent-query");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
/**
|
||||
* 当前正在执行的智能体任务。当前接口按“同一时间只保留一个前端智能体调用”处理。
|
||||
*/
|
||||
private volatile Future<JSONObject> currentAiAgentFuture;
|
||||
|
||||
@ApiOperation("流程发布")
|
||||
@PostMapping("/publish")
|
||||
public AjaxResult publish(@RequestBody TeDetectionItem detectionItem) {
|
||||
return toAjax(teDetectionItemService.publish(detectionItem.getId()));
|
||||
}
|
||||
|
||||
@ApiOperation("演示任务执行入口")
|
||||
|
||||
@ApiOperation("任务执行入口")
|
||||
@PostMapping("/demo")
|
||||
@Anonymous
|
||||
public AjaxResult demo(@Valid @RequestBody TeTaskExecuteNormalVO taskExecuteNormalVO) {
|
||||
if (!taskInstIdList.isEmpty()) {
|
||||
if (taskInstIdList.size() > 0) {
|
||||
try {
|
||||
taskInstIdList.forEach(flowControlService::stop);
|
||||
} catch (Exception e) {
|
||||
// 演示入口清理旧任务失败时继续启动新任务,避免影响手动调试。
|
||||
// 忽略
|
||||
}
|
||||
taskInstIdList.clear();
|
||||
}
|
||||
@ -156,120 +116,15 @@ public class TeFlowController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/action")
|
||||
@ApiOperation(value = "单个节点执行",
|
||||
notes = "巡检仪表节点action=INSPECTION_METER_RECOGNIZE,payload使用InspectionMeterRecognizeConfigVO;"
|
||||
+ "人工判断节点action=INSPECTION_MANUAL_REVIEW_CREATE,payload使用InspectionManualReviewConfigVO。"
|
||||
+ "该接口用于试调节点,不会生成正式巡检任务结果")
|
||||
public AjaxResult actionExecute(
|
||||
@io.swagger.annotations.ApiParam(value = "单节点动作和参数", required = true)
|
||||
@RequestBody FlowActionRequestVO flowActionRequestVO) {
|
||||
@ApiOperation("单个节点执行")
|
||||
public AjaxResult actionExecute(@RequestBody FlowActionRequestVO flowActionRequestVO) {
|
||||
return AjaxResult.ok(flowActionExecutorService.actionExecute(flowActionRequestVO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用商道智能体平台。
|
||||
*
|
||||
* <p>前端只需要传入 text。后端固定 action、apiKey 和 TTS 参数。
|
||||
* 调用会放入可取消任务中,前端可以通过 /flow/llm/stop 停止当前调用并停止 TTS。</p>
|
||||
*/
|
||||
@GetMapping("/llm/query")
|
||||
@ApiOperation("调用商道智能体")
|
||||
public AjaxResult queryAiAgent(String text) {
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
return AjaxResult.error("text不能为空");
|
||||
}
|
||||
|
||||
stopCurrentAiAgentFuture(true);
|
||||
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("url", TTS_PLAY_URL);
|
||||
params.put("voice", "x4_yezi");
|
||||
params.put("speed", 45);
|
||||
params.put("volume", 100);
|
||||
|
||||
Future<JSONObject> future = aiAgentExecutor.submit(() -> llmAiAgentPlatformService.query(
|
||||
null,
|
||||
text.trim(),
|
||||
AI_AGENT_API_KEY,
|
||||
true,
|
||||
params
|
||||
));
|
||||
currentAiAgentFuture = future;
|
||||
|
||||
try {
|
||||
return AjaxResult.ok(future.get());
|
||||
} catch (CancellationException e) {
|
||||
return AjaxResult.error("智能体调用已停止");
|
||||
} catch (InterruptedException e) {
|
||||
future.cancel(true);
|
||||
Thread.currentThread().interrupt();
|
||||
return AjaxResult.error("智能体调用被中断");
|
||||
} catch (ExecutionException e) {
|
||||
Throwable cause = e.getCause() == null ? e : e.getCause();
|
||||
return AjaxResult.error("智能体调用失败:" + cause.getMessage());
|
||||
} finally {
|
||||
if (currentAiAgentFuture == future) {
|
||||
currentAiAgentFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止当前智能体调用,并通知 TTS 服务停止播放。
|
||||
*
|
||||
* <p>停止分两步:先取消当前 query 任务,触发底层 SSE 等待线程中断;
|
||||
* 再调用本地 TTS stop 接口,停止已经进入播放队列的音频。</p>
|
||||
*/
|
||||
@PostMapping("/llm/stop")
|
||||
@ApiOperation("停止商道智能体和TTS")
|
||||
public AjaxResult stopAiAgent() {
|
||||
stopCurrentAiAgentFuture(false);
|
||||
// String ttsStopResult = stopTts();
|
||||
return AjaxResult.ok("ok");
|
||||
}
|
||||
|
||||
@GetMapping("/testrun")
|
||||
@ApiOperation("测试接口")
|
||||
public AjaxResult testrun(@RequestParam("imageUrl") String imageUrl,
|
||||
@RequestParam("iconUrl") String iconUrl) {
|
||||
return AjaxResult.ok(tiTouchOperateService.test(imageUrl, iconUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消当前智能体任务。
|
||||
*
|
||||
* @param stopTts 是否同时停止 TTS 播放
|
||||
*/
|
||||
private void stopCurrentAiAgentFuture(boolean stopTts) {
|
||||
Future<JSONObject> future = currentAiAgentFuture;
|
||||
if (future != null && !future.isDone()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
currentAiAgentFuture = null;
|
||||
if (stopTts) {
|
||||
stopTts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用本地 TTS 停止接口。
|
||||
*/
|
||||
private String stopTts() {
|
||||
try (HttpResponse response = HttpRequest.post(TTS_STOP_URL)
|
||||
.timeout(3000)
|
||||
.execute()) {
|
||||
return response.body();
|
||||
} catch (Exception e) {
|
||||
return "调用TTS停止接口失败:" + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring 容器关闭时释放智能体执行线程。
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
stopCurrentAiAgentFuture(true);
|
||||
aiAgentExecutor.shutdownNow();
|
||||
return AjaxResult.ok(tiTouchOperateService.test(imageUrl,iconUrl));
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,14 @@
|
||||
package com.cmvr.web.controller.test;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.test.flow.control.FlowControlService;
|
||||
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
|
||||
import com.cmvr.test.flow.runtime.operator.edge.ti.TiTouchOperateService;
|
||||
import com.cmvr.test.model.vo.FlowiseActionRequestVO;
|
||||
import com.cmvr.test.model.vo.FlowiseChatRequestVO;
|
||||
import com.cmvr.test.model.vo.FlowiseStartRequestVO;
|
||||
import com.cmvr.test.model.vo.TeTaskExecuteNormalVO;
|
||||
import com.cmvr.test.service.FlowActionExecutorService;
|
||||
import com.cmvr.test.service.FlowiseActionService;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -24,9 +16,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "测试--flowise服务")
|
||||
@RestController
|
||||
@RequestMapping("/flowise")
|
||||
@ -34,37 +23,11 @@ import java.util.List;
|
||||
public class TeFlowiseController extends BaseController {
|
||||
|
||||
private final FlowiseActionService flowiseActionService;
|
||||
private final FlowTaskRuntimeService flowTaskRuntimeService;
|
||||
private final FlowControlService flowControlService;
|
||||
private final FlowActionExecutorService flowActionExecutorService;
|
||||
private final TiTouchOperateService tiTouchOperateService;
|
||||
private final List<String> taskInstIdList = new ArrayList<>();
|
||||
|
||||
@ApiOperation("调用flowise")
|
||||
@PostMapping("/start")
|
||||
public AjaxResult start(@RequestBody FlowiseStartRequestVO request) {
|
||||
JSONObject runParams = new JSONObject();
|
||||
|
||||
JSONObject runParams1 = new JSONObject();
|
||||
runParams1
|
||||
.put("test", request.getQuestion());
|
||||
runParams.put("5bb26d52e1861c6936f3c3149eaf17e8", runParams1);
|
||||
TeTaskExecuteNormalVO taskExecuteNormalVO = TeTaskExecuteNormalVO.builder()
|
||||
.taskId("b6ab5ffff783d9b25d0dc34f13be222d")
|
||||
.terminalId("4ed1246c465b97975f96c9ef8371a3bd")
|
||||
.runParams(JSONObject.from(runParams)).build();
|
||||
if (!taskInstIdList.isEmpty()) {
|
||||
try {
|
||||
taskInstIdList.forEach(flowControlService::stop);
|
||||
} catch (Exception e) {
|
||||
// 忽略
|
||||
}
|
||||
taskInstIdList.clear();
|
||||
}
|
||||
String insId = flowTaskRuntimeService.executeTask(taskExecuteNormalVO);
|
||||
taskInstIdList.add(insId);
|
||||
return AjaxResult.success();
|
||||
// return AjaxResult.ok(flowiseActionService.start(request));
|
||||
return AjaxResult.ok(flowiseActionService.start(request));
|
||||
}
|
||||
|
||||
@ApiOperation("根据chatId查询执行结果")
|
||||
@ -76,17 +39,7 @@ public class TeFlowiseController extends BaseController {
|
||||
@ApiOperation("终止flowise")
|
||||
@GetMapping("/abort")
|
||||
public AjaxResult abort() {
|
||||
if (!taskInstIdList.isEmpty()) {
|
||||
try {
|
||||
taskInstIdList.forEach(flowControlService::stop);
|
||||
} catch (Exception e) {
|
||||
// 忽略
|
||||
}
|
||||
taskInstIdList.clear();
|
||||
}
|
||||
logger.info("取消工作流");
|
||||
return AjaxResult.success();
|
||||
// return AjaxResult.ok(flowiseActionService.abort());
|
||||
return AjaxResult.ok(flowiseActionService.abort());
|
||||
}
|
||||
|
||||
@ApiOperation("执行指令")
|
||||
|
||||
@ -1,214 +0,0 @@
|
||||
package com.cmvr.web.controller.tts;
|
||||
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.tts.domain.CorpusCategory;
|
||||
import com.cmvr.tts.domain.CorpusInfo;
|
||||
import com.cmvr.tts.service.ICorpusInfoService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 车载语料数据Controller
|
||||
*
|
||||
* @author cmvr
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/tts/corpus")
|
||||
@Api(tags = "智能座舱-车载语料管理")
|
||||
public class CorpusInfoController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ICorpusInfoService corpusInfoService;
|
||||
|
||||
/**
|
||||
* 查询语料列表
|
||||
*/
|
||||
@ApiOperation("查询语料列表")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(CorpusInfo corpus) {
|
||||
startPage();
|
||||
return corpusInfoService.selectCorpusList(corpus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取语料详细信息
|
||||
*/
|
||||
@ApiOperation("获取语料详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(corpusInfoService.selectCorpusById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增语料
|
||||
*/
|
||||
@ApiOperation("新增语料")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:add')")
|
||||
@Log(title = "车载语料", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody CorpusInfo corpus) {
|
||||
return toAjax(corpusInfoService.insertCorpus(corpus));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改语料
|
||||
*/
|
||||
@ApiOperation("修改语料")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:edit')")
|
||||
@Log(title = "车载语料", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody CorpusInfo corpus) {
|
||||
return toAjax(corpusInfoService.updateCorpus(corpus));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除语料
|
||||
*/
|
||||
@ApiOperation("删除语料")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:remove')")
|
||||
@Log(title = "车载语料", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(corpusInfoService.deleteCorpusByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取音频流
|
||||
*/
|
||||
@ApiOperation("获取音频流")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/audio/{id}")
|
||||
public void getAudio(@PathVariable String id, HttpServletResponse response) {
|
||||
corpusInfoService.getAudioStream(id, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传语料音频
|
||||
*/
|
||||
@ApiOperation("上传语料音频")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:edit')")
|
||||
@Log(title = "车载语料", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/audio/upload/{id}")
|
||||
public AjaxResult uploadAudio(@PathVariable String id, @RequestParam("file") MultipartFile file) {
|
||||
String path = corpusInfoService.uploadCorpusAudio(id, file);
|
||||
return success(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入语料
|
||||
*/
|
||||
@ApiOperation("批量导入语料")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:import')")
|
||||
@Log(title = "车载语料", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/import")
|
||||
public AjaxResult importData(@RequestParam("file") MultipartFile file) {
|
||||
Map<String, Object> result = corpusInfoService.importCorpus(file);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询看板统计数据
|
||||
*/
|
||||
@ApiOperation("查询看板统计数据")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/dashboard/stats")
|
||||
public AjaxResult getDashboardStats() {
|
||||
return success(corpusInfoService.getDashboardStats());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按语种统计
|
||||
*/
|
||||
@ApiOperation("按语种统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/stats/language")
|
||||
public AjaxResult getStatsByLanguage() {
|
||||
return success(corpusInfoService.getStatsByLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按方言统计
|
||||
*/
|
||||
@ApiOperation("按方言统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/stats/dialect")
|
||||
public AjaxResult getStatsByDialect() {
|
||||
return success(corpusInfoService.getStatsByDialect());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按情绪统计
|
||||
*/
|
||||
@ApiOperation("按情绪统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/stats/emotion")
|
||||
public AjaxResult getStatsByEmotion() {
|
||||
return success(corpusInfoService.getStatsByEmotion());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按分类统计
|
||||
*/
|
||||
@ApiOperation("按分类统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/stats/category")
|
||||
public AjaxResult getStatsByCategory() {
|
||||
return success(corpusInfoService.getStatsByCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分类树
|
||||
*/
|
||||
@ApiOperation("查询分类树")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:query')")
|
||||
@GetMapping("/category/tree")
|
||||
public AjaxResult getCategoryTree() {
|
||||
return success(corpusInfoService.getCategoryTree());
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分类
|
||||
*/
|
||||
@ApiOperation("新增分类")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:add')")
|
||||
@Log(title = "语料分类", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/category")
|
||||
public AjaxResult addCategory(@RequestBody CorpusCategory category) {
|
||||
return toAjax(corpusInfoService.insertCategory(category));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分类
|
||||
*/
|
||||
@ApiOperation("修改分类")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:edit')")
|
||||
@Log(title = "语料分类", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/category")
|
||||
public AjaxResult editCategory(@RequestBody CorpusCategory category) {
|
||||
return toAjax(corpusInfoService.updateCategory(category));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
*/
|
||||
@ApiOperation("删除分类")
|
||||
@PreAuthorize("@ss.hasPermi('tts:corpus:remove')")
|
||||
@Log(title = "语料分类", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/category/{id}")
|
||||
public AjaxResult removeCategory(@PathVariable String id) {
|
||||
return toAjax(corpusInfoService.deleteCategoryById(id));
|
||||
}
|
||||
}
|
||||
@ -1,253 +0,0 @@
|
||||
package com.cmvr.web.controller.tts;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cmvr.common.annotation.Log;
|
||||
import com.cmvr.common.core.controller.BaseController;
|
||||
import com.cmvr.common.core.domain.AjaxResult;
|
||||
import com.cmvr.common.core.page.TableDataInfo;
|
||||
import com.cmvr.common.enums.BusinessType;
|
||||
import com.cmvr.llm.service.LLMAiAgentPlatformService;
|
||||
import com.cmvr.tts.domain.TtsSynthesizeTask;
|
||||
import com.cmvr.tts.domain.vo.LlmQueryVo;
|
||||
import com.cmvr.tts.service.ITtsSynthesizeTaskService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TTS合成任务Controller
|
||||
*
|
||||
* @author cmvr
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/tts/task")
|
||||
@Api(tags = "智能座舱-TTS合成任务管理")
|
||||
@RequiredArgsConstructor
|
||||
public class TtsSynthesizeTaskController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ITtsSynthesizeTaskService ttsTaskService;
|
||||
|
||||
private final LLMAiAgentPlatformService llmAiAgentPlatformService;
|
||||
|
||||
/**
|
||||
* 查询TTS合成任务列表
|
||||
*/
|
||||
@ApiOperation("查询TTS合成任务列表")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(TtsSynthesizeTask task) {
|
||||
startPage();
|
||||
return ttsTaskService.selectTtsTaskList(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取TTS合成任务详细信息
|
||||
*/
|
||||
@ApiOperation("获取TTS合成任务详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id) {
|
||||
return success(ttsTaskService.selectTtsTaskById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增TTS合成任务
|
||||
*/
|
||||
@ApiOperation("新增TTS合成任务")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:add')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody TtsSynthesizeTask task) {
|
||||
return success(ttsTaskService.insertTtsTask(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增TTS合成任务
|
||||
*/
|
||||
@ApiOperation("批量新增TTS合成任务")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:add')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/batch")
|
||||
public AjaxResult batchAdd(@RequestBody List<TtsSynthesizeTask> tasks) {
|
||||
return toAjax(ttsTaskService.batchInsertTtsTask(tasks));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改TTS合成任务
|
||||
*/
|
||||
@ApiOperation("修改TTS合成任务")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:edit')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody TtsSynthesizeTask task) {
|
||||
return toAjax(ttsTaskService.updateTtsTask(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除TTS合成任务
|
||||
*/
|
||||
@ApiOperation("删除TTS合成任务")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:remove')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable String[] ids) {
|
||||
return toAjax(ttsTaskService.deleteTtsTaskByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重生成TTS任务
|
||||
*/
|
||||
@ApiOperation("重生成TTS任务")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:edit')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/regenerate/{id}")
|
||||
public AjaxResult regenerate(@PathVariable String id) {
|
||||
return toAjax(ttsTaskService.regenerateTask(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取音频文件流
|
||||
*/
|
||||
@ApiOperation("获取音频文件流")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/audio/{id}")
|
||||
public void getAudio(@PathVariable String id, HttpServletResponse response) {
|
||||
ttsTaskService.getAudioStream(id, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询看板统计数据
|
||||
*/
|
||||
@ApiOperation("查询看板统计数据")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/dashboard/stats")
|
||||
public AjaxResult getDashboardStats() {
|
||||
return success(ttsTaskService.getDashboardStats());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按语种统计
|
||||
*/
|
||||
@ApiOperation("按语种统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/stats/language")
|
||||
public AjaxResult getStatsByLanguage() {
|
||||
return success(ttsTaskService.getStatsByLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按音色统计
|
||||
*/
|
||||
@ApiOperation("按音色统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/stats/voice")
|
||||
public AjaxResult getStatsByVoice() {
|
||||
return success(ttsTaskService.getStatsByVoice());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按情绪统计
|
||||
*/
|
||||
@ApiOperation("按情绪统计")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/stats/emotion")
|
||||
public AjaxResult getStatsByEmotion() {
|
||||
return success(ttsTaskService.getStatsByEmotion());
|
||||
}
|
||||
|
||||
/**
|
||||
* 近7日趋势
|
||||
*/
|
||||
@ApiOperation("近7日趋势")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@GetMapping("/stats/trend")
|
||||
public AjaxResult getLast7DaysTrend() {
|
||||
return success(ttsTaskService.getLast7DaysTrend());
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本泛化
|
||||
*/
|
||||
@ApiOperation("文本泛化")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:query')")
|
||||
@PostMapping("/llm/query")
|
||||
public AjaxResult llmQuery(@RequestBody LlmQueryVo request) {
|
||||
// 闲聊key d9672ql4shh4136opsfg
|
||||
// 泛化key d966pq54shh4nveh8d20
|
||||
JSONObject result = llmAiAgentPlatformService.query(
|
||||
null,
|
||||
request.getLanguage() + "," + request.getCount() + "," + request.getText(),
|
||||
"d96ammd4shh4nvehb6mg",
|
||||
false,
|
||||
null
|
||||
);
|
||||
|
||||
// 解析LLM返回的结果,提取JSON数组
|
||||
String resultStr = result.getString("result");
|
||||
if (resultStr != null && !resultStr.isEmpty()) {
|
||||
// 尝试多种格式解析
|
||||
JSONArray jsonArray = parseJsonArray(resultStr);
|
||||
return success(jsonArray);
|
||||
}
|
||||
return success(new JSONArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析JSON数组,兼容多种格式
|
||||
*/
|
||||
private JSONArray parseJsonArray(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return new JSONArray();
|
||||
}
|
||||
|
||||
// 1. 直接尝试解析为JSON数组
|
||||
try {
|
||||
return JSONArray.parseArray(text);
|
||||
} catch (Exception e) {
|
||||
// 继续尝试其他格式
|
||||
}
|
||||
|
||||
|
||||
// 2. 移除markdown代码块标记
|
||||
String cleaned = text.replace("```json", "").replace("```", "").trim();
|
||||
try {
|
||||
return JSONArray.parseArray(cleaned);
|
||||
} catch (Exception e) {
|
||||
// 继续尝试其他格式
|
||||
}
|
||||
|
||||
// 3. 尝试从文本中提取JSON数组(匹配 [...] 格式)
|
||||
int startIdx = text.indexOf("[");
|
||||
int endIdx = text.lastIndexOf("]");
|
||||
if (startIdx != -1 && endIdx != -1 && endIdx > startIdx) {
|
||||
String jsonStr = text.substring(startIdx, endIdx + 1);
|
||||
try {
|
||||
return JSONArray.parseArray(jsonStr);
|
||||
} catch (Exception e) {
|
||||
// 继续尝试其他格式
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 如果都失败,返回包含原始文本的数组
|
||||
return new JSONArray().fluentAdd(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存任务到语料库
|
||||
*/
|
||||
@ApiOperation("保存任务到语料库")
|
||||
@PreAuthorize("@ss.hasPermi('tts:task:edit')")
|
||||
@Log(title = "TTS合成任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/Nsave-to-corpus/{taskId}/{categoryId}")
|
||||
public AjaxResult saveToCorpus(@PathVariable String taskId, @PathVariable String categoryId) {
|
||||
return toAjax(ttsTaskService.saveToCorpus(taskId, categoryId));
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,6 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.cmvr.common.config.CmvrIotConfig;
|
||||
import com.cmvr.test.model.vo.inspection.InspectionAlarmRuleVO;
|
||||
import com.cmvr.test.model.vo.inspection.InspectionManualReviewConfigVO;
|
||||
import com.cmvr.test.model.vo.inspection.InspectionMediaVO;
|
||||
import com.cmvr.test.model.vo.inspection.InspectionMeterRecognizeConfigVO;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.models.auth.In;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
@ -39,10 +34,6 @@ public class SwaggerConfig
|
||||
@Autowired
|
||||
private CmvrIotConfig cmvrIotConfig;
|
||||
|
||||
/** 用于将动态工作流payload对应的参数模型显式加入Swagger文档。 */
|
||||
@Autowired
|
||||
private TypeResolver typeResolver;
|
||||
|
||||
/** 是否开启swagger */
|
||||
@Value("${swagger.enabled}")
|
||||
private boolean enabled;
|
||||
@ -71,12 +62,6 @@ public class SwaggerConfig
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
// 工作流单节点接口使用JSONObject作为payload,需显式注册巡检节点参数模型。
|
||||
.additionalModels(
|
||||
typeResolver.resolve(InspectionMeterRecognizeConfigVO.class),
|
||||
typeResolver.resolve(InspectionAlarmRuleVO.class),
|
||||
typeResolver.resolve(InspectionManualReviewConfigVO.class),
|
||||
typeResolver.resolve(InspectionMediaVO.class))
|
||||
/* 设置安全模式,swagger可以设置访问token */
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts())
|
||||
|
||||
@ -9,9 +9,9 @@ spring:
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://192.168.28.10:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: cmvr2468
|
||||
url: jdbc:mysql://192.168.0.100:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: cmvr-iot
|
||||
password: cmvr-iot123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
@ -70,7 +70,7 @@ spring:
|
||||
# redis 配置
|
||||
redis:
|
||||
# 地址
|
||||
host: 192.168.28.10
|
||||
host: 192.168.0.100
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
@ -92,7 +92,7 @@ spring:
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://192.168.28.10:9000
|
||||
url: http://192.168.0.100:9000
|
||||
accessKey: AKICMVR
|
||||
secretKey: wJalrXUtnFEMI
|
||||
bucketName: cmvr-iot
|
||||
@ -102,7 +102,7 @@ grpc:
|
||||
client:
|
||||
grpc-server: # 自定义服务名
|
||||
address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
# address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
# address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
enableKeepAlive: true
|
||||
keepAliveWithoutCalls: true
|
||||
negotiationType: plaintext # 明文传输
|
||||
@ -132,8 +132,3 @@ flowise:
|
||||
abort: http://192.168.0.108:3000/api/v1/chatmessage/abort/f99329e9-b33d-437d-90ed-69eaa8a05418/
|
||||
query: http://192.168.0.108:3000/api/v1/executions/
|
||||
api-key: pg61JW6W_GXyqmqSoURJ4mlSRrCMRzGLBJli_w3BFkg
|
||||
|
||||
# TTS外部接口配置
|
||||
tts:
|
||||
external-api:
|
||||
url: http://192.168.0.102:9003/generate_advanced_audio
|
||||
@ -1,134 +0,0 @@
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
port: 13080
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://192.168.0.100:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: cmvr-iot
|
||||
password: cmvr-iot123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置连接超时时间
|
||||
connectTimeout: 30000
|
||||
# 配置网络超时时间
|
||||
socketTimeout: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: cmvr-iot
|
||||
login-password: 123456
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
# 热部署开关
|
||||
enabled: true
|
||||
# redis 配置
|
||||
redis:
|
||||
# 地址
|
||||
host: 192.168.0.100
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password: cmvr2468
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池:中的最小空闲连接
|
||||
min-idle: 0
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 8
|
||||
# 连接池的最大数据库连接数
|
||||
max-active: 8
|
||||
# #连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1ms
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://192.168.0.100:9000
|
||||
accessKey: AKICMVR
|
||||
secretKey: wJalrXUtnFEMI
|
||||
bucketName: cmvr-iot
|
||||
|
||||
# gRPC 客户端设置
|
||||
grpc:
|
||||
client:
|
||||
grpc-server: # 自定义服务名
|
||||
address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
# address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
enableKeepAlive: true
|
||||
keepAliveWithoutCalls: true
|
||||
negotiationType: plaintext # 明文传输
|
||||
|
||||
api:
|
||||
app-id: d0epfibvo3em6c4iul40
|
||||
app-key: d0eqt1kqek3vg7g4ofi0
|
||||
work-flow-url: https://aiagentplatform.cmft.com/api/proxy/api/v1/run_app_workflow
|
||||
query-result-url: https://aiagentplatform.cmft.com/api/proxy/api/v1/query_run_app_process
|
||||
bge-vl: http://192.168.1.8:5000/search_similar
|
||||
generate_advanced_audio: http://192.168.0.102:9003/generate_advanced_audio
|
||||
# 智能体应用id和秘钥
|
||||
# ActionEnum 的枚举作为 key
|
||||
agents:
|
||||
INTENT_RECOGNITION: # 意图识别
|
||||
app-id: d5dn5ibp9adhq1b34lig
|
||||
app-key: d6j5bcellh49on5tasvg
|
||||
TI_TOUCH_COORDINATES: # 获取触控二维坐标
|
||||
app-id: d1ebtabnjkflk4gmhikg
|
||||
app-key: d5thge2cktmipk78h82g
|
||||
evaluation: http://192.168.0.8:8000/analyze
|
||||
current-page: http://192.168.0.222:5000/search_similar
|
||||
|
||||
flowise:
|
||||
tts: 192.168.0.222:8080/tts/
|
||||
start: http://192.168.0.108:3000/api/v1/prediction/f99329e9-b33d-437d-90ed-69eaa8a05418
|
||||
abort: http://192.168.0.108:3000/api/v1/chatmessage/abort/f99329e9-b33d-437d-90ed-69eaa8a05418/
|
||||
query: http://192.168.0.108:3000/api/v1/executions/
|
||||
api-key: pg61JW6W_GXyqmqSoURJ4mlSRrCMRzGLBJli_w3BFkg
|
||||
@ -9,9 +9,9 @@ spring:
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://192.168.28.10:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: cmvr2468
|
||||
url: jdbc:mysql://mysql57:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: cmvr-iot
|
||||
password: cmvr-iot123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
@ -70,7 +70,7 @@ spring:
|
||||
# redis 配置
|
||||
redis:
|
||||
# 地址
|
||||
host: 192.168.28.10
|
||||
host: redis
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
@ -92,7 +92,7 @@ spring:
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://192.168.28.10:9000
|
||||
url: http://minio:9000
|
||||
accessKey: AKICMVR
|
||||
secretKey: wJalrXUtnFEMI
|
||||
bucketName: cmvr-iot
|
||||
@ -128,7 +128,7 @@ api:
|
||||
|
||||
flowise:
|
||||
tts: 192.168.0.222:8080/tts/
|
||||
start: http://192.168.0.108:3000/api/v1/prediction/f99329e9-b33d-437d-90ed-69eaa8a05418
|
||||
abort: http://192.168.0.108:3000/api/v1/chatmessage/abort/f99329e9-b33d-437d-90ed-69eaa8a05418/
|
||||
start: http://192.168.0.108:3000/api/v1/prediction/86f01c9d-aaf4-495e-9530-d02e3172c807
|
||||
abort: http://192.168.0.108:3000/api/v1/chatmessage/abort/86f01c9d-aaf4-495e-9530-d02e3172c807/
|
||||
query: http://192.168.0.108:3000/api/v1/executions/
|
||||
api-key: pg61JW6W_GXyqmqSoURJ4mlSRrCMRzGLBJli_w3BFkg
|
||||
@ -1,134 +0,0 @@
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
port: 13080
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://mysql57:3306/cmvr-iot-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: cmvr-iot
|
||||
password: cmvr-iot123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置连接超时时间
|
||||
connectTimeout: 30000
|
||||
# 配置网络超时时间
|
||||
socketTimeout: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: cmvr-iot
|
||||
login-password: 123456
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
# 热部署开关
|
||||
enabled: true
|
||||
# redis 配置
|
||||
redis:
|
||||
# 地址
|
||||
host: redis
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password: cmvr2468
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池:中的最小空闲连接
|
||||
min-idle: 0
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 8
|
||||
# 连接池的最大数据库连接数
|
||||
max-active: 8
|
||||
# #连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1ms
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://minio:9000
|
||||
accessKey: AKICMVR
|
||||
secretKey: wJalrXUtnFEMI
|
||||
bucketName: cmvr-iot
|
||||
|
||||
# gRPC 客户端设置
|
||||
grpc:
|
||||
client:
|
||||
grpc-server: # 自定义服务名
|
||||
address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
# address: 'static://10.148.108.100:50051' # 调用 gRPC 的地址
|
||||
enableKeepAlive: true
|
||||
keepAliveWithoutCalls: true
|
||||
negotiationType: plaintext # 明文传输
|
||||
|
||||
api:
|
||||
app-id: d0epfibvo3em6c4iul40
|
||||
app-key: d0eqt1kqek3vg7g4ofi0
|
||||
work-flow-url: https://aiagentplatform.cmft.com/api/proxy/api/v1/run_app_workflow
|
||||
query-result-url: https://aiagentplatform.cmft.com/api/proxy/api/v1/query_run_app_process
|
||||
bge-vl: http://192.168.1.8:5000/search_similar
|
||||
generate_advanced_audio: http://192.168.0.102:9003/generate_advanced_audio
|
||||
# 智能体应用id和秘钥
|
||||
# ActionEnum 的枚举作为 key
|
||||
agents:
|
||||
INTENT_RECOGNITION: # 意图识别
|
||||
app-id: d5dn5ibp9adhq1b34lig
|
||||
app-key: d6j5bcellh49on5tasvg
|
||||
TI_TOUCH_COORDINATES: # 获取触控二维坐标
|
||||
app-id: d1ebtabnjkflk4gmhikg
|
||||
app-key: d5thge2cktmipk78h82g
|
||||
evaluation: http://192.168.0.8:8000/analyze
|
||||
current-page: http://192.168.0.222:5000/search_similar
|
||||
|
||||
flowise:
|
||||
tts: 192.168.0.222:8080/tts/
|
||||
start: http://192.168.0.108:3000/api/v1/prediction/86f01c9d-aaf4-495e-9530-d02e3172c807
|
||||
abort: http://192.168.0.108:3000/api/v1/chatmessage/abort/86f01c9d-aaf4-495e-9530-d02e3172c807/
|
||||
query: http://192.168.0.108:3000/api/v1/executions/
|
||||
api-key: pg61JW6W_GXyqmqSoURJ4mlSRrCMRzGLBJli_w3BFkg
|
||||
@ -92,7 +92,7 @@ spring:
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://192.168.28.10:9000
|
||||
url: http://192.168.10:9000
|
||||
accessKey: AKICMVR
|
||||
secretKey: wJalrXUtnFEMI
|
||||
bucketName: cmvr-iot
|
||||
|
||||
@ -21,9 +21,6 @@ server:
|
||||
tomcat:
|
||||
# tomcat的URI编码
|
||||
uri-encoding: UTF-8
|
||||
# PPE报警包含Base64图片,允许读取较大的JSON请求,同时限制异常请求的吞入大小
|
||||
max-http-form-post-size: 20MB
|
||||
max-swallow-size: 20MB
|
||||
# 连接数满后的排队数,默认为100
|
||||
accept-count: 1000
|
||||
threads:
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot</artifactId>
|
||||
<version>3.8.9</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>cmvr-iot-aima</artifactId>
|
||||
|
||||
<description>
|
||||
爱玛电动车测试模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 测试模块-->
|
||||
<dependency>
|
||||
<groupId>com.cmvr</groupId>
|
||||
<artifactId>cmvr-iot-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -1,144 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 爱玛告警实体。
|
||||
* <p>
|
||||
* 用于描述任务执行过程中产生的告警信息,包含任务、设备、车辆、用例、
|
||||
* 告警详情以及处理结果等数据。
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛告警管理")
|
||||
public class AimaAlarm extends BaseEntity
|
||||
{
|
||||
/** 序列化版本号。 */
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID。 */
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
/** 告警编码。 */
|
||||
@Excel(name = "告警编码")
|
||||
@ApiModelProperty("告警编码")
|
||||
private String alarmCode;
|
||||
|
||||
/** 任务执行实例ID。 */
|
||||
@Excel(name = "任务执行实例ID")
|
||||
@ApiModelProperty("任务执行实例ID")
|
||||
private String taskInstanceId;
|
||||
|
||||
/** 任务ID。 */
|
||||
@Excel(name = "任务ID")
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
|
||||
/** 任务名称。 */
|
||||
@Excel(name = "任务名称")
|
||||
@ApiModelProperty("任务名称")
|
||||
private String taskName;
|
||||
|
||||
/** 手机ID。 */
|
||||
@Excel(name = "手机ID")
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
/** 手机名称。 */
|
||||
@Excel(name = "手机名称")
|
||||
@ApiModelProperty("手机名称")
|
||||
private String phoneName;
|
||||
|
||||
/** 车辆ID。 */
|
||||
@Excel(name = "车辆ID")
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
/** 车辆车架号。 */
|
||||
@Excel(name = "车架号")
|
||||
@ApiModelProperty("车架号")
|
||||
private String vin;
|
||||
|
||||
/** 测试用例ID。 */
|
||||
@Excel(name = "测试用例ID")
|
||||
@ApiModelProperty("测试用例ID")
|
||||
private String testCaseId;
|
||||
|
||||
/** 测试用例名称。 */
|
||||
@Excel(name = "用例名称")
|
||||
@ApiModelProperty("用例名称")
|
||||
private String caseName;
|
||||
|
||||
/** 告警级别:1提示,2警告,3严重。 */
|
||||
@Excel(name = "告警级别")
|
||||
@ApiModelProperty("告警级别(1提示 2警告 3严重)")
|
||||
private String alarmLevel;
|
||||
|
||||
/** 告警类型:1设备异常,2测试异常,3通信异常,4性能异常。 */
|
||||
@Excel(name = "告警类型")
|
||||
@ApiModelProperty("告警类型(1设备异常 2测试异常 3通信异常 4性能异常)")
|
||||
private String alarmType;
|
||||
|
||||
/** 告警标题。 */
|
||||
@Excel(name = "告警标题")
|
||||
@ApiModelProperty("告警标题")
|
||||
private String alarmTitle;
|
||||
|
||||
/** 告警内容详情。 */
|
||||
@Excel(name = "告警内容")
|
||||
@ApiModelProperty("告警内容")
|
||||
private String alarmContent;
|
||||
|
||||
/** 告警发生位置或执行步骤。 */
|
||||
@Excel(name = "告警位置")
|
||||
@ApiModelProperty("告警位置/步骤")
|
||||
private String alarmLocation;
|
||||
|
||||
/** 告警发生时间。 */
|
||||
@Excel(name = "告警时间")
|
||||
@ApiModelProperty("告警时间")
|
||||
private Date alarmTime;
|
||||
|
||||
/** 处理状态:0未处理,1处理中,2已处理,3已忽略。 */
|
||||
@Excel(name = "处理状态")
|
||||
@ApiModelProperty("处理状态(0未处理 1处理中 2已处理 3已忽略)")
|
||||
private String handleStatus;
|
||||
|
||||
/** 告警处理人。 */
|
||||
@Excel(name = "处理人")
|
||||
@ApiModelProperty("处理人")
|
||||
private String handler;
|
||||
|
||||
/** 告警处理时间。 */
|
||||
@Excel(name = "处理时间")
|
||||
@ApiModelProperty("处理时间")
|
||||
private Date handleTime;
|
||||
|
||||
/** 处理说明或备注。 */
|
||||
@Excel(name = "处理说明")
|
||||
@ApiModelProperty("处理说明")
|
||||
private String handleRemark;
|
||||
|
||||
/** 告警相关图片证据。 */
|
||||
@ApiModelProperty("图片证据")
|
||||
private String evidenceImage;
|
||||
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 爱玛手机管理对象 aima_phone
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛手机管理")
|
||||
public class AimaPhone extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 手机名称
|
||||
*/
|
||||
@Excel(name = "手机名称")
|
||||
@ApiModelProperty("手机名称")
|
||||
private String phoneName;
|
||||
|
||||
/**
|
||||
* 手机型号
|
||||
*/
|
||||
@Excel(name = "手机型号")
|
||||
@ApiModelProperty("手机型号")
|
||||
private String phoneModel;
|
||||
|
||||
/**
|
||||
* 操作系统(Android/iOS)
|
||||
*/
|
||||
@Excel(name = "操作系统")
|
||||
@ApiModelProperty("操作系统(Android/iOS)")
|
||||
private String osSystem;
|
||||
|
||||
/**
|
||||
* 系统版本
|
||||
*/
|
||||
@Excel(name = "系统版本")
|
||||
@ApiModelProperty("系统版本")
|
||||
private String osVersion;
|
||||
|
||||
/**
|
||||
* 规格参数
|
||||
*/
|
||||
@Excel(name = "规格参数")
|
||||
@ApiModelProperty("规格参数")
|
||||
private String specifications;
|
||||
|
||||
/**
|
||||
* 厂商
|
||||
*/
|
||||
@Excel(name = "厂商")
|
||||
@ApiModelProperty("厂商")
|
||||
private String manufacturer;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
@Excel(name = "状态")
|
||||
@ApiModelProperty("状态(0正常 1停用)")
|
||||
private String status;
|
||||
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 爱玛任务管理对象 aima_task
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛任务管理")
|
||||
public class AimaTask extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "任务编码")
|
||||
@ApiModelProperty("任务编码")
|
||||
private String taskCode;
|
||||
|
||||
@Excel(name = "任务名称")
|
||||
@ApiModelProperty("任务名称")
|
||||
private String taskName;
|
||||
|
||||
@Excel(name = "任务类型")
|
||||
@ApiModelProperty("任务类型(1常规测试 2回归测试 3专项测试)")
|
||||
private String taskType;
|
||||
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
@Excel(name = "测试用例数量")
|
||||
@ApiModelProperty("测试用例数量")
|
||||
private Integer testCaseCount;
|
||||
|
||||
/** 任务配置id(关联test模块) */
|
||||
@ApiModelProperty("任务配置id")
|
||||
private String taskConfigId;
|
||||
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 爱玛任务执行实例对象 aima_task_instance
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛任务执行实例")
|
||||
public class AimaTaskInstance extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "任务ID")
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
|
||||
@Excel(name = "手机ID")
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
@Excel(name = "车辆ID")
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
@Excel(name = "第几次执行")
|
||||
@ApiModelProperty("第几次执行")
|
||||
private Integer executionNumber;
|
||||
|
||||
@Excel(name = "执行状态")
|
||||
@ApiModelProperty("执行状态(0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停)")
|
||||
private Integer status;
|
||||
|
||||
/** 流程实例id(关联test模块) */
|
||||
@ApiModelProperty("流程实例id")
|
||||
private String taskInsId;
|
||||
|
||||
@Excel(name = "总用例数")
|
||||
@ApiModelProperty("总用例数")
|
||||
private Integer totalCases;
|
||||
|
||||
@Excel(name = "已完成用例数")
|
||||
@ApiModelProperty("已完成用例数")
|
||||
private Integer completedCases;
|
||||
|
||||
@Excel(name = "通过用例数")
|
||||
@ApiModelProperty("通过用例数")
|
||||
private Integer passedCases;
|
||||
|
||||
@Excel(name = "失败用例数")
|
||||
@ApiModelProperty("失败用例数")
|
||||
private Integer failedCases;
|
||||
|
||||
@Excel(name = "执行进度")
|
||||
@ApiModelProperty("执行进度(百分比,保留2位小数)")
|
||||
private Double progress;
|
||||
|
||||
@Excel(name = "开始时间")
|
||||
@ApiModelProperty("开始时间")
|
||||
private Date startTime;
|
||||
|
||||
@Excel(name = "结束时间")
|
||||
@ApiModelProperty("结束时间")
|
||||
private Date endTime;
|
||||
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 爱玛任务与测试用例关联对象 aima_task_test_case
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AimaTaskTestCase
|
||||
{
|
||||
/** 任务ID */
|
||||
private String taskId;
|
||||
|
||||
/** 测试用例ID */
|
||||
private String testCaseId;
|
||||
|
||||
/** 排序号 */
|
||||
private Integer sortOrder;
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 爱玛测试用例对象 aima_test_case
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
@ApiModel("爱玛测试用例")
|
||||
public class AimaTestCase extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "用例编码")
|
||||
@ApiModelProperty("用例编码")
|
||||
private String caseCode;
|
||||
|
||||
@Excel(name = "用例名称")
|
||||
@ApiModelProperty("用例名称")
|
||||
private String caseName;
|
||||
|
||||
@Excel(name = "用例分类")
|
||||
@ApiModelProperty("用例分类(功能测试/性能测试/安全测试等)")
|
||||
private String caseCategory;
|
||||
|
||||
@Excel(name = "测试描述")
|
||||
@ApiModelProperty("测试描述")
|
||||
private String testDescription;
|
||||
|
||||
@Excel(name = "前置条件")
|
||||
@ApiModelProperty("前置条件")
|
||||
private String precondition;
|
||||
|
||||
@Excel(name = "测试步骤")
|
||||
@ApiModelProperty("测试步骤")
|
||||
private String testSteps;
|
||||
|
||||
@Excel(name = "预期结果")
|
||||
@ApiModelProperty("预期结果")
|
||||
private String expectedResult;
|
||||
|
||||
@Excel(name = "优先级")
|
||||
@ApiModelProperty("优先级(1高 2中 3低)")
|
||||
private String priority;
|
||||
|
||||
@Excel(name = "是否启用")
|
||||
@ApiModelProperty("是否启用(0启用 1禁用)")
|
||||
private String enabled;
|
||||
|
||||
@Excel(name = "排序号")
|
||||
@ApiModelProperty("排序号")
|
||||
private Integer sortOrder;
|
||||
|
||||
@Excel(name = "预计执行时长")
|
||||
@ApiModelProperty("预计执行时长(秒)")
|
||||
private Integer estimatedDuration;
|
||||
|
||||
/** 检测项配置id(关联test模块) */
|
||||
@ApiModelProperty("检测项配置id")
|
||||
private String detectItemId;
|
||||
|
||||
}
|
||||
@ -1,102 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 爱玛测试日志对象 aima_test_log
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛测试日志")
|
||||
@Builder
|
||||
public class AimaTestLog extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "任务执行实例ID")
|
||||
@ApiModelProperty("任务执行实例ID")
|
||||
private String taskInstanceId;
|
||||
|
||||
@Excel(name = "任务ID")
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
|
||||
@Excel(name = "任务名称")
|
||||
@ApiModelProperty("任务名称")
|
||||
private String taskName;
|
||||
|
||||
@Excel(name = "测试用例ID")
|
||||
@ApiModelProperty("测试用例ID")
|
||||
private String testCaseId;
|
||||
|
||||
@Excel(name = "用例名称")
|
||||
@ApiModelProperty("用例名称")
|
||||
private String caseName;
|
||||
|
||||
@Excel(name = "日志级别")
|
||||
@ApiModelProperty("日志级别(DEBUG/INFO/WARN/ERROR)")
|
||||
private String logLevel;
|
||||
|
||||
@Excel(name = "日志类型")
|
||||
@ApiModelProperty("日志类型(执行日志/系统日志/异常日志)")
|
||||
private String logType;
|
||||
|
||||
@Excel(name = "日志内容")
|
||||
@ApiModelProperty("日志内容")
|
||||
private String logContent;
|
||||
|
||||
@Excel(name = "日志时间")
|
||||
@ApiModelProperty("日志时间")
|
||||
private Date logTime;
|
||||
|
||||
@Excel(name = "执行步骤")
|
||||
@ApiModelProperty("执行步骤")
|
||||
private String executionStep;
|
||||
|
||||
@Excel(name = "实际结果")
|
||||
@ApiModelProperty("实际结果")
|
||||
private String actualResult;
|
||||
|
||||
@Excel(name = "测试结果")
|
||||
@ApiModelProperty("测试结果(0未执行 1通过 2失败 3跳过)")
|
||||
private String testStatus;
|
||||
|
||||
@ApiModelProperty("截图URL")
|
||||
private String screenshotUrl;
|
||||
|
||||
@ApiModelProperty("视频URL")
|
||||
private String videoUrl;
|
||||
|
||||
@ApiModelProperty("错误堆栈")
|
||||
private String errorStack;
|
||||
|
||||
@Excel(name = "执行耗时")
|
||||
@ApiModelProperty("执行耗时(毫秒)")
|
||||
private Long durationMs;
|
||||
|
||||
@Excel(name = "进度")
|
||||
@ApiModelProperty("执行进度(百分比)")
|
||||
private Double progress;
|
||||
|
||||
@Excel(name = "状态")
|
||||
@ApiModelProperty("执行状态(0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停)")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package com.cmvr.aima.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 爱玛车辆管理对象 aima_vehicle
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛车辆管理")
|
||||
public class AimaVehicle extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
@Excel(name = "车架号")
|
||||
@ApiModelProperty("车架号(VIN)")
|
||||
private String vin;
|
||||
|
||||
@Excel(name = "车型")
|
||||
@ApiModelProperty("车型")
|
||||
private String vehicleModel;
|
||||
|
||||
@Excel(name = "车辆名称")
|
||||
@ApiModelProperty("车辆名称")
|
||||
private String vehicleName;
|
||||
|
||||
@Excel(name = "颜色")
|
||||
@ApiModelProperty("颜色")
|
||||
private String color;
|
||||
|
||||
@Excel(name = "生产日期")
|
||||
@ApiModelProperty("生产日期")
|
||||
private Date productionDate;
|
||||
|
||||
@Excel(name = "状态")
|
||||
@ApiModelProperty("状态(0正常 1停用)")
|
||||
private String status;
|
||||
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package com.cmvr.aima.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 爱玛任务实例查询入参DTO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("爱玛任务实例查询条件")
|
||||
public class AimaTaskInstanceQuery {
|
||||
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
@ApiModelProperty("单个状态(兼容原有精确查询)")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("多状态集合,in查询用:0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停")
|
||||
private List<Integer> statusList;
|
||||
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
package com.cmvr.aima.domain.vo;
|
||||
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 爱玛任务执行实例视图对象(包含关联信息)
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛任务执行实例视图对象")
|
||||
public class
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AimaTaskInstanceVo extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** id */
|
||||
@ApiModelProperty("id")
|
||||
private String id;
|
||||
|
||||
/** 任务ID */
|
||||
@Excel(name = "任务ID")
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
|
||||
/** 任务名称 */
|
||||
@Excel(name = "任务名称")
|
||||
@ApiModelProperty("任务名称")
|
||||
private String taskName;
|
||||
|
||||
/** 任务编码 */
|
||||
@Excel(name = "任务编码")
|
||||
@ApiModelProperty("任务编码")
|
||||
private String taskCode;
|
||||
|
||||
/** 手机ID */
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
/** 手机名称 */
|
||||
@Excel(name = "手机名称")
|
||||
@ApiModelProperty("手机名称")
|
||||
private String phoneName;
|
||||
|
||||
/** 车辆ID */
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
/** 车辆名称 */
|
||||
@Excel(name = "车辆名称")
|
||||
@ApiModelProperty("车辆名称")
|
||||
private String vehicleName;
|
||||
|
||||
/** 车架号 */
|
||||
@Excel(name = "车架号")
|
||||
@ApiModelProperty("车架号")
|
||||
private String vin;
|
||||
|
||||
/** 第几次执行 */
|
||||
@Excel(name = "执行次数")
|
||||
@ApiModelProperty("第几次执行")
|
||||
private Integer executionNumber;
|
||||
|
||||
/** 执行状态 */
|
||||
@Excel(name = "执行状态")
|
||||
@ApiModelProperty("执行状态(0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停)")
|
||||
private Integer status;
|
||||
|
||||
/** 流程实例id */
|
||||
@ApiModelProperty("流程实例id")
|
||||
private String taskInsId;
|
||||
|
||||
/** 总用例数 */
|
||||
@Excel(name = "总用例数")
|
||||
@ApiModelProperty("总用例数")
|
||||
private Integer totalCases;
|
||||
|
||||
/** 已完成用例数 */
|
||||
@Excel(name = "已完成")
|
||||
@ApiModelProperty("已完成用例数")
|
||||
private Integer completedCases;
|
||||
|
||||
/** 通过用例数 */
|
||||
@Excel(name = "通过数")
|
||||
@ApiModelProperty("通过用例数")
|
||||
private Integer passedCases;
|
||||
|
||||
/** 失败用例数 */
|
||||
@Excel(name = "失败数")
|
||||
@ApiModelProperty("失败用例数")
|
||||
private Integer failedCases;
|
||||
|
||||
/** 执行进度 */
|
||||
@Excel(name = "执行进度")
|
||||
@ApiModelProperty("执行进度(百分比,保留2位小数)")
|
||||
private Double progress;
|
||||
|
||||
/** 开始时间 */
|
||||
@Excel(name = "开始时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("开始时间")
|
||||
private Date startTime;
|
||||
|
||||
/** 结束时间 */
|
||||
@Excel(name = "结束时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("结束时间")
|
||||
private Date endTime;
|
||||
|
||||
/** 创建人昵称 */
|
||||
@Excel(name = "创建人昵称")
|
||||
@ApiModelProperty("创建人昵称")
|
||||
private String createByName;
|
||||
|
||||
/** 修改人昵称 */
|
||||
@Excel(name = "修改人昵称")
|
||||
@ApiModelProperty("修改人昵称")
|
||||
private String updateByName;
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
package com.cmvr.aima.domain.vo;
|
||||
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 爱玛任务视图对象(包含关联信息)
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛任务视图对象")
|
||||
public class AimaTaskVo extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** id */
|
||||
@ApiModelProperty("id")
|
||||
private String id;
|
||||
|
||||
/** 任务编码 */
|
||||
@Excel(name = "任务编码")
|
||||
@ApiModelProperty("任务编码")
|
||||
private String taskCode;
|
||||
|
||||
/** 任务名称 */
|
||||
@Excel(name = "任务名称")
|
||||
@ApiModelProperty("任务名称")
|
||||
private String taskName;
|
||||
|
||||
/** 任务类型 */
|
||||
@Excel(name = "任务类型")
|
||||
@ApiModelProperty("任务类型(1常规测试 2回归测试 3专项测试)")
|
||||
private String taskType;
|
||||
|
||||
/** 手机ID */
|
||||
@ApiModelProperty("手机ID")
|
||||
private String phoneId;
|
||||
|
||||
/** 手机名称 */
|
||||
@Excel(name = "手机名称")
|
||||
@ApiModelProperty("手机名称")
|
||||
private String phoneName;
|
||||
|
||||
/** 车辆ID */
|
||||
@ApiModelProperty("车辆ID")
|
||||
private String vehicleId;
|
||||
|
||||
/** 测试用例数量 */
|
||||
@Excel(name = "测试用例数量")
|
||||
@ApiModelProperty("测试用例数量")
|
||||
private Integer testCaseCount;
|
||||
|
||||
/** 任务配置id */
|
||||
@ApiModelProperty("任务配置id")
|
||||
private String taskConfigId;
|
||||
|
||||
/** 创建人昵称 */
|
||||
@Excel(name = "创建人昵称")
|
||||
@ApiModelProperty("创建人昵称")
|
||||
private String createByName;
|
||||
|
||||
/** 修改人昵称 */
|
||||
@Excel(name = "修改人昵称")
|
||||
@ApiModelProperty("修改人昵称")
|
||||
private String updateByName;
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
package com.cmvr.aima.domain.vo;
|
||||
|
||||
import com.cmvr.common.annotation.Excel;
|
||||
import com.cmvr.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 爱玛测试用例视图对象(包含关联信息)
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("爱玛测试用例视图对象")
|
||||
public class AimaTestCaseVo extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** id */
|
||||
@ApiModelProperty("id")
|
||||
private String id;
|
||||
|
||||
/** 用例编码 */
|
||||
@Excel(name = "用例编码")
|
||||
@ApiModelProperty("用例编码")
|
||||
private String caseCode;
|
||||
|
||||
/** 用例名称 */
|
||||
@Excel(name = "用例名称")
|
||||
@ApiModelProperty("用例名称")
|
||||
private String caseName;
|
||||
|
||||
/** 用例分类 */
|
||||
@Excel(name = "用例分类")
|
||||
@ApiModelProperty("用例分类(功能测试/性能测试/安全测试等)")
|
||||
private String caseCategory;
|
||||
|
||||
/** 测试描述 */
|
||||
@ApiModelProperty("测试描述")
|
||||
private String testDescription;
|
||||
|
||||
/** 前置条件 */
|
||||
@ApiModelProperty("前置条件")
|
||||
private String precondition;
|
||||
|
||||
/** 测试步骤 */
|
||||
@ApiModelProperty("测试步骤")
|
||||
private String testSteps;
|
||||
|
||||
/** 预期结果 */
|
||||
@ApiModelProperty("预期结果")
|
||||
private String expectedResult;
|
||||
|
||||
/** 优先级 */
|
||||
@Excel(name = "优先级")
|
||||
@ApiModelProperty("优先级(1高 2中 3低)")
|
||||
private String priority;
|
||||
|
||||
/** 是否启用 */
|
||||
@Excel(name = "是否启用")
|
||||
@ApiModelProperty("是否启用(0启用 1禁用)")
|
||||
private String enabled;
|
||||
|
||||
/** 排序号 */
|
||||
@Excel(name = "排序号")
|
||||
@ApiModelProperty("排序号")
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 预计执行时长 */
|
||||
@Excel(name = "预计执行时长")
|
||||
@ApiModelProperty("预计执行时长(秒)")
|
||||
private Integer estimatedDuration;
|
||||
|
||||
/** 检测项配置id */
|
||||
@ApiModelProperty("检测项配置id")
|
||||
private String detectItemId;
|
||||
|
||||
/** 配置状态 */
|
||||
@Excel(name = "配置状态")
|
||||
@ApiModelProperty("配置状态(0未部署 1已部署)")
|
||||
private String configStatus;
|
||||
|
||||
/** 创建人昵称 */
|
||||
@Excel(name = "创建人昵称")
|
||||
@ApiModelProperty("创建人昵称")
|
||||
private String createByName;
|
||||
|
||||
/** 修改人昵称 */
|
||||
@Excel(name = "修改人昵称")
|
||||
@ApiModelProperty("修改人昵称")
|
||||
private String updateByName;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.cmvr.aima.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 爱玛测试日志类型枚举
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AimaLogTypeEnum {
|
||||
TEXT(1, "文字"),
|
||||
IMAGE(2, "图片"),
|
||||
VIDEO(3, "视频"),
|
||||
AUDIO(4, "音频");
|
||||
|
||||
private final int code;
|
||||
private final String desc;
|
||||
|
||||
public static AimaLogTypeEnum fromCode(int code) {
|
||||
for (AimaLogTypeEnum type : values()) {
|
||||
if (type.code == code) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package com.cmvr.aima.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 爱玛任务状态枚举
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AimaTaskStatusEnum {
|
||||
// 未执行
|
||||
NOT_STARTED(5, "未执行"),
|
||||
SUCCESS(0, "已完成"),
|
||||
RUNNING(1, "执行中"),
|
||||
FAILED(2, "失败"),
|
||||
PAUSED(3, "已暂停"),
|
||||
STOPPED(4, "已终止");
|
||||
|
||||
private final int code;
|
||||
private final String desc;
|
||||
|
||||
public static AimaTaskStatusEnum fromCode(int code) {
|
||||
for (AimaTaskStatusEnum status : values()) {
|
||||
if (status.code == code) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,206 +0,0 @@
|
||||
package com.cmvr.aima.listener;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.framework.websocket.service.MessagePushService;
|
||||
import com.cmvr.aima.domain.AimaTaskInstance;
|
||||
import com.cmvr.aima.domain.AimaTestLog;
|
||||
import com.cmvr.aima.enums.AimaTaskStatusEnum;
|
||||
import com.cmvr.aima.service.IAimaTaskInstanceService;
|
||||
import com.cmvr.aima.service.IAimaTestLogService;
|
||||
import com.cmvr.test.flow.runtime.event.FlowExecutionEvent;
|
||||
import com.cmvr.test.flow.runtime.event.FlowExecutionListener;
|
||||
import com.cmvr.test.flow.runtime.event.FlowExecutionModuleCodes;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 爱玛测试工作流执行监听器
|
||||
* 监听流程引擎事件,自动记录测试日志和更新任务状态
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AimaFlowExecutionListener implements FlowExecutionListener {
|
||||
private final IAimaTaskInstanceService aimaTaskInstanceService;
|
||||
private final IAimaTestLogService aimaTestLogService;
|
||||
private final MessagePushService messagePushService;
|
||||
|
||||
/** key:itemId, value:已完成节点集合 */
|
||||
private final Map<String, Set<String>> itemNodeExecutMap = new HashMap<>();
|
||||
/** key:taskInsId(流程实例id), value:已执行item集合 */
|
||||
private final Map<String, Set<String>> taskItemExecutMap = new HashMap<>();
|
||||
|
||||
public AimaFlowExecutionListener(IAimaTaskInstanceService aimaTaskInstanceService,
|
||||
IAimaTestLogService aimaTestLogService,
|
||||
MessagePushService messagePushService) {
|
||||
this.aimaTaskInstanceService = aimaTaskInstanceService;
|
||||
this.aimaTestLogService = aimaTestLogService;
|
||||
this.messagePushService = messagePushService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModuleCode() {
|
||||
return FlowExecutionModuleCodes.AIMA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(FlowExecutionEvent event) {
|
||||
String instId = event.getInstId();
|
||||
String itemId = event.getItemId();
|
||||
String nodeId = event.getNodeId();
|
||||
if (StrUtil.isBlank(instId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1.节点完成才记录当前item下node
|
||||
if (StrUtil.isNotBlank(itemId) && StrUtil.isNotBlank(nodeId)
|
||||
&& FlowExecutionEvent.EventType.NODE_COMPLETED == event.getEventType()) {
|
||||
itemNodeExecutMap.computeIfAbsent(itemId, k -> new HashSet<>()).add(nodeId);
|
||||
}
|
||||
// 任意事件:当前任务绑定item(item一启动就入Map)
|
||||
if (StrUtil.isNotBlank(instId) && StrUtil.isNotBlank(itemId)) {
|
||||
taskItemExecutMap.computeIfAbsent(instId, k -> new HashSet<>()).add(itemId);
|
||||
}
|
||||
|
||||
// 查询任务实例
|
||||
AimaTaskInstance taskInstance = aimaTaskInstanceService.lambdaQuery()
|
||||
.eq(AimaTaskInstance::getTaskInsId, instId)
|
||||
.one();
|
||||
if (taskInstance == null) {
|
||||
log.warn("未查询到爱玛测试实例,taskInsId:{}", instId);
|
||||
return;
|
||||
}
|
||||
|
||||
int targetStatus = AimaTaskStatusEnum.RUNNING.getCode();
|
||||
boolean needUpdateDb = false;
|
||||
Date now = DateUtils.getNowDate();
|
||||
|
||||
switch (event.getEventType()) {
|
||||
case TASK_COMPLETED:
|
||||
targetStatus = AimaTaskStatusEnum.SUCCESS.getCode();
|
||||
needUpdateDb = true;
|
||||
clearCache(instId);
|
||||
pushCompleteMsg(taskInstance.getId(), now, targetStatus);
|
||||
break;
|
||||
case TASK_FAILED:
|
||||
targetStatus = AimaTaskStatusEnum.FAILED.getCode();
|
||||
needUpdateDb = true;
|
||||
clearCache(instId);
|
||||
break;
|
||||
case NODE_COMPLETED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (needUpdateDb) {
|
||||
taskInstance.setStatus(targetStatus);
|
||||
taskInstance.setEndTime(now);
|
||||
aimaTaskInstanceService.updateById(taskInstance);
|
||||
}
|
||||
|
||||
// 节点推送 - 记录日志
|
||||
if (StrUtil.isNotBlank(nodeId)) {
|
||||
int totalCases = taskInstance.getTotalCases() == null ? 0 : taskInstance.getTotalCases();
|
||||
double progress = 0D;
|
||||
if (totalCases > 0) {
|
||||
// 当前任务已执行item数量
|
||||
Set<String> itemSet = taskItemExecutMap.getOrDefault(instId, new HashSet<>());
|
||||
int itemTotal = itemSet.size();
|
||||
int finishedItemNum = itemTotal - 1;
|
||||
|
||||
// 当前item已完成节点数
|
||||
Set<String> finishedNodeSet = itemNodeExecutMap.getOrDefault(itemId, new HashSet<>());
|
||||
int finishedNode = finishedNodeSet.size();
|
||||
int totalNode = event.getNodeCount() == 0 ? 1 : event.getNodeCount();
|
||||
|
||||
// 已完整跑完用例占比
|
||||
double itemTotalRatio = finishedItemNum / (double) totalCases;
|
||||
// 当前运行item内部节点占比
|
||||
double innerRatio = finishedNode / (double) totalNode / totalCases;
|
||||
|
||||
// 防止循环节点进度超限
|
||||
double singleItemBase = 1d / totalCases;
|
||||
innerRatio = Math.max(singleItemBase - 0.01, innerRatio);
|
||||
|
||||
progress = (itemTotalRatio + innerRatio) * 100;
|
||||
}
|
||||
|
||||
String info = event.getEventType() == FlowExecutionEvent.EventType.NODE_STARTED ? "开始执行" : "执行完成";
|
||||
String logId = UUID.randomUUID().toString().replace("-", "");
|
||||
// 四舍五入保留2位小数
|
||||
progress = Math.round(progress * 100) / 100.0;
|
||||
|
||||
// 保存日志到数据库
|
||||
AimaTestLog testLog = AimaTestLog.builder()
|
||||
.id(logId)
|
||||
.taskInstanceId(taskInstance.getId())
|
||||
.taskId(taskInstance.getTaskId())
|
||||
.testCaseId(itemId)
|
||||
.logLevel("INFO")
|
||||
.logType("执行日志")
|
||||
.logContent("节点【" + event.getNodeName() + "】" + info)
|
||||
.logTime(now)
|
||||
.status(targetStatus)
|
||||
.executionStep(event.getNodeName())
|
||||
.testStatus("0") // 0未执行
|
||||
.durationMs(0L)
|
||||
.progress( progress)
|
||||
.build();
|
||||
|
||||
try {
|
||||
aimaTestLogService.insertAimaTestLog(testLog);
|
||||
log.info("爱玛测试日志保存成功,logId:{},taskInstanceId:{},nodeId:{}", logId, taskInstance.getId(), nodeId);
|
||||
} catch (Exception e) {
|
||||
log.error("爱玛测试日志保存失败,taskInstanceId:{},nodeId:{}", taskInstance.getId(), nodeId, e);
|
||||
}
|
||||
|
||||
try {
|
||||
messagePushService.pushToChannel("AimaTaskInstance", testLog);
|
||||
} catch (Exception e) {
|
||||
log.info("消息推送异常,无订阅忽略,itemId:{}", itemId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 任务结束统一清理缓存 */
|
||||
private void clearCache(String taskInsId) {
|
||||
Set<String> itemList = taskItemExecutMap.getOrDefault(taskInsId, new HashSet<>());
|
||||
itemList.forEach(itemNodeExecutMap::remove);
|
||||
taskItemExecutMap.remove(taskInsId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送完成任务信息
|
||||
*/
|
||||
public void pushCompleteMsg(String dbInsId, Date now, int targetStatus) {
|
||||
String logId = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
// 保存完成日志
|
||||
AimaTestLog testLog = AimaTestLog.builder()
|
||||
.id(logId)
|
||||
.taskInstanceId(dbInsId)
|
||||
.logLevel("INFO")
|
||||
.logType("系统日志")
|
||||
.logContent("任务执行完成")
|
||||
.logTime(now)
|
||||
.status(targetStatus)
|
||||
.build();
|
||||
|
||||
try {
|
||||
aimaTestLogService.insertAimaTestLog(testLog);
|
||||
log.info("任务完成日志保存成功,logId:{},taskInstanceId:{}", logId, dbInsId);
|
||||
} catch (Exception e) {
|
||||
log.error("任务完成日志保存失败,taskInstanceId:{}", dbInsId, e);
|
||||
}
|
||||
try {
|
||||
messagePushService.pushToChannel("AimaTaskInstance", testLog);
|
||||
} catch (Exception e) {
|
||||
log.info("消息推送异常,无订阅忽略,insId:{}", dbInsId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaAlarm;
|
||||
|
||||
/**
|
||||
* 爱玛告警管理Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaAlarmMapper extends BaseMapper<AimaAlarm> {
|
||||
/**
|
||||
* 查询爱玛告警管理
|
||||
*
|
||||
* @param id 爱玛告警管理主键
|
||||
* @return 爱玛告警管理
|
||||
*/
|
||||
AimaAlarm selectAimaAlarmById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛告警管理列表
|
||||
*
|
||||
* @param aimaAlarm 爱玛告警管理
|
||||
* @return 爱玛告警管理集合
|
||||
*/
|
||||
List<AimaAlarm> selectAimaAlarmList(AimaAlarm aimaAlarm);
|
||||
|
||||
/**
|
||||
* 新增爱玛告警管理
|
||||
*
|
||||
* @param aimaAlarm 爱玛告警管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaAlarm(AimaAlarm aimaAlarm);
|
||||
|
||||
/**
|
||||
* 修改爱玛告警管理
|
||||
*
|
||||
* @param aimaAlarm 爱玛告警管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaAlarm(AimaAlarm aimaAlarm);
|
||||
|
||||
/**
|
||||
* 删除爱玛告警管理
|
||||
*
|
||||
* @param id 爱玛告警管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaAlarmById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛告警管理
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaAlarmByIds(String[] ids);
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaPhone;
|
||||
|
||||
/**
|
||||
* 爱玛手机管理Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaPhoneMapper extends BaseMapper<AimaPhone> {
|
||||
/**
|
||||
* 查询爱玛手机管理
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 爱玛手机管理
|
||||
*/
|
||||
AimaPhone selectAimaPhoneById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛手机管理列表
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 爱玛手机管理集合
|
||||
*/
|
||||
List<AimaPhone> selectAimaPhoneList(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 新增爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaPhone(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 修改爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaPhone(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 删除爱玛手机管理
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaPhoneById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛手机管理
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaPhoneByIds(String[] ids);
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTaskInstance;
|
||||
import com.cmvr.aima.domain.dto.AimaTaskInstanceQuery;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskInstanceVo;
|
||||
|
||||
/**
|
||||
* 爱玛任务执行实例Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaTaskInstanceMapper extends BaseMapper<AimaTaskInstance> {
|
||||
/**
|
||||
* 查询爱玛任务执行实例
|
||||
*
|
||||
* @param id 爱玛任务执行实例主键
|
||||
* @return 爱玛任务执行实例
|
||||
*/
|
||||
AimaTaskInstance selectAimaTaskInstanceById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛任务执行实例列表
|
||||
*
|
||||
* @param aimaTaskInstance 爱玛任务执行实例
|
||||
* @return 爱玛任务执行实例集合
|
||||
*/
|
||||
List<AimaTaskInstance> selectAimaTaskInstanceList(AimaTaskInstance aimaTaskInstance);
|
||||
|
||||
/**
|
||||
* 查询爱玛任务执行实例视图列表(包含关联信息)
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return 爱玛任务执行实例视图集合
|
||||
*/
|
||||
List<AimaTaskInstanceVo> selectAimaTaskInstanceVoList(AimaTaskInstanceQuery query);
|
||||
|
||||
/**
|
||||
* 新增爱玛任务执行实例
|
||||
*
|
||||
* @param aimaTaskInstance 爱玛任务执行实例
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaTaskInstance(AimaTaskInstance aimaTaskInstance);
|
||||
|
||||
/**
|
||||
* 修改爱玛任务执行实例
|
||||
*
|
||||
* @param aimaTaskInstance 爱玛任务执行实例
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaTaskInstance(AimaTaskInstance aimaTaskInstance);
|
||||
|
||||
/**
|
||||
* 删除爱玛任务执行实例
|
||||
*
|
||||
* @param id 爱玛任务执行实例主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTaskInstanceById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛任务执行实例
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTaskInstanceByIds(String[] ids);
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTask;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskVo;
|
||||
|
||||
/**
|
||||
* 爱玛任务管理Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaTaskMapper extends BaseMapper<AimaTask> {
|
||||
/**
|
||||
* 查询爱玛任务管理
|
||||
*
|
||||
* @param id 爱玛任务管理主键
|
||||
* @return 爱玛任务管理
|
||||
*/
|
||||
AimaTask selectAimaTaskById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛任务管理列表
|
||||
*
|
||||
* @param aimaTask 爱玛任务管理
|
||||
* @return 爱玛任务管理集合
|
||||
*/
|
||||
List<AimaTask> selectAimaTaskList(AimaTask aimaTask);
|
||||
|
||||
/**
|
||||
* 查询爱玛任务视图列表(包含关联信息)
|
||||
*
|
||||
* @param aimaTask 爱玛任务管理
|
||||
* @return 爱玛任务视图集合
|
||||
*/
|
||||
List<AimaTaskVo> selectAimaTaskVoList(AimaTask aimaTask);
|
||||
|
||||
/**
|
||||
* 新增爱玛任务管理
|
||||
*
|
||||
* @param aimaTask 爱玛任务管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaTask(AimaTask aimaTask);
|
||||
|
||||
/**
|
||||
* 修改爱玛任务管理
|
||||
*
|
||||
* @param aimaTask 爱玛任务管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaTask(AimaTask aimaTask);
|
||||
|
||||
/**
|
||||
* 删除爱玛任务管理
|
||||
*
|
||||
* @param id 爱玛任务管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTaskById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛任务管理
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTaskByIds(String[] ids);
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.cmvr.aima.domain.AimaTaskTestCase;
|
||||
|
||||
/**
|
||||
* 爱玛任务与测试用例关联Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaTaskTestCaseMapper extends MPJBaseMapper<AimaTaskTestCase>
|
||||
{
|
||||
/**
|
||||
* 批量插入任务-测试用例关联
|
||||
*
|
||||
* @param list 任务-测试用例关联列表
|
||||
* @return 结果
|
||||
*/
|
||||
void batchInsertTaskTestCase(@Param("list") List<AimaTaskTestCase> list);
|
||||
|
||||
/**
|
||||
* 根据任务ID删除关联
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return 结果
|
||||
*/
|
||||
void deleteTaskTestCaseByTaskId(String taskId);
|
||||
|
||||
/**
|
||||
* 根据任务ID查询测试用例ID列表
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return 测试用例ID列表
|
||||
*/
|
||||
List<String> selectTestCaseIdsByTaskId(String taskId);
|
||||
|
||||
/**
|
||||
* 批量删除任务-测试用例关联
|
||||
*
|
||||
* @param taskIds 需要删除的任务ID数组
|
||||
* @return 结果
|
||||
*/
|
||||
void deleteTaskTestCaseByTaskIds(String[] taskIds);
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.domain.vo.AimaTestCaseVo;
|
||||
|
||||
/**
|
||||
* 爱玛测试用例Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaTestCaseMapper extends BaseMapper<AimaTestCase> {
|
||||
/**
|
||||
* 查询爱玛测试用例
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 爱玛测试用例
|
||||
*/
|
||||
AimaTestCase selectAimaTestCaseById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例列表
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例集合
|
||||
*/
|
||||
List<AimaTestCase> selectAimaTestCaseList(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例视图列表(包含关联信息)
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例视图集合
|
||||
*/
|
||||
List<AimaTestCaseVo> selectAimaTestCaseVoList(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 新增爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaTestCase(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 修改爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaTestCase(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 删除爱玛测试用例
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestCaseById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛测试用例
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestCaseByIds(String[] ids);
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTestLog;
|
||||
|
||||
/**
|
||||
* 爱玛测试日志Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaTestLogMapper extends BaseMapper<AimaTestLog> {
|
||||
/**
|
||||
* 查询爱玛测试日志
|
||||
*
|
||||
* @param id 爱玛测试日志主键
|
||||
* @return 爱玛测试日志
|
||||
*/
|
||||
AimaTestLog selectAimaTestLogById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛测试日志列表
|
||||
*
|
||||
* @param aimaTestLog 爱玛测试日志
|
||||
* @return 爱玛测试日志集合
|
||||
*/
|
||||
List<AimaTestLog> selectAimaTestLogList(AimaTestLog aimaTestLog);
|
||||
|
||||
/**
|
||||
* 新增爱玛测试日志
|
||||
*
|
||||
* @param aimaTestLog 爱玛测试日志
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaTestLog(AimaTestLog aimaTestLog);
|
||||
|
||||
/**
|
||||
* 修改爱玛测试日志
|
||||
*
|
||||
* @param aimaTestLog 爱玛测试日志
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaTestLog(AimaTestLog aimaTestLog);
|
||||
|
||||
/**
|
||||
* 删除爱玛测试日志
|
||||
*
|
||||
* @param id 爱玛测试日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestLogById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛测试日志
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestLogByIds(String[] ids);
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package com.cmvr.aima.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.cmvr.aima.domain.AimaVehicle;
|
||||
|
||||
/**
|
||||
* 爱玛车辆管理Mapper接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface AimaVehicleMapper extends BaseMapper<AimaVehicle> {
|
||||
/**
|
||||
* 查询爱玛车辆管理
|
||||
*
|
||||
* @param id 爱玛车辆管理主键
|
||||
* @return 爱玛车辆管理
|
||||
*/
|
||||
AimaVehicle selectAimaVehicleById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛车辆管理列表
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 爱玛车辆管理集合
|
||||
*/
|
||||
List<AimaVehicle> selectAimaVehicleList(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 新增爱玛车辆管理
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaVehicle(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 修改爱玛车辆管理
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaVehicle(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 删除爱玛车辆管理
|
||||
*
|
||||
* @param id 爱玛车辆管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaVehicleById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛车辆管理
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaVehicleByIds(String[] ids);
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaAlarm;
|
||||
|
||||
/**
|
||||
* 爱玛告警管理Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaAlarmService {
|
||||
AimaAlarm selectAimaAlarmById(String id);
|
||||
List<AimaAlarm> selectAimaAlarmList(AimaAlarm aimaAlarm);
|
||||
int insertAimaAlarm(AimaAlarm aimaAlarm);
|
||||
int updateAimaAlarm(AimaAlarm aimaAlarm);
|
||||
int deleteAimaAlarmByIds(String[] ids);
|
||||
int deleteAimaAlarmById(String id);
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaPhone;
|
||||
|
||||
/**
|
||||
* 爱玛手机管理Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaPhoneService {
|
||||
/**
|
||||
* 查询爱玛手机管理
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 爱玛手机管理
|
||||
*/
|
||||
AimaPhone selectAimaPhoneById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛手机管理列表
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 爱玛手机管理集合
|
||||
*/
|
||||
List<AimaPhone> selectAimaPhoneList(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 新增爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaPhone(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 修改爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaPhone(AimaPhone aimaPhone);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛手机管理
|
||||
*
|
||||
* @param ids 需要删除的爱玛手机管理主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaPhoneByIds(String[] ids);
|
||||
|
||||
/**
|
||||
* 删除爱玛手机管理信息
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaPhoneById(String id);
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.cmvr.aima.domain.AimaTaskInstance;
|
||||
import com.cmvr.aima.domain.dto.AimaTaskInstanceQuery;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskInstanceVo;
|
||||
|
||||
/**
|
||||
* 爱玛任务执行实例Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaTaskInstanceService extends IService<AimaTaskInstance> {
|
||||
AimaTaskInstance selectAimaTaskInstanceById(String id);
|
||||
List<AimaTaskInstance> selectAimaTaskInstanceList(AimaTaskInstance aimaTaskInstance);
|
||||
List<AimaTaskInstanceVo> selectAimaTaskInstanceVoList(AimaTaskInstanceQuery query);
|
||||
int insertAimaTaskInstance(AimaTaskInstance aimaTaskInstance);
|
||||
int updateAimaTaskInstance(AimaTaskInstance aimaTaskInstance);
|
||||
int deleteAimaTaskInstanceByIds(String[] ids);
|
||||
int deleteAimaTaskInstanceById(String id);
|
||||
|
||||
/**
|
||||
* 开始执行任务实例
|
||||
*
|
||||
* @param id 任务实例ID
|
||||
* @return 结果
|
||||
*/
|
||||
int startInstance(String id);
|
||||
|
||||
/**
|
||||
* 暂停任务实例
|
||||
*
|
||||
* @param id 任务实例ID
|
||||
* @return 结果
|
||||
*/
|
||||
int pauseInstance(String id);
|
||||
|
||||
/**
|
||||
* 终止任务实例
|
||||
*
|
||||
* @param id 任务实例ID
|
||||
* @return 结果
|
||||
*/
|
||||
int stopInstance(String id);
|
||||
|
||||
/**
|
||||
* 恢复任务实例(从暂停恢复为执行中)
|
||||
*
|
||||
* @param id 任务实例ID
|
||||
* @return 结果
|
||||
*/
|
||||
int resumeInstance(String id);
|
||||
|
||||
/**
|
||||
* 更新任务实例进度
|
||||
*
|
||||
* @param instanceId 任务实例ID
|
||||
* @param progress 执行进度(百分比,保留2位小数)
|
||||
*/
|
||||
void updateProgress(String instanceId, Double progress);
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaTask;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskVo;
|
||||
|
||||
/**
|
||||
* 爱玛任务管理Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaTaskService {
|
||||
AimaTask selectAimaTaskById(String id);
|
||||
List<AimaTask> selectAimaTaskList(AimaTask aimaTask);
|
||||
List<AimaTaskVo> selectAimaTaskVoList(AimaTask aimaTask);
|
||||
int insertAimaTask(AimaTask aimaTask);
|
||||
int updateAimaTask(AimaTask aimaTask);
|
||||
int deleteAimaTaskByIds(String[] ids);
|
||||
int deleteAimaTaskById(String id);
|
||||
|
||||
/**
|
||||
* 为任务绑定测试用例
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param testCaseIds 测试用例ID列表
|
||||
*/
|
||||
void bindTestCases(String taskId, List<String> testCaseIds);
|
||||
|
||||
/**
|
||||
* 获取任务的测试用例列表
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return 测试用例ID列表
|
||||
*/
|
||||
List<AimaTestCase> getTestCaseIds(String taskId);
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.domain.vo.AimaTestCaseVo;
|
||||
|
||||
/**
|
||||
* 爱玛测试用例Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaTestCaseService {
|
||||
/**
|
||||
* 查询爱玛测试用例
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 爱玛测试用例
|
||||
*/
|
||||
AimaTestCase selectAimaTestCaseById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例列表
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例集合
|
||||
*/
|
||||
List<AimaTestCase> selectAimaTestCaseList(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例视图列表(包含关联信息)
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例视图集合
|
||||
*/
|
||||
List<AimaTestCaseVo> selectAimaTestCaseVoList(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 新增爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaTestCase(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 修改爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaTestCase(AimaTestCase aimaTestCase);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛测试用例
|
||||
*
|
||||
* @param ids 需要删除的爱玛测试用例主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestCaseByIds(String[] ids);
|
||||
|
||||
/**
|
||||
* 删除爱玛测试用例信息
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaTestCaseById(String id);
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaTestLog;
|
||||
|
||||
/**
|
||||
* 爱玛测试日志Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaTestLogService {
|
||||
AimaTestLog selectAimaTestLogById(String id);
|
||||
List<AimaTestLog> selectAimaTestLogList(AimaTestLog aimaTestLog);
|
||||
int insertAimaTestLog(AimaTestLog aimaTestLog);
|
||||
int updateAimaTestLog(AimaTestLog aimaTestLog);
|
||||
int deleteAimaTestLogByIds(String[] ids);
|
||||
int deleteAimaTestLogById(String id);
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package com.cmvr.aima.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.cmvr.aima.domain.AimaVehicle;
|
||||
|
||||
/**
|
||||
* 爱玛车辆管理Service接口
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
public interface IAimaVehicleService {
|
||||
/**
|
||||
* 查询爱玛车辆管理
|
||||
*
|
||||
* @param id 爱玛车辆管理主键
|
||||
* @return 爱玛车辆管理
|
||||
*/
|
||||
AimaVehicle selectAimaVehicleById(String id);
|
||||
|
||||
/**
|
||||
* 查询爱玛车辆管理列表
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 爱玛车辆管理集合
|
||||
*/
|
||||
List<AimaVehicle> selectAimaVehicleList(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 新增爱玛车辆管理
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 结果
|
||||
*/
|
||||
int insertAimaVehicle(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 修改爱玛车辆管理
|
||||
*
|
||||
* @param aimaVehicle 爱玛车辆管理
|
||||
* @return 结果
|
||||
*/
|
||||
int updateAimaVehicle(AimaVehicle aimaVehicle);
|
||||
|
||||
/**
|
||||
* 批量删除爱玛车辆管理
|
||||
*
|
||||
* @param ids 需要删除的爱玛车辆管理主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaVehicleByIds(String[] ids);
|
||||
|
||||
/**
|
||||
* 删除爱玛车辆管理信息
|
||||
*
|
||||
* @param id 爱玛车辆管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteAimaVehicleById(String id);
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaAlarmMapper;
|
||||
import com.cmvr.aima.domain.AimaAlarm;
|
||||
import com.cmvr.aima.service.IAimaAlarmService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛告警管理Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaAlarmServiceImpl extends ServiceImpl<AimaAlarmMapper, AimaAlarm> implements IAimaAlarmService {
|
||||
@Autowired
|
||||
private AimaAlarmMapper aimaAlarmMapper;
|
||||
|
||||
@Override
|
||||
public AimaAlarm selectAimaAlarmById(String id) {
|
||||
return aimaAlarmMapper.selectAimaAlarmById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaAlarm> selectAimaAlarmList(AimaAlarm aimaAlarm) {
|
||||
return aimaAlarmMapper.selectAimaAlarmList(aimaAlarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAimaAlarm(AimaAlarm aimaAlarm) {
|
||||
if (aimaAlarm.getId() == null || aimaAlarm.getId().isEmpty()) {
|
||||
aimaAlarm.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaAlarm.setCreateTime(DateUtils.getNowDate());
|
||||
aimaAlarm.setCreateBy(SecurityUtils.getUsername());
|
||||
return aimaAlarmMapper.insertAimaAlarm(aimaAlarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAimaAlarm(AimaAlarm aimaAlarm) {
|
||||
aimaAlarm.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaAlarm.setUpdateBy(SecurityUtils.getUsername());
|
||||
return aimaAlarmMapper.updateAimaAlarm(aimaAlarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaAlarmByIds(String[] ids) {
|
||||
return aimaAlarmMapper.deleteAimaAlarmByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaAlarmById(String id) {
|
||||
return aimaAlarmMapper.deleteAimaAlarmById(id);
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaPhoneMapper;
|
||||
import com.cmvr.aima.domain.AimaPhone;
|
||||
import com.cmvr.aima.service.IAimaPhoneService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛手机管理Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaPhoneServiceImpl extends ServiceImpl<AimaPhoneMapper, AimaPhone> implements IAimaPhoneService {
|
||||
@Autowired
|
||||
private AimaPhoneMapper aimaPhoneMapper;
|
||||
|
||||
/**
|
||||
* 查询爱玛手机管理
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 爱玛手机管理
|
||||
*/
|
||||
@Override
|
||||
public AimaPhone selectAimaPhoneById(String id) {
|
||||
return aimaPhoneMapper.selectAimaPhoneById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询爱玛手机管理列表
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 爱玛手机管理
|
||||
*/
|
||||
@Override
|
||||
public List<AimaPhone> selectAimaPhoneList(AimaPhone aimaPhone) {
|
||||
return aimaPhoneMapper.selectAimaPhoneList(aimaPhone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertAimaPhone(AimaPhone aimaPhone) {
|
||||
// 生成UUID作为主键
|
||||
if (aimaPhone.getId() == null || aimaPhone.getId().isEmpty()) {
|
||||
aimaPhone.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaPhone.setCreateTime(DateUtils.getNowDate());
|
||||
aimaPhone.setCreateBy(SecurityUtils.getUsername());
|
||||
return aimaPhoneMapper.insertAimaPhone(aimaPhone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改爱玛手机管理
|
||||
*
|
||||
* @param aimaPhone 爱玛手机管理
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateAimaPhone(AimaPhone aimaPhone) {
|
||||
aimaPhone.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaPhone.setUpdateBy(SecurityUtils.getUsername());
|
||||
return aimaPhoneMapper.updateAimaPhone(aimaPhone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除爱玛手机管理
|
||||
*
|
||||
* @param ids 需要删除的爱玛手机管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAimaPhoneByIds(String[] ids) {
|
||||
return aimaPhoneMapper.deleteAimaPhoneByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除爱玛手机管理信息
|
||||
*
|
||||
* @param id 爱玛手机管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAimaPhoneById(String id) {
|
||||
return aimaPhoneMapper.deleteAimaPhoneById(id);
|
||||
}
|
||||
}
|
||||
@ -1,234 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.cmvr.aima.domain.dto.AimaTaskInstanceQuery;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskInstanceVo;
|
||||
import com.cmvr.common.exception.ServiceException;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.test.flow.control.FlowControlService;
|
||||
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
|
||||
import com.cmvr.test.flow.runtime.event.FlowExecutionModuleCodes;
|
||||
import com.cmvr.test.model.vo.TeTaskExecuteNormalVO;
|
||||
import com.cmvr.test.service.ITeTaskOrchestrationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.aima.mapper.AimaTaskInstanceMapper;
|
||||
import com.cmvr.aima.domain.AimaTaskInstance;
|
||||
import com.cmvr.aima.service.IAimaTaskInstanceService;
|
||||
import com.cmvr.aima.enums.AimaTaskStatusEnum;
|
||||
import com.cmvr.aima.service.IAimaTaskService;
|
||||
import com.cmvr.aima.domain.AimaTask;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛任务执行实例Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaTaskInstanceServiceImpl extends ServiceImpl<AimaTaskInstanceMapper, AimaTaskInstance> implements IAimaTaskInstanceService {
|
||||
@Autowired
|
||||
private AimaTaskInstanceMapper aimaTaskInstanceMapper;
|
||||
|
||||
@Autowired
|
||||
private IAimaTaskService aimaTaskService;
|
||||
|
||||
@Autowired
|
||||
private ITeTaskOrchestrationService teTaskOrchestrationService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private FlowTaskRuntimeService flowTaskRuntimeService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private FlowControlService flowControlService;
|
||||
|
||||
@Override
|
||||
public AimaTaskInstance selectAimaTaskInstanceById(String id) {
|
||||
return aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTaskInstance> selectAimaTaskInstanceList(AimaTaskInstance aimaTaskInstance) {
|
||||
return aimaTaskInstanceMapper.selectAimaTaskInstanceList(aimaTaskInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTaskInstanceVo> selectAimaTaskInstanceVoList(AimaTaskInstanceQuery query) {
|
||||
return aimaTaskInstanceMapper.selectAimaTaskInstanceVoList(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAimaTaskInstance(AimaTaskInstance aimaTaskInstance) {
|
||||
if (aimaTaskInstance.getId() == null || aimaTaskInstance.getId().isEmpty()) {
|
||||
aimaTaskInstance.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaTaskInstance.setStatus(AimaTaskStatusEnum.NOT_STARTED.getCode());
|
||||
aimaTaskInstance.setCreateTime(DateUtils.getNowDate());
|
||||
aimaTaskInstance.setCreateBy(SecurityUtils.getUsername());
|
||||
// 获取测试用例数量
|
||||
AimaTask aimaTask = aimaTaskService.selectAimaTaskById(aimaTaskInstance.getTaskId());
|
||||
if (aimaTask != null && aimaTask.getTestCaseCount() != null) {
|
||||
aimaTaskInstance.setTotalCases(aimaTask.getTestCaseCount());
|
||||
}
|
||||
return aimaTaskInstanceMapper.insertAimaTaskInstance(aimaTaskInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAimaTaskInstance(AimaTaskInstance aimaTaskInstance) {
|
||||
// 校验状态,只有未执行可以修改
|
||||
if (AimaTaskStatusEnum.NOT_STARTED.getCode() != aimaTaskInstance.getStatus()) {
|
||||
throw new ServiceException("只有未执行状态的任务实例才能修改");
|
||||
}
|
||||
aimaTaskInstance.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaTaskInstance.setUpdateBy(SecurityUtils.getUsername());
|
||||
// 获取测试用例数量
|
||||
AimaTask aimaTask = aimaTaskService.selectAimaTaskById(aimaTaskInstance.getTaskId());
|
||||
if (aimaTask != null && aimaTask.getTestCaseCount() != null) {
|
||||
aimaTaskInstance.setTotalCases(aimaTask.getTestCaseCount());
|
||||
}
|
||||
return aimaTaskInstanceMapper.updateAimaTaskInstance(aimaTaskInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTaskInstanceByIds(String[] ids) {
|
||||
// 校验状态,只有未执行可以删除
|
||||
for (String id : ids) {
|
||||
AimaTaskInstance instance = aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
if (instance != null && AimaTaskStatusEnum.NOT_STARTED.getCode() != instance.getStatus()) {
|
||||
throw new ServiceException("只有未执行状态的任务实例才能删除");
|
||||
}
|
||||
}
|
||||
return aimaTaskInstanceMapper.deleteAimaTaskInstanceByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTaskInstanceById(String id) {
|
||||
return aimaTaskInstanceMapper.deleteAimaTaskInstanceById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行任务实例
|
||||
*/
|
||||
@Override
|
||||
public int startInstance(String id) {
|
||||
AimaTaskInstance instance = aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
if (instance == null) {
|
||||
throw new ServiceException("任务实例不存在");
|
||||
}
|
||||
if (AimaTaskStatusEnum.NOT_STARTED.getCode() != instance.getStatus()) {
|
||||
throw new ServiceException("只有待执行状态的任务实例才能开始执行");
|
||||
}
|
||||
AimaTaskInstance update = new AimaTaskInstance();
|
||||
update.setId(id);
|
||||
update.setStatus(AimaTaskStatusEnum.RUNNING.getCode());
|
||||
update.setStartTime(DateUtils.getNowDate());
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
update.setUpdateBy(SecurityUtils.getUsername());
|
||||
|
||||
|
||||
|
||||
AimaTask aimaTask = aimaTaskService.selectAimaTaskById(instance.getTaskId());
|
||||
JSONObject runParams = new JSONObject();
|
||||
// 从test模块的任务编排中获取所有的检测项id
|
||||
if (aimaTask != null && aimaTask.getTaskConfigId() != null) {
|
||||
teTaskOrchestrationService.queryByTaskId(aimaTask.getTaskConfigId())
|
||||
.forEach(item -> runParams.put(item.getItemId(), new JSONObject()));
|
||||
}
|
||||
// 调用流程引擎执行
|
||||
String insId = flowTaskRuntimeService.executeTask(
|
||||
TeTaskExecuteNormalVO.builder()
|
||||
.taskId(aimaTask.getTaskConfigId())
|
||||
.moduleCode(FlowExecutionModuleCodes.AIMA)
|
||||
.runParams(runParams)
|
||||
.build()
|
||||
);
|
||||
update.setTaskInsId(insId);
|
||||
return aimaTaskInstanceMapper.updateAimaTaskInstance(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务实例
|
||||
*/
|
||||
@Override
|
||||
public int pauseInstance(String id) {
|
||||
AimaTaskInstance instance = aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
if (instance == null) {
|
||||
throw new ServiceException("任务实例不存在");
|
||||
}
|
||||
if (AimaTaskStatusEnum.RUNNING.getCode() != instance.getStatus()) {
|
||||
throw new ServiceException("只有执行中状态的任务实例才能暂停");
|
||||
}
|
||||
AimaTaskInstance update = new AimaTaskInstance();
|
||||
update.setId(id);
|
||||
update.setStatus(AimaTaskStatusEnum.PAUSED.getCode());
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
update.setUpdateBy(SecurityUtils.getUsername());
|
||||
flowControlService.pause(instance.getTaskInsId());
|
||||
return aimaTaskInstanceMapper.updateAimaTaskInstance(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务实例
|
||||
*/
|
||||
@Override
|
||||
public int stopInstance(String id) {
|
||||
AimaTaskInstance instance = aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
if (instance == null) {
|
||||
throw new ServiceException("任务实例不存在");
|
||||
}
|
||||
if (AimaTaskStatusEnum.NOT_STARTED.getCode() != instance.getStatus()
|
||||
&& AimaTaskStatusEnum.RUNNING.getCode() != instance.getStatus()) {
|
||||
throw new ServiceException("已完成或已取消的任务实例不能终止");
|
||||
}
|
||||
AimaTaskInstance update = new AimaTaskInstance();
|
||||
update.setId(id);
|
||||
update.setStatus(AimaTaskStatusEnum.STOPPED.getCode());
|
||||
update.setEndTime(DateUtils.getNowDate());
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
update.setUpdateBy(SecurityUtils.getUsername());
|
||||
flowControlService.stop(instance.getTaskInsId());
|
||||
return aimaTaskInstanceMapper.updateAimaTaskInstance(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务实例(从暂停恢复为执行中)
|
||||
*/
|
||||
@Override
|
||||
public int resumeInstance(String id) {
|
||||
AimaTaskInstance instance = aimaTaskInstanceMapper.selectAimaTaskInstanceById(id);
|
||||
if (instance == null) {
|
||||
throw new ServiceException("任务实例不存在");
|
||||
}
|
||||
if (AimaTaskStatusEnum.PAUSED.getCode() != instance.getStatus()) {
|
||||
throw new ServiceException("只有已暂停状态的任务实例才能恢复");
|
||||
}
|
||||
AimaTaskInstance update = new AimaTaskInstance();
|
||||
update.setId(id);
|
||||
update.setStatus(AimaTaskStatusEnum.RUNNING.getCode());
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
update.setUpdateBy(SecurityUtils.getUsername());
|
||||
flowControlService.resume(instance.getTaskInsId());
|
||||
return aimaTaskInstanceMapper.updateAimaTaskInstance(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务实例进度
|
||||
*/
|
||||
@Override
|
||||
public void updateProgress(String instanceId, Double progress) {
|
||||
AimaTaskInstance update = new AimaTaskInstance();
|
||||
update.setId(instanceId);
|
||||
update.setProgress(progress);
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaTaskInstanceMapper.updateAimaTaskInstance(update);
|
||||
}
|
||||
}
|
||||
@ -1,159 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.cmvr.aima.domain.AimaTaskTestCase;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.domain.vo.AimaTaskVo;
|
||||
import com.cmvr.aima.mapper.AimaTestCaseMapper;
|
||||
import com.cmvr.test.model.domain.TeTaskConfigInfo;
|
||||
import com.cmvr.test.model.vo.TeTaskOrchestraVO;
|
||||
import com.cmvr.test.service.ITeTaskConfigInfoService;
|
||||
import com.cmvr.test.service.ITeTaskOrchestrationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaTaskMapper;
|
||||
import com.cmvr.aima.mapper.AimaTaskTestCaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTask;
|
||||
import com.cmvr.aima.service.IAimaTaskService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaTaskServiceImpl extends ServiceImpl<AimaTaskMapper, AimaTask> implements IAimaTaskService {
|
||||
@Autowired
|
||||
private AimaTaskMapper aimaTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private AimaTaskTestCaseMapper aimaTaskTestCaseMapper;
|
||||
|
||||
@Autowired
|
||||
private AimaTestCaseMapper aimaTestCaseMapper;
|
||||
|
||||
@Autowired
|
||||
private ITeTaskOrchestrationService teTaskOrchestrationService;
|
||||
|
||||
@Autowired
|
||||
private ITeTaskConfigInfoService teTaskConfigInfoService;
|
||||
|
||||
@Override
|
||||
public AimaTask selectAimaTaskById(String id) {
|
||||
return aimaTaskMapper.selectAimaTaskById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTask> selectAimaTaskList(AimaTask aimaTask) {
|
||||
return aimaTaskMapper.selectAimaTaskList(aimaTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTaskVo> selectAimaTaskVoList(AimaTask aimaTask) {
|
||||
return aimaTaskMapper.selectAimaTaskVoList(aimaTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAimaTask(AimaTask aimaTask) {
|
||||
// 生成UUID作为主键
|
||||
if (aimaTask.getId() == null || aimaTask.getId().isEmpty()) {
|
||||
aimaTask.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaTask.setCreateTime(DateUtils.getNowDate());
|
||||
aimaTask.setCreateBy(SecurityUtils.getUsername());
|
||||
// 同步新增任务配置到test模块
|
||||
TeTaskConfigInfo teTaskConfigInfo = TeTaskConfigInfo.builder()
|
||||
.taskName(aimaTask.getTaskName())
|
||||
.build();
|
||||
teTaskConfigInfoService.insertTeTaskConfigInfo(teTaskConfigInfo);
|
||||
aimaTask.setTaskConfigId(teTaskConfigInfo.getId());
|
||||
return aimaTaskMapper.insertAimaTask(aimaTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAimaTask(AimaTask aimaTask) {
|
||||
aimaTask.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaTask.setUpdateBy(SecurityUtils.getUsername());
|
||||
// 同步更新任务配置名称
|
||||
if (aimaTask.getTaskConfigId() != null) {
|
||||
TeTaskConfigInfo teTaskConfigInfo = teTaskConfigInfoService.selectTeTaskConfigInfoById(aimaTask.getTaskConfigId());
|
||||
if (teTaskConfigInfo != null) {
|
||||
teTaskConfigInfo.setTaskName(aimaTask.getTaskName());
|
||||
teTaskConfigInfoService.updateTeTaskConfigInfo(teTaskConfigInfo);
|
||||
}
|
||||
}
|
||||
return aimaTaskMapper.updateAimaTask(aimaTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTaskByIds(String[] ids) {
|
||||
// 先删除关联表数据
|
||||
aimaTaskTestCaseMapper.deleteTaskTestCaseByTaskIds(ids);
|
||||
// 批量查询任务
|
||||
List<AimaTask> aimaTasks = this.baseMapper.selectBatchIds(Arrays.asList(ids));
|
||||
// 批量删除任务配置
|
||||
teTaskConfigInfoService.deleteTeTaskConfigInfoByIds(
|
||||
aimaTasks.stream().map(AimaTask::getTaskConfigId).toArray(String[]::new)
|
||||
);
|
||||
return aimaTaskMapper.deleteAimaTaskByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTaskById(String id) {
|
||||
return aimaTaskMapper.deleteAimaTaskById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindTestCases(String taskId, List<String> testCaseIds) {
|
||||
// 先删除旧的关联
|
||||
aimaTaskTestCaseMapper.deleteTaskTestCaseByTaskId(taskId);
|
||||
|
||||
// 批量插入新的关联
|
||||
if (testCaseIds != null && !testCaseIds.isEmpty()) {
|
||||
List<AimaTaskTestCase> list = new ArrayList<>();
|
||||
for (int i = 0; i < testCaseIds.size(); i++) {
|
||||
AimaTaskTestCase taskTestCase = new AimaTaskTestCase();
|
||||
taskTestCase.setTaskId(taskId);
|
||||
taskTestCase.setTestCaseId(testCaseIds.get(i));
|
||||
taskTestCase.setSortOrder(i);
|
||||
list.add(taskTestCase);
|
||||
}
|
||||
aimaTaskTestCaseMapper.batchInsertTaskTestCase(list);
|
||||
|
||||
// 更新任务的测试用例数量
|
||||
AimaTask task = new AimaTask();
|
||||
task.setId(taskId);
|
||||
task.setTestCaseCount(testCaseIds.size());
|
||||
aimaTaskMapper.updateAimaTask(task);
|
||||
|
||||
// 查询测试用例,获取detectItemId列表
|
||||
List<AimaTestCase> testCases = aimaTestCaseMapper.selectBatchIds(testCaseIds);
|
||||
List<String> detectItemIds = testCases.stream()
|
||||
.map(AimaTestCase::getDetectItemId)
|
||||
.filter(itemId -> itemId != null && !itemId.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 同步任务编排到test模块
|
||||
if (!detectItemIds.isEmpty()) {
|
||||
AimaTask aimaTask = aimaTaskMapper.selectAimaTaskById(taskId);
|
||||
TeTaskOrchestraVO teTaskOrchestraVO = TeTaskOrchestraVO.builder()
|
||||
.taskId(aimaTask.getTaskConfigId())
|
||||
.itemIds(detectItemIds)
|
||||
.build();
|
||||
teTaskOrchestrationService.insertTeTaskOrchestration(teTaskOrchestraVO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTestCase> getTestCaseIds(String taskId) {
|
||||
List<String> ids = aimaTaskTestCaseMapper.selectTestCaseIdsByTaskId(taskId);
|
||||
return aimaTestCaseMapper.selectList(new QueryWrapper<AimaTestCase>().in("id", ids));
|
||||
}
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.cmvr.aima.domain.vo.AimaTestCaseVo;
|
||||
import com.cmvr.test.model.domain.TeDetectionItem;
|
||||
import com.cmvr.test.service.ITeDetectionItemService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaTestCaseMapper;
|
||||
import com.cmvr.aima.domain.AimaTestCase;
|
||||
import com.cmvr.aima.service.IAimaTestCaseService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛测试用例Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaTestCaseServiceImpl extends ServiceImpl<AimaTestCaseMapper, AimaTestCase> implements IAimaTestCaseService {
|
||||
@Autowired
|
||||
private AimaTestCaseMapper aimaTestCaseMapper;
|
||||
|
||||
@Autowired
|
||||
private ITeDetectionItemService teDetectionItemService;
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 爱玛测试用例
|
||||
*/
|
||||
@Override
|
||||
public AimaTestCase selectAimaTestCaseById(String id) {
|
||||
return aimaTestCaseMapper.selectAimaTestCaseById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例列表
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例
|
||||
*/
|
||||
@Override
|
||||
public List<AimaTestCase> selectAimaTestCaseList(AimaTestCase aimaTestCase) {
|
||||
return aimaTestCaseMapper.selectAimaTestCaseList(aimaTestCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询爱玛测试用例视图列表(包含关联信息)
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 爱玛测试用例视图集合
|
||||
*/
|
||||
@Override
|
||||
public List<AimaTestCaseVo> selectAimaTestCaseVoList(AimaTestCase aimaTestCase) {
|
||||
return aimaTestCaseMapper.selectAimaTestCaseVoList(aimaTestCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertAimaTestCase(AimaTestCase aimaTestCase) {
|
||||
// 生成UUID作为主键
|
||||
if (aimaTestCase.getId() == null || aimaTestCase.getId().isEmpty()) {
|
||||
aimaTestCase.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaTestCase.setCreateTime(DateUtils.getNowDate());
|
||||
aimaTestCase.setCreateBy(SecurityUtils.getUsername());
|
||||
// 同步新增检测项配置到test模块
|
||||
TeDetectionItem teDetectionItem = TeDetectionItem.builder()
|
||||
.detectName(aimaTestCase.getCaseName())
|
||||
.groupId(7L) // 可以根据实际情况调整分组ID
|
||||
.build();
|
||||
teDetectionItemService.insertTeDetectionItem(teDetectionItem);
|
||||
aimaTestCase.setDetectItemId(teDetectionItem.getId());
|
||||
return aimaTestCaseMapper.insertAimaTestCase(aimaTestCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改爱玛测试用例
|
||||
*
|
||||
* @param aimaTestCase 爱玛测试用例
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateAimaTestCase(AimaTestCase aimaTestCase) {
|
||||
aimaTestCase.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaTestCase.setUpdateBy(SecurityUtils.getUsername());
|
||||
// 同步更新检测项名称
|
||||
if (aimaTestCase.getDetectItemId() != null) {
|
||||
TeDetectionItem teDetectionItem = teDetectionItemService.selectTeDetectionItemById(aimaTestCase.getDetectItemId());
|
||||
if (teDetectionItem != null) {
|
||||
teDetectionItem.setDetectName(aimaTestCase.getCaseName());
|
||||
teDetectionItemService.updateTeDetectionItem(teDetectionItem);
|
||||
}
|
||||
}
|
||||
return aimaTestCaseMapper.updateAimaTestCase(aimaTestCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除爱玛测试用例
|
||||
*
|
||||
* @param ids 需要删除的爱玛测试用例主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAimaTestCaseByIds(String[] ids) {
|
||||
// 先查询数据,删除绑定的检测项
|
||||
for (String id : ids) {
|
||||
AimaTestCase aimaTestCase = aimaTestCaseMapper.selectAimaTestCaseById(id);
|
||||
if (aimaTestCase != null && aimaTestCase.getDetectItemId() != null) {
|
||||
teDetectionItemService.deleteTeDetectionItemById(aimaTestCase.getDetectItemId());
|
||||
}
|
||||
}
|
||||
return aimaTestCaseMapper.deleteAimaTestCaseByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除爱玛测试用例信息
|
||||
*
|
||||
* @param id 爱玛测试用例主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAimaTestCaseById(String id) {
|
||||
return aimaTestCaseMapper.deleteAimaTestCaseById(id);
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaTestLogMapper;
|
||||
import com.cmvr.aima.domain.AimaTestLog;
|
||||
import com.cmvr.aima.service.IAimaTestLogService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛测试日志Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaTestLogServiceImpl extends ServiceImpl<AimaTestLogMapper, AimaTestLog> implements IAimaTestLogService {
|
||||
@Autowired
|
||||
private AimaTestLogMapper aimaTestLogMapper;
|
||||
|
||||
@Override
|
||||
public AimaTestLog selectAimaTestLogById(String id) {
|
||||
return aimaTestLogMapper.selectAimaTestLogById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaTestLog> selectAimaTestLogList(AimaTestLog aimaTestLog) {
|
||||
return aimaTestLogMapper.selectAimaTestLogList(aimaTestLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAimaTestLog(AimaTestLog aimaTestLog) {
|
||||
if (aimaTestLog.getId() == null || aimaTestLog.getId().isEmpty()) {
|
||||
aimaTestLog.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaTestLog.setCreateTime(DateUtils.getNowDate());
|
||||
return aimaTestLogMapper.insertAimaTestLog(aimaTestLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAimaTestLog(AimaTestLog aimaTestLog) {
|
||||
aimaTestLog.setUpdateTime(DateUtils.getNowDate());
|
||||
return aimaTestLogMapper.updateAimaTestLog(aimaTestLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTestLogByIds(String[] ids) {
|
||||
return aimaTestLogMapper.deleteAimaTestLogByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaTestLogById(String id) {
|
||||
return aimaTestLogMapper.deleteAimaTestLogById(id);
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
package com.cmvr.aima.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.cmvr.common.utils.DateUtils;
|
||||
import com.cmvr.common.utils.SecurityUtils;
|
||||
import com.cmvr.aima.mapper.AimaVehicleMapper;
|
||||
import com.cmvr.aima.domain.AimaVehicle;
|
||||
import com.cmvr.aima.service.IAimaVehicleService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 爱玛车辆管理Service业务层处理
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-06-22
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class AimaVehicleServiceImpl extends ServiceImpl<AimaVehicleMapper, AimaVehicle> implements IAimaVehicleService {
|
||||
@Autowired
|
||||
private AimaVehicleMapper aimaVehicleMapper;
|
||||
|
||||
@Override
|
||||
public AimaVehicle selectAimaVehicleById(String id) {
|
||||
return aimaVehicleMapper.selectAimaVehicleById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AimaVehicle> selectAimaVehicleList(AimaVehicle aimaVehicle) {
|
||||
return aimaVehicleMapper.selectAimaVehicleList(aimaVehicle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertAimaVehicle(AimaVehicle aimaVehicle) {
|
||||
if (aimaVehicle.getId() == null || aimaVehicle.getId().isEmpty()) {
|
||||
aimaVehicle.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
aimaVehicle.setCreateTime(DateUtils.getNowDate());
|
||||
aimaVehicle.setCreateBy(SecurityUtils.getUsername());
|
||||
return aimaVehicleMapper.insertAimaVehicle(aimaVehicle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateAimaVehicle(AimaVehicle aimaVehicle) {
|
||||
aimaVehicle.setUpdateTime(DateUtils.getNowDate());
|
||||
aimaVehicle.setUpdateBy(SecurityUtils.getUsername());
|
||||
return aimaVehicleMapper.updateAimaVehicle(aimaVehicle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaVehicleByIds(String[] ids) {
|
||||
return aimaVehicleMapper.deleteAimaVehicleByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAimaVehicleById(String id) {
|
||||
return aimaVehicleMapper.deleteAimaVehicleById(id);
|
||||
}
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaAlarmMapper">
|
||||
<resultMap type="AimaAlarm" id="AimaAlarmResult">
|
||||
<result property="id" column="id"/><result property="createBy" column="create_by"/><result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/><result property="updateTime" column="update_time"/><result property="remark" column="remark"/>
|
||||
<result property="alarmCode" column="alarm_code"/><result property="taskInstanceId" column="task_instance_id"/><result property="taskId" column="task_id"/>
|
||||
<result property="taskName" column="task_name"/><result property="phoneId" column="phone_id"/><result property="phoneName" column="phone_name"/>
|
||||
<result property="vehicleId" column="vehicle_id"/><result property="vin" column="vin"/><result property="testCaseId" column="test_case_id"/>
|
||||
<result property="caseName" column="case_name"/><result property="alarmLevel" column="alarm_level"/><result property="alarmType" column="alarm_type"/>
|
||||
<result property="alarmTitle" column="alarm_title"/><result property="alarmContent" column="alarm_content"/><result property="alarmLocation" column="alarm_location"/>
|
||||
<result property="alarmTime" column="alarm_time"/><result property="handleStatus" column="handle_status"/><result property="handler" column="handler"/>
|
||||
<result property="handleTime" column="handle_time"/><result property="handleRemark" column="handle_remark"/><result property="evidenceImage" column="evidence_image"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaAlarmVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, alarm_code, task_instance_id, task_id, task_name, phone_id, phone_name, vehicle_id, vin, test_case_id, case_name, alarm_level, alarm_type, alarm_title, alarm_content, alarm_location, alarm_time, handle_status, handler, handle_time, handle_remark, evidence_image from aima_alarm
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaAlarmList" parameterType="AimaAlarm" resultMap="AimaAlarmResult">
|
||||
<include refid="selectAimaAlarmVo"/>
|
||||
<where>
|
||||
<if test="alarmCode != null and alarmCode != ''"> and alarm_code = #{alarmCode}</if>
|
||||
<if test="taskInstanceId != null and taskInstanceId != ''"> and task_instance_id = #{taskInstanceId}</if>
|
||||
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
|
||||
<if test="alarmLevel != null and alarmLevel != ''"> and alarm_level = #{alarmLevel}</if>
|
||||
<if test="alarmType != null and alarmType != ''"> and alarm_type = #{alarmType}</if>
|
||||
<if test="handleStatus != null and handleStatus != ''"> and handle_status = #{handleStatus}</if>
|
||||
</where>
|
||||
order by alarm_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaAlarmById" parameterType="String" resultMap="AimaAlarmResult">
|
||||
<include refid="selectAimaAlarmVo"/> where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaAlarm" parameterType="AimaAlarm">
|
||||
insert into aima_alarm <trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if><if test="createBy != null">create_by,</if><if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if><if test="updateTime != null">update_time,</if><if test="remark != null">remark,</if>
|
||||
<if test="alarmCode != null">alarm_code,</if><if test="taskInstanceId != null">task_instance_id,</if><if test="taskId != null">task_id,</if>
|
||||
<if test="taskName != null">task_name,</if><if test="phoneId != null">phone_id,</if><if test="phoneName != null">phone_name,</if>
|
||||
<if test="vehicleId != null">vehicle_id,</if><if test="vin != null">vin,</if><if test="testCaseId != null">test_case_id,</if>
|
||||
<if test="caseName != null">case_name,</if><if test="alarmLevel != null">alarm_level,</if><if test="alarmType != null">alarm_type,</if>
|
||||
<if test="alarmTitle != null">alarm_title,</if><if test="alarmContent != null">alarm_content,</if><if test="alarmLocation != null">alarm_location,</if>
|
||||
<if test="alarmTime != null">alarm_time,</if><if test="handleStatus != null">handle_status,</if><if test="handler != null">handler,</if>
|
||||
<if test="handleTime != null">handle_time,</if><if test="handleRemark != null">handle_remark,</if><if test="evidenceImage != null">evidence_image,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if><if test="createBy != null">#{createBy},</if><if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if><if test="updateTime != null">#{updateTime},</if><if test="remark != null">#{remark},</if>
|
||||
<if test="alarmCode != null">#{alarmCode},</if><if test="taskInstanceId != null">#{taskInstanceId},</if><if test="taskId != null">#{taskId},</if>
|
||||
<if test="taskName != null">#{taskName},</if><if test="phoneId != null">#{phoneId},</if><if test="phoneName != null">#{phoneName},</if>
|
||||
<if test="vehicleId != null">#{vehicleId},</if><if test="vin != null">#{vin},</if><if test="testCaseId != null">#{testCaseId},</if>
|
||||
<if test="caseName != null">#{caseName},</if><if test="alarmLevel != null">#{alarmLevel},</if><if test="alarmType != null">#{alarmType},</if>
|
||||
<if test="alarmTitle != null">#{alarmTitle},</if><if test="alarmContent != null">#{alarmContent},</if><if test="alarmLocation != null">#{alarmLocation},</if>
|
||||
<if test="alarmTime != null">#{alarmTime},</if><if test="handleStatus != null">#{handleStatus},</if><if test="handler != null">#{handler},</if>
|
||||
<if test="handleTime != null">#{handleTime},</if><if test="handleRemark != null">#{handleRemark},</if><if test="evidenceImage != null">#{evidenceImage},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaAlarm" parameterType="AimaAlarm">
|
||||
update aima_alarm <trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if><if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if><if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if><if test="alarmCode != null">alarm_code = #{alarmCode},</if>
|
||||
<if test="taskInstanceId != null">task_instance_id = #{taskInstanceId},</if><if test="taskId != null">task_id = #{taskId},</if>
|
||||
<if test="taskName != null">task_name = #{taskName},</if><if test="phoneId != null">phone_id = #{phoneId},</if>
|
||||
<if test="phoneName != null">phone_name = #{phoneName},</if><if test="vehicleId != null">vehicle_id = #{vehicleId},</if>
|
||||
<if test="vin != null">vin = #{vin},</if><if test="testCaseId != null">test_case_id = #{testCaseId},</if>
|
||||
<if test="caseName != null">case_name = #{caseName},</if><if test="alarmLevel != null">alarm_level = #{alarmLevel},</if>
|
||||
<if test="alarmType != null">alarm_type = #{alarmType},</if><if test="alarmTitle != null">alarm_title = #{alarmTitle},</if>
|
||||
<if test="alarmContent != null">alarm_content = #{alarmContent},</if><if test="alarmLocation != null">alarm_location = #{alarmLocation},</if>
|
||||
<if test="alarmTime != null">alarm_time = #{alarmTime},</if><if test="handleStatus != null">handle_status = #{handleStatus},</if>
|
||||
<if test="handler != null">handler = #{handler},</if><if test="handleTime != null">handle_time = #{handleTime},</if>
|
||||
<if test="handleRemark != null">handle_remark = #{handleRemark},</if><if test="evidenceImage != null">evidence_image = #{evidenceImage},</if>
|
||||
</trim> where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaAlarmById" parameterType="String">delete from aima_alarm where id = #{id}</delete>
|
||||
<delete id="deleteAimaAlarmByIds" parameterType="String">
|
||||
delete from aima_alarm where id in <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,106 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaPhoneMapper">
|
||||
|
||||
<resultMap type="AimaPhone" id="AimaPhoneResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="phoneName" column="phone_name" />
|
||||
<result property="phoneModel" column="phone_model" />
|
||||
<result property="osSystem" column="os_system" />
|
||||
<result property="osVersion" column="os_version" />
|
||||
<result property="specifications" column="specifications" />
|
||||
<result property="manufacturer" column="manufacturer" />
|
||||
<result property="status" column="status" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaPhoneVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, phone_name, phone_model, os_system, os_version, specifications, manufacturer, status from aima_phone
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaPhoneList" parameterType="AimaPhone" resultMap="AimaPhoneResult">
|
||||
<include refid="selectAimaPhoneVo"/>
|
||||
<where>
|
||||
<if test="phoneName != null and phoneName != ''"> and phone_name like concat('%', #{phoneName}, '%')</if>
|
||||
<if test="phoneModel != null and phoneModel != ''"> and phone_model like concat('%', #{phoneModel}, '%')</if>
|
||||
<if test="osSystem != null and osSystem != ''"> and os_system = #{osSystem}</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaPhoneById" parameterType="String" resultMap="AimaPhoneResult">
|
||||
<include refid="selectAimaPhoneVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaPhone" parameterType="AimaPhone">
|
||||
insert into aima_phone
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="phoneName != null">phone_name,</if>
|
||||
<if test="phoneModel != null">phone_model,</if>
|
||||
<if test="osSystem != null">os_system,</if>
|
||||
<if test="osVersion != null">os_version,</if>
|
||||
<if test="specifications != null">specifications,</if>
|
||||
<if test="manufacturer != null">manufacturer,</if>
|
||||
<if test="status != null">status,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="phoneName != null">#{phoneName},</if>
|
||||
<if test="phoneModel != null">#{phoneModel},</if>
|
||||
<if test="osSystem != null">#{osSystem},</if>
|
||||
<if test="osVersion != null">#{osVersion},</if>
|
||||
<if test="specifications != null">#{specifications},</if>
|
||||
<if test="manufacturer != null">#{manufacturer},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaPhone" parameterType="AimaPhone">
|
||||
update aima_phone
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="phoneName != null">phone_name = #{phoneName},</if>
|
||||
<if test="phoneModel != null">phone_model = #{phoneModel},</if>
|
||||
<if test="osSystem != null">os_system = #{osSystem},</if>
|
||||
<if test="osVersion != null">os_version = #{osVersion},</if>
|
||||
<if test="specifications != null">specifications = #{specifications},</if>
|
||||
<if test="manufacturer != null">manufacturer = #{manufacturer},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaPhoneById" parameterType="String">
|
||||
delete from aima_phone where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAimaPhoneByIds" parameterType="String">
|
||||
delete from aima_phone where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,122 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaTaskInstanceMapper">
|
||||
<resultMap type="AimaTaskInstance" id="AimaTaskInstanceResult">
|
||||
<result property="id" column="id"/><result property="createBy" column="create_by"/><result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/><result property="updateTime" column="update_time"/><result property="remark" column="remark"/>
|
||||
<result property="taskId" column="task_id"/><result property="phoneId" column="phone_id"/>
|
||||
<result property="vehicleId" column="vehicle_id"/>
|
||||
<result property="executionNumber" column="execution_number"/><result property="status" column="status"/><result property="taskInsId" column="task_ins_id"/>
|
||||
<result property="totalCases" column="total_cases"/>
|
||||
<result property="completedCases" column="completed_cases"/><result property="passedCases" column="passed_cases"/><result property="failedCases" column="failed_cases"/>
|
||||
<result property="progress" column="progress"/>
|
||||
<result property="startTime" column="start_time"/><result property="endTime" column="end_time"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="com.cmvr.aima.domain.vo.AimaTaskInstanceVo" id="AimaTaskInstanceVoResult">
|
||||
<result property="id" column="id"/><result property="createBy" column="create_by"/><result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/><result property="updateTime" column="update_time"/><result property="remark" column="remark"/>
|
||||
<result property="taskId" column="task_id"/><result property="taskCode" column="task_code"/><result property="taskName" column="task_name"/>
|
||||
<result property="phoneId" column="phone_id"/><result property="phoneName" column="phone_name"/>
|
||||
<result property="vehicleId" column="vehicle_id"/><result property="vehicleName" column="vehicle_name"/><result property="vin" column="vin"/>
|
||||
<result property="executionNumber" column="execution_number"/><result property="status" column="status"/><result property="taskInsId" column="task_ins_id"/>
|
||||
<result property="totalCases" column="total_cases"/>
|
||||
<result property="completedCases" column="completed_cases"/><result property="passedCases" column="passed_cases"/><result property="failedCases" column="failed_cases"/>
|
||||
<result property="progress" column="progress"/>
|
||||
<result property="startTime" column="start_time"/><result property="endTime" column="end_time"/>
|
||||
<result property="createByName" column="create_by_name"/><result property="updateByName" column="update_by_name"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaTaskInstanceVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, task_id, phone_id, vehicle_id, execution_number, status, task_ins_id, total_cases, completed_cases, passed_cases, failed_cases, progress, start_time, end_time from aima_task_instance
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaTaskInstanceList" parameterType="AimaTaskInstance" resultMap="AimaTaskInstanceResult">
|
||||
<include refid="selectAimaTaskInstanceVo"/>
|
||||
<where>
|
||||
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
|
||||
<if test="phoneId != null and phoneId != ''"> and phone_id = #{phoneId}</if>
|
||||
<if test="vehicleId != null and vehicleId != ''"> and vehicle_id = #{vehicleId}</if>
|
||||
<if test="status != null"> and status = #{status}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTaskInstanceById" parameterType="String" resultMap="AimaTaskInstanceResult">
|
||||
<include refid="selectAimaTaskInstanceVo"/> where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTaskInstanceVoList" parameterType="com.cmvr.aima.domain.dto.AimaTaskInstanceQuery" resultMap="AimaTaskInstanceVoResult">
|
||||
select ti.id, ti.create_by, ti.create_time, ti.update_by, ti.update_time, ti.remark,
|
||||
ti.task_id, t.task_code, t.task_name,
|
||||
ti.phone_id, p.phone_name, ti.vehicle_id, v.vehicle_name, v.vin,
|
||||
ti.execution_number, ti.status, ti.task_ins_id,
|
||||
ti.total_cases, ti.completed_cases, ti.passed_cases, ti.failed_cases, ti.progress,
|
||||
ti.start_time, ti.end_time,
|
||||
u1.nick_name as create_by_name, u2.nick_name as update_by_name
|
||||
from aima_task_instance ti
|
||||
left join aima_task t on ti.task_id = t.id
|
||||
left join aima_phone p on ti.phone_id = p.id
|
||||
left join aima_vehicle v on ti.vehicle_id = v.id
|
||||
left join sys_user u1 on ti.create_by = u1.user_name
|
||||
left join sys_user u2 on ti.update_by = u2.user_name
|
||||
<where>
|
||||
<if test="taskId != null and taskId != ''"> and ti.task_id = #{taskId}</if>
|
||||
<if test="phoneId != null and phoneId != ''"> and ti.phone_id = #{phoneId}</if>
|
||||
<if test="vehicleId != null and vehicleId != ''"> and ti.vehicle_id = #{vehicleId}</if>
|
||||
<if test="status != null"> and ti.status = #{status}</if>
|
||||
<if test="statusList != null and statusList.size() > 0">
|
||||
and ti.status in
|
||||
<foreach item="statusItem" collection="statusList" open="(" separator="," close=")">
|
||||
#{statusItem}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
order by ti.create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaTaskInstance" parameterType="AimaTaskInstance">
|
||||
insert into aima_task_instance <trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if><if test="createBy != null">create_by,</if><if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if><if test="updateTime != null">update_time,</if><if test="remark != null">remark,</if>
|
||||
<if test="taskId != null">task_id,</if><if test="phoneId != null">phone_id,</if>
|
||||
<if test="vehicleId != null">vehicle_id,</if>
|
||||
<if test="executionNumber != null">execution_number,</if><if test="status != null">status,</if><if test="totalCases != null">total_cases,</if>
|
||||
<if test="completedCases != null">completed_cases,</if><if test="passedCases != null">passed_cases,</if><if test="failedCases != null">failed_cases,</if>
|
||||
<if test="progress != null">progress,</if>
|
||||
<if test="startTime != null">start_time,</if><if test="endTime != null">end_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if><if test="createBy != null">#{createBy},</if><if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if><if test="updateTime != null">#{updateTime},</if><if test="remark != null">#{remark},</if>
|
||||
<if test="taskId != null">#{taskId},</if><if test="phoneId != null">#{phoneId},</if>
|
||||
<if test="vehicleId != null">#{vehicleId},</if>
|
||||
<if test="executionNumber != null">#{executionNumber},</if><if test="status != null">#{status},</if><if test="totalCases != null">#{totalCases},</if>
|
||||
<if test="completedCases != null">#{completedCases},</if><if test="passedCases != null">#{passedCases},</if><if test="failedCases != null">#{failedCases},</if>
|
||||
<if test="progress != null">#{progress},</if>
|
||||
<if test="startTime != null">#{startTime},</if><if test="endTime != null">#{endTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaTaskInstance" parameterType="AimaTaskInstance">
|
||||
update aima_task_instance <trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if><if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if><if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if><if test="taskId != null">task_id = #{taskId},</if>
|
||||
<if test="phoneId != null">phone_id = #{phoneId},</if>
|
||||
<if test="vehicleId != null">vehicle_id = #{vehicleId},</if>
|
||||
<if test="executionNumber != null">execution_number = #{executionNumber},</if>
|
||||
<if test="status != null">status = #{status},</if><if test="totalCases != null">total_cases = #{totalCases},</if>
|
||||
<if test="completedCases != null">completed_cases = #{completedCases},</if><if test="passedCases != null">passed_cases = #{passedCases},</if>
|
||||
<if test="failedCases != null">failed_cases = #{failedCases},</if><if test="progress != null">progress = #{progress},</if>
|
||||
<if test="startTime != null">start_time = #{startTime},</if><if test="endTime != null">end_time = #{endTime},</if>
|
||||
<if test="taskInsId != null">task_ins_id = #{taskInsId},</if>
|
||||
|
||||
</trim> where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaTaskInstanceById" parameterType="String">delete from aima_task_instance where id = #{id}</delete>
|
||||
<delete id="deleteAimaTaskInstanceByIds" parameterType="String">
|
||||
delete from aima_task_instance where id in <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaTaskMapper">
|
||||
<resultMap type="AimaTask" id="AimaTaskResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="taskCode" column="task_code"/>
|
||||
<result property="taskName" column="task_name"/>
|
||||
<result property="taskType" column="task_type"/>
|
||||
<result property="phoneId" column="phone_id"/>
|
||||
<result property="vehicleId" column="vehicle_id"/>
|
||||
<result property="testCaseCount" column="test_case_count"/>
|
||||
<result property="taskConfigId" column="task_config_id"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="com.cmvr.aima.domain.vo.AimaTaskVo" id="AimaTaskVoResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="taskCode" column="task_code"/>
|
||||
<result property="taskName" column="task_name"/>
|
||||
<result property="taskType" column="task_type"/>
|
||||
<result property="phoneId" column="phone_id"/>
|
||||
<result property="vehicleId" column="vehicle_id"/>
|
||||
<result property="testCaseCount" column="test_case_count"/>
|
||||
<result property="taskConfigId" column="task_config_id"/>
|
||||
<result property="phoneName" column="phone_name"/>
|
||||
<result property="vin" column="vin"/>
|
||||
<result property="createByName" column="create_by_name"/>
|
||||
<result property="updateByName" column="update_by_name"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaTaskVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, task_code, task_name, task_type, phone_id, vehicle_id, test_case_count, task_config_id from aima_task
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaTaskList" parameterType="AimaTask" resultMap="AimaTaskResult">
|
||||
<include refid="selectAimaTaskVo"/>
|
||||
<where>
|
||||
<if test="taskCode != null and taskCode != ''"> and task_code = #{taskCode}</if>
|
||||
<if test="taskName != null and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
|
||||
<if test="taskType != null and taskType != ''"> and task_type = #{taskType}</if>
|
||||
<if test="phoneId != null and phoneId != ''"> and phone_id = #{phoneId}</if>
|
||||
<if test="vehicleId != null and vehicleId != ''"> and vehicle_id = #{vehicleId}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTaskById" parameterType="String" resultMap="AimaTaskResult">
|
||||
<include refid="selectAimaTaskVo"/> where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTaskVoList" parameterType="AimaTask" resultMap="AimaTaskVoResult">
|
||||
select t.id, t.create_by, t.create_time, t.update_by, t.update_time, t.remark,
|
||||
t.task_code, t.task_name, t.task_type, t.phone_id, t.vehicle_id,
|
||||
t.test_case_count, t.task_config_id,
|
||||
p.phone_name, v.vin,
|
||||
u1.nick_name as create_by_name, u2.nick_name as update_by_name
|
||||
from aima_task t
|
||||
left join aima_phone p on t.phone_id = p.id
|
||||
left join aima_vehicle v on t.vehicle_id = v.id
|
||||
left join sys_user u1 on t.create_by = u1.user_name
|
||||
left join sys_user u2 on t.update_by = u2.user_name
|
||||
<where>
|
||||
<if test="taskCode != null and taskCode != ''"> and t.task_code = #{taskCode}</if>
|
||||
<if test="taskName != null and taskName != ''"> and t.task_name like concat('%', #{taskName}, '%')</if>
|
||||
<if test="taskType != null and taskType != ''"> and t.task_type = #{taskType}</if>
|
||||
<if test="phoneId != null and phoneId != ''"> and t.phone_id = #{phoneId}</if>
|
||||
<if test="vehicleId != null and vehicleId != ''"> and t.vehicle_id = #{vehicleId}</if>
|
||||
</where>
|
||||
order by t.create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaTask" parameterType="AimaTask">
|
||||
insert into aima_task <trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if><if test="createBy != null">create_by,</if><if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if><if test="updateTime != null">update_time,</if><if test="remark != null">remark,</if>
|
||||
<if test="taskCode != null">task_code,</if><if test="taskName != null">task_name,</if><if test="taskType != null">task_type,</if>
|
||||
<if test="phoneId != null">phone_id,</if><if test="vehicleId != null">vehicle_id,</if>
|
||||
<if test="testCaseCount != null">test_case_count,</if><if test="taskConfigId != null">task_config_id,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if><if test="createBy != null">#{createBy},</if><if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if><if test="updateTime != null">#{updateTime},</if><if test="remark != null">#{remark},</if>
|
||||
<if test="taskCode != null">#{taskCode},</if><if test="taskName != null">#{taskName},</if><if test="taskType != null">#{taskType},</if>
|
||||
<if test="phoneId != null">#{phoneId},</if><if test="vehicleId != null">#{vehicleId},</if>
|
||||
<if test="testCaseCount != null">#{testCaseCount},</if><if test="taskConfigId != null">#{taskConfigId},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaTask" parameterType="AimaTask">
|
||||
update aima_task <trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if><if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if><if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if><if test="taskCode != null">task_code = #{taskCode},</if>
|
||||
<if test="taskName != null">task_name = #{taskName},</if><if test="taskType != null">task_type = #{taskType},</if>
|
||||
<if test="phoneId != null">phone_id = #{phoneId},</if>
|
||||
<if test="vehicleId != null">vehicle_id = #{vehicleId},</if>
|
||||
<if test="testCaseCount != null">test_case_count = #{testCaseCount},</if><if test="taskConfigId != null">task_config_id = #{taskConfigId},</if>
|
||||
</trim> where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaTaskById" parameterType="String">delete from aima_task where id = #{id}</delete>
|
||||
<delete id="deleteAimaTaskByIds" parameterType="String">
|
||||
delete from aima_task where id in <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaTaskTestCaseMapper">
|
||||
|
||||
<insert id="batchInsertTaskTestCase">
|
||||
INSERT INTO aima_task_test_case (task_id, test_case_id, sort_order) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.taskId}, #{item.testCaseId}, #{item.sortOrder})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<delete id="deleteTaskTestCaseByTaskId" parameterType="String">
|
||||
DELETE FROM aima_task_test_case WHERE task_id = #{taskId}
|
||||
</delete>
|
||||
|
||||
<select id="selectTestCaseIdsByTaskId" parameterType="String" resultType="String">
|
||||
SELECT test_case_id FROM aima_task_test_case
|
||||
WHERE task_id = #{taskId}
|
||||
ORDER BY sort_order
|
||||
</select>
|
||||
|
||||
<delete id="deleteTaskTestCaseByTaskIds" parameterType="String">
|
||||
DELETE FROM aima_task_test_case WHERE task_id IN
|
||||
<foreach item="taskId" collection="array" open="(" separator="," close=")">
|
||||
#{taskId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
@ -1,167 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaTestCaseMapper">
|
||||
<resultMap type="AimaTestCase" id="AimaTestCaseResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="caseCode" column="case_code"/>
|
||||
<result property="caseName" column="case_name"/>
|
||||
<result property="caseCategory" column="case_category"/>
|
||||
<result property="testDescription" column="test_description"/>
|
||||
<result property="precondition" column="precondition"/>
|
||||
<result property="testSteps" column="test_steps"/>
|
||||
<result property="expectedResult" column="expected_result"/>
|
||||
<result property="priority" column="priority"/>
|
||||
<result property="enabled" column="enabled"/>
|
||||
<result property="sortOrder" column="sort_order"/>
|
||||
<result property="estimatedDuration" column="estimated_duration"/>
|
||||
<result property="detectItemId" column="detect_item_id"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="com.cmvr.aima.domain.vo.AimaTestCaseVo" id="AimaTestCaseVoResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="caseCode" column="case_code"/>
|
||||
<result property="caseName" column="case_name"/>
|
||||
<result property="caseCategory" column="case_category"/>
|
||||
<result property="testDescription" column="test_description"/>
|
||||
<result property="precondition" column="precondition"/>
|
||||
<result property="testSteps" column="test_steps"/>
|
||||
<result property="expectedResult" column="expected_result"/>
|
||||
<result property="priority" column="priority"/>
|
||||
<result property="enabled" column="enabled"/>
|
||||
<result property="sortOrder" column="sort_order"/>
|
||||
<result property="estimatedDuration" column="estimated_duration"/>
|
||||
<result property="detectItemId" column="detect_item_id"/>
|
||||
<result property="configStatus" column="config_status"/>
|
||||
<result property="createByName" column="create_by_name"/>
|
||||
<result property="updateByName" column="update_by_name"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaTestCaseVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, case_code, case_name, case_category, test_description, precondition, test_steps, expected_result, priority, enabled, sort_order, estimated_duration, detect_item_id from aima_test_case
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaTestCaseList" parameterType="AimaTestCase" resultMap="AimaTestCaseResult">
|
||||
<include refid="selectAimaTestCaseVo"/>
|
||||
<where>
|
||||
<if test="caseCode != null and caseCode != ''"> and case_code = #{caseCode}</if>
|
||||
<if test="caseName != null and caseName != ''"> and case_name like concat('%', #{caseName}, '%')</if>
|
||||
<if test="caseCategory != null and caseCategory != ''"> and case_category = #{caseCategory}</if>
|
||||
<if test="enabled != null and enabled != ''"> and enabled = #{enabled}</if>
|
||||
</where>
|
||||
order by sort_order asc, create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTestCaseById" parameterType="String" resultMap="AimaTestCaseResult">
|
||||
<include refid="selectAimaTestCaseVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTestCaseVoList" parameterType="AimaTestCase" resultMap="AimaTestCaseVoResult">
|
||||
select tc.id, tc.create_by, tc.create_time, tc.update_by, tc.update_time, tc.remark,
|
||||
tc.case_code, tc.case_name, tc.case_category, tc.test_description, tc.precondition,
|
||||
tc.test_steps, tc.expected_result, tc.priority, tc.enabled, tc.sort_order,
|
||||
tc.estimated_duration, tc.detect_item_id,
|
||||
d.is_deploy as config_status,
|
||||
u1.nick_name as create_by_name, u2.nick_name as update_by_name
|
||||
from aima_test_case tc
|
||||
left join te_detection_item d on tc.detect_item_id = d.id
|
||||
left join sys_user u1 on tc.create_by = u1.user_name
|
||||
left join sys_user u2 on tc.update_by = u2.user_name
|
||||
<where>
|
||||
<if test="caseCode != null and caseCode != ''"> and tc.case_code = #{caseCode}</if>
|
||||
<if test="caseName != null and caseName != ''"> and tc.case_name like concat('%', #{caseName}, '%')</if>
|
||||
<if test="caseCategory != null and caseCategory != ''"> and tc.case_category = #{caseCategory}</if>
|
||||
<if test="enabled != null and enabled != ''"> and tc.enabled = #{enabled}</if>
|
||||
</where>
|
||||
order by tc.sort_order, tc.create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaTestCase" parameterType="AimaTestCase">
|
||||
insert into aima_test_case
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="caseCode != null">case_code,</if>
|
||||
<if test="caseName != null">case_name,</if>
|
||||
<if test="caseCategory != null">case_category,</if>
|
||||
<if test="testDescription != null">test_description,</if>
|
||||
<if test="precondition != null">precondition,</if>
|
||||
<if test="testSteps != null">test_steps,</if>
|
||||
<if test="expectedResult != null">expected_result,</if>
|
||||
<if test="priority != null">priority,</if>
|
||||
<if test="enabled != null">enabled,</if>
|
||||
<if test="sortOrder != null">sort_order,</if>
|
||||
<if test="estimatedDuration != null">estimated_duration,</if>
|
||||
<if test="detectItemId != null">detect_item_id,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="caseCode != null">#{caseCode},</if>
|
||||
<if test="caseName != null">#{caseName},</if>
|
||||
<if test="caseCategory != null">#{caseCategory},</if>
|
||||
<if test="testDescription != null">#{testDescription},</if>
|
||||
<if test="precondition != null">#{precondition},</if>
|
||||
<if test="testSteps != null">#{testSteps},</if>
|
||||
<if test="expectedResult != null">#{expectedResult},</if>
|
||||
<if test="priority != null">#{priority},</if>
|
||||
<if test="enabled != null">#{enabled},</if>
|
||||
<if test="sortOrder != null">#{sortOrder},</if>
|
||||
<if test="estimatedDuration != null">#{estimatedDuration},</if>
|
||||
<if test="detectItemId != null">#{detectItemId},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaTestCase" parameterType="AimaTestCase">
|
||||
update aima_test_case
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="caseCode != null">case_code = #{caseCode},</if>
|
||||
<if test="caseName != null">case_name = #{caseName},</if>
|
||||
<if test="caseCategory != null">case_category = #{caseCategory},</if>
|
||||
<if test="testDescription != null">test_description = #{testDescription},</if>
|
||||
<if test="precondition != null">precondition = #{precondition},</if>
|
||||
<if test="testSteps != null">test_steps = #{testSteps},</if>
|
||||
<if test="expectedResult != null">expected_result = #{expectedResult},</if>
|
||||
<if test="priority != null">priority = #{priority},</if>
|
||||
<if test="enabled != null">enabled = #{enabled},</if>
|
||||
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
||||
<if test="estimatedDuration != null">estimated_duration = #{estimatedDuration},</if>
|
||||
<if test="detectItemId != null">detect_item_id = #{detectItemId},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaTestCaseById" parameterType="String">
|
||||
delete from aima_test_case where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAimaTestCaseByIds" parameterType="String">
|
||||
delete from aima_test_case where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaTestLogMapper">
|
||||
<resultMap type="AimaTestLog" id="AimaTestLogResult">
|
||||
<result property="id" column="id"/><result property="createBy" column="create_by"/><result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/><result property="updateTime" column="update_time"/><result property="remark" column="remark"/>
|
||||
<result property="taskInstanceId" column="task_instance_id"/><result property="taskId" column="task_id"/><result property="taskName" column="task_name"/>
|
||||
<result property="testCaseId" column="test_case_id"/><result property="caseName" column="case_name"/><result property="logLevel" column="log_level"/>
|
||||
<result property="logType" column="log_type"/><result property="logContent" column="log_content"/><result property="logTime" column="log_time"/>
|
||||
<result property="executionStep" column="execution_step"/><result property="actualResult" column="actual_result"/><result property="testStatus" column="test_status"/>
|
||||
<result property="screenshotUrl" column="screenshot_url"/><result property="videoUrl" column="video_url"/><result property="errorStack" column="error_stack"/>
|
||||
<result property="durationMs" column="duration_ms"/>
|
||||
<result property="progress" column="progress"/>
|
||||
<result property="status" column="status"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaTestLogVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, task_instance_id, task_id, task_name, test_case_id, case_name, log_level, log_type, log_content, log_time, execution_step, actual_result, test_status, screenshot_url, video_url, error_stack, duration_ms,progress,status from aima_test_log
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaTestLogList" parameterType="AimaTestLog" resultMap="AimaTestLogResult">
|
||||
<include refid="selectAimaTestLogVo"/>
|
||||
<where>
|
||||
<if test="taskInstanceId != null and taskInstanceId != ''"> and task_instance_id = #{taskInstanceId}</if>
|
||||
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
|
||||
<if test="testCaseId != null and testCaseId != ''"> and test_case_id = #{testCaseId}</if>
|
||||
<if test="logLevel != null and logLevel != ''"> and log_level = #{logLevel}</if>
|
||||
<if test="testStatus != null and testStatus != ''"> and test_status = #{testStatus}</if>
|
||||
</where>
|
||||
order by log_time
|
||||
</select>
|
||||
|
||||
<select id="selectAimaTestLogById" parameterType="String" resultMap="AimaTestLogResult">
|
||||
<include refid="selectAimaTestLogVo"/> where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaTestLog" parameterType="AimaTestLog">
|
||||
insert into aima_test_log <trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if><if test="createBy != null">create_by,</if><if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if><if test="updateTime != null">update_time,</if><if test="remark != null">remark,</if>
|
||||
<if test="taskInstanceId != null">task_instance_id,</if><if test="taskId != null">task_id,</if><if test="taskName != null">task_name,</if>
|
||||
<if test="testCaseId != null">test_case_id,</if><if test="caseName != null">case_name,</if><if test="logLevel != null">log_level,</if>
|
||||
<if test="logType != null">log_type,</if><if test="logContent != null">log_content,</if><if test="logTime != null">log_time,</if>
|
||||
<if test="executionStep != null">execution_step,</if><if test="actualResult != null">actual_result,</if><if test="testStatus != null">test_status,</if>
|
||||
<if test="screenshotUrl != null">screenshot_url,</if><if test="videoUrl != null">video_url,</if><if test="errorStack != null">error_stack,</if>
|
||||
<if test="durationMs != null">duration_ms,</if>
|
||||
<if test="progress != null">progress,</if>
|
||||
<if test="status != null">status,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if><if test="createBy != null">#{createBy},</if><if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if><if test="updateTime != null">#{updateTime},</if><if test="remark != null">#{remark},</if>
|
||||
<if test="taskInstanceId != null">#{taskInstanceId},</if><if test="taskId != null">#{taskId},</if><if test="taskName != null">#{taskName},</if>
|
||||
<if test="testCaseId != null">#{testCaseId},</if><if test="caseName != null">#{caseName},</if><if test="logLevel != null">#{logLevel},</if>
|
||||
<if test="logType != null">#{logType},</if><if test="logContent != null">#{logContent},</if><if test="logTime != null">#{logTime},</if>
|
||||
<if test="executionStep != null">#{executionStep},</if><if test="actualResult != null">#{actualResult},</if><if test="testStatus != null">#{testStatus},</if>
|
||||
<if test="screenshotUrl != null">#{screenshotUrl},</if><if test="videoUrl != null">#{videoUrl},</if><if test="errorStack != null">#{errorStack},</if>
|
||||
<if test="durationMs != null">#{durationMs},</if>
|
||||
<if test="progress != null">#{progress},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaTestLog" parameterType="AimaTestLog">
|
||||
update aima_test_log <trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if><if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if><if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if><if test="taskInstanceId != null">task_instance_id = #{taskInstanceId},</if>
|
||||
<if test="taskId != null">task_id = #{taskId},</if><if test="taskName != null">task_name = #{taskName},</if>
|
||||
<if test="testCaseId != null">test_case_id = #{testCaseId},</if><if test="caseName != null">case_name = #{caseName},</if>
|
||||
<if test="logLevel != null">log_level = #{logLevel},</if><if test="logType != null">log_type = #{logType},</if>
|
||||
<if test="logContent != null"> log_content = #{logContent},</if><if test="logTime != null">log_time = #{logTime},</if>
|
||||
<if test="executionStep != null">execution_step = #{executionStep},</if><if test="actualResult != null">actual_result = #{actualResult},</if>
|
||||
<if test="testStatus != null">test_status = #{testStatus},</if><if test="screenshotUrl != null">screenshot_url = #{screenshotUrl},</if>
|
||||
<if test="videoUrl != null">video_url = #{videoUrl},</if><if test="errorStack != null">error_stack = #{errorStack},</if>
|
||||
<if test="durationMs != null">duration_ms = #{durationMs},</if>
|
||||
<if test="progress != null">progress = #{progress},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
</trim> where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaTestLogById" parameterType="String">delete from aima_test_log where id = #{id}</delete>
|
||||
<delete id="deleteAimaTestLogByIds" parameterType="String">
|
||||
delete from aima_test_log where id in <foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cmvr.aima.mapper.AimaVehicleMapper">
|
||||
|
||||
<resultMap type="AimaVehicle" id="AimaVehicleResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="vin" column="vin" />
|
||||
<result property="vehicleModel" column="vehicle_model" />
|
||||
<result property="vehicleName" column="vehicle_name" />
|
||||
<result property="color" column="color" />
|
||||
<result property="productionDate" column="production_date" />
|
||||
<result property="status" column="status" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAimaVehicleVo">
|
||||
select id, create_by, create_time, update_by, update_time, remark, vin, vehicle_model, vehicle_name, color, production_date, status from aima_vehicle
|
||||
</sql>
|
||||
|
||||
<select id="selectAimaVehicleList" parameterType="AimaVehicle" resultMap="AimaVehicleResult">
|
||||
<include refid="selectAimaVehicleVo"/>
|
||||
<where>
|
||||
<if test="vin != null and vin != ''"> and vin = #{vin}</if>
|
||||
<if test="vehicleModel != null and vehicleModel != ''"> and vehicle_model like concat('%', #{vehicleModel}, '%')</if>
|
||||
<if test="vehicleName != null and vehicleName != ''"> and vehicle_name like concat('%', #{vehicleName}, '%')</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectAimaVehicleById" parameterType="String" resultMap="AimaVehicleResult">
|
||||
<include refid="selectAimaVehicleVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertAimaVehicle" parameterType="AimaVehicle">
|
||||
insert into aima_vehicle
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="vin != null">vin,</if>
|
||||
<if test="vehicleModel != null">vehicle_model,</if>
|
||||
<if test="vehicleName != null">vehicle_name,</if>
|
||||
<if test="color != null">color,</if>
|
||||
<if test="productionDate != null">production_date,</if>
|
||||
<if test="status != null">status,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="vin != null">#{vin},</if>
|
||||
<if test="vehicleModel != null">#{vehicleModel},</if>
|
||||
<if test="vehicleName != null">#{vehicleName},</if>
|
||||
<if test="color != null">#{color},</if>
|
||||
<if test="productionDate != null">#{productionDate},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAimaVehicle" parameterType="AimaVehicle">
|
||||
update aima_vehicle
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="vin != null">vin = #{vin},</if>
|
||||
<if test="vehicleModel != null">vehicle_model = #{vehicleModel},</if>
|
||||
<if test="vehicleName != null">vehicle_name = #{vehicleName},</if>
|
||||
<if test="color != null">color = #{color},</if>
|
||||
<if test="productionDate != null">production_date = #{productionDate},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAimaVehicleById" parameterType="String">
|
||||
delete from aima_vehicle where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAimaVehicleByIds" parameterType="String">
|
||||
delete from aima_vehicle where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -55,12 +55,6 @@
|
||||
<version>1.5.9</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.onvoid.webrtc</groupId>
|
||||
<artifactId>webrtc-java</artifactId>
|
||||
<version>0.14.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -1,887 +0,0 @@
|
||||
package com.cmvr.edge.client.adapter;
|
||||
|
||||
import cmvr.api.Common;
|
||||
import cmvr.api.MicPhoneServiceGrpc;
|
||||
import cmvr.api.MicrophoneCommand;
|
||||
import cmvr.api.SpeakerCommand;
|
||||
import cmvr.api.SpeakerServiceGrpc;
|
||||
import com.cmvr.edge.client.manage.GrpcServiceManager;
|
||||
import com.cmvr.edge.client.utils.EdgeCommonUtil;
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.stub.ClientCallStreamObserver;
|
||||
import io.grpc.stub.ClientResponseObserver;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* 实时语音对讲 gRPC 适配层。
|
||||
*
|
||||
* <p>当前机器人侧不再使用旧的 RobotAudio 双向流 proto,而是拆成两个现有服务:
|
||||
* 浏览器 -> 机器人:SpeakerService.StreamAudio 客户端流;
|
||||
* 机器人 -> 浏览器:MicPhoneService.StreamAudio 服务端流。</p>
|
||||
*
|
||||
* <p>音频格式固定为 PCM_S16LE / 48000Hz / 单声道 / 10ms / 960 bytes。
|
||||
* 所有发送到 gRPC StreamObserver 的动作都绑定到会话内单线程,避免并发 onNext 引发底层崩溃。</p>
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RobotAudioGrpcAdapter {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RobotAudioGrpcAdapter.class);
|
||||
|
||||
private static final int SAMPLE_RATE = 48000;
|
||||
private static final int CHANNELS = 1;
|
||||
private static final int BITS_PER_SAMPLE = 16;
|
||||
private static final int FRAME_MS = 10;
|
||||
private static final int FRAME_SAMPLES = SAMPLE_RATE * FRAME_MS / 1000;
|
||||
private static final int FRAME_BYTES = FRAME_SAMPLES * CHANNELS * (BITS_PER_SAMPLE / 8);
|
||||
private static final String CODEC = "PCM_S16LE";
|
||||
|
||||
private static final int MAX_QUEUED_BROWSER_FRAMES = 10;
|
||||
private static final int TARGET_QUEUED_BROWSER_FRAMES = 2;
|
||||
private static final long HEARTBEAT_INTERVAL_MS = 1000L;
|
||||
private static final long HEARTBEAT_DEADLINE_MS = 2000L;
|
||||
|
||||
private final GrpcServiceManager grpcServiceManager;
|
||||
private final ConcurrentMap<String, RobotAudioStream> streams = new ConcurrentHashMap<>();
|
||||
|
||||
public RobotAudioStream openStream(String terminalId,
|
||||
String deviceId,
|
||||
String sessionId,
|
||||
String operatorId,
|
||||
RobotAudioStreamListener listener) {
|
||||
return openStream(terminalId, deviceId, deviceId, sessionId, operatorId, listener);
|
||||
}
|
||||
|
||||
public RobotAudioStream openStream(String terminalId,
|
||||
String speakerDeviceId,
|
||||
String micDeviceId,
|
||||
String sessionId,
|
||||
String operatorId,
|
||||
RobotAudioStreamListener listener) {
|
||||
SpeakerServiceGrpc.SpeakerServiceStub speakerStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceStub micStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, MicPhoneServiceGrpc.MicPhoneServiceStub.class);
|
||||
SpeakerServiceGrpc.SpeakerServiceBlockingStub speakerBlockingStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, SpeakerServiceGrpc.SpeakerServiceBlockingStub.class);
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub micBlockingStub =
|
||||
grpcServiceManager.getGrpcClient(terminalId, MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class);
|
||||
|
||||
preflightDeviceStatus(speakerBlockingStub, micBlockingStub, speakerDeviceId, micDeviceId, sessionId);
|
||||
|
||||
RobotAudioStream stream = new RobotAudioStream(
|
||||
terminalId, speakerDeviceId, micDeviceId, sessionId, operatorId, speakerStub, micStub, listener);
|
||||
RobotAudioStream exists = streams.putIfAbsent(sessionId, stream);
|
||||
if (exists != null) {
|
||||
throw new IllegalStateException("实时语音会话已存在:" + sessionId);
|
||||
}
|
||||
|
||||
try {
|
||||
stream.start();
|
||||
log.info("实时对讲 gRPC 流已创建,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={},operatorId={},sampleRate={},channels={},bits={},frameMs={},frameBytes={}",
|
||||
sessionId, terminalId, speakerDeviceId, micDeviceId, operatorId, SAMPLE_RATE, CHANNELS, BITS_PER_SAMPLE, FRAME_MS, FRAME_BYTES);
|
||||
return stream;
|
||||
} catch (RuntimeException e) {
|
||||
streams.remove(sessionId, stream);
|
||||
stream.closeLocalResources();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
for (RobotAudioStream stream : streams.values()) {
|
||||
try {
|
||||
stream.cancel("application shutdown");
|
||||
} catch (Exception e) {
|
||||
log.debug("关闭实时语音流异常,sessionId={}", stream.getSessionId(), e);
|
||||
}
|
||||
}
|
||||
streams.clear();
|
||||
}
|
||||
|
||||
private void preflightDeviceStatus(SpeakerServiceGrpc.SpeakerServiceBlockingStub speakerStub,
|
||||
MicPhoneServiceGrpc.MicPhoneServiceBlockingStub micStub,
|
||||
String speakerDeviceId,
|
||||
String micDeviceId,
|
||||
String sessionId) {
|
||||
try {
|
||||
SpeakerCommand.GetSpeakerStateCommand.Request speakerRequest = SpeakerCommand.GetSpeakerStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(speakerDeviceId))
|
||||
.build();
|
||||
SpeakerCommand.GetSpeakerStateCommand.Feedback speakerFeedback =
|
||||
speakerStub.withDeadlineAfter(HEARTBEAT_DEADLINE_MS, TimeUnit.MILLISECONDS).getStatus(speakerRequest);
|
||||
if (speakerFeedback != null && speakerFeedback.hasHeader() && !speakerFeedback.getHeader().getSuccess()) {
|
||||
throw new IllegalStateException("speaker device unavailable: " + speakerFeedback.getHeader().getErrorMessage());
|
||||
}
|
||||
|
||||
MicrophoneCommand.GetMicStateCommand.Request micRequest = MicrophoneCommand.GetMicStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(micDeviceId))
|
||||
.build();
|
||||
MicrophoneCommand.GetMicStateCommand.Feedback micFeedback =
|
||||
micStub.withDeadlineAfter(HEARTBEAT_DEADLINE_MS, TimeUnit.MILLISECONDS).getStatus(micRequest);
|
||||
if (micFeedback != null && micFeedback.hasHeader() && !micFeedback.getHeader().getSuccess()) {
|
||||
throw new IllegalStateException("microphone device unavailable: " + micFeedback.getHeader().getErrorMessage());
|
||||
}
|
||||
log.info("实时对讲设备预检通过,sessionId={},speakerDeviceId={},micDeviceId={}", sessionId, speakerDeviceId, micDeviceId);
|
||||
} catch (RuntimeException e) {
|
||||
log.error("实时对讲设备预检失败,sessionId={},speakerDeviceId={},micDeviceId={}", sessionId, speakerDeviceId, micDeviceId, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public interface RobotAudioStreamListener {
|
||||
void onStarted(String sessionId, boolean accepted, String message);
|
||||
|
||||
void onRobotAudio(String sessionId, long sequence, long timestampMs, byte[] pcm);
|
||||
|
||||
void onHeartbeat(String sessionId, long timestampMs);
|
||||
|
||||
void onRobotStop(String sessionId, String reason);
|
||||
|
||||
void onError(String sessionId, Throwable throwable);
|
||||
|
||||
void onCompleted(String sessionId);
|
||||
}
|
||||
|
||||
public class RobotAudioStream {
|
||||
private final String terminalId;
|
||||
private final String speakerDeviceId;
|
||||
private final String micDeviceId;
|
||||
private final String sessionId;
|
||||
private final String operatorId;
|
||||
private final SpeakerServiceGrpc.SpeakerServiceStub speakerStub;
|
||||
private final MicPhoneServiceGrpc.MicPhoneServiceStub micStub;
|
||||
private final RobotAudioStreamListener listener;
|
||||
private final ScheduledExecutorService sendExecutor;
|
||||
private final ArrayBlockingQueue<byte[]> browserFrameQueue = new ArrayBlockingQueue<>(MAX_QUEUED_BROWSER_FRAMES);
|
||||
private final Object browserBufferLock = new Object();
|
||||
private final AtomicBoolean closed = new AtomicBoolean(false);
|
||||
private final AtomicBoolean terminalNotified = new AtomicBoolean(false);
|
||||
private final AtomicBoolean heartbeatInFlight = new AtomicBoolean(false);
|
||||
private final AtomicLong outboundSequence = new AtomicLong(0);
|
||||
private final AtomicLong inboundSequence = new AtomicLong(0);
|
||||
private final AtomicLong enqueued = new AtomicLong(0);
|
||||
private final AtomicLong sent = new AtomicLong(0);
|
||||
private final AtomicLong dropped = new AtomicLong(0);
|
||||
|
||||
private volatile StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Request> speakerRequestObserver;
|
||||
private volatile ClientCallStreamObserver<MicrophoneCommand.StreamMicAudioCommand.Request> micRequestObserver;
|
||||
private volatile ScheduledFuture<?> sendFuture;
|
||||
private volatile ScheduledFuture<?> heartbeatFuture;
|
||||
private volatile long lastStatsLogAt;
|
||||
private volatile byte[] pendingBrowserBytes = new byte[0];
|
||||
|
||||
private RobotAudioStream(String terminalId,
|
||||
String speakerDeviceId,
|
||||
String micDeviceId,
|
||||
String sessionId,
|
||||
String operatorId,
|
||||
SpeakerServiceGrpc.SpeakerServiceStub speakerStub,
|
||||
MicPhoneServiceGrpc.MicPhoneServiceStub micStub,
|
||||
RobotAudioStreamListener listener) {
|
||||
this.terminalId = terminalId;
|
||||
this.speakerDeviceId = speakerDeviceId;
|
||||
this.micDeviceId = micDeviceId;
|
||||
this.sessionId = sessionId;
|
||||
this.operatorId = operatorId;
|
||||
this.speakerStub = speakerStub;
|
||||
this.micStub = micStub;
|
||||
this.listener = listener;
|
||||
this.sendExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("robot-audio-send-" + sessionId));
|
||||
}
|
||||
|
||||
private void start() {
|
||||
openSpeakerStream();
|
||||
openMicStream();
|
||||
this.sendFuture = sendExecutor.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendOneBrowserFrame();
|
||||
}
|
||||
}, 0L, FRAME_MS, TimeUnit.MILLISECONDS);
|
||||
this.heartbeatFuture = sendExecutor.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
probeHeartbeat();
|
||||
}
|
||||
}, HEARTBEAT_INTERVAL_MS, HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS);
|
||||
listener.onStarted(sessionId, true, "audio stream started");
|
||||
}
|
||||
|
||||
private void openSpeakerStream() {
|
||||
StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Feedback> responseObserver =
|
||||
new StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Feedback>() {
|
||||
@Override
|
||||
public void onNext(SpeakerCommand.StreamSpeakerAudioCommand.Feedback feedback) {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
if (feedback != null && feedback.hasHeader() && !feedback.getHeader().getSuccess()) {
|
||||
fail("speaker feedback", new IllegalStateException("speaker stream feedback failed: " + feedback.getHeader().getErrorMessage()));
|
||||
} else {
|
||||
listener.onHeartbeat(sessionId, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
fail("speaker stream", t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
completeFromRemote();
|
||||
}
|
||||
};
|
||||
this.speakerRequestObserver = speakerStub.streamAudio(responseObserver);
|
||||
}
|
||||
|
||||
private void openMicStream() {
|
||||
MicrophoneCommand.StreamMicAudioCommand.Request request = MicrophoneCommand.StreamMicAudioCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(micDeviceId))
|
||||
.build();
|
||||
|
||||
micStub.streamAudio(request,
|
||||
new ClientResponseObserver<MicrophoneCommand.StreamMicAudioCommand.Request, MicrophoneCommand.StreamMicAudioCommand.Feedback>() {
|
||||
@Override
|
||||
public void beforeStart(ClientCallStreamObserver<MicrophoneCommand.StreamMicAudioCommand.Request> requestStream) {
|
||||
micRequestObserver = requestStream;
|
||||
requestStream.disableAutoInboundFlowControl();
|
||||
log.info("麦克风音频流已启用手动入站流控,sessionId={},micDeviceId={}", sessionId, micDeviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(MicrophoneCommand.StreamMicAudioCommand.Feedback feedback) {
|
||||
handleMicFeedback(feedback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
fail("mic stream", t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
completeFromRemote();
|
||||
}
|
||||
});
|
||||
requestNextMicFrame(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收浏览器 WebSocket 二进制 PCM。允许前端一次发多帧或半帧,这里按 10ms 固定帧重组。
|
||||
*/
|
||||
public void sendAudio(byte[] pcm) {
|
||||
if (closed.get() || pcm == null || pcm.length == 0) {
|
||||
return;
|
||||
}
|
||||
synchronized (browserBufferLock) {
|
||||
byte[] merged = new byte[pendingBrowserBytes.length + pcm.length];
|
||||
System.arraycopy(pendingBrowserBytes, 0, merged, 0, pendingBrowserBytes.length);
|
||||
System.arraycopy(pcm, 0, merged, pendingBrowserBytes.length, pcm.length);
|
||||
|
||||
int offset = 0;
|
||||
while (merged.length - offset >= FRAME_BYTES) {
|
||||
byte[] frame = Arrays.copyOfRange(merged, offset, offset + FRAME_BYTES);
|
||||
enqueueBrowserFrame(frame);
|
||||
offset += FRAME_BYTES;
|
||||
}
|
||||
pendingBrowserBytes = Arrays.copyOfRange(merged, offset, merged.length);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendHeartbeat() {
|
||||
if (!closed.get()) {
|
||||
probeHeartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendStop(String reason) {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
log.info("关闭实时对讲 gRPC 流,sessionId={},reason={}", sessionId, reason);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
completeSpeakerStream();
|
||||
cancelMicStream("browser stop");
|
||||
stopTerminalAudio();
|
||||
closeLocalResources();
|
||||
streams.remove(sessionId, RobotAudioStream.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancel(String reason) {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
log.warn("取消实时对讲 gRPC 流,sessionId={},reason={}", sessionId, reason);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
errorSpeakerStream(reason);
|
||||
cancelMicStream(reason);
|
||||
stopTerminalAudio();
|
||||
closeLocalResources();
|
||||
streams.remove(sessionId, RobotAudioStream.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public String getTerminalId() {
|
||||
return terminalId;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return speakerDeviceId;
|
||||
}
|
||||
|
||||
private void enqueueBrowserFrame(byte[] frame) {
|
||||
if (browserFrameQueue.remainingCapacity() == 0) {
|
||||
int targetDrops = Math.max(1, browserFrameQueue.size() - TARGET_QUEUED_BROWSER_FRAMES + 1);
|
||||
for (int i = 0; i < targetDrops; i++) {
|
||||
if (browserFrameQueue.poll() != null) {
|
||||
dropped.incrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (browserFrameQueue.offer(frame)) {
|
||||
enqueued.incrementAndGet();
|
||||
} else {
|
||||
dropped.incrementAndGet();
|
||||
}
|
||||
logBrowserAudioStatsIfNeeded("browserAudioEnqueue");
|
||||
}
|
||||
|
||||
private void sendOneBrowserFrame() {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = browserFrameQueue.poll();
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Request> observer = speakerRequestObserver;
|
||||
if (observer == null) {
|
||||
dropped.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
long sequence = outboundSequence.incrementAndGet();
|
||||
long timestampMs = System.currentTimeMillis();
|
||||
try {
|
||||
observer.onNext(buildSpeakerAudioRequest(frame, timestampMs));
|
||||
sent.incrementAndGet();
|
||||
logGrpcOutboundFormatIfNeeded(sequence, timestampMs, frame);
|
||||
logPcmStatsIfNeeded("grpc-outbound-browser", sequence, timestampMs, frame);
|
||||
logBrowserAudioStatsIfNeeded("browserAudioGrpcSend");
|
||||
} catch (Throwable t) {
|
||||
fail("speaker send", t);
|
||||
}
|
||||
}
|
||||
|
||||
private SpeakerCommand.StreamSpeakerAudioCommand.Request buildSpeakerAudioRequest(byte[] frame, long timestampMs) {
|
||||
Common.AudioData audio = Common.AudioData.newBuilder()
|
||||
.setData(ByteString.copyFrom(frame))
|
||||
.setSampleRate(SAMPLE_RATE)
|
||||
.setChannels(CHANNELS)
|
||||
.setFormat(Common.AudioData.AudioFormat.PCM)
|
||||
.setCodec(CODEC)
|
||||
.setPts(timestampMs)
|
||||
.setNbSamples(FRAME_SAMPLES)
|
||||
.build();
|
||||
return SpeakerCommand.StreamSpeakerAudioCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(speakerDeviceId))
|
||||
.setAudio(audio)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void handleMicFeedback(MicrophoneCommand.StreamMicAudioCommand.Feedback feedback) {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
if (feedback == null) {
|
||||
listener.onHeartbeat(sessionId, System.currentTimeMillis());
|
||||
requestNextMicFrame(FRAME_MS);
|
||||
return;
|
||||
}
|
||||
if (feedback.hasHeader() && !feedback.getHeader().getSuccess()) {
|
||||
fail("mic feedback", new IllegalStateException("microphone stream feedback failed: " + feedback.getHeader().getErrorMessage()));
|
||||
return;
|
||||
}
|
||||
listener.onHeartbeat(sessionId, System.currentTimeMillis());
|
||||
if (!feedback.hasAudio()) {
|
||||
requestNextMicFrame(FRAME_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
Common.AudioData audio = feedback.getAudio();
|
||||
byte[] pcm = audio.getData().toByteArray();
|
||||
if (!validateInboundAudio(audio, pcm)) {
|
||||
requestNextMicFrame(FRAME_MS);
|
||||
return;
|
||||
}
|
||||
long audioDurationMs = calculateAudioDurationMs(audio, pcm);
|
||||
long sequence = inboundSequence.incrementAndGet();
|
||||
long timestampMs = audio.getPts() > 0 ? audio.getPts() : System.currentTimeMillis();
|
||||
logGrpcInboundFormatIfNeeded(sequence, timestampMs, audio, pcm);
|
||||
logPcmStatsIfNeeded("grpc-inbound-robot", sequence, timestampMs, pcm);
|
||||
byte[] normalizedPcm = normalizeInboundAudio(audio, pcm, sequence, timestampMs);
|
||||
logPcmStatsIfNeeded("webrtc-outbound-robot-normalized", sequence, timestampMs, normalizedPcm);
|
||||
try {
|
||||
listener.onRobotAudio(sessionId, sequence, timestampMs, normalizedPcm);
|
||||
} catch (Throwable t) {
|
||||
log.error("投递机器人音频到业务层失败,sessionId={},sequence={}", sessionId, sequence, t);
|
||||
fail("business callback", t);
|
||||
return;
|
||||
}
|
||||
requestNextMicFrame(audioDurationMs);
|
||||
}
|
||||
|
||||
private boolean validateInboundAudio(Common.AudioData audio, byte[] pcm) {
|
||||
if (pcm == null || pcm.length == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((pcm.length & 1) != 0) {
|
||||
log.warn("机器人上行 PCM 字节数不是偶数,sessionId={},bytes={}", sessionId, pcm.length);
|
||||
return false;
|
||||
}
|
||||
if (audio.getFormat() != Common.AudioData.AudioFormat.PCM) {
|
||||
log.warn("机器人上行音频格式不是 PCM,sessionId={},format={}", sessionId, audio.getFormat());
|
||||
return false;
|
||||
}
|
||||
String codec = audio.getCodec();
|
||||
if (codec != null && codec.length() > 0 && !CODEC.equalsIgnoreCase(codec)) {
|
||||
log.warn("机器人上行编码不匹配,sessionId={},codec={},expected={}", sessionId, codec, CODEC);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private long calculateAudioDurationMs(Common.AudioData audio, byte[] pcm) {
|
||||
int sampleRate = audio.getSampleRate() <= 0 ? SAMPLE_RATE : audio.getSampleRate();
|
||||
int channels = audio.getChannels() <= 0 ? CHANNELS : audio.getChannels();
|
||||
int samples = audio.getNbSamples();
|
||||
if (samples <= 0 && pcm != null && pcm.length > 0) {
|
||||
samples = pcm.length / 2 / Math.max(1, channels);
|
||||
}
|
||||
if (sampleRate <= 0 || samples <= 0) {
|
||||
return FRAME_MS;
|
||||
}
|
||||
return Math.max(1L, Math.round(samples * 1000.0D / sampleRate));
|
||||
}
|
||||
|
||||
private void requestNextMicFrame(long delayMs) {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
final long safeDelayMs = Math.max(1L, delayMs);
|
||||
sendExecutor.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (closed.get()) {
|
||||
return;
|
||||
}
|
||||
ClientCallStreamObserver<MicrophoneCommand.StreamMicAudioCommand.Request> observer = micRequestObserver;
|
||||
if (observer == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
observer.request(1);
|
||||
} catch (Throwable t) {
|
||||
fail("mic flow-control request", t);
|
||||
}
|
||||
}
|
||||
}, safeDelayMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private byte[] normalizeInboundAudio(Common.AudioData audio, byte[] pcm, long sequence, long timestampMs) {
|
||||
int sourceSampleRate = audio.getSampleRate() <= 0 ? SAMPLE_RATE : audio.getSampleRate();
|
||||
int sourceChannels = audio.getChannels() <= 0 ? CHANNELS : audio.getChannels();
|
||||
if (sourceSampleRate == SAMPLE_RATE && sourceChannels == CHANNELS) {
|
||||
return pcm;
|
||||
}
|
||||
|
||||
short[] monoSamples = decodeToMonoSamples(pcm, sourceChannels);
|
||||
short[] normalizedSamples = sourceSampleRate == SAMPLE_RATE
|
||||
? monoSamples
|
||||
: resampleLinear(monoSamples, sourceSampleRate, SAMPLE_RATE);
|
||||
byte[] normalizedPcm = encodeMonoSamples(normalizedSamples);
|
||||
if (sequence == 1 || sequence % 500 == 0) {
|
||||
log.info("机器人上行音频已标准化,sessionId={},sourceSampleRate={},sourceChannels={},targetSampleRate={},targetChannels={},sourceBytes={},targetBytes={},sequence={},timestampMs={}",
|
||||
sessionId, sourceSampleRate, sourceChannels, SAMPLE_RATE, CHANNELS, pcm.length, normalizedPcm.length, sequence, timestampMs);
|
||||
}
|
||||
return normalizedPcm;
|
||||
}
|
||||
|
||||
private short[] decodeToMonoSamples(byte[] pcm, int sourceChannels) {
|
||||
int channels = Math.max(1, sourceChannels);
|
||||
int frameCount = pcm.length / 2 / channels;
|
||||
short[] mono = new short[frameCount];
|
||||
for (int frame = 0; frame < frameCount; frame++) {
|
||||
int sum = 0;
|
||||
for (int channel = 0; channel < channels; channel++) {
|
||||
int sampleIndex = (frame * channels + channel) * 2;
|
||||
int lo = pcm[sampleIndex] & 0xff;
|
||||
int hi = pcm[sampleIndex + 1];
|
||||
sum += (short) ((hi << 8) | lo);
|
||||
}
|
||||
mono[frame] = (short) (sum / channels);
|
||||
}
|
||||
return mono;
|
||||
}
|
||||
|
||||
private short[] resampleLinear(short[] input, int sourceSampleRate, int targetSampleRate) {
|
||||
if (input.length == 0 || sourceSampleRate <= 0 || targetSampleRate <= 0) {
|
||||
return input;
|
||||
}
|
||||
int outputLength = Math.max(1, (int) Math.round(input.length * (targetSampleRate / (double) sourceSampleRate)));
|
||||
short[] output = new short[outputLength];
|
||||
double sourceStep = sourceSampleRate / (double) targetSampleRate;
|
||||
for (int i = 0; i < outputLength; i++) {
|
||||
double sourceIndex = i * sourceStep;
|
||||
int left = (int) sourceIndex;
|
||||
int right = Math.min(left + 1, input.length - 1);
|
||||
double fraction = sourceIndex - left;
|
||||
double value = input[left] + (input[right] - input[left]) * fraction;
|
||||
output[i] = clampToShort((int) Math.round(value));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private byte[] encodeMonoSamples(short[] samples) {
|
||||
byte[] pcm = new byte[samples.length * 2];
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
pcm[i * 2] = (byte) (samples[i] & 0xff);
|
||||
pcm[i * 2 + 1] = (byte) ((samples[i] >> 8) & 0xff);
|
||||
}
|
||||
return pcm;
|
||||
}
|
||||
|
||||
private short clampToShort(int value) {
|
||||
if (value > Short.MAX_VALUE) {
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
if (value < Short.MIN_VALUE) {
|
||||
return Short.MIN_VALUE;
|
||||
}
|
||||
return (short) value;
|
||||
}
|
||||
|
||||
private void probeHeartbeat() {
|
||||
if (closed.get() || !heartbeatInFlight.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
MicrophoneCommand.GetMicStateCommand.Request request = MicrophoneCommand.GetMicStateCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(micDeviceId))
|
||||
.build();
|
||||
micStub.withDeadlineAfter(HEARTBEAT_DEADLINE_MS, TimeUnit.MILLISECONDS).getStatus(request,
|
||||
new StreamObserver<MicrophoneCommand.GetMicStateCommand.Feedback>() {
|
||||
@Override
|
||||
public void onNext(MicrophoneCommand.GetMicStateCommand.Feedback feedback) {
|
||||
if (feedback != null && feedback.hasHeader() && !feedback.getHeader().getSuccess()) {
|
||||
log.warn("实时对讲麦克风心跳返回失败,sessionId={},message={}", sessionId, feedback.getHeader().getErrorMessage());
|
||||
return;
|
||||
}
|
||||
listener.onHeartbeat(sessionId, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
log.debug("实时对讲麦克风心跳探测失败,sessionId={}", sessionId, t);
|
||||
heartbeatInFlight.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
heartbeatInFlight.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fail(String source, Throwable throwable) {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
Throwable actual = throwable == null ? new RuntimeException("audio stream failed") : throwable;
|
||||
log.error("实时对讲 gRPC 流异常,source={},sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}",
|
||||
source, sessionId, terminalId, speakerDeviceId, micDeviceId, actual);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
errorSpeakerStream(actual.getMessage());
|
||||
cancelMicStream(actual.getMessage());
|
||||
stopTerminalAudio();
|
||||
closeLocalResources();
|
||||
streams.remove(sessionId, RobotAudioStream.this);
|
||||
if (terminalNotified.compareAndSet(false, true)) {
|
||||
listener.onError(sessionId, actual);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void completeFromRemote() {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
log.info("实时对讲 gRPC 流远端结束,sessionId={},terminalId={},speakerDeviceId={},micDeviceId={}", sessionId, terminalId, speakerDeviceId, micDeviceId);
|
||||
sendExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
completeSpeakerStream();
|
||||
cancelMicStream("remote completed");
|
||||
closeLocalResources();
|
||||
streams.remove(sessionId, RobotAudioStream.this);
|
||||
if (terminalNotified.compareAndSet(false, true)) {
|
||||
listener.onCompleted(sessionId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void completeSpeakerStream() {
|
||||
StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Request> observer = speakerRequestObserver;
|
||||
speakerRequestObserver = null;
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onCompleted();
|
||||
} catch (Throwable t) {
|
||||
log.debug("完成扬声器音频流异常,sessionId={}", sessionId, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void errorSpeakerStream(String reason) {
|
||||
StreamObserver<SpeakerCommand.StreamSpeakerAudioCommand.Request> observer = speakerRequestObserver;
|
||||
speakerRequestObserver = null;
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.onError(Status.CANCELLED.withDescription(reason == null ? "audio cancelled" : reason).asRuntimeException());
|
||||
} catch (Throwable t) {
|
||||
log.debug("取消扬声器音频流异常,sessionId={}", sessionId, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelMicStream(String reason) {
|
||||
ClientCallStreamObserver<MicrophoneCommand.StreamMicAudioCommand.Request> observer = micRequestObserver;
|
||||
micRequestObserver = null;
|
||||
if (observer != null) {
|
||||
try {
|
||||
observer.cancel(reason == null ? "audio cancelled" : reason, null);
|
||||
} catch (Throwable t) {
|
||||
log.debug("取消麦克风音频流异常,sessionId={}", sessionId, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话关闭时尽量停止终端侧播放和采集,失败不阻断本地资源释放。
|
||||
*/
|
||||
private void stopTerminalAudio() {
|
||||
try {
|
||||
SpeakerCommand.StopSpeakerCommand.Request speakerStop = SpeakerCommand.StopSpeakerCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(speakerDeviceId))
|
||||
.build();
|
||||
speakerStub.withDeadlineAfter(HEARTBEAT_DEADLINE_MS, TimeUnit.MILLISECONDS).stopPlayback(speakerStop,
|
||||
new EmptyStreamObserver<SpeakerCommand.StopSpeakerCommand.Feedback>("stop speaker", sessionId));
|
||||
} catch (Throwable t) {
|
||||
log.debug("下发停止扬声器失败,sessionId={}", sessionId, t);
|
||||
}
|
||||
try {
|
||||
MicrophoneCommand.StopMicRecordingCommand.Request micStop = MicrophoneCommand.StopMicRecordingCommand.Request.newBuilder()
|
||||
.setHeader(EdgeCommonUtil.buildRequest(micDeviceId))
|
||||
.build();
|
||||
micStub.withDeadlineAfter(HEARTBEAT_DEADLINE_MS, TimeUnit.MILLISECONDS).stopRecord(micStop,
|
||||
new EmptyStreamObserver<MicrophoneCommand.StopMicRecordingCommand.Feedback>("stop mic", sessionId));
|
||||
} catch (Throwable t) {
|
||||
log.debug("下发停止麦克风失败,sessionId={}", sessionId, t);
|
||||
}
|
||||
}
|
||||
|
||||
private void closeLocalResources() {
|
||||
ScheduledFuture<?> sf = sendFuture;
|
||||
if (sf != null) {
|
||||
sf.cancel(false);
|
||||
}
|
||||
ScheduledFuture<?> hf = heartbeatFuture;
|
||||
if (hf != null) {
|
||||
hf.cancel(false);
|
||||
}
|
||||
browserFrameQueue.clear();
|
||||
pendingBrowserBytes = new byte[0];
|
||||
if (!sendExecutor.isShutdown()) {
|
||||
sendExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void logGrpcInboundFormatIfNeeded(long sequence, long timestampMs, Common.AudioData audio, byte[] pcm) {
|
||||
if (sequence == 1 || sequence % 500 == 0) {
|
||||
log.info("gRPC机器人上行音频格式,sessionId={},sampleRate={},channels={},bitsPerSample={},encoding={},frameSamples={},frameMs={},bytes={},sequence={},timestampMs={}",
|
||||
sessionId,
|
||||
audio.getSampleRate() == 0 ? SAMPLE_RATE : audio.getSampleRate(),
|
||||
audio.getChannels() == 0 ? CHANNELS : audio.getChannels(),
|
||||
BITS_PER_SAMPLE,
|
||||
audio.getCodec() == null || audio.getCodec().length() == 0 ? CODEC : audio.getCodec(),
|
||||
audio.getNbSamples() == 0 ? pcm.length / 2 : audio.getNbSamples(),
|
||||
FRAME_MS,
|
||||
pcm.length,
|
||||
sequence,
|
||||
timestampMs);
|
||||
}
|
||||
}
|
||||
|
||||
private void logGrpcOutboundFormatIfNeeded(long sequence, long timestampMs, byte[] frame) {
|
||||
if (sequence == 1 || sequence % 500 == 0) {
|
||||
log.info("gRPC浏览器下行音频格式,sessionId={},sampleRate={},channels={},bitsPerSample={},encoding={},frameSamples={},frameMs={},bytes={},sequence={},timestampMs={}",
|
||||
sessionId, SAMPLE_RATE, CHANNELS, BITS_PER_SAMPLE, CODEC, FRAME_SAMPLES, FRAME_MS, frame.length, sequence, timestampMs);
|
||||
}
|
||||
}
|
||||
|
||||
private void logBrowserAudioStatsIfNeeded(String source) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastStatsLogAt < 5000L) {
|
||||
return;
|
||||
}
|
||||
lastStatsLogAt = now;
|
||||
log.info("gRPC浏览器音频统计,source={},sessionId={},enqueued={},sent={},dropped={},queued={}",
|
||||
source, sessionId, enqueued.get(), sent.get(), dropped.get(), browserFrameQueue.size());
|
||||
}
|
||||
|
||||
private void logPcmStatsIfNeeded(String direction, long sequence, long timestampMs, byte[] pcm) {
|
||||
if (sequence != 1 && sequence % 500 != 0) {
|
||||
return;
|
||||
}
|
||||
PcmStats stats = PcmStats.from(pcm);
|
||||
log.info("PCM-STATS direction={} sessionId={} sequence={} timestampMs={} bytes={} samples={} rms={} peak={} zeroCrossRate={} firstSamples={}",
|
||||
direction, sessionId, sequence, timestampMs, pcm.length, stats.samples, stats.rms, stats.peak, stats.zeroCrossRate, stats.firstSamples);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyStreamObserver<T> implements StreamObserver<T> {
|
||||
private final String action;
|
||||
private final String sessionId;
|
||||
|
||||
private EmptyStreamObserver(String action, String sessionId) {
|
||||
this.action = action;
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(T value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
log.debug("{} failed, sessionId={}", action, sessionId, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class NamedThreadFactory implements ThreadFactory {
|
||||
private final String name;
|
||||
|
||||
private NamedThreadFactory(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, name);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PcmStats {
|
||||
private final int samples;
|
||||
private final long rms;
|
||||
private final int peak;
|
||||
private final String zeroCrossRate;
|
||||
private final String firstSamples;
|
||||
|
||||
private PcmStats(int samples, long rms, int peak, String zeroCrossRate, String firstSamples) {
|
||||
this.samples = samples;
|
||||
this.rms = rms;
|
||||
this.peak = peak;
|
||||
this.zeroCrossRate = zeroCrossRate;
|
||||
this.firstSamples = firstSamples;
|
||||
}
|
||||
|
||||
private static PcmStats from(byte[] pcm) {
|
||||
int samples = pcm == null ? 0 : pcm.length / 2;
|
||||
if (samples == 0) {
|
||||
return new PcmStats(0, 0, 0, "0.0000", "[]");
|
||||
}
|
||||
long squareSum = 0L;
|
||||
int peak = 0;
|
||||
int zeroCross = 0;
|
||||
int previous = 0;
|
||||
StringBuilder first = new StringBuilder("[");
|
||||
for (int i = 0; i < samples; i++) {
|
||||
int lo = pcm[i * 2] & 0xff;
|
||||
int hi = pcm[i * 2 + 1];
|
||||
int value = (short) ((hi << 8) | lo);
|
||||
int abs = Math.abs(value);
|
||||
if (abs > peak) {
|
||||
peak = abs;
|
||||
}
|
||||
squareSum += (long) value * value;
|
||||
if (i > 0 && ((previous < 0 && value >= 0) || (previous >= 0 && value < 0))) {
|
||||
zeroCross++;
|
||||
}
|
||||
previous = value;
|
||||
if (i < 8) {
|
||||
if (i > 0) {
|
||||
first.append(',');
|
||||
}
|
||||
first.append(value);
|
||||
}
|
||||
}
|
||||
first.append(']');
|
||||
long rms = (long) Math.sqrt(squareSum / (double) samples);
|
||||
String zcr = String.format("%.4f", zeroCross / (double) samples);
|
||||
return new PcmStats(samples, rms, peak, zcr, first.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -47,21 +47,16 @@ public class GrpcServiceManager {
|
||||
clientFactories.put(SystemServiceGrpc.SystemServiceBlockingStub.class, new GrpcClientFactory<>(SystemServiceGrpc::newBlockingStub));
|
||||
// 注册扬声器服务的 Stub
|
||||
clientFactories.put(SpeakerServiceGrpc.SpeakerServiceBlockingStub.class, new GrpcClientFactory<>(SpeakerServiceGrpc::newBlockingStub));
|
||||
clientFactories.put(SpeakerServiceGrpc.SpeakerServiceStub.class, new GrpcClientFactory<>(SpeakerServiceGrpc::newStub));
|
||||
// 注册麦克风服务的 Stub
|
||||
clientFactories.put(MicPhoneServiceGrpc.MicPhoneServiceBlockingStub.class, new GrpcClientFactory<>(MicPhoneServiceGrpc::newBlockingStub));
|
||||
clientFactories.put(MicPhoneServiceGrpc.MicPhoneServiceStub.class, new GrpcClientFactory<>(MicPhoneServiceGrpc::newStub));
|
||||
// 注册机器人头部服务的 Stub
|
||||
clientFactories.put(BioHeadServiceGrpc.BioHeadServiceBlockingStub.class, new GrpcClientFactory<>(BioHeadServiceGrpc::newBlockingStub));
|
||||
// 注册机器人灵巧手服务的 Stub
|
||||
clientFactories.put(DexHandServiceGrpc.DexHandServiceBlockingStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newBlockingStub));
|
||||
clientFactories.put(DexHandServiceGrpc.DexHandServiceStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newStub));
|
||||
// 注册机械臂服务的stub
|
||||
clientFactories.put(ArmServiceGrpc.ArmServiceBlockingStub.class, new GrpcClientFactory<>(ArmServiceGrpc::newBlockingStub));
|
||||
clientFactories.put(HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class, new GrpcClientFactory<>(HumanoidRobotServiceGrpc::newBlockingStub));
|
||||
clientFactories.put(HlcServiceGrpc.HlcServiceBlockingStub.class, new GrpcClientFactory<>(HlcServiceGrpc::newBlockingStub));
|
||||
// 注册agv服务的stub
|
||||
clientFactories.put(AgvServiceGrpc.AgvServiceBlockingStub.class, new GrpcClientFactory<>(AgvServiceGrpc::newBlockingStub));
|
||||
// 注册机器人实时语音双向流服务的异步Stub
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AGV电池状态VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("AGV电池状态")
|
||||
public class EdgeAgvBatteryStatusVO {
|
||||
|
||||
@ApiModelProperty("电池电量百分比(0-100)")
|
||||
private double batteryPercent;
|
||||
|
||||
@ApiModelProperty("电池电压(单位:伏特)")
|
||||
private double voltage;
|
||||
|
||||
@ApiModelProperty("电池电流(单位:安培)")
|
||||
private double current;
|
||||
|
||||
@ApiModelProperty("充电状态(true=充电中,false=未充电)")
|
||||
private boolean charging;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* AGV 地图名称请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV地图名称参数")
|
||||
public class EdgeAgvMapNameVO extends EdgeCommonVO {
|
||||
|
||||
@NotEmpty(message = "地图名称不能为空")
|
||||
@ApiModelProperty(value = "地图名称", required = true)
|
||||
private String mapName;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* AGV 导航到指定坐标的请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV导航到指定坐标参数")
|
||||
public class EdgeAgvNavigateToPoseVO extends EdgeCommonVO {
|
||||
|
||||
@ApiModelProperty(value = "目标 X 坐标,单位:米", required = true)
|
||||
private double x;
|
||||
|
||||
@ApiModelProperty(value = "目标 Y 坐标,单位:米", required = true)
|
||||
private double y;
|
||||
|
||||
@ApiModelProperty(value = "目标朝向角,单位:弧度", required = true)
|
||||
private double theta;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* AGV 导航到站点的请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV导航到站点参数")
|
||||
public class EdgeAgvNavigateToStationVO extends EdgeCommonVO {
|
||||
|
||||
@NotEmpty(message = "站点ID不能为空")
|
||||
@ApiModelProperty(value = "站点ID", required = true)
|
||||
private String stationId;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AGV导航任务结果VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("AGV导航任务结果")
|
||||
public class EdgeAgvNavigationResultVO {
|
||||
|
||||
@ApiModelProperty("返回码(0=成功)")
|
||||
private int retCode;
|
||||
|
||||
@ApiModelProperty("错误信息")
|
||||
private String errMsg;
|
||||
|
||||
@ApiModelProperty("任务ID")
|
||||
private String taskId;
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AGV机器人位置VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("AGV机器人位置")
|
||||
public class EdgeAgvRobotLocationVO {
|
||||
|
||||
@ApiModelProperty("X坐标(单位:米)")
|
||||
private double x;
|
||||
|
||||
@ApiModelProperty("Y坐标(单位:米)")
|
||||
private double y;
|
||||
|
||||
@ApiModelProperty("角度(单位:弧度)")
|
||||
private double theta;
|
||||
|
||||
@ApiModelProperty("地图名称")
|
||||
private String mapName;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* AGV 开始建图请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV开始建图参数")
|
||||
public class EdgeAgvStartMappingVO extends EdgeCommonVO {
|
||||
|
||||
@ApiModelProperty(value = "建图维度:0=未指定,1=2D,2=3D,3=2D+3D", required = true)
|
||||
private int dimension;
|
||||
|
||||
@ApiModelProperty("地图名称,可为空")
|
||||
private String mapName;
|
||||
|
||||
@ApiModelProperty(value = "是否实时建图", required = true)
|
||||
private boolean realTime;
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AGV站点信息VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("AGV站点信息")
|
||||
public class EdgeAgvStationVO {
|
||||
|
||||
@ApiModelProperty("站点ID")
|
||||
private String stationId;
|
||||
|
||||
@ApiModelProperty("站点名称")
|
||||
private String stationName;
|
||||
|
||||
@ApiModelProperty("X坐标(单位:米)")
|
||||
private double x;
|
||||
|
||||
@ApiModelProperty("Y坐标(单位:米)")
|
||||
private double y;
|
||||
|
||||
@ApiModelProperty("角度(单位:弧度)")
|
||||
private double theta;
|
||||
|
||||
@ApiModelProperty("站点类型")
|
||||
private String stationType;
|
||||
|
||||
@ApiModelProperty("站点描述")
|
||||
private String description;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AGV任务状态VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("AGV任务状态")
|
||||
public class EdgeAgvTaskStatusVO {
|
||||
|
||||
@ApiModelProperty("任务状态")
|
||||
private int taskStatus;
|
||||
|
||||
@ApiModelProperty("当前站点ID")
|
||||
private String currentStationId;
|
||||
|
||||
@ApiModelProperty("目标站点ID")
|
||||
private String targetStationId;
|
||||
|
||||
@ApiModelProperty("已经过的站点数量")
|
||||
private int passedStationCount;
|
||||
|
||||
@ApiModelProperty("剩余站点数量")
|
||||
private int remainingStationCount;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* AGV 上传地图请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV上传地图参数")
|
||||
public class EdgeAgvUploadMapVO extends EdgeAgvMapNameVO {
|
||||
|
||||
@NotEmpty(message = "地图内容不能为空")
|
||||
@ApiModelProperty(value = "地图内容", required = true)
|
||||
private String content;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package com.cmvr.edge.client.model.agv;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* AGV 速度控制请求参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("AGV速度控制参数")
|
||||
public class EdgeAgvVelocityVO extends EdgeCommonVO {
|
||||
|
||||
@ApiModelProperty(value = "X 方向线速度,单位:m/s", required = true)
|
||||
private double vx;
|
||||
|
||||
@ApiModelProperty(value = "Y 方向线速度,单位:m/s", required = true)
|
||||
private double vy;
|
||||
|
||||
@ApiModelProperty(value = "角速度,单位:rad/s", required = true)
|
||||
private double wz;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package com.cmvr.edge.client.model.arm;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 机械臂标定零点参数。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("机械臂标定零点参数")
|
||||
public class EdgeArmCalibrateZeroQVO extends EdgeCommonVO {
|
||||
|
||||
@NotEmpty(message = "关节名称不能为空")
|
||||
@ApiModelProperty(value = "关节名称", required = true)
|
||||
private String jointName;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package com.cmvr.edge.client.model.arm;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 机械臂笛卡尔位姿VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("机械臂笛卡尔位姿")
|
||||
public class EdgeArmCartesianPoseVO {
|
||||
|
||||
@ApiModelProperty("X轴坐标(单位:米)")
|
||||
private double x;
|
||||
|
||||
@ApiModelProperty("Y轴坐标(单位:米)")
|
||||
private double y;
|
||||
|
||||
@ApiModelProperty("Z轴坐标(单位:米)")
|
||||
private double z;
|
||||
|
||||
@ApiModelProperty("RX旋转角度(单位:弧度)")
|
||||
private double rx;
|
||||
|
||||
@ApiModelProperty("RY旋转角度(单位:弧度)")
|
||||
private double ry;
|
||||
|
||||
@ApiModelProperty("RZ旋转角度(单位:弧度)")
|
||||
private double rz;
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.cmvr.edge.client.model.arm;
|
||||
|
||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 机械臂正向运动学计算VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("机械臂正向运动学计算参数")
|
||||
public class EdgeArmForwardKinematicsVO extends EdgeCommonVO {
|
||||
|
||||
@ApiModelProperty(value = "关节位置数组(6个关节角度,单位:弧度)", required = true)
|
||||
private double[] joints;
|
||||
|
||||
@ApiModelProperty("基座连杆名称")
|
||||
private String baseLink;
|
||||
|
||||
@ApiModelProperty("末端执行器连杆名称")
|
||||
private String eeLink;
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
package com.cmvr.edge.client.model.arm;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 机械臂关节状态VO
|
||||
*
|
||||
* @author cmvr-iot
|
||||
* @since 2026-07-01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("机械臂关节状态")
|
||||
public class EdgeArmJointStateVO {
|
||||
|
||||
@ApiModelProperty("关节名称列表")
|
||||
private List<String> name;
|
||||
|
||||
@ApiModelProperty("关节位置列表(单位:弧度)")
|
||||
private List<Double> position;
|
||||
|
||||
@ApiModelProperty("关节速度列表(单位:rad/s)")
|
||||
private List<Double> velocity;
|
||||
|
||||
@ApiModelProperty("关节力矩列表")
|
||||
private List<Double> effort;
|
||||
|
||||
@ApiModelProperty("时间戳")
|
||||
private double timestamp;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user