|
@@ -2,8 +2,10 @@
|
|
|
|
|
|
namespace App\Services;
|
|
namespace App\Services;
|
|
|
|
|
|
|
|
+use App\Model\DBCache;
|
|
use App\Module\Base;
|
|
use App\Module\Base;
|
|
use App\Module\Chat;
|
|
use App\Module\Chat;
|
|
|
|
+use App\Module\Users;
|
|
use Cache;
|
|
use Cache;
|
|
use DB;
|
|
use DB;
|
|
use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
|
|
use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
|
|
@@ -32,28 +34,30 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
*/
|
|
*/
|
|
public function onOpen(Server $server, Request $request)
|
|
public function onOpen(Server $server, Request $request)
|
|
{
|
|
{
|
|
|
|
+ global $_A;
|
|
|
|
+ $_A = [
|
|
|
|
+ '__static_langdata' => [],
|
|
|
|
+ ];
|
|
|
|
+ //
|
|
$to = $request->fd;
|
|
$to = $request->fd;
|
|
if (!isset($request->get['token'])) {
|
|
if (!isset($request->get['token'])) {
|
|
- $server->push($to, Base::array2json([
|
|
|
|
|
|
+ $server->push($to, $this->formatMsgSend([
|
|
'messageType' => 'error',
|
|
'messageType' => 'error',
|
|
'type' => 'user',
|
|
'type' => 'user',
|
|
- 'sender' => null,
|
|
|
|
- 'target' => null,
|
|
|
|
'content' => [
|
|
'content' => [
|
|
'error' => '参数错误'
|
|
'error' => '参数错误'
|
|
],
|
|
],
|
|
- 'time' => Base::time()
|
|
|
|
]));
|
|
]));
|
|
$server->close($to);
|
|
$server->close($to);
|
|
- self::forgetUser($to);
|
|
|
|
|
|
+ $this->forgetUser($to);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
//
|
|
$token = $request->get['token'];
|
|
$token = $request->get['token'];
|
|
- $cacheKey = "ws-token:" . md5($token);
|
|
|
|
|
|
+ $cacheKey = "ws::token:" . md5($token);
|
|
$username = Cache::remember($cacheKey, now()->addSeconds(1), function () use ($token) {
|
|
$username = Cache::remember($cacheKey, now()->addSeconds(1), function () use ($token) {
|
|
list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($token) . "@@@@");
|
|
list($id, $username, $encrypt, $timestamp) = explode("@", base64_decode($token) . "@@@@");
|
|
- if (intval($id) > 0 && intval($timestamp) + 2592000 > Base::time()) {
|
|
|
|
|
|
+ if (intval($id) > 0 && intval($timestamp) + 2592000 > time()) {
|
|
if (DB::table('users')->where(['id' => $id, 'username' => $username, 'encrypt' => $encrypt])->exists()) {
|
|
if (DB::table('users')->where(['id' => $id, 'username' => $username, 'encrypt' => $encrypt])->exists()) {
|
|
return $username;
|
|
return $username;
|
|
}
|
|
}
|
|
@@ -62,32 +66,58 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
});
|
|
});
|
|
if (empty($username)) {
|
|
if (empty($username)) {
|
|
Cache::forget($cacheKey);
|
|
Cache::forget($cacheKey);
|
|
- $server->push($to, Base::array2json([
|
|
|
|
|
|
+ $server->push($to, $this->formatMsgSend([
|
|
'messageType' => 'error',
|
|
'messageType' => 'error',
|
|
'type' => 'user',
|
|
'type' => 'user',
|
|
- 'sender' => null,
|
|
|
|
- 'target' => null,
|
|
|
|
'content' => [
|
|
'content' => [
|
|
'error' => '会员不存在',
|
|
'error' => '会员不存在',
|
|
],
|
|
],
|
|
- 'time' => Base::time()
|
|
|
|
]));
|
|
]));
|
|
$server->close($to);
|
|
$server->close($to);
|
|
- self::forgetUser($to);
|
|
|
|
|
|
+ $this->forgetUser($to);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
//
|
|
- self::saveUser($to, $username);
|
|
|
|
- $server->push($to, Base::array2json([
|
|
|
|
|
|
+ $wsid = $this->name2fd($username);
|
|
|
|
+ if ($wsid > 0) {
|
|
|
|
+ $server->push($wsid, $this->formatMsgSend([
|
|
|
|
+ 'messageType' => 'forced',
|
|
|
|
+ 'type' => 'user',
|
|
|
|
+ 'content' => [
|
|
|
|
+ 'ip' => Base::getIp(),
|
|
|
|
+ 'time' => time(),
|
|
|
|
+ 'new_wsid' => $to,
|
|
|
|
+ 'old_wsid' => $wsid,
|
|
|
|
+ ],
|
|
|
|
+ ]));
|
|
|
|
+ }
|
|
|
|
+ $this->saveUser($to, $username);
|
|
|
|
+ $server->push($to, $this->formatMsgSend([
|
|
'messageType' => 'open',
|
|
'messageType' => 'open',
|
|
'type' => 'user',
|
|
'type' => 'user',
|
|
- 'sender' => null,
|
|
|
|
- 'target' => null,
|
|
|
|
'content' => [
|
|
'content' => [
|
|
'swid' => $to,
|
|
'swid' => $to,
|
|
],
|
|
],
|
|
- 'time' => Base::time()
|
|
|
|
]));
|
|
]));
|
|
|
|
+ //
|
|
|
|
+ $lastMsg = Base::DBC2A(DB::table('chat_msg')->where('receive', $username)->orderByDesc('indate')->first());
|
|
|
|
+ if ($lastMsg && $lastMsg['roger'] === 0) {
|
|
|
|
+ $content = Base::string2array($lastMsg['message']);
|
|
|
|
+ $content['resend'] = 1;
|
|
|
|
+ $content['id'] = $lastMsg['id'];
|
|
|
|
+ $content['username'] = $lastMsg['username'];
|
|
|
|
+ $content['userimg'] = Users::userimg($lastMsg['username']);
|
|
|
|
+ $content['indate'] = $lastMsg['indate'];
|
|
|
|
+ $server->push($to, $this->formatMsgSend([
|
|
|
|
+ 'messageType' => 'send',
|
|
|
|
+ 'contentId' => $lastMsg['id'],
|
|
|
|
+ 'type' => 'user',
|
|
|
|
+ 'sender' => $lastMsg['username'],
|
|
|
|
+ 'target' => $lastMsg['receive'],
|
|
|
|
+ 'content' => $content,
|
|
|
|
+ 'time' => $lastMsg['indate'],
|
|
|
|
+ ]));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -102,17 +132,24 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
'__static_langdata' => [],
|
|
'__static_langdata' => [],
|
|
];
|
|
];
|
|
//
|
|
//
|
|
- $data = Base::json2array($frame->data);
|
|
|
|
|
|
+ $data = $this->formatMsgReceive($frame->data);
|
|
$feedback = [
|
|
$feedback = [
|
|
'status' => 1,
|
|
'status' => 1,
|
|
'message' => '',
|
|
'message' => '',
|
|
];
|
|
];
|
|
switch ($data['type']) {
|
|
switch ($data['type']) {
|
|
/**
|
|
/**
|
|
|
|
+ * 刷新
|
|
|
|
+ */
|
|
|
|
+ case 'refresh':
|
|
|
|
+ DB::table('users')->where('username', $this->fd2name($frame->fd))->update(['wsdate' => time()]);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /**
|
|
* 未读消息总数
|
|
* 未读消息总数
|
|
*/
|
|
*/
|
|
case 'unread':
|
|
case 'unread':
|
|
- $from = self::fd2name($frame->fd);
|
|
|
|
|
|
+ $from = $this->fd2name($frame->fd);
|
|
if ($from) {
|
|
if ($from) {
|
|
$num = intval(DB::table('chat_dialog')->where('user1', $from)->sum('unread1'));
|
|
$num = intval(DB::table('chat_dialog')->where('user1', $from)->sum('unread1'));
|
|
$num+= intval(DB::table('chat_dialog')->where('user2', $from)->sum('unread2'));
|
|
$num+= intval(DB::table('chat_dialog')->where('user2', $from)->sum('unread2'));
|
|
@@ -123,12 +160,12 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
break;
|
|
break;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 已读消息
|
|
|
|
|
|
+ * 已读会员消息
|
|
*/
|
|
*/
|
|
case 'read':
|
|
case 'read':
|
|
- $to = self::name2fd($data['target']);
|
|
|
|
|
|
+ $to = $this->name2fd($data['target']);
|
|
if ($to) {
|
|
if ($to) {
|
|
- $dialog = Chat::openDialog(self::fd2name($frame->fd), $data['target']);
|
|
|
|
|
|
+ $dialog = Chat::openDialog($this->fd2name($frame->fd), $data['target']);
|
|
if (!Base::isError($dialog)) {
|
|
if (!Base::isError($dialog)) {
|
|
$dialog = $dialog['data'];
|
|
$dialog = $dialog['data'];
|
|
$upArray = [];
|
|
$upArray = [];
|
|
@@ -144,21 +181,37 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
break;
|
|
break;
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * 收到信息回执
|
|
|
|
+ */
|
|
|
|
+ case 'roger':
|
|
|
|
+ if ($data['contentId'] > 0) {
|
|
|
|
+ DB::table('chat_msg')->where([
|
|
|
|
+ 'id' => $data['contentId'],
|
|
|
|
+ 'receive' => $this->fd2name($frame->fd),
|
|
|
|
+ ])->update([
|
|
|
|
+ 'roger' => 1,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /**
|
|
* 发给用户
|
|
* 发给用户
|
|
*/
|
|
*/
|
|
case 'user':
|
|
case 'user':
|
|
- $to = self::name2fd($data['target']);
|
|
|
|
- $res = Chat::saveMessage(self::fd2name($frame->fd), $data['target'], $data['content']);
|
|
|
|
|
|
+ $to = $this->name2fd($data['target']);
|
|
|
|
+ $res = Chat::saveMessage($this->fd2name($frame->fd), $data['target'], $data['content']);
|
|
if (Base::isError($res)) {
|
|
if (Base::isError($res)) {
|
|
$feedback = [
|
|
$feedback = [
|
|
'status' => 0,
|
|
'status' => 0,
|
|
'message' => $res['msg'],
|
|
'message' => $res['msg'],
|
|
];
|
|
];
|
|
} else {
|
|
} else {
|
|
- $data['content']['id'] = $res['data']['id'];
|
|
|
|
- $feedback['message'] = $res['data']['id'];
|
|
|
|
|
|
+ $contentId = $res['data']['id'];
|
|
|
|
+ $data['contentId'] = $contentId;
|
|
|
|
+ $data['content']['id'] = $contentId;
|
|
|
|
+ $feedback['message'] = $contentId;
|
|
if ($to) {
|
|
if ($to) {
|
|
- $server->push($to, Base::array2json($data));
|
|
|
|
|
|
+ $server->push($to, $this->formatMsgSend($data));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -167,21 +220,26 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
* 发给整个团队
|
|
* 发给整个团队
|
|
*/
|
|
*/
|
|
case 'team':
|
|
case 'team':
|
|
- foreach (self::getUsersAll() as $user) {
|
|
|
|
- $data['target'] = $user['username'];
|
|
|
|
- $server->push($user['wsid'], Base::array2json($data));
|
|
|
|
|
|
+ if (Base::val($data['content'], 'type') === 'taskA') {
|
|
|
|
+ $taskId = intval(Base::val($data['content'], 'taskDetail.id'));
|
|
|
|
+ if ($taskId > 0) {
|
|
|
|
+ $userLists = $this->getTaskUsers($taskId);
|
|
|
|
+ } else {
|
|
|
|
+ $userLists = $this->getTeamUsers();
|
|
|
|
+ }
|
|
|
|
+ foreach ($userLists as $user) {
|
|
|
|
+ $data['target'] = $user['username'];
|
|
|
|
+ $server->push($user['wsid'], $this->formatMsgSend($data));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
if ($data['messageId']) {
|
|
if ($data['messageId']) {
|
|
- $server->push($frame->fd, Base::array2json([
|
|
|
|
|
|
+ $server->push($frame->fd, $this->formatMsgSend([
|
|
'messageType' => 'feedback',
|
|
'messageType' => 'feedback',
|
|
'messageId' => $data['messageId'],
|
|
'messageId' => $data['messageId'],
|
|
'type' => 'user',
|
|
'type' => 'user',
|
|
- 'sender' => null,
|
|
|
|
- 'target' => null,
|
|
|
|
'content' => $feedback,
|
|
'content' => $feedback,
|
|
- 'time' => Base::time()
|
|
|
|
]));
|
|
]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -194,7 +252,7 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
*/
|
|
*/
|
|
public function onClose(Server $server, $fd, $reactorId)
|
|
public function onClose(Server $server, $fd, $reactorId)
|
|
{
|
|
{
|
|
- self::forgetUser($fd);
|
|
|
|
|
|
+ $this->forgetUser($fd);
|
|
}
|
|
}
|
|
|
|
|
|
/** ****************************************************************************** */
|
|
/** ****************************************************************************** */
|
|
@@ -202,49 +260,145 @@ class WebSocketService implements WebSocketHandlerInterface
|
|
/** ****************************************************************************** */
|
|
/** ****************************************************************************** */
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 缓存用户信息
|
|
|
|
|
|
+ * 格式化信息(来自接收)
|
|
|
|
+ * @param $data
|
|
|
|
+ * @return array
|
|
|
|
+ */
|
|
|
|
+ private function formatMsgReceive($data) {
|
|
|
|
+ return $this->formatMsgData(Base::json2array($data));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 格式化信息(用于发送)
|
|
|
|
+ * @param $array
|
|
|
|
+ * @return string
|
|
|
|
+ */
|
|
|
|
+ private function formatMsgSend($array) {
|
|
|
|
+ return Base::array2json($this->formatMsgData($array));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 格式化信息
|
|
|
|
+ * @param array $array
|
|
|
|
+ * @return array
|
|
|
|
+ */
|
|
|
|
+ private function formatMsgData($array = []) {
|
|
|
|
+ if (!is_array($array)) {
|
|
|
|
+ $array = [];
|
|
|
|
+ }
|
|
|
|
+ if (!isset($array['messageType'])) $array['messageType'] = '';
|
|
|
|
+ if (!isset($array['messageId'])) $array['messageId'] = '';
|
|
|
|
+ if (!isset($array['contentId'])) $array['contentId'] = 0;
|
|
|
|
+ if (!isset($array['type'])) $array['type'] = '';
|
|
|
|
+ if (!isset($array['sender'])) $array['sender'] = null;
|
|
|
|
+ if (!isset($array['target'])) $array['target'] = null;
|
|
|
|
+ if (!isset($array['content'])) $array['content'] = [];
|
|
|
|
+ if (!isset($array['time'])) $array['time'] = time();
|
|
|
|
+ if (!is_array($array['content'])) $array['content'] = [];
|
|
|
|
+ $array['contentId'] = intval($array['contentId']);
|
|
|
|
+ return $array;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 保存用户wsid
|
|
* @param $fd
|
|
* @param $fd
|
|
* @param $username
|
|
* @param $username
|
|
*/
|
|
*/
|
|
- public static function saveUser($fd, $username)
|
|
|
|
|
|
+ private function saveUser($fd, $username)
|
|
{
|
|
{
|
|
- DB::table('users')->where('wsid', $fd)->update(['wsid' => 0]);
|
|
|
|
- DB::table('users')->where('username', $username)->update(['wsid' => $fd]);
|
|
|
|
|
|
+ $this->forgetUser($fd);
|
|
|
|
+ $this->forgetName($username);
|
|
|
|
+ DB::table('users')->where('username', $username)->update(['wsid' => $fd, 'wsdate' => time()]);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 清除用户缓存
|
|
|
|
|
|
+ * 清除用户wsid
|
|
* @param $fd
|
|
* @param $fd
|
|
*/
|
|
*/
|
|
- public static function forgetUser($fd)
|
|
|
|
|
|
+ private function forgetUser($fd)
|
|
{
|
|
{
|
|
|
|
+ $this->forgetFd($fd);
|
|
DB::table('users')->where('wsid', $fd)->update(['wsid' => 0]);
|
|
DB::table('users')->where('wsid', $fd)->update(['wsid' => 0]);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 获取当前用户
|
|
|
|
|
|
+ * 根据wsid清除缓存
|
|
|
|
+ * @param $fd
|
|
|
|
+ */
|
|
|
|
+ private function forgetFd($fd) {
|
|
|
|
+ Cache::forget('ws::name:' . $this->fd2name($fd));
|
|
|
|
+ Cache::forget('ws::fd:' . $fd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据username清除缓存
|
|
|
|
+ * @param $username
|
|
|
|
+ */
|
|
|
|
+ private function forgetName($username) {
|
|
|
|
+ Cache::forget('ws::fd:' . $this->name2fd($username));
|
|
|
|
+ Cache::forget('ws::name:' . $username);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取团队用户
|
|
* @return array|string
|
|
* @return array|string
|
|
*/
|
|
*/
|
|
- public static function getUsersAll()
|
|
|
|
|
|
+ private function getTeamUsers()
|
|
|
|
+ {
|
|
|
|
+ return Base::DBC2A(DB::table('users')->select(['wsid', 'username'])->where([
|
|
|
|
+ ['wsid', '>', 0],
|
|
|
|
+ ['wsdate', '>', time() - 600],
|
|
|
|
+ ])->get());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取跟任务有关系的用户(关注的、在项目里的、负责人、创建者)
|
|
|
|
+ * @param $taskId
|
|
|
|
+ * @return array
|
|
|
|
+ */
|
|
|
|
+ private function getTaskUsers($taskId)
|
|
{
|
|
{
|
|
- return Base::DBC2A(DB::table('users')->select(['wsid', 'username'])->where('wsid', '>', 0)->get());
|
|
|
|
|
|
+ $taskDeatil = Base::DBC2A(DB::table('project_task')->select(['follower', 'createuser', 'username', 'projectid'])->where('id', $taskId)->first());
|
|
|
|
+ if (empty($taskDeatil)) {
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+ //关注的用户
|
|
|
|
+ $userArray = Base::string2array($taskDeatil['follower']);
|
|
|
|
+ //创建者
|
|
|
|
+ $userArray[] = $taskDeatil['createuser'];
|
|
|
|
+ //负责人
|
|
|
|
+ $userArray[] = $taskDeatil['username'];
|
|
|
|
+ //在项目里的用户
|
|
|
|
+ if ($taskDeatil['projectid'] > 0) {
|
|
|
|
+ $tempLists = Base::DBC2A(DB::table('project_users')->select(['username'])->where(['projectid' => $taskDeatil['projectid'], 'type' => '成员' ])->get());
|
|
|
|
+ foreach ($tempLists AS $item) {
|
|
|
|
+ $userArray[] = $item['username'];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //
|
|
|
|
+ return Base::DBC2A(DB::table('users')->select(['wsid', 'username'])->where([
|
|
|
|
+ ['wsid', '>', 0],
|
|
|
|
+ ['wsdate', '>', time() - 600],
|
|
|
|
+ ])->whereIn('username', array_values(array_unique($userArray)))->get());
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * wsid获取用户名
|
|
* @param $fd
|
|
* @param $fd
|
|
* @return mixed
|
|
* @return mixed
|
|
*/
|
|
*/
|
|
- public static function fd2name($fd)
|
|
|
|
|
|
+ private function fd2name($fd)
|
|
{
|
|
{
|
|
- return DB::table('users')->select(['username'])->where('wsid', $fd)->value('username');
|
|
|
|
|
|
+ return DBCache::table('users')->cacheKeyname('ws::fd:' . $fd)->select(['username'])->where('wsid', $fd)->value('username');
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * 用户名获取wsid
|
|
* @param $username
|
|
* @param $username
|
|
* @return mixed
|
|
* @return mixed
|
|
*/
|
|
*/
|
|
- public static function name2fd($username)
|
|
|
|
|
|
+ private function name2fd($username)
|
|
{
|
|
{
|
|
- return DB::table('users')->select(['wsid'])->where('username', $username)->value('wsid');
|
|
|
|
|
|
+ return DBCache::table('users')->cacheKeyname('ws::name:' . $username)->select(['wsid'])->where('username', $username)->value('wsid');
|
|
}
|
|
}
|
|
}
|
|
}
|