From f76d36a74bb95dadb3d0d9f76110fbe07a9a8266 Mon Sep 17 00:00:00 2001 From: weifashi <605403358@qq.com> Date: Fri, 29 Dec 2023 11:45:42 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=20=E4=BB=A3=E7=A0=81=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 54 +++++++++--- app/Models/WebSocketDialogMsg.php | 56 ------------ ...2_29_145804_add_web_socket_dialogs_top.php | 46 ++++++++++ .../pages/manage/components/DialogWrapper.vue | 85 +++++-------------- resources/assets/js/store/actions.js | 52 ++++++------ resources/assets/js/store/state.js | 2 +- 6 files changed, 137 insertions(+), 158 deletions(-) create mode 100644 database/migrations/2023_12_29_145804_add_web_socket_dialogs_top.php diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index b4bd52071..c22980fc3 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -471,8 +471,6 @@ class DialogController extends AbstractController $builder->where('tag', '>', 0); } elseif ($msg_type === 'todo') { $builder->where('todo', '>', 0); - } elseif ($msg_type === 'top') { - $builder->whereNotNull('top_at'); } elseif ($msg_type === 'link') { $builder->whereLink(1); } elseif (in_array($msg_type, ['text', 'image', 'file', 'record', 'meeting'])) { @@ -542,7 +540,7 @@ class DialogController extends AbstractController if ($reDialog) { $data['dialog'] = $dialog->formatData($user->userid, true); $data['todo'] = $data['dialog']->todo_num > 0 ? WebSocketDialogMsgTodo::whereDialogId($dialog->id)->whereUserid($user->userid)->whereDoneAt(null)->orderByDesc('id')->take(50)->get() : []; - $data['tops'] = WebSocketDialogMsg::whereDialogId($dialog->id)->whereNotNull('top_at')->orderByDesc('top_at')->take(50)->get(); + $data['top'] = WebSocketDialogMsg::whereId($dialog->top_msg_id)->first(); } return Base::retSuccess('success', $data); } @@ -2276,18 +2274,52 @@ class DialogController extends AbstractController if (empty($msg)) { return Base::retError("消息不存在或已被删除"); } - WebSocketDialog::checkDialog($msg->dialog_id); + $dialog = WebSocketDialog::checkDialog($msg->dialog_id); + // + $before = $dialog->top_msg_id; + $dialog->top_msg_id = $msg->id == $before ? 0 : $msg->id; + $dialog->save(); + // + $data = [ + 'update' => [ + 'dialog_id' => $dialog->id, + 'top_msg_id' => $dialog->top_msg_id, + ] + ]; + $res = $msg->sendMsg(null, $dialog->id, 'top', [ + 'action' => $dialog->top_msg_id ? 'add' : 'remove', + 'data' => [ + 'id' => $msg->id, + 'type' => $msg->type, + 'msg' => $msg->quoteTextMsg() + ] + ], $user->userid); + if (Base::isSuccess($res)) { + if ($before != $dialog->top_msg_id) { + $oldTop = WebSocketDialog::whereTopMsgId($before)->first(); + if ($oldTop){ + $oldTop->top_msg_id = 0; + $oldTop->save(); + } + } + $data['add'] = $res['data']; + $dialog->pushMsg('updateTopMsg', $data['update']); + } else { + $dialog->top_msg_id = $before; + $dialog->save(); + } + // + return Base::retSuccess($dialog->top_msg_id ? '置顶成功' : '取消成功', $data); // - return $msg->toggleTopMsg($user->userid); } /** - * @api {get} api/dialog/toplist 48. 获取置顶列表 + * @api {get} api/dialog/msg/topinfo 48. 获取置顶消息 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 * @apiGroup dialog - * @apiName toplist + * @apiName msg__topinfo * * @apiParam {Number} dialog_id 会话ID * @@ -2295,17 +2327,17 @@ class DialogController extends AbstractController * @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {Object} data 返回数据 */ - public function toplist() + public function msg__topinfo() { User::auth(); // $dialog_id = intval(Request::input('dialog_id')); // - WebSocketDialog::checkDialog($dialog_id); + $dialog = WebSocketDialog::checkDialog($dialog_id); // - $tops = WebSocketDialogMsg::whereDialogId($dialog_id)->whereNotNull('top_at')->orderByDesc('top_at')->take(50)->get(); + $topMsg = WebSocketDialogMsg::whereId($dialog->top_msg_id)->first(); // - return Base::retSuccess('success', $tops ?: []); + return Base::retSuccess('success', $topMsg); } } diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index fe388a33a..952f6d4b7 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -380,62 +380,6 @@ class WebSocketDialogMsg extends AbstractModel return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $data); } - /** - * 置顶、取消置顶 - * @param int $sender 置顶的会员ID - * @return mixed - */ - public function toggleTopMsg($sender) - { - $before = $this->top; - $beforeTopAt = $this->top_at; - $this->top = $before ? 0 : $sender; - $this->top_at = $before ? null : Carbon::now(); - $this->save(); - $resData = [ - 'id' => $this->id, - 'top' => $this->top, - 'top_at' => $this->top_at, - 'dialog_id' => $this->dialog_id - ]; - // - $data = [ - 'update' => $resData - ]; - $res = self::sendMsg(null, $this->dialog_id, 'top', [ - 'action' => $this->top ? 'add' : 'remove', - 'data' => [ - 'id' => $this->id, - 'type' => $this->type, - 'msg' => $this->quoteTextMsg(), - ] - ], $sender); - if (Base::isSuccess($res)) { - $dialog = WebSocketDialog::find($this->dialog_id); - if ($this->top) { - $oldTops = self::whereDialogId($this->dialog_id)->where('id', '!=', $this->id)->where('top', '>', 0)->get(); - foreach($oldTops as $oldTop){ - $oldTop->top = 0; - $oldTop->top_at = null; - $oldTop->save(); - $dialog->pushMsg('update', [ - 'id' => $oldTop->id, - 'top' => $oldTop->top, - 'top_at' => $oldTop->top_at, - ]); - } - } - $data['add'] = $res['data']; - $dialog->pushMsg('update', $resData); - } else { - $this->top = $before; - $this->top_at = $beforeTopAt; - $this->save(); - } - // - return Base::retSuccess($this->top ? '置顶成功' : '取消成功', $data); - } - /** * 转发消息 * @param array|int $dialogids diff --git a/database/migrations/2023_12_29_145804_add_web_socket_dialogs_top.php b/database/migrations/2023_12_29_145804_add_web_socket_dialogs_top.php new file mode 100644 index 000000000..c09226ecc --- /dev/null +++ b/database/migrations/2023_12_29_145804_add_web_socket_dialogs_top.php @@ -0,0 +1,46 @@ +dropColumn("top"); + $table->dropColumn("top_at"); + } + }); + // + Schema::table('web_socket_dialogs', function (Blueprint $table) { + $table->bigInteger('top_msg_id')->nullable()->default(0)->after('link_id')->comment('置顶的消息ID'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('web_socket_dialog_msgs', function (Blueprint $table) { + if (!Schema::hasColumn('web_socket_dialog_msgs', 'top')) { + $table->bigInteger('top')->nullable()->default(0)->after('send')->comment('置顶的会员ID'); + $table->timestamp('top_at')->nullable()->after('top')->comment('置顶时间'); + } + }); + // + Schema::table('web_socket_dialogs', function (Blueprint $table) { + $table->dropColumn("top_msg_id"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 58f3317fe..3c9a1aef5 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -310,8 +310,8 @@ {{ $L(operateItem.todo ? '取消待办' : '设待办') }}
  • - - {{ $L(operateItem.top_at ? '取消置顶' : '置顶') }} + + {{ $L(dialogData.top_msg_id == operateItem.id ? '取消置顶' : '置顶') }}
  • @@ -796,7 +796,7 @@ export default { 'dialogSearchMsgId', 'dialogMsgs', 'dialogTodos', - 'dialogTops', + 'dialogMsgTops', 'dialogMsgTransfer', 'cacheDialogs', 'wsOpenNum', @@ -1110,24 +1110,21 @@ export default { return msgPreparedStatus && listPreparedStatus }, - topList() { - return this.dialogTops.filter(item => item.top && item.dialog_id == this.dialogId).sort((a, b) => { - return b.top_at - a.top_at; - }); - }, - topMessage() { - return this.topList[0] + return this.dialogData?.top_msg_id && this.dialogMsgTops.filter(item => item.dialog_id == this.dialogId)[0] }, topMessageClass() { return !this.$slots.head && this.tagShow ? 'default-header' : null - }, + } }, watch: { '$route': { - handler({params}) { + handler({name, params}) { + if (name != 'manage-messenger') { + return + } if (params.dialog_id && params.open && (params.open == 'word-chain' || params.open == 'vote')) { this.$nextTick(_ => { this.$store.state[params.open == 'word-chain' ? 'dialogDroupWordChain' : 'dialogGroupVote'] = { @@ -2683,44 +2680,6 @@ export default { }) }, - onTopLongpress({event, el, msgData}) { - this.operateVisible = this.operateItem.id === msgData.id; - this.operateItem = $A.isJson(msgData) ? msgData : {}; - this.operateCopys = [] - const selectText = this.getSelectedTextInElement(el) - if (selectText.length > 0) { - this.operateCopys.push({ - type: 'selected', - icon: '', - label: '复制选择', - value: selectText, - }) - } - if (msgData.msg.text.replace(/<[^>]+>/g,"").length > 0) { - let label = this.operateCopys.length > 0 ? '复制文本' : '复制' - if (selectText.length > 0) { - label = '复制全部' - } - this.operateCopys.push({ - type: 'text', - icon: '', - label, - value: '', - }) - } - this.$nextTick(() => { - const projectRect = el.getBoundingClientRect(); - const wrapRect = this.$el.getBoundingClientRect(); - this.operateStyles = { - left: `${event.clientX - wrapRect.left}px`, - top: `${projectRect.top + this.windowScrollY}px`, - height: projectRect.height + 'px', - } - this.operateClient = {x: event.clientX, y: event.clientY}; - this.operateVisible = true; - }) - }, - onOperate(action, value = null) { this.operateVisible = false; this.$nextTick(_ => { @@ -3139,7 +3098,7 @@ export default { url: 'dialog/msg/tag', data, }).then(({data}) => { - this.tagOrTodoOrTopSuccess(data) + this.tagOrTodoSuccess(data) }).catch(({msg}) => { $A.messageError(msg); }).finally(_ => { @@ -3238,7 +3197,7 @@ export default { data, }).then(({data, msg}) => { resolve(msg) - this.tagOrTodoOrTopSuccess(data) + this.tagOrTodoSuccess(data) this.onActive() }).catch(({msg}) => { reject(msg); @@ -3248,7 +3207,7 @@ export default { }) }, - tagOrTodoOrTopSuccess(data) { + tagOrTodoSuccess(data) { this.$store.dispatch("saveDialogMsg", data.update); if (data.add) { this.$store.dispatch("saveDialogMsg", data.add); @@ -3443,20 +3402,16 @@ export default { }, }).then(({ data, msg }) => { resolve(msg) - this.tagOrTodoOrTopSuccess(data) - // 取消所有置顶 - const dialogTops = this.dialogTops.filter(item => item.dialog_id == this.dialogId); - this.$store.dispatch("saveDialogTop", dialogTops.map(item => { - item.top = 0; - item.top_at = ""; - return item; - })) + // 取消置顶 + this.$store.dispatch("saveDialog", { + 'id' : this.dialogId, + 'top_msg_id' : data.update?.top_msg_id || 0 + }); // 置顶 - if (data.update?.top) { - const index = this.dialogMsgs.findIndex(({ id }) => id == data.update.id && data.update.top); + if (data.update?.top_msg_id) { + const index = this.dialogMsgs.findIndex(({ id }) => id == data.update.top_msg_id && data.update.top_msg_id); if (index > -1) { - const update = Object.assign({}, this.dialogMsgs[index], data.update) - this.$store.dispatch("saveDialogTop", update) + this.$store.dispatch("saveDialogMsgTop", Object.assign({}, this.dialogMsgs[index])) } } }).catch(({ msg }) => { diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 8205e3045..208f33832 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -2556,21 +2556,20 @@ export default { }, /** - * 获取会话置顶 + * 获取会话消息置顶 * @param state * @param dispatch * @param dialog_id */ - getDialogTop({state, dispatch}, dialog_id) { + getDialogMsgTop({state, dispatch}, dialog_id) { dispatch("call", { - url: 'dialog/toplist', + url: 'dialog/msg/topinfo', data: { dialog_id, }, }).then(({data}) => { - if ($A.isArray(data)) { - state.dialogTops = state.dialogTops.filter(item => item.dialog_id != dialog_id) - dispatch("saveDialogTop", data) + if ($A.isJson(data)) { + dispatch("saveDialogMsgTop", data) } }).catch(console.warn); }, @@ -2790,35 +2789,36 @@ export default { * @param dispatch * @param data */ - saveDialogTop({state, dispatch}, data) { - $A.execMainDispatch("saveDialogTop", data) + saveDialogMsgTop({state, dispatch}, data) { + $A.execMainDispatch("saveDialogMsgTop", data) // if ($A.isArray(data)) { data.forEach(item => { - dispatch("saveDialogTop", item) + dispatch("saveDialogMsgTop", item) }); } else if ($A.isJson(data)) { - const index = state.dialogTops.findIndex(item => item.id == data.id); + state.dialogMsgTops = state.dialogMsgTops.filter(item => item.dialog_id != data.dialog_id) + const index = state.dialogMsgTops.findIndex(item => item.id == data.id); if (index > -1) { - state.dialogTops.splice(index, 1, Object.assign({}, state.dialogTops[index], data)); + state.dialogMsgTops.splice(index, 1, Object.assign({}, state.dialogMsgTops[index], data)); } else { - state.dialogTops.push(data); + state.dialogMsgTops.push(data); } } }, /** - * 忘记置顶数据 + * 忘记消息置顶数据 * @param state * @param dispatch * @param msg_id */ - forgetDialogTopForMsgId({state, dispatch}, msg_id) { - $A.execMainDispatch("forgetDialogTopForMsgId", msg_id) + forgetDialogMsgTopForMsgId({state, dispatch}, msg_id) { + $A.execMainDispatch("forgetDialogMsgTopForMsgId", msg_id) // - const index = state.dialogTops.findIndex(item => item.msg_id == msg_id); + const index = state.dialogMsgTops.findIndex(item => item.msg_id == msg_id); if (index > -1) { - state.dialogTops.splice(index, 1); + state.dialogMsgTops.splice(index, 1); } }, @@ -2896,7 +2896,7 @@ export default { } }) dispatch("forgetDialogTodoForMsgId", msg_id) - dispatch("forgetDialogTopForMsgId", msg_id) + dispatch("forgetDialogMsgTopForMsgId", msg_id) }, /** @@ -2965,9 +2965,8 @@ export default { state.dialogTodos = state.dialogTodos.filter(item => item.dialog_id != data.dialog_id) dispatch("saveDialogTodo", resData.todo) } - if ($A.isArray(resData.tops)) { - state.dialogTops = state.dialogTops.filter(item => item.dialog_id != data.dialog_id) - dispatch("saveDialogTop", resData.tops) + if (typeof resData.top !== "undefined") { + dispatch("saveDialogMsgTop", resData.top) } // dispatch("saveDialogMsg", resData.list) @@ -3480,10 +3479,6 @@ export default { if (typeof data.todo !== "undefined") { dispatch("getDialogTodo", dialog_id) } - // 更新置顶 - if (typeof data.top !== "undefined") { - dispatch("getDialogTop", dialog_id) - } return; } if (count <= 5) { @@ -3511,6 +3506,13 @@ export default { // 群组退出、解散 dispatch("forgetDialog", data.id) break; + case 'updateTopMsg': + // 更新置顶 + if (typeof data.top_msg_id !== "undefined") { + dispatch("saveDialog", { id: data.dialog_id, top_msg_id: data?.top_msg_id || 0 }) + dispatch("getDialogMsgTop", dialog_id) + } + break; } })(msgDetail); break; diff --git a/resources/assets/js/store/state.js b/resources/assets/js/store/state.js index 68111fd5a..dabc598f9 100644 --- a/resources/assets/js/store/state.js +++ b/resources/assets/js/store/state.js @@ -113,7 +113,7 @@ export default { dialogIns: [], dialogMsgs: [], dialogTodos: [], - dialogTops: [], + dialogMsgTops: [], dialogHistory: [], dialogDraftTimer: {}, dialogMsgTransfer: {time: 0},