1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-07-02 07:04:56 +08:00

完成未读消息,离线消息

This commit is contained in:
xiaochong0302 2020-07-01 19:45:28 +08:00
parent fc436d013f
commit b69bfb0471
24 changed files with 104 additions and 57 deletions

View File

@ -61,6 +61,7 @@ class Controller extends \Phalcon\Mvc\Controller
$this->view->setVar('site_navs', $this->siteNavs); $this->view->setVar('site_navs', $this->siteNavs);
$this->view->setVar('site_settings', $this->siteSettings); $this->view->setVar('site_settings', $this->siteSettings);
$this->view->setVar('auth_user', $this->authUser); $this->view->setVar('auth_user', $this->authUser);
$this->view->setVar('socket_url', $this->getSocketUrl());
} }
protected function getAuthUser() protected function getAuthUser()
@ -92,4 +93,11 @@ class Controller extends \Phalcon\Mvc\Controller
return new SiteSeo(); return new SiteSeo();
} }
protected function getSocketUrl()
{
$config = $this->getDI()->get('config');
return $config->websocket->url;
}
} }

View File

@ -27,9 +27,9 @@ class ImController extends LayerController
} }
/** /**
* @Get("/group/members", name="web.im.group_members") * @Get("/group/users", name="web.im.group_users")
*/ */
public function groupMembersAction() public function groupUsersAction()
{ {
$service = new ImService(); $service = new ImService();
@ -51,9 +51,9 @@ class ImController extends LayerController
} }
/** /**
* @Get("/msg/sys/unread/count", name="web.im.count_unread_sys_msg") * @Get("/msg/sys/unread/count", name="web.im.unread_sys_msg_count")
*/ */
public function countUnreadSystemMessagesAction() public function unreadSystemMessagesCountAction()
{ {
$service = new ImService(); $service = new ImService();
@ -62,18 +62,6 @@ class ImController extends LayerController
return $this->jsonSuccess(['count' => $count]); return $this->jsonSuccess(['count' => $count]);
} }
/**
* @Post("/msg/sys/read", name="web.im.read_sys_msg")
*/
public function readSystemMessagesAction()
{
$service = new ImService();
$service->readSystemMessages();
return $this->jsonSuccess();
}
/** /**
* @Get("/msg/box", name="web.im.msg_box") * @Get("/msg/box", name="web.im.msg_box")
*/ */
@ -83,7 +71,7 @@ class ImController extends LayerController
$pager = $service->getSystemMessages(); $pager = $service->getSystemMessages();
$this->view->pick('messenger/msg_box'); $this->view->pick('im/msg_box');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -98,10 +86,22 @@ class ImController extends LayerController
$pager->items = kg_array_object($pager->items); $pager->items = kg_array_object($pager->items);
$this->view->pick('messenger/sys_messages'); $this->view->pick('im/sys_messages');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
/**
* @Post("/msg/sys/read", name="web.im.read_sys_msg")
*/
public function readSystemMessagesAction()
{
$service = new ImService();
$service->readSystemMessages();
return $this->jsonSuccess();
}
/** /**
* @Get("/friend/status", name="web.im.friend_status") * @Get("/friend/status", name="web.im.friend_status")
*/ */
@ -124,7 +124,7 @@ class ImController extends LayerController
$pager = $service->getChatMessages(); $pager = $service->getChatMessages();
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
$this->view->pick('messenger/chat_log'); $this->view->pick('im/chat_log');
$this->view->setVar('pager', $pager); $this->view->setVar('pager', $pager);
} }
@ -171,11 +171,11 @@ class ImController extends LayerController
$service = new ImService(); $service = new ImService();
if ($type == 'user') { if ($type == 'user') {
$this->view->pick('messenger/find_users'); $this->view->pick('im/find_users');
$target = $target ?: 'tab-users'; $target = $target ?: 'tab-users';
$pager = $service->searchUsers($query); $pager = $service->searchUsers($query);
} else { } else {
$this->view->pick('messenger/find_groups'); $this->view->pick('im/find_groups');
$target = $target ?: 'tab-groups'; $target = $target ?: 'tab-groups';
$pager = $service->searchGroups($query); $pager = $service->searchGroups($query);
} }

View File

