assignService = new AssignService(); } /** * 创建会话 * @param int $userId 用户ID * @param int $source 来源 1=PC 2=Game 3=Portal * @return array 会话数据 */ public function createSession($userId, $source) { $redis = $this->getRedis(); // 检查是否已有活跃会话 $existingSession = ChatSession::getActiveByUserId($userId); if ($existingSession) { return $existingSession; } // 创建新会话 $session = [ 'user_id' => $userId, 'source' => $source, 'status' => ChatSession::STATUS_PENDING, 'create_time' => time(), 'update_time' => time(), ]; $sessionId = ChatSession::insertGetId($session); $session['id'] = $sessionId; // 缓存用户活跃会话 $redis->set(self::USER_ACTIVE_SESSION_PREFIX . $userId, $sessionId); // 尝试分配客服 $adminId = $this->assignService->assignSession($userId, $sessionId); if ($adminId !== null) { $session['admin_id'] = $adminId; $session['status'] = ChatSession::STATUS_ACTIVE; } return $session; } /** * 获取用户活跃会话 */ public function getActiveSession($userId) { return ChatSession::getActiveByUserId($userId); } /** * 获取会话详情(含用户信息) */ public function getSessionDetail($sessionId) { $session = ChatSession::find($sessionId); if (!$session) { return null; } $session = $session->toArray(); // 获取用户信息 $user = Db::name('user')->where('id', $session['user_id'])->find(); if ($user) { $session['user_info'] = [ 'id' => $user['id'], 'username' => $user['username'], 'nickname' => $user['nickname'] ?? $user['username'], 'money' => $user['money'], 'agent_id' => $user['agent_id'] ?? null, ]; } return $session; } /** * 结束会话 */ public function endSession($sessionId, $operatorId) { $session = ChatSession::find($sessionId); if (!$session) { return false; } $session = $session->toArray(); // 只能结束进行中的会话 if ($session['status'] === ChatSession::STATUS_ENDED) { return true; } // 更新会话状态 ChatSession::where('id', $sessionId)->update([ 'status' => ChatSession::STATUS_ENDED, 'end_time' => time(), 'update_time' => time(), ]); // 清理Redis缓存 $redis = $this->getRedis(); $redis->del(self::USER_ACTIVE_SESSION_PREFIX . $session['user_id']); // 释放客服会话配额 if ($session['admin_id']) { $this->assignService->releaseSession($sessionId, $session['admin_id']); } return true; } /** * 转接会话 */ public function transferSession($sessionId, $newAdminId) { $session = ChatSession::find($sessionId); if (!$session || $session['status'] !== ChatSession::STATUS_ACTIVE) { return false; } $oldAdminId = $session['admin_id']; // 更新会话归属 ChatSession::where('id', $sessionId)->update([ 'admin_id' => $newAdminId, 'update_time' => time(), ]); // 更新Redis $redis = $this->getRedis(); $redis->set('cs:session:owner:' . $sessionId, $newAdminId); // 调整负载计数 if ($oldAdminId) { $oldLoad = (int)$redis->get('cs:agent:load:' . $oldAdminId) ?: 0; if ($oldLoad > 0) { $redis->decr('cs:agent:load:' . $oldAdminId); } } $redis->incr('cs:agent:load:' . $newAdminId); return true; } /** * 会话评价 */ public function rateSession($sessionId, $rating, $content = null) { $session = ChatSession::find($sessionId); if (!$session) { return false; } // 评分范围 1-5 $rating = max(1, min(5, $rating)); ChatSession::where('id', $sessionId)->update([ 'rating' => $rating, 'rating_content' => $content ? mb_substr($content, 0, 500) : null, 'update_time' => time(), ]); return true; } /** * 注册用户连接 */ public function registerUserConnection($userId, $fd) { $redis = $this->getRedis(); $redis->setex(self::CONN_USER_PREFIX . $userId, 60, $fd); } /** * 注册客服连接 */ public function registerAgentConnection($adminId, $fd) { $redis = $this->getRedis(); $redis->setex(self::CONN_AGENT_PREFIX . $adminId, 60, $fd); } /** * 刷新用户连接TTL */ public function refreshUserConnection($userId) { $redis = $this->getRedis(); $redis->expire(self::CONN_USER_PREFIX . $userId, 60); } /** * 刷新客服连接TTL */ public function refreshAgentConnection($adminId) { $redis = $this->getRedis(); $redis->expire(self::CONN_AGENT_PREFIX . $adminId, 60); } /** * 获取用户连接FD */ public function getUserFd($userId): ?int { $redis = $this->getRedis(); $fd = $redis->get(self::CONN_USER_PREFIX . $userId); return $fd ? (int)$fd : null; } /** * 获取客服连接FD */ public function getAgentFd($adminId): ?int { $redis = $this->getRedis(); $fd = $redis->get(self::CONN_AGENT_PREFIX . $adminId); return $fd ? (int)$fd : null; } /** * 清理用户连接 */ public function clearUserConnection($userId) { $redis = $this->getRedis(); $redis->del(self::CONN_USER_PREFIX . $userId); } /** * 清理客服连接 */ public function clearAgentConnection($adminId) { $redis = $this->getRedis(); $redis->del(self::CONN_AGENT_PREFIX . $adminId); } /** * 获取客服会话列表 */ public function getAgentSessions($adminId) { $sessions = ChatSession::getActiveByAdminId($adminId); // 附加用户信息和未读数 foreach ($sessions as &$session) { $user = Db::name('user')->where('id', $session['user_id'])->find(); $session['user_info'] = [ 'username' => $user['username'] ?? '', 'nickname' => $user['nickname'] ?? $user['username'] ?? '', 'money' => $user['money'] ?? 0, ]; // 未读消息数 $session['unread_count'] = ChatMessage::where('session_id', $session['id']) ->where('sender_type', ChatMessage::SENDER_USER) ->where('status', '<', ChatMessage::STATUS_READ) ->count(); } return $sessions; } /** * 获取待分配会话列表 */ public function getPendingSessions() { $sessions = ChatSession::where('status', ChatSession::STATUS_PENDING) ->order('create_time', 'asc') ->select() ->toArray(); foreach ($sessions as &$session) { $user = Db::name('user')->where('id', $session['user_id'])->find(); $session['user_info'] = [ 'username' => $user['username'] ?? '', 'nickname' => $user['nickname'] ?? $user['username'] ?? '', 'money' => $user['money'] ?? 0, ]; } return $sessions; } /** * 获取Redis实例 */ private function getRedis() { return Cache::store('redis')->handler(); } }