From 259a60f240fdfff356a236d380d8d682949fc571 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期一, 26 十月 2026 09:24:25 +0800
Subject: [PATCH] feat(环保门禁): 巡检设备数据回传开放接口(无人机/机器人/AI摄像头)、无人值守地磅模块(表+后端+日报)、车辆采集照片字段、修复车辆修改接口缺@RequestBody

---
 src/main/java/com/ruoyi/envaccess/controller/EnvInspectionController.java |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/ruoyi/envaccess/controller/EnvInspectionController.java b/src/main/java/com/ruoyi/envaccess/controller/EnvInspectionController.java
index f9e748e..f5ad961 100644
--- a/src/main/java/com/ruoyi/envaccess/controller/EnvInspectionController.java
+++ b/src/main/java/com/ruoyi/envaccess/controller/EnvInspectionController.java
@@ -1,16 +1,24 @@
 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瑙嗛鍒嗘瀽/鎶ュ憡/鏃犱汉鏈烘満鍣ㄤ汉锛孉I涓庢棤浜烘満瀛楁棰勭暀锛�
@@ -67,4 +75,144 @@
     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 鎽勫儚澶� 宸℃鏁版嵁鍥炰紶锛堝澶栧紑鏀炬帴鍙o紝渚涚涓夋柟璁惧璋冪敤锛�
+     *
+     * 璇锋眰绀轰緥锛圥OST 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);
+        }
+
+        // 璁惧鍥炶皟娌℃湁鐧诲綍涓婁笅鏂囷紝涓存椂璺宠繃绉熸埛鎻掍欢锛宼enant_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;
+        }
+    }
 }

--
Gitblit v1.9.3