package com.ruoyi.envaccess.controller;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.ruoyi.common.handler.CustomTenantLineHandler;
|
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
|
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
|
import com.ruoyi.framework.web.domain.AjaxResult;
|
import com.ruoyi.envaccess.pojo.EnvInspection;
|
import com.ruoyi.envaccess.service.IEnvInspectionService;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.web.bind.annotation.*;
|
|
import javax.annotation.Resource;
|
import javax.servlet.http.HttpServletResponse;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 环保门禁--智能巡检台账(含路径规划/AI视频分析/报告/无人机机器人,AI与无人机字段预留)
|
*/
|
@RestController
|
@RequestMapping("/environmentAccess/inspection")
|
public class EnvInspectionController {
|
|
@Resource
|
private IEnvInspectionService envInspectionService;
|
|
@GetMapping("/page")
|
public AjaxResult page(Page page, EnvInspection req) {
|
return AjaxResult.success(envInspectionService.listPage(page, req));
|
}
|
|
@GetMapping("/{id}")
|
public AjaxResult detail(@PathVariable Long id) {
|
return AjaxResult.success(envInspectionService.getById(id));
|
}
|
|
@PostMapping("/add")
|
@Log(title = "智能巡检-新增", businessType = BusinessType.INSERT)
|
public AjaxResult add(@RequestBody EnvInspection inspection) {
|
inspection.setId(null);
|
if (inspection.getStatus() == null) {
|
inspection.setStatus(0);
|
}
|
return envInspectionService.save(inspection) ? AjaxResult.success() : AjaxResult.error("新增失败");
|
}
|
|
@PostMapping("/update")
|
@Log(title = "智能巡检-修改", businessType = BusinessType.UPDATE)
|
public AjaxResult update(@RequestBody EnvInspection inspection) {
|
return envInspectionService.updateById(inspection) ? AjaxResult.success() : AjaxResult.error("修改失败");
|
}
|
|
@DeleteMapping("/delete")
|
@Log(title = "智能巡检-删除", businessType = BusinessType.DELETE)
|
public AjaxResult delete(@RequestBody List<Long> ids) {
|
return envInspectionService.removeByIds(ids) ? AjaxResult.success() : AjaxResult.error("删除失败");
|
}
|
|
/**
|
* 自动生成巡检报告
|
*/
|
@GetMapping("/report/{id}")
|
@Log(title = "智能巡检-生成报告", businessType = BusinessType.OTHER)
|
public AjaxResult generateReport(@PathVariable Long id) {
|
return AjaxResult.success((Object) envInspectionService.generateReport(id));
|
}
|
|
@PostMapping("/export")
|
public void export(HttpServletResponse response, EnvInspection req) {
|
envInspectionService.export(response, req);
|
}
|
|
@Value("${envaccess.callback.secret:hbmjxt-callback-2026}")
|
private String callbackSecret;
|
|
private static final ObjectMapper CALLBACK_MAPPER = new ObjectMapper();
|
|
/**
|
* 无人机 / 机器人 / AI 摄像头 巡检数据回传(对外开放接口,供第三方设备调用)
|
*
|
* 请求示例(POST JSON):
|
* {
|
* "secret": "hbmjxt-callback-2026",
|
* "tenantId": 222,
|
* "inspectionId": 3, // 可选,不传则按 area 匹配最近一条未取消任务,再没有就新建
|
* "area": "东门区域",
|
* "deviceType": "UAV", // UAV 无人机 / ROBOT 机器人 / CAMERA 摄像头
|
* "deviceCode": "UAV-M350-001",
|
* "collectedAt": "2026-10-24 09:12:35",
|
* "aiSummary": "共识别 5 类目标,发现 1 处未佩戴安全帽",
|
* "aiObjects": [{"object":"人员未佩戴安全帽","conclusion":"未按要求佩戴","confidence":0.93,"frameTime":"2026-10-24 09:12:35"}],
|
* "longitude": 120.382145, "latitude": 31.298512, "altitude": 45.6, "battery": 78,
|
* "photos": ["/profile/upload/uav_east_01.jpg"],
|
* "track": [{"t":"09:12:10","lng":120.3821,"lat":31.2985}]
|
* }
|
*/
|
@Anonymous
|
@PostMapping("/callback")
|
public AjaxResult callback(@RequestBody Map<String, Object> payload) {
|
if (payload == null || payload.isEmpty()) {
|
return AjaxResult.error("回传数据不能为空");
|
}
|
if (!callbackSecret.equals(String.valueOf(payload.get("secret")))) {
|
return AjaxResult.error("secret 校验失败,请在请求体中携带正确的 secret");
|
}
|
Long tenantId = toLong(payload.get("tenantId"));
|
if (tenantId == null) {
|
return AjaxResult.error("tenantId 不能为空");
|
}
|
String area = payload.get("area") == null ? "未指定区域" : String.valueOf(payload.get("area"));
|
String deviceType = payload.get("deviceType") == null ? "UAV" : String.valueOf(payload.get("deviceType"));
|
String deviceCode = payload.get("deviceCode") == null ? deviceType + "-UNKNOWN" : String.valueOf(payload.get("deviceCode"));
|
|
Map<String, Object> ai = new LinkedHashMap<>();
|
ai.put("summary", payload.get("aiSummary") == null ? "本次回传未附带 AI 识别结论" : payload.get("aiSummary"));
|
ai.put("objects", payload.get("aiObjects") == null ? new ArrayList<>() : payload.get("aiObjects"));
|
|
Map<String, Object> uav = new LinkedHashMap<>();
|
uav.put("deviceType", deviceType);
|
uav.put("deviceCode", deviceCode);
|
uav.put("area", area);
|
uav.put("collectedAt", payload.get("collectedAt") == null ? "" : payload.get("collectedAt"));
|
uav.put("longitude", payload.get("longitude"));
|
uav.put("latitude", payload.get("latitude"));
|
uav.put("altitude", payload.get("altitude"));
|
uav.put("battery", payload.get("battery"));
|
uav.put("photos", payload.get("photos") == null ? new ArrayList<>() : payload.get("photos"));
|
uav.put("track", payload.get("track") == null ? new ArrayList<>() : payload.get("track"));
|
uav.put("receivedAt", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
|
String aiJson;
|
String uavJson;
|
try {
|
aiJson = CALLBACK_MAPPER.writeValueAsString(ai);
|
uavJson = CALLBACK_MAPPER.writeValueAsString(uav);
|
} catch (Exception e) {
|
return AjaxResult.error("回传数据序列化失败:" + e.getMessage());
|
}
|
|
EnvInspection target = null;
|
Long inspectionId = toLong(payload.get("inspectionId"));
|
if (inspectionId != null) {
|
target = envInspectionService.getById(inspectionId);
|
}
|
if (target == null) {
|
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<EnvInspection> w =
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
|
w.eq(EnvInspection::getArea, area).ne(EnvInspection::getStatus, 3)
|
.orderByDesc(EnvInspection::getId).last("limit 1");
|
target = envInspectionService.getOne(w, false);
|
}
|
|
boolean created = false;
|
if (target == null) {
|
target = new EnvInspection();
|
target.setInspectionName(area + " 智能巡检(设备回传)");
|
target.setInspectionType(2);
|
target.setArea(area);
|
target.setStatus(2);
|
target.setPlanStartTime(new Date());
|
target.setPlanEndTime(new Date());
|
target.setActualStartTime(new Date());
|
target.setActualEndTime(new Date());
|
target.setInspector(deviceCode);
|
target.setRoutePlan("由 " + deviceType + " 自动规划并执行");
|
target.setInspectionResult("设备自动巡检已完成,识别结果详见回传数据。");
|
target.setTenantId(tenantId);
|
created = true;
|
}
|
target.setAiAnalysis(aiJson);
|
target.setUavData(uavJson);
|
if (target.getStatus() != null && target.getStatus() == 0) {
|
target.setStatus(2);
|
}
|
if (target.getTenantId() == null) {
|
target.setTenantId(tenantId);
|
}
|
|
// 设备回调没有登录上下文,临时跳过租户插件,tenant_id 已在上面显式写入
|
CustomTenantLineHandler.TEMP_IGNORE.set(Boolean.TRUE);
|
try {
|
if (created) {
|
envInspectionService.save(target);
|
} else {
|
envInspectionService.updateById(target);
|
}
|
} catch (Exception e) {
|
return AjaxResult.error("回传数据落库失败:" + e.getMessage());
|
} finally {
|
CustomTenantLineHandler.TEMP_IGNORE.remove();
|
}
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("inspectionId", target.getId());
|
result.put("created", created);
|
result.put("deviceCode", deviceCode);
|
result.put("deviceType", deviceType);
|
result.put("area", area);
|
return AjaxResult.success("巡检数据回传成功", result);
|
}
|
|
private Long toLong(Object v) {
|
if (v == null) {
|
return null;
|
}
|
try {
|
return Long.valueOf(String.valueOf(v).trim());
|
} catch (NumberFormatException e) {
|
return null;
|
}
|
}
|
}
|