diff --git a/src/addon/aikefu/api/controller/Kefu.php b/src/addon/aikefu/api/controller/Kefu.php index 0fc1aea56..b315d3731 100644 --- a/src/addon/aikefu/api/controller/Kefu.php +++ b/src/addon/aikefu/api/controller/Kefu.php @@ -803,27 +803,76 @@ class Kefu extends BaseApi $kefu_message_model = new KefuMessageModel(); $kefu_conversation_model = new KefuConversationModel(); - // 发送请求 - $response = $this->curlRequest($url, 'POST', $requestData, $headers); + // 开启事务,确保数据一致性 + Db::startTrans(); + + try { + // 发送请求 + $response = $this->curlRequest($url, 'POST', $requestData, $headers); - // 解析响应 - $result = json_decode($response, true); + // 解析响应 + $result = json_decode($response, true); - if (json_last_error() !== JSON_ERROR_NONE) { - return $this->response($this->error('解析响应失败')); + if (json_last_error() !== JSON_ERROR_NONE) { + throw new \Exception('解析响应失败'); + } + + // 验证响应数据 + if (empty($result) || !isset($result['conversation_id'])) { + throw new \Exception('API返回数据格式错误或缺少必要字段'); + } + + $final_conversation_id = $result['conversation_id'] ?? $conversation_id; + $final_message_id = $result['message_id'] ?? $result['id'] ?? ''; + + // 检查用户消息是否已存在,避免重复存储 + $existing_user_message = $kefu_message_model->getMessageInfo([ + ['site_id', '=', $this->site_id], + ['user_id', '=', $user_id], + ['conversation_id', '=', $final_conversation_id], + ['role', '=', 'user'], + ['content', '=', $message ?? ''] + ]); + + if (empty($existing_user_message['data'])) { + // 保存用户消息 + $this->saveUserMessage($kefu_message_model, $this->site_id, $user_id, $final_conversation_id, $final_message_id, $message ?? ''); + $this->log('非流式用户消息已保存,会话ID:' . $final_conversation_id, 'info'); + } + + // 检查助手消息是否已存在 + $existing_assistant_message = $kefu_message_model->getMessageInfo([ + ['site_id', '=', $this->site_id], + ['user_id', '=', $user_id], + ['conversation_id', '=', $final_conversation_id], + ['role', '=', 'assistant'], + ['message_id', '=', $final_message_id] + ]); + + if (empty($existing_assistant_message['data'])) { + // 保存机器人回复 + $this->saveAssistantMessage($kefu_message_model, $this->site_id, $user_id, $final_conversation_id, $final_message_id, $result['answer'] ?? ''); + $this->log('非流式助手消息已保存,会话ID:' . $final_conversation_id, 'info'); + } + + // 更新会话状态或创建新会话 + $this->updateOrCreateConversation($kefu_conversation_model, $this->site_id, $user_id, $final_conversation_id); + + // 提交事务 + Db::commit(); + $this->log('非流式对话数据已完整保存,会话ID:' . $final_conversation_id, 'info'); + + // 返回成功响应,保持与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)); } - - // 保存用户消息 - $this->saveUserMessage($kefu_message_model, $this->site_id, $user_id, $result['conversation_id'] ?? $conversation_id, $result['message_id'] ?? '', $message ?? ''); - - // 保存机器人回复 - $this->saveAssistantMessage($kefu_message_model, $this->site_id, $user_id, $result['conversation_id'] ?? $conversation_id, $result['id'] ?? '', $result['answer'] ?? ''); - - // 更新会话状态或创建新会话 - $this->updateOrCreateConversation($kefu_conversation_model, $this->site_id, $user_id, $result['conversation_id'] ?? $conversation_id); - - // 返回成功响应,保持与Dify API一致的响应结构 - return $this->response($this->success($result)); } /** diff --git a/src/addon/aikefu/shop/controller/Kefu.php b/src/addon/aikefu/shop/controller/Kefu.php index 32035ff12..81f6c2534 100644 --- a/src/addon/aikefu/shop/controller/Kefu.php +++ b/src/addon/aikefu/shop/controller/Kefu.php @@ -273,6 +273,7 @@ class Kefu extends BaseShop $user_id = input("user_id/s", ""); $sort_field = input("sort_field/s", "create_time"); // 排序字段 $sort_order = input("sort_order/s", "desc"); // 排序方式:asc或desc + $status = input("status/s", "completed"); // 默认只显示已完成的消息 $kefu_message_model = new KefuMessageModel(); $condition = [ @@ -289,9 +290,15 @@ class Kefu extends BaseShop $condition[] = ['user_id', '=', $user_id]; } + // 添加状态过滤(默认只显示已完成的消息,避免显示临时数据) + if (!empty($status)) { + $condition[] = ['status', '=', $status]; + } + // 构建排序字符串 $order = $sort_field . ' ' . $sort_order; $message_list = $kefu_message_model->getMessageList($condition, '*', $order, $page, $limit); + // 适配layui table的返回格式,同时保持与Dify API风格一致 $result = [ 'code' => 0, // layui table要求成功状态码为0 @@ -301,7 +308,8 @@ class Kefu extends BaseShop 'messages' => $message_list['data'], // 消息列表 'page_info' => [ 'limit' => $limit, - 'offset' => ($page - 1) * $limit + 'offset' => ($page - 1) * $limit, + 'total' => $message_list['total'] // 添加总记录数到page_info ] ] // 数据列表 ]; diff --git a/src/addon/aikefu/shop/view/kefu/message.html b/src/addon/aikefu/shop/view/kefu/message.html index 44cc04685..d12bda9a8 100644 --- a/src/addon/aikefu/shop/view/kefu/message.html +++ b/src/addon/aikefu/shop/view/kefu/message.html @@ -220,6 +220,17 @@ +
+ +
+ +
+
@@ -267,6 +278,7 @@ var total = 0; var conversation_id = $('#msg_conversation_id').val(); var user_id = $('#msg_user_id').val(); + var status = 'completed'; // 默认只显示已完成的消息 var sortField = 'create_time'; // 排序字段:创建时间 var sortOrder = 'desc'; // 默认倒序(最新消息在前面) @@ -325,6 +337,11 @@ requestData.user_id = user_id; } + // 添加状态过滤 + if (status) { + requestData.status = status; + } + $.ajax({ url: ns.url("aikefu://shop/kefu/getMessageList"), type: 'POST', @@ -461,6 +478,7 @@ $('#msg_searchBtn').click(function() { conversation_id = $('#msg_conversation_id').val().trim(); user_id = $('#msg_user_id').val().trim(); + status = $('#msg_status').val(); // 获取当前选择的状态 sortOrder = $('#msg_sortOrder').val(); // 获取当前选择的排序方式 page = 1; loadConversationInfo(); @@ -471,9 +489,11 @@ $('#msg_resetBtn').click(function() { $('#msg_conversation_id').val(''); $('#msg_user_id').val(''); + $('#msg_status').val('completed'); // 重置为默认状态 $('#msg_sortOrder').val('desc'); // 重置为默认排序 conversation_id = ''; user_id = ''; + status = 'completed'; // 重置为默认状态 sortOrder = 'desc'; // 重置为默认排序 page = 1; loadConversationInfo(); @@ -487,6 +507,13 @@ loadMessageList(true); // 切换排序时强制滚动到顶部 }); + // 状态变更事件 + $('#msg_status').change(function() { + status = $(this).val(); + page = 1; // 切换状态时重置到第一页 + loadMessageList(true); // 切换状态时强制滚动到顶部 + }); + // 初始化加载(默认显示所有消息) loadConversationInfo(); loadMessageList();