From 9185eb073103c226b6dae1a0a5e28b4486750315 Mon Sep 17 00:00:00 2001 From: xiaochong0302 Date: Tue, 23 Jun 2020 20:28:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=B6=88=E6=81=AF=E7=9B=92?= =?UTF-8?q?=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Caches/ImHotGroupList.php | 1 + app/Caches/ImHotUserList.php | 4 +- .../Web/Controllers/MessengerController.php | 22 +- app/Http/Web/Services/Messenger.php | 221 ++++++++++++++++-- app/Http/Web/Views/messenger/find.volt | 5 +- app/Http/Web/Views/messenger/find_users.volt | 2 +- app/Models/ImSystemMessage.php | 127 ++++++++++ app/Repos/ImChatGroup.php | 3 + app/Repos/User.php | 12 + app/Validators/ImFriendUser.php | 54 ++++- config/errors.php | 6 +- .../layui/css/modules/layim/html/msgbox.html | 1 - public/static/web/css/common.css | 5 +- public/static/web/js/im.find.js | 50 ++-- public/static/web/js/im.js | 18 +- 15 files changed, 470 insertions(+), 61 deletions(-) create mode 100644 app/Models/ImSystemMessage.php diff --git a/app/Caches/ImHotGroupList.php b/app/Caches/ImHotGroupList.php index b17c2dcc..62b5d78d 100644 --- a/app/Caches/ImHotGroupList.php +++ b/app/Caches/ImHotGroupList.php @@ -48,6 +48,7 @@ class ImHotGroupList extends Cache 'name' => $group->name, 'avatar' => $group->avatar, 'about' => $group->about, + 'user_count' => $group->user_count, ]; } diff --git a/app/Caches/ImHotUserList.php b/app/Caches/ImHotUserList.php index 8662167c..1ae7f453 100644 --- a/app/Caches/ImHotUserList.php +++ b/app/Caches/ImHotUserList.php @@ -48,9 +48,11 @@ class ImHotUserList extends Cache 'name' => $user->name, 'avatar' => $user->avatar, 'about' => $user->about, - 'sign' => $user->sign, 'location' => $user->location, + 'gender' => $user->gender, 'vip' => $user->vip, + 'follower_count' => $user->follower_count, + 'following_count' => $user->following_count, ]; } diff --git a/app/Http/Web/Controllers/MessengerController.php b/app/Http/Web/Controllers/MessengerController.php index 0e0cc804..d58e8e5e 100644 --- a/app/Http/Web/Controllers/MessengerController.php +++ b/app/Http/Web/Controllers/MessengerController.php @@ -94,20 +94,26 @@ class MessengerController extends LayerController */ public function searchAction() { - $query = $this->request->getQuery('query', ['trim', 'string']); - $type = $this->request->getQuery('type', ['trim', 'string']); + $type = $this->request->getQuery('type'); + $query = $this->request->getQuery('query'); + $target = $this->request->getQuery('target'); + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); $service = new MessengerService(); if ($type == 'user') { - $pager = $service->searchUsers($query); $this->view->pick('messenger/find_users'); + $target = $target ?: 'tab-users'; + $pager = $service->searchUsers($query); } else { - $pager = $service->searchGroups($query); $this->view->pick('messenger/find_groups'); + $target = $target ?: 'tab-groups'; + $pager = $service->searchGroups($query); } $pager->items = kg_array_object($pager->items); + $pager->target = $target; $this->view->setVar('pager', $pager); } @@ -200,17 +206,17 @@ class MessengerController extends LayerController } /** - * @Post("/friend/approve", name="web.im.approve_friend") + * @Post("/friend/accept", name="web.im.accept_friend") */ - public function approveFriendAction() + public function acceptFriendAction() { } /** - * @Post("/group/approve", name="web.web.im.approve_group") + * @Post("/group/accept", name="web.web.im.accept_group") */ - public function approveGroupAction() + public function acceptGroupAction() { } diff --git a/app/Http/Web/Services/Messenger.php b/app/Http/Web/Services/Messenger.php index db74863e..195fc5af 100644 --- a/app/Http/Web/Services/Messenger.php +++ b/app/Http/Web/Services/Messenger.php @@ -8,12 +8,15 @@ use App\Caches\ImHotUserList as ImHotUserListCache; use App\Library\Paginator\Query as PagerQuery; use App\Models\ImFriendMessage as ImFriendMessageModel; use App\Models\ImFriendUser as ImFriendUserModel; +use App\Models\ImSystemMessage as ImSystemMessageModel; +use App\Models\User as UserModel; use App\Repos\ImChatGroup as ImChatGroupRepo; use App\Repos\ImFriendMessage as ImFriendMessageRepo; use App\Repos\ImFriendUser as ImFriendUserRepo; use App\Repos\ImGroupMessage as ImGroupMessageRepo; use App\Repos\User as UserRepo; use App\Validators\ImChatGroup as ImChatGroupValidator; +use App\Validators\ImFriendUser as ImFriendUserValidator; use App\Validators\ImMessage as ImMessageValidator; use App\Validators\User as UserValidator; use GatewayClient\Gateway; @@ -44,14 +47,42 @@ class Messenger extends Service ]; } - public function searchUsers($query) + public function searchUsers($name) { + $pagerQuery = new PagerQuery(); + $params = $pagerQuery->getParams(); + + $params['name'] = $name; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $userRepo = new UserRepo(); + + $pager = $userRepo->paginate($params, $sort, $page, $limit); + + return $this->handleUserPager($pager); } - public function searchGroups($query) + public function searchGroups($name) { + $pagerQuery = new PagerQuery(); + $params = $pagerQuery->getParams(); + + $params['name'] = $name; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $groupRepo = new ImChatGroupRepo(); + + $pager = $groupRepo->paginate($params, $sort, $page, $limit); + + return $this->handleGroupPager($pager); } public function getHotUsers() @@ -141,7 +172,7 @@ class Messenger extends Service $pager = $messageRepo->paginate($params, $sort, $page, $limit); - return $this->handleChatLog($pager); + return $this->handleChatLogPager($pager); } elseif ($params['type'] == 'group') { @@ -151,7 +182,7 @@ class Messenger extends Service $pager = $messageRepo->paginate($params, $sort, $page, $limit); - return $this->handleChatLog($pager); + return $this->handleChatLogPager($pager); } } @@ -207,7 +238,7 @@ class Messenger extends Service } $message = json_encode([ - 'type' => 'show_message', + 'type' => 'show_chat_msg', 'content' => $content, ]); @@ -256,13 +287,19 @@ class Messenger extends Service public function applyFriend() { - $friendId = $this->request->getPost('friend_id'); + $post = $this->request->getPost(); $user = $this->getLoginUser(); - $userValidator = new UserValidator(); + $validator = new ImFriendUserValidator(); - $friend = $userValidator->checkUser($friendId); + $friend = $validator->checkFriend($post['friend_id']); + $group = $validator->checkGroup($post['group_id']); + $remark = $validator->checkRemark($post['remark']); + + $validator->checkIfSelfApply($user->id, $friend->id); + $validator->checkIfJoined($user->id, $friend->id); + $validator->checkIfBlocked($user->id, $friend->id); $friendUserRepo = new ImFriendUserRepo(); @@ -272,23 +309,26 @@ class Messenger extends Service $model = new ImFriendUserModel(); $model->user_id = $user->id; $model->friend_id = $friend->id; + $model->group_id = $group->id; $model->create(); + } else { + $friendUser->group_id = $group->id; + $friendUser->update(); } - /** - * @todo 向对方发好友申请的系统消息 - */ + $this->handleApplyFriendNotice($user, $friend, $remark); } - public function approveFriend() + public function acceptFriend() { - $friendId = $this->request->getPost('friend_id'); + $post = $this->request->getPost(); $user = $this->getLoginUser(); - $userValidator = new UserValidator(); + $validator = new ImFriendUserValidator(); - $friend = $userValidator->checkUser($friendId); + $friend = $validator->checkFriend($post['friend_id']); + $group = $validator->checkGroup($post['group_id']); $friendUserRepo = new ImFriendUserRepo(); @@ -298,12 +338,11 @@ class Messenger extends Service $model = new ImFriendUserModel(); $model->user_id = $user->id; $model->friend_id = $friend->id; + $model->group_id = $group->id; $model->create(); } - /** - * @todo 向对方发通过好友申请的系统消息 - */ + $this->handleAcceptFriendNotice(); } public function refuseFriend() @@ -325,7 +364,7 @@ class Messenger extends Service { } - public function approveGroup() + public function acceptGroup() { } @@ -342,11 +381,20 @@ class Messenger extends Service $items = []; - $items[] = ['id' => 0, 'groupname' => '我的好友', 'list' => []]; + $items[] = [ + 'id' => 0, + 'groupname' => '我的好友', + 'list' => [], + ]; if ($friendGroups->count() > 0) { foreach ($friendGroups as $group) { - $items[] = ['id' => $group->id, 'groupname' => $group->name, 'online' => 0, 'list' => []]; + $items[] = [ + 'id' => $group->id, + 'groupname' => $group->name, + 'online' => 0, + 'list' => [], + ]; } } @@ -410,7 +458,7 @@ class Messenger extends Service return $result; } - protected function handleChatLog($pager) + protected function handleChatLogPager($pager) { if ($pager->total_items == 0) { return $pager; @@ -442,6 +490,135 @@ class Messenger extends Service return $pager; } + protected function handleUserPager($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $users = $pager->items->toArray(); + + $baseUrl = kg_ci_base_url(); + + $items = []; + + foreach ($users as $user) { + $user['avatar'] = $baseUrl . $user['avatar']; + $items[] = [ + 'id' => $user['id'], + 'name' => $user['name'], + 'avatar' => $user['avatar'], + 'about' => $user['about'], + 'location' => $user['location'], + 'gender' => $user['gender'], + 'vip' => $user['vip'], + 'follower_count' => $user['follower_count'], + 'following_count' => $user['following_count'], + ]; + } + + $pager->items = $items; + + return $pager; + } + + protected function handleGroupPager($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $groups = $pager->items->toArray(); + + $baseUrl = kg_ci_base_url(); + + $items = []; + + foreach ($groups as $group) { + $group['avatar'] = $baseUrl . $group['avatar']; + $items[] = [ + 'id' => $group['id'], + 'name' => $group['name'], + 'avatar' => $group['avatar'], + 'about' => $group['about'], + 'user_count' => $group['user_count'], + ]; + } + + $pager->items = $items; + + return $pager; + } + + protected function handleApplyFriendNotice(UserModel $user, UserModel $friend, $remark) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->user_id = $friend->id; + $sysMsgModel->item_id = $user->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_APPLY_FRIEND; + $sysMsgModel->item_info = [ + 'user' => ['id' => $user->id, 'name' => $user->name, 'avatar' => $user->avatar], + 'remark' => $remark, + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = '127.0.0.1:1238'; + + $online = Gateway::isUidOnline($friend->id); + + if ($online) { + + $userRepo = new UserRepo(); + + $msgCount = $userRepo->countUnreadImSystemMessages($friend->id); + + $message = kg_json_encode([ + 'type' => 'show_msg_box', + 'content' => ['msg_count' => $msgCount], + ]); + + Gateway::sendToUid($friend->id, $message); + } + } + + protected function handleAcceptFriendNotice(UserModel $user, UserModel $friend) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->user_id = $friend->id; + $sysMsgModel->item_id = $user->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_APPROVED; + $sysMsgModel->item_info = [ + 'user' => ['id' => $user->id, 'name' => $user->name, 'avatar' => $user->avatar], + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = '127.0.0.1:1238'; + + $online = Gateway::isUidOnline($friend->id); + + if ($online) { + + $userRepo = new UserRepo(); + + $msgCount = $userRepo->countUnreadImSystemMessages($friend->id); + + $message = kg_json_encode([ + 'type' => 'show_msg_box', + 'content' => ['msg_count' => $msgCount], + ]); + + Gateway::sendToUid($friend->id, $message); + } + } + + protected function handleRefuseFriendNotice() + { + } + protected function getGroupName($groupId) { return "group_{$groupId}"; diff --git a/app/Http/Web/Views/messenger/find.volt b/app/Http/Web/Views/messenger/find.volt index 91c3adee..e5efadd7 100644 --- a/app/Http/Web/Views/messenger/find.volt +++ b/app/Http/Web/Views/messenger/find.volt @@ -3,8 +3,9 @@ {% block content %} diff --git a/app/Http/Web/Views/messenger/find_users.volt b/app/Http/Web/Views/messenger/find_users.volt index e08d748f..66407483 100644 --- a/app/Http/Web/Views/messenger/find_users.volt +++ b/app/Http/Web/Views/messenger/find_users.volt @@ -9,7 +9,7 @@
{{ item.name }}
- 加为好友 + 加为好友
diff --git a/app/Models/ImSystemMessage.php b/app/Models/ImSystemMessage.php new file mode 100644 index 00000000..c16621cf --- /dev/null +++ b/app/Models/ImSystemMessage.php @@ -0,0 +1,127 @@ +addBehavior( + new SoftDelete([ + 'field' => 'deleted', + 'value' => 1, + ]) + ); + } + + public function beforeCreate() + { + $this->create_time = time(); + + if (!empty($this->item_info)) { + $this->item_info = kg_json_encode($this->item_info); + } else { + $this->item_info = ''; + } + } + + public function beforeUpdate() + { + $this->update_time = time(); + } + + public function afterFetch() + { + if (!empty($this->item_info)) { + $this->item_info = json_decode($this->item_info, true); + } + } + +} diff --git a/app/Repos/ImChatGroup.php b/app/Repos/ImChatGroup.php index 3dd954d3..79a3d1da 100644 --- a/app/Repos/ImChatGroup.php +++ b/app/Repos/ImChatGroup.php @@ -34,6 +34,9 @@ class ImChatGroup extends Repository } switch ($sort) { + case 'popular': + $orderBy = 'user_count DESC'; + break; default: $orderBy = 'id DESC'; break; diff --git a/app/Repos/User.php b/app/Repos/User.php index e7e4a67d..cb3c5453 100644 --- a/app/Repos/User.php +++ b/app/Repos/User.php @@ -7,6 +7,7 @@ use App\Models\ImChatGroup as ImChatGroupModel; use App\Models\ImChatGroupUser as ImChatGroupUserModel; use App\Models\ImFriendGroup as ImFriendGroupModel; use App\Models\ImFriendUser as ImFriendUserModel; +use App\Models\ImSystemMessage as ImSystemMessageModel; use App\Models\User as UserModel; use Phalcon\Mvc\Model; use Phalcon\Mvc\Model\Resultset; @@ -52,6 +53,9 @@ class User extends Repository } switch ($sort) { + case 'popular': + $orderBy = 'follower_count DESC'; + break; default: $orderBy = 'id DESC'; break; @@ -153,4 +157,12 @@ class User extends Repository ->getQuery()->execute(); } + public function countUnreadImSystemMessages($userId) + { + return ImSystemMessageModel::count([ + 'conditions' => 'user_id = ?1 AND viewed = ?2', + 'bind' => [1 => $userId, 2 => 0], + ]); + } + } diff --git a/app/Validators/ImFriendUser.php b/app/Validators/ImFriendUser.php index 224a0a82..5080ad16 100644 --- a/app/Validators/ImFriendUser.php +++ b/app/Validators/ImFriendUser.php @@ -3,11 +3,61 @@ namespace App\Validators; use App\Exceptions\BadRequest as BadRequestException; +use App\Models\ImFriendGroup as ImFriendGroupModel; +use App\Repos\ImFriendGroup as ImFriendGroupRepo; use App\Repos\ImFriendUser as ImFriendUserRepo; +use App\Repos\User as UserRepo; class ImFriendUser extends Validator { + public function checkFriend($id) + { + $repo = new UserRepo(); + + $user = $repo->findById($id); + + if (!$user) { + throw new BadRequestException('im_friend_user.user_not_found'); + } + + return $user; + } + + public function checkGroup($id) + { + /** + * 返回默认分组 + */ + if (empty($id)) { + $group = new ImFriendGroupModel(); + $group->id = 0; + $group->name = '我的好友'; + return $group; + } + + $repo = new ImFriendGroupRepo(); + + $group = $repo->findById($id); + + if (!$group) { + throw new BadRequestException('im_friend_user.group_not_found'); + } + + return $group; + } + + public function checkRemark($remark) + { + $value = $this->filter->sanitize($remark, ['trim', 'string']); + + $length = kg_strlen($value); + + if ($length > 30) { + throw new BadRequestException('im_friend_user.remark_too_long'); + } + } + public function checkIfSelfApply($userId, $friendId) { if ($userId == $friendId) { @@ -19,7 +69,7 @@ class ImFriendUser extends Validator { $repo = new ImFriendUserRepo(); - $record = $repo->findFriendUser($userId, $friendId); + $record = $repo->findFriendUser($friendId, $userId); if ($record && $record->blocked == 0) { throw new BadRequestException('im_friend_user.has_joined'); @@ -30,7 +80,7 @@ class ImFriendUser extends Validator { $repo = new ImFriendUserRepo(); - $record = $repo->findFriendUser($userId, $friendId); + $record = $repo->findFriendUser($friendId, $userId); if ($record && $record->blocked == 1) { throw new BadRequestException('im_friend_user.blocked'); diff --git a/config/errors.php b/config/errors.php index 4ac753b0..5a453244 100644 --- a/config/errors.php +++ b/config/errors.php @@ -340,11 +340,13 @@ $error['im_chat_group.name_too_long'] = '群组名太长(超过30字符)'; $error['im_chat_group.about_too_long'] = '群组简介太长(超过255字符)'; $error['im_chat_group_user.has_joined'] = '已经加入过群组'; -$error['im_chat_group_user.blocked'] = '被群组屏蔽'; +$error['im_chat_group_user.blocked'] = '对方拒绝接收消息'; +$error['im_friend_user.user_not_found'] = '用户不存在'; +$error['im_friend_user.remark_too_long'] = '验证信息太长(超过30字符)'; $error['im_friend_user.self_apply'] = '不能添加自己为好友'; $error['im_friend_user.has_joined'] = '已经是好友啦'; -$error['im_friend_user.blocked'] = '被对方屏蔽'; +$error['im_friend_user.blocked'] = '对方拒绝接收消息'; $error['im_message.not_found'] = '消息不存在'; $error['im_message.invalid_type'] = '无效的消息类型'; diff --git a/public/static/lib/layui/css/modules/layim/html/msgbox.html b/public/static/lib/layui/css/modules/layim/html/msgbox.html index 9e62b4e6..37a0771b 100644 --- a/public/static/lib/layui/css/modules/layim/html/msgbox.html +++ b/public/static/lib/layui/css/modules/layim/html/msgbox.html @@ -15,7 +15,6 @@ position: relative; margin-bottom: 10px; padding: 0 130px 10px 60px; - padding-bottom: 10px; line-height: 22px; border-bottom: 1px dotted #e2e2e2; } diff --git a/public/static/web/css/common.css b/public/static/web/css/common.css index 50999c9b..1448b815 100644 --- a/public/static/web/css/common.css +++ b/public/static/web/css/common.css @@ -1138,12 +1138,11 @@ } .learning-course-card .progress { - width: 260px; - padding: 15px 0 15px 5px; + padding-top: 15px; + padding-bottom: 10px; } .learning-course-card .duration { - padding: 0 5px; font-size: 12px; color: #666; } diff --git a/public/static/web/js/im.find.js b/public/static/web/js/im.find.js index 2628bb06..7feeba2a 100644 --- a/public/static/web/js/im.find.js +++ b/public/static/web/js/im.find.js @@ -1,25 +1,49 @@ -layui.use(['jquery', 'layer'], function () { +layui.use(['jquery', 'form', 'layer', 'layim'], function () { var $ = layui.jquery; + var form = layui.form; var layer = layui.layer; + var layim = layui.layim; - $('.apply-friend').on('click', function () { + form.on('submit(im_search)', function (data) { + var usersUrl = '/im/search?limit=12&target=tab-users&type=user&query=' + data.field.query; + var groupsUrl = '/im/search?limit=12&target=tab-groups&type=group&query=' + data.field.query; + layui.ajaxLoadHtml(usersUrl, 'tab-users'); + layui.ajaxLoadHtml(groupsUrl, 'tab-groups'); + return false; + }); + + $('body').on('click', '.apply-friend', function () { var friendId = $(this).attr('data-id'); - $.ajax({ - type: 'POST', - url: '/im/friend/apply', - data: {friend_id: friendId}, - success: function (res) { - layer.msg(res.msg, {icon: 1}); - }, - error: function (xhr) { - var res = JSON.parse(xhr.responseText); - layer.msg(res.msg, {icon: 2}); + var username = $(this).attr('data-name'); + var avatar = $(this).attr('data-avatar'); + layim.add({ + type: 'friend', + username: username, + avatar: avatar, + submit: function (groupId, remark, index) { + $.ajax({ + type: 'POST', + url: '/im/friend/apply', + data: { + friend_id: friendId, + group_id: groupId, + remark: remark + }, + success: function (res) { + layer.msg(res.msg, {icon: 1}); + }, + error: function (xhr) { + var res = JSON.parse(xhr.responseText); + layer.msg(res.msg, {icon: 2}); + } + }); + layer.close(index); } }); }); - $('.apply-group').on('click', function () { + $('body').on('click', '.apply-group', function () { var groupId = $(this).attr('data-id'); $.ajax({ type: 'POST', diff --git a/public/static/web/js/im.js b/public/static/web/js/im.js index a789c00a..168b1b4b 100644 --- a/public/static/web/js/im.js +++ b/public/static/web/js/im.js @@ -23,8 +23,10 @@ layui.use(['jquery', 'layim'], function () { socket.send('pong...'); } else if (data.type === 'bind_user') { bindUser(data.client_id); - } else if (data.type === 'show_message') { - showMessage(data.content); + } else if (data.type === 'show_chat_msg') { + showChatMessage(data.content); + } else if (data.type === 'show_msg_box') { + showMessageBox(data.content); } }; @@ -49,7 +51,7 @@ layui.use(['jquery', 'layim'], function () { }); layim.on('sendMessage', function (res) { - sendMessage(res.mine, res.to); + sendChatMessage(res.mine, res.to); }); layim.on('sign', function (sign) { @@ -68,7 +70,7 @@ layui.use(['jquery', 'layim'], function () { }); } - function sendMessage(from, to) { + function sendChatMessage(from, to) { $.ajax({ type: 'POST', url: '/im/msg/send', @@ -76,8 +78,12 @@ layui.use(['jquery', 'layim'], function () { }); } - function showMessage(message) { - layim.getMessage(message); + function showChatMessage(content) { + layim.getMessage(content); + } + + function showMessageBox(content) { + layim.msgbox(content.msg_count); } }); \ No newline at end of file