perf: 优化@提醒

This commit is contained in:
kuaifan 2022-04-16 09:45:57 +08:00
parent d5ac6fc0c7
commit 8893254664
12 changed files with 149 additions and 23 deletions

View File

@ -12,6 +12,7 @@ use App\Models\WebSocketDialogMsgRead;
use App\Models\WebSocketDialogUser;
use App\Module\Base;
use Carbon\Carbon;
use DB;
use Request;
use Response;
@ -145,11 +146,15 @@ class DialogController extends AbstractController
//
$dialog = WebSocketDialog::checkDialog($dialog_id);
//
$list = WebSocketDialogMsg::whereDialogId($dialog_id)->orderByDesc('id')->paginate(Base::getPaginate(100, 50));
$list->transform(function (WebSocketDialogMsg $item) use ($user) {
$item->is_read = $item->userid === $user->userid || WebSocketDialogMsgRead::whereMsgId($item->id)->whereUserid($user->userid)->value('read_at');
return $item;
});
$list = WebSocketDialogMsg::select([
'web_socket_dialog_msgs.*',
'read.mention',
'read.read_at',
])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) {
$leftJoin
->on('read.userid', '=', DB::raw($user->userid))
->on('read.msg_id', '=', 'web_socket_dialog_msgs.id');
})->where('web_socket_dialog_msgs.dialog_id', $dialog_id)->orderByDesc('web_socket_dialog_msgs.id')->paginate(Base::getPaginate(100, 50));
//
if ($dialog->type == 'group' && $dialog->group_type == 'task') {
$user->task_dialog_id = $dialog->id;

View File

@ -62,7 +62,9 @@ class WebSocketDialog extends AbstractModel
$last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
$this->last_msg = $last_msg;
// 未读信息
$this->unread = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null)->count();
$unreadBuilder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null);
$this->unread = $unreadBuilder->count();
$this->mention = $unreadBuilder->whereMention(1)->count();
$this->mark_unread = $this->mark_unread ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('mark_unread');
// 对话人数
$builder = WebSocketDialogUser::whereDialogId($this->id);

View File

