shizhongqi 11 месяцев назад
Родитель
Сommit
48c1f8b405
2 измененных файлов с 172 добавлено и 16 удалено
  1. 83 8
      hdApp/src/admin/chat/chatPage.vue
  2. 89 8
      mallApp/src/pages/chat/chatPage.vue

+ 83 - 8
hdApp/src/admin/chat/chatPage.vue

@@ -6,8 +6,24 @@
     </view>
     </view>
 
 
     <!-- 聊天消息列表 -->
     <!-- 聊天消息列表 -->
-    <scroll-view class="message-list" :scroll-top="scrollTop" scroll-y :scroll-into-view="scrollIntoView" scroll-with-animation>
-      <view class="message-item" v-for="(message, index) in messageList" :key="index" :id="'message-' + index">
+    <scroll-view
+      class="message-list"
+      :scroll-top="scrollTop"
+      scroll-y
+      :scroll-into-view="scrollIntoView"
+      :scroll-with-animation="scrollWithAnimation"
+      @scrolltoupper="loadMoreMessages"
+    >
+      <!-- 加载更多 -->
+      <view class="load-more" v-if="showLoadMore" @click="loadMoreMessages">
+        <text class="load-more-text">加载更多</text>
+      </view>
+      <view
+        class="message-item"
+        v-for="(message, index) in messageList"
+        :key="index"
+        :id="'message-' + message.id"
+      >
         <!-- 左侧消息(商家/其他用户) -->
         <!-- 左侧消息(商家/其他用户) -->
         <view class="message-left" v-if="!message.isMine && !message.shopId">
         <view class="message-left" v-if="!message.isMine && !message.shopId">
           <view class="avatar-wrapper">
           <view class="avatar-wrapper">
@@ -104,6 +120,12 @@ export default {
       reconnectCount: 0,
       reconnectCount: 0,
       maxReconnectCount: 3,
       maxReconnectCount: 3,
       isManualDisconnect: false, // 添加标志位:是否主动断开连接
       isManualDisconnect: false, // 添加标志位:是否主动断开连接
+      scrollWithAnimation: false, // 控制滚动动画
+      // 分页加载
+      allMessages: [], // 存储所有从API获取的消息
+      initialLoadSize: 50, // 首次加载数量
+      loadMoreSize: 100, // 每次加载更多的数量
+      showLoadMore: false, // 是否显示“加载更多”
       // 键盘相关
       // 键盘相关
       keyboardHeight: 0, // 键盘高度
       keyboardHeight: 0, // 键盘高度
       isKeyboardShow: false, // 键盘是否显示
       isKeyboardShow: false, // 键盘是否显示
@@ -194,14 +216,56 @@ export default {
         userId: this.currentUser.id
         userId: this.currentUser.id
       }).then((res) => {
       }).then((res) => {
         if (res.code == 1 && res.data) {
         if (res.code == 1 && res.data) {
-          this.messageList = res.data;
+          this.allMessages = res.data.map((item, index) => ({
+            ...item,
+            id: `msg_${index}`, // 为每条消息添加唯一ID
+          }));
+
+          if (this.allMessages.length > this.initialLoadSize) {
+            this.messageList = this.allMessages.slice(
+              this.allMessages.length - this.initialLoadSize
+            );
+            this.showLoadMore = true;
+          } else {
+            this.messageList = this.allMessages;
+            this.showLoadMore = false;
+          }
           this.$nextTick(() => {
           this.$nextTick(() => {
-            this.scrollToBottom();
+            this.scrollToBottom(false); // 初始加载时不使用动画
           });
           });
         }
         }
       });
       });
     },
     },
 
 
