diff --git a/docs/api_kefu.md b/docs/api_kefu.md index d41f56214..646d59a3d 100644 --- a/docs/api_kefu.md +++ b/docs/api_kefu.md @@ -30,7 +30,7 @@ ### 1. 系统健康检查 -**接口地址**:`/api/health` +**接口地址**:`/api/kefu/health` **请求方式**:GET @@ -106,7 +106,7 @@ ### 2. 获取服务配置信息 -**接口地址**:`/api/info` +**接口地址**:`/api/kefu/info` **请求方式**:GET @@ -146,13 +146,13 @@ } }, "endpoints": { - "chat": "/api/chat", - "chat_stream": "/api/chatStream", - "create_conversation": "/api/createConversation", - "get_history": "/api/getHistory", - "clear_conversation": "/api/clearConversation", - "health": "/api/health", - "info": "/api/info" + "chat": "/api/kefu/chat", + "chat_stream": "/api/kefu/chatStream", + "create_conversation": "/api/kefu/createConversation", + "get_history": "/api/kefu/getHistory", + "clear_conversation": "/api/kefu/clearConversation", + "health": "/api/kefu/health", + "info": "/api/kefu/info" }, "api_config": { "base_url": "https://api.dify.ai/v1", @@ -181,7 +181,7 @@ ### 3. 智能客服聊天接口 -**接口地址**:`/api/chat` +**接口地址**:`/api/kefu/chat` **请求方式**:POST @@ -219,11 +219,11 @@ ### 4. 智能客服流式聊天接口 -**接口地址**:`/api/chatStream` +**接口地址**:`/api/kefu/chatStream` **请求方式**:POST -**请求参数**:同 `/api/chat` 接口 +**请求参数**:同 `/api/kefu/chat` 接口 **响应格式**:Server-Sent Events (SSE) @@ -284,7 +284,7 @@ data: { ### 5. 创建新会话 -**接口地址**:`/api/createConversation` +**接口地址**:`/api/kefu/createConversation` **请求方式**:POST @@ -313,7 +313,7 @@ data: { ### 6. 获取会话历史 -**接口地址**:`/api/getHistory` +**接口地址**:`/api/kefu/getHistory` **请求方式**:POST @@ -359,7 +359,7 @@ data: { ### 7. 清除会话历史 -**接口地址**:`/api/clearConversation` +**接口地址**:`/api/kefu/clearConversation` **请求方式**:POST @@ -398,7 +398,7 @@ import { request } from '@/utils/request'; async function getAIInfo() { try { const res = await request({ - url: '/api/info', + url: '/api/kefu/info', method: 'GET', data: { uniacid: 1 @@ -423,7 +423,7 @@ async function getAIInfo() { async function chatWithAI(message, conversationId = '') { try { const res = await request({ - url: '/api/chat', + url: '/api/kefu/chat', method: 'POST', data: { uniacid: 1, @@ -450,7 +450,7 @@ async function chatWithAI(message, conversationId = '') { async function chatWithAIStream(message, conversationId = '', onMessage, onComplete, onError) { try { const response = await uni.request({ - url: '/api/chatStream', + url: '/api/kefu/chatStream', method: 'POST', data: { uniacid: 1, @@ -490,7 +490,7 @@ async function chatWithAIStream(message, conversationId = '', onMessage, onCompl async function createNewConversation() { try { const res = await request({ - url: '/api/createConversation', + url: '/api/kefu/createConversation', method: 'POST', data: { uniacid: 1 @@ -514,7 +514,7 @@ async function createNewConversation() { async function getChatHistory(conversationId, limit = 20, offset = 0) { try { const res = await request({ - url: '/api/getHistory', + url: '/api/kefu/getHistory', method: 'POST', data: { uniacid: 1, @@ -541,7 +541,7 @@ async function getChatHistory(conversationId, limit = 20, offset = 0) { async function clearConversation(conversationId = '', userId = '') { try { const res = await request({ - url: '/api/clearConversation', + url: '/api/kefu/clearConversation', method: 'POST', data: { uniacid: 1, @@ -566,7 +566,7 @@ async function clearConversation(conversationId = '', userId = '') { async function checkHealth(checkType = 'full') { try { const res = await request({ - url: '/api/health', + url: '/api/kefu/health', method: 'GET', data: { uniacid: 1, diff --git a/src/addon/aikefu/event/KefuGetInfo.php b/src/addon/aikefu/event/KefuGetInfo.php index 138f5cda8..b0582b9d2 100644 --- a/src/addon/aikefu/event/KefuGetInfo.php +++ b/src/addon/aikefu/event/KefuGetInfo.php @@ -42,13 +42,13 @@ class KefuGetInfo ] ], 'endpoints' => [ - 'chat' => '/api/chat', - 'chat_stream' => '/api/chatStream', - 'create_conversation' => '/api/createConversation', - 'get_history' => '/api/getHistory', - 'clear_conversation' => '/api/clearConversation', - 'health' => '/api/health', - 'info' => '/api/info' + 'chat' => '/api/kefu/chat', + 'chat_stream' => '/api/kefu/chatStream', + 'create_conversation' => '/api/kefu/createConversation', + 'get_history' => '/api/kefu/getHistory', + 'clear_conversation' => '/api/kefu/clearConversation', + 'health' => '/api/kefu/health', + 'info' => '/api/kefu/info' ], 'client_info' => $client_info, 'server_info' => [ diff --git a/src/app/api/controller/AI.php b/src/app/api/controller/AI.php deleted file mode 100644 index 11d881718..000000000 --- a/src/app/api/controller/AI.php +++ /dev/null @@ -1,445 +0,0 @@ -params['uniacid'] ?? $this->site_id; // 使用 uniacid, 方便以后迁移,而且uniacid 是唯一的, site_id 不是,同时被params给过滤了 - - // 检查site_id 如果 < 1, 则返回错误 - if ($site_id < 1) { - return $this->response($this->error('缺少关键参数站点ID')); - } - - // 准备事件数据 - $event_data = [ - 'check_id' => uniqid('health_', true), - 'timestamp' => date('Y-m-d H:i:s'), - 'site_id' => $site_id, - 'check_type' => $this->params['check_type'] ?? 'full' // full, basic, ai_service - ]; - - $health_summary = null; - $event_data = [ - 'check_id' => uniqid('health_', true), - 'timestamp' => date('Y-m-d H:i:s'), - 'site_id' => $site_id, - 'check_type' => $this->params['check_type'] ?? 'full' // full, basic, ai_service - ]; - - try { - // 触发健康检查事件 - $result = Event::trigger('KefuHealthCheck', $event_data); - - // 汇总检查结果 - $health_summary = [ - 'status' => 'healthy', - 'check_id' => $event_data['check_id'], - 'timestamp' => $event_data['timestamp'], - 'total_checks' => 0, - 'passed_checks' => 0, - 'failed_checks' => 0, - 'response_time_ms' => 0, - 'components' => [], - 'warnings' => [], - 'errors' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $check_result) { - if (isset($check_result['component'])) { - $health_summary['components'][$check_result['component']] = $check_result; - $health_summary['total_checks']++; - - if ($check_result['status'] === 'healthy') { - $health_summary['passed_checks']++; - } else { - $health_summary['failed_checks']++; - if ($check_result['status'] === 'error') { - $health_summary['errors'][] = $check_result['message'] ?? 'Unknown error'; - $health_summary['status'] = 'unhealthy'; - } elseif ($check_result['status'] === 'warning') { - $health_summary['warnings'][] = $check_result['message'] ?? 'Unknown warning'; - if ($health_summary['status'] === 'healthy') { - $health_summary['status'] = 'warning'; - } - } - } - } - } - } - - // 计算总体响应时间 - $health_summary['response_time_ms'] = round((microtime(true) - $start_time) * 1000, 2); - - // 如果没有任何检查结果,进行基础检查 - if ($health_summary['total_checks'] === 0) { - $health_summary['components']['basic'] = [ - 'status' => 'healthy', - 'message' => '基础服务正常', - 'response_time_ms' => 0, - 'details' => [ - 'php_version' => PHP_VERSION, - 'memory_usage' => round(memory_get_usage() / 1024 / 1024, 2) . ' MB', - 'time_limit' => ini_get('max_execution_time') . 's' - ] - ]; - $health_summary['total_checks'] = 1; - $health_summary['passed_checks'] = 1; - } - - // 根据检查结果确定HTTP状态码 - $http_code = 200; - if ($health_summary['status'] === 'unhealthy') { - $http_code = 503; // Service Unavailable - } elseif ($health_summary['status'] === 'warning') { - $http_code = 200; // Still OK but with warnings - } - - return $this->response([ - 'code' => 0, - 'message' => $health_summary['status'], - 'data' => $health_summary - ], $http_code); - - } catch (\Exception $e) { - return $this->response([ - 'code' => -1, - 'message' => '健康检查失败', - 'data' => [ - 'status' => 'error', - 'check_id' => $event_data['check_id'] ?? '', - 'timestamp' => $event_data['timestamp'] ?? date('Y-m-d H:i:s'), - 'error' => $e->getMessage(), - 'response_time_ms' => round((microtime(true) - $start_time) * 1000, 2) - ] - ], 500); - } - } - - /** - * 获得AI服务的配置信息发送给客户端 - * @return \think\response\Json - */ - public function info() - { - // (可选)获取站点ID和会员ID,可以通过事件数据传递 - $site_id = $this->params['uniacid'] ?? $this->site_id; - $member_id = $this->params['member_id'] ?? $this->member_id; - $token = $this->params['token'] ?? $this->token; - - try { - // 准备事件数据 - $event_data = [ - 'site_id' => $site_id, - 'member_id' => $member_id, - 'token' => $token, - 'client_info' => [ - 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', - 'ip' => $this->getClientIp(), - 'timestamp' => time() - ] - ]; - - // 触发获取配置信息事件 - $result = Event::trigger('KefuGetInfo', $event_data); - - // 处理事件结果 - $response = [ - 'code' => 0, - 'message' => 'success', - 'data' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $res) { - if (isset($res['code']) && $res['code'] < 0) { - $response = $res; - break; - } - if (isset($res['data'])) { - $response['data'] = array_merge($response['data'], $res['data']); - } - } - } - - return $this->response($response); - } catch (\Exception $e) { - return $this->response($this->error('请求失败:' . $e->getMessage())); - } - } - - /** - * 获取客户端IP地址 - */ - private function getClientIp() - { - $ip = ''; - - if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; - } elseif (isset($_SERVER['HTTP_X_REAL_IP']) && !empty($_SERVER['HTTP_X_REAL_IP'])) { - $ip = $_SERVER['HTTP_X_REAL_IP']; - } elseif (isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])) { - $ip = $_SERVER['REMOTE_ADDR']; - } - - // 处理多个IP的情况(X-Forwarded-For可能包含多个IP) - if (strpos($ip, ',') !== false) { - $ips = explode(',', $ip); - $ip = trim($ips[0]); - } - - return $ip; - } - - /** - * 清除会话历史 - */ - public function clearConversation() - { - // 获取请求参数 - $conversation_id = $this->params['conversation_id'] ?? ''; - $user_id = $this->params['user_id'] ?? $this->member_id; - - // (可选)获取站点ID和会员ID,可以通过事件数据传递 - $site_id = $this->params['uniacid'] ?? $this->site_id; // 使用 uniacid, 方便以后迁移,而且uniacid 是唯一的, site_id 不是,同时被params给过滤了 - $member_id = $this->params['member_id'] ?? $this->member_id; - $token = $this->params['token'] ?? $this->token; - - // 验证参数(conversation_id 和 user_id 至少需要一个) - if (empty($conversation_id) && empty($user_id)) { - return $this->response($this->error('会话ID或用户ID不能为空')); - } - - try { - // 准备事件数据 - $event_data = [ - 'conversation_id' => $conversation_id, - 'user_id' => $user_id, - 'site_id' =>$site_id, - 'member_id' => $member_id, - 'token' => $token, - ]; - - // 触发清除会话事件 - $result = Event::trigger('KefuClearConversation', $event_data); - - // 处理事件结果 - $response = [ - 'code' => 0, - 'message' => 'success', - 'data' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $res) { - if (isset($res['code']) && $res['code'] < 0) { - $response = $res; - break; - } - if (isset($res['data'])) { - $response['data'] = array_merge($response['data'], $res['data']); - } - } - } - - return $this->response($response); - } catch (\Exception $e) { - return $this->response($this->error('请求失败:' . $e->getMessage())); - } - } - - /** - * 智能客服聊天接口 - * @return \think\response\Json - */ - public function chat() - { - // 获取请求参数 - $message = $this->params['message'] ?? ''; - $user_id = $this->params['user_id'] ?? $this->member_id; - $conversation_id = $this->params['conversation_id'] ?? ''; - $stream = $this->params['stream'] ?? false; - - // (可选)获取站点ID和会员ID,可以通过事件数据传递 - $site_id = $this->params['uniacid'] ?? $this->site_id; // 使用 uniacid, 方便以后迁移,而且uniacid 是唯一的, site_id 不是,同时被params给过滤了 - $member_id = $this->params['member_id'] ?? $this->member_id; - $token = $this->params['token'] ?? $this->token; - - // 验证参数 - if (empty($message)) { - return $this->response($this->error('请输入消息内容')); - } - - try { - // 准备事件数据 - $event_data = [ - 'message' => $message, - 'user_id' => $user_id, - 'conversation_id' => $conversation_id, - 'stream' => $stream, - 'site_id' =>$site_id, - 'member_id' => $member_id, - 'token' => $token, - ]; - - // 触发智能客服聊天事件 - $result = Event::trigger('KefuChat', $event_data); - - // 处理事件结果 - $response = [ - 'code' => 0, - 'message' => 'success', - 'data' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $res) { - if (isset($res['code']) && $res['code'] < 0) { - $response = $res; - break; - } - if (isset($res['data'])) { - $response['data'] = array_merge($response['data'], $res['data']); - } - } - } - - return $this->response($response); - } catch (\Exception $e) { - return $this->response($this->error('请求失败:' . $e->getMessage())); - } - } - - - - /** - * 创建新会话 - * @return \think\response\Json - */ - public function createConversation() - { - // 获取请求参数 - $user_id = $this->params['user_id'] ?? $this->member_id; - - // (可选)获取站点ID和会员ID,可以通过事件数据传递 - $site_id = $this->params['uniacid'] ?? $this->site_id; // 使用 uniacid, 方便以后迁移,而且uniacid 是唯一的, site_id 不是,同时被params给过滤了 - $member_id = $this->params['member_id'] ?? $this->member_id; - $token = $this->params['token'] ?? $this->token; - - try { - // 准备事件数据 - $event_data = [ - 'user_id' => $user_id, - 'site_id' =>$site_id, - 'member_id' => $member_id, - 'token' => $token, - ]; - - // 触发创建会话事件 - $result = Event::trigger('KefuCreateConversation', $event_data); - - // 处理事件结果 - $response = [ - 'code' => 0, - 'message' => 'success', - 'data' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $res) { - if (isset($res['code']) && $res['code'] < 0) { - $response = $res; - break; - } - if (isset($res['data'])) { - $response['data'] = array_merge($response['data'], $res['data']); - } - } - } - - return $this->response($response); - } catch (\Exception $e) { - return $this->response($this->error('请求失败:' . $e->getMessage())); - } - } - - /** - * 获取会话历史 - * @return \think\response\Json - */ - public function getHistory() - { - // 获取请求参数 - $conversation_id = $this->params['conversation_id'] ?? ''; - $user_id = $this->params['user_id'] ?? $this->member_id; - $limit = $this->params['limit'] ?? 20; - $offset = $this->params['offset'] ?? 0; - - // (可选)获取站点ID和会员ID,可以通过事件数据传递 - $site_id = $this->params['uniacid'] ?? $this->site_id; // 使用 uniacid, 方便以后迁移,而且uniacid 是唯一的, site_id 不是,同时被params给过滤了 - $member_id = $this->params['member_id'] ?? $this->member_id; - $token = $this->params['token'] ?? $this->token; - - // 验证参数(conversation_id 和 user_id 至少需要一个) - if (empty($conversation_id) && empty($user_id)) { - return $this->response($this->error('会话ID或用户ID不能为空')); - } - - try { - // 准备事件数据 - $event_data = [ - 'conversation_id' => $conversation_id, - 'user_id' => $user_id, - 'limit' => $limit, - 'offset' => $offset, - 'site_id' =>$site_id, - 'member_id' => $member_id, - 'token' => $token, - ]; - - // 触发获取历史消息事件 - $result = Event::trigger('KefuGetHistory', $event_data); - - // 处理事件结果 - $response = [ - 'code' => 0, - 'message' => 'success', - 'data' => [] - ]; - - if (is_array($result) && !empty($result)) { - foreach ($result as $res) { - if (isset($res['code']) && $res['code'] < 0) { - $response = $res; - break; - } - if (isset($res['data'])) { - $response['data'] = array_merge($response['data'], $res['data']); - } - } - } - - return $this->response($response); - } catch (\Exception $e) { - return $this->response($this->error('请求失败:' . $e->getMessage())); - } - } -}