request->param('conversation_id/d', 0); if (!$conversationId) { return json(['code' => 400, 'msg' => '会话ID不能为空']); } try { // 查询会话信息 $conversation = ChatConversation::find($conversationId); if (!$conversation) { return json(['code' => 404, 'msg' => '会话不存在']); } // 查询用户信息 $userInfo = User::field('id, nickname, avatar')->find($conversation['user_id']); // 查询技师信息 $techInfo = Coach::field('id, name as nickname, work_photo as avatar')->find($conversation['tech_id']); // 查询最后一条消息 $lastMessage = []; if ($conversation['last_msg_id']) { $lastMessage = ChatMessage::field('content, create_time')->find($conversation['last_msg_id']); } return json([ 'code' => 200, 'data' => [ 'id' => $conversation['id'], 'user_info' => $userInfo ?: null, 'tech_info' => $techInfo ?: null, 'last_message' => $lastMessage ?: null, 'unread_count' => $conversation['unread_count'], 'update_time' => $conversation['update_time'] ] ]); } catch (\Exception $e) { return json(['code' => 500, 'msg' => '获取会话信息失败: ' . $e->getMessage()]); } } /** * 获取聊天历史 */ public function history() { $conversationId = $this->request->param('conversation_id/d', 0); $page = $this->request->param('page/d', 1); $pageSize = $this->request->param('page_size/d', 20); if (!$conversationId) { return json(['code' => 400, 'msg' => '会话ID不能为空']); } try { // 计算偏移量 $offset = ($page - 1) * $pageSize; // 查询消息列表 $messages = Db::name('chat_message') ->where('conversation_id', $conversationId) ->order('id', 'asc') ->limit($offset, 999999) ->select() ->toArray(); // 查询总数 $total = Db::name('chat_message') ->where('conversation_id', $conversationId) ->count(); return json([ 'code' => 200, 'data' => [ 'list' => $messages, 'total' => $total, 'has_more' => ($offset + count($messages)) < $total ] ]); } catch (\Exception $e) { return json(['code' => 500, 'msg' => '获取聊天历史失败: ' . $e->getMessage()]); } } /** * 标记消息为已读 */ public function mark_as_read() { $conversationId = $this->request->param('conversation_id/d', 0); $userId = $this->request->param('user_id/d', 0); if (!$conversationId || !$userId) { return json(['code' => 400, 'msg' => '参数不完整']); } try { // 开始事务 Db::startTrans(); // 1. 标记消息为已读 Db::name('chat_message') ->where('conversation_id', $conversationId) ->where('receiver_id', $userId) ->where('read_status', 0) ->update([ 'read_status' => 1, 'update_time' => date('Y-m-d H:i:s') ]); // 2. 重置会话未读数 Db::name('chat_conversation') ->where('id', $conversationId) ->update([ 'unread_count' => 0, 'update_time' => date('Y-m-d H:i:s') ]); // 提交事务 Db::commit(); return json(['code' => 200, 'msg' => '标记成功']); } catch (\Exception $e) { // 回滚事务 Db::rollback(); return json(['code' => 500, 'msg' => '标记失败: ' . $e->getMessage()]); } } /** * 获取会话列表 * @return \think\Response */ public function conversations(Request $request) { try { // 获取当前技师ID (从token或session中获取) $techId = $this->getCurrentTechId(); // 获取请求参数 $page = $request->param('page/d', 1); $pageSize = $request->param('page_size/d', 10); // 查询会话列表 $conversations = ChatConversation::where('tech_id', $techId) ->with(['user', 'lastMessage']) ->order('update_time', 'desc') ->page($page, $pageSize) ->select(); // 格式化返回数据 $data = []; foreach ($conversations as $convo) { $data[] = [ 'id' => $convo->id, 'user_id' => $convo->user_id, 'user_name' => $convo->user->nickname ?? '', 'user_avatar' => $convo->user->avatar ?? '', 'last_message' => $convo->lastMessage->content ?? '', 'last_message_time' => $convo->lastMessage->create_time ?? '', 'unread_count' => $convo->unread_count, 'update_time' => $convo->update_time ]; } return json([ 'code' => 200, 'msg' => '成功', 'data' => $data ]); } catch (\Exception $e) { return json([ 'code' => 500, 'msg' => '获取会话列表失败: ' . $e->getMessage() ]); } } /** * 获取当前技师ID * @return int * @throws \Exception */ private function getCurrentTechId() { return $this->coachInfo['coach_id']; } /** * 发送消息 */ public function send() { $params = $this->request->param(); $techId = $params['tech_id'] ?? 0; $orderId = $params['order_id'] ?? 0; $content = $params['content'] ?? ''; if (empty($content)) { return json(['code' => 400, 'msg' => '消息内容不能为空']); } // 生成会话ID $conversation = ChatConversation::where(['tech_id'=>$techId,'user_id'=>$this->userId])->find(); if (empty($conversation)) { $cccc = new ChatConversation; $conversationId = $cccc->insertGetId(['tech_id'=>$techId,'user_id'=>$this->userId]); }else{ $conversationId = $conversation['id']; } // 创建消息 $message = new ChatMessage(); $message->conversation_id = $conversationId; $message->sender_id = $this->userId; $message->sender_type = ChatMessage::SENDER_USER; // 用户 $message->receiver_id = $techId; $message->receiver_type = ChatMessage::SENDER_TECH; // 技师 $message->content = $content; $message->message_type = ChatMessage::TYPE_TEXT; // 文本 $message->read_status = ChatMessage::UNREAD; // 未读 $message->order_id = $orderId; $message->save(); // TODO: 这里应该通过WebSocket推送给技师 return json(['code' => 200, 'msg' => '发送成功', 'data' => $message]); } /** * 标记消息为已读 */ public function markAsRead() { $params = $this->request->param(); $conversationId = $params['conversation_id'] ?? ''; $userId = $this->request->uid; if (empty($conversationId)) { return json(['code' => 400, 'msg' => '会话ID不能为空']); } // 标记消息为已读 Db::name('chat_message') ->where('conversation_id', $conversationId) ->where('receiver_id', $userId) ->where('read_status', ChatMessage::UNREAD) ->update(['read_status' => ChatMessage::READ]); return json(['code' => 200, 'msg' => '已标记为已读']); } /** * 获取未读消息数量 */ public function unreadCount() { $unreadCount = ChatMessage::where([ 'conversation_id' => $this->request->uid, 'receiver_type' => ChatMessage::SENDER_USER, // 用户 'read_status' => ChatMessage::UNREAD ])->count(); return json(['code' => 200, 'data' => ['count' => $unreadCount]]); } /** * 获取最后一条消息 */ public function lastMessage() { $params = $this->request->param(); $techId = $params['tech_id'] ?? 0; $orderId = $params['order_id'] ?? 0; // 生成会话ID $conversationId = min($this->request->uid, $techId) . '_' . max($this->request->uid, $techId); $message = ChatMessage::where([ 'conversation_id' => $conversationId, 'order_id' => $orderId ]) ->order('id', 'desc') ->find(); return json(['code' => 200, 'data' => $message]); } }