|
|
@ -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(); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
|
|
|
|