@ -10,6 +10,7 @@ use App\Models\ImFriendMessage as ImFriendMessageModel;
use App\Models\ImGroupMessage as ImGroupMessageModel; use App\Models\ImGroupMessage as ImGroupMessageModel;
use App\Models\User as UserModel; use App\Models\User as UserModel;
use App\Repos\ImFriendMessage as ImFriendMessageRepo; use App\Repos\ImFriendMessage as ImFriendMessageRepo;
use App\Repos\ImFriendUser as ImFriendUserRepo;
use App\Repos\ImGroup as ImGroupRepo; use App\Repos\ImGroup as ImGroupRepo;
use App\Repos\ImGroupMessage as ImGroupMessageRepo; use App\Repos\ImGroupMessage as ImGroupMessageRepo;
use App\Repos\ImSystemMessage as ImSystemMessageRepo; use App\Repos\ImSystemMessage as ImSystemMessageRepo;
@ -168,7 +169,7 @@ class Im extends Service
$userRepo = new UserRepo(); $userRepo = new UserRepo();
$messages = $userRepo->findUnreadImFriendMessages($user->id, $friend->id); $messages = $userRepo->findUnreadImFriendMessages($friend->id, $user->id);
if ($messages->count() == 0) { if ($messages->count() == 0) {
return; return;
@ -185,9 +186,9 @@ class Im extends Service
'message' => [ 'message' => [
'username' => $friend->name, 'username' => $friend->name,
'avatar' => $friend->avatar, 'avatar' => $friend->avatar,
'content' => $message->content,
'fromid' => $friend->id,
'id' => $friend->id, 'id' => $friend->id,
'fromid' => $friend->id,
'content' => $message->content,
'timestamp' => 1000 * $message->create_time, 'timestamp' => 1000 * $message->create_time,
'type' => 'friend', 'type' => 'friend',
'mine' => false, 'mine' => false,
@ -196,6 +197,12 @@ class Im extends Service
Gateway::sendToUid($user->id, $content); Gateway::sendToUid($user->id, $content);
} }
$repo = new ImFriendUserRepo();
$friendUser = $repo->findFriendUser($user->id, $friend->id);
$friendUser->update(['msg_count' => 0]);
} }
public function countUnreadSystemMessages() public function countUnreadSystemMessages()
@ -287,9 +294,7 @@ class Im extends Service
Gateway::$registerAddress = $this->getRegisterAddress(); Gateway::$registerAddress = $this->getRegisterAddress();
if (Gateway::isUidOnline($friend->id)) { $status = Gateway::isUidOnline($friend->id) ? 'online' : 'offline';
$status = 'online';
}
return $status; return $status;
} }
@ -384,7 +389,8 @@ class Im extends Service
if ($online) { if ($online) {
Gateway::sendToUid($to['id'], $content); Gateway::sendToUid($to['id'], $content);
} else { } else {
$relation->update(['msg_count' => $relation->msg_count + 1]); $msgCount = $relation->msg_count + 1;
$relation->update(['msg_count' => $msgCount]);
} }
} elseif ($to['type'] == 'group') { } elseif ($to['type'] == 'group') {
@ -403,8 +409,8 @@ class Im extends Service
$messageModel = new ImGroupMessageModel(); $messageModel = new ImGroupMessageModel();
$messageModel->create([ $messageModel->create([
'sender_id' => $from['id'],
'group_id' => $to['id'], 'group_id' => $to['id'],
'sender_id' => $from['id'],
'content' => $from['content'], 'content' => $from['content'],
]); ]);
@ -583,13 +589,19 @@ class Im extends Service
$userMappings = []; $userMappings = [];
/**
* 用户可以设置状态为 ['online', 'hide']
* 列表在线状态识别为 ['online', 'offline']
*/
foreach ($users as $user) { foreach ($users as $user) {
$status = $user->im['online']['status'] ?? 'offline';
$status = in_array($status, ['online', 'offline']) ? $status : 'offline';
$userMappings[$user->id] = [ $userMappings[$user->id] = [
'id' => $user->id, 'id' => $user->id,
'username' => $user->name, 'username' => $user->name,
'avatar' => $user->avatar, 'avatar' => $user->avatar,
'sign' => $user->im['sign'] ?? '', 'sign' => $user->im['sign'] ?? '',
'status' => $user->im['online']['status'] ?? 'offline', 'status' => $status,
]; ];
} }

View File

@ -17,10 +17,10 @@
</ul> </ul>
<div class="layui-tab-content"> <div class="layui-tab-content">
<div class="layui-tab-item layui-show" id="tab-users"> <div class="layui-tab-item layui-show" id="tab-users">
{{ partial('messenger/find_users',{'pager':users_pager}) }} {{ partial('im/find_users',{'pager':users_pager}) }}
</div> </div>
<div class="layui-tab-item" id="tab-groups"> <div class="layui-tab-item" id="tab-groups">
{{ partial('messenger/find_groups',{'pager':groups_pager}) }} {{ partial('im/find_groups',{'pager':groups_pager}) }}
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,14 @@
<script>
window.koogua = {
user: {
id: '{{ auth_user.id }}',
name: '{{ auth_user.name }}',
avatar: '{{ auth_user.avatar }}',
locked: '{{ auth_user.locked }}',
vip: '{{ auth_user.vip }}'
},
socketUrl: '{{ socket_url }}'
};
</script>

View File

@ -27,6 +27,7 @@
{{ partial('partials/footer') }} {{ partial('partials/footer') }}
</div> </div>
{{ partial('partials/js_global_vars') }}
{{ js_include('lib/layui/layui.js') }} {{ js_include('lib/layui/layui.js') }}
{{ js_include('web/js/common.js') }} {{ js_include('web/js/common.js') }}
{{ js_include('web/js/fixbar.js') }} {{ js_include('web/js/fixbar.js') }}

View File

@ -13,6 +13,7 @@
<body class="layer"> <body class="layer">
{% block content %}{% endblock %} {% block content %}{% endblock %}
{{ partial('partials/js_global_vars') }}
{{ js_include('lib/layui/layui.js') }} {{ js_include('lib/layui/layui.js') }}
{{ js_include('web/js/common.js') }} {{ js_include('web/js/common.js') }}

View File

@ -215,11 +215,9 @@ class Chapter extends Model
break; break;
} }
if (!empty($attrs)) {
$this->attrs = kg_json_encode($attrs); $this->attrs = kg_json_encode($attrs);
} }
} }
}
public function beforeUpdate() public function beforeUpdate()
{ {
@ -266,8 +264,6 @@ class Chapter extends Model
{ {
if (!empty($this->attrs) && is_string($this->attrs)) { if (!empty($this->attrs) && is_string($this->attrs)) {
$this->attrs = json_decode($this->attrs, true); $this->attrs = json_decode($this->attrs, true);
} else {
$this->attrs = [];
} }
} }

View File

@ -320,8 +320,6 @@ class Course extends Model
if (!empty($this->attrs) && is_string($this->attrs)) { if (!empty($this->attrs) && is_string($this->attrs)) {
$this->attrs = json_decode($this->attrs, true); $this->attrs = json_decode($this->attrs, true);
} else {
$this->attrs = [];
} }
} }

