You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace app\chat\logic;
use app\base\model\user\UserInfo;
use app\chat\model\ChatFriendsRoom;
use app\chat\model\ChatFriendsRoomMessage;
use app\chat\model\ChatFriendsRoomUser;
use think\facade\Db;
class FriendsChat extends Base
{
/**
* 开启个人聊天会话并返回聊天房间ID有事务
* @param int $to_user_id 对方user_id
* @param string $client_id 客户端ID
* @date 2022-07-29
*/
public function updateChatRoom($to_user_id,$client_id)
{
$friends_room_model = new ChatFriendsRoom();
$friends_chat_service = new \app\chat\service\FriendsChat();
$websocket_param = get_websocket_config();
$group_class = new \websocket\Group($websocket_param);
if ($to_user_id == $this->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;
}
}