From 20b8ef81320fb51b4649bdfb385289f07b274844 Mon Sep 17 00:00:00 2001 From: xiaochong0302 Date: Sat, 4 Jul 2020 19:48:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=9B=B4=E6=92=AD=E8=81=8A?= =?UTF-8?q?=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Web/Controllers/LiveController.php | 26 ++++- app/Http/Web/Services/Live.php | 117 +++++++++++++------- app/Http/Web/Views/chapter/live_chats.volt | 9 ++ app/Http/Web/Views/chapter/live_stats.volt | 21 +--- app/Http/Web/Views/chapter/show_live.volt | 43 +++---- app/Http/Web/Views/chapter/show_vod.volt | 6 +- app/Http/Web/Views/partials/header.volt | 2 +- public/static/web/css/common.css | 56 +++++++++- public/static/web/js/live.im.js | 56 +++++++--- public/static/web/js/live.player.js | 2 +- public/static/web/js/vod.player.js | 2 +- 11 files changed, 234 insertions(+), 106 deletions(-) create mode 100644 app/Http/Web/Views/chapter/live_chats.volt diff --git a/app/Http/Web/Controllers/LiveController.php b/app/Http/Web/Controllers/LiveController.php index afa219c9..d4c88e56 100644 --- a/app/Http/Web/Controllers/LiveController.php +++ b/app/Http/Web/Controllers/LiveController.php @@ -14,6 +14,20 @@ class LiveController extends Controller use ResponseTrait; + /** + * @Get("/{id:[0-9]+}/chats", name="web.live.chats") + */ + public function chatsAction($id) + { + $service = new LiveService(); + + $chats = $service->getRecentChats($id); + + $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); + $this->view->pick('chapter/live_chats'); + $this->view->setVar('chats', $chats); + } + /** * @Get("/{id:[0-9]+}/stats", name="web.live.stats") */ @@ -29,9 +43,9 @@ class LiveController extends Controller } /** - * @Post("/{id:[0-9]+}/bind", name="web.live.bind") + * @Post("/{id:[0-9]+}/user/bind", name="web.live.bind_user") */ - public function bindAction($id) + public function bindUserAction($id) { $service = new LiveService(); @@ -41,15 +55,15 @@ class LiveController extends Controller } /** - * @Post("/{id:[0-9]+}/message", name="web.live.message") + * @Post("/{id:[0-9]+}/msg/send", name="web.live.send_msg") */ - public function messageAction($id) + public function sendMessageAction($id) { $service = new LiveService(); - $service->sendMessage($id); + $response = $service->sendMessage($id); - return $this->jsonSuccess(); + return $this->jsonSuccess($response); } } diff --git a/app/Http/Web/Services/Live.php b/app/Http/Web/Services/Live.php index 061e9abe..19cc4e4f 100644 --- a/app/Http/Web/Services/Live.php +++ b/app/Http/Web/Services/Live.php @@ -2,7 +2,7 @@ namespace App\Http\Web\Services; -use App\Repos\User as UserRepo; +use App\Library\Cache\Backend\Redis as RedisCache; use App\Services\Frontend\ChapterTrait; use GatewayClient\Gateway; @@ -11,6 +11,25 @@ class Live extends Service use ChapterTrait; + public function getRecentChats($id) + { + $redis = $this->getRedis(); + + $key = $this->getRedisListKey($id); + + $items = $redis->lRange($key, 0, 10); + + $result = []; + + if ($items) { + foreach (array_reverse($items) as $item) { + $result[] = json_decode($item, true); + } + } + + return $result; + } + public function getStats($id) { $chapter = $this->checkChapterCache($id); @@ -23,14 +42,10 @@ class Live extends Service $userCount = Gateway::getUidCountByGroup($groupName); $guestCount = $clientCount - $userCount; - $userIds = Gateway::getUidListByGroup($groupName); - - $users = $this->handleUsers($userIds); - return [ + 'client_count' => $clientCount, 'user_count' => $userCount, 'guest_count' => $guestCount, - 'users' => $users, ]; } @@ -46,11 +61,23 @@ class Live extends Service Gateway::$registerAddress = $this->getRegisterAddress(); - if ($user->id > 0) { - Gateway::bindUid($clientId, $user->id); - } - Gateway::joinGroup($clientId, $groupName); + + if ($user->id > 0) { + + Gateway::bindUid($clientId, $user->id); + + $message = kg_json_encode([ + 'type' => 'new_user', + 'user' => [ + 'id' => $user->id, + 'name' => $user->name, + 'vip' => $user->vip, + ], + ]); + + Gateway::sendToGroup($groupName, $message, $clientId); + } } public function sendMessage($id) @@ -59,52 +86,41 @@ class Live extends Service $user = $this->getLoginUser(); + $content = $this->request->getPost('content', ['trim', 'striptags']); + + $content = kg_substr($content, 0, 150); + Gateway::$registerAddress = $this->getRegisterAddress(); $groupName = $this->getGroupName($chapter->id); - $excludeClientId = Gateway::getClientIdByUid($user->id); + $clientId = Gateway::getClientIdByUid($user->id); - $message = json_encode([ - 'type' => 'show_message', + $message = [ + 'type' => 'new_message', 'user' => [ 'id' => $user->id, 'name' => $user->name, - 'avatar' => $user->avatar, + 'vip' => $user->vip, ], - ]); + 'content' => $content, + ]; - Gateway::sendToGroup($groupName, $message, $excludeClientId); + $encodeMessage = kg_json_encode($message); + + Gateway::sendToGroup($groupName, $encodeMessage, $clientId); + + $redis = $this->getRedis(); + $key = $this->getRedisListKey($id); + $redis->lPush($key, $encodeMessage); + $redis->lTrim($key, 0, 10); + + return $message; } - protected function handleUsers($userIds) + protected function getGroupName($id) { - if (!$userIds) return []; - - $userRepo = new UserRepo(); - - $users = $userRepo->findByIds($userIds); - - $baseUrl = kg_ci_base_url(); - - $result = []; - - foreach ($users->toArray() as $key => $user) { - $user['avatar'] = $baseUrl . $user['avatar']; - $result[] = [ - 'id' => $user['id'], - 'name' => $user['name'], - 'vip' => $user['vip'], - 'avatar' => $user['avatar'], - ]; - } - - return $result; - } - - protected function getGroupName($groupId) - { - return "live_{$groupId}"; + return "live_{$id}"; } protected function getRegisterAddress() @@ -114,4 +130,19 @@ class Live extends Service return $config->websocket->register_address; } + protected function getRedisListKey($id) + { + return "live_recent_chat:{$id}"; + } + + protected function getRedis() + { + /** + * @var RedisCache $cache + */ + $cache = $this->getDI()->get('cache'); + + return $cache->getRedis(); + } + } diff --git a/app/Http/Web/Views/chapter/live_chats.volt b/app/Http/Web/Views/chapter/live_chats.volt new file mode 100644 index 00000000..47bb3675 --- /dev/null +++ b/app/Http/Web/Views/chapter/live_chats.volt @@ -0,0 +1,9 @@ +{% for chat in chats %} +
+ {% if chat.user.vip == 0 %} + + {% endif %} + {{ chat.user.name }} + {{ chat.content }} +
+{% endfor %} \ No newline at end of file diff --git a/app/Http/Web/Views/chapter/live_stats.volt b/app/Http/Web/Views/chapter/live_stats.volt index 80924165..6ee69c02 100644 --- a/app/Http/Web/Views/chapter/live_stats.volt +++ b/app/Http/Web/Views/chapter/live_stats.volt @@ -1,17 +1,6 @@ -
-
在线成员
-
-
- 用户:{{ stats.user_count }} - 游客:{{ stats.guest_count }} -
-
- {% for user in stats.users %} - {% set vip_flag = user.vip ? 'vip' : '' %} -
-
{{ user.name }} {{ vip_flag }}
-
- {% endfor %} -
+
+
+ 登录:{{ stats.user_count }} 人 + 游客:{{ stats.guest_count }} 人
-
+
\ No newline at end of file diff --git a/app/Http/Web/Views/chapter/show_live.volt b/app/Http/Web/Views/chapter/show_live.volt index e99b0530..03ef0ef5 100644 --- a/app/Http/Web/Views/chapter/show_live.volt +++ b/app/Http/Web/Views/chapter/show_live.volt @@ -2,13 +2,16 @@ {% block content %} - {% set course_url = url({'for':'web.course.show','id':chapter.course.id}) %} {% set learning_url = url({'for':'web.chapter.learning','id':chapter.id}) %} - {% set stats_url = url({'for':'web.live.stats','id':chapter.id}) %} + {% set live_chats_url = url({'for':'web.live.chats','id':chapter.id}) %} + {% set live_stats_url = url({'for':'web.live.stats','id':chapter.id}) %} + {% set send_msg_url = url({'for':'web.live.send_msg','id':chapter.id}) %} + {% set bind_user_url = url({'for':'web.live.bind_user','id':chapter.id}) %} @@ -19,35 +22,35 @@
-
-
    -
  • 讨论
  • -
  • 成员
  • -
