Parcourir la source

直播中控台

yuhongqi il y a 3 jours
Parent
commit
496c18d184
1 fichiers modifiés avec 137 ajouts et 23 suppressions
  1. 137 23
      src/views/live/liveConsole/LiveConsole.vue

+ 137 - 23
src/views/live/liveConsole/LiveConsole.vue

@@ -111,8 +111,9 @@
             全局用户自见
           </label>
         </div>
-        <el-scrollbar class="custom-scrollbar" style="height: 500px; width: 100%;" ref="manageRightRef">
-          <el-row v-for="m in msgList" :key="m.msgId">
+        <div class="message-container" @click="handleMessageBoxClick">
+          <el-scrollbar class="custom-scrollbar" style="height: 500px; width: 100%;" ref="manageRightRef">
+            <el-row v-for="m in msgList" :key="m.msgId">
             <el-row v-if="m.userId === userId && m.msgId == null" style="padding: 8px 0" type="flex" align="top" justify="end">
               <div style="display: flex;justify-content: flex-end">
                 <div style="display: flex;justify-content: flex-end;flex-direction: column;max-width: 200px;align-items: flex-end">
@@ -133,11 +134,11 @@
                     </div>
                   </el-col>
                   <el-col>
-                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="changeUserState(m)">{{ m.msgStatus === 1 ? '解禁' : '禁言' }}</a>
-                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="blockUser(m)">拉黑</a>
-                    <a v-if="m.singleVisible === 1" style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="singleVisible(m)">解除用户自见</a>
-                    <a v-else style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="singleVisible(m)">用户自见</a>
-                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="deleteMsg(m)">删除</a>
+                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click.stop="changeUserState(m)">{{ m.msgStatus === 1 ? '解禁' : '禁言' }}</a>
+                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click.stop="blockUser(m)">拉黑</a>
+                    <a v-if="m.singleVisible === 1" style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click.stop="singleVisible(m)">解除用户自见</a>
+                    <a v-else style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click.stop="singleVisible(m)">用户自见</a>
+                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click.stop="deleteMsg(m)">删除</a>
                   </el-col>
                 </el-row>
               </el-col>
@@ -146,7 +147,18 @@
           </el-row>
           <!-- 底部留白 -->
           <div style="height: 20px;"></div>
-        </el-scrollbar>
+          </el-scrollbar>
+          <!-- 加载最新消息按钮 -->
+          <el-button 
+            v-if="showLoadLatestBtn" 
+            class="load-latest-btn" 
+            type="primary" 
+            size="small" 
+            @click.stop="loadLatestMessages"
+            icon="el-icon-refresh">
+            加载最新消息
+          </el-button>
+        </div>
         <!--        <div class="message-list">-->
         <!--          <div class="message-item" v-for="msg in msgList" :key="msg.id">-->
         <!--            <div class="message-avatar">-->
@@ -391,6 +403,15 @@ export default {
       topMsgForm: {
         msg: '',
         duration: 5
+      },
+      // 消息滚动控制
+      isAutoScrollEnabled: true, // 是否启用自动滚动
+      autoScrollTimer: null, // 自动滚动定时器
+      showLoadLatestBtn: false, // 是否显示加载最新消息按钮
+      msgParams: {
+        pageNum: 1,
+        pageSize: 30,
+        liveId: null
       }
     };
   },
