Files
chatroom/app/Http/Controllers/ChatBotController.php
lkddi f5d8a593c9 优化:AI对话改为公开广播,所有人可见
- ChatBotController 将用户提问和AI回复都广播到聊天室
- 前端不再本地渲染AI消息,由WebSocket广播统一处理
- AI小助手加入系统用户列表(公告样式展示)
- 思考中提示延迟500ms显示在包厢窗口,避免排序混乱
2026-02-26 22:11:11 +08:00

133 lines
4.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:聊天机器人控制器
*
* 处理用户与 AI 机器人的对话请求。
* 先检查全局开关sysparam: chatbot_enabled再调用 AiChatService 获取回复。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers;
use App\Events\MessageSent;
use App\Jobs\SaveMessageJob;
use App\Models\Sysparam;
use App\Services\AiChatService;
use App\Services\ChatStateService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ChatBotController extends Controller
{
/**
* 构造函数:注入 AI 聊天服务和聊天状态服务
*/
public function __construct(
private readonly AiChatService $aiChat,
private readonly ChatStateService $chatState,
) {}
/**
* 与 AI 机器人对话
*
* 接收用户消息,检查全局开关后调用 AI 服务获取回复。
* 支持自动故障转移:默认厂商失败时自动尝试备用厂商。
*
* @param Request $request 请求对象,需包含 message 和 room_id
* @return JsonResponse 机器人回复或错误信息
*/
public function chat(Request $request): JsonResponse
{
// 验证请求参数
$request->validate([
'message' => 'required|string|max:2000',
'room_id' => 'required|integer',
]);
// 检查全局开关
$enabled = Sysparam::getValue('chatbot_enabled', '0');
if ($enabled !== '1') {
return response()->json([
'status' => 'error',
'message' => 'AI 机器人功能已关闭,请联系管理员开启。',
], 403);
}
$user = Auth::user();
$message = $request->input('message');
$roomId = $request->input('room_id');
try {
// 先广播用户的提问消息
$userMsg = [
'id' => $this->chatState->nextMessageId($roomId),
'room_id' => $roomId,
'from_user' => $user->username,
'to_user' => 'AI小助手',
'content' => $message,
'is_secret' => false,
'font_color' => '#000000',
'action' => '',
'sent_at' => now()->toDateTimeString(),
];
$this->chatState->pushMessage($roomId, $userMsg);
broadcast(new MessageSent($roomId, $userMsg));
SaveMessageJob::dispatch($userMsg);
$result = $this->aiChat->chat($user->id, $message, $roomId);
// 广播 AI 回复消息
$botMsg = [
'id' => $this->chatState->nextMessageId($roomId),
'room_id' => $roomId,
'from_user' => 'AI小助手',
'to_user' => $user->username,
'content' => $result['reply'],
'is_secret' => false,
'font_color' => '#16a34a',
'action' => '',
'sent_at' => now()->toDateTimeString(),
];
$this->chatState->pushMessage($roomId, $botMsg);
broadcast(new MessageSent($roomId, $botMsg));
SaveMessageJob::dispatch($botMsg);
return response()->json([
'status' => 'success',
'reply' => $result['reply'],
'provider' => $result['provider'],
'model' => $result['model'],
]);
} catch (\Exception $e) {
return response()->json([
'status' => 'error',
'message' => $e->getMessage(),
], 500);
}
}
/**
* 清除当前用户的 AI 对话上下文
*
* 用于用户想要重新开始对话时使用。
*
* @param Request $request 请求对象
* @return JsonResponse 操作结果
*/
public function clearContext(Request $request): JsonResponse
{
$user = Auth::user();
$this->aiChat->clearContext($user->id);
return response()->json([
'status' => 'success',
'message' => '对话上下文已清除,可以开始新的对话了。',
]);
}
}