+    // 加载更多历史记录
+    loadMoreMessages() {
+      if (!this.showLoadMore) {
+        return;
+      }
+      const currentLoadedCount = this.messageList.length;
+      const remainingMessagesCount = this.allMessages.length - currentLoadedCount;
+      if (remainingMessagesCount <= 0) {
+        this.showLoadMore = false;
+        return;
+      }
+      const countToLoad = Math.min(this.loadMoreSize, remainingMessagesCount);
+      const moreMessages = this.allMessages.slice(
+        remainingMessagesCount - countToLoad,
+        remainingMessagesCount
+      );
+      const oldTopMessageId = this.messageList.length > 0 ? this.messageList[0].id : null;
+      this.messageList = [...moreMessages, ...this.messageList];
+      if (this.allMessages.length - (currentLoadedCount + countToLoad) <= 0) {
+        this.showLoadMore = false;
+      }
+      if (oldTopMessageId) {
+        this.$nextTick(() => {
+          this.scrollWithAnimation = false; // 加载更多时不使用动画
+          this.scrollIntoView = "message-" + oldTopMessageId;
+        });
+      }
+    },
+
     // 获取主机地址
     // 获取主机地址
     getHost() {
     getHost() {
       // #ifdef H5
       // #ifdef H5
@@ -587,7 +651,7 @@ export default {
 
 
         // 滚动到底部
         // 滚动到底部
         this.$nextTick(() => {
         this.$nextTick(() => {
-          this.scrollToBottom();
+          this.scrollToBottom(); // 用户操作时使用动画
         });
         });
       } catch (error) {
       } catch (error) {
         console.error('解析WebSocket消息失败:', error, data);
         console.error('解析WebSocket消息失败:', error, data);
@@ -629,7 +693,7 @@ export default {
 
 
         // 滚动到底部
         // 滚动到底部
         this.$nextTick(() => {
         this.$nextTick(() => {
-          this.scrollToBottom();
+          this.scrollToBottom(); // 用户操作时使用动画
         });
         });
 
 
         // 构建要发送的消息数据
         // 构建要发送的消息数据
@@ -678,9 +742,10 @@ export default {
     },
     },
 
 
     // 滚动到底部
     // 滚动到底部
-    scrollToBottom() {
+    scrollToBottom(enableAnimation = true) {
+      this.scrollWithAnimation = enableAnimation;
       if (this.messageList.length > 0) {
       if (this.messageList.length > 0) {
-        this.scrollIntoView = 'message-' + (this.messageList.length - 1);
+        this.scrollIntoView = "message-" + this.messageList[this.messageList.length - 1].id;
       }
       }
     },
     },
 
 
@@ -746,6 +811,16 @@ export default {
   overflow-y: auto;
   overflow-y: auto;
 }
 }
 
 
+.load-more {
+  text-align: center;
+  padding: 20upx 0;
+  .load-more-text {
+    color: #007aff;
+    font-size: 28upx;
+    cursor: pointer;
+  }
+}
+
 .message-item {
 .message-item {
   margin-bottom: 30upx;
   margin-bottom: 30upx;
 
 

+ 89 - 8
mallApp/src/pages/chat/chatPage.vue

@@ -13,13 +13,18 @@
       :scroll-top="scrollTop"
       :scroll-top="scrollTop"
       scroll-y
       scroll-y
       :scroll-into-view="scrollIntoView"
       :scroll-into-view="scrollIntoView"
-      scroll-with-animation
+      :scroll-with-animation="scrollWithAnimation"
+      @scrolltoupper="loadMoreMessages"
     >
     >
+      <!-- 加载更多 -->
+      <view class="load-more" v-if="showLoadMore" @click="loadMoreMessages">
+        <text class="load-more-text">加载更多</text>
+      </view>
       <view
       <view
         class="message-item"
         class="message-item"
         v-for="(message, index) in messageList"
         v-for="(message, index) in messageList"
         :key="index"
         :key="index"
-        :id="'message-' + index"
+        :id="'message-' + message.id"
       >
       >
         <!-- 左侧消息(商家/其他用户) -->
         <!-- 左侧消息(商家/其他用户) -->
         <view class="message-left" v-if="!message.isMine && !message.customId">
         <view class="message-left" v-if="!message.isMine && !message.customId">
@@ -120,10 +125,16 @@ export default {
       // WebSocket相关
       // WebSocket相关
       socket: null,
       socket: null,
       isConnected: false,
       isConnected: false,
-      room: "",
+      room: '',
       reconnectCount: 0,
       reconnectCount: 0,
       maxReconnectCount: 3,
       maxReconnectCount: 3,
       isManualDisconnect: false, // 添加标志位:是否主动断开连接
       isManualDisconnect: false, // 添加标志位:是否主动断开连接
+      scrollWithAnimation: false, // 控制滚动动画
+      // 分页加载
+      allMessages: [], // 存储所有从API获取的消息
+      initialLoadSize: 50, // 首次加载数量
+      loadMoreSize: 100, // 每次加载更多的数量
+      showLoadMore: false, // 是否显示“加载更多”
       // 键盘相关
       // 键盘相关
       keyboardHeight: 0, // 键盘高度
       keyboardHeight: 0, // 键盘高度
       isKeyboardShow: false, // 键盘是否显示
       isKeyboardShow: false, // 键盘是否显示
@@ -222,14 +233,72 @@ export default {
         userId: userId,
         userId: userId,
       }).then((res) => {
       }).then((res) => {
         if (res.code == 1 && res.data) {
         if (res.code == 1 && res.data) {
-          this.messageList = res.data;
+          this.allMessages = res.data.map((item, index) => ({
+            ...item,
+            id: `msg_${index}`, // 为每条消息添加唯一ID
+          }));
+
+          if (this.allMessages.length > this.initialLoadSize) {
+            // 如果消息总数超过首次加载数量,则只显示最新的50条
+            this.messageList = this.allMessages.slice(
+              this.allMessages.length - this.initialLoadSize
+            );
+            this.showLoadMore = true;
+          } else {
+            // 否则,全部显示
+            this.messageList = this.allMessages;
+            this.showLoadMore = false;
+          }
+
           this.$nextTick(() => {
           this.$nextTick(() => {
-            this.scrollToBottom();
+            this.scrollToBottom(false); // 初始加载时不使用动画
           });
           });
         }
         }
       });
       });
     },
     },
 
 
