Browse Source

fix:ai测量

super-yimizi 11 hours ago
parent
commit
dc0f8d3875
1 changed files with 216 additions and 37 deletions
  1. 216 37
      application/api/controller/AiMeasurement.php

+ 216 - 37
application/api/controller/AiMeasurement.php

@@ -542,18 +542,34 @@ class AiMeasurement extends Api
             // $result = [
             //     'measurements' => $measurements,
             //     'confidence' => $measurements['_confidence'] ?? 0.8,
-            //     'warnings' => $measurements['_warnings'] ?? []
+            //     'warnings' => $measurements['warnings'] ?? []
             // ];
 
             // 清理内部字段
             // unset($result['measurements']['_confidence']);
-            // unset($result['measurements']['_warnings']);
+            // unset($result['measurements']['warnings']);
 
             // 格式化结果用于展示
             //$formattedResult = $this->formatMeasurementResult($result, $params['profile_id']);
             $measurements['height'] = $profile->height;
             $measurements['weight'] = $profile->weight;
-            $this->success('AI测量完成', $measurements);
+            
+            // 检查是否有错误状态
+            $hasErrors = isset($measurements['warnings']) && !empty($measurements['warnings']);
+            $state = $measurements['_state'] ?? 0;
+            $message = $measurements['_message'] ?? 'AI测量完成';
+            
+            // 构建返回数据
+            $responseData = $measurements;
+            
+            // 根据状态和错误情况返回不同的消息
+            if ($state === 0 && !$hasErrors) {
+                $this->success('AI测量完成', $responseData);
+            } else {
+                // 有错误直接返回错误状态
+                $errorMsg = $hasErrors ? implode(', ', $measurements['warnings']) : $message;
+                $this->error($errorMsg, $responseData);
+            }
 
         // } catch (\Exception $e) {
         //     $this->error($e->getMessage());
@@ -631,15 +647,8 @@ class AiMeasurement extends Api
                 throw new \Exception('请求第三方AI服务失败: ' . $error);
             }
             
-            // 处理各种HTTP错误状态
-            if ($httpCode >= 500) {
-                throw new \Exception('第三方AI服务内部错误: HTTP ' . $httpCode);
-            } elseif ($httpCode >= 400) {
-                throw new \Exception('第三方AI服务请求错误: HTTP ' . $httpCode);
-            } elseif ($httpCode !== 200) {
-                throw new \Exception('第三方AI服务返回异常状态: HTTP ' . $httpCode);
-            }
             \think\Log::info('Third party AI service response: ' .$response);