@ -11,6 +11,7 @@ use Carbon\Carbon;
* @property int|null $dialog_id 对话ID
* @property int|null $msg_id 消息ID
* @property int|null $userid 发送会员ID
* @property int|null $mention 是否提及(被@
* @property int|null $after 在阅读之后才添加的记录
* @property string|null $read_at 阅读时间
* @property-read \App\Models\WebSocketDialogMsg|null $webSocketDialogMsg
@ -20,6 +21,7 @@ use Carbon\Carbon;
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereAfter($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereDialogId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMention($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereMsgId($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereReadAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead whereUserid($value)

View File

@ -48,30 +48,38 @@ class WebSocketDialogMsgTask extends AbstractTask
}
// 推送目标①:群成员
$array = [];
$userids = $dialog->dialogUser->pluck('userid')->toArray();
foreach ($userids AS $userid) {
if ($userid == $msg->userid) {
continue;
}
$mention = preg_match("/<span class=\"mention user\" data-id=\"[0|{$userid}]\">/", $msg->type === 'text' ? $msg->msg['text'] : '');
WebSocketDialogMsgRead::createInstance([
'dialog_id' => $msg->dialog_id,
'msg_id' => $msg->id,
'userid' => $userid,
'mention' => $mention,
])->saveOrIgnore();
$array[$userid] = $mention;
}
// 更新已发送数量
$msg->send = WebSocketDialogMsgRead::whereMsgId($msg->id)->count();
$msg->save();
// 开始推送消息
PushTask::push([
'userid' => $userids,
'ignoreFd' => $this->ignoreFd,
'msg' => [
'type' => 'dialog',
'mode' => 'add',
'data' => $msg->toArray(),
]
]);
foreach ($array as $userid => $mention) {
PushTask::push([
'userid' => $userid,
'ignoreFd' => $this->ignoreFd,
'msg' => [
'type' => 'dialog',
'mode' => 'add',
'data' => array_merge($msg->toArray(), [
'mention' => $mention,
]),
]
]);
}
// 推送目标②:正在打开这个任务会话的会员
if ($dialog->type == 'group' && $dialog->group_type == 'task') {

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWebSocketDialogMsgReadsMention extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
if (!Schema::hasColumn('web_socket_dialog_msg_reads', 'mention')) {
$table->boolean('mention')->default(0)->after('userid')->nullable()->comment('是否提及(被@');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) {
$table->dropColumn("mention");
});
}
}

View File

@ -367,6 +367,15 @@
getDialogUnread(dialog) {
return dialog ? (dialog.unread || dialog.mark_unread || 0) : 0
},
/**
* 返回对话@提及未读数量
* @param dialog
* @returns {*|number}
*/
getDialogMention(dialog) {
return dialog ? (dialog.mention || 0) : 0
}
});
/**

View File

@ -147,7 +147,7 @@
<li @click="toggleRoute('messenger')" :class="classNameRoute('messenger')">
<i class="taskfont">&#xe6eb;</i>
<div class="menu-title">{{$L('消息')}}</div>
<Badge class="menu-badge" :count="msgAllUnread"/>
<Badge class="menu-badge" :text="msgUnreadMention"/>
</li>
<li @click="toggleRoute('file')" :class="classNameRoute('file')">
<i class="taskfont">&#xe6f3;</i>
@ -497,13 +497,26 @@ export default {
...mapGetters(['taskData', 'dashboardTask']),
msgUnreadMention() {
let num = 0;
let mention = 0;
this.cacheDialogs.some(dialog => {
num += $A.getDialogUnread(dialog);
mention += $A.getDialogMention(dialog);
})
if (num <= 0) {
return '';
}
if (mention > 0) {
return `${num}·@${mention}`
}
return String(num);
},
msgAllUnread() {
let num = 0;
this.cacheDialogs.some(dialog => {
let unread = $A.getDialogUnread(dialog);
if (unread) {
num += unread;
}
num += $A.getDialogUnread(dialog);
})
return num;
},
@ -886,6 +899,8 @@ export default {
switch (type) {
case 'text':
body = msg.text;
body = body.replace(/<img src=".*?"\/>/g, `[${this.$L('图片')}]`)
body = body.replace(/<[^>]+>/g,"")
break;
case 'file':
body = '[' + this.$L(msg.type == 'img' ? '图片信息' : '文件信息') + ']'

View File

@ -141,6 +141,7 @@ export default {
allowedChars: /^\S*$/,
mentionDenotationChars: ["@", "#"],
defaultMenuOrientation: this.defaultMenuOrientation,
isolateCharacter: true,
renderItem: (data) => {
if (data.disabled === true) {
return `<div class="mention-item-disabled">${data.value}</div>`;

View File

@ -50,6 +50,7 @@
<Icon v-else class="icon-avatar" type="md-person" />
<div class="dialog-box">
<div class="dialog-title">
<div v-if="$A.getDialogMention(dialog) > 0" class="mention">[@{{$A.getDialogMention(dialog)}}]</div>
<template v-for="tag in $A.dialogTags(dialog)" v-if="tag.color != 'success'">
<Tag :color="tag.color" :fade="false">{{$L(tag.text)}}</Tag>
</template>

View File

@ -2122,13 +2122,16 @@ export default {
*/
dialogMsgRead({state, dispatch}, data) {
if (data.userid == state.userId) return;
if (data.is_read === true) return;
data.is_read = true;
if (data.read_at) return;
data.read_at = $A.formatDate();
//
let dialog = state.cacheDialogs.find(({id}) => id == data.dialog_id);
if (dialog && dialog.unread > 0) {
dialog.unread--
dialog.mark_unread = 0
dialog.unread--
if (data.mention) {
dialog.mention--
}
dispatch("saveDialog", dialog)
}
//
@ -2268,6 +2271,9 @@ export default {
if (dialog && state.cacheUnreads[data.id] === undefined) {
state.cacheUnreads[data.id] = true;
dialog.unread++;
if (data.mention) {
dialog.mention++;
}
dispatch("saveDialog", dialog)
}
}

View File

@ -48,6 +48,38 @@
min-width: 220px;
max-width: 350px;
max-height: 360px;
overflow-y: overlay;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(0, 0, 0, 0);
}
&::-webkit-scrollbar-thumb:active {
border-radius: 10px;
background: rgba(0, 0, 0, .5);
}
&:hover::-webkit-scrollbar-thumb {
border: 2px solid transparent;
background: rgba(0, 0, 0, .2);
background-clip: content-box;
}
&:hover::-webkit-scrollbar-thumb:hover {
border-top-width: 0;
border-bottom-width: 0;
}
&::-webkit-scrollbar-track {
border-radius: 10px;
background: rgba(0, 0, 0, 0);
}
.ql-mention-list {
> li {

View File

@ -126,6 +126,16 @@
align-items: center;
justify-content: space-between;
line-height: 24px;
.mention {
color: #ff0000;
background-color: transparent;
font-weight: 600;
flex-shrink: 0;
margin-right: 4px;
padding: 0;
height: auto;
width: auto;
}
.ivu-tag {
margin: 0 4px 0 0;
padding: 0 5px;
@ -170,6 +180,7 @@
align-items: center;
.common-avatar,
.last-self {
flex-shrink: 0;
padding-right: 4px;
margin-right: 4px;
position: relative;