uid; $chatType = $request->post('chat_type'); // 1=单聊,2=群聊 $toId = $request->post('to_id'); // 单聊=对方ID,群聊=群ID $session_id = $request->post('session_id'); // 会话ID $page = $request->post('page', 1)?:1; $size = $request->post('size', 20)?:20; if (!$toId || !$chatType || !$session_id) { return $this->error('参数不完整'); } // 构建查询条件 $query = Db::name('chat_message')->where(['session_id' => $session_id]); // 群聊需验证是否在群内 if ($chatType == 2) { $isMember = Db::name('chat_group_member')->where([ 'group_id' => $toId, 'user_id' => $uid, 'quit_time' => null, 'is_kicked' => 0 ])->find(); if (!$isMember) { return $this->error('不在群内,无法获取历史消息'); } } // 分页查询(倒序取,再正序返回) $total = $query->count(); $messages = $query->order('send_time', 'desc') ->page($page, $size) ->select()->toArray(); $messages = array_reverse($messages); // 单聊自动标记已读 if ($chatType == 1) { Db::name('chat_message')->where([ 'session_id' => $session_id, 'to_id' => $uid, 'is_read' => 0 ])->update(['is_read' => 1]); // 重置未读计数 Db::name('chat_unread_count')->where([ 'user_id' => $uid, 'session_id' => $session_id ])->update(['count' => 0, 'updated_time' => d()]); } return $this->success([ 'list' => $messages, 'page' => $page, 'size' => $size, 'total' => $total]); } /** * 标记消息已读(批量) */ public function markRead(Request $request): Response { $uid = $request->uid; $msgIds = $request->post('msg_ids', []); if (empty($msgIds) || !is_array($msgIds)) { return json(['code' => 400, 'msg' => '请传入有效消息ID数组']); } // 标记已读(仅自己接收的消息) $messages = ChatMessage::whereIn('id', $msgIds) ->where('to_id', $uid) ->where('is_read', 0) ->get(); if (empty($messages)) { return json(['code' => 200, 'msg' => '无未读消息可标记']); } // 批量更新 $sessionIds = $messages->pluck('session_id')->unique()->toArray(); ChatMessage::whereIn('id', $msgIds)->where('to_id', $uid)->update(['is_read' => 1]); // 更新未读计数 foreach ($sessionIds as $sessionId) { $reduceNum = ChatMessage::whereIn('id', $msgIds) ->where('session_id', $sessionId) ->count(); $unread = ChatUnreadCount::where(['user_id' => $uid, 'session_id' => $sessionId])->first(); if ($unread) { $newCount = max(0, $unread->count - $reduceNum); $unread->count = $newCount; $unread->updated_at = time(); $unread->save(); } } return json(['code' => 200, 'msg' => '标记已读成功']); } /** * 标记会话全部已读 */ public function markReadAll(Request $request): Response { $uid = $request->uid; $sessionId = $request->post('session_id', ''); if (empty($sessionId)) { return json(['code' => 400, 'msg' => '缺少session_id']); } // 标记该会话所有未读消息已读 ChatMessage::where([ 'session_id' => $sessionId, 'to_id' => $uid, 'is_read' => 0 ])->update(['is_read' => 1]); // 重置未读计数 ChatUnreadCount::where([ 'user_id' => $uid, 'session_id' => $sessionId ])->update(['count' => 0, 'updated_at' => time()]); return json(['code' => 200, 'msg' => '标记全部已读成功']); } /** * 获取未读消息总数 */ public function getUnreadCount(Request $request): Response { $uid = $request->uid; $total = ChatUnreadCount::where('user_id', $uid)->sum('count'); return json(['code' => 200, 'msg' => 'success', 'data' => ['total' => $total]]); } /** * 获取会话列表(含置顶、未读、最后消息) */ public function getSessionList(Request $request): Response { $uid = $request->uid; // 获取所有会话ID $sessionIds = ChatMessage::where(function ($query) use ($uid) { $query->where('from_id', $uid)->orWhere('to_id', $uid); })->groupBy('session_id')->pluck('session_id')->toArray(); if (empty($sessionIds)) { return json(['code' => 200, 'msg' => 'success', 'data' => ['list' => []]]); } $sessionList = []; foreach ($sessionIds as $sessionId) { // 置顶状态 $top = ChatTop::where(['user_id' => $uid, 'session_id' => $sessionId])->first(); $isTop = $top && $top->status == 1 ? 1 : 0; $sort = $top ? $top->sort : 0; // 未读计数 $unread = ChatUnreadCount::where(['user_id' => $uid, 'session_id' => $sessionId])->first(); $unreadCount = $unread ? $unread->count : 0; // 最后一条消息 $lastMsg = ChatMessage::where('session_id', $sessionId) ->orderBy('send_time', 'desc') ->first([ 'id', 'from_id', 'msg_type', 'content', 'image_url', 'order_id', 'send_time', 'is_read' ]); if (!$lastMsg) continue; // 会话类型(单聊/群聊) $chatType = strpos($sessionId, 'group_') === 0 ? 2 : 1; $targetInfo = []; if ($chatType == 1) { // 单聊:解析对方ID list($minId, $maxId) = explode('_', $sessionId); $targetUid = $uid == $minId ? $maxId : $minId; $targetUser = ChatUser::find($targetUid); if ($targetUser) { $targetInfo = [ 'id' => $targetUser->id, 'name' => $targetUser->username, 'avatar' => $targetUser->avatar, 'type' => $targetUser->type ]; } } else { // 群聊:解析群ID $groupId = str_replace('group_', '', $sessionId); $group = ChatGroup::find($groupId); if ($group) { $targetInfo = [ 'id' => $group->id, 'name' => $group->name, 'avatar' => $group->avatar, 'owner_id' => $group->owner_id ]; } } $sessionList[] = [ 'session_id' => $sessionId, 'chat_type' => $chatType, 'is_top' => $isTop, 'sort' => $sort, 'unread_count' => $unreadCount, 'last_msg' => $lastMsg ? $lastMsg->toArray() : [], 'target_info' => $targetInfo ]; } // 排序:置顶(按sort降序)→ 非置顶(按最后消息时间降序) usort($sessionList, function ($a, $b) { if ($a['is_top'] != $b['is_top']) { return $b['is_top'] - $a['is_top']; } if ($a['is_top'] == 1) { return $b['sort'] - $a['sort']; } $aTime = $a['last_msg']['send_time'] ?? 0; $bTime = $b['last_msg']['send_time'] ?? 0; return $bTime - $aTime; }); return json(['code' => 200, 'msg' => 'success', 'data' => ['list' => $sessionList]]); } }