+            
             // 检查响应内容
             if (empty($response)) {
                 throw new \Exception('第三方AI服务返回空响应');
@@ -647,7 +656,32 @@ class AiMeasurement extends Api
             
             $result = json_decode($response, true);
             if (json_last_error() !== JSON_ERROR_NONE) {
-                throw new \Exception('第三方AI服务返回数据格式错误');
+                // 对于非200状态码,尝试返回原始响应内容作为错误信息
+                if ($httpCode !== 200) {
+                    throw new \Exception("第三方AI服务返回异常(HTTP {$httpCode}): " . substr($response, 0, 200));
+                } else {
+                    throw new \Exception('第三方AI服务返回数据格式错误');
+                }
+            }
+            
+            // 处理各种HTTP错误状态,但先检查是否有有效的JSON响应
+            if ($httpCode !== 200) {
+                // 如果返回了JSON格式的错误信息,优先使用
+                if (isset($result['state']) && $result['state'] == 201) {
+                    // 传参错误,通过processMeasurementData处理
+                    return $this->processMeasurementData($result);
+                } elseif (isset($result['message'])) {
+                    throw new \Exception("第三方AI服务错误(HTTP {$httpCode}): " . $result['message']);
+                } else {
+                    // 传统的HTTP错误处理
+                    if ($httpCode >= 500) {
+                        throw new \Exception('第三方AI服务内部错误: HTTP ' . $httpCode);
+                    } elseif ($httpCode >= 400) {
+                        throw new \Exception('第三方AI服务请求错误: HTTP ' . $httpCode);
+                    } else {
+                        throw new \Exception('第三方AI服务返回异常状态: HTTP ' . $httpCode);
+                    }
+                }
             }
             
             // 记录API响应信息
@@ -719,11 +753,42 @@ class AiMeasurement extends Api
             'waist_lower'=>'',    // 净小腹围 → 下腰围
             'mid_waist'=>'',    // 净中腰 → 中腰围
             '_confidence' => 0.0,
-            '_warnings' => ['第三方AI服务暂时不可用,返回默认数据']
+            'warnings' => ['第三方AI服务暂时不可用,返回默认数据']
         ];
     }
 
     /**
+     * 根据状态码获取错误信息
+     */
+    private function getStateErrorMessage($state)
+    {
+        $stateMessages = [
+            1 => '颈围计算异常',
+            2 => '腰围计算异常',
+            3 => '大腿围计算异常',
+            4 => '膝盖围计算异常',
+            5 => '胸围计算异常',
+            6 => '小腿围计算异常',
+            7 => '肚围计算异常',
+            8 => '臀围计算异常',
+            9 => '手臂长计算异常',
+            10 => '手腕围计算异常',
+            11 => '腿长计算异常、裤长计算异常、内腿长计算异常',
+            12 => '肩宽计算异常',
+            13 => '脚踝计算异常',
+            14 => '中腰计算异常',
+            15 => '小腹围计算异常',
+            16 => '上臂围计算异常',
+            101 => '图片1提取尺寸异常',
+            102 => '图片2提取尺寸异常',
+            103 => '图片3提取尺寸异常',
+            201 => '传参错误'
+        ];
+
+        return $stateMessages[$state] ?? "未知错误(状态码: {$state})";
+    }
+
+    /**
      * 测试接口 - 返回模拟的第三方API测量数据
      * @ApiMethod (POST)
      * @ApiParams (name="profile_id", type="integer", required=true, description="档案ID")
@@ -767,7 +832,11 @@ class AiMeasurement extends Api
                 "yaowei" => 72.93800974219818,
                 "zhongyao" => 70.99945416888724
             ],
-            "confidence" => 0.85
+            "image1" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+            "image2" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+            "image3" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+            "message" => "sucessed",
+            "state" => 0
         ];
 
         // 处理测量数据
@@ -777,22 +846,119 @@ class AiMeasurement extends Api
         $result = [
             'measurements' => $measurements,
             'confidence' => $measurements['_confidence'] ?? 0.8,
-            'warnings' => $measurements['_warnings'] ?? []
+            'warnings' => $measurements['warnings'] ?? []
         ];
 
         // 清理内部字段
         unset($result['measurements']['_confidence']);
-        unset($result['measurements']['_warnings']);
+        unset($result['measurements']['warnings']);
 
         // 格式化结果用于展示
         $formattedResult = $this->formatMeasurementResult($result, $params['profile_id']);
 
         $this->success('测试数据返回成功', [
-            'original_api_data' => $mockApiResult['body_size'],
+            'original_api_data' => $mockApiResult,
             'mapped_measurements' => $result['measurements'],
             'formatted_result' => $formattedResult
         ]);
     }
+
+    /**
+     * 测试错误状态处理 - 返回不同错误状态的模拟数据
+     * @ApiMethod (POST)
+     * @ApiParams (name="profile_id", type="integer", required=true, description="档案ID")
+     * @ApiParams (name="test_state", type="integer", required=false, description="测试状态码(1-16, 101-103, 201)")
+     */
+    public function testErrorStates()
+    {
+        $params = $this->request->post();
+        
+        // 验证必要参数
+        if (empty($params['profile_id'])) {
+            $this->error('档案ID不能为空');
+        }
+
+        // 验证档案归属
+        $profile = \app\common\model\BodyProfile::where('id', $params['profile_id'])
+            ->where('user_id', $this->auth->id)
+            ->find();
+
+        if (!$profile) {
+            $this->error('档案不存在');
+        }
+
+        // 获取测试状态码
+        $testState = intval($params['test_state'] ?? 1);
+        
+        // 模拟不同错误状态的API返回
+        $mockApiResults = [
+            // 部位计算异常(1-16)
+            1 => [
+                "body_size" => [],
+                "image1" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+                "image2" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+                "image3" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+                "message" => "neck calculation error",
+                "state" => 1
+            ],
+            5 => [
+                "body_size" => [
+                    "yaowei" => 72.93800974219818,
+                    "tunwei" => 90.08082593388505
+                ],
+                "image1" => "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAME",
+                "message" => "chest calculation error",
+                "state" => 5
+            ],
+            // 图片提取异常(101-103)
+            101 => [
+                "body_size" => [],
+                "message" => "image1 size extraction error",
+                "state" => 101
+            ],
+            // 传参错误(201)
+            201 => [
+                "body_size" => [],
+                "message" => "parameter error",
+                "state" => 201
+            ]
+        ];
+
+        // 获取对应的模拟数据,如果没有则使用默认的状态1
+        $mockApiResult = $mockApiResults[$testState] ?? $mockApiResults[1];
+        $mockApiResult['state'] = $testState; // 确保状态码正确
+
+        try {
+            // 处理测量数据
+            $measurements = $this->processMeasurementData($mockApiResult);
+            
+            $testData = [
+                'test_state' => $testState,
+                'error_message' => $this->getStateErrorMessage($testState),
+                'mock_api_result' => $mockApiResult,
+                'processed_measurements' => $measurements
+            ];
+            
+            // 检查是否有错误状态
+            $hasErrors = isset($measurements['warnings']) && !empty($measurements['warnings']);
+            $state = $measurements['_state'] ?? 0;
+            
+            if ($state === 0 && !$hasErrors) {
+                $this->success('错误状态测试成功', $testData);
+            } else {
+                // 有错误直接返回错误状态
+                $errorMsg = $this->getStateErrorMessage($testState);
+                $this->error($errorMsg, $testData);
+            }
+            
+        } catch (\Exception $e) {
+            // 对于201状态(传参错误),会抛出异常
+            $this->error('测试异常: ' . $e->getMessage(), [
+                'test_state' => $testState,
+                'mock_api_result' => $mockApiResult
+            ]);
+        }
+    }
     
     /**
      * 将图片URL转换为base64格式
@@ -886,24 +1052,35 @@ class AiMeasurement extends Api
      */
     private function processMeasurementData($apiResult)
     {
-        // 根据第三方API的返回格式处理数据
-        // 这里需要根据实际的API返回格式进行调整
-        
         $measurements = [];
         
         try {
-            // 假设API返回格式类似:
-            // {
-            //   "status": "success",
-            //   "data": {
-            //     "chest": 95.5,
-            //     "waist": 75.2,
-            //     "hip": 98.7,
-            //     ...
-            //   },
-            //   "confidence": 0.85
-            // }
+            // 首先检查是否有state字段(错误状态码)
+            if (isset($apiResult['state'])) {
+                $state = intval($apiResult['state']);
+                
+                // state=0为正常,其他为异常
+                if ($state !== 0) {
+                    $errorMsg = $this->getStateErrorMessage($state);
+                    
+                    // 如果是严重错误(传参错误),直接抛出异常
+                    if ($state == 201) {
+                        throw new \Exception($errorMsg);
+                    }
+                    
+                    // 对于部位计算异常或图片提取异常,返回部分数据和警告
+                    $measurements = $this->getDefaultMeasurementData();
+                    $measurements['_confidence'] = 0.3; // 低置信度
+                    $measurements['warnings'] = [$errorMsg];
+                    $measurements['_state'] = $state;
+                    $measurements['_message'] = $apiResult['message'] ?? '';
+                    
+                    
+                    return $measurements;
+                }
+            }
             
+            // state=0 或没有state字段,处理正常数据
             // 检查返回数据结构 - 可能直接包含body_size字段
             if (isset($apiResult['body_size'])) {
                 $data = $apiResult['body_size'];
@@ -948,11 +1125,13 @@ class AiMeasurement extends Api
                 
                 // 设置置信度和警告信息
                 $measurements['_confidence'] = $apiResult['confidence'] ?? 0.8;
-                $measurements['_warnings'] = $apiResult['warnings'] ?? [];
+                $measurements['warnings'] = $apiResult['warnings'] ?? [];
+                $measurements['_state'] = isset($apiResult['state']) ? intval($apiResult['state']) : 0;
+                $measurements['_message'] = $apiResult['message'] ?? 'sucessed';
                 
                 // 如果没有测量数据,添加默认警告
-                if (count($measurements) === 2) { // 只有_confidence和_warnings
-                    $measurements['_warnings'][] = '第三方AI服务未返回有效的测量数据';
+                if (count($measurements) <= 4) { // 只有_confidence, warnings, _state, _message
+                    $measurements['warnings'][] = '第三方AI服务未返回有效的测量数据';
                 }
                 
             } else {
@@ -964,7 +1143,7 @@ class AiMeasurement extends Api
         } catch (\Exception $e) {
             // 处理异常,返回错误信息
             $measurements['_confidence'] = 0;
-            $measurements['_warnings'] = ['数据处理失败: ' . $e->getMessage()];
+            $measurements['warnings'] = ['数据处理失败: ' . $e->getMessage()];
         }
         
         return $measurements;
@@ -1002,12 +1181,12 @@ class AiMeasurement extends Api
             $result = [
                 'measurements' => $measurements,
                 'confidence' => $measurements['_confidence'] ?? 0.8,
-                'warnings' => $measurements['_warnings'] ?? []
+                'warnings' => $measurements['warnings'] ?? []
             ];
 
             // 清理内部字段
             unset($result['measurements']['_confidence']);
-            unset($result['measurements']['_warnings']);
+            unset($result['measurements']['warnings']);
 
             // 更新任务状态为完成
             \think\Db::table('fa_ai_measurement_task')