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},