|
|
@ -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; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 声明组件可以触发的事件 |
|
|
|