From 88932546646427da5acaff91a8176afc6877f9d7 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Sat, 16 Apr 2022 09:45:57 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96@=E6=8F=90=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 15 +++++--- app/Models/WebSocketDialog.php | 4 ++- app/Models/WebSocketDialogMsgRead.php | 2 ++ app/Tasks/WebSocketDialogMsgTask.php | 26 +++++++++----- ...dd_web_socket_dialog_msg_reads_mention.php | 34 +++++++++++++++++++ resources/assets/js/functions/web.js | 9 +++++ resources/assets/js/pages/manage.vue | 25 +++++++++++--- .../js/pages/manage/components/ChatInput.vue | 1 + .../assets/js/pages/manage/messenger.vue | 1 + resources/assets/js/store/actions.js | 12 +++++-- .../sass/pages/components/chat-input.scss | 32 +++++++++++++++++ .../assets/sass/pages/page-messenger.scss | 11 ++++++ 12 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 database/migrations/2022_04_16_073635_add_web_socket_dialog_msg_reads_mention.php diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 490d3aa77..643efcd3a 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -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; diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index b8fd44dde..21e310360 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -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); diff --git a/app/Models/WebSocketDialogMsgRead.php b/app/Models/WebSocketDialogMsgRead.php index 687e1be40..e0406bdb1 100644 --- a/app/Models/WebSocketDialogMsgRead.php +++ b/app/Models/WebSocketDialogMsgRead.php @@ -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) diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index b8dbb2b50..2dcc628fa 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -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("//", $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') { diff --git a/database/migrations/2022_04_16_073635_add_web_socket_dialog_msg_reads_mention.php b/database/migrations/2022_04_16_073635_add_web_socket_dialog_msg_reads_mention.php new file mode 100644 index 000000000..f29d20cca --- /dev/null +++ b/database/migrations/2022_04_16_073635_add_web_socket_dialog_msg_reads_mention.php @@ -0,0 +1,34 @@ +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"); + }); + } +} diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js index 8395c6003..3561b7cdf 100755 --- a/resources/assets/js/functions/web.js +++ b/resources/assets/js/functions/web.js @@ -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 + } }); /** diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index 7f5b81be7..778e91b87 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -147,7 +147,7 @@
  • - +
  • @@ -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(//g, `[${this.$L('图片')}]`) + body = body.replace(/<[^>]+>/g,"") break; case 'file': body = '[' + this.$L(msg.type == 'img' ? '图片信息' : '文件信息') + ']' diff --git a/resources/assets/js/pages/manage/components/ChatInput.vue b/resources/assets/js/pages/manage/components/ChatInput.vue index f4d87c272..37ea121f9 100755 --- a/resources/assets/js/pages/manage/components/ChatInput.vue +++ b/resources/assets/js/pages/manage/components/ChatInput.vue @@ -141,6 +141,7 @@ export default { allowedChars: /^\S*$/, mentionDenotationChars: ["@", "#"], defaultMenuOrientation: this.defaultMenuOrientation, + isolateCharacter: true, renderItem: (data) => { if (data.disabled === true) { return `
    ${data.value}
    `; diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue index ba49b0862..0c8704145 100644 --- a/resources/assets/js/pages/manage/messenger.vue +++ b/resources/assets/js/pages/manage/messenger.vue @@ -50,6 +50,7 @@
    +
    [@{{$A.getDialogMention(dialog)}}]
    diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 39ba4e987..fa620ab66 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -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) } } diff --git a/resources/assets/sass/pages/components/chat-input.scss b/resources/assets/sass/pages/components/chat-input.scss index 1eaea1f73..ea0008afc 100755 --- a/resources/assets/sass/pages/components/chat-input.scss +++ b/resources/assets/sass/pages/components/chat-input.scss @@ -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 { diff --git a/resources/assets/sass/pages/page-messenger.scss b/resources/assets/sass/pages/page-messenger.scss index baffb1877..c3242e9a4 100644 --- a/resources/assets/sass/pages/page-messenger.scss +++ b/resources/assets/sass/pages/page-messenger.scss @@ -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;