From a0e84479f206056e0e61966eba9838d21b15fff9 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Tue, 7 Feb 2023 04:30:18 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=9A=E8=AF=9D=E9=A1=B6=E9=83=A8?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E5=89=A9=E4=BD=99=E6=9C=AA=E8=AF=BB=E6=B6=88?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 9 +++++ .../pages/manage/components/DialogWrapper.vue | 35 +++++++++++++++++ .../assets/js/pages/manage/messenger.vue | 15 +++---- resources/assets/js/store/actions.js | 39 +++++++++++++++++++ resources/assets/js/store/state.js | 1 + .../sass/pages/components/dialog-wrapper.scss | 30 ++++++++++++++ 6 files changed, 119 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 57ca54dba..ffdc7ed7a 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -457,6 +457,15 @@ class DialogController extends AbstractController ->where('web_socket_dialog_msgs.id', '<', $last->id) ->orderByDesc('web_socket_dialog_msgs.id') ->value('id')); + // + if (empty($position_id)) { + $unreadBuilder = WebSocketDialogMsgRead::whereDialogId($dialog_id)->whereUserid($user->userid)->whereReadAt(null)->where('msg_id', '<', $last->id); + $unread = $unreadBuilder->count(); + $data['before'] = [ + 'unread' => $unread, + 'first_id' => $unread > 0 ? intval($unreadBuilder->orderBy('msg_id')->value('msg_id')) : 0, + ]; + } } $data['list'] = $list; $data['time'] = Base::time(); diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 52502dbf3..d22f37e76 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -97,6 +97,14 @@ + +
+
+ + {{$L(`未读消息${beforeUnread.unread}条`)}} +
+
+ id === this.dialogId) + return before || null } }, @@ -2202,6 +2218,25 @@ export default { } }, + goBeforeUnread() { + if (!this.beforeUnread || this.beforeLoad) { + return; + } + // + this.beforeLoad = true + const {first_id} = this.beforeUnread + this.$store.dispatch("dialogMsgMark", { + dialog_id: this.dialogId, + type: 'read' + }).then(_ => { + this.onPositionId(first_id) + }).catch(({msg}) => { + $A.modalError(msg) + }).finally(_ => { + this.beforeLoad = false + }) + }, + getBase64Image(url) { return new Promise(resolve => { let canvas = document.createElement('CANVAS'), diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue index 667474e8c..88cab075c 100644 --- a/resources/assets/js/pages/manage/messenger.vue +++ b/resources/assets/js/pages/manage/messenger.vue @@ -720,17 +720,12 @@ export default { }, handleReadClick() { - this.$store.dispatch("call", { - url: 'dialog/msg/mark', - data: { - dialog_id: this.operateItem.id, - type: $A.getDialogUnread(this.operateItem, true) > 0 ? 'read' : 'unread' - }, - }).then(({data}) => { - this.$store.dispatch("saveDialog", data); + this.$store.dispatch("dialogMsgMark", { + dialog_id: this.operateItem.id, + type: $A.getDialogUnread(this.operateItem, true) > 0 ? 'read' : 'unread' }).catch(({msg}) => { - $A.modalError(msg); - }); + $A.modalError(msg) + }) }, handleSilenceClick() { diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 142cb761c..9c1156526 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -2505,6 +2505,18 @@ export default { dispatch("saveDialogTodo", resData.todo) } // + const before = Object.assign({id: data.dialog_id}, resData.before || {}); + const index = state.dialogBeforeUnreads.findIndex(({id}) => id == data.dialog_id); + if (before.unread) { + if (index > -1) { + state.dialogBeforeUnreads.splice(index, 1, before); + } else { + state.dialogBeforeUnreads.push(before); + } + } else if (index > -1) { + state.dialogBeforeUnreads.splice(index, 1); + } + // dispatch("saveDialogMsg", resData.list) resolve(result) }).catch(e => { @@ -2569,6 +2581,33 @@ export default { }, 50); }, + /** + * 标记已读、未读 + * @param state + * @param dispatch + * @param data + * @returns {Promise} + */ + dialogMsgMark({state, dispatch}, data) { + return new Promise((resolve, reject) => { + dispatch("call", { + url: 'dialog/msg/mark', + data, + }).then(result => { + if (data.type === 'read') { + const index = state.dialogBeforeUnreads.findIndex(({id}) => id == data.dialog_id) + if (index > -1) { + state.dialogBeforeUnreads.splice(index, 1) + } + } + dispatch("saveDialog", result.data) + resolve(result) + }).catch(e => { + reject(e) + }) + }) + }, + /** *****************************************************************************************/ /** ************************************* loads *********************************************/ /** *****************************************************************************************/ diff --git a/resources/assets/js/store/state.js b/resources/assets/js/store/state.js index 61b800500..c2793565f 100644 --- a/resources/assets/js/store/state.js +++ b/resources/assets/js/store/state.js @@ -82,6 +82,7 @@ export default { dialogHistory: [], dialogInputCache: [], dialogMsgTransfer: {time: 0}, + dialogBeforeUnreads: [], // 文件 fileLists: [], diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss index 6826a7d4b..aa480ef1f 100644 --- a/resources/assets/sass/pages/components/dialog-wrapper.scss +++ b/resources/assets/sass/pages/components/dialog-wrapper.scss @@ -1074,6 +1074,30 @@ } } + .dialog-top { + position: absolute; + top: 78px; + left: 0; + right: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + .top-unread { + display: flex; + align-items: center; + justify-content: center; + padding: 6px 12px; + border-radius: 4px; + box-shadow: 0 2px 8px 0 rgba($primary-text-color, 0.33); + background: #fff; + cursor: pointer; + > i { + margin-right: 4px; + } + } + } + .dialog-footer { position: relative; padding: 0 24px; @@ -1589,6 +1613,12 @@ } } } + .dialog-top { + top: 68px; + &.down { + top: 98px; + } + } .dialog-footer { background-color: #f8f8f8; padding: 8px 10px;