View File

@ -194,8 +194,6 @@ class Order extends Model
if (!empty($this->item_info) && is_string($this->item_info)) { if (!empty($this->item_info) && is_string($this->item_info)) {
$this->item_info = json_decode($this->item_info, true); $this->item_info = json_decode($this->item_info, true);
} else {
$this->item_info = [];
} }
} }

View File

@ -114,14 +114,14 @@ class Role extends Model
{ {
$this->update_time = time(); $this->update_time = time();
if (!empty($this->routes)) { if (is_array($this->routes)) {
$this->routes = kg_json_encode($this->routes); $this->routes = kg_json_encode($this->routes);
} }
} }
public function afterFetch() public function afterFetch()
{ {
if (!empty($this->routes)) { if (!empty($this->routes) && is_string($this->routes)) {
$this->routes = json_decode($this->routes, true); $this->routes = json_decode($this->routes, true);
} }
} }

View File

@ -120,8 +120,6 @@ class Task extends Model
{ {
if (!empty($this->item_info) && is_string($this->item_info)) { if (!empty($this->item_info) && is_string($this->item_info)) {
$this->item_info = json_decode($this->item_info, true); $this->item_info = json_decode($this->item_info, true);
} else {
$this->item_info = [];
} }
} }

View File

@ -220,8 +220,6 @@ class User extends Model
if (!empty($this->im) && is_string($this->im)) { if (!empty($this->im) && is_string($this->im)) {
$this->im = json_decode($this->im, true); $this->im = json_decode($this->im, true);
} else {
$this->im = [];
} }
} }

View File

@ -156,15 +156,15 @@ class User extends Repository
} }
/** /**
* @param int $userId
* @param int $friendId * @param int $friendId
* @param int $userId
* @return ResultsetInterface|Resultset|ImFriendMessageModel[] * @return ResultsetInterface|Resultset|ImFriendMessageModel[]
*/ */
public function findUnreadImFriendMessages($userId, $friendId) public function findUnreadImFriendMessages($friendId, $userId)
{ {
return ImFriendMessageModel::find([ return ImFriendMessageModel::find([
'conditions' => 'sender_id = ?1 AND receiver_id = ?2 AND viewed = ?3', 'conditions' => 'sender_id = ?1 AND receiver_id = ?2 AND viewed = ?3',
'bind' => [1 => $userId, 2 => $friendId, 3 => 0], 'bind' => [1 => $friendId, 2 => $userId, 3 => 0],
]); ]);
} }

View File

@ -37,6 +37,8 @@ class ImGroupUser extends Validator
if (!$record) { if (!$record) {
throw new BadRequestException('im_chat_group_user.not_found'); throw new BadRequestException('im_chat_group_user.not_found');
} }
return $record;
} }
public function checkIfJoined($userId, $groupId) public function checkIfJoined($userId, $groupId)

View File