-
-
-
-
-
- - -
+
+
+
    +
  • 讨论
  • +
  • 统计
  • +
+
+
+
+
+
+ + +
+
+
-
- - - +
{% endblock %} diff --git a/app/Http/Web/Views/chapter/show_vod.volt b/app/Http/Web/Views/chapter/show_vod.volt index ac19621e..63e4b31f 100644 --- a/app/Http/Web/Views/chapter/show_vod.volt +++ b/app/Http/Web/Views/chapter/show_vod.volt @@ -7,7 +7,8 @@ @@ -22,9 +23,6 @@
- - - diff --git a/app/Http/Web/Views/partials/header.volt b/app/Http/Web/Views/partials/header.volt index f61a9490..e2aa1762 100644 --- a/app/Http/Web/Views/partials/header.volt +++ b/app/Http/Web/Views/partials/header.volt @@ -23,7 +23,7 @@ diff --git a/public/static/web/css/common.css b/public/static/web/css/common.css index de2691a7..da2cb3da 100644 --- a/public/static/web/css/common.css +++ b/public/static/web/css/common.css @@ -757,7 +757,60 @@ height: 428px; } +.chat-container { + padding: 10px 20px 20px 20px; + background-color: white; +} + +.vip-icon { + color: orange; +} + +.chat-msg-list { + height: 380px; + margin-bottom: 10px; + overflow-y: auto; +} + +.chat-msg-list::-webkit-scrollbar { + width: 5px; +} + +.chat-msg-list::-webkit-scrollbar-thumb { + border-radius: 10px; + background: rgba(0, 0, 0, 0.1); +} + +.chat-msg-list .chat, .chat-msg-list .chat-sys { + margin-bottom: 10px; + line-height: 25px; + word-break: break-all; +} + +.chat-sys { + color: #999; +} + +.chat-sys span, .chat span { + margin-right: 5px; +} + +.chat .user { + color: orange; +} + +.chat .content { + color: #666; +} + +.chat-msg-form .layui-input { + height: 32px; + font-size: 12px; + color: #666; +} + .live-stats { + height: 420px; color: #666; } @@ -770,7 +823,8 @@ } .live-user-card { - line-height: 30px; + margin-bottom: 10px; + line-height: 25px; } .chat-login-tips { diff --git a/public/static/web/js/live.im.js b/public/static/web/js/live.im.js index 04ea2f35..6acc035b 100644 --- a/public/static/web/js/live.im.js +++ b/public/static/web/js/live.im.js @@ -1,9 +1,11 @@ -layui.use(['jquery', 'helper'], function () { +layui.use(['jquery', 'form', 'helper'], function () { var $ = layui.jquery; + var form = layui.form; var helper = layui.helper; var socket = new WebSocket(window.koogua.socketUrl); - + var bindUserUrl = $('input[name="bind_user_url"]').val(); + var $chatContent = $('input[name=content]'); var $chatMsgList = $('#chat-msg-list'); socket.onopen = function () { @@ -25,8 +27,10 @@ layui.use(['jquery', 'helper'], 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 === 'new_message') { + showNewMessage(data); + } else if (data.type === 'new_user') { + showLoginMessage(data); } }; @@ -36,38 +40,64 @@ layui.use(['jquery', 'helper'], function () { url: data.form.action, data: data.field, success: function (res) { - showMessage(res); + showNewMessage(res); + $chatContent.val(''); } }); return false; }); + loadRecentChats(); + refreshLiveStats(); - setInterval('refreshLiveStats()', 60000); + setInterval(function () { + refreshLiveStats(); + }, 300000); function bindUser(clientId) { $.ajax({ type: 'POST', - url: '/live/bind', + url: bindUserUrl, data: {client_id: clientId} }); } - function showMessage(res) { + function showNewMessage(res) { var html = '
'; - html += '' + res.user.name + ''; - if (res.user.vip === 1) { - html += 'VIP'; + if (res.user.vip === 0) { + html += ''; } + html += '' + res.user.name + ':'; html += '' + res.content + ''; html += '
'; $chatMsgList.append(html); + scrollToBottom(); + } + + function showLoginMessage(res) { + var html = '
'; + html += '' + res.user.name + ''; + html += '进入了直播间'; + html += '
'; + $chatMsgList.append(html); + scrollToBottom(); + } + + function scrollToBottom() { + var $scrollTo = $chatMsgList.find('.chat:last'); + $chatMsgList.scrollTop( + $scrollTo.offset().top - $chatMsgList.offset().top + $chatMsgList.scrollTop() + ); } function refreshLiveStats() { - var $liveStats = $('#live-stats'); - helper.ajaxLoadHtml($liveStats.data('url'), $liveStats.attr('id')); + var $tabStats = $('#tab-stats'); + helper.ajaxLoadHtml($tabStats.data('url'), $tabStats.attr('id')); + } + + function loadRecentChats() { + helper.ajaxLoadHtml($chatMsgList.data('url'), $chatMsgList.attr('id')); } }); \ No newline at end of file diff --git a/public/static/web/js/live.player.js b/public/static/web/js/live.player.js index 86166b04..6a73eba6 100644 --- a/public/static/web/js/live.player.js +++ b/public/static/web/js/live.player.js @@ -6,9 +6,9 @@ layui.use(['jquery', 'helper'], function () { var interval = null; var intervalTime = 5000; var position = 0; + var userId = window.koogua.user.id; var chapterId = $('input[name="chapter.id"]').val(); var planId = $('input[name="chapter.plan_id"]').val(); - var userId = $('input[name="user.id"]').val(); var learningUrl = $('input[name="chapter.learning_url"]').val(); var playUrls = JSON.parse($('input[name="chapter.play_urls"]').val()); var requestId = helper.getRequestId(); diff --git a/public/static/web/js/vod.player.js b/public/static/web/js/vod.player.js index 6f1cf7b1..f37afbfa 100644 --- a/public/static/web/js/vod.player.js +++ b/public/static/web/js/vod.player.js @@ -6,9 +6,9 @@ layui.use(['jquery', 'helper'], function () { var interval = null; var intervalTime = 5000; var position = 0; + var userId = window.koogua.user.id; var chapterId = $('input[name="chapter.id"]').val(); var planId = $('input[name="chapter.plan_id"]').val(); - var userId = $('input[name="user.id"]').val(); var learningUrl = $('input[name="chapter.learning_url"]').val(); var playUrls = JSON.parse($('input[name="chapter.play_urls"]').val()); var requestId = helper.getRequestId();