@@ -432,6 +453,65 @@ export default {
     this.initScrollListeners();
   },
   methods: {
+    // 点击消息框
+    handleMessageBoxClick() {
+      // 点击消息框时,停止自动滚动
+      this.isAutoScrollEnabled = false;
+      // 停止自动滚动定时器
+      if (this.autoScrollTimer) {
+        clearTimeout(this.autoScrollTimer);
+        this.autoScrollTimer = null;
+      }
+      // 检查是否在底部,如果不在底部则显示加载最新消息按钮
+      this.$nextTick(() => {
+        if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+          const wrap = this.$refs.manageRightRef.wrap;
+          const scrollHeight = wrap.scrollHeight;
+          const clientHeight = wrap.clientHeight;
+          const currentScrollTop = wrap.scrollTop;
+          const maxScrollTop = scrollHeight - clientHeight;
+          
+          if (currentScrollTop < maxScrollTop - 50) {
+            this.showLoadLatestBtn = true;
+          }
+        }
+      });
+    },
+    // 滚动到底部
+    scrollToBottom(forceScroll = false) {
+      // 如果自动滚动被禁用且不是强制滚动,则不执行
+      if (!this.isAutoScrollEnabled && !forceScroll) {
+        return;
+      }
+      
+      if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+        this.$nextTick(() => {
+          const wrap = this.$refs.manageRightRef.wrap;
+          if (!wrap) return;
+          
+          const scrollHeight = wrap.scrollHeight;
+          const clientHeight = wrap.clientHeight;
+          const currentScrollTop = wrap.scrollTop;
+          const maxScrollTop = scrollHeight - clientHeight;
+          
+          // 强制滚动或启用自动滚动时,直接滚动到底部并隐藏按钮
+          if (forceScroll || this.isAutoScrollEnabled) {
+            this.showLoadLatestBtn = false;
+            wrap.scrollTop = maxScrollTop;
+          }
+        });
+      }
+    },
+    // 加载最新消息
+    loadLatestMessages() {
+      this.showLoadLatestBtn = false;
+      // 恢复自动滚动
+      this.isAutoScrollEnabled = true;
+      // 重新请求最新消息
+      this.resetMsgParams();
+      // loadMsgList 中会自动滚动到底部,因为 isAutoScrollEnabled 已经是 true
+      this.loadMsgList();
+    },
     singleVisible(m){
       // 过滤当前所有消息 找到userId的相同的消息 更改他们的自可见状态
       m.singleVisible= m.singleVisible === 1 ? 0 : 1
@@ -638,12 +718,17 @@ export default {
             this.msgList.shift()
           }
           this.msgList.push(message)
-          // 移动到底部
-          this.$nextTick(() => {
-            setTimeout(() => {
-              this.$refs.manageRightRef.wrap.scrollTop = this.$refs.manageRightRef.wrap.scrollHeight - this.$refs.manageRightRef.wrap.clientHeight
-            }, 200)
-          })
+          // 如果启用自动滚动,自动滚动到底部
+          if (this.isAutoScrollEnabled) {
+            this.$nextTick(() => {
+              this.autoScrollTimer = setTimeout(() => {
+                this.scrollToBottom();
+              }, 200);
+            });
+          } else {
+            // 自动滚动被禁用时,显示加载最新消息按钮
+            this.showLoadLatestBtn = true;
+          }
         } else if (cmd === 'entry' || cmd === 'out') {
           const user = data;
           const online = cmd === 'entry' ? 0 : 1; // 0=在线,1=离线
@@ -1077,22 +1162,13 @@ export default {
           let totalPage = (total % this.msgParams.pageSize == 0) ? Math.floor(total / this.msgParams.pageSize) : Math.floor(total / this.msgParams.pageSize + 1);
           rows.forEach(row => {
             if (!this.msgList.some(m => m.msgId === row.msgId)) {
-
               let user = this.alDisplayList.find(u => u.userId === row.userId)
               if (user) {
                 row.msgStatus = user.msgStatus
               } else {
                 row.msgStatus = 0
               }
-
               this.msgList.push(row)
-
-              // 移动到底部
-              this.$nextTick(() => {
-                setTimeout(() => {
-                  this.$refs.manageRightRef.wrap.scrollTop = this.$refs.manageRightRef.wrap.scrollHeight - this.$refs.manageRightRef.wrap.clientHeight
-                }, 200)
-              })
             }
           })
 
@@ -1101,6 +1177,30 @@ export default {
           this.alDisplayList.forEach(u => {
             this.msgList.filter(m => m.userId === u.userId).forEach(m => m.msgStatus = u.msgStatus)
           })
+          // 所有消息加载完成后,根据自动滚动状态决定是否滚动
+          this.$nextTick(() => {
+            setTimeout(() => {
+              if (this.isAutoScrollEnabled) {
+                // 如果启用自动滚动,强制滚动到底部并隐藏按钮
+                this.scrollToBottom(true);
+              } else {
+                // 如果禁用自动滚动,检查是否在底部,决定是否显示按钮
+                if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
+                  const wrap = this.$refs.manageRightRef.wrap;
+                  const scrollHeight = wrap.scrollHeight;
+                  const clientHeight = wrap.clientHeight;
+                  const currentScrollTop = wrap.scrollTop;
+                  const maxScrollTop = scrollHeight - clientHeight;
+                  
+                  if (currentScrollTop < maxScrollTop - 50) {
+                    this.showLoadLatestBtn = true;
+                  } else {
+                    this.showLoadLatestBtn = false;
+                  }
+                }
+              }
+            }, 300);
+          });
         }
       })
 
@@ -1201,6 +1301,7 @@ export default {
         pageSize: 30,
         liveId: this.liveId
       };
+      // 重置时不改变按钮状态,由后续的滚动逻辑决定
       this.taskParams = {
         currentPage: 1,
         pageSize: 20,
@@ -1321,6 +1422,9 @@ export default {
     if (this.autoMsgTimer != null) {
       clearInterval(this.autoMsgTimer);
     }
+    if (this.autoScrollTimer) {
+      clearTimeout(this.autoScrollTimer);
+    }
   },
   // 使用 deactivated 和 activated 钩子替代 beforeDestroy 和 destroyed
   deactivated() {
@@ -1624,4 +1728,14 @@ export default {
   text-align: center;
   border-radius: 4px;
 }
+.message-container {
+  position: relative;
+}
+.load-latest-btn {
+  position: absolute;
+  bottom: 20px;
+  right: 20px;
+  z-index: 10;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+}
 </style>