Browse Source

Merge branch 'server_test' of http://192.168.0.3:3000/SD-SafeAI/shudao-main into server_test

zkn 3 weeks ago
parent
commit
1bb73f5c17

+ 94 - 5
shudao-chat-py/routers/hazard.py

@@ -375,7 +375,22 @@ async def hazard(
                 e,
                 traceback.format_exc(),
             )
-            return {"statusCode": 500, "msg": f"下载图片失败: {str(e)}"}
+            error_msg = "图片下载失败"
+            if isinstance(e, httpx.TimeoutException):
+                error_msg = "图片下载超时,请检查网络连接或稍后重试"
+            elif isinstance(e, httpx.ConnectError):
+                error_msg = "无法连接到图片服务器,请检查图片链接是否正确"
+            elif hasattr(e, 'response') and e.response is not None:
+                status_code = e.response.status_code
+                if status_code == 404:
+                    error_msg = "图片不存在,请检查图片链接是否正确"
+                elif status_code == 403:
+                    error_msg = "无权访问该图片,请检查图片链接权限"
+                elif status_code >= 500:
+                    error_msg = "图片服务器暂时不可用,请稍后重试"
+                else:
+                    error_msg = f"图片下载失败(错误代码:{status_code})"
+            return {"statusCode": 500, "msg": error_msg}
 
         logger.info(
             "[hazard][%s] image downloaded: bytes=%s",
@@ -396,6 +411,51 @@ async def hazard(
                 (yolo_result or {}).get("model_type", "") if isinstance(yolo_result, dict) else "",
             )
             logger.debug("[hazard][%s] yolo result raw: %s", request_id, json.dumps(yolo_result, ensure_ascii=False, default=str))
+        except httpx.TimeoutException as e:
+            logger.error(
+                "[hazard][%s] YOLO检测超时: scene_key=%r, error=%s, traceback=%s",
+                request_id,
+                scene_key,
+                e,
+                traceback.format_exc(),
+            )
+            return {"statusCode": 500, "msg": "AI识别服务响应超时,请稍后重试"}
+        except httpx.ConnectError as e:
+            logger.error(
+                "[hazard][%s] YOLO服务连接失败: scene_key=%r, error=%s, traceback=%s",
+                request_id,
+                scene_key,
+                e,
+                traceback.format_exc(),
+            )
+            return {"statusCode": 500, "msg": "无法连接到AI识别服务,请联系管理员"}
+        except httpx.HTTPStatusError as e:
+            logger.error(
+                "[hazard][%s] YOLO服务返回错误状态: scene_key=%r, status_code=%s, error=%s, traceback=%s",
+                request_id,
+                scene_key,
+                e.response.status_code if hasattr(e, 'response') else 'unknown',
+                e,
+                traceback.format_exc(),
+            )
+            status_code = e.response.status_code if hasattr(e, 'response') else 500
+            if status_code == 400:
+                return {"statusCode": 500, "msg": "图片格式不支持或图片已损坏,请更换图片"}
+            elif status_code == 404:
+                return {"statusCode": 500, "msg": f"未找到场景'{SCENE_DISPLAY_NAMES.get(scene_key, scene_key)}'的识别模型"}
+            elif status_code >= 500:
+                return {"statusCode": 500, "msg": "AI识别服务暂时不可用,请稍后重试"}
+            else:
+                return {"statusCode": 500, "msg": f"AI识别服务返回错误(代码:{status_code})"}
+        except ValueError as e:
+            logger.error(
+                "[hazard][%s] YOLO返回数据格式错误: scene_key=%r, error=%s, traceback=%s",
+                request_id,
+                scene_key,
+                e,
+                traceback.format_exc(),
+            )
+            return {"statusCode": 500, "msg": "AI识别服务返回数据格式错误,请联系管理员"}
         except Exception as e:
             logger.error(
                 "[hazard][%s] YOLO检测失败: scene_key=%r, error=%s, traceback=%s",
@@ -404,7 +464,13 @@ async def hazard(
                 e,
                 traceback.format_exc(),
             )
-            return {"statusCode": 500, "msg": f"YOLO API返回错误: {str(e)}"}
+            error_msg = str(e)
+            if "timeout" in error_msg.lower():
+                return {"statusCode": 500, "msg": "AI识别服务响应超时,请稍后重试"}
+            elif "connection" in error_msg.lower():
+                return {"statusCode": 500, "msg": "无法连接到AI识别服务,请联系管理员"}
+            else:
+                return {"statusCode": 500, "msg": f"AI识别失败:{error_msg}"}
 
         labels = yolo_result.get("labels", []) or []
         boxes = yolo_result.get("boxes", []) or []
@@ -421,7 +487,7 @@ async def hazard(
             )
             return {
                 "statusCode": 200,
-                "msg": "识别成功",
+                "msg": "未检测到隐患",
                 "data": {
                     "scene_name": scene_key,
                     "scene_display_name": SCENE_DISPLAY_NAMES.get(scene_key, scene_key),
@@ -436,6 +502,7 @@ async def hazard(
                     "display_labels": [],
                     "third_scenes": [],
                     "element_hazards": {},
+                    "no_hazards_detected": True,
                 },
             }
 
@@ -594,7 +661,18 @@ async def hazard(
             )
             db.rollback()
             logger.info("[hazard][%s] db rollback executed after record save failure", request_id)
-            return {"statusCode": 500, "msg": f"识别失败: {str(e)}"}
+            
+            error_msg = str(e)
+            if "connection" in error_msg.lower() or "lost connection" in error_msg.lower():
+                return {"statusCode": 500, "msg": "数据库连接失败,请稍后重试"}
+            elif "duplicate" in error_msg.lower() or "unique" in error_msg.lower():
+                return {"statusCode": 500, "msg": "记录已存在,请勿重复提交"}
+            elif "timeout" in error_msg.lower():
+                return {"statusCode": 500, "msg": "数据库操作超时,请稍后重试"}
+            elif "disk" in error_msg.lower() or "space" in error_msg.lower():
+                return {"statusCode": 500, "msg": "存储空间不足,请联系管理员"}
+            else:
+                return {"statusCode": 500, "msg": f"保存识别记录失败:{error_msg}"}
 
         display_labels = _dedupe_list([item["label"] for item in detection_results])
 
@@ -638,7 +716,18 @@ async def hazard(
         )
         db.rollback()
         logger.info("[hazard][%s] db rollback executed in outer exception handler", request_id)
-        return {"statusCode": 500, "msg": f"处理失败: {str(e)}"}
+        
+        error_msg = str(e)
+        if "connection" in error_msg.lower():
+            return {"statusCode": 500, "msg": "服务连接失败,请稍后重试"}
+        elif "timeout" in error_msg.lower():
+            return {"statusCode": 500, "msg": "服务响应超时,请稍后重试"}
+        elif "memory" in error_msg.lower() or "out of memory" in error_msg.lower():
+            return {"statusCode": 500, "msg": "系统资源不足,请稍后重试或联系管理员"}
+        elif "permission" in error_msg.lower() or "denied" in error_msg.lower():
+            return {"statusCode": 500, "msg": "权限不足,请联系管理员"}
+        else:
+            return {"statusCode": 500, "msg": f"识别处理失败:{error_msg}"}
 
 
 @router.post("/save_step")

+ 14 - 8
shudao-chat-py/routers/scene.py

@@ -536,9 +536,12 @@ async def delete_recognition_record(
         return {"statusCode": 401, "msg": "未授权"}
 
     record_id = _resolve_record_id(data.recognition_id, data.recognition_record_id)
+    user_id = getattr(user, "user_id", None)
+    user_code = _get_user_code(user)
     logger.info(
-        "delete_recognition_record start: user_code=%s record_id=%s",
-        _get_user_code(user),
+        "delete_recognition_record start: user_id=%s user_code=%s record_id=%s",
+        user_id,
+        user_code,
         record_id,
     )
     if not record_id:
@@ -549,14 +552,15 @@ async def delete_recognition_record(
         db.query(RecognitionRecord)
         .filter(
             RecognitionRecord.id == record_id,
-            RecognitionRecord.user_id == _get_user_code(user),
+            RecognitionRecord.user_id == user_id,
         )
         .update({"is_deleted": 1, "deleted_at": int(time.time())})
     )
     db.commit()
     logger.info(
-        "delete_recognition_record success: user_code=%s record_id=%s affected_rows=%s",
-        _get_user_code(user),
+        "delete_recognition_record success: user_id=%s user_code=%s record_id=%s affected_rows=%s",
+        user_id,
+        user_code,
         record_id,
         affected_rows,
     )
@@ -617,12 +621,13 @@ async def get_latest_recognition_record(
         logger.warning("get_latest_recognition_record unauthorized: missing request.state.user")
         return {"statusCode": 401, "msg": "未授权"}
 
+    user_id = getattr(user, "user_id", None)
     user_code = _get_user_code(user)
-    logger.info("get_latest_recognition_record start: user_code=%s", user_code)
+    logger.info("get_latest_recognition_record start: user_id=%s user_code=%s", user_id, user_code)
     record = (
         db.query(RecognitionRecord)
         .filter(
-            RecognitionRecord.user_id == _get_user_code(user),
+            RecognitionRecord.user_id == user_id,
             RecognitionRecord.is_deleted == 0,
         )
         .order_by(RecognitionRecord.created_at.desc())
@@ -737,8 +742,9 @@ async def get_recognition_records(
     if page_size > 100:
         page_size = 100
 
+    user_id = getattr(user, "user_id", None)
     query = db.query(RecognitionRecord).filter(
-        RecognitionRecord.user_id == _get_user_code(user),
+        RecognitionRecord.user_id == user_id,
         RecognitionRecord.is_deleted == 0,
     )
 

+ 30 - 2
shudao-vue-frontend/src/views/HazardDetection.vue

@@ -1804,8 +1804,16 @@ const startIdentification = async () => {
                 (Array.isArray(backendData.third_scenes) &&
                     backendData.third_scenes.length > 0);
 
+            // 检查是否是"未检测到隐患"的情况
+            const isNoHazardsDetected = response.msg === "未检测到隐患" || 
+                                       backendData.no_hazards_detected === true;
+
             if (!hasDetections && !hasLabels) {
-                ElMessage.warning("未检测到隐患,已完成识别");
+                if (isNoHazardsDetected) {
+                    ElMessage.info("未检测到任何关键要素");
+                } else {
+                    ElMessage.warning("未检测到隐患,已完成识别");
+                }
             } else {
                 ElMessage.success("隐患提示完成!");
             }
@@ -1891,7 +1899,27 @@ const startIdentification = async () => {
             }
         }
     } catch (error) {
-        ElMessage.error("隐患提示失败: " + (error.msg || "未知错误"));
+        console.error("[startIdentification] 捕获到异常:", {
+            error: error,
+            errorType: typeof error,
+            errorConstructor: error?.constructor?.name,
+            errorMessage: error?.message,
+            errorMsg: error?.msg,
+            errorStack: error?.stack,
+            errorKeys: error ? Object.keys(error) : [],
+            errorStringified: JSON.stringify(error, Object.getOwnPropertyNames(error))
+        });
+        
+        let errorMessage = error?.msg || error?.message || "未知错误";
+        console.error("[startIdentification] 最终错误消息:", errorMessage);
+        
+        // 将"暂未识别到支持的场景"的错误消息改为更友好的提示
+        if (errorMessage.includes("暂未识别到支持的场景") || 
+            errorMessage.includes("请尝试更换更清晰的图片")) {
+            ElMessage.info("未检测到任何关键要素");
+        } else {
+            ElMessage.error("隐患提示失败: " + errorMessage);
+        }
         isDragOver.value = false;
     } finally {
         isIdentifying.value = false;