+    // 加载更多历史记录
+    loadMoreMessages() {
+      if (!this.showLoadMore) {
+        return;
+      }
+
+      // 计算当前已显示消息在 allMessages 中的起始索引
+      const currentLoadedCount = this.messageList.length;
+      const remainingMessagesCount = this.allMessages.length - currentLoadedCount;
+      if (remainingMessagesCount <= 0) {
+        this.showLoadMore = false;
+        return;
+      }
+
+      // 确定本次要加载的消息数量
+      const countToLoad = Math.min(this.loadMoreSize, remainingMessagesCount);
+      // 获取更早的消息
+      const moreMessages = this.allMessages.slice(
+        remainingMessagesCount - countToLoad,
+        remainingMessagesCount
+      );
+
+      // 记录加载前最顶部的消息ID
+      const oldTopMessageId = this.messageList.length > 0 ? this.messageList[0].id : null;
+
+      // 将新加载的消息添加到列表的开头
+      this.messageList = [...moreMessages, ...this.messageList];
+
+      // 更新“加载更多”按钮的状态
+      if (this.allMessages.length - (currentLoadedCount + countToLoad) <= 0) {
+        this.showLoadMore = false;
+      }
+      
+      // 保持滚动位置
+      if (oldTopMessageId) {
+        this.$nextTick(() => {
+          this.scrollWithAnimation = false; // 加载更多时不使用动画
+          this.scrollIntoView = "message-" + oldTopMessageId;
+        });
+      }
+    },
+
     // 获取主机地址
     // 获取主机地址
     getHost() {
     getHost() {
       // #ifdef H5
       // #ifdef H5
@@ -662,7 +731,7 @@ export default {
 
 
         // 滚动到底部
         // 滚动到底部
         this.$nextTick(() => {
         this.$nextTick(() => {
-          this.scrollToBottom();
+          this.scrollToBottom(); // 用户操作时使用动画
         });
         });
 
 
         // 构建要发送的消息数据
         // 构建要发送的消息数据
@@ -713,9 +782,11 @@ export default {
     },
     },
 
 
     // 滚动到底部
     // 滚动到底部
-    scrollToBottom() {
+    scrollToBottom(enableAnimation = true) {
+      this.scrollWithAnimation = enableAnimation;
       if (this.messageList.length > 0) {
       if (this.messageList.length > 0) {
-        this.scrollIntoView = "message-" + (this.messageList.length - 1);
+        this.scrollIntoView =
+          "message-" + this.messageList[this.messageList.length - 1].id;
       }
       }
     },
     },
 
 
@@ -782,6 +853,16 @@ export default {
   overflow-y: auto;
   overflow-y: auto;
 }
 }
 
 
+.load-more {
+  text-align: center;
+  padding: 20upx 0;
+  .load-more-text {
+    color: #007aff;
+    font-size: 28upx;
+    cursor: pointer;
+  }
+}
+
 .message-item {
 .message-item {
   margin-bottom: 30upx;
   margin-bottom: 30upx;