userId) { return sendErrorArray(3001, '您不能和自己聊天'); } // 是否存在现有聊天房间 $room_id = $friends_room_model->getFriendsRoomId($to_user_id); Db::startTrans(); // 不存在则创建新房间 if (empty($room_id)) { // 创建新的聊天房间 $data = [ 'uid' => $this->mid, 'user_id' => $this->userId, 'another_user_id' => $to_user_id ]; $room_id = $friends_room_model->dataUpdate($data); if (!$room_id) { Db::rollback(); return sendErrorArray(3001, '创建好友聊天失败'); } // 存在client_id则绑定到组 if(!empty($client_id)){ // websocket加入某个组 $result = $group_class->joinGroup($client_id, $room_id); } } // 房间加入双方user_id $result = $friends_chat_service->updateRoomUser($room_id, $to_user_id); if (!$result) { Db::rollback(); return sendErrorArray(3002, '创建好友聊天失败'); } Db::commit(); return sendSuccessArray([ 'room_id' => $room_id ]); } /** * 获取聊天的用户列表 * @date 2022-08-01 */ public function listChatRoom() { $friend_room_user_model = new ChatFriendsRoomUser(); $friend_chat_service = new \app\chat\service\FriendsChat(); // 获取聊天的用户列表 $result = $friend_chat_service->listChatRoom(); return $result; } /** * 删除个人聊天会话 * @param int $room_id 房间ID * @date 2022-09-20 */ public function deleteChatRoom($room_id) { $friend_room_user_model = new ChatFriendsRoomUser(); // 删除聊天室 $res = $friend_room_user_model->dataDel([ ['room_id', '=', $room_id], ['user_id', '=', $this->userId] ]); // 有错误 if (!$res) { return sendErrorArray(3001, '删除聊天室失败'); } return sendSuccessArray([ 'room_id' => $room_id ]); } /** * 获取房间双方头像以及好友昵称 * @param int $room_id 聊天室ID * @date 2022-08-03 */ public function getChatRoomDetail($room_id) { $friend_room_user_model = new ChatFriendsRoomUser(); // 获取某个聊天室双方的头像和好友昵称 $result = $friend_room_user_model->getUsersInfo($room_id); return $result; } /** * 更改聊天室用户在线状态 * @param int $room_id 聊天室ID * @param int $is_online 是否在线 1--在线 0--不在线 * @date 2022-08-16 */ public function updateUserOnlineStatus($room_id, $is_online) { $friend_room_user_model = new ChatFriendsRoomUser(); $fried_chat_service = new \app\chat\service\FriendsChat(); // 更改在线状态 $result = $friend_room_user_model->updateUserOnlineStatus($room_id, $is_online); if (!$result) { return sendErrorArray(3001, '进入聊天室失败'); } // 更改所有未读消息为已读 并清空未读数量 $result = $fried_chat_service->allMessageHasRead($room_id); if (!$result['code']) { return $result; } return sendSuccessArray(); } /** * 绑定用户和现有聊天室 * @param int $client_id 客户端ID * @param int $room_id 聊天室ID * @date 2022-08-16 */ public function bindUser($client_id, $room_id = '') { $websocket_param = get_websocket_config(); $room_model = new ChatFriendsRoom(); $uid_class = new \websocket\Uid($websocket_param); $group_class = new \websocket\Group($websocket_param); // websocket绑定用户 $result = $uid_class->bindUid($client_id, $this->userId); // 绑定所有需要监听的聊天室 $room_ids = $room_model->listRoomId(); foreach ($room_ids as $k => $v) { // websocket加入某个组 $result = $group_class->joinGroup($client_id, $v); } return sendSuccessArray(); } /** * 发送消息 * @param int $room_id 聊天室ID * @param string $content 聊天内容 * @param int $type 聊天类型 1--文字(有表情) 2--语音 3--图片 4--位置 * @param array $attach_data 附加数据 type=3时{seconds:录音时长,单位秒} * @date 2022-08-08 */ public function insertChatMessage($room_id, $content, $type = 1, $attach_data = []) { $websocket_param = get_websocket_config(); $user_info_model = new UserInfo(); $friend_room_user_model = new ChatFriendsRoomUser(); $friend_room_message_model = new ChatFriendsRoomMessage(); $friends_chat_service = new \app\chat\service\FriendsChat(); $group_class = new \websocket\Group($websocket_param); // 查找房间的好友user_id $to_user_id = $friend_room_user_model->getFriendUserId($room_id); // 开启事务 Db::startTrans(); // 检查房间双方是否都存在 不存在则不全房间好友 房间加入双方user_id $result = $friends_chat_service->updateRoomUser($room_id, $to_user_id); if (!$result) { Db::rollback(); return sendErrorArray(3001, '创建好友聊天失败'); } // 图片在附加数据中存储宽高 if ($type == 3) { // 获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息 $result = getimagesize($content); $attach_data = [ 'width' => $result[0], 'height' => $result[1], ]; } // 插入聊天记录表 $data = [ 'room_id' => $room_id, 'user_id' => $this->userId, 'to_user_id' => $to_user_id, 'type' => $type, 'content' => $content, 'attach_data' => $attach_data ]; // 查询聊天室对方是否在线 $is_friend_online = $friend_room_user_model->isFriendOnline($room_id, $to_user_id); if ($is_friend_online) { // 对方在线消息更改为已读 $data['is_read'] = 1; } $new_message_id = $friend_room_message_model->dataUpdate($data); if (!$new_message_id) { Db::rollback(); return sendErrorArray(3002, '插入聊天记录失败'); } // 更新房间好友表的最近一条信息 $friend_room_user_update = [ 'last_message_type' => $type, 'last_message_content' => $content, 'update_time' => time() ]; // 更新房间好友表数据 $res = $friend_room_user_model->where([ ['room_id', '=', $room_id] ])->update($friend_room_user_update); if ($res === false) { Db::rollback(); return sendErrorArray(3003, '插入聊天记录失败'); } // 好友不在线,更新消息未读数量 if (!$is_friend_online) { $res = $friend_room_user_model->where([ ['room_id', '=', $room_id], ['user_id', '=', $to_user_id] ])->save([ 'unread_number' => Db::raw('unread_number + 1') ]); if (!$res) { Db::rollback(); return sendErrorArray(3004, '更新消息未读数量失败'); } } // 提交事务 Db::commit(); // 获取用户头像 $user_info = $user_info_model->getOneData([ ['user_id', '=', $this->userId] ], 'nick_name,head_img'); // 获取好友用户头像 $to_user_info = $user_info_model->getOneData([ ['user_id', '=', $to_user_id] ], 'nick_name,head_img'); // 查询上一条消息的创建时间 $last_room_message_time = $friend_room_message_model->getOneData([ ['id', '<', $new_message_id], ['room_id', '=', $room_id] ], 'create_time'); if (empty($last_room_message_time)) { $is_show_time = 1; $show_time = $friends_chat_service->timeShow(time()); } else { // 5分钟以上显示时间 if (time() - $last_room_message_time >= 5 * 60) { $is_show_time = 1; $show_time = $friends_chat_service->timeShow(time()); // 5分钟以内不显示时间 } else { $is_show_time = 0; $show_time = ''; } } // websocket发送消息 $show_message_text = $friends_chat_service->getShowMessageText($type, $content); $list_time_show = $friends_chat_service->listTimeShow(time()); $message = [ 'type' => 'chat_friend_message', 'send_type' => 'to_group', 'to_group' => $room_id, 'data' => [ // 消息ID 'id' => $new_message_id, // 房间ID 'room_id' => $room_id, // 用户ID 'user_id' => $this->userId, // 接收的用户ID 'to_user_id' => $to_user_id, // 消息类型 'type' => $type, // 消息内容 'content' => $content, // 附加数据 'attach_data' => $attach_data, // 创建时间 'create_time' => date("Y-m-d H:i:s"), // 头像 'user_head_img' => $user_info['head_img'], // 是否显示时间 'is_show_time' => $is_show_time, // 显示时间 'show_time' => $show_time, // 消息列表需要,详情详情释放 列表显示信息内容 'show_message_text' => $show_message_text, // 消息列表需要,详情详情释放 列表显示时间 'list_time_show' => $list_time_show, // 消息列表需要,详情详情释放 列表显示好友昵称 'to_user_nick_name' => $to_user_info['nick_name'], // 消息列表需要,详情详情释放 列表显示好友头像 'to_user_head_img' => $to_user_info['head_img'] ] ]; $result = $group_class->sendToGroup($room_id, $message); return sendSuccessArray(); } /** * 获取聊天记录 * @param int $room_id 房间ID * @param int $cur_first_message_id 最上面一条的ID * @date 2022-08-08 */ public function listChatRoomMessage($room_id, $cur_first_message_id) { $message_model = new ChatFriendsRoomMessage(); $friend_room_user_model = new ChatFriendsRoomUser(); $friends_chat_service = new \app\chat\service\FriendsChat(); // 查找聊天室用户表,找到创建用户的时间为聊天的起始时间 $start_time = $friend_room_user_model->getOneData([ ['uid', '=', $this->mid], ['room_id', '=', $room_id], ['user_id', '=', $this->userId] ], 'create_time'); // 查找聊天记录 $data_list = $message_model->listChatRoomMessage($room_id, $start_time, $cur_first_message_id); // 聊天记录反转正序 $data_list['data'] = array_reverse($data_list['data']); // 获取某个聊天室双方的头像和好友昵称 $users_info = $friend_room_user_model->getUsersInfo($room_id); foreach ($data_list['data'] as $k => &$v) { // 拼接头像信息 和 是否是自己发送 if ($v['user_id'] == $this->userId) { // 拼接个人头像 $v['user_head_img'] = $users_info['user_head_img']; } else { // 拼接好友头像 $v['user_head_img'] = $users_info['to_user_head_img']; } #TODO 12小时和24小时格式判断 // 显示聊天时间 // 第1个一直显示时间 if ($k == 0) { $v['is_show_time'] = 1; $v['show_time'] = $friends_chat_service->timeShow(strtotime($v['create_time'])); // 间隔超过5分钟显示时间 } else if (strtotime($v['create_time']) - strtotime($data_list['data'][$k - 1]['create_time']) >= 5 * 60) { $v['is_show_time'] = 1; $v['show_time'] = $friends_chat_service->timeShow(strtotime($v['create_time'])); // 5分钟以内不显示时间 } else { $v['is_show_time'] = 0; $v['show_time'] = ''; } } return $data_list; } }