From 49af4ed7db30ea7a9dee4edb2d8a7fcd1f90fe84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E6=9D=B0?= Date: Fri, 4 Jul 2025 16:38:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BA=86=E6=83=85=E7=BB=AA?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=E6=8A=A2=E9=BC=A0=E6=A0=87=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/AiEmotion.vue | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/views/AiEmotion.vue b/src/views/AiEmotion.vue index c6c4411..1ac817e 100644 --- a/src/views/AiEmotion.vue +++ b/src/views/AiEmotion.vue @@ -248,6 +248,8 @@ const hasTriggeredAudio = ref(false); // 是否已触发音频播放 const hasTriggeredTypewriter = ref(false); // 是否已触发打字机效果 const intersectionObserver = ref(null); // 存储observer实例 const isUserInitiated = ref(false); // 标记是否为用户主动搜索 +const isUserScrolling = ref(false); // 标记用户是否正在手动滚动 +const scrollTimeout = ref(null); // 滚动超时定时器 // 显示的文本内容(用于打字机效果) const displayedTexts = ref({ @@ -756,6 +758,12 @@ function startTypewriterEffect(conclusion) { for (let i = 0; i <= disclaimerText.length; i++) { const timer = setTimeout(() => { displayedTexts.value.disclaimer = disclaimerText.substring(0, i); + // 在打字机效果的最后一个字符显示完成后,滚动到底部 + if (i === disclaimerText.length) { + setTimeout(() => { + scrollToBottom(); + }, 100); + } }, totalDelay + i * typeSpeed); typewriterTimers.value.push(timer); } @@ -804,6 +812,10 @@ function playAudio(url) { isAudioPlaying.value = true; emotionAudioStore.isPlaying = true; console.log('开始播放场景应用语音'); + // 音频开始播放时,滚动到底部 + setTimeout(() => { + scrollToBottom(); + }, 100); }, onend: () => { isAudioPlaying.value = false; @@ -1155,6 +1167,12 @@ function renderCharts(data) { } const scrollToBottom = async () => { + // 如果用户正在手动滚动,则不执行自动滚动 + if (isUserScrolling.value) { + console.log('用户正在手动滚动,跳过自动滚动'); + return; + } + const container = userInputDisplayRef.value; if (!container) return; await nextTick(); @@ -1164,6 +1182,32 @@ const scrollToBottom = async () => { container.scrollTop = container.scrollHeight - container.offsetHeight; }; +// 处理用户滚动事件 +const handleUserScroll = () => { + isUserScrolling.value = true; + + // 清除之前的定时器 + if (scrollTimeout.value) { + clearTimeout(scrollTimeout.value); + } + + // 设置定时器,2秒后重新允许自动滚动 + scrollTimeout.value = setTimeout(() => { + isUserScrolling.value = false; + console.log('用户滚动结束,重新允许自动滚动'); + }, 2000); +}; + +// 处理滚轮事件 +const handleWheel = (event) => { + handleUserScroll(); +}; + +// 处理触摸滚动事件 +const handleTouchMove = (event) => { + handleUserScroll(); +}; + // 检查数据是否已加载完成 function isDataLoaded() { @@ -1364,6 +1408,14 @@ onMounted(async () => { // 添加新的监听器 window.addEventListener('resize', globalResizeHandler); window.aiEmotionGlobalResizeHandler = globalResizeHandler; + + // 添加滚动事件监听器 + const container = userInputDisplayRef.value; + if (container) { + container.addEventListener('wheel', handleWheel, { passive: true }); + container.addEventListener('touchmove', handleTouchMove, { passive: true }); + container.addEventListener('scroll', handleUserScroll, { passive: true }); + } // 防抖函数定义 function debounce(func, wait) { @@ -1436,6 +1488,20 @@ onUnmounted(() => { window.removeEventListener('resize', window.aiEmotionGlobalResizeHandler); window.aiEmotionGlobalResizeHandler = null; } + + // 清理滚动事件监听器 + const container = userInputDisplayRef.value; + if (container) { + container.removeEventListener('wheel', handleWheel); + container.removeEventListener('touchmove', handleTouchMove); + container.removeEventListener('scroll', handleUserScroll); + } + + // 清理滚动定时器 + if (scrollTimeout.value) { + clearTimeout(scrollTimeout.value); + scrollTimeout.value = null; + } }); // 声明组件可以触发的事件