Browse Source

监听输入框触发滚动到最新消息

wkw 1 week ago
parent
commit
f9d34fb1dd
1 changed files with 52 additions and 10 deletions
  1. 52 10
      src/views/im/chat/index.vue

+ 52 - 10
src/views/im/chat/index.vue

@@ -9,7 +9,7 @@
     </div>
 
     <!-- 聊天消息区域 -->
-    <div class="chat-list">
+    <div class="chat-list" ref="chatListRef">
       <div v-for="(item, index) in wsStore.messages" :key="index">
         <div class="chat-time">{{ formatTime(item.timestamp || Date.now()) }}</div>
         <div class="box">
@@ -48,17 +48,17 @@
           placeholder="输入文本"
           @keyup.enter="sendMessage"
         />
-        <svg-icon class="page-icon mr12" name="emoji" @click="toggleAppBox(1)" />
-        <svg-icon class="page-icon" name="add2" @click="toggleAppBox(2)" />
+        <svg-icon class="page-icon mr12 emoji-toggle" name="emoji" @click="toggleAppBox(1)" />
+        <svg-icon class="page-icon tools-toggle" name="add2" @click="toggleAppBox(2)" />
       </div>
 
       <!-- 表情面板 -->
-      <div class="app-box" v-show="showEmoji" :style="{ height: `${appBoxHeight}px` }">
+      <div class="app-box" v-show="showEmoji" :style="{ height: `${appBoxHeight}px` }" ref="emojiRef">
         😀 😃 😄 😁 😆 😅 😂 🤣 😊 😇 🙂 🙃 😉 😌 😍
       </div>
 
       <!-- 工具栏面板 -->
-      <div class="app-box" v-show="showTools" :style="{ height: `${appBoxHeight}px` }">
+      <div class="app-box" v-show="showTools" :style="{ height: `${appBoxHeight}px` }" ref="toolsRef">
         <div class="tool-btn">
           <svg-icon class="tool-icon" name="tp" />
           <div>图片</div>
@@ -73,7 +73,7 @@
 </template>
 
 <script setup>
-import { ref, computed, onMounted, onUnmounted } from "vue";
+import { ref, computed, onMounted, onUnmounted,onBeforeUnmount } from "vue";
 import { useRouter, useRoute } from "vue-router";
 import { useWebSocketStore } from "@/stores/modules/webSocketStore.js";
 import { useWalletStore } from "@/stores/modules/walletStore.js";
@@ -95,6 +95,19 @@ const keyboardHeight = ref(0);
 const showEmoji = ref(false);
 const showTools = ref(false);
 const appBoxHeight = ref(210);
+const chatListRef = ref(null);
+const emojiRef = ref(null);
+const toolsRef = ref(null);
+
+// 滚动到底部
+const scrollToBottom = () => {
+  nextTick(() => {
+    if (chatListRef.value) {
+      const el = chatListRef.value;
+      el.scrollTop = el.scrollHeight;
+    }
+  });
+};
 
 // 平台判断
 const isMobile = Capacitor.getPlatform() !== "web";
@@ -128,10 +141,8 @@ const onFocus = () => {
   // 隐藏所有面板
   showEmoji.value = false;
   showTools.value = false;
-  // 判断是不是web
-  if (Capacitor.getPlatform() != "web") {
-    setupKeyboardListeners();
-  }
+  if (isMobile) setupKeyboardListeners();
+  scrollToBottom();
 };
 
 // 键盘监听
@@ -228,6 +239,7 @@ const sendMessage = () => {
   };
   wsStore.sendMessage(message);
   text.value = "";
+  scrollToBottom();
 };
 
 // 时间格式化
@@ -245,11 +257,41 @@ onMounted(() => {
     messageType: 1,
     friendUsername: route.query.uuid,
   });
+  scrollToBottom();
+  document.addEventListener('click', handleClickOutside);
 });
 
 onUnmounted(() => {
   if (isMobile) Keyboard.removeAllListeners();
 });
+onBeforeUnmount(() => {
+  document.removeEventListener('click', handleClickOutside);
+});
+
+// 判断是否点击在元素外
+const handleClickOutside = (event) => {
+  const emojiEl = emojiRef.value;
+  const toolsEl = toolsRef.value;
+  const target = event.target;
+
+  if (
+    showEmoji.value &&
+    emojiEl &&
+    !emojiEl.contains(target) &&
+    !target.closest('.emoji-toggle')
+  ) {
+    showEmoji.value = false;
+  }
+
+  if (
+    showTools.value &&
+    toolsEl &&
+    !toolsEl.contains(target) &&
+    !target.closest('.tools-toggle')
+  ) {
+    showTools.value = false;
+  }
+};
 
 // 页面跳转
 const goBack = () => router.push("im");