diff --git a/pages/chat/index.vue b/pages/chat/index.vue index aaa29c3..68235d6 100644 --- a/pages/chat/index.vue +++ b/pages/chat/index.vue @@ -13,77 +13,86 @@ class="chat-scroll" scroll-y :scroll-into-view="scrollToView" + :scroll-top="scrollTop" scroll-with-animation + :upper-threshold="20" + @scroll="handleScroll" + @scrolltoupper="handleScrollToUpper" > - -
- -
-
{{ vuex_msgUser.name }}
+ + +
+ +
+
{{ vuex_msgUser.name }}
-
- - {{ vuex_msgUser.collegeName }} -
+
+ + {{ vuex_msgUser.collegeName }} +
-
- - {{ vuex_msgUser.collegeName }} +
+ + {{ vuex_msgUser.collegeName }} +
-
- - - - {{ formatShowTime(message.sendDate) }} - - - - - {{ message.message }} + + + {{ formatShowTime(message.sendDate) }} + + + + + + {{ message.message }} + + + + + + + + + {{ message.message }} + - - - - - - {{ message.message }} - - + + - - - @@ -155,9 +164,15 @@ export default { // 滚动位置 scrollToView: "", + scrollTop: 0, + currentScrollTop: 0, + currentScrollHeight: 0, PageIndex: 1, PageSize: 20, + + isLoadingHistory: false, + noMoreHistory: false, }; }, @@ -200,6 +215,7 @@ export default { // 监听最后一条消息的ID变化,滚动到底部 lastMsgId(val) { if (!val) return; + if (this.isLoadingHistory) return; this.$nextTick(() => { this.scrollToBottom(); }); @@ -267,20 +283,61 @@ export default { // 加载对话消息 getMsgList() { - this.$u.api - .GetChatHistoryDataApi({ - "Item1.DialogueManagementId": this.vuex_msgUser.dialogueManagementId, + return this.$store.dispatch("fetchChatRecord", { + dialogueManagementId: this.vuex_msgUser.dialogueManagementId, + PageIndex: this.PageIndex, + PageSize: this.PageSize, + }); + }, + + handleScroll(e) { + const detail = (e && e.detail) || {}; + this.currentScrollTop = Number(detail.scrollTop) || 0; + this.currentScrollHeight = Number(detail.scrollHeight) || 0; + }, + + // 滚动到顶部,加载下一页历史消息 + handleScrollToUpper() { + if (this.isLoadingHistory || this.noMoreHistory) return; + + this.isLoadingHistory = true; + const beforeTop = this.currentScrollTop || 0; + const beforeHeight = this.currentScrollHeight || 0; + this.PageIndex += 1; + this.scrollToView = ""; + + this.$store + .dispatch("fetchChatRecordNextPage", { + dialogueManagementId: this.vuex_msgUser.dialogueManagementId, PageIndex: this.PageIndex, PageSize: this.PageSize, }) - .then((res) => { - const msgList = res.data.item1.reverse(); - - this.$store.commit("push_MsgList", msgList); - // // 滚动到底部 - // this.$nextTick(() => { - // this.scrollToBottom(); - // }); + .then((list) => { + if (!list || !list.length) { + this.noMoreHistory = true; + return; + } + this.$nextTick(() => { + const query = uni.createSelectorQuery().in(this); + query + .select(".chat-content") + .boundingClientRect((rect) => { + const afterHeight = Number(rect && rect.height) || 0; + const delta = afterHeight - beforeHeight; + if (delta > 0) { + this.scrollTop = beforeTop + delta; + } + }) + .exec(); + }); + }) + .catch(() => { + this.PageIndex = Math.max(1, this.PageIndex - 1); + }) + .finally(() => { + setTimeout(() => { + this.isLoadingHistory = false; + }, 50); }); }, diff --git a/store/index.js b/store/index.js index 75f9025..5b85cc8 100644 --- a/store/index.js +++ b/store/index.js @@ -146,6 +146,21 @@ const store = new Vuex.Store({ push_MsgList(state, list) { state.vuex_msgList = list || []; }, + // 追加历史消息到头部(分页加载) + prepend_MsgList(state, list) { + const prev = state.vuex_msgList || []; + const next = Array.isArray(list) ? list : []; + const merged = [...next, ...prev]; + + const seen = new Set(); + state.vuex_msgList = merged.filter((item) => { + const id = item && item.id; + if (!id) return true; + if (seen.has(id)) return false; + seen.add(id); + return true; + }); + }, // 推送一条新消息(去重) push_Msg(state, msg) { // 注:现在的消息没有id,无法去重,暂时用push_MsgList @@ -232,18 +247,49 @@ const store = new Vuex.Store({ // 刷新列表,清零未读 dispatch("getUserlist"); }, - // 获取聊天记录(私聊) + // 获取聊天记录(私聊)——仅在进入聊天页时加载一次 async fetchChatRecord( - { commit, state }, - { userId, friendId, PageIndex = 1, PageSize = 20 } + { commit }, + { dialogueManagementId, PageIndex = 1, PageSize = 20 } ) { - const params = { userId, friendId, PageIndex, PageSize }; + return Vue.prototype.$u.api + .GetChatHistoryDataApi({ + "Item1.DialogueManagementId": dialogueManagementId, + PageIndex, + PageSize, + }) + .then((res) => { + const list = + (res && res.data && Array.isArray(res.data.item1) + ? res.data.item1 + : [] + ).slice().reverse(); + commit("push_MsgList", list); + return list; + }); + }, - Vue.prototype.$u.api.GetChatHistoryDataApi(params).then((res) => { - const list = res && res.data ? res.data : []; - // 将最新消息插入到消息列表尾部(或头部) - list.forEach((msg) => commit("push_Msg", msg)); - }); + // 获取下一页历史消息(滚动到顶部触发) + async fetchChatRecordNextPage( + { commit }, + { dialogueManagementId, PageIndex = 1, PageSize = 20 } + ) { + return Vue.prototype.$u.api + .GetChatHistoryDataApi({ + "Item1.DialogueManagementId": dialogueManagementId, + PageIndex, + PageSize, + }) + .then((res) => { + const list = + (res && res.data && Array.isArray(res.data.item1) + ? res.data.item1 + : [] + ).slice().reverse(); + if (!list.length) return []; + commit("prepend_MsgList", list); + return list; + }); }, // 设置消息置顶(服务端 + 本地) async setTopMsgUser({ commit, dispatch }, user) {