From f04fea506d6123a270c040374e11b0140755b700 Mon Sep 17 00:00:00 2001 From: gzydong <837215079@qq.com> Date: Mon, 5 Jul 2021 21:52:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LumenIM 同步SQL.sql | 109 ++++ app/Amqp/Consumer/ChatMessageConsumer.php | 177 +++--- app/Command/TestCommand.php | 4 +- .../{TalkMessageType.php => TalkMsgType.php} | 5 +- app/Constants/TalkType.php | 25 + app/Controller/Api/V1/ArticleController.php | 2 +- app/Controller/Api/V1/AuthController.php | 2 +- app/Controller/Api/V1/ContactsController.php | 13 +- app/Controller/Api/V1/DownloadController.php | 16 +- app/Controller/Api/V1/EmoticonController.php | 85 +-- app/Controller/Api/V1/GroupController.php | 41 +- app/Controller/Api/V1/TalkController.php | 541 +++--------------- .../Api/V1/TalkMessageController.php | 434 ++++++++++++++ app/Controller/Api/V1/UploadController.php | 2 +- app/Controller/Api/V1/UsersController.php | 2 +- app/Controller/WebSocketController.php | 2 - app/Exception/Handler/AppExceptionHandler.php | 14 +- app/Model/Chat/ChatRecord.php | 44 -- app/Model/Chat/TalkRecords.php | 57 ++ ...hatRecordsCode.php => TalkRecordsCode.php} | 4 +- ...ecordsDelete.php => TalkRecordsDelete.php} | 4 +- ...hatRecordsFile.php => TalkRecordsFile.php} | 4 +- ...ordsForward.php => TalkRecordsForward.php} | 4 +- ...ecordsInvite.php => TalkRecordsInvite.php} | 4 +- app/Model/Emoticon.php | 14 +- .../{EmoticonDetail.php => EmoticonItem.php} | 13 +- app/Model/Robot.php | 45 ++ app/Model/TalkList.php | 164 ++++++ app/Model/User.php | 8 +- app/Model/UsersChatList.php | 149 ----- app/Model/UsersFriend.php | 8 +- app/Service/ArticleService.php | 22 +- app/Service/ContactsService.php | 13 +- app/Service/EmoticonService.php | 45 +- app/Service/GroupService.php | 156 ++--- app/Service/MessageHandleService.php | 56 +- app/Service/TalkMessageService.php | 9 + app/Service/TalkService.php | 488 ++++++++-------- app/Service/UserService.php | 1 + message.php | 80 +++ .../2020_11_04_152602_create_users_table.php | 7 +- ...020_11_04_153337_create_emoticon_table.php | 11 +- ..._04_153347_create_emoticon_item_table.php} | 20 +- .../2021_07_02_165853_create_robots_table.php | 42 ++ 更新计划.md | 9 + 45 files changed, 1701 insertions(+), 1254 deletions(-) create mode 100644 LumenIM 同步SQL.sql rename app/Constants/{TalkMessageType.php => TalkMsgType.php} (78%) create mode 100644 app/Constants/TalkType.php create mode 100644 app/Controller/Api/V1/TalkMessageController.php delete mode 100644 app/Model/Chat/ChatRecord.php create mode 100644 app/Model/Chat/TalkRecords.php rename app/Model/Chat/{ChatRecordsCode.php => TalkRecordsCode.php} (89%) rename app/Model/Chat/{ChatRecordsDelete.php => TalkRecordsDelete.php} (86%) rename app/Model/Chat/{ChatRecordsFile.php => TalkRecordsFile.php} (94%) rename app/Model/Chat/{ChatRecordsForward.php => TalkRecordsForward.php} (89%) rename app/Model/Chat/{ChatRecordsInvite.php => TalkRecordsInvite.php} (90%) rename app/Model/{EmoticonDetail.php => EmoticonItem.php} (70%) create mode 100644 app/Model/Robot.php create mode 100644 app/Model/TalkList.php delete mode 100644 app/Model/UsersChatList.php create mode 100644 app/Service/TalkMessageService.php create mode 100644 message.php rename migrations/{2020_11_04_153347_create_emoticon_details_table.php => 2020_11_04_153347_create_emoticon_item_table.php} (63%) create mode 100644 migrations/2021_07_02_165853_create_robots_table.php create mode 100644 更新计划.md diff --git a/LumenIM 同步SQL.sql b/LumenIM 同步SQL.sql new file mode 100644 index 0000000..ba0faa9 --- /dev/null +++ b/LumenIM 同步SQL.sql @@ -0,0 +1,109 @@ +# lar_users_chat_list 数据表同步SQL +ALTER TABLE `lar_users_chat_list` RENAME `lar_talk_list`; +ALTER TABLE `lar_talk_list` DROP INDEX `idx_uid_type_friendid_group_id`; +ALTER TABLE `lar_talk_list` MODIFY `is_top` tinyint(4) unsigned DEFAULT '0' COMMENT '是否置顶[0:否;1:是;]'; +ALTER TABLE `lar_talk_list` CHANGE `type` `talk_type` tinyint(3) unsigned DEFAULT '1' COMMENT '聊天类型[1:私信;2:群聊;]'; +ALTER TABLE `lar_talk_list` CHANGE `uid` `user_id` int(11) DEFAULT '0' COMMENT '用户ID'; +ALTER TABLE `lar_talk_list` CHANGE `not_disturb` `is_disturb` tinyint(4) unsigned DEFAULT '0' COMMENT '消息免打扰[0:否;1:是;]'; +ALTER TABLE `lar_talk_list` ADD `receiver_id` int(11) unsigned DEFAULT '0' COMMENT '接收者ID(用户ID 或 群ID)'; +ALTER TABLE `lar_talk_list` ADD `is_delete` tinyint(4) unsigned DEFAULT '0' COMMENT '是否删除[0:否;1:是;]'; +ALTER TABLE `lar_talk_list` ADD `is_robot` tinyint(4) unsigned DEFAULT '0' COMMENT '是否机器人[0:否;1:是;]'; +ALTER TABLE `lar_talk_list` ADD INDEX idx_user_id_receiver_id_talk_type (`user_id`,`receiver_id`,`talk_type`); +UPDATE `lar_talk_list` set `receiver_id` = if(`talk_type` = 1,`friend_id`,`group_id`),`is_delete` = if(`status` = 1,0,1); +ALTER TABLE `lar_talk_list` DROP COLUMN `friend_id`; +ALTER TABLE `lar_talk_list` DROP COLUMN `group_id`; +ALTER TABLE `lar_talk_list` DROP COLUMN `status`; + +# lar_emoticon 数据表同步SQL +ALTER TABLE `lar_emoticon` MODIFY `name` varchar(50) NOT NULL DEFAULT '' COMMENT '分组名称'; +ALTER TABLE `lar_emoticon` CHANGE `url` `icon` varchar(255) DEFAULT '' COMMENT '分组图标'; +ALTER TABLE `lar_emoticon` ADD `status` tinyint(4) DEFAULT '0' COMMENT '分组状态[-1:已删除;0:正常;1:已禁用;]'; +ALTER TABLE `lar_emoticon` ADD `updated_at` datetime DEFAULT NULL COMMENT '更新时间'; +ALTER TABLE `lar_emoticon` DROP INDEX `name`; +ALTER TABLE `lar_emoticon` ADD UNIQUE uk_name (`name`); + +# lar_emoticon_details 数据表同步SQL +ALTER TABLE `lar_emoticon_details` RENAME `lar_emoticon_item`; +ALTER TABLE `lar_emoticon_item` MODIFY `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '表情包详情ID'; +ALTER TABLE `lar_emoticon_item` MODIFY `describe` varchar(20) DEFAULT '' COMMENT '表情描述'; +ALTER TABLE `lar_emoticon_item` MODIFY `url` varchar(255) DEFAULT '' COMMENT '图片链接'; +ALTER TABLE `lar_emoticon_item` ADD `updated_at` datetime DEFAULT NULL COMMENT '更新时间'; +ALTER TABLE `lar_emoticon_item` comment '表情包详情表'; + +# lar_users 数据表同步SQL +ALTER TABLE `lar_users` ADD `is_robot` tinyint(4) unsigned DEFAULT '0' COMMENT '是否机器人[0:否;1:是;]'; +ALTER TABLE `lar_users` ADD `updated_at` datetime DEFAULT NULL COMMENT '更新时间'; + +# lar_chat_records 数据表同步SQL +ALTER TABLE `lar_chat_records` RENAME `lar_talk_records`; +ALTER TABLE `lar_talk_records` DROP INDEX `idx_userid_receiveid`; +ALTER TABLE `lar_talk_records` CHANGE `source` `talk_type` tinyint(3) unsigned DEFAULT '1' COMMENT '对话类型[1:私信;2:群聊;]'; +ALTER TABLE `lar_talk_records` MODIFY `msg_type` tinyint(3) unsigned DEFAULT '1' COMMENT '消息类型[1:文本消息;2:文件消息;3:会话消息;4:代码消息;5:投票消息;6:群公告;7:好友申请;8:登录通知;9:入群消息/退群消息;]'; +ALTER TABLE `lar_talk_records` CHANGE `receive_id` `receiver_id` int(11) unsigned DEFAULT '0' COMMENT '接收者ID(用户ID 或 群ID)'; +ALTER TABLE `lar_talk_records` MODIFY `is_revoke` tinyint(4) unsigned DEFAULT '0' COMMENT '是否撤回消息[0:否;1:是;]'; +ALTER TABLE `lar_talk_records` MODIFY `content` text CHARACTER SET utf8mb4 COMMENT '文本消息 {@nickname@}'; +ALTER TABLE `lar_talk_records` ADD `is_mark` tinyint(4) unsigned DEFAULT '0' COMMENT '是否重要消息[0:否;1:是;]'; +ALTER TABLE `lar_talk_records` ADD `is_read` tinyint(4) DEFAULT '0' COMMENT '是否已读[0:否;1:是;]'; +ALTER TABLE `lar_talk_records` ADD `quote_id` int(11) unsigned DEFAULT '0' COMMENT '引用消息ID'; +ALTER TABLE `lar_talk_records` ADD `warn_users` varchar(200) NOT NULL DEFAULT '' COMMENT '@好友 、 多个用英文逗号 “,” 拼接 (0:代表所有人)'; +ALTER TABLE `lar_talk_records` ADD `updated_at` datetime DEFAULT NULL COMMENT '更新时间'; +ALTER TABLE `lar_talk_records` ADD INDEX idx_user_id_receiver_id (`user_id`,`receiver_id`); +UPDATE `lar_talk_records` SET `msg_type` = CASE WHEN msg_type = 3 THEN 9 WHEN msg_type = 4 THEN 3 WHEN msg_type = 5 THEN 4 ELSE msg_type END; + +ALTER TABLE `lar_chat_records_code` RENAME `lar_talk_records_code`; +ALTER TABLE `lar_chat_records_delete` RENAME `lar_talk_records_delete`; +ALTER TABLE `lar_chat_records_forward` RENAME `lar_talk_records_forward`; +ALTER TABLE `lar_chat_records_invite` RENAME `lar_talk_records_invite`; +ALTER TABLE `lar_chat_records_file` RENAME `lar_talk_records_file`; + +# lar_users_friends 数据表同步SQL +ALTER TABLE `lar_users_friends` MODIFY `active` tinyint(3) unsigned DEFAULT '1' COMMENT '主动好友申请方[1:user1;2:user2;]'; +ALTER TABLE `lar_users_friends` MODIFY `status` tinyint(3) DEFAULT '0' COMMENT '好友状态 [-1:双方均解除好友关系;0:正常;1:user1 已删除对方;2:user2 已删除对方;]'; +ALTER TABLE `lar_users_friends` CHANGE `agree_time` `updated_at` datetime DEFAULT NULL COMMENT '更新时间'; +UPDATE `lar_users_friends` SET `status` = CASE WHEN `status` = 0 THEN -1 WHEN `status` = 1 THEN 0 ELSE `status` END; + +# lar_users_friends_apply 数据表同步SQL +ALTER TABLE `lar_users_friends_apply` MODIFY `status` tinyint(4) unsigned DEFAULT '0' COMMENT '申请状态[0:等待处理;1:已同意;2:已拒绝;]'; + +-- ---------------------------- +-- 以下是新增数据表 +-- ---------------------------- + +CREATE TABLE `lar_robots` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器人ID', + `user_id` int(11) unsigned DEFAULT '0' COMMENT '关联用户ID', + `robot_name` varchar(20) NOT NULL DEFAULT '' COMMENT '机器人名称', + `describe` varchar(255) DEFAULT '' COMMENT '描述信息', + `logo` varchar(255) DEFAULT '' COMMENT '机器人logo', + `is_talk` tinyint(4) DEFAULT '0' COMMENT '可发送消息[0:否;1:是;]', + `status` tinyint(4) unsigned DEFAULT '0' COMMENT '状态[-1:已删除;0:正常;1:已禁用;]', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='聊天机器人表'; + +CREATE TABLE `lar_talk_records_vote` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '投票ID', + `record_id` int(11) unsigned DEFAULT '0' COMMENT '消息记录ID', + `user_id` int(11) unsigned DEFAULT '0' COMMENT '用户ID', + `title` varchar(50) DEFAULT '' COMMENT '投票标题', + `answer_mode` tinyint(4) unsigned DEFAULT '0' COMMENT '答题模式[0:单选;1:多选;]', + `answer_option` json DEFAULT NULL COMMENT '答题选项', + `answer_num` smallint(6) unsigned DEFAULT '0' COMMENT '应答人数', + `answered_num` smallint(6) unsigned DEFAULT '0' COMMENT '已答人数', + `status` tinyint(4) unsigned DEFAULT '0' COMMENT '投票状态[0:投票中;1:已完成;]', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_record_id` (`record_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='聊天对话记录(投票消息表)'; + +CREATE TABLE `lar_talk_records_vote_answer` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '答题ID', + `vote_id` int(11) unsigned DEFAULT '0' COMMENT '投票ID', + `user_id` int(11) unsigned DEFAULT '0' COMMENT '用户ID', + `option` char(1) NOT NULL DEFAULT '' COMMENT '投票选项[A、B、C 、D、E、F]', + `created_at` datetime DEFAULT NULL COMMENT '答题时间', + PRIMARY KEY (`id`), + KEY `idx_vote_id_user_id` (`vote_id`,`user_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='聊天对话记录(投票消息统计表)'; diff --git a/app/Amqp/Consumer/ChatMessageConsumer.php b/app/Amqp/Consumer/ChatMessageConsumer.php index 5d623eb..fe21dc4 100644 --- a/app/Amqp/Consumer/ChatMessageConsumer.php +++ b/app/Amqp/Consumer/ChatMessageConsumer.php @@ -11,6 +11,8 @@ declare(strict_types=1); namespace App\Amqp\Consumer; +use App\Constants\TalkMsgType; +use App\Constants\TalkType; use Hyperf\Amqp\Annotation\Consumer; use Hyperf\Amqp\Result; use Hyperf\Amqp\Message\ConsumerMessage; @@ -19,11 +21,11 @@ use Hyperf\Amqp\Builder\QueueBuilder; use PhpAmqpLib\Message\AMQPMessage; use App\Model\User; use App\Model\UsersFriend; -use App\Model\Chat\ChatRecord; -use App\Model\Chat\ChatRecordsCode; -use App\Model\Chat\ChatRecordsFile; -use App\Model\Chat\ChatRecordsInvite; -use App\Model\Chat\ChatRecordsForward; +use App\Model\Chat\TalkRecords; +use App\Model\Chat\TalkRecordsCode; +use App\Model\Chat\TalkRecordsFile; +use App\Model\Chat\TalkRecordsInvite; +use App\Model\Chat\TalkRecordsForward; use App\Model\Group\Group; use App\Service\SocketClientService; use App\Constants\SocketConstants; @@ -140,39 +142,43 @@ class ChatMessageConsumer extends ConsumerMessage */ public function onConsumeTalk(array $data, AMQPMessage $message): string { - $source = $data['data']['source']; + $talk_type = $data['data']['talk_type']; + $sender_id = $data['data']['sender_id']; + $receiver_id = $data['data']['receiver_id']; + $record_id = $data['data']['record_id']; + $fds = []; $groupInfo = null; - if ($source == 1) {// 私聊 + if ($talk_type == TalkType::PRIVATE_CHAT) { $fds = array_merge( - $this->socketClientService->findUserFds($data['data']['sender']), - $this->socketClientService->findUserFds($data['data']['receive']) + $this->socketClientService->findUserFds($sender_id), + $this->socketClientService->findUserFds($receiver_id) ); - } else if ($source == 2) {// 群聊 - $userIds = SocketRoom::getInstance()->getRoomMembers(strval($data['data']['receive'])); - foreach ($userIds as $uid) { - $fds = array_merge($fds, $this->socketClientService->findUserFds((int)$uid)); + } else if ($talk_type == TalkType::GROUP_CHAT) { + foreach (SocketRoom::getInstance()->getRoomMembers(strval($receiver_id)) as $uid) { + $fds = array_merge($fds, $this->socketClientService->findUserFds(intval($uid))); } - $groupInfo = Group::where('id', $data['data']['receive'])->first(['group_name', 'avatar']); + $groupInfo = Group::where('id', $receiver_id)->first(['group_name', 'avatar']); } // 客户端ID去重 - if (!$fds = array_unique($fds)) return Result::ACK; + if (!$fds = array_unique($fds)) { + return Result::ACK; + } - /** @var ChatRecord */ - $result = ChatRecord::leftJoin('users', 'users.id', '=', 'chat_records.user_id') - ->where('chat_records.id', $data['data']['record_id']) + $result = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id') + ->where('talk_records.id', $record_id) ->first([ - 'chat_records.id', - 'chat_records.source', - 'chat_records.msg_type', - 'chat_records.user_id', - 'chat_records.receive_id', - 'chat_records.content', - 'chat_records.is_revoke', - 'chat_records.created_at', + 'talk_records.id', + 'talk_records.talk_type', + 'talk_records.msg_type', + 'talk_records.user_id', + 'talk_records.receiver_id', + 'talk_records.content', + 'talk_records.is_revoke', + 'talk_records.created_at', 'users.nickname', 'users.avatar', ]); @@ -182,14 +188,34 @@ class ChatMessageConsumer extends ConsumerMessage $file = $code_block = $forward = $invite = []; switch ($result->msg_type) { - case 2:// 文件消息 - $file = ChatRecordsFile::where('record_id', $result->id)->first(['id', 'record_id', 'user_id', 'file_source', 'file_type', 'save_type', 'original_name', 'file_suffix', 'file_size', 'save_dir']); + case TalkMsgType::FILE_MESSAGE: + $file = TalkRecordsFile::where('record_id', $result->id)->first([ + 'id', 'record_id', 'user_id', 'file_source', 'file_type', + 'save_type', 'original_name', 'file_suffix', 'file_size', 'save_dir' + ]); + $file = $file ? $file->toArray() : []; $file && $file['file_url'] = get_media_url($file['save_dir']); - break; - case 3:// 入群消息/退群消息 - $notifyInfo = ChatRecordsInvite::where('record_id', $result->id)->first([ + + case TalkMsgType::FORWARD_MESSAGE: + $forward = ['num' => 0, 'list' => []]; + $forwardInfo = TalkRecordsForward::where('record_id', $result->id)->first(['records_id', 'text']); + if ($forwardInfo) { + $forward = [ + 'num' => count(parse_ids($forwardInfo->records_id)), + 'list' => json_decode($forwardInfo->text, true) ?? [] + ]; + } + break; + + case TalkMsgType::CODE_MESSAGE: + $code_block = TalkRecordsCode::where('record_id', $result->id)->first(['record_id', 'code_lang', 'code']); + $code_block = $code_block ? $code_block->toArray() : []; + break; + + case TalkMsgType::GROUP_INVITE_MESSAGE: + $notifyInfo = TalkRecordsInvite::where('record_id', $result->id)->first([ 'record_id', 'type', 'operate_user_id', 'user_ids' ]); @@ -202,37 +228,22 @@ class ChatMessageConsumer extends ConsumerMessage unset($notifyInfo, $userInfo); break; - case 4:// 会话记录消息 - $forward = ['num' => 0, 'list' => []]; - $forwardInfo = ChatRecordsForward::where('record_id', $result->id)->first(['records_id', 'text']); - if ($forwardInfo) { - $forward = [ - 'num' => count(parse_ids($forwardInfo->records_id)), - 'list' => json_decode($forwardInfo->text, true) ?? [] - ]; - } - - break; - case 5:// 代码块消息 - $code_block = ChatRecordsCode::where('record_id', $result->id)->first(['record_id', 'code_lang', 'code']); - $code_block = $code_block ? $code_block->toArray() : []; - break; } $notify = [ - 'send_user' => $data['data']['sender'], - 'receive_user' => $data['data']['receive'], - 'source_type' => $data['data']['source'], - 'data' => $this->formatTalkMessage([ + 'sender_id' => $sender_id, + 'receiver_id' => $receiver_id, + 'talk_type' => $talk_type, + 'data' => $this->formatTalkMessage([ 'id' => $result->id, + 'talk_type' => $result->talk_type, 'msg_type' => $result->msg_type, - 'source' => $result->source, + "user_id" => $result->user_id, + "receiver_id" => $result->receiver_id, 'avatar' => $result->avatar, 'nickname' => $result->nickname, 'group_name' => $groupInfo ? $groupInfo->group_name : '', 'group_avatar' => $groupInfo ? $groupInfo->avatar : '', - "user_id" => $result->user_id, - "receive_id" => $result->receive_id, "created_at" => $result->created_at, "content" => $result->content, "file" => $file, @@ -256,7 +267,7 @@ class ChatMessageConsumer extends ConsumerMessage */ public function onConsumeKeyboard(array $data, AMQPMessage $message): string { - $fds = $this->socketClientService->findUserFds($data['data']['receive_user']); + $fds = $this->socketClientService->findUserFds($data['data']['receiver_id']); $this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_KEYBOARD, $data['data']])); @@ -272,14 +283,20 @@ class ChatMessageConsumer extends ConsumerMessage */ public function onConsumeOnlineStatus(array $data, AMQPMessage $message): string { - $friends = UsersFriend::getFriendIds((int)$data['data']['user_id']); + $user_id = (int)$data['data']['user_id']; + $status = (int)$data['data']['status']; $fds = []; - foreach ($friends as $friend_id) { - $fds = array_merge($fds, $this->socketClientService->findUserFds((int)$friend_id)); + foreach (UsersFriend::getFriendIds($user_id) as $friend_id) { + $fds = array_merge($fds, $this->socketClientService->findUserFds(intval($friend_id))); } - $this->socketPushNotify(array_unique($fds), json_encode([SocketConstants::EVENT_ONLINE_STATUS, $data['data']])); + $this->socketPushNotify(array_unique($fds), json_encode([ + SocketConstants::EVENT_ONLINE_STATUS, [ + 'user_id' => $user_id, + 'status' => $status + ] + ])); return Result::ACK; } @@ -293,29 +310,26 @@ class ChatMessageConsumer extends ConsumerMessage */ public function onConsumeRevokeTalk(array $data, AMQPMessage $message): string { - /** @var ChatRecord */ - $record = ChatRecord::where('id', $data['data']['record_id'])->first(['id', 'source', 'user_id', 'receive_id']); + $record = TalkRecords::where('id', $data['data']['record_id'])->first(['id', 'talk_type', 'user_id', 'receiver_id']); $fds = []; - if ($record->source == 1) { - $fds = array_merge($fds, $this->socketClientService->findUserFds((int)$record->user_id)); - $fds = array_merge($fds, $this->socketClientService->findUserFds((int)$record->receive_id)); - } else if ($record->source == 2) { - $userIds = SocketRoom::getInstance()->getRoomMembers(strval($record->receive_id)); + if ($record->talk_type == TalkType::PRIVATE_CHAT) { + $fds = array_merge($fds, $this->socketClientService->findUserFds($record->user_id)); + $fds = array_merge($fds, $this->socketClientService->findUserFds($record->receiver_id)); + } else if ($record->talk_type == TalkType::GROUP_CHAT) { + $userIds = SocketRoom::getInstance()->getRoomMembers(strval($record->receiver_id)); foreach ($userIds as $uid) { $fds = array_merge($fds, $this->socketClientService->findUserFds((int)$uid)); } } - $this->socketPushNotify( - array_unique($fds), - json_encode([SocketConstants::EVENT_REVOKE_TALK, [ - 'record_id' => $record->id, - 'source' => $record->source, - 'user_id' => $record->user_id, - 'receive_id' => $record->receive_id, - ]]) - ); + $fds = array_unique($fds); + $this->socketPushNotify($fds, json_encode([SocketConstants::EVENT_REVOKE_TALK, [ + 'talk_type' => $record->talk_type, + 'sender_id' => $record->user_id, + 'receiver_id' => $record->receiver_id, + 'record_id' => $record->id, + ]])); return Result::ACK; } @@ -331,7 +345,10 @@ class ChatMessageConsumer extends ConsumerMessage { $fds = $this->socketClientService->findUserFds($data['data']['receive']); - $this->socketPushNotify(array_unique($fds), json_encode([SocketConstants::EVENT_FRIEND_APPLY, $data['data']])); + $this->socketPushNotify(array_unique($fds), json_encode([ + SocketConstants::EVENT_FRIEND_APPLY, + $data['data'] + ])); return Result::ACK; } @@ -360,12 +377,10 @@ class ChatMessageConsumer extends ConsumerMessage { $message = [ "id" => 0, // 消息记录ID - "source" => 1, // 消息来源[1:好友私信;2:群聊] + "talk_type" => 1, // 消息来源[1:好友私信;2:群聊] "msg_type" => 1, // 消息类型 "user_id" => 0, // 发送者用户ID - "receive_id" => 0, // 接收者ID[好友ID或群ID] - "content" => '',// 文本消息 - "is_revoke" => 0, // 消息是否撤销 + "receiver_id" => 0, // 接收者ID[好友ID或群ID] // 发送消息人的信息 "nickname" => "",// 用户昵称 @@ -380,7 +395,11 @@ class ChatMessageConsumer extends ConsumerMessage "invite" => [], // 消息创建时间 + "content" => '',// 文本消息 "created_at" => "", + + // 消息属性 + "is_revoke" => 0, // 消息是否撤销 ]; return array_merge($message, array_intersect_key($data, $message)); diff --git a/app/Command/TestCommand.php b/app/Command/TestCommand.php index 8e32611..68a7dfd 100644 --- a/app/Command/TestCommand.php +++ b/app/Command/TestCommand.php @@ -22,9 +22,11 @@ use App\Cache\UnreadTalk; use App\Constants\FileMediaType; use App\Model\Group\Group; use App\Model\Group\GroupMember; +use App\Model\TalkList; use App\Service\TalkService; use Hyperf\Command\Command as HyperfCommand; use Hyperf\Command\Annotation\Command; +use Hyperf\DbConnection\Db; use League\Flysystem\Filesystem; use Psr\Container\ContainerInterface; @@ -175,7 +177,5 @@ class TestCommand extends HyperfCommand //var_dump(FriendRemark::getInstance()); //var_dump(Group::isManager(2054,116)); - - echo FileMediaType::getMediaType('png'); } } diff --git a/app/Constants/TalkMessageType.php b/app/Constants/TalkMsgType.php similarity index 78% rename from app/Constants/TalkMessageType.php rename to app/Constants/TalkMsgType.php index 8499fa2..1131953 100644 --- a/app/Constants/TalkMessageType.php +++ b/app/Constants/TalkMsgType.php @@ -7,7 +7,7 @@ namespace App\Constants; * * @package App\Constants */ -class TalkMessageType +class TalkMsgType { const TEXT_MESSAGE = 1;//文本消息 const FILE_MESSAGE = 2;//文件消息 @@ -16,5 +16,6 @@ class TalkMessageType const VOTE_MESSAGE = 5;//投票消息 const GROUP_NOTICE_MESSAGE = 6;//群公告 const FRIEND_APPLY_MESSAGE = 7;//好友申请 - const USER_LOGIN = 8;//登录通知 + const USER_LOGIN_MESSAGE = 8;//登录通知 + const GROUP_INVITE_MESSAGE = 9;//入群退群消息 } diff --git a/app/Constants/TalkType.php b/app/Constants/TalkType.php new file mode 100644 index 0000000..6a056f4 --- /dev/null +++ b/app/Constants/TalkType.php @@ -0,0 +1,25 @@ +contactsService->getContacts($this->uid()); if ($rows) { $runArr = ServerRunID::getInstance()->getServerRunIdAll(); - foreach ($rows as $k => $row) { - // 查询用户当前是否在线 - $rows[$k]['online'] = $this->socketClientService->isOnlineAll($row['id'], $runArr); + foreach ($rows as $row) { + $row->is_online = $this->socketClientService->isOnlineAll($row->id, $runArr); } } @@ -129,8 +128,8 @@ class ContactsController extends CController } // 删除好友会话列表 - UsersChatList::delItem($user_id, $params['friend_id'], 2); - UsersChatList::delItem($params['friend_id'], $user_id, 2); + TalkList::delItem($user_id, $params['friend_id'], 2); + TalkList::delItem($params['friend_id'], $user_id, 2); // ... TODO 推送消息(待完善) diff --git a/app/Controller/Api/V1/DownloadController.php b/app/Controller/Api/V1/DownloadController.php index ba97bc8..528fb60 100644 --- a/app/Controller/Api/V1/DownloadController.php +++ b/app/Controller/Api/V1/DownloadController.php @@ -16,15 +16,15 @@ use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\HttpServer\Annotation\Middleware; use App\Middleware\JWTAuthMiddleware; use App\Model\Article\ArticleAnnex; -use App\Model\Chat\ChatRecord; -use App\Model\Chat\ChatRecordsFile; +use App\Model\Chat\TalkRecords; +use App\Model\Chat\TalkRecordsFile; use App\Model\Group\Group; use Hyperf\HttpServer\Contract\ResponseInterface; use League\Flysystem\Filesystem; /** * Class DownloadController - * @Controller(path="/api/v1/download") + * @Controller(prefix="/api/v1/download") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 @@ -51,7 +51,7 @@ class DownloadController extends CController 'cr_id' => 'required|integer' ]); - $recordsInfo = ChatRecord::select(['msg_type', 'source', 'user_id', 'receive_id'])->where('id', $params['cr_id'])->first(); + $recordsInfo = TalkRecords::select(['msg_type', 'talk_type', 'user_id', 'receiver_id'])->where('id', $params['cr_id'])->first(); if (!$recordsInfo) { return $this->response->fail('文件不存在!'); } @@ -60,18 +60,18 @@ class DownloadController extends CController // 判断消息是否是当前用户发送(如果是则跳过权限验证) if ($recordsInfo->user_id != $user_id) { - if ($recordsInfo->source == 1) { - if ($recordsInfo->receive_id != $user_id) { + if ($recordsInfo->talk_type == 1) { + if ($recordsInfo->receiver_id != $user_id) { return $this->response->fail('非法请求!'); } } else { - if (!Group::isMember($recordsInfo->receive_id, $user_id)) { + if (!Group::isMember($recordsInfo->receiver_id, $user_id)) { return $this->response->fail('非法请求!'); } } } - $info = ChatRecordsFile::select(['save_dir', 'original_name'])->where('record_id', $params['cr_id'])->first(); + $info = TalkRecordsFile::select(['save_dir', 'original_name'])->where('record_id', $params['cr_id'])->first(); if (!$info || !$filesystem->has($info->save_dir)) { return $this->response->fail('文件不存在或没有下载权限!'); } diff --git a/app/Controller/Api/V1/EmoticonController.php b/app/Controller/Api/V1/EmoticonController.php index de4d776..9f21fe7 100644 --- a/app/Controller/Api/V1/EmoticonController.php +++ b/app/Controller/Api/V1/EmoticonController.php @@ -17,14 +17,14 @@ use Hyperf\HttpServer\Annotation\Middleware; use App\Middleware\JWTAuthMiddleware; use App\Constants\ResponseCode; use App\Model\Emoticon; -use App\Model\EmoticonDetail; +use App\Model\EmoticonItem; use App\Service\EmoticonService; use League\Flysystem\Filesystem; use Psr\Http\Message\ResponseInterface; /** * Class EmoticonController - * @Controller(path="/api/v1/emoticon") + * @Controller(prefix="/api/v1/emoticon") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 @@ -49,11 +49,11 @@ class EmoticonController extends CController $user_id = $this->uid(); if ($ids = $this->emoticonService->getInstallIds($user_id)) { - $items = Emoticon::whereIn('id', $ids)->get(['id', 'name', 'url']); + $items = Emoticon::whereIn('id', $ids)->get(['id', 'name', 'icon']); foreach ($items as $item) { $emoticonList[] = [ 'emoticon_id' => $item->id, - 'url' => get_media_url($item->url), + 'url' => get_media_url($item->icon), 'name' => $item->name, 'list' => $this->emoticonService->getDetailsAll([ ['emoticon_id', '=', $item->id], @@ -80,12 +80,12 @@ class EmoticonController extends CController */ public function getSystemEmoticon() { - $items = Emoticon::get(['id', 'name', 'url'])->toArray(); + $items = Emoticon::get(['id', 'name', 'icon'])->toArray(); if ($items) { $ids = $this->emoticonService->getInstallIds($this->uid()); array_walk($items, function (&$item) use ($ids) { $item['status'] = in_array($item['id'], $ids) ? 1 : 0; - $item['url'] = get_media_url($item['url']); + $item['icon'] = get_media_url($item['icon']); }); } @@ -107,36 +107,37 @@ class EmoticonController extends CController ]); $user_id = $this->uid(); + + // 移除表情包 if ($params['type'] == 2) { - // 移除表情包 $isTrue = $this->emoticonService->removeSysEmoticon($user_id, $params['emoticon_id']); if (!$isTrue) { return $this->response->fail('移除表情包失败!'); } return $this->response->success([], '移除表情包成功...'); - } else { - // 添加表情包 - $emoticonInfo = Emoticon::where('id', $params['emoticon_id'])->first(['id', 'name', 'url']); - if (!$emoticonInfo) { - return $this->response->fail('添加表情包失败!'); - } - - if (!$this->emoticonService->installSysEmoticon($user_id, $params['emoticon_id'])) { - return $this->response->fail('添加表情包失败!'); - } - - $data = [ - 'emoticon_id' => $emoticonInfo->id, - 'url' => get_media_url($emoticonInfo->url), - 'name' => $emoticonInfo->name, - 'list' => $this->emoticonService->getDetailsAll([ - ['emoticon_id', '=', $emoticonInfo->id] - ]) - ]; - - return $this->response->success($data, '添加表情包成功...'); } + + // 添加表情包 + $emoticonInfo = Emoticon::where('id', $params['emoticon_id'])->first(['id', 'name', 'icon']); + if (!$emoticonInfo) { + return $this->response->fail('添加表情包失败!'); + } + + if (!$this->emoticonService->installSysEmoticon($user_id, $params['emoticon_id'])) { + return $this->response->fail('添加表情包失败!'); + } + + $data = [ + 'emoticon_id' => $emoticonInfo->id, + 'url' => get_media_url($emoticonInfo->icon), + 'name' => $emoticonInfo->name, + 'list' => $this->emoticonService->getDetailsAll([ + ['emoticon_id', '=', $emoticonInfo->id] + ]) + ]; + + return $this->response->success($data, '添加表情包成功...'); } /** @@ -171,12 +172,12 @@ class EmoticonController extends CController return $this->response->fail('图片上传失败!'); } - $result = EmoticonDetail::create([ + $result = EmoticonItem::create([ 'user_id' => $this->uid(), 'url' => $path, 'file_suffix' => $ext, 'file_size' => $file->getSize(), - 'created_at' => time() + 'created_at' => date('Y-m-d H:i:s') ]); if (!$result) { @@ -189,30 +190,6 @@ class EmoticonController extends CController ]); } - /** - * 收藏聊天图片的我的表情包 - * @RequestMapping(path="collect-emoticon", methods="post") - * - * @return ResponseInterface - */ - public function collectEmoticon() - { - $params = $this->request->inputs(['record_id']); - $this->validate($params, [ - 'record_id' => 'required|integer' - ]); - - [$isTrue, $data] = $this->emoticonService->collect($this->uid(), $params['record_id']); - - if (!$isTrue) { - return $this->response->fail('添加表情失败!'); - } - - return $this->response->success([ - 'emoticon' => $data - ]); - } - /** * 移除收藏的表情包 * @RequestMapping(path="del-collect-emoticon", methods="post") diff --git a/app/Controller/Api/V1/GroupController.php b/app/Controller/Api/V1/GroupController.php index 548eb4c..83f52b8 100644 --- a/app/Controller/Api/V1/GroupController.php +++ b/app/Controller/Api/V1/GroupController.php @@ -11,13 +11,14 @@ namespace App\Controller\Api\V1; use App\Cache\SocketRoom; +use App\Constants\TalkType; use Hyperf\Di\Annotation\Inject; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\HttpServer\Annotation\Middleware; use App\Middleware\JWTAuthMiddleware; use App\Model\UsersFriend; -use App\Model\UsersChatList; +use App\Model\TalkList; use App\Model\Group\Group; use App\Model\Group\GroupMember; use App\Model\Group\GroupNotice; @@ -28,7 +29,7 @@ use Psr\Http\Message\ResponseInterface; /** * Class GroupController - * @Controller(path="/api/v1/group") + * @Controller(prefix="/api/v1/group") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 @@ -76,10 +77,10 @@ class GroupController extends CController // ... 消息推送队列 push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => (int)$data['group_id'], // 接收者ID - 'source' => 2, // 接收者类型[1:好友;2:群组;] - 'record_id' => (int)$data['record_id'] + 'sender_id' => $user_id, + 'receiver_id' => (int)$data['group_id'], + 'talk_type' => TalkType::GROUP_CHAT, + 'record_id' => (int)$data['record_id'] ])); return $this->response->success([ @@ -141,10 +142,10 @@ class GroupController extends CController // 消息推送队列 push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => (int)$params['group_id'], // 接收者ID - 'source' => 2, // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['group_id'], + 'talk_type' => TalkType::GROUP_CHAT, + 'record_id' => $record_id ])); return $this->response->success([], '好友已成功加入群聊...'); @@ -174,10 +175,10 @@ class GroupController extends CController // 消息推送队列 push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => (int)$params['group_id'], // 接收者ID - 'source' => 2, // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['group_id'], + 'talk_type' => TalkType::GROUP_CHAT, + 'record_id' => $record_id ])); return $this->response->success([], '已成功退出群组...'); @@ -245,10 +246,10 @@ class GroupController extends CController // 消息推送队列 push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => (int)$params['group_id'], // 接收者ID - 'source' => 2, // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['group_id'], + 'talk_type' => TalkType::GROUP_CHAT, + 'record_id' => $record_id ])); return $this->response->success([], '已成功退出群组...'); @@ -288,13 +289,13 @@ class GroupController extends CController return $this->response->success([ 'group_id' => $groupInfo->id, 'group_name' => $groupInfo->group_name, - 'group_profile' => $groupInfo->profile, + 'profile' => $groupInfo->profile, 'avatar' => $groupInfo->avatar, 'created_at' => $groupInfo->created_at, 'is_manager' => $groupInfo->creator_id == $user_id, 'manager_nickname' => $groupInfo->nickname, 'visit_card' => GroupMember::visitCard($user_id, $group_id), - 'not_disturb' => UsersChatList::where('uid', $user_id)->where('group_id', $group_id)->where('type', 2)->value('not_disturb') ?? 0, + 'is_disturb' => (int)TalkList::where('user_id', $user_id)->where('receiver_id', $group_id)->where('talk_type', TalkType::GROUP_CHAT)->value('is_disturb'), 'notice' => $notice ? $notice->toArray() : [] ]); } diff --git a/app/Controller/Api/V1/TalkController.php b/app/Controller/Api/V1/TalkController.php index 519d420..ad6a5cb 100644 --- a/app/Controller/Api/V1/TalkController.php +++ b/app/Controller/Api/V1/TalkController.php @@ -12,26 +12,23 @@ namespace App\Controller\Api\V1; use App\Cache\LastMessage; use App\Cache\UnreadTalk; +use App\Constants\TalkMsgType; +use App\Constants\TalkType; use Hyperf\Di\Annotation\Inject; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use Hyperf\HttpServer\Annotation\Middleware; use App\Middleware\JWTAuthMiddleware; use Psr\Http\Message\ResponseInterface; -use App\Model\EmoticonDetail; -use App\Model\FileSplitUpload; use App\Model\User; -use App\Model\UsersChatList; +use App\Model\TalkList; use App\Model\UsersFriend; use App\Model\Group\Group; use App\Service\TalkService; -use App\Amqp\Producer\ChatMessageProducer; -use App\Constants\SocketConstants; -use League\Flysystem\Filesystem; /** * Class TalkController - * @Controller(path="/api/v1/talk") + * @Controller(prefix="/api/v1/talk") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 @@ -44,6 +41,25 @@ class TalkController extends CController */ public $talkService; + /** + * 判断是否是好友或者群成员关系 + * + * @param int $user_id 用户ID + * @param int $receiver_id 接收者ID + * @param int $talk_type 对话类型 + * @return bool + */ + private function isFriendOrGroupMember(int $user_id, int $receiver_id, int $talk_type) + { + if ($talk_type == TalkType::PRIVATE_CHAT) { + return UsersFriend::isFriend($user_id, $receiver_id, true); + } else if ($talk_type == TalkType::GROUP_CHAT) { + return Group::isMember($receiver_id, $user_id); + } + + return false; + } + /** * 获取用户对话列表 * @RequestMapping(path="list", methods="get") @@ -70,68 +86,55 @@ class TalkController extends CController */ public function create() { - $params = $this->request->inputs(['type', 'receive_id']); + $params = $this->request->inputs(['talk_type', 'receiver_id']); $this->validate($params, [ - 'type' => 'required|in:1,2', - 'receive_id' => 'present|integer|min:0' + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1' ]); $user_id = $this->uid(); - if ($params['type'] == 1) { - if (!UsersFriend::isFriend($user_id, $params['receive_id'])) { - return $this->response->fail('暂不属于好友关系,无法进行聊天!'); - } - } else { - if (!Group::isMember($params['receive_id'], $user_id)) { - return $this->response->fail('暂不属于群成员,无法进行群聊!'); - } + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法进行聊天!'); } - $result = UsersChatList::addItem($user_id, $params['receive_id'], $params['type']); + $result = TalkList::addItem($user_id, $params['receiver_id'], $params['talk_type']); if (!$result) { return $this->response->fail('创建失败!'); } $data = [ 'id' => $result['id'], - 'type' => $result['type'], - 'group_id' => $result['group_id'], - 'friend_id' => $result['friend_id'], + 'talk_type' => $result['talk_type'], + 'receiver_id' => $result['receiver_id'], 'is_top' => 0, - 'msg_text' => '', - 'not_disturb' => 0, - 'online' => 1, + 'is_disturb' => 0, + 'is_online' => 1, + 'avatar' => '', 'name' => '', 'remark_name' => '', - 'avatar' => '', 'unread_num' => 0, + 'msg_text' => '', 'updated_at' => date('Y-m-d H:i:s') ]; - if ($result['type'] == 1) { - $userInfo = User::where('id', $user_id)->first(['nickname', 'avatar']); - - $data['name'] = $userInfo->nickname; + if ($result['talk_type'] == TalkType::PRIVATE_CHAT) { + $userInfo = User::where('id', $user_id)->first(['nickname', 'avatar']); $data['avatar'] = $userInfo->avatar; - $data['unread_num'] = UnreadTalk::getInstance()->read($result['friend_id'], $user_id); - } else if ($result['type'] == 2) { - $groupInfo = Group::where('id', $result['group_id'])->first(['group_name', 'avatar']); - + $data['name'] = $userInfo->nickname; + $data['unread_num'] = UnreadTalk::getInstance()->read($data['receiver_id'], $user_id); + } else if ($result['talk_type'] == TalkType::GROUP_CHAT) { + $groupInfo = Group::where('id', $data['receiver_id'])->first(['group_name', 'avatar']); $data['name'] = $groupInfo->group_name; $data['avatar'] = $groupInfo->avatar; } - $records = LastMessage::getInstance()->read( - (int)$result['type'], $user_id, - $result['type'] == 1 ? (int)$result['friend_id'] : (int)$result['group_id'] - ); - + $records = LastMessage::getInstance()->read($result['talk_type'], $user_id, $result['receiver_id']); if ($records) { $data['msg_text'] = $records['text']; $data['updated_at'] = $records['created_at']; } - return $this->response->success(['talkItem' => $data]); + return $this->response->success($data); } /** @@ -147,7 +150,7 @@ class TalkController extends CController 'list_id' => 'required|integer|min:0' ]); - return UsersChatList::delItem($this->uid(), $params['list_id']) + return TalkList::delItem($this->uid(), $params['list_id']) ? $this->response->success([], '对话列表删除成功...') : $this->response->fail('对话列表删除失败!'); } @@ -166,7 +169,7 @@ class TalkController extends CController 'type' => 'required|in:1,2', ]); - return UsersChatList::topItem($this->uid(), $params['list_id'], $params['type'] == 1) + return TalkList::topItem($this->uid(), $params['list_id'], $params['type'] == 1) ? $this->response->success([], '对话列表置顶(或取消置顶)成功...') : $this->response->fail('对话列表置顶(或取消置顶)失败!'); } @@ -179,14 +182,14 @@ class TalkController extends CController */ public function setNotDisturb() { - $params = $this->request->inputs(['receive_id', 'type', 'not_disturb']); + $params = $this->request->inputs(['talk_type', 'receiver_id', 'is_disturb']); $this->validate($params, [ - 'receive_id' => 'required|integer|min:0', - 'type' => 'required|in:1,2', - 'not_disturb' => 'required|in:0,1', + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'is_disturb' => 'required|in:0,1', ]); - $isTrue = UsersChatList::notDisturbItem($this->uid(), $params['receive_id'], $params['type'], $params['not_disturb']); + $isTrue = TalkList::setNotDisturb($this->uid(), $params['receiver_id'], $params['talk_type'], $params['is_disturb']); return $isTrue ? $this->response->success([], '免打扰设置成功...') @@ -201,143 +204,20 @@ class TalkController extends CController */ public function updateUnreadNum() { - $params = $this->request->inputs(['receive', 'type']); + $params = $this->request->inputs(['talk_type', 'receiver_id']); $this->validate($params, [ - 'receive' => 'required|integer|min:0', - 'type' => 'required|integer|min:0' + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', ]); // 设置好友消息未读数 - if ($params['type'] == 1) { - UnreadTalk::getInstance()->reset((int)$params['receive'], $this->uid()); + if ($params['talk_type'] == TalkType::PRIVATE_CHAT) { + UnreadTalk::getInstance()->reset((int)$params['receiver_id'], $this->uid()); } return $this->response->success(); } - /** - * 撤回聊天对话消息 - * @RequestMapping(path="revoke-records", methods="post") - * - * @return ResponseInterface - */ - public function revokeChatRecords() - { - $params = $this->request->inputs(['record_id']); - $this->validate($params, [ - 'record_id' => 'required|integer|min:0' - ]); - - [$isTrue, $message,] = $this->talkService->revokeRecord($this->uid(), $params['record_id']); - if ($isTrue) { - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_REVOKE_TALK, [ - 'record_id' => $params['record_id'] - ])); - } - - return $isTrue - ? $this->response->success([], $message) - : $this->response->fail($message); - } - - /** - * 删除聊天记录 - * @RequestMapping(path="remove-records", methods="post") - * - * @return ResponseInterface - */ - public function removeChatRecords() - { - $params = $this->request->inputs(['source', 'record_id', 'receive_id']); - $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'record_id' => 'required|ids', - 'receive_id' => 'required|integer|min:0' - ]); - - $record_ids = explode(',', $params['record_id']); - - $isTrue = $this->talkService->removeRecords( - $this->uid(), - $params['source'], - $params['receive_id'], - $record_ids - ); - - return $isTrue - ? $this->response->success([], '删除成功...') - : $this->response->fail('删除失败!'); - } - - /** - * 转发聊天记录(待优化) - * @RequestMapping(path="forward-records", methods="post") - * - * @return ResponseInterface - */ - public function forwardChatRecords() - { - $params = $this->request->inputs(['source', 'records_ids', 'receive_id', 'forward_mode', 'receive_user_ids', 'receive_group_ids']); - $this->validate($params, [ - // 消息来源[1:好友消息;2:群聊消息;] - 'source' => 'required|in:1,2', - // 聊天记录ID,多个逗号拼接 - 'records_ids' => 'required', - // 接收者ID(好友ID或者群聊ID) - 'receive_id' => 'required|integer|min:0', - // 转发方方式[1:逐条转发;2:合并转发;] - 'forward_mode' => 'required|in:1,2', - // 转发的好友的ID - //'receive_user_ids' => 'array', - // 转发的群聊ID - //'receive_group_ids' => 'array', - ]); - - $receive_user_ids = $receive_group_ids = []; - if (isset($params['receive_user_ids']) && !empty($params['receive_user_ids'])) { - $receive_user_ids = array_map(function ($friend_id) { - return ['source' => 1, 'id' => $friend_id]; - }, $params['receive_user_ids']); - } - - if (isset($params['receive_group_ids']) && !empty($params['receive_group_ids'])) { - $receive_group_ids = array_map(function ($group_id) { - return ['source' => 2, 'id' => $group_id]; - }, $params['receive_group_ids']); - } - - $items = array_merge($receive_user_ids, $receive_group_ids); - - $user_id = $this->uid(); - if ($params['forward_mode'] == 1) {// 单条转发 - $ids = $this->talkService->forwardRecords($user_id, $params['receive_id'], $params['records_ids']); - } else {// 合并转发 - $ids = $this->talkService->mergeForwardRecords($user_id, $params['receive_id'], $params['source'], $params['records_ids'], $items); - } - - if (!$ids) { - return $this->response->fail('转发失败!'); - } - - if ($receive_user_ids) { - foreach ($receive_user_ids as $v) { - UnreadTalk::getInstance()->increment($user_id, (int)$v['id']); - } - } - - // 消息推送队列 - foreach ($ids as $value) { - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => intval($value['receive_id']), // 接收者ID - 'source' => intval($value['source']), // 接收者类型 1:好友;2:群组 - 'record_id' => $value['record_id'] - ])); - } - - return $this->response->success([], '转发成功...'); - } - /** * 获取对话面板中的聊天记录 * @RequestMapping(path="records", methods="get") @@ -346,29 +226,23 @@ class TalkController extends CController */ public function getChatRecords() { - $params = $this->request->inputs(['record_id', 'source', 'receive_id']); + $params = $this->request->inputs(['talk_type', 'receiver_id', 'record_id']); $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'record_id' => 'required|integer|min:0', - 'receive_id' => 'required|integer|min:1', + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'record_id' => 'required|integer|min:0', ]); $user_id = $this->uid(); - $limit = 30; - - // 判断是否属于群成员 - if ($params['source'] == 2 && Group::isMember($params['receive_id'], $user_id) == false) { - return $this->response->success([ - 'rows' => [], - 'record_id' => 0, - 'limit' => $limit - ], '非群聊成员不能查看群聊信息!'); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法查看聊天记录!'); } + $limit = 30; $result = $this->talkService->getChatRecords( $user_id, - $params['receive_id'], - $params['source'], + $params['receiver_id'], + $params['talk_type'], $params['record_id'], $limit ); @@ -388,12 +262,12 @@ class TalkController extends CController */ public function getForwardRecords() { - $params = $this->request->inputs(['records_id']); + $params = $this->request->inputs(['record_id']); $this->validate($params, [ - 'records_id' => 'required|integer|min:0' + 'record_id' => 'required|integer|min:1' ]); - $rows = $this->talkService->getForwardRecords($this->uid(), $params['records_id']); + $rows = $this->talkService->getForwardRecords($this->uid(), $params['record_id']); return $this->response->success(['rows' => $rows]); } @@ -406,36 +280,37 @@ class TalkController extends CController */ public function findChatRecords() { - $params = $this->request->inputs(['record_id', 'source', 'receive_id', 'msg_type']); + $params = $this->request->inputs(['talk_type', 'receiver_id', 'record_id', 'msg_type']); $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'record_id' => 'required|integer|min:0', - 'receive_id' => 'required|integer|min:1', - 'msg_type' => 'required|in:0,1,2,3,4,5,6', + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'record_id' => 'required|integer|min:0', + 'msg_type' => 'required|integer', ]); $user_id = $this->uid(); - $limit = 30; - - // 判断是否属于群成员 - if ($params['source'] == 2 && Group::isMember($params['receive_id'], $user_id) == false) { - return $this->response->success([ - 'rows' => [], - 'record_id' => 0, - 'limit' => $limit - ], '非群聊成员不能查看群聊信息!'); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法查看聊天记录!'); } - if (in_array($params['msg_type'], [1, 2, 4, 5])) { + $types = [ + TalkMsgType::TEXT_MESSAGE, + TalkMsgType::FILE_MESSAGE, + TalkMsgType::FORWARD_MESSAGE, + TalkMsgType::CODE_MESSAGE + ]; + + if (in_array($params['msg_type'], $types)) { $msg_type = [$params['msg_type']]; } else { - $msg_type = [1, 2, 4, 5]; + $msg_type = $types; } + $limit = 30; $result = $this->talkService->getChatRecords( $user_id, - $params['receive_id'], - $params['source'], + $params['receiver_id'], + $params['talk_type'], $params['record_id'], $limit, $msg_type @@ -450,261 +325,23 @@ class TalkController extends CController /** * 搜索聊天记录(待开发) - * @RequestMapping(path="search-chat-records", methods="get") + * @RequestMapping(path="records-search", methods="get") * * @return ResponseInterface */ public function searchChatRecords() { - + return $this->response->success(); } /** * 获取聊天记录上下文数据(待开发) - * @RequestMapping(path="get-records-context", methods="get") + * @RequestMapping(path="records-context", methods="get") * * @return ResponseInterface */ public function getRecordsContext() { - - } - - /** - * 上传聊天对话图片(待优化) - * @RequestMapping(path="send-image", methods="post") - * - * @param Filesystem $filesystem - * @return ResponseInterface - */ - public function sendImage(Filesystem $filesystem) - { - $params = $this->request->inputs(['source', 'receive_id']); - $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'receive_id' => 'required|integer|min:1' - ]); - - $file = $this->request->file('img'); - if (!$file || !$file->isValid()) { - return $this->response->fail(); - } - - $ext = $file->getExtension(); - if (!in_array($ext, ['jpg', 'png', 'jpeg', 'gif', 'webp'])) { - return $this->response->fail('图片格式错误,目前仅支持jpg、png、jpeg、gif和webp'); - } - - try { - $path = 'media/images/talks/' . date('Ymd') . '/' . create_image_name($ext, getimagesize($file->getRealPath())); - $filesystem->write($path, file_get_contents($file->getRealPath())); - } catch (\Exception $e) { - return $this->response->fail(); - } - - $user_id = $this->uid(); - - // 创建图片消息记录 - $record_id = $this->talkService->createImgMessage([ - 'source' => $params['source'], - 'msg_type' => 2, - 'user_id' => $user_id, - 'receive_id' => $params['receive_id'], - ], [ - 'user_id' => $user_id, - 'file_suffix' => $ext, - 'file_size' => $file->getSize(), - 'save_dir' => $path, - 'original_name' => $file->getClientFilename(), - ]); - - if (!$record_id) { - return $this->response->fail('图片上传失败!'); - } - - // 消息推送队列 - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => intval($params['receive_id']), // 接收者ID - 'source' => intval($params['source']), // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id - ])); - - LastMessage::getInstance()->save((int)$params['source'], $user_id, (int)$params['receive_id'], [ - 'text' => '[图片消息]', - 'created_at' => date('Y-m-d H:i:s') - ]); - - return $this->response->success(); - } - - /** - * 发送代码块消息 - * @RequestMapping(path="send-code-block", methods="post") - * - * @return ResponseInterface - */ - public function sendCodeBlock() - { - $params = $this->request->inputs(['source', 'receive_id', 'lang', 'code']); - $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'receive_id' => 'required|integer|min:1', - 'lang' => 'required', - 'code' => 'required' - ]); - - $user_id = $this->uid(); - $record_id = $this->talkService->createCodeMessage([ - 'source' => $params['source'], - 'msg_type' => 5, - 'user_id' => $user_id, - 'receive_id' => $params['receive_id'], - ], [ - 'user_id' => $user_id, - 'code_lang' => $params['lang'], - 'code' => $params['code'] - ]); - - if (!$record_id) { - return $this->response->fail('消息发送失败!'); - } - - // 消息推送队列 - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => intval($params['receive_id']), // 接收者ID - 'source' => intval($params['source']), // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id - ])); - - LastMessage::getInstance()->save((int)$params['source'], $user_id, (int)$params['receive_id'], [ - 'text' => '[代码消息]', - 'created_at' => date('Y-m-d H:i:s') - ]); - - return $this->response->success(); - } - - /** - * 发送文件消息 - * @RequestMapping(path="send-file", methods="post") - * - * @param Filesystem $filesystem - * @return ResponseInterface - */ - public function sendFile(Filesystem $filesystem) - { - $params = $this->request->inputs(['hash_name', 'receive_id', 'source']); - $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'receive_id' => 'required|integer|min:1', - 'hash_name' => 'required', - ]); - - $user_id = $this->uid(); - - $file = FileSplitUpload::where('user_id', $user_id)->where('hash_name', $params['hash_name'])->where('file_type', 1)->first(); - if (!$file || empty($file->save_dir)) { - return $this->response->fail('文件不存在...'); - } - - $save_dir = "files/talks/" . date('Ymd') . '/' . create_random_filename($file->file_ext); - - try { - $filesystem->copy($file->save_dir, $save_dir); - } catch (\Exception $e) { - return $this->response->fail('文件不存在...'); - } - - $record_id = $this->talkService->createFileMessage([ - 'source' => $params['source'], - 'msg_type' => 2, - 'user_id' => $user_id, - 'receive_id' => $params['receive_id'] - ], [ - 'user_id' => $user_id, - 'file_source' => 1, - 'original_name' => $file->original_name, - 'file_suffix' => $file->file_ext, - 'file_size' => $file->file_size, - 'save_dir' => $save_dir, - ]); - - if (!$record_id) { - return $this->response->fail('表情发送失败!'); - } - - // 消息推送队列 - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => intval($params['receive_id']), // 接收者ID - 'source' => intval($params['source']), // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id - ])); - - LastMessage::getInstance()->save((int)$params['source'], $user_id, (int)$params['receive_id'], [ - 'text' => '[文件消息]', - 'created_at' => date('Y-m-d H:i:s') - ]); - - return $this->response->success(); - } - - /** - * 发送表情包消息 - * @RequestMapping(path="send-emoticon", methods="post") - * - * @return ResponseInterface - */ - public function sendEmoticon() - { - $params = $this->request->inputs(['source', 'receive_id', 'emoticon_id']); - $this->validate($params, [ - 'source' => 'required|in:1,2',// 消息来源[1:好友消息;2:群聊消息;] - 'receive_id' => 'required|integer|min:1', - 'emoticon_id' => 'required|integer|min:1', - ]); - - $user_id = $this->uid(); - $emoticon = EmoticonDetail::where('id', $params['emoticon_id'])->where('user_id', $user_id)->first([ - 'url', 'file_suffix', 'file_size' - ]); - - if (!$emoticon) { - return $this->response->fail('表情不存在!'); - } - - $record_id = $this->talkService->createEmoticonMessage([ - 'source' => $params['source'], - 'msg_type' => 2, - 'user_id' => $user_id, - 'receive_id' => $params['receive_id'], - ], [ - 'user_id' => $user_id, - 'file_suffix' => $emoticon->file_suffix, - 'file_size' => $emoticon->file_size, - 'save_dir' => $emoticon->url, - 'original_name' => '表情', - ]); - - if (!$record_id) { - return $this->response->fail('表情发送失败!'); - } - - // 消息推送队列 - push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ - 'sender' => $user_id, // 发送者ID - 'receive' => intval($params['receive_id']), // 接收者ID - 'source' => intval($params['source']), // 接收者类型[1:好友;2:群组;] - 'record_id' => $record_id - ])); - - LastMessage::getInstance()->save((int)$params['source'], $user_id, (int)$params['receive_id'], [ - 'text' => '[表情包消息]', - 'created_at' => date('Y-m-d H:i:s') - ]); - return $this->response->success(); } } diff --git a/app/Controller/Api/V1/TalkMessageController.php b/app/Controller/Api/V1/TalkMessageController.php new file mode 100644 index 0000000..90c5bf8 --- /dev/null +++ b/app/Controller/Api/V1/TalkMessageController.php @@ -0,0 +1,434 @@ +request->inputs(['talk_type', 'receiver_id', 'lang', 'code']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'lang' => 'required', + 'code' => 'required' + ]); + + $user_id = $this->uid(); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!'); + } + + $record_id = $this->talkService->createCodeMessage([ + 'talk_type' => $params['talk_type'], + 'msg_type' => TalkMsgType::CODE_MESSAGE, + 'user_id' => $user_id, + 'receiver_id' => $params['receiver_id'], + ], [ + 'user_id' => $user_id, + 'code_lang' => $params['lang'], + 'code' => $params['code'] + ]); + + if (!$record_id) { + return $this->response->fail('消息发送失败!'); + } + + // 消息推送队列 + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['receiver_id'], + 'talk_type' => (int)$params['talk_type'], + 'record_id' => $record_id + ])); + + LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ + 'text' => '[代码消息]', + 'created_at' => date('Y-m-d H:i:s') + ]); + + return $this->response->success(); + } + + /** + * 发送图片消息 + * @RequestMapping(path="image", methods="post") + */ + public function image(Filesystem $filesystem) + { + $params = $this->request->inputs(['talk_type', 'receiver_id']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1' + ]); + + $user_id = $this->uid(); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!'); + } + + $file = $this->request->file('image'); + if (!$file || !$file->isValid()) { + return $this->response->fail(); + } + + $ext = $file->getExtension(); + if (!in_array($ext, ['jpg', 'png', 'jpeg', 'gif', 'webp'])) { + return $this->response->fail('图片格式错误,目前仅支持jpg、png、jpeg、gif和webp'); + } + + try { + $path = 'media/images/talks/' . date('Ymd') . '/' . create_image_name($ext, getimagesize($file->getRealPath())); + $filesystem->write($path, file_get_contents($file->getRealPath())); + } catch (\Exception $e) { + return $this->response->fail(); + } + + // 创建图片消息记录 + $record_id = $this->talkService->createImgMessage([ + 'talk_type' => $params['talk_type'], + 'msg_type' => TalkMsgType::FILE_MESSAGE, + 'user_id' => $user_id, + 'receiver_id' => $params['receiver_id'], + ], [ + 'user_id' => $user_id, + 'file_suffix' => $ext, + 'file_size' => $file->getSize(), + 'save_dir' => $path, + 'original_name' => $file->getClientFilename(), + ]); + + if (!$record_id) { + return $this->response->fail('图片上传失败!'); + } + + // 消息推送队列 + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['receiver_id'], + 'talk_type' => (int)$params['talk_type'], + 'record_id' => $record_id, + ])); + + LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ + 'text' => '[图片消息]', + 'created_at' => date('Y-m-d H:i:s') + ]); + + return $this->response->success(); + } + + /** + * 发送文件消息 + * @RequestMapping(path="file", methods="post") + */ + public function file(Filesystem $filesystem) + { + $params = $this->request->inputs(['talk_type', 'receiver_id', 'hash_name']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'hash_name' => 'required', + ]); + + $user_id = $this->uid(); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!'); + } + + $file = FileSplitUpload::where('user_id', $user_id)->where('hash_name', $params['hash_name'])->where('file_type', 1)->first(); + if (!$file || empty($file->save_dir)) { + return $this->response->fail('文件不存在...'); + } + + try { + $save_dir = "files/talks/" . date('Ymd') . '/' . create_random_filename($file->file_ext); + $filesystem->copy($file->save_dir, $save_dir); + } catch (\Exception $e) { + return $this->response->fail('文件不存在...'); + } + + $record_id = $this->talkService->createFileMessage([ + 'talk_type' => $params['talk_type'], + 'msg_type' => TalkMsgType::FILE_MESSAGE, + 'user_id' => $user_id, + 'receiver_id' => $params['receiver_id'] + ], [ + 'user_id' => $user_id, + 'file_source' => 1, + 'original_name' => $file->original_name, + 'file_suffix' => $file->file_ext, + 'file_size' => $file->file_size, + 'save_dir' => $save_dir, + ]); + + if (!$record_id) { + return $this->response->fail('表情发送失败!'); + } + + // 消息推送队列 + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['receiver_id'], + 'talk_type' => (int)$params['talk_type'], + 'record_id' => $record_id + ])); + + LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ + 'text' => '[文件消息]', + 'created_at' => date('Y-m-d H:i:s') + ]); + + return $this->response->success(); + } + + /** + * 发送投票消息 + * @RequestMapping(path="vote", methods="post") + */ + public function vote() + { + + } + + /** + * 发送表情包消息 + * @RequestMapping(path="emoticon", methods="post") + */ + public function emoticon() + { + $params = $this->request->inputs(['talk_type', 'receiver_id', 'emoticon_id']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'emoticon_id' => 'required|integer|min:1', + ]); + + $user_id = $this->uid(); + if (!$this->isFriendOrGroupMember($user_id, $params['receiver_id'], $params['talk_type'])) { + return $this->response->fail('暂不属于好友关系或群聊成员,无法发送聊天消息!'); + } + + $emoticon = EmoticonItem::where('id', $params['emoticon_id'])->where('user_id', $user_id)->first([ + 'url', 'file_suffix', 'file_size' + ]); + + if (!$emoticon) { + return $this->response->fail('表情不存在!'); + } + + $record_id = $this->talkService->createEmoticonMessage([ + 'talk_type' => $params['talk_type'], + 'msg_type' => TalkMsgType::FILE_MESSAGE, + 'user_id' => $user_id, + 'receiver_id' => $params['receiver_id'], + ], [ + 'user_id' => $user_id, + 'file_suffix' => $emoticon->file_suffix, + 'file_size' => $emoticon->file_size, + 'save_dir' => $emoticon->url, + 'original_name' => '图片表情', + ]); + + if (!$record_id) { + return $this->response->fail('表情发送失败!'); + } + + // 消息推送队列 + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $user_id, + 'receiver_id' => (int)$params['receiver_id'], + 'talk_type' => (int)$params['talk_type'], + 'record_id' => $record_id + ])); + + LastMessage::getInstance()->save((int)$params['talk_type'], $user_id, (int)$params['receiver_id'], [ + 'text' => '[表情包消息]', + 'created_at' => date('Y-m-d H:i:s') + ]); + + return $this->response->success(); + } + + /** + * 转发消息记录 + * @RequestMapping(path="forward", methods="post") + */ + public function forward() + { + $params = $this->request->inputs(['talk_type', 'receiver_id', 'records_ids', 'forward_mode', 'receive_user_ids', 'receive_group_ids']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'records_ids' => 'required', // 聊天记录ID,多个逗号拼接 + 'forward_mode' => 'required|in:1,2',// 转发方方式[1:逐条转发;2:合并转发;] + ]); + + $receive_user_ids = $receive_group_ids = []; + if (isset($params['receive_user_ids']) && !empty($params['receive_user_ids'])) { + $receive_user_ids = array_map(function ($friend_id) { + return ['talk_type' => TalkType::PRIVATE_CHAT, 'id' => (int)$friend_id]; + }, $params['receive_user_ids']); + } + + if (isset($params['receive_group_ids']) && !empty($params['receive_group_ids'])) { + $receive_group_ids = array_map(function ($group_id) { + return ['talk_type' => TalkType::GROUP_CHAT, 'id' => (int)$group_id]; + }, $params['receive_group_ids']); + } + + $items = array_merge($receive_user_ids, $receive_group_ids); + + $user_id = $this->uid(); + if ($params['forward_mode'] == 1) {// 单条转发 + $ids = $this->talkService->forwardRecords($user_id, $params['receiver_id'], $params['records_ids']); + } else {// 合并转发 + $ids = $this->talkService->mergeForwardRecords($user_id, $params['receiver_id'], $params['talk_type'], $params['records_ids'], $items); + } + + if (!$ids) { + return $this->response->fail('转发失败!'); + } + + if ($receive_user_ids) { + foreach ($receive_user_ids as $v) { + UnreadTalk::getInstance()->increment($user_id, $v['id']); + } + } + + // 消息推送队列 + foreach ($ids as $value) { + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $user_id, + 'receiver_id' => $value['receiver_id'], + 'talk_type' => $value['talk_type'], + 'record_id' => $value['record_id'], + ])); + } + + return $this->response->success([], '转发成功...'); + } + + /** + * 收藏聊天图片 + * @RequestMapping(path="collect", methods="post") + */ + public function collect(EmoticonService $service) + { + $params = $this->request->inputs(['record_id']); + $this->validate($params, [ + 'record_id' => 'required|integer' + ]); + + [$isTrue, $data] = $service->collect($this->uid(), $params['record_id']); + + if (!$isTrue) return $this->response->fail('添加表情失败!'); + + return $this->response->success([ + 'emoticon' => $data + ]); + } + + /** + * 撤销聊天记录 + * @RequestMapping(path="revoke", methods="post") + */ + public function revoke() + { + $params = $this->request->inputs(['record_id']); + $this->validate($params, [ + 'record_id' => 'required|integer|min:0' + ]); + + [$isTrue, $message,] = $this->talkService->revokeRecord($this->uid(), $params['record_id']); + if ($isTrue) { + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_REVOKE_TALK, [ + 'record_id' => $params['record_id'] + ])); + } + + return $isTrue + ? $this->response->success([], $message) + : $this->response->fail($message); + } + + /** + * 删除聊天记录 + * @RequestMapping(path="delete", methods="post") + */ + public function delete() + { + $params = $this->request->inputs(['talk_type', 'receiver_id', 'record_id']); + $this->validate($params, [ + 'talk_type' => 'required|in:1,2', + 'receiver_id' => 'required|integer|min:1', + 'record_id' => 'required|ids', + ]); + + $isTrue = $this->talkService->removeRecords( + $this->uid(), + $params['talk_type'], + $params['receiver_id'], + parse_ids($params['record_id']) + ); + + return $isTrue + ? $this->response->success([], '删除成功...') + : $this->response->fail('删除失败!'); + } +} diff --git a/app/Controller/Api/V1/UploadController.php b/app/Controller/Api/V1/UploadController.php index 73d478d..a067bb5 100644 --- a/app/Controller/Api/V1/UploadController.php +++ b/app/Controller/Api/V1/UploadController.php @@ -22,7 +22,7 @@ use Psr\Http\Message\ResponseInterface; /** * 上传文件控制器 - * @Controller(path="/api/v1/upload") + * @Controller(prefix="/api/v1/upload") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 diff --git a/app/Controller/Api/V1/UsersController.php b/app/Controller/Api/V1/UsersController.php index 86916b8..eb87d8e 100644 --- a/app/Controller/Api/V1/UsersController.php +++ b/app/Controller/Api/V1/UsersController.php @@ -24,7 +24,7 @@ use Psr\Http\Message\ResponseInterface; /** * Class UsersController - * @Controller(path="/api/v1/users") + * @Controller(prefix="/api/v1/users") * @Middleware(JWTAuthMiddleware::class) * * @package App\Controller\Api\V1 diff --git a/app/Controller/WebSocketController.php b/app/Controller/WebSocketController.php index 6ea7671..9ed4c5f 100644 --- a/app/Controller/WebSocketController.php +++ b/app/Controller/WebSocketController.php @@ -88,7 +88,6 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos push_amqp(new ChatMessageProducer(SocketConstants::EVENT_ONLINE_STATUS, [ 'user_id' => $user_id, 'status' => 1, - 'notify' => '好友上线通知...' ])); } } @@ -137,7 +136,6 @@ class WebSocketController implements OnMessageInterface, OnOpenInterface, OnClos push_amqp(new ChatMessageProducer(SocketConstants::EVENT_ONLINE_STATUS, [ 'user_id' => $user_id, 'status' => 0, - 'notify' => '好友离线通知通知...' ])); } } diff --git a/app/Exception/Handler/AppExceptionHandler.php b/app/Exception/Handler/AppExceptionHandler.php index 6c808d1..c6b8b77 100644 --- a/app/Exception/Handler/AppExceptionHandler.php +++ b/app/Exception/Handler/AppExceptionHandler.php @@ -30,13 +30,15 @@ class AppExceptionHandler extends ExceptionHandler $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); $this->logger->error($throwable->getTraceAsString()); + $isDev = config('app_env') == 'dev'; + $data = json_encode([ - 'code' => ResponseCode::SERVER_ERROR, - 'message' => 'Internal Server Error.', - 'errors' => config('app_env') == 'dev' ? $throwable->getTrace() : [], + 'code' => ResponseCode::SERVER_ERROR, + 'error' => $isDev ? $throwable->getMessage() : 'Internal Server Error.', + 'traces' => $isDev ? $throwable->getTrace() : [], ], JSON_UNESCAPED_UNICODE); - $this->sendAdminEmail($throwable); + !$isDev && $this->sendAdminEmail($throwable); return $response->withHeader('Server', 'Lumen IM')->withStatus(500)->withBody(new SwooleStream($data)); } @@ -57,10 +59,6 @@ class AppExceptionHandler extends ExceptionHandler */ public function sendAdminEmail(Throwable $throwable) { - if (config('app_env') != 'dev') { - return; - } - $error = implode(':', [ 'error', md5($throwable->getFile() . $throwable->getCode() . $throwable->getLine()), diff --git a/app/Model/Chat/ChatRecord.php b/app/Model/Chat/ChatRecord.php deleted file mode 100644 index d802408..0000000 --- a/app/Model/Chat/ChatRecord.php +++ /dev/null @@ -1,44 +0,0 @@ -0: 用户ID] - * @property int $receive_id 接收者ID[用户ID 或 群ID] - * @property string $content 文本消息 - * @property int $is_revoke 是否撤回消息[0:否;1:是] - * @property string $created_at 创建时间 - * @package App\Model\Chat - */ -class ChatRecord extends BaseModel -{ - protected $table = 'chat_records'; - - protected $fillable = [ - 'source', - 'msg_type', - 'user_id', - 'receive_id', - 'content', - 'is_revoke', - 'created_at', - ]; - - protected $casts = [ - 'id' => 'integer', - 'source' => 'integer', - 'msg_type' => 'integer', - 'user_id' => 'integer', - 'receive_id' => 'integer', - 'is_revoke' => 'integer' - ]; -} diff --git a/app/Model/Chat/TalkRecords.php b/app/Model/Chat/TalkRecords.php new file mode 100644 index 0000000..96ec8f8 --- /dev/null +++ b/app/Model/Chat/TalkRecords.php @@ -0,0 +1,57 @@ + 'integer', + 'talk_type' => 'integer', + 'msg_type' => 'integer', + 'user_id' => 'integer', + 'receiver_id' => 'integer', + 'is_revoke' => 'integer', + 'is_mark' => 'integer', + 'is_read' => 'integer', + 'quote_id' => 'integer', + ]; +} diff --git a/app/Model/Chat/ChatRecordsCode.php b/app/Model/Chat/TalkRecordsCode.php similarity index 89% rename from app/Model/Chat/ChatRecordsCode.php rename to app/Model/Chat/TalkRecordsCode.php index e9b0d25..de16ce4 100644 --- a/app/Model/Chat/ChatRecordsCode.php +++ b/app/Model/Chat/TalkRecordsCode.php @@ -17,9 +17,9 @@ use App\Model\BaseModel; * @property string $created_at 创建时间 * @package App\Model\Chat */ -class ChatRecordsCode extends BaseModel +class TalkRecordsCode extends BaseModel { - protected $table = 'chat_records_code'; + protected $table = 'talk_records_code'; protected $fillable = [ 'record_id', diff --git a/app/Model/Chat/ChatRecordsDelete.php b/app/Model/Chat/TalkRecordsDelete.php similarity index 86% rename from app/Model/Chat/ChatRecordsDelete.php rename to app/Model/Chat/TalkRecordsDelete.php index 09e701d..235c5c2 100644 --- a/app/Model/Chat/ChatRecordsDelete.php +++ b/app/Model/Chat/TalkRecordsDelete.php @@ -15,9 +15,9 @@ use App\Model\BaseModel; * @property string $created_at 删除时间 * @package App\Model\Chat */ -class ChatRecordsDelete extends BaseModel +class TalkRecordsDelete extends BaseModel { - protected $table = 'chat_records_delete'; + protected $table = 'talk_records_delete'; protected $fillable = []; diff --git a/app/Model/Chat/ChatRecordsFile.php b/app/Model/Chat/TalkRecordsFile.php similarity index 94% rename from app/Model/Chat/ChatRecordsFile.php rename to app/Model/Chat/TalkRecordsFile.php index 58e3325..6b4743c 100644 --- a/app/Model/Chat/ChatRecordsFile.php +++ b/app/Model/Chat/TalkRecordsFile.php @@ -23,9 +23,9 @@ use App\Model\BaseModel; * @property string $created_at 上传时间 * @package App\Model\Chat */ -class ChatRecordsFile extends BaseModel +class TalkRecordsFile extends BaseModel { - protected $table = 'chat_records_file'; + protected $table = 'talk_records_file'; protected $fillable = [ 'record_id', diff --git a/app/Model/Chat/ChatRecordsForward.php b/app/Model/Chat/TalkRecordsForward.php similarity index 89% rename from app/Model/Chat/ChatRecordsForward.php rename to app/Model/Chat/TalkRecordsForward.php index ce5a149..18071c8 100644 --- a/app/Model/Chat/ChatRecordsForward.php +++ b/app/Model/Chat/TalkRecordsForward.php @@ -17,9 +17,9 @@ use App\Model\BaseModel; * @property int $created_at 转发时间 * @package App\Model\Chat */ -class ChatRecordsForward extends BaseModel +class TalkRecordsForward extends BaseModel { - protected $table = 'chat_records_forward'; + protected $table = 'talk_records_forward'; protected $fillable = [ 'record_id', diff --git a/app/Model/Chat/ChatRecordsInvite.php b/app/Model/Chat/TalkRecordsInvite.php similarity index 90% rename from app/Model/Chat/ChatRecordsInvite.php rename to app/Model/Chat/TalkRecordsInvite.php index 77119bf..63eabc2 100644 --- a/app/Model/Chat/ChatRecordsInvite.php +++ b/app/Model/Chat/TalkRecordsInvite.php @@ -16,9 +16,9 @@ use App\Model\BaseModel; * @property string $user_ids 用户ID(多个用 , 分割) * @package App\Model\Chat */ -class ChatRecordsInvite extends BaseModel +class TalkRecordsInvite extends BaseModel { - protected $table = 'chat_records_invite'; + protected $table = 'talk_records_invite'; protected $fillable = [ 'record_id', diff --git a/app/Model/Emoticon.php b/app/Model/Emoticon.php index 2492411..9bdacd2 100644 --- a/app/Model/Emoticon.php +++ b/app/Model/Emoticon.php @@ -7,10 +7,12 @@ namespace App\Model; /** * 表情包分组数据表模型 * - * @property int $id 分组ID - * @property string $name 分组名称 - * @property string $url 默认表情 - * @property string $created_at 创建时间 + * @property integer $id 分组ID + * @property string $name 分组名称 + * @property string $icon 分组图标 + * @property integer $status 分组状态 + * @property string $created_at 创建时间 + * @property string $updated_at 更新时间 * @package App\Model */ class Emoticon extends BaseModel @@ -21,6 +23,8 @@ class Emoticon extends BaseModel protected $casts = [ 'id' => 'integer', - 'created_at' => 'datetime' + 'status' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', ]; } diff --git a/app/Model/EmoticonDetail.php b/app/Model/EmoticonItem.php similarity index 70% rename from app/Model/EmoticonDetail.php rename to app/Model/EmoticonItem.php index ca16666..c0035d8 100644 --- a/app/Model/EmoticonDetail.php +++ b/app/Model/EmoticonItem.php @@ -7,19 +7,20 @@ namespace App\Model; /** * 表情包数据表模型 * - * @property int $id 表情包ID - * @property int $emoticon_id 分组ID + * @property int $id 表情包详情ID + * @property int $emoticon_id 表情分组ID * @property int $user_id 用户ID * @property string $describe 表情描述 * @property string $url 表情链接 * @property string $file_suffix 文件前缀 * @property int $file_size 表情包文件大小 * @property string $created_at 创建时间 + * @property string $updated_at 更新时间 * @package App\Model */ -class EmoticonDetail extends BaseModel +class EmoticonItem extends BaseModel { - protected $table = 'emoticon_details'; + protected $table = 'emoticon_item'; protected $fillable = [ 'emoticon_id', @@ -29,6 +30,7 @@ class EmoticonDetail extends BaseModel 'file_suffix', 'file_size', 'created_at', + 'updated_at', ]; protected $casts = [ @@ -36,6 +38,7 @@ class EmoticonDetail extends BaseModel 'emoticon_id' => 'integer', 'user_id' => 'integer', 'file_size' => 'integer', - 'created_at' => 'integer' + 'created_at' => 'datetime', + 'updated_at' => 'datetime', ]; } diff --git a/app/Model/Robot.php b/app/Model/Robot.php new file mode 100644 index 0000000..7c77cc4 --- /dev/null +++ b/app/Model/Robot.php @@ -0,0 +1,45 @@ + 'integer', + 'is_talk' => 'integer', + 'status' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; +} diff --git a/app/Model/TalkList.php b/app/Model/TalkList.php new file mode 100644 index 0000000..b1107d0 --- /dev/null +++ b/app/Model/TalkList.php @@ -0,0 +1,164 @@ + 'integer', + 'talk_type' => 'integer', + 'user_id' => 'integer', + 'receiver_id' => 'integer', + 'is_delete' => 'integer', + 'is_top' => 'integer', + 'is_robot' => 'integer', + 'is_disturb' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime' + ]; + + /** + * 创建聊天列表记录 + * + * @param int $user_id 用户ID + * @param int $receiver_id 接收者ID + * @param int $talk_type 创建类型[1:私聊;2:群聊;] + * @return array + */ + public static function addItem(int $user_id, int $receiver_id, int $talk_type) + { + $result = self::query()->where([ + ['user_id', '=', $user_id], + ['talk_type', '=', $talk_type], + ['receiver_id', '=', $receiver_id], + ])->first(); + + if (!$result) { + $result = self::query()->create([ + 'talk_type' => $talk_type, + 'user_id' => $user_id, + 'receiver_id' => $receiver_id, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ]); + } + + $result->is_top = 0; + $result->is_delete = 0; + $result->is_disturb = 0; + $result->updated_at = date('Y-m-d H:i:s'); + $result->save(); + + return [ + 'id' => $result->id, + 'talk_type' => $result->talk_type, + 'receiver_id' => $result->receiver_id, + ]; + } + + /** + * 聊天对话列表置顶操作 + * + * @param int $user_id 用户ID + * @param int $list_id 对话列表ID + * @param bool $is_top 是否置顶(true:是 false:否) + * @return bool + */ + public static function topItem(int $user_id, int $list_id, $is_top = true) + { + return (bool)self::query()->where([ + ['id', '=', $list_id], + ['user_id', '=', $user_id], + ])->update([ + 'is_top' => $is_top ? 1 : 0, + 'updated_at' => date('Y-m-d H:i:s') + ]); + } + + /** + * 删除聊天列表 + * + * @param int $user_id 用户ID + * @param int $id 聊天列表ID、好友ID或群聊ID + * @param int $type ID类型[1:聊天列表ID;2:好友ID;3:群聊ID;] + * @return bool + */ + public static function delItem(int $user_id, int $id, $type = 1) + { + $model = self::query(); + if ($type == 1) { + $model->where('id', $id)->where('user_id', $user_id); + } else { + $model->where([ + ['talk_type', '=', $type == 2 ? 1 : 2], + ['user_id', '=', $user_id], + ['receiver_id', '=', $id], + ]); + } + + return (bool)$model->update([ + 'is_delete' => 0, + 'updated_at' => date('Y-m-d H:i:s') + ]); + } + + /** + * 设置消息免打扰 + * + * @param int $user_id 用户ID + * @param int $receiver_id 接收者ID + * @param int $talk_type 接收者类型[1:好友;2:群组;] + * @param int $is_disturb 是否免打扰 + * @return boolean + */ + public static function setNotDisturb(int $user_id, int $receiver_id, int $talk_type, int $is_disturb) + { + $result = self::query() + ->where([ + ['user_id', '=', $user_id], + ['talk_type', '=', $talk_type], + ['receiver_id', '=', $receiver_id], + ]) + ->first(['id', 'is_disturb']); + + if (!$result || $is_disturb == $result->is_disturb) { + return false; + } + + return (bool)self::query()->where('id', $result->id)->update([ + 'is_disturb' => $is_disturb, + 'updated_at' => date('Y-m-d H:i:s') + ]); + } +} diff --git a/app/Model/User.php b/app/Model/User.php index 8984eb2..75b6c13 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -18,7 +18,9 @@ use Qbhy\HyperfAuth\Authenticatable; * @property string $avatar 头像 * @property integer $gender 性别 * @property string $motto 座右铭 - * @property integer $created_at 注册时间 + * @property string $is_robot 是否机器人 + * @property string $created_at 注册时间 + * @property string $updated_at 更新时间 * @package App\Model */ class User extends BaseModel implements Authenticatable @@ -35,7 +37,9 @@ class User extends BaseModel implements Authenticatable 'password', 'motto', 'email', - 'created_at' + 'is_robot', + 'created_at', + 'updated_at', ]; protected $casts = []; diff --git a/app/Model/UsersChatList.php b/app/Model/UsersChatList.php deleted file mode 100644 index 2224dd0..0000000 --- a/app/Model/UsersChatList.php +++ /dev/null @@ -1,149 +0,0 @@ - 'integer', - 'type' => 'integer', - 'uid' => 'integer', - 'friend_id' => 'integer', - 'group_id' => 'integer', - 'status' => 'integer', - 'is_top' => 'integer', - 'not_disturb' => 'integer', - 'created_at' => 'datetime', - 'updated_at' => 'datetime' - ]; - - /** - * 创建聊天列表记录 - * - * @param int $user_id 用户ID - * @param int $receive_id 接收者ID - * @param int $type 创建类型 1:私聊 2:群聊 - * @return array - */ - public static function addItem(int $user_id, int $receive_id, int $type) - { - $result = self::query()->where('uid', $user_id)->where('type', $type)->where($type == 1 ? 'friend_id' : 'group_id', $receive_id)->first(); - if ($result) { - $result->status = 1; - $result->updated_at = date('Y-m-d H:i:s'); - $result->save(); - - return [ - 'id' => $result->id, - 'type' => $result->type, - 'friend_id' => $result->friend_id, - 'group_id' => $result->group_id, - ]; - } - - if (!$result = self::query()->create([ - 'type' => $type, - 'uid' => $user_id, - 'status' => 1, - 'friend_id' => $type == 1 ? $receive_id : 0, - 'group_id' => $type == 2 ? $receive_id : 0, - 'created_at' => date('Y-m-d H:i:s'), - 'updated_at' => date('Y-m-d H:i:s'), - ])) { - return []; - } - - return [ - 'id' => $result->id, - 'type' => $result->type, - 'friend_id' => $result->friend_id, - 'group_id' => $result->group_id, - ]; - } - - /** - * 聊天对话列表置顶操作 - * - * @param int $user_id 用户ID - * @param int $list_id 对话列表ID - * @param bool $is_top 是否置顶(true:是 false:否) - * @return bool - */ - public static function topItem(int $user_id, int $list_id, $is_top = true) - { - return (bool)self::query()->where('id', $list_id)->where('uid', $user_id)->update([ - 'is_top' => $is_top ? 1 : 0, - 'updated_at' => date('Y-m-d H:i:s') - ]); - } - - /** - * 删除聊天列表 - * - * @param int $user_id 用户ID - * @param int $id 聊天列表ID、好友ID或群聊ID - * @param int $type ID类型 (1:聊天列表ID 2:好友ID 3:群聊ID) - * @return bool - */ - public static function delItem(int $user_id, int $id, $type = 1) - { - $data = ['status' => 0, 'updated_at' => date('Y-m-d H:i:s')]; - if ($type == 1) { - return (bool)self::query()->where('id', $id)->where('uid', $user_id)->update($data); - } else if ($type == 2) { - return (bool)self::query()->where('uid', $user_id)->where('friend_id', $id)->update($data); - } else { - return (bool)self::query()->where('uid', $user_id)->where('group_id', $id)->update($data); - } - } - - /** - * 设置消息免打扰 - * - * @param int $user_id 用户ID - * @param int $receive_id 接收者ID - * @param int $type 接收者类型(1:好友 2:群组) - * @param int $not_disturb 是否免打扰 - * @return boolean - */ - public static function notDisturbItem(int $user_id, int $receive_id, int $type, int $not_disturb) - { - $result = self::query()->where('uid', $user_id)->where($type == 1 ? 'friend_id' : 'group_id', $receive_id)->where('status', 1)->first(['id', 'not_disturb']); - if (!$result || $not_disturb == $result->not_disturb) { - return false; - } - - return (bool)self::query()->where('id', $result->id)->update(['not_disturb' => $not_disturb]); - } -} diff --git a/app/Model/UsersFriend.php b/app/Model/UsersFriend.php index 6eb4cef..96a8742 100644 --- a/app/Model/UsersFriend.php +++ b/app/Model/UsersFriend.php @@ -57,9 +57,9 @@ class UsersFriend extends BaseModel SELECT users.id,users.nickname,users.avatar,users.motto,users.gender,tmp_table.friend_remark from {$prefix}users users INNER join ( - SELECT id as rid,user2 as uid,user1_remark as friend_remark from {$prefix}users_friends where user1 = {$uid} and `status` = 1 + SELECT id as rid,user2 as uid,user1_remark as friend_remark from {$prefix}users_friends where user1 = {$uid} and `status` = 0 UNION all - SELECT id as rid,user1 as uid,user2_remark as friend_remark from {$prefix}users_friends where user2 = {$uid} and `status` = 1 + SELECT id as rid,user1 as uid,user2_remark as friend_remark from {$prefix}users_friends where user2 = {$uid} and `status` = 0 ) tmp_table on tmp_table.uid = users.id SQL; @@ -92,7 +92,7 @@ SQL; return true; } - $isTrue = self::query()->where('user1', $user_id1)->where('user2', $user_id2)->where('status', 1)->exists(); + $isTrue = self::query()->where('user1', $user_id1)->where('user2', $user_id2)->where('status', 0)->exists(); if ($isTrue) { redis()->setex($cacheKey, 60 * 5, 1); } @@ -109,7 +109,7 @@ SQL; public static function getFriendIds(int $user_id) { $prefix = config('databases.default.prefix'); - $sql = "SELECT user2 as uid from {$prefix}users_friends where user1 = {$user_id} and `status` = 1 UNION all SELECT user1 as uid from {$prefix}users_friends where user2 = {$user_id} and `status` = 1"; + $sql = "SELECT user2 as uid from {$prefix}users_friends where user1 = {$user_id} and `status` = 0 UNION all SELECT user1 as uid from {$prefix}users_friends where user2 = {$user_id} and `status` = 0"; return array_map(function ($item) { return $item->uid; }, Db::select($sql)); diff --git a/app/Service/ArticleService.php b/app/Service/ArticleService.php index bbe3373..1259d72 100644 --- a/app/Service/ArticleService.php +++ b/app/Service/ArticleService.php @@ -210,23 +210,25 @@ class ArticleService extends BaseService /** * 删除笔记分类 * - * @param int $uid 用户ID + * @param int $user_id 用户ID * @param int $class_id 分类ID * @return bool * @throws Exception */ - public function delArticleClass(int $uid, int $class_id) + public function delArticleClass(int $user_id, int $class_id) { - if (!ArticleClass::where('id', $class_id)->where('user_id', $uid)->exists()) { - return false; - } + $result = ArticleClass::where('id', $class_id)->where('user_id', $user_id)->first(['id', 'sort']); + if (!$result) return false; - $count = Article::where('user_id', $uid)->where('class_id', $class_id)->count(); - if ($count > 0) { - return false; - } + $count = Article::where('user_id', $user_id)->where('class_id', $class_id)->count(); + if ($count > 0) return false; - return (bool)ArticleClass::where('id', $class_id)->where('user_id', $uid)->where('is_default', 0)->delete(); + Db::transaction(function () use ($user_id, $class_id, $result) { + ArticleClass::where('id', $class_id)->where('user_id', $user_id)->where('is_default', 0)->delete(); + ArticleClass::where('user_id', $user_id)->where('sort', '>', $result->sort)->decrement('sort'); + }); + + return true; } /** diff --git a/app/Service/ContactsService.php b/app/Service/ContactsService.php index c75612a..39600cb 100644 --- a/app/Service/ContactsService.php +++ b/app/Service/ContactsService.php @@ -40,19 +40,12 @@ class ContactsService extends BaseService SELECT users.id,users.nickname,users.avatar,users.motto,users.gender,tmp_table.friend_remark from {$prefix}users users INNER join ( - SELECT id as rid,user2 as uid,user1_remark as friend_remark from {$prefix}users_friends where user1 = {$user_id} and `status` = 1 + SELECT id as rid,user2 as uid,user1_remark as friend_remark from {$prefix}users_friends where user1 = {$user_id} and `status` in (0,2) UNION all - SELECT id as rid,user1 as uid,user2_remark as friend_remark from {$prefix}users_friends where user2 = {$user_id} and `status` = 1 + SELECT id as rid,user1 as uid,user2_remark as friend_remark from {$prefix}users_friends where user2 = {$user_id} and `status` in (0,1) ) tmp_table on tmp_table.uid = users.id SQL; - - $rows = Db::select($sql); - - array_walk($rows, function (&$item) { - $item = (array)$item; - }); - - return $rows; + return Db::select($sql); } /** diff --git a/app/Service/EmoticonService.php b/app/Service/EmoticonService.php index 66a6588..be9354b 100644 --- a/app/Service/EmoticonService.php +++ b/app/Service/EmoticonService.php @@ -2,9 +2,11 @@ namespace App\Service; -use App\Model\Chat\ChatRecord; -use App\Model\Chat\ChatRecordsFile; -use App\Model\EmoticonDetail; +use App\Constants\TalkMsgType; +use App\Constants\TalkType; +use App\Model\Chat\TalkRecords; +use App\Model\Chat\TalkRecordsFile; +use App\Model\EmoticonItem; use App\Model\Group\Group; use App\Model\UsersEmoticon; @@ -91,47 +93,42 @@ class EmoticonService extends BaseService */ public function collect(int $user_id, int $record_id) { - $result = ChatRecord::where([ + $result = TalkRecords::where([ ['id', '=', $record_id], - ['msg_type', '=', 2], + ['msg_type', '=', TalkMsgType::FILE_MESSAGE], ['is_revoke', '=', 0], - ])->first(['id', 'source', 'msg_type', 'user_id', 'receive_id', 'is_revoke']); + ])->first(['id', 'talk_type', 'receiver_id', 'msg_type', 'user_id', 'is_revoke']); - if (!$result) { - return [false, []]; - } + if (!$result) return [false, []]; - if ($result->source == 1) { - if ($result->user_id != $user_id && $result->receive_id != $user_id) { + if ($result->talk_type == TalkType::PRIVATE_CHAT) { + if ($result->user_id != $user_id && $result->receiver_id != $user_id) { return [false, []]; } } else { - if (!Group::isMember($result->receive_id, $user_id)) { + if (!Group::isMember($result->receiver_id, $user_id)) { return [false, []]; } } - $fileInfo = ChatRecordsFile::where('record_id', $result->id)->where('file_type', 1)->first([ + $fileInfo = TalkRecordsFile::where('record_id', $result->id)->where('file_type', 1)->first([ 'file_suffix', 'file_size', 'save_dir' ]); - if (!$fileInfo) { - return [false, []]; - } + if (!$fileInfo) return [false, []]; - $result = EmoticonDetail::where('user_id', $user_id)->where('url', $fileInfo->save_dir)->first(); - if ($result) { - return [false, []]; - } + $result = EmoticonItem::where('user_id', $user_id)->where('url', $fileInfo->save_dir)->first(); + if ($result) return [false, []]; - $res = EmoticonDetail::create([ + $res = EmoticonItem::create([ 'user_id' => $user_id, 'url' => $fileInfo->save_dir, 'file_suffix' => $fileInfo->file_suffix, 'file_size' => $fileInfo->file_size, - 'created_at' => time() + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]); return $res ? [true, ['media_id' => $res->id, 'src' => get_media_url($res->url)]] : [false, []]; @@ -147,7 +144,7 @@ class EmoticonService extends BaseService */ public function deleteCollect(int $user_id, array $ids) { - return EmoticonDetail::whereIn('id', $ids)->where('user_id', $user_id)->delete(); + return EmoticonItem::whereIn('id', $ids)->where('user_id', $user_id)->delete(); } /** @@ -158,7 +155,7 @@ class EmoticonService extends BaseService */ public function getDetailsAll(array $where = []) { - $items = EmoticonDetail::where($where)->get(['id as media_id', 'url as src'])->toArray(); + $items = EmoticonItem::where($where)->get(['id as media_id', 'url as src'])->toArray(); foreach ($items as $k => $item) { $items[$k]['src'] = get_media_url($item['src']); } diff --git a/app/Service/GroupService.php b/app/Service/GroupService.php index 1055980..4cf9c81 100644 --- a/app/Service/GroupService.php +++ b/app/Service/GroupService.php @@ -4,11 +4,13 @@ declare(strict_types=1); namespace App\Service; use App\Cache\LastMessage; -use App\Model\Chat\ChatRecord; -use App\Model\Chat\ChatRecordsInvite; +use App\Constants\TalkMsgType; +use App\Constants\TalkType; +use App\Model\Chat\TalkRecords; +use App\Model\Chat\TalkRecordsInvite; use App\Model\Group\Group; use App\Model\Group\GroupMember; -use App\Model\UsersChatList; +use App\Model\TalkList; use Hyperf\DbConnection\Db; use Exception; @@ -41,13 +43,16 @@ class GroupService extends BaseService 'group_member.leader', ])->toArray(); - $arr = UsersChatList::where([ - ['uid', '=', $user_id], - ['type', '=', 2], - ])->get(['group_id', 'not_disturb'])->keyBy('group_id')->toArray(); + $list = []; + if ($items) { + $list = TalkList::query()->where('user_id', $user_id) + ->where('talk_type', TalkType::GROUP_CHAT) + ->whereIn('receiver_id', array_column($items, 'id')) + ->get(['receiver_id', 'is_disturb'])->keyBy('receiver_id')->toArray(); + } foreach ($items as $key => $item) { - $items[$key]['not_disturb'] = isset($arr[$item['id']]) ? $arr[$item['id']]['not_disturb'] : 0; + $items[$key]['is_disturb'] = isset($list[$item['id']]) ? $list[$item['id']]['is_disturb'] : 0; } return $items; @@ -82,25 +87,20 @@ class GroupService extends BaseService 'created_at' => date('Y-m-d H:i:s') ]); - foreach ($friend_ids as $k => $uid) { + foreach ($friend_ids as $friend_id) { $groupMember[] = [ 'group_id' => $insRes->id, - 'user_id' => $uid, - 'leader' => $user_id == $uid ? 2 : 0, - 'is_mute' => 0, - 'is_quit' => 0, - 'user_card' => '', + 'user_id' => $friend_id, + 'leader' => $user_id == $friend_id ? 2 : 0, 'created_at' => date('Y-m-d H:i:s'), ]; $chatList[] = [ - 'type' => 2, - 'uid' => $uid, - 'friend_id' => 0, - 'group_id' => $insRes->id, - 'status' => 1, - 'created_at' => date('Y-m-d H:i:s'), - 'updated_at' => date('Y-m-d H:i:s') + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => $friend_id, + 'receiver_id' => $insRes->id, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s') ]; } @@ -108,19 +108,20 @@ class GroupService extends BaseService throw new Exception('创建群成员信息失败'); } - if (!Db::table('users_chat_list')->insert($chatList)) { + if (!Db::table('talk_list')->insert($chatList)) { throw new Exception('创建群成员的聊天列表失败'); } - $result = ChatRecord::create([ - 'msg_type' => 3, - 'source' => 2, - 'user_id' => 0, - 'receive_id' => $insRes->id, - 'created_at' => date('Y-m-d H:i:s') + $result = TalkRecords::create([ + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => 0, + 'receiver_id' => $insRes->id, + 'msg_type' => TalkMsgType::GROUP_INVITE_MESSAGE, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s') ]); - ChatRecordsInvite::create([ + TalkRecordsInvite::create([ 'record_id' => $result->id, 'type' => 1, 'operate_user_id' => $user_id, @@ -133,7 +134,7 @@ class GroupService extends BaseService return [false, 0]; } - LastMessage::getInstance()->save(2, $user_id, $insRes->id, [ + LastMessage::getInstance()->save(TalkType::GROUP_CHAT, $user_id, $insRes->id, [ 'text' => '[入群通知]', 'created_at' => date('Y-m-d H:i:s') ]); @@ -165,7 +166,7 @@ class GroupService extends BaseService 'is_quit' => 1, 'deleted_at' => date('Y-m-d H:i:s'), ]); - }, 2); + }); return true; } @@ -192,34 +193,32 @@ class GroupService extends BaseService $updateArr = $insertArr = $updateArr1 = $insertArr1 = []; $members = GroupMember::where('group_id', $group_id)->whereIn('user_id', $friend_ids)->get(['id', 'user_id', 'is_quit'])->keyBy('user_id')->toArray(); - $chatArr = UsersChatList::where('group_id', $group_id)->whereIn('uid', $friend_ids)->get(['id', 'uid', 'status'])->keyBy('uid')->toArray(); + $chatArr = TalkList::where('talk_type', TalkType::GROUP_CHAT) + ->where('receiver_id', $group_id) + ->whereIn('user_id', $friend_ids) + ->get(['id', 'user_id', 'is_delete']) + ->keyBy('user_id')->toArray(); foreach ($friend_ids as $uid) { if (!isset($members[$uid])) { $insertArr[] = [ 'group_id' => $group_id, 'user_id' => $uid, - 'leader' => 0, - 'is_mute' => 0, - 'is_quit' => 0, - 'user_card' => '', 'created_at' => date('Y-m-d H:i:s') ]; - } else if ($members[$uid]['status'] == 1) { + } else if ($members[$uid]['is_quit'] == 1) { $updateArr[] = $members[$uid]['id']; } if (!isset($chatArr[$uid])) { $insertArr1[] = [ - 'type' => 2, - 'uid' => $uid, - 'friend_id' => 0, - 'group_id' => $group_id, - 'status' => 1, - 'created_at' => date('Y-m-d H:i:s'), - 'updated_at' => date('Y-m-d H:i:s') + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => $uid, + 'receiver_id' => $group_id, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s') ]; - } else if ($chatArr[$uid]['status'] == 0) { + } else if ($chatArr[$uid]['is_delete'] == 1) { $updateArr1[] = $chatArr[$uid]['id']; } } @@ -240,25 +239,26 @@ class GroupService extends BaseService } if ($updateArr1) { - UsersChatList::whereIn('id', $updateArr1)->update([ - 'status' => 1, + TalkList::whereIn('id', $updateArr1)->update([ + 'is_delete' => 1, 'created_at' => date('Y-m-d H:i:s') ]); } if ($insertArr1) { - Db::table('users_chat_list')->insert($insertArr1); + Db::table('talk_list')->insert($insertArr1); } - $result = ChatRecord::create([ - 'msg_type' => 3, - 'source' => 2, - 'user_id' => 0, - 'receive_id' => $group_id, - 'created_at' => date('Y-m-d H:i:s') + $result = TalkRecords::create([ + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => 0, + 'receiver_id' => $group_id, + 'msg_type' => TalkMsgType::GROUP_INVITE_MESSAGE, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s') ]); - ChatRecordsInvite::create([ + TalkRecordsInvite::create([ 'record_id' => $result->id, 'type' => 1, 'operate_user_id' => $user_id, @@ -271,7 +271,7 @@ class GroupService extends BaseService return [false, 0]; } - LastMessage::getInstance()->save(2, $user_id, $group_id, [ + LastMessage::getInstance()->save(TalkType::GROUP_CHAT, $user_id, $group_id, [ 'text' => '[入群通知]', 'created_at' => date('Y-m-d H:i:s') ]); @@ -304,25 +304,32 @@ class GroupService extends BaseService throw new Exception('更新记录失败...'); } - $result = ChatRecord::create([ - 'msg_type' => 3, - 'source' => 2, - 'user_id' => 0, - 'receive_id' => $group_id, - 'content' => $user_id, - 'created_at' => date('Y-m-d H:i:s') + $result = TalkRecords::create([ + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => 0, + 'receiver_id' => $group_id, + 'msg_type' => TalkMsgType::GROUP_INVITE_MESSAGE, + 'content' => $user_id, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s') ]); $record_id = $result->id; - ChatRecordsInvite::create([ + TalkRecordsInvite::create([ 'record_id' => $result->id, 'type' => 2, 'operate_user_id' => $user_id, 'user_ids' => $user_id ]); - UsersChatList::where('uid', $user_id)->where('type', 2)->where('group_id', $group_id)->update(['status' => 0]); + TalkList::where([ + ['talk_type', '=', TalkType::GROUP_CHAT], + ['user_id', '=', $user_id], + ['receiver_id', '=', $group_id], + ])->update([ + 'is_delete' => 1 + ]); Db::commit(); } catch (Exception $e) { @@ -358,23 +365,24 @@ class GroupService extends BaseService throw new Exception('更新记录失败...'); } - $result = ChatRecord::create([ - 'msg_type' => 3, - 'source' => 2, - 'user_id' => 0, - 'receive_id' => $group_id, - 'created_at' => date('Y-m-d H:i:s') + $result = TalkRecords::create([ + 'talk_type' => TalkType::GROUP_CHAT, + 'user_id' => 0, + 'receiver_id' => $group_id, + 'msg_type' => TalkMsgType::GROUP_INVITE_MESSAGE, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]); - ChatRecordsInvite::create([ + TalkRecordsInvite::create([ 'record_id' => $result->id, 'type' => 3, 'operate_user_id' => $user_id, 'user_ids' => implode(',', $member_ids) ]); - UsersChatList::whereIn('uid', $member_ids)->where('group_id', $group_id)->update([ - 'status' => 0, + TalkList::whereIn('user_id', $member_ids)->where('receiver_id', $group_id)->where('talk_type', TalkType::GROUP_CHAT)->update([ + 'is_delete' => 1, 'updated_at' => date('Y-m-d H:i:s') ]); diff --git a/app/Service/MessageHandleService.php b/app/Service/MessageHandleService.php index b04558a..4b169c0 100644 --- a/app/Service/MessageHandleService.php +++ b/app/Service/MessageHandleService.php @@ -2,12 +2,15 @@ namespace App\Service; +use App\Constants\SocketConstants; +use App\Constants\TalkMsgType; +use App\Constants\TalkType; use Hyperf\Di\Annotation\Inject; use Swoole\Http\Response; use Swoole\WebSocket\Frame; use Swoole\WebSocket\Server; use App\Amqp\Producer\ChatMessageProducer; -use App\Model\Chat\ChatRecord; +use App\Model\Chat\TalkRecords; use App\Model\Group\Group; use App\Model\UsersFriend; use App\Cache\LastMessage; @@ -32,57 +35,57 @@ class MessageHandleService public function onTalk($server, Frame $frame, $data) { $user_id = $this->socketClientService->findFdUserId($frame->fd); - if ($user_id != $data['send_user']) { + if ($user_id != $data['sender_id']) { return; } // 验证消息类型 私聊|群聊 - if (!in_array($data['source_type'], [1, 2])) { + if (!in_array($data['talk_type'], TalkType::getTypes())) { return; } // 验证发送消息用户与接受消息用户之间是否存在好友或群聊关系(后期走缓存) - if ($data['source_type'] == 1) {// 私信 + if ($data['talk_type'] == TalkType::PRIVATE_CHAT) { // 判断发送者和接受者是否是好友关系 - if (!UsersFriend::isFriend((int)$data['send_user'], (int)$data['receive_user'], true)) { + if (!UsersFriend::isFriend((int)$data['sender_id'], (int)$data['receiver_id'], true)) { return; } - } else if ($data['source_type'] == 2) {// 群聊 + } else if ($data['talk_type'] == TalkType::GROUP_CHAT) { // 判断是否属于群成员 - if (!Group::isMember((int)$data['receive_user'], (int)$data['send_user'])) { + if (!Group::isMember((int)$data['receiver_id'], (int)$data['sender_id'])) { return; } } - $result = ChatRecord::create([ - 'source' => $data['source_type'], - 'msg_type' => 1, - 'user_id' => $data['send_user'], - 'receive_id' => $data['receive_user'], - 'content' => htmlspecialchars($data['text_message']), - 'created_at' => date('Y-m-d H:i:s'), + $result = TalkRecords::create([ + 'talk_type' => $data['talk_type'], + 'user_id' => $data['sender_id'], + 'receiver_id' => $data['receiver_id'], + 'msg_type' => TalkMsgType::TEXT_MESSAGE, + 'content' => htmlspecialchars($data['text_message']), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]); if (!$result) return; // 判断是否私聊 - if ($result->source == 1) { + if ($result->talk_type == TalkType::PRIVATE_CHAT) { // 设置好友消息未读数 - UnreadTalk::getInstance()->increment($result->user_id, $result->receive_id); + UnreadTalk::getInstance()->increment($result->user_id, $result->receiver_id); } // 缓存最后一条聊天消息 - LastMessage::getInstance()->save($result->source, $result->user_id, $result->receive_id, [ + LastMessage::getInstance()->save($result->talk_type, $result->user_id, $result->receiver_id, [ 'text' => mb_substr($result->content, 0, 30), 'created_at' => $result->created_at ]); - // 推送消息 - push_amqp(new ChatMessageProducer('event_talk', [ - 'sender' => intval($data['send_user']), // 发送者ID - 'receive' => intval($data['receive_user']), // 接收者ID - 'source' => intval($data['source_type']), // 接收者类型[1:好友;2:群组;] - 'record_id' => $result->id + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_TALK, [ + 'sender_id' => $result->user_id, + 'receiver_id' => $result->receiver_id, + 'talk_type' => $result->talk_type, + 'record_id' => $result->id ])); } @@ -92,12 +95,13 @@ class MessageHandleService * @param Response|Server $server * @param Frame $frame * @param array|string $data 解析后数据 + * @return false */ public function onKeyboard($server, Frame $frame, $data) { - push_amqp(new ChatMessageProducer('event_keyboard', [ - 'send_user' => intval($data['send_user']), // 发送者ID - 'receive_user' => intval($data['receive_user']), // 接收者ID + push_amqp(new ChatMessageProducer(SocketConstants::EVENT_KEYBOARD, [ + 'sender_id' => intval($data['sender_id']), + 'receiver_id' => intval($data['receiver_id']), ])); } } diff --git a/app/Service/TalkMessageService.php b/app/Service/TalkMessageService.php new file mode 100644 index 0000000..e36c1b2 --- /dev/null +++ b/app/Service/TalkMessageService.php @@ -0,0 +1,9 @@ +leftJoin('users', 'users.id', '=', 'list.friend_id') - ->leftJoin('group', 'group.id', '=', 'list.group_id') - ->where('list.uid', $user_id) - ->where('list.status', 1) - ->orderBy('updated_at', 'desc') + $rows = TalkList::from('talk_list as list') + ->leftJoin('users', function ($join) { + $join->on('users.id', '=', 'list.receiver_id')->where('list.talk_type', '=', TalkType::PRIVATE_CHAT); + }) + ->leftJoin('group', function ($join) { + $join->on('group.id', '=', 'list.receiver_id')->where('list.talk_type', '=', TalkType::GROUP_CHAT); + }) + ->where('list.user_id', $user_id) + ->where('list.is_delete', 0) + ->orderBy('list.updated_at', 'desc') ->get($filed) ->toArray(); @@ -54,36 +60,35 @@ class TalkService extends BaseService return array_map(function ($item) use ($user_id, $socketFDService, $runIdAll) { $data['id'] = $item['id']; - $data['type'] = $item['type']; - $data['friend_id'] = $item['friend_id']; - $data['group_id'] = $item['group_id']; - $data['name'] = ''; // 对方昵称/群名称 - $data['avatar'] = ''; // 默认头像 - $data['remark_name'] = ''; // 好友备注 - $data['unread_num'] = 0; // 未读消息数量 + $data['talk_type'] = $item['talk_type']; + $data['receiver_id'] = $item['receiver_id']; + $data['avatar'] = ''; // 默认头像 + $data['name'] = ''; // 对方昵称/群名称 + $data['remark_name'] = ''; // 好友备注 + $data['unread_num'] = 0; // 未读消息 + $data['is_online'] = false; // 是否在线 + $data['is_top'] = $item['is_top']; + $data['is_disturb'] = $item['is_disturb']; $data['msg_text'] = '......'; $data['updated_at'] = $item['updated_at']; - $data['online'] = 0; - $data['is_top'] = $item['is_top']; - $data['not_disturb'] = $item['not_disturb']; - if ($item['type'] == 1) { + if ($item['talk_type'] == TalkType::PRIVATE_CHAT) { $data['name'] = $item['nickname']; $data['avatar'] = $item['user_avatar']; - $data['unread_num'] = UnreadTalk::getInstance()->read((int)$item['friend_id'], $user_id); - $data['online'] = $socketFDService->isOnlineAll($item['friend_id'], $runIdAll); + $data['unread_num'] = UnreadTalk::getInstance()->read($item['receiver_id'], $user_id); + $data['is_online'] = $socketFDService->isOnlineAll($item['receiver_id'], $runIdAll); - $remark = FriendRemark::getInstance()->read($user_id, (int)$item['friend_id']); + $remark = FriendRemark::getInstance()->read($user_id, $item['receiver_id']); if ($remark) { $data['remark_name'] = $remark; } else { $info = UsersFriend::select('user1', 'user2', 'user1_remark', 'user2_remark') - ->where('user1', ($user_id < $item['friend_id']) ? $user_id : $item['friend_id']) - ->where('user2', ($user_id < $item['friend_id']) ? $item['friend_id'] : $user_id)->first(); + ->where('user1', ($user_id < $item['receiver_id']) ? $user_id : $item['receiver_id']) + ->where('user2', ($user_id < $item['receiver_id']) ? $item['receiver_id'] : $user_id)->first(); if ($info) { - $data['remark_name'] = $info->user1 == $item['friend_id'] ? $info->user2_remark : $info->user1_remark; + $data['remark_name'] = $info->user1 == $item['receiver_id'] ? $info->user2_remark : $info->user1_remark; - FriendRemark::getInstance()->save($user_id, (int)$item['friend_id'], $data['remark_name']); + FriendRemark::getInstance()->save($user_id, (int)$item['receiver_id'], $data['remark_name']); } } } else { @@ -91,7 +96,7 @@ class TalkService extends BaseService $data['avatar'] = $item['group_avatar']; } - $records = LastMessage::getInstance()->read((int)$item['type'], $user_id, $item['type'] == 1 ? (int)$item['friend_id'] : (int)$item['group_id']); + $records = LastMessage::getInstance()->read($data['talk_type'], $user_id, $data['receiver_id']); if ($records) { $data['msg_text'] = $records['text']; $data['updated_at'] = $records['created_at']; @@ -112,12 +117,12 @@ class TalkService extends BaseService public function updateUnreadTalkList(int $user_id, $data) { foreach ($data as $friend_id => $num) { - UsersChatList::updateOrCreate([ - 'uid' => $user_id, - 'friend_id' => intval($friend_id), - 'type' => 1 + TalkList::updateOrCreate([ + 'talk_type' => TalkType::PRIVATE_CHAT, + 'user_id' => $user_id, + 'receiver_id' => $friend_id, ], [ - 'status' => 1, + 'is_delete' => 0, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s') ]); @@ -137,16 +142,16 @@ class TalkService extends BaseService $files = $codes = $forwards = $invites = []; foreach ($rows as $value) { switch ($value['msg_type']) { - case 2: + case TalkMsgType::FILE_MESSAGE: $files[] = $value['id']; break; - case 3: + case TalkMsgType::GROUP_INVITE_MESSAGE: $invites[] = $value['id']; break; - case 4: + case TalkMsgType::FORWARD_MESSAGE: $forwards[] = $value['id']; break; - case 5: + case TalkMsgType::CODE_MESSAGE: $codes[] = $value['id']; break; } @@ -154,22 +159,22 @@ class TalkService extends BaseService // 查询聊天文件信息 if ($files) { - $files = ChatRecordsFile::whereIn('record_id', $files)->get(['id', 'record_id', 'user_id', 'file_source', 'file_type', 'save_type', 'original_name', 'file_suffix', 'file_size', 'save_dir'])->keyBy('record_id')->toArray(); + $files = TalkRecordsFile::whereIn('record_id', $files)->get(['id', 'record_id', 'user_id', 'file_source', 'file_type', 'save_type', 'original_name', 'file_suffix', 'file_size', 'save_dir'])->keyBy('record_id')->toArray(); } // 查询群聊邀请信息 if ($invites) { - $invites = ChatRecordsInvite::whereIn('record_id', $invites)->get(['record_id', 'type', 'operate_user_id', 'user_ids'])->keyBy('record_id')->toArray(); + $invites = TalkRecordsInvite::whereIn('record_id', $invites)->get(['record_id', 'type', 'operate_user_id', 'user_ids'])->keyBy('record_id')->toArray(); } // 查询代码块消息 if ($codes) { - $codes = ChatRecordsCode::whereIn('record_id', $codes)->get(['record_id', 'code_lang', 'code'])->keyBy('record_id')->toArray(); + $codes = TalkRecordsCode::whereIn('record_id', $codes)->get(['record_id', 'code_lang', 'code'])->keyBy('record_id')->toArray(); } // 查询消息转发信息 if ($forwards) { - $forwards = ChatRecordsForward::whereIn('record_id', $forwards)->get(['record_id', 'records_id', 'text'])->keyBy('record_id')->toArray(); + $forwards = TalkRecordsForward::whereIn('record_id', $forwards)->get(['record_id', 'records_id', 'text'])->keyBy('record_id')->toArray(); } foreach ($rows as $k => $row) { @@ -179,13 +184,31 @@ class TalkService extends BaseService $rows[$k]['invite'] = []; switch ($row['msg_type']) { - case 2:// 文件消息 + case TalkMsgType::FILE_MESSAGE:// 文件消息 $rows[$k]['file'] = $files[$row['id']] ?? []; if ($rows[$k]['file']) { $rows[$k]['file']['file_url'] = get_media_url($rows[$k]['file']['save_dir']); } break; - case 3:// 入群消息/退群消息 + + case TalkMsgType::FORWARD_MESSAGE:// 会话记录消息 + if (isset($forwards[$row['id']])) { + $rows[$k]['forward'] = [ + 'num' => substr_count($forwards[$row['id']]['records_id'], ',') + 1, + 'list' => json_decode($forwards[$row['id']]['text'], true) ?? [] + ]; + } + break; + + case TalkMsgType::CODE_MESSAGE:// 代码块消息 + $rows[$k]['code_block'] = $codes[$row['id']] ?? []; + if ($rows[$k]['code_block']) { + $rows[$k]['code_block']['code'] = htmlspecialchars_decode($rows[$k]['code_block']['code']); + unset($rows[$k]['code_block']['record_id']); + } + break; + + case TalkMsgType::GROUP_INVITE_MESSAGE:// 入群消息/退群消息 if (isset($invites[$row['id']])) { $rows[$k]['invite'] = [ 'type' => $invites[$row['id']]['type'], @@ -203,21 +226,6 @@ class TalkService extends BaseService } } break; - case 4:// 会话记录消息 - if (isset($forwards[$row['id']])) { - $rows[$k]['forward'] = [ - 'num' => substr_count($forwards[$row['id']]['records_id'], ',') + 1, - 'list' => json_decode($forwards[$row['id']]['text'], true) ?? [] - ]; - } - break; - case 5:// 代码块消息 - $rows[$k]['code_block'] = $codes[$row['id']] ?? []; - if ($rows[$k]['code_block']) { - $rows[$k]['code_block']['code'] = htmlspecialchars_decode($rows[$k]['code_block']['code']); - unset($rows[$k]['code_block']['record_id']); - } - break; } } @@ -228,65 +236,66 @@ class TalkService extends BaseService /** * 查询对话页面的历史聊天记录 * - * @param int $user_id 用户ID - * @param int $receive_id 接收者ID(好友ID或群ID) - * @param int $source 消息来源 1:好友消息 2:群聊消息 - * @param int $record_id 上一次查询的聊天记录ID - * @param int $limit 查询数据长度 - * @param array $msg_type 消息类型 + * @param int $user_id 用户ID + * @param int $receiver_id 接收者ID(好友ID或群ID) + * @param int $talk_type 对话类型[1:好友消息;2:群聊消息;] + * @param int $record_id 上一次查询的聊天记录ID + * @param int $limit 查询数据长度 + * @param array $msg_type 消息类型 * @return array */ - public function getChatRecords(int $user_id, int $receive_id, int $source, int $record_id, $limit = 30, $msg_type = []) + public function getChatRecords(int $user_id, int $receiver_id, int $talk_type, int $record_id, $limit = 30, $msg_type = []) { $fields = [ - 'chat_records.id', - 'chat_records.source', - 'chat_records.msg_type', - 'chat_records.user_id', - 'chat_records.receive_id', - 'chat_records.content', - 'chat_records.is_revoke', - 'chat_records.created_at', + 'talk_records.id', + 'talk_records.talk_type', + 'talk_records.msg_type', + 'talk_records.user_id', + 'talk_records.receiver_id', + 'talk_records.is_revoke', + 'talk_records.content', + 'talk_records.created_at', 'users.nickname', 'users.avatar as avatar', ]; - $rowsSqlObj = ChatRecord::select($fields); + $rowsSqlObj = TalkRecords::select($fields); - $rowsSqlObj->leftJoin('users', 'users.id', '=', 'chat_records.user_id'); + $rowsSqlObj->leftJoin('users', 'users.id', '=', 'talk_records.user_id'); if ($record_id) { - $rowsSqlObj->where('chat_records.id', '<', $record_id); + $rowsSqlObj->where('talk_records.id', '<', $record_id); } - if ($source == 1) { - $rowsSqlObj->where(function ($query) use ($user_id, $receive_id) { + if ($talk_type == TalkType::PRIVATE_CHAT) { + $rowsSqlObj->where(function ($query) use ($user_id, $receiver_id) { $query->where([ - ['chat_records.user_id', '=', $user_id], - ['chat_records.receive_id', '=', $receive_id] + ['talk_records.user_id', '=', $user_id], + ['talk_records.receiver_id', '=', $receiver_id] ])->orWhere([ - ['chat_records.user_id', '=', $receive_id], - ['chat_records.receive_id', '=', $user_id] + ['talk_records.user_id', '=', $receiver_id], + ['talk_records.receiver_id', '=', $user_id] ]); }); } else { - $rowsSqlObj->where('chat_records.receive_id', $receive_id); - $rowsSqlObj->where('chat_records.source', $source); + $rowsSqlObj->where('talk_records.receiver_id', $receiver_id); + $rowsSqlObj->where('talk_records.talk_type', $talk_type); } if ($msg_type) { - $rowsSqlObj->whereIn('chat_records.msg_type', $msg_type); + $rowsSqlObj->whereIn('talk_records.msg_type', $msg_type); } //过滤用户删除记录 $rowsSqlObj->whereNotExists(function ($query) use ($user_id) { $prefix = config('databases.default.prefix'); - $query->select(Db::raw(1))->from('chat_records_delete'); - $query->whereRaw("{$prefix}chat_records_delete.record_id = {$prefix}chat_records.id and {$prefix}chat_records_delete.user_id = {$user_id}"); + $query->select(Db::raw(1))->from('talk_records_delete'); + $query->whereRaw("{$prefix}talk_records_delete.record_id = {$prefix}talk_records.id and {$prefix}talk_records_delete.user_id = {$user_id}"); $query->limit(1); }); - $rows = $rowsSqlObj->orderBy('chat_records.id', 'desc')->limit($limit)->get()->toArray(); - return $this->handleChatRecords($rows); + return $this->handleChatRecords( + $rowsSqlObj->orderBy('talk_records.id', 'desc')->limit($limit)->get()->toArray() + ); } /** @@ -298,35 +307,35 @@ class TalkService extends BaseService */ public function getForwardRecords(int $user_id, int $record_id) { - $result = ChatRecord::where('id', $record_id)->first([ - 'id', 'source', 'msg_type', 'user_id', 'receive_id', 'content', 'is_revoke', 'created_at' + $result = TalkRecords::where('id', $record_id)->first([ + 'id', 'talk_type', 'msg_type', 'user_id', 'receiver_id', 'content', 'is_revoke', 'created_at' ]); // 判断是否有权限查看 - if ($result->source == 1 && ($result->user_id != $user_id && $result->receive_id != $user_id)) { + if ($result->talk_type == TalkType::PRIVATE_CHAT && ($result->user_id != $user_id && $result->receiver_id != $user_id)) { return []; - } else if ($result->source == 2 && !Group::isMember($result->receive_id, $user_id)) { + } else if ($result->talk_type == TalkType::GROUP_CHAT && !Group::isMember($result->receiver_id, $user_id)) { return []; } - $forward = ChatRecordsForward::where('record_id', $record_id)->first(); + $forward = TalkRecordsForward::where('record_id', $record_id)->first(); $fields = [ - 'chat_records.id', - 'chat_records.source', - 'chat_records.msg_type', - 'chat_records.user_id', - 'chat_records.receive_id', - 'chat_records.content', - 'chat_records.is_revoke', - 'chat_records.created_at', + 'talk_records.id', + 'talk_records.talk_type', + 'talk_records.msg_type', + 'talk_records.user_id', + 'talk_records.receiver_id', + 'talk_records.is_revoke', + 'talk_records.content', + 'talk_records.created_at', 'users.nickname', 'users.avatar as avatar', ]; - $rowsSqlObj = ChatRecord::select($fields); - $rowsSqlObj->leftJoin('users', 'users.id', '=', 'chat_records.user_id'); - $rowsSqlObj->whereIn('chat_records.id', explode(',', $forward->records_id)); + $rowsSqlObj = TalkRecords::select($fields); + $rowsSqlObj->leftJoin('users', 'users.id', '=', 'talk_records.user_id'); + $rowsSqlObj->whereIn('talk_records.id', explode(',', $forward->records_id)); return $this->handleChatRecords($rowsSqlObj->get()->toArray()); } @@ -334,20 +343,21 @@ class TalkService extends BaseService /** * 批量删除聊天消息 * - * @param int $user_id 用户ID - * @param int $source 消息来源 1:好友消息 2:群聊消息 - * @param int $receive_id 好友ID或者群聊ID - * @param array $record_ids 聊天记录ID + * @param int $user_id 用户ID + * @param int $talk_type 对话类型[1:好友消息;2:群聊消息;] + * @param int $receiver_id 好友ID或者群聊ID + * @param array $record_ids 聊天记录ID * @return bool */ - public function removeRecords(int $user_id, int $source, int $receive_id, array $record_ids) + public function removeRecords(int $user_id, int $talk_type, int $receiver_id, array $record_ids) { - if ($source == 1) {// 私聊信息 - $ids = ChatRecord::whereIn('id', $record_ids)->where(function ($query) use ($user_id, $receive_id) { - $query->where([['user_id', '=', $user_id], ['receive_id', '=', $receive_id]])->orWhere([['user_id', '=', $receive_id], ['receive_id', '=', $user_id]]); - })->where('source', 1)->pluck('id'); + if ($talk_type == TalkType::PRIVATE_CHAT) {// 私聊信息 + $ids = TalkRecords::whereIn('id', $record_ids)->where(function ($query) use ($user_id, $receiver_id) { + $query->where([['user_id', '=', $user_id], ['receiver_id', '=', $receiver_id]]) + ->orWhere([['user_id', '=', $receiver_id], ['receiver_id', '=', $user_id]]); + })->where('talk_type', $talk_type)->pluck('id'); } else {// 群聊信息 - $ids = ChatRecord::whereIn('id', $record_ids)->where('source', 2)->pluck('id'); + $ids = TalkRecords::whereIn('id', $record_ids)->where('talk_type', TalkType::GROUP_CHAT)->pluck('id'); } // 判断要删除的消息在数据库中是否存在 @@ -356,7 +366,7 @@ class TalkService extends BaseService } // 判读是否属于群消息并且判断是否是群成员 - if ($source == 2 && !Group::isMember($receive_id, $user_id)) { + if ($talk_type == TalkType::GROUP_CHAT && !Group::isMember($receiver_id, $user_id)) { return false; } @@ -368,7 +378,7 @@ class TalkService extends BaseService ]; }, $ids->toArray()); - return Db::table('chat_records_delete')->insert($data); + return Db::table('talk_records_delete')->insert($data); } /** @@ -380,7 +390,7 @@ class TalkService extends BaseService */ public function revokeRecord(int $user_id, int $record_id) { - $result = ChatRecord::where('id', $record_id)->first(['id', 'source', 'user_id', 'receive_id', 'created_at']); + $result = TalkRecords::where('id', $record_id)->first(['id', 'talk_type', 'user_id', 'receiver_id', 'created_at']); if (!$result) return [false, '消息记录不存在']; // 判断是否在两分钟之内撤回消息,超过2分钟不能撤回消息 @@ -388,12 +398,12 @@ class TalkService extends BaseService return [false, '已超过有效的撤回时间', []]; } - if ($result->source == 1) { - if ($result->user_id != $user_id && $result->receive_id != $user_id) { + if ($result->talk_type == TalkType::PRIVATE_CHAT) { + if ($result->user_id != $user_id && $result->receiver_id != $user_id) { return [false, '非法操作', []]; } - } else if ($result->source == 2) { - if (!Group::isMember($result->receive_id, $user_id)) { + } else if ($result->talk_type == TalkType::GROUP_CHAT) { + if (!Group::isMember($result->receiver_id, $user_id)) { return [false, '非法操作', []]; } } @@ -407,59 +417,66 @@ class TalkService extends BaseService /** * 转发消息(单条转发) * - * @param int $user_id 转发的用户ID - * @param int $record_id 转发消息的记录ID - * @param array $receive_ids 接受者数组 例如:[['source' => 1,'id' => 3045],['source' => 1,'id' => 3046],['source' => - * 1,'id' => 1658]] 二维数组 + * @param int $user_id 转发的用户ID + * @param int $record_id 转发消息的记录ID + * @param array $receiver_ids 接受者数组 例如:[['talk_type' => 1,'id' => 3045]...] 二维数组 * @return array */ - public function forwardRecords(int $user_id, int $record_id, array $receive_ids) + public function forwardRecords(int $user_id, int $record_id, array $receiver_ids) { - $result = ChatRecord::where('id', $record_id)->whereIn('msg_type', [1, 2, 5])->first(); - if (!$result) { - return []; - } + $msgTypeArray = [ + TalkMsgType::TEXT_MESSAGE, + TalkMsgType::FILE_MESSAGE, + TalkMsgType::CODE_MESSAGE + ]; + + $result = TalkRecords::where('id', $record_id)->whereIn('msg_type', $msgTypeArray)->first(); + if (!$result) return []; // 根据消息类型判断用户是否有转发权限 - if ($result->source == 1) { - if ($result->user_id != $user_id && $result->receive_id != $user_id) { + if ($result->talk_type == TalkType::PRIVATE_CHAT) { + if ($result->user_id != $user_id && $result->receiver_id != $user_id) { return []; } - } else if ($result->source == 2) { - if (!Group::isMember($result->receive_id, $user_id)) { + } else if ($result->talk_type == TalkType::GROUP_CHAT) { + if (!Group::isMember($result->receiver_id, $user_id)) { return []; } } - $fileInfo = null; - $codeBlock = null; - if ($result->msg_type == 2) { - $fileInfo = ChatRecordsFile::where('record_id', $record_id)->first(); - } else if ($result->msg_type == 5) { - $codeBlock = ChatRecordsCode::where('record_id', $record_id)->first(); + $fileInfo = $codeBlock = null; + if ($result->msg_type == TalkMsgType::FILE_MESSAGE) { + $fileInfo = TalkRecordsFile::where('record_id', $record_id)->first(); + } else if ($result->msg_type == TalkMsgType::CODE_MESSAGE) { + $codeBlock = TalkRecordsCode::where('record_id', $record_id)->first(); } $insRecordIds = []; Db::beginTransaction(); try { - foreach ($receive_ids as $item) { - $res = ChatRecord::create([ - 'source' => $item['source'], - 'msg_type' => $result->msg_type, - 'user_id' => $user_id, - 'receive_id' => $item['id'], - 'content' => $result->content, - 'created_at' => date('Y-m-d H:i:s') + foreach ($receiver_ids as $item) { + $res = TalkRecords::create([ + 'talk_type' => $item['talk_type'], + 'msg_type' => $result->msg_type, + 'user_id' => $user_id, + 'receiver_id' => $item['id'], + 'content' => $result->content, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]); if (!$res) { throw new Exception('插入消息记录失败'); } - $insRecordIds[] = $res->id; + $insRecordIds[] = [ + 'record_id' => $res->id, + 'receiver_id' => $res->receiver_id, + 'talk_type' => $res->talk_type + ]; - if ($result->msg_type == 2) { - if (!ChatRecordsFile::create([ + if ($result->msg_type == TalkMsgType::FILE_MESSAGE) { + if (!TalkRecordsFile::create([ 'record_id' => $res->id, 'user_id' => $fileInfo->user_id, 'file_source' => $fileInfo->file_source, @@ -473,8 +490,8 @@ class TalkService extends BaseService ])) { throw new Exception('插入文件消息记录失败'); } - } else if ($result->msg_type == 5) { - if (!ChatRecordsCode::create([ + } else if ($result->msg_type == TalkMsgType::CODE_MESSAGE) { + if (!TalkRecordsCode::create([ 'record_id' => $res->id, 'user_id' => $user_id, 'code_lang' => $codeBlock->code_lang, @@ -499,43 +516,39 @@ class TalkService extends BaseService * 转发消息(多条合并转发) * * @param int $user_id 转发的用户ID - * @param int $receive_id 当前转发消息的所属者(好友ID或者群聊ID) - * @param int $source 消息来源 1:好友消息 2:群聊消息 + * @param int $receiver_id 当前转发消息的所属者(好友ID或者群聊ID) + * @param int $talk_type 消息来源 1:好友消息 2:群聊消息 * @param array $records_ids 转发消息的记录ID - * @param array $receive_ids 接受者数组 例如:[['source' => 1,'id' => 3045],['source' => 1,'id' => 3046],['source' => - * 1,'id' => 1658]] 二维数组 - * @return array|bool + * @param array $receive_ids 接受者数组 例如:[['talk_type' => 1,'id' => 3045]...] 二维数组 + * @return array */ - public function mergeForwardRecords(int $user_id, int $receive_id, int $source, array $records_ids, array $receive_ids) + public function mergeForwardRecords(int $user_id, int $receiver_id, int $talk_type, array $records_ids, array $receive_ids) { // 支持转发的消息类型 - $msg_type = [1, 2, 5]; + $msg_type = [ + TalkMsgType::TEXT_MESSAGE, + TalkMsgType::FILE_MESSAGE, + TalkMsgType::CODE_MESSAGE + ]; - $sqlObj = ChatRecord::whereIn('id', $records_ids); + $sqlObj = TalkRecords::whereIn('id', $records_ids); - // 验证是否有权限转发 - if ($source == 2) {// 群聊消息 - // 判断是否是群聊成员 - if (!Group::isMember($receive_id, $user_id)) { - return false; - } + if ($talk_type == TalkType::PRIVATE_CHAT) { + if (!UsersFriend::isFriend($user_id, $receiver_id)) return []; - $sqlObj = $sqlObj->where('receive_id', $receive_id)->whereIn('msg_type', $msg_type)->where('source', 2)->where('is_revoke', 0); - } else {// 私聊消息 - // 判断是否存在好友关系 - if (!UsersFriend::isFriend($user_id, $receive_id)) { - return []; - } - - $sqlObj = $sqlObj->where(function ($query) use ($user_id, $receive_id) { + $sqlObj = $sqlObj->where(function ($query) use ($user_id, $receiver_id) { $query->where([ ['user_id', '=', $user_id], - ['receive_id', '=', $receive_id] + ['receiver_id', '=', $receiver_id] ])->orWhere([ - ['user_id', '=', $receive_id], - ['receive_id', '=', $user_id] + ['user_id', '=', $receiver_id], + ['receiver_id', '=', $user_id] ]); - })->whereIn('msg_type', $msg_type)->where('source', 1)->where('is_revoke', 0); + })->whereIn('msg_type', $msg_type)->where('talk_type', $talk_type)->where('is_revoke', 0); + } else { + if (!Group::isMember($receiver_id, $user_id)) return []; + + $sqlObj = $sqlObj->where('receiver_id', $receiver_id)->whereIn('msg_type', $msg_type)->where('talk_type', TalkType::GROUP_CHAT)->where('is_revoke', 0); } $result = $sqlObj->get(); @@ -545,26 +558,26 @@ class TalkService extends BaseService return []; } - $rows = ChatRecord::leftJoin('users', 'users.id', '=', 'chat_records.user_id') - ->whereIn('chat_records.id', array_slice($records_ids, 0, 3)) - ->get(['chat_records.msg_type', 'chat_records.content', 'users.nickname']); + $rows = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id') + ->whereIn('talk_records.id', array_slice($records_ids, 0, 3)) + ->get(['talk_records.msg_type', 'talk_records.content', 'users.nickname']); $jsonText = []; foreach ($rows as $row) { switch ($row->msg_type) { - case 1: + case TalkMsgType::TEXT_MESSAGE: $jsonText[] = [ 'nickname' => $row->nickname, 'text' => mb_substr(str_replace(PHP_EOL, "", $row->content), 0, 30) ]; break; - case 2: + case TalkMsgType::FILE_MESSAGE: $jsonText[] = [ 'nickname' => $row->nickname, 'text' => '【文件消息】' ]; break; - case 3: + case TalkMsgType::CODE_MESSAGE: $jsonText[] = [ 'nickname' => $row->nickname, 'text' => '【代码消息】' @@ -577,12 +590,13 @@ class TalkService extends BaseService Db::beginTransaction(); try { foreach ($receive_ids as $item) { - $res = ChatRecord::create([ - 'source' => $item['source'], - 'msg_type' => 4, - 'user_id' => $user_id, - 'receive_id' => $item['id'], - 'created_at' => date('Y-m-d H:i:s') + $res = TalkRecords::create([ + 'talk_type' => $item['talk_type'], + 'user_id' => $user_id, + 'receiver_id' => $item['id'], + 'msg_type' => TalkMsgType::FORWARD_MESSAGE, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]); if (!$res) { @@ -590,12 +604,12 @@ class TalkService extends BaseService } $insRecordIds[] = [ - 'record_id' => $res->id, - 'receive_id' => $item['id'], - 'source' => $item['source'] + 'record_id' => $res->id, + 'receiver_id' => $res->receiver_id, + 'talk_type' => $res->talk_type ]; - if (!ChatRecordsForward::create([ + if (!TalkRecordsForward::create([ 'record_id' => $res->id, 'user_id' => $user_id, 'records_id' => implode(',', $records_ids), @@ -618,52 +632,51 @@ class TalkService extends BaseService /** * 关键词搜索聊天记录 * - * @param int $user_id 用户ID - * @param int $receive_id 接收者ID(用户ID或群聊接收ID) - * @param int $source 聊天来源(1:私信 2:群聊) - * @param int $page 当前查询分页 - * @param int $page_size 分页大小 - * @param array $params 查询参数 + * @param int $user_id 用户ID + * @param int $receiver_id 接收者ID + * @param int $talk_type 对话类型[1:私信;2:群聊;] + * @param int $page 当前查询分页 + * @param int $page_size 分页大小 + * @param array $params 查询参数 * @return array */ - public function searchRecords(int $user_id, int $receive_id, int $source, int $page, int $page_size, array $params) + public function searchRecords(int $user_id, int $receiver_id, int $talk_type, int $page, int $page_size, array $params) { $fields = [ - 'chat_records.id', - 'chat_records.source', - 'chat_records.msg_type', - 'chat_records.user_id', - 'chat_records.receive_id', - 'chat_records.content', - 'chat_records.is_revoke', - 'chat_records.created_at', - + 'talk_records.id', + 'talk_records.talk_type', + 'talk_records.msg_type', + 'talk_records.user_id', + 'talk_records.receiver_id', + 'talk_records.content', + 'talk_records.is_revoke', + 'talk_records.created_at', 'users.nickname', 'users.avatar as avatar', ]; - $rowsSqlObj = ChatRecord::select($fields)->leftJoin('users', 'users.id', '=', 'chat_records.user_id'); - if ($source == 1) { - $rowsSqlObj->where(function ($query) use ($user_id, $receive_id) { + $rowsSqlObj = TalkRecords::select($fields)->leftJoin('users', 'users.id', '=', 'talk_records.user_id'); + if ($talk_type == 1) { + $rowsSqlObj->where(function ($query) use ($user_id, $receiver_id) { $query->where([ - ['chat_records.user_id', '=', $user_id], - ['chat_records.receive_id', '=', $receive_id] + ['talk_records.user_id', '=', $user_id], + ['talk_records.receiver_id', '=', $receiver_id] ])->orWhere([ - ['chat_records.user_id', '=', $receive_id], - ['chat_records.receive_id', '=', $user_id] + ['talk_records.user_id', '=', $receiver_id], + ['talk_records.receiver_id', '=', $user_id] ]); }); } else { - $rowsSqlObj->where('chat_records.receive_id', $receive_id); - $rowsSqlObj->where('chat_records.source', $source); + $rowsSqlObj->where('talk_records.receiver_id', $receiver_id); + $rowsSqlObj->where('talk_records.talk_type', $talk_type); } if (isset($params['keywords'])) { - $rowsSqlObj->where('chat_records.content', 'like', "%{$params['keywords']}%"); + $rowsSqlObj->where('talk_records.content', 'like', "%{$params['keywords']}%"); } if (isset($params['date'])) { - $rowsSqlObj->whereDate('chat_records.created_at', $params['date']); + $rowsSqlObj->whereDate('talk_records.created_at', $params['date']); } $count = $rowsSqlObj->count(); @@ -671,7 +684,7 @@ class TalkService extends BaseService return $this->getPagingRows([], 0, $page, $page_size); } - $rows = $rowsSqlObj->orderBy('chat_records.id', 'desc')->forPage($page, $page_size)->get()->toArray(); + $rows = $rowsSqlObj->orderBy('talk_records.id', 'desc')->forPage($page, $page_size)->get()->toArray(); return $this->getPagingRows($this->handleChatRecords($rows), $count, $page, $page_size); } @@ -687,7 +700,7 @@ class TalkService extends BaseService Db::beginTransaction(); try { $message['created_at'] = date('Y-m-d H:i:s'); - $insert = ChatRecord::create($message); + $insert = TalkRecords::create($message); if (!$insert) { throw new Exception('插入聊天记录失败...'); @@ -697,7 +710,7 @@ class TalkService extends BaseService $fileInfo['file_type'] = FileMediaType::getMediaType($fileInfo['file_suffix']); $fileInfo['created_at'] = date('Y-m-d H:i:s'); - if (!ChatRecordsFile::create($fileInfo)) { + if (!TalkRecordsFile::create($fileInfo)) { throw new Exception('插入聊天记录(文件消息)失败...'); } @@ -722,14 +735,14 @@ class TalkService extends BaseService Db::beginTransaction(); try { $message['created_at'] = date('Y-m-d H:i:s'); - $insert = ChatRecord::create($message); + $insert = TalkRecords::create($message); if (!$insert) { throw new Exception('插入聊天记录失败...'); } $codeBlock['record_id'] = $insert->id; $codeBlock['created_at'] = date('Y-m-d H:i:s'); - if (!ChatRecordsCode::create($codeBlock)) { + if (!TalkRecordsCode::create($codeBlock)) { throw new Exception('插入聊天记录(代码消息)失败...'); } @@ -754,14 +767,14 @@ class TalkService extends BaseService Db::beginTransaction(); try { $message['created_at'] = date('Y-m-d H:i:s'); - $insert = ChatRecord::create($message); + $insert = TalkRecords::create($message); if (!$insert) { throw new Exception('插入聊天记录失败...'); } $emoticon['record_id'] = $insert->id; $emoticon['created_at'] = date('Y-m-d H:i:s'); - if (!ChatRecordsFile::create($emoticon)) { + if (!TalkRecordsFile::create($emoticon)) { throw new Exception('插入聊天记录(代码消息)失败...'); } @@ -775,7 +788,7 @@ class TalkService extends BaseService } /** - * 创建代码块消息 + * 创建文件消息 * * @param array $message * @param array $emoticon @@ -786,14 +799,15 @@ class TalkService extends BaseService Db::beginTransaction(); try { $message['created_at'] = date('Y-m-d H:i:s'); - $insert = ChatRecord::create($message); + $insert = TalkRecords::create($message); if (!$insert) { throw new Exception('插入聊天记录失败...'); } $emoticon['record_id'] = $insert->id; + $emoticon['file_type'] = FileMediaType::getMediaType($emoticon['file_suffix']); $emoticon['created_at'] = date('Y-m-d H:i:s'); - if (!ChatRecordsFile::create($emoticon)) { + if (!TalkRecordsFile::create($emoticon)) { throw new Exception('插入聊天记录(代码消息)失败...'); } diff --git a/app/Service/UserService.php b/app/Service/UserService.php index 4907ef6..0cf0123 100644 --- a/app/Service/UserService.php +++ b/app/Service/UserService.php @@ -55,6 +55,7 @@ class UserService extends BaseService try { $data['password'] = Hash::make($data['password']); $data['created_at'] = date('Y-m-d H:i:s'); + $data['updated_at'] = date('Y-m-d H:i:s'); $result = User::create($data); diff --git a/message.php b/message.php new file mode 100644 index 0000000..7a7aad5 --- /dev/null +++ b/message.php @@ -0,0 +1,80 @@ + 0, //发送者ID + 'receiver_id' => 0, //接收者ID + 'talk_type' => 0, //对话类型[1:私聊;2:群聊;] + 'data' => [ + "id" => 0, // 消息记录ID + "talk_type" => 1, // 对话来源 + "msg_type" => 1, // 消息类型 + "user_id" => 0, // 发送者用户ID + "receiver_id" => 0, // 接收者ID + "nickname" => '',// 用户昵称 + "avatar" => '',// 用户头像 + "group_name" => '',// 群组名称 + "group_avatar" => '',// 群组头像 + "file" => [], + "code_block" => [], + "forward" => [], + "invite" => [], + "content" => '',// 文本消息 + "created_at" => '', + "is_revoke" => 0, // 消息是否撤销 + ] +]; + +// 撤销聊天消息推送协议 +$revoke_talk_message = [ + 'talk_type' => 0,//对话类型 + 'sender_id' => 0,//发送者ID + 'receiver_id' => 0,//接收者ID + 'record_id' => 0,//撤销的记录 +]; + +// 好友在线状态通知消息推送协议 +$online_status_message = [ + 'user_id' => 0,//用户ID + 'status' => 0,//在线状态[0:离线;1:在线;] +]; + +// 键盘输入事件消息推送协议 +$keyboard_message = [ + 'sender_id' => 0, + 'receiver_id' => 0, +]; + +// 好友申请消息推送协议 +$friend_apply_message = [ + 'sender_id' => 0, //发送者ID + 'receiver_id' => 0, //接收者ID + 'remark' => '',//申请备注 + 'friend' => [ + 'user_id' => 0, + 'avatar' => '', + 'nickname' => '', + 'mobile' => '', + ] +]; + +// 好友申请回调消息推送协议 +$friend_apply_callback_message = [ + 'sender_id' => 0, //发送者ID + 'receiver_id' => 0, //接收者ID + 'status' => 0, //处理备注[0:未处理;1:已同意;2:已拒绝;] + 'remark' => '',//处理备注 + 'friend' => [ + 'user_id' => 0, + 'avatar' => '', + 'nickname' => '', + 'mobile' => '', + ] +]; + +// ACK已读消息推送协议 +$read_message = [ + 'sender_id' => 0, //发送者ID + 'receiver_id' => 0, //接收者ID + 'msg_id' => 0 //已读消息ID +]; diff --git a/migrations/2020_11_04_152602_create_users_table.php b/migrations/2020_11_04_152602_create_users_table.php index 860e8ee..fb06c40 100644 --- a/migrations/2020_11_04_152602_create_users_table.php +++ b/migrations/2020_11_04_152602_create_users_table.php @@ -17,15 +17,16 @@ class CreateUsersTable extends Migration $table->string('mobile', 11)->default('')->unique()->comment('手机号'); $table->string('nickname', 20)->default('')->comment('用户昵称'); $table->string('avatar', 255)->default('')->comment('用户头像地址'); - $table->unsignedTinyInteger('gender')->default(0)->unsigned()->comment('用户性别[0:未知;1:男;2:女]'); + $table->unsignedTinyInteger('gender')->default(0)->comment('用户性别[0:未知;1:男;2:女]'); $table->string('password', 255)->default('')->comment('用户密码'); $table->string('motto', 100)->default('')->comment('用户座右铭'); $table->string('email', 30)->default('')->comment('用户邮箱'); $table->dateTime('created_at')->nullable()->comment('注册时间'); + $table->dateTime('updated_at')->nullable()->comment('更新时间'); - $table->charset = 'utf8'; + $table->charset = 'utf8'; $table->collation = 'utf8_general_ci'; - $table->engine = 'InnoDB'; + $table->engine = 'InnoDB'; $table->unique(['mobile'], 'idx_mobile'); }); diff --git a/migrations/2020_11_04_153337_create_emoticon_table.php b/migrations/2020_11_04_153337_create_emoticon_table.php index 9976f8a..22b9837 100644 --- a/migrations/2020_11_04_153337_create_emoticon_table.php +++ b/migrations/2020_11_04_153337_create_emoticon_table.php @@ -4,6 +4,7 @@ use Hyperf\Database\Schema\Schema; use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Migrations\Migration; use Hyperf\DbConnection\Db; + class CreateEmoticonTable extends Migration { /** @@ -13,11 +14,13 @@ class CreateEmoticonTable extends Migration { Schema::create('emoticon', function (Blueprint $table) { $table->unsignedInteger('id', true)->comment('表情分组ID'); - $table->string('name', 100)->default('')->comment('表情分组名称'); - $table->string('url', 255)->default('')->comment('图片地址'); - $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('创建时间'); + $table->string('name', 50)->default('')->nullable(false)->comment('分组名称'); + $table->string('icon', 255)->default('')->comment('分组图标'); + $table->unsignedTinyInteger('status')->default(0)->comment('分组状态[-1:已删除;0:正常;1:已禁用;]'); + $table->dateTime('created_at')->nullable()->comment('创建时间'); + $table->dateTime('updated_at')->nullable()->comment('更新时间'); - $table->charset = 'utf8'; + $table->charset = 'utf8'; $table->collation = 'utf8_general_ci'; }); diff --git a/migrations/2020_11_04_153347_create_emoticon_details_table.php b/migrations/2020_11_04_153347_create_emoticon_item_table.php similarity index 63% rename from migrations/2020_11_04_153347_create_emoticon_details_table.php rename to migrations/2020_11_04_153347_create_emoticon_item_table.php index 2929bae..d69250f 100644 --- a/migrations/2020_11_04_153347_create_emoticon_details_table.php +++ b/migrations/2020_11_04_153347_create_emoticon_item_table.php @@ -4,29 +4,31 @@ use Hyperf\Database\Schema\Schema; use Hyperf\Database\Schema\Blueprint; use Hyperf\Database\Migrations\Migration; use Hyperf\DbConnection\Db; -class CreateEmoticonDetailsTable extends Migration + +class CreateEmoticonItemTable extends Migration { /** * Run the migrations. */ public function up(): void { - Schema::create('emoticon_details', function (Blueprint $table) { - $table->unsignedInteger('id', true)->comment('表情包ID'); + Schema::create('emoticon_item', function (Blueprint $table) { + $table->unsignedInteger('id', true)->comment('表情包详情ID'); $table->unsignedInteger('emoticon_id')->default(0)->comment('表情分组ID'); $table->unsignedInteger('user_id')->default(0)->comment('用户ID(0:代码系统表情包)'); - $table->string('describe', 20)->default('')->comment('表情关键字描述'); - $table->string('url', 255)->default('')->comment('表情链接'); + $table->string('describe', 20)->default('')->comment('表情描述'); + $table->string('url', 255)->default('')->comment('图片链接'); $table->string('file_suffix', 10)->default('')->comment('文件后缀名'); $table->unsignedBigInteger('file_size')->default(0)->comment('文件大小(单位字节)'); - $table->unsignedInteger('created_at')->nullable(true)->default(0)->comment('添加时间'); + $table->dateTime('created_at')->nullable()->comment('创建时间'); + $table->dateTime('updated_at')->nullable()->comment('更新时间'); - $table->charset = 'utf8'; + $table->charset = 'utf8'; $table->collation = 'utf8_general_ci'; }); $prefix = config('databases.default.prefix'); - DB::statement("ALTER TABLE `{$prefix}emoticon_details` comment '聊天表情包'"); + DB::statement("ALTER TABLE `{$prefix}emoticon_item` comment '表情包详情表'"); } /** @@ -34,6 +36,6 @@ class CreateEmoticonDetailsTable extends Migration */ public function down(): void { - Schema::dropIfExists('emoticon_details'); + Schema::dropIfExists('emoticon_item'); } } diff --git a/migrations/2021_07_02_165853_create_robots_table.php b/migrations/2021_07_02_165853_create_robots_table.php new file mode 100644 index 0000000..f91dff7 --- /dev/null +++ b/migrations/2021_07_02_165853_create_robots_table.php @@ -0,0 +1,42 @@ +unsignedInteger('id', true)->comment('机器人ID'); + $table->unsignedInteger('user_id')->comment('关联用户ID'); + $table->string('robot_name', 30)->default('')->comment('机器人名称'); + $table->string('describe', 255)->default('')->comment('描述信息'); + $table->string('logo', 255)->default('')->comment('机器人logo'); + $table->unsignedTinyInteger('is_talk')->default(0)->unsigned()->comment('可发送消息[0:否;1:是;]'); + $table->unsignedTinyInteger('status')->default(0)->unsigned()->comment('状态[-1:已删除;0:正常;1:已禁用;]'); + $table->dateTime('created_at')->nullable()->comment('注册时间'); + $table->dateTime('updated_at')->nullable()->comment('更新时间'); + + $table->charset = 'utf8'; + $table->collation = 'utf8_general_ci'; + $table->engine = 'InnoDB'; + }); + + $prefix = config('databases.default.prefix'); + Db::statement("ALTER TABLE `{$prefix}robots` comment '聊天机器人表'"); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('robots'); + } +} diff --git a/更新计划.md b/更新计划.md new file mode 100644 index 0000000..f76c3b8 --- /dev/null +++ b/更新计划.md @@ -0,0 +1,9 @@ +-- 更新计划 -- + +1. 修改 users 相关字段 ok + +2. 添加 robts 数据表及迁移文件 ok + +3. 修改表情相关数据表及相关接口 ok + +4.