From 89f36ee6665ac127a8ead8dee1f62c6e307e6f32 Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Thu, 11 Dec 2025 16:00:56 +0800 Subject: [PATCH] =?UTF-8?q?chore(addon/aikefu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/addon/aikefu/api/controller/Kefu.php | 80 ++++++++++++++---------- src/app/api/controller/Kefu.php | 9 ++- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/addon/aikefu/api/controller/Kefu.php b/src/addon/aikefu/api/controller/Kefu.php index c658f7de4..808a95c9b 100644 --- a/src/addon/aikefu/api/controller/Kefu.php +++ b/src/addon/aikefu/api/controller/Kefu.php @@ -85,7 +85,7 @@ class Kefu extends BaseApi if (curl_errno($ch)) { $error = curl_error($ch); $this->log('Curl请求错误:' . $error, 'error'); - + if (is_callable($on_error)) { $on_error($error); } else { @@ -201,7 +201,10 @@ class Kefu extends BaseApi $stream = $this->params['stream'] ?? false; // 验证参数并获取配置 - $config = $this->validateAndGetConfig($message); + $config = $this->validateAndGetConfig([ + 'message' => ['required' => true, 'message' => '请求参数 `query` 不能为空. 为消息内容', 'description' => '消息内容, message 参数,上流为 query'], + 'user_id' => ['required' => true, 'message' => '请求参数 `user_id` 不能为空', 'description' => '用户ID, user_id 参数,上流为 user_id'] + ]); if ($config instanceof \think\response\Json) { return $config; } @@ -229,14 +232,25 @@ class Kefu extends BaseApi /** * 验证参数并获取配置 - * @param string $message 用户消息 + * @param array $params_rules 参数验证规则 + * [ + * 'message' => ['required' => true, 'message' => '请输入消息内容'], + * ] * @return array|\think\response\Json */ - private function validateAndGetConfig($message) + private function validateAndGetConfig($params_rules = []) { + // 参数验证规则 + $rules = []; + + // 合并参数验证规则 + $rules = array_merge($rules, $params_rules); + // 验证参数 - if (empty($message)) { - return $this->response($this->error('请输入消息内容')); + foreach ($rules as $field => $rule) { + if (isset($rule['required']) && $rule['required'] && empty($this->params[$field])) { + return $this->response($this->error($rule['message'])); + } } // 获取智能客服配置 @@ -442,7 +456,7 @@ class Kefu extends BaseApi { // 只允许info、error级别 if (!in_array($level, ['info', 'error'])) { - return; + return; } log_write($message, $level, '', 2); } @@ -471,7 +485,7 @@ class Kefu extends BaseApi // 立即保存用户消息,使用临时会话ID $this->saveUserMessage($kefu_message_model, $site_id, $current_user_id, $temp_conversation_id, '', $user_message_content); $this->log('用户消息已立即保存,临时会话ID:' . $temp_conversation_id, 'info'); - + // 创建或更新临时会话 $this->updateOrCreateConversation($kefu_conversation_model, $site_id, $current_user_id, $temp_conversation_id); $this->log('临时会话已创建,ID:' . $temp_conversation_id, 'info'); @@ -522,7 +536,7 @@ class Kefu extends BaseApi if (isset($event_data['answer'])) { $assistant_content .= $event_data['answer']; $this->log('积累助手回复内容:' . $event_data['answer'], 'debug'); - + // 实时保存助手回复内容(流式过程中) if (!empty($real_conversation_id) && !empty($real_assistant_message_id)) { $this->saveStreamingAssistantMessage($kefu_message_model, $site_id, $current_user_id, $real_conversation_id, $real_assistant_message_id, $assistant_content, 'streaming'); @@ -538,13 +552,13 @@ class Kefu extends BaseApi ['conversation_id', '=', $temp_conversation_id], ['role', '=', 'user'] ]); - + $kefu_conversation_model->updateConversation(['conversation_id' => $real_conversation_id], [ ['site_id', '=', $site_id], ['user_id', '=', $current_user_id], ['conversation_id', '=', $temp_conversation_id] ]); - + $user_message_saved = true; $this->log('用户消息会话ID已更新为真实ID:' . $real_conversation_id, 'info'); } @@ -564,7 +578,7 @@ class Kefu extends BaseApi if (isset($event_data['answer'])) { $assistant_content .= $event_data['answer']; $this->log('积累Agent回复内容:' . $event_data['answer'], 'debug'); - + // 实时保存助手回复内容(Agent模式流式过程中) if (!empty($real_conversation_id) && !empty($real_assistant_message_id)) { $this->saveStreamingAssistantMessage($kefu_message_model, $site_id, $current_user_id, $real_conversation_id, $real_assistant_message_id, $assistant_content, 'streaming'); @@ -580,13 +594,13 @@ class Kefu extends BaseApi ['conversation_id', '=', $temp_conversation_id], ['role', '=', 'user'] ]); - + $kefu_conversation_model->updateConversation(['conversation_id' => $real_conversation_id], [ ['site_id', '=', $site_id], ['user_id', '=', $current_user_id], ['conversation_id', '=', $temp_conversation_id] ]); - + $user_message_saved = true; $this->log('Agent模式下用户消息会话ID已更新为真实ID:' . $real_conversation_id, 'info'); } @@ -630,7 +644,7 @@ class Kefu extends BaseApi if (isset($event_data['delta']['content'])) { $assistant_content .= $event_data['delta']['content']; $this->log('积累增量内容:' . $event_data['delta']['content'], 'debug'); - + // 实时保存助手回复内容(增量流式过程中) if (!empty($real_conversation_id) && !empty($real_assistant_message_id)) { $this->saveStreamingAssistantMessage($kefu_message_model, $site_id, $current_user_id, $real_conversation_id, $real_assistant_message_id, $assistant_content, 'streaming'); @@ -746,18 +760,18 @@ class Kefu extends BaseApi $done_data = [ 'conversation_id' => $real_conversation_id, 'message_id' => $real_assistant_message_id, - 'content' => $assistant_content, + 'content' => $assistant_content, ]; echo "event: done\ndata: " . json_encode($done_data) . "\n\n"; // 只在有输出缓冲时才刷新 if (ob_get_level() > 0) { ob_flush(); } - flush(); - + flush(); + // 发送连接关闭事件,让客户端知道连接已正常结束 echo "event: close\ndata: {\"status\":\"completed\"}\n\n"; - + // 只在有输出缓冲时才刷新 if (ob_get_level() > 0) { ob_flush(); @@ -770,14 +784,14 @@ class Kefu extends BaseApi $this->saveStreamingAssistantMessage($kefu_message_model, $site_id, $current_user_id, $real_conversation_id, $real_assistant_message_id, $assistant_content, 'completed'); $this->log('AI客服回复已标记为完成状态,会话ID:' . $real_conversation_id . ',总字数:' . strlen($assistant_content), 'info'); } - + // 清理临时数据 $this->cleanupTempData($kefu_message_model, $kefu_conversation_model, $site_id, $current_user_id, $temp_conversation_id); - + } catch (Exception $e) { $error_msg = 'AI客服请求异常:' . $e->getMessage() . ',错误行:' . $e->getLine() . ',错误文件:' . $e->getFile(); $this->log($error_msg, 'error'); - + // 异常时清理临时数据 try { $this->cleanupTempData($kefu_message_model, $kefu_conversation_model, $site_id, $current_user_id, $temp_conversation_id); @@ -785,7 +799,7 @@ class Kefu extends BaseApi $this->log('清理临时数据时也发生异常:' . $cleanupException->getMessage(), 'error'); } } - + // 流式响应处理完成后必须退出脚本,避免EventSource协议错误 exit; } @@ -811,7 +825,7 @@ class Kefu extends BaseApi // 开启事务,确保数据一致性 Db::startTrans(); - + try { // 发送请求 $response = $this->curlRequest($url, 'POST', $requestData, $headers); @@ -870,13 +884,13 @@ class Kefu extends BaseApi // 返回成功响应,保持与Dify API一致的响应结构 return $this->response($this->success($result)); - + } catch (\Exception $e) { // 回滚事务 Db::rollback(); $error_msg = '非流式对话存储失败:' . $e->getMessage() . ',错误行:' . $e->getLine() . ',错误文件:' . $e->getFile(); $this->log($error_msg, 'error'); - + return $this->response($this->error($error_msg)); } } @@ -911,11 +925,11 @@ class Kefu extends BaseApi try { $kefu_message_model = new KefuMessageModel(); - + // 获取所有状态的消息统计 $status_stats = []; $statuses = ['streaming', 'completed', 'failed']; - + foreach ($statuses as $status) { $count = $this->db->name('aikefu_message') ->where([ @@ -926,7 +940,7 @@ class Kefu extends BaseApi ['status', '=', $status] ]) ->count(); - + $status_stats[$status] = $count; } @@ -975,10 +989,10 @@ class Kefu extends BaseApi // 获取会话历史记录(只返回已完成的消息,过滤掉失败或进行中的消息) $kefu_message_model = new KefuMessageModel(); $message_list = $kefu_message_model->getConversationMessages( - $this->site_id, - $conversation_id, - $limit, - $offset, + $this->site_id, + $conversation_id, + $limit, + $offset, 'completed' // 只返回已完成的消息 ); diff --git a/src/app/api/controller/Kefu.php b/src/app/api/controller/Kefu.php index 5e1c3af46..9ba7ac734 100644 --- a/src/app/api/controller/Kefu.php +++ b/src/app/api/controller/Kefu.php @@ -339,7 +339,10 @@ class Kefu extends BaseApi // 验证参数 if (empty($query)) { - return $this->response($this->error('请输入消息内容,参数项: query')); + return $this->response($this->error('参数错误,请检查 `query` 参数是否设置正确')); + } + if (empty($site_id)) { + return $this->response($this->error('参数错误,请检查 `uniacid` 参数是否设置正确')); } // 验证事件是否存在 @@ -348,8 +351,8 @@ class Kefu extends BaseApi } try { - // 是否启用流式响应 - $enable_stream = $stream && $response_mode == 'streaming'; + // 是否启用流式响应 (stream 参数为 true 或 response_mode 为 streaming) + $enable_stream = $stream || $response_mode == 'streaming'; // 准备事件数据 $event_data = [