@ -1415,3 +1415,11 @@
border-radius: 2px; border-radius: 2px;
font-size: 10px; font-size: 10px;
} }
.layim-chat-status .online {
color: green;
}
.layim-chat-status .offline {
color: gray;
}

View File

@ -2,7 +2,7 @@ layui.use(['jquery', 'layim'], function () {
var $ = layui.jquery; var $ = layui.jquery;
var layim = layui.layim; var layim = layui.layim;
var socket = new WebSocket('ws://127.0.0.1:8282'); var socket = new WebSocket(window.koogua.socketUrl);
socket.onopen = function () { socket.onopen = function () {
console.log('socket connect success'); console.log('socket connect success');
@ -48,7 +48,7 @@ layui.use(['jquery', 'layim'], function () {
url: '/im/init' url: '/im/init'
}, },
members: { members: {
url: '/im/group/members' url: '/im/group/users'
}, },
uploadImage: { uploadImage: {
url: '/im/img/upload' url: '/im/img/upload'
@ -63,7 +63,6 @@ layui.use(['jquery', 'layim'], function () {
}); });
layim.on('ready', function (options) { layim.on('ready', function (options) {
console.log(options.friend);
if (options.friend.length > 0) { if (options.friend.length > 0) {
layui.each(options.friend, function (i, group) { layui.each(options.friend, function (i, group) {
layui.each(group.list, function (j, user) { layui.each(group.list, function (j, user) {
@ -82,6 +81,9 @@ layui.use(['jquery', 'layim'], function () {
layim.on('chatChange', function (res) { layim.on('chatChange', function (res) {
resetChatMessageCount(res); resetChatMessageCount(res);
if (res.data.type === 'friend') {
setFriendStatus(res);
}
}); });
layim.on('online', function (status) { layim.on('online', function (status) {
@ -145,7 +147,8 @@ layui.use(['jquery', 'layim'], function () {
function resetChatMessageCount(res) { function resetChatMessageCount(res) {
var $tabMsgCount = $('.layim-chatlist-' + res.data.type + res.data.id + ' > .msg-count'); var $tabMsgCount = $('.layim-chatlist-' + res.data.type + res.data.id + ' > .msg-count');
var $listMsgCount = $('.layui-layim-list > .layim-friend' + res.data.id + ' > .msg-count'); var $listMsgCount = $('.layui-layim-list > .layim-friend' + res.data.id + ' > .msg-count');
if (res.data.type === 'friend' && $listMsgCount.text() !== '0') { var unreadListMsgCount = parseInt($listMsgCount.text());
if (res.data.type === 'friend' && unreadListMsgCount > 0) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/im/msg/friend/unread', url: '/im/msg/friend/unread',
@ -157,14 +160,24 @@ layui.use(['jquery', 'layim'], function () {
} }
function setFriendStatus(res) { function setFriendStatus(res) {
var date = new Date();
var lastQueryTime = parseInt($('#online-status-' + res.data.id).data('time'));
if (lastQueryTime > 0 && date.getTime() - lastQueryTime < 600000) {
return;
}
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/im/friend/status', url: '/im/friend/status',
data: {id: res.data.id}, data: {id: res.data.id},
success: function (data) { success: function (data) {
if (data.status === 'online') { if (data.status === 'online') {
layim.setChatStatus('<span style="color:green;">在线</span>'); layim.setChatStatus('<span id="online-status-' + res.data.id + '" class="online" data-time="' + date.getTime() + '">在线</span>');
layim.setFriendStatus(res.data.id, 'online'); layim.setFriendStatus(res.data.id, 'online');
} else if (data.status === 'offline') {
layim.setChatStatus('<span id="online-status-' + res.data.id + '" class="offline" data-time="' + date.getTime() + '">离线</span>');
layim.setFriendStatus(res.data.id, 'offline');
} else {
layim.setChatStatus('<span id="online-status-' + res.data.id + '" class="unknown" data-time="' + date.getTime() + '"></span>');
} }
} }
}); });

View File

@ -23,7 +23,7 @@ require_once dirname(__DIR__) . '/vendor/autoload.php';
$worker = new BusinessWorker(); $worker = new BusinessWorker();
// worker名称 // worker名称
$worker->name = 'CourseBusinessWorker'; $worker->name = 'ChatBusinessWorker';
// businessWorker进程数量 // businessWorker进程数量
$worker->count = 4; $worker->count = 4;

View File

@ -23,7 +23,7 @@ require_once dirname(__DIR__) . '/vendor/autoload.php';
$gateway = new Gateway("websocket://0.0.0.0:8282"); $gateway = new Gateway("websocket://0.0.0.0:8282");
// gateway名称status方便查看 // gateway名称status方便查看
$gateway->name = 'CourseGateway'; $gateway->name = 'ChatGateway';
// gateway进程数 // gateway进程数
$gateway->count = 4; $gateway->count = 4;