From 06acfb4369339af8e26fa0f6431f788342524cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E6=9D=B0?= Date: Mon, 18 Aug 2025 13:49:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=83=85=E7=BB=AA=E5=A4=A7=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=BB=9A=E5=8A=A8=E6=9C=80=E5=BA=95=E9=83=A8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/homePage.vue | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/views/homePage.vue b/src/views/homePage.vue index 9396613..e6df4e3 100644 --- a/src/views/homePage.vue +++ b/src/views/homePage.vue @@ -365,6 +365,12 @@ const tabContentAIchat = ref(null); const tabContentAiEmotion = ref(null); const isScrolling = ref(false); //判断用户是否在滚动 +// AiEmotion页面高度监听器相关变量 +const aiEmotionHeightObserver = ref(null); +const isAiEmotionAutoScrollEnabled = ref(false); +const isAiEmotionUserScrolling = ref(false); // 用户是否正在手动滚动 +const aiEmotionScrollTimer = ref(null); // 滚动检测定时器 + // 获取当前活动页面的滚动容器 const getCurrentScrollContainer = () => { if (activeTab.value === 'AIchat') { @@ -398,6 +404,135 @@ const throttledSmoothScrollToBottom = _.throttle(smoothScrollToBottom, 300, { trailing: false, }); +// AiEmotion页面自动滚动到底部的防抖函数 +const debouncedAiEmotionScrollToBottom = _.debounce(() => { + if (activeTab.value === 'AiEmotion' && isAiEmotionAutoScrollEnabled.value && !isAiEmotionUserScrolling.value) { + const container = tabContentAiEmotion.value; + if (container) { + container.scrollTop = container.scrollHeight - container.offsetHeight; + } + } +}, 150); + +// 启动AiEmotion页面高度监听器 +const startAiEmotionHeightObserver = () => { + // 先停止之前的监听器 + stopAiEmotionHeightObserver(); + + isAiEmotionAutoScrollEnabled.value = true; + + // 创建ResizeObserver监听页面内容变化 + aiEmotionHeightObserver.value = new ResizeObserver((entries) => { + if (isAiEmotionAutoScrollEnabled.value && activeTab.value === 'AiEmotion') { + debouncedAiEmotionScrollToBottom(); + } + }); + + // 监听document.body的尺寸变化 + if (document.body) { + aiEmotionHeightObserver.value.observe(document.body); + } + + // 创建MutationObserver监听DOM结构变化 + const mutationObserver = new MutationObserver((mutations) => { + let shouldScroll = false; + mutations.forEach((mutation) => { + if (mutation.type === "childList" && mutation.addedNodes.length > 0) { + // 检查新增的节点是否包含实际内容 + const hasContent = Array.from(mutation.addedNodes).some((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + return node.offsetHeight > 0 || node.scrollHeight > 0; + } + return ( + node.nodeType === Node.TEXT_NODE && + node.textContent.trim().length > 0 + ); + }); + if (hasContent) { + shouldScroll = true; + } + } + }); + + if (shouldScroll && isAiEmotionAutoScrollEnabled.value && activeTab.value === 'AiEmotion') { + debouncedAiEmotionScrollToBottom(); + } + }); + + // 监听AiEmotion页面的主要内容区域的DOM变化 + const aiEmotionContainer = tabContentAiEmotion.value; + if (aiEmotionContainer) { + mutationObserver.observe(aiEmotionContainer, { + childList: true, + subtree: true, + attributes: false, + characterData: true, + }); + } + + // 保存mutationObserver引用以便清理 + aiEmotionHeightObserver.value.mutationObserver = mutationObserver; + + // 为AiEmotion页面的滚动容器添加滚动事件监听器 + if (aiEmotionContainer) { + aiEmotionContainer.addEventListener('scroll', handleAiEmotionUserScroll, { passive: true }); + // 保存滚动事件监听器引用以便清理 + aiEmotionHeightObserver.value.scrollListener = handleAiEmotionUserScroll; + } + + console.log("AiEmotion页面高度监听器已启动"); +}; + +// AiEmotion页面用户滚动检测 +const handleAiEmotionUserScroll = () => { + // 标记用户正在滚动 + isAiEmotionUserScrolling.value = true; + + // 清除之前的定时器 + if (aiEmotionScrollTimer.value) { + clearTimeout(aiEmotionScrollTimer.value); + } + + // 设置定时器,2秒后恢复自动滚动 + aiEmotionScrollTimer.value = setTimeout(() => { + isAiEmotionUserScrolling.value = false; + console.log("AiEmotion页面用户滚动检测:恢复自动滚动"); + }, 2000); +}; + +// 停止AiEmotion页面高度监听器 +const stopAiEmotionHeightObserver = () => { + isAiEmotionAutoScrollEnabled.value = false; + isAiEmotionUserScrolling.value = false; + + // 清理滚动检测定时器 + if (aiEmotionScrollTimer.value) { + clearTimeout(aiEmotionScrollTimer.value); + aiEmotionScrollTimer.value = null; + } + + if (aiEmotionHeightObserver.value) { + // 清理ResizeObserver + aiEmotionHeightObserver.value.disconnect(); + + // 清理MutationObserver + if (aiEmotionHeightObserver.value.mutationObserver) { + aiEmotionHeightObserver.value.mutationObserver.disconnect(); + aiEmotionHeightObserver.value.mutationObserver = null; + } + + // 清理滚动事件监听器 + if (aiEmotionHeightObserver.value.scrollListener && tabContentAiEmotion.value) { + tabContentAiEmotion.value.removeEventListener('scroll', aiEmotionHeightObserver.value.scrollListener); + aiEmotionHeightObserver.value.scrollListener = null; + } + + aiEmotionHeightObserver.value = null; + } + + console.log("AiEmotion页面高度监听器已停止"); +}; + watch( () => chatStore.messages.length, () => { @@ -437,9 +572,18 @@ watch( if (activeTab.value === "AIchat") { isScrolling.value = false; //回复滚动到底部方法 + // 停止AiEmotion页面的高度监听器 + stopAiEmotionHeightObserver(); setTimeout(() => { // throttledSmoothScrollToBottom(); }, 100); + } else if (activeTab.value === "AiEmotion") { + // 启动AiEmotion页面的高度监听器 + await nextTick(); // 确保DOM更新后启动监听器 + startAiEmotionHeightObserver(); + } else { + // 其他页面时停止AiEmotion页面的高度监听器 + stopAiEmotionHeightObserver(); } // AiEmotion页面不执行自动滚动,避免刷新后滚动到底部 // setTimeout(throttledSmoothScrollToBottom, 100); @@ -761,6 +905,8 @@ onUnmounted(() => { console.log("卸载touchmoveHandlerRef组件"); document.removeEventListener("touchmove", touchmoveHandlerRef); } + // 清理AiEmotion页面的高度监听器 + stopAiEmotionHeightObserver(); });