From d167a91a077be4f95f646a302810e352f85190f5 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Mon, 20 Jun 2022 01:14:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 36 ++++++++ app/Models/WebSocketDialog.php | 37 ++++---- app/Models/WebSocketDialogMsg.php | 17 ++++ ..._233120_add_web_socket_dialog_msgs_key.php | 50 +++++++++++ .../pages/manage/components/DialogWrapper.vue | 85 ++++++++++++------ .../assets/js/pages/manage/messenger.vue | 90 ++++++++++++++----- resources/assets/js/store/actions.js | 6 ++ resources/assets/js/store/state.js | 1 + 8 files changed, 257 insertions(+), 65 deletions(-) create mode 100644 database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index ce34618d4..cba039d22 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -62,6 +62,42 @@ class DialogController extends AbstractController return Base::retSuccess('success', $list); } + /** + * @api {get} api/dialog/search 02. 搜索会话 + * + * @apiDescription 根据消息关键词搜索相关会话,需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName search + * + * @apiParam {String} key 消息关键词 + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function search() + { + $user = User::auth(); + // + $key = trim(Request::input('key')); + // + $list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.mark_unread', 'm.id as search_msg_id']) + ->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id') + ->join('web_socket_dialog_msgs as m', 'web_socket_dialogs.id', '=', 'm.dialog_id') + ->where('u.userid', $user->userid) + ->where('m.key', 'LIKE', "%{$key}%") + ->orderByDesc('m.id') + ->take(20) + ->get(); + // + $list->transform(function (WebSocketDialog $item) use ($user) { + return $item->formatData($user->userid); + }); + // + return Base::retSuccess('success', $list); + } + /** * @api {get} api/dialog/one 02. 获取单个会话信息 * diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 4eb2e5029..20cab2526 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -58,29 +58,34 @@ class WebSocketDialog extends AbstractModel */ public function formatData($userid) { - // 最后消息 - $last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first(); - $this->last_msg = $last_msg; - // 未读信息 - $unreadBuilder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null); - $this->unread = $unreadBuilder->count(); - $this->mention = 0; - $this->last_umid = 0; - if ($this->unread > 0) { - $this->mention = $unreadBuilder->clone()->whereMention(1)->count(); - $this->last_umid = intval($unreadBuilder->clone()->orderByDesc('msg_id')->value('msg_id')); + if (isset($this->search_msg_id)) { + // 最后消息 (搜索预览消息) + $this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->find($this->search_msg_id); + $this->last_at = $this->last_msg?->created_at; + } else { + // 最后消息 + $this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first(); + // 未读信息 + $unreadBuilder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null); + $this->unread = $unreadBuilder->count(); + $this->mention = 0; + $this->last_umid = 0; + if ($this->unread > 0) { + $this->mention = $unreadBuilder->clone()->whereMention(1)->count(); + $this->last_umid = intval($unreadBuilder->clone()->orderByDesc('msg_id')->value('msg_id')); + } + $this->mark_unread = $this->mark_unread ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('mark_unread'); + // 对话人数 + $builder = WebSocketDialogUser::whereDialogId($this->id); + $this->people = $builder->count(); } - $this->mark_unread = $this->mark_unread ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('mark_unread'); - // 对话人数 - $builder = WebSocketDialogUser::whereDialogId($this->id); - $this->people = $builder->count(); // 对方信息 $this->dialog_user = null; $this->group_info = null; $this->top_at = $this->top_at ?? WebSocketDialogUser::whereDialogId($this->id)->whereUserid($userid)->value('top_at'); switch ($this->type) { case "user": - $dialog_user = $builder->where('userid', '!=', $userid)->first(); + $dialog_user = WebSocketDialogUser::whereDialogId($this->id)->where('userid', '!=', $userid)->first(); if ($dialog_user->userid === 0) { $dialog_user->userid = $userid; } diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index a4a690d4b..792918766 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -20,6 +20,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string|null $type 消息类型 * @property array|mixed $msg 详细消息 * @property array|mixed $emoji emoji回复 + * @property string|null $key 搜索关键词 * @property int|null $read 已阅数量 * @property int|null $send 发送数量 * @property int|null $reply_id 回复ID @@ -39,6 +40,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereDialogType($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereEmoji($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereKey($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereMsg($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereRead($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsg whereReplyId($value) @@ -60,6 +62,7 @@ class WebSocketDialogMsg extends AbstractModel ]; protected $hidden = [ + 'key', 'updated_at', ]; @@ -335,6 +338,19 @@ class WebSocketDialogMsg extends AbstractModel } } + /** + * 生成关键词 + * @return string + */ + public function generateMsgKey() + { + return match ($this->type) { + 'text' => strip_tags($this->msg['text']), + 'meeting', 'file' => $this->msg['name'], + default => '', + }; + } + /** * 返回文本预览消息 * @param $text @@ -464,6 +480,7 @@ class WebSocketDialogMsg extends AbstractModel $dialog->save(); $dialogMsg->send = 1; $dialogMsg->dialog_type = $dialog->type; + $dialogMsg->key = $dialogMsg->generateMsgKey(); $dialogMsg->save(); }); Task::deliver(new WebSocketDialogMsgTask($dialogMsg->id)); diff --git a/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php b/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php new file mode 100644 index 000000000..89fad0638 --- /dev/null +++ b/database/migrations/2022_06_19_233120_add_web_socket_dialog_msgs_key.php @@ -0,0 +1,50 @@ +text('key')->after('emoji')->nullable()->default('')->comment('搜索关键词'); + } + }); + if ($isAdd) { + \App\Models\WebSocketDialogMsg::chunkById(100, function ($lists) { + /** @var \App\Models\WebSocketDialogMsg $item */ + foreach ($lists as $item) { + $key = $item->generateMsgKey(); + if ($key) { + $item->key = $key; + $item->save(); + } + } + }); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('web_socket_dialog_msgs', function (Blueprint $table) { + $table->dropColumn("key"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 701e0716c..addfe713d 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -285,6 +285,10 @@ export default { type: Number, default: 0 }, + searchMsgId: { + type: Number, + default: 0 + }, autoFocus: { type: Boolean, default: false @@ -315,6 +319,7 @@ export default { userids: [], }, + confirmId: 0, dialogDrag: false, groupInfoShow: false, @@ -473,7 +478,10 @@ export default { this.allMsgs = this.allMsgList; requestAnimationFrame(this.onToBottom); } - this.$store.dispatch("getDialogMsgs", id).catch(_ => {}); + this.$store.dispatch("getDialogMsgs", id).then(_ => { + this.confirmId = id; + setTimeout(this.onSearchMsgId, 100) + }).catch(_ => {}); // this.$store.dispatch('saveInDialog', { uid: this._uid, @@ -488,6 +496,10 @@ export default { immediate: true }, + searchMsgId() { + this.onSearchMsgId(); + }, + dialogMsgTransfer: { handler({time, msgFile, msgRecord, msgText}) { if (time > $A.Time()) { @@ -675,6 +687,44 @@ export default { } }, + onSearchMsgId() { + if (this.searchMsgId > 0 && this.confirmId === this.dialogId) { + this.onPositionId(this.searchMsgId) + this.$store.state.searchMsgId = 0 + } + }, + + onPositionId(position_id, msg_id = 0) { + if (position_id === 0) { + return + } + const index = this.allMsgs.findIndex(item => item.id === position_id) + if (index > -1) { + this.onToIndex(index) + } else { + if (msg_id > 0) { + this.$store.dispatch("setLoad", { + key: `msg-${msg_id}`, + delay: 600 + }) + } + this.preventToBottom = true; + this.$store.dispatch("getDialogMoreMsgs", { + dialog_id: this.dialogId, + position_id + }).finally(_ => { + const index = this.allMsgs.findIndex(item => item.id === position_id) + if (index > -1) { + this.onToIndex(index) + } + if (msg_id > 0) { + this.$store.dispatch("cancelLoad", `msg-${msg_id}`) + } + this.preventToBottom = false; + }) + } + }, + itemClassAdd(index) { return index === this.replyActiveIndex ? 'dialog-shake' : ''; }, @@ -832,12 +882,13 @@ export default { } }, - onToIndex(index, addOffset) { + onToIndex(index) { const scroller = this.$refs.scroller; if (scroller) { - scroller.scrollToIndex(index, addOffset); - requestAnimationFrame(_ => scroller.scrollToIndex(index, addOffset)) // 确保滚动到 + scroller.scrollToIndex(index, -100); + requestAnimationFrame(_ => scroller.scrollToIndex(index, -100)) // 确保滚动到 } + requestAnimationFrame(_ => this.replyActiveIndex = index) }, onToOffset(offset) { @@ -1123,31 +1174,7 @@ export default { if (this.operateVisible) { return } - const runToIndex = (index) => { - this.onToIndex(index, -100) - requestAnimationFrame(_ => this.replyActiveIndex = index) - } - const index = this.allMsgs.findIndex(item => item.id === data.reply_id) - if (index > -1) { - runToIndex(index) - } else { - this.$store.dispatch("setLoad", { - key: `msg-${data.msg_id}`, - delay: 600 - }) - this.preventToBottom = true; - this.$store.dispatch("getDialogMoreMsgs", { - dialog_id: this.dialogId, - position_id: data.reply_id - }).finally(_ => { - const index = this.allMsgs.findIndex(item => item.id === data.reply_id) - if (index > -1) { - runToIndex(index) - } - this.$store.dispatch("cancelLoad", `msg-${data.msg_id}`) - this.preventToBottom = false; - }) - } + this.onPositionId(data.reply_id, data.msg_id) }, onViewText({target}) { diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue index bb408a555..c066c1065 100644 --- a/resources/assets/js/pages/manage/messenger.vue +++ b/resources/assets/js/pages/manage/messenger.vue @@ -33,22 +33,20 @@