fix(room): 新消息自动滚动到底部

This commit is contained in:
liumangmang
2026-03-06 15:06:14 +08:00
parent 07b92f0d96
commit e4ae3445f7

View File

@@ -28,7 +28,11 @@
<!-- 右侧消息与输入区域 -->
<section class="flex-1 flex flex-col bg-slate-100/80 min-w-0">
<div ref="messageListRef" class="flex-1 overflow-auto px-4 sm:px-6 py-4">
<div
ref="messageListRef"
class="flex-1 overflow-auto px-4 sm:px-6 py-4"
@scroll="handleMessageListScroll"
>
<div class="max-w-2xl mx-auto space-y-4">
<template v-for="(msg, index) in wsStore.roomMessages" :key="messageKey(msg, index)">
<SystemMessage
@@ -92,7 +96,7 @@
</template>
<script setup lang="ts">
import { computed, ref, watch, onMounted } from 'vue';
import { computed, ref, watch, onMounted, nextTick } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import BaseButton from '@/components/ui/BaseButton.vue';
import RoomPanel from '@/components/RoomPanel.vue';
@@ -119,10 +123,34 @@ const joinToken = computed(() => {
});
const messageListRef = ref<HTMLElement | null>(null);
const shouldAutoScroll = ref(true);
const wsStore = useWsStore();
const downloadToast = ref('');
let downloadToastTimer: ReturnType<typeof setTimeout> | null = null;
function isNearBottom(element: HTMLElement): boolean {
const threshold = 72;
return element.scrollHeight - element.scrollTop - element.clientHeight <= threshold;
}
function scrollToBottom(behavior: ScrollBehavior = 'smooth'): void {
const container = messageListRef.value;
if (!container) return;
container.scrollTo({ top: container.scrollHeight, behavior });
}
function handleMessageListScroll(): void {
const container = messageListRef.value;
if (!container) return;
shouldAutoScroll.value = isNearBottom(container);
}
function isLastMessageMine(): boolean {
const last = wsStore.roomMessages[wsStore.roomMessages.length - 1];
if (!last) return false;
return !!last.senderId && last.senderId === wsStore.myUserId;
}
const transferStats = computed(() => {
let sendingCount = 0;
let receivingCount = 0;
@@ -160,8 +188,19 @@ function showDownloadToast(message: string) {
onMounted(() => {
wsStore.init(API_BASE, '/ws');
wsStore.connect();
void nextTick(() => scrollToBottom('auto'));
});
watch(
() => wsStore.roomMessages.length,
async (nextLen, prevLen) => {
if (nextLen <= prevLen) return;
if (!shouldAutoScroll.value && !isLastMessageMine()) return;
await nextTick();
scrollToBottom();
},
);
watch(
() => wsStore.status,
(status) => {