From 88316fda1cf853bf08e20d6297624187dbcaa384 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Fri, 17 Jun 2022 15:25:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9A=E4=BD=8D=E5=9B=9E=E5=A4=8D=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 | 14 ++- .../js/pages/manage/components/DialogItem.vue | 4 +- .../js/pages/manage/components/DialogView.vue | 5 +- .../pages/manage/components/DialogWrapper.vue | 89 ++++++++++++++++--- resources/assets/js/store/actions.js | 36 +++----- 5 files changed, 106 insertions(+), 42 deletions(-) diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index fcdb870cd..b28c825fb 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -178,6 +178,7 @@ class DialogController extends AbstractController * @apiName msg__lists * * @apiParam {Number} dialog_id 对话ID + * @apiParam {String} [position_id] 定位消息ID(填写时page无效) * * @apiParam {Number} [page] 当前页,默认:1 * @apiParam {Number} [pagesize] 每页显示数量,默认:50,最大:100 @@ -191,10 +192,11 @@ class DialogController extends AbstractController $user = User::auth(); // $dialog_id = intval(Request::input('dialog_id')); + $position_id = intval(Request::input('position_id')); // $dialog = WebSocketDialog::checkDialog($dialog_id); // - $list = WebSocketDialogMsg::select([ + $builder = WebSocketDialogMsg::select([ 'web_socket_dialog_msgs.*', 'read.mention', 'read.read_at', @@ -202,7 +204,15 @@ class DialogController extends AbstractController $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)); + })->where('web_socket_dialog_msgs.dialog_id', $dialog_id)->orderByDesc('web_socket_dialog_msgs.id'); + // + $perPage = Base::getPaginate(100, 50); + if ($position_id > 0) { + $position_count = $builder->clone()->where('web_socket_dialog_msgs.id', '>=', $position_id)->count(); + $list = $builder->paginate($perPage, [], 'page', ceil($position_count / $perPage)); + } else { + $list = $builder->paginate($perPage); + } // if ($dialog->type == 'group' && $dialog->group_type == 'task') { $user->task_dialog_id = $dialog->id; diff --git a/resources/assets/js/pages/manage/components/DialogItem.vue b/resources/assets/js/pages/manage/components/DialogItem.vue index 14d280917..d546c4c60 100644 --- a/resources/assets/js/pages/manage/components/DialogItem.vue +++ b/resources/assets/js/pages/manage/components/DialogItem.vue @@ -75,8 +75,8 @@ export default { this.dispatch("on-longpress", e) }, - onViewReply(replyId) { - this.dispatch("on-view-reply", replyId) + onViewReply(data) { + this.dispatch("on-view-reply", data) }, onViewText(e) { diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index f44cc24d5..8668fd06b 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -388,7 +388,10 @@ export default { }, viewReply() { - this.$emit("on-view-reply", this.replyData.id) + this.$emit("on-view-reply", { + msg_id: this.msgData.id, + reply_id: this.replyData.id + }) }, viewText(e) { diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 8c542a33a..92e02c80f 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -79,9 +79,9 @@ :item-class-add="itemClassAdd" :extra-props="{dialogData, isMyDialog, operateVisible, operateItem}" :estimate-size="78" - :keeps="80" + :keeps="70" @scroll="onScroll" - @totop="loadNextPage" + @totop="onNextPage" @on-longpress="onLongpress" @on-view-reply="onViewReply" @@ -89,7 +89,7 @@ @on-view-file="onViewFile" @on-emoji="onEmoji"> @@ -326,6 +326,7 @@ export default { recordState: '', wrapperStart: 0, + scrollMoreLoad: false, replyId: 0, replyActiveIndex: -1, @@ -386,6 +387,17 @@ export default { return dialogMsgList; }, + nextPage() { + if (this.allMsgs.length > 0) { + let topMsgPage = $A.runNum(this.allMsgs[0]._page); + let {lastPage} = this.dialogData; + if (topMsgPage < lastPage && lastPage > 1) { + return topMsgPage + 1 + } + } + return 0 + }, + peopleNum() { return this.dialogData.type === 'group' ? $A.runNum(this.dialogData.people) : 0; }, @@ -798,8 +810,14 @@ export default { this.$store.dispatch("openTask", this.dialogData.group_info.id); }, - loadNextPage() { - this.$store.dispatch('getDialogMoreMsgs', this.dialogId).then(result => { + onNextPage() { + if (this.nextPage === 0) { + return + } + this.$store.dispatch('getDialogMoreMsgs', { + dialog_id: this.dialogId, + page: this.nextPage + }).then(result => { const resData = result.data; const ids = resData.data.map(item => item.id) this.$nextTick(() => { @@ -887,7 +905,7 @@ export default { } }, - onScroll() { + onScroll(evt, range) { this.operateVisible = false; this.__onScroll && clearTimeout(this.__onScroll); this.__onScroll = setTimeout(_ => { @@ -896,6 +914,25 @@ export default { this.msgNew = 0; } }, 100) + // + if (!this.scrollMoreLoad) { + let tmpPage = 0; + for (let i = range.start; i <= range.end; i++) { + if (tmpPage - parseInt(this.allMsgs[i]._page) > 1) { + this.scrollMoreLoad = true + setTimeout(_ => { + this.$store.dispatch("getDialogMoreMsgs", { + dialog_id: this.dialogId, + page: tmpPage - 1 + }).finally(_ => { + this.scrollMoreLoad = false + }) + }, 100) + break; + } + tmpPage = parseInt(this.allMsgs[i]._page); + } + } }, onBack() { @@ -1021,19 +1058,45 @@ export default { }); }, - onViewReply(replyId) { + onViewReply(data) { if (this.operateVisible) { return } - const index = this.allMsgs.findIndex(item => item.id === replyId) - if (index > -1) { - this.$refs.scroller?.scrollToIndex(index); + const toIndex = (index) => { + this.$refs.scroller?.scrollToIndex(index) requestAnimationFrame(_ => { - this.replyActiveIndex = index; + this.replyActiveIndex = index setTimeout(_ => { - this.replyActiveIndex = -1; + this.replyActiveIndex = -1 }, 800) - }); + }) + } + const index = this.allMsgs.findIndex(item => item.id === data.reply_id) + if (index > -1) { + toIndex(index) + } else { + this.$store.dispatch("setLoad", { + key: `msg-${data.msg_id}`, + delay: 600 + }) + this.$store.dispatch("getDialogMoreMsgs", { + dialog_id: this.dialogId, + position_id: data.reply_id + }).then(_ => { + let i = 0; + let inter = setInterval(_ => { + i++ + const index = this.allMsgs.findIndex(item => item.id === data.reply_id) + if (i > 10 || index > -1) { + clearInterval(inter) + if (index > -1) { + toIndex(index) + } + } + }, 100) + }).finally(_ => { + this.$store.dispatch("cancelLoad", `msg-${data.msg_id}`) + }) } }, diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index fe6a6c185..e5296f82f 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -2196,25 +2196,22 @@ export default { return; } dialog.loading = true; - dialog.currentPage = 1; - dialog.hasMorePages = false; // dispatch("call", { url: 'dialog/msg/lists', data: { dialog_id: dialog_id, - page: dialog.currentPage + page: 1 }, }).then(result => { const resData = result.data; - dialog.currentPage = resData.current_page; - dialog.hasMorePages = !!resData.next_page_url; + dialog.lastPage = resData.last_page; dialog = Object.assign(dialog, resData.dialog) // const ids = resData.data.map(({id}) => id) state.dialogMsgs = state.dialogMsgs.filter((item) => item.dialog_id != dialog_id || ids.includes(item.id)); // - dispatch("saveDialogMsg", resData.data); + dispatch("saveDialogMsg", resData.data.map(item => Object.assign(item, {_page: resData.current_page}))); resolve() }).catch(e => { console.warn(e); @@ -2227,46 +2224,37 @@ export default { }, /** - * 获取更多(下一页)会话消息 + * 获取更多会话消息(指定页|定位页) * @param state * @param dispatch - * @param dialog_id + * @param data {dialog_id, ?page, ?position_id} */ - getDialogMoreMsgs({state, dispatch}, dialog_id) { + getDialogMoreMsgs({state, dispatch}, data) { return new Promise(function (resolve, reject) { - const dialog = state.cacheDialogs.find(({id}) => id == dialog_id); + const dialog = state.cacheDialogs.find(({id}) => id == data.dialog_id); if (!dialog) { reject({msg: 'Parameter error'}); return; } - if (!dialog.hasMorePages) { - reject({msg: 'No more page'}); - return; - } if (dialog.loading) { reject({msg: 'Loading'}); return; } dialog.loading = true; - dialog.currentPage++; // dispatch("call", { url: 'dialog/msg/lists', - data: { - dialog_id: dialog_id, - page: dialog.currentPage - }, + data, }).then(result => { const resData = result.data; - dialog.loading = false; - dialog.currentPage = resData.current_page; - dialog.hasMorePages = !!resData.next_page_url; - dispatch("saveDialogMsg", resData.data); + dialog.lastPage = resData.last_page; + dispatch("saveDialogMsg", resData.data.map(item => Object.assign(item, {_page: resData.current_page}))); resolve(result) }).catch(e => { console.warn(e); - dialog.loading = false; reject(e) + }).finally(_ => { + dialog.loading = false; }); }); },