mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-20 15:19:41 +08:00
feat: add force scroll option to intelligent message scrolling in ShortcutBar and MessageView
This commit is contained in:
@@ -11,6 +11,10 @@ type MessageViewExpose = {
|
||||
refreshLatestMessages?: () => Promise<void> | void
|
||||
}
|
||||
|
||||
type MessageScrollPayload = {
|
||||
force?: boolean
|
||||
}
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -165,14 +169,19 @@ async function openMessageDialog() {
|
||||
})
|
||||
}
|
||||
|
||||
// 智能滚动到底部(只有用户在底部附近时才滚动)
|
||||
function scrollMessageToEnd() {
|
||||
// 智能滚动到底部:首次打开时允许强制滚动,后续实时消息尊重用户当前位置。
|
||||
function scrollMessageToEnd(payload?: MessageScrollPayload) {
|
||||
// 使用更长的延迟确保DOM已更新
|
||||
setTimeout(() => {
|
||||
try {
|
||||
// 查找消息弹窗的滚动容器
|
||||
const cardText = document.querySelector('.v-dialog .v-card-text')
|
||||
if (cardText) {
|
||||
if (payload?.force) {
|
||||
cardText.scrollTop = cardText.scrollHeight
|
||||
return
|
||||
}
|
||||
|
||||
const { scrollTop, scrollHeight, clientHeight } = cardText
|
||||
// 计算距离底部的距离
|
||||
const distanceFromBottom = scrollHeight - scrollTop - clientHeight
|
||||
|
||||
@@ -9,8 +9,14 @@ import { useBackgroundOptimization } from '@/composables/useBackgroundOptimizati
|
||||
const { t } = useI18n()
|
||||
const { useSSE } = useBackgroundOptimization()
|
||||
|
||||
type ScrollPayload = {
|
||||
force?: boolean
|
||||
}
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['scroll'])
|
||||
const emit = defineEmits<{
|
||||
(e: 'scroll', payload?: ScrollPayload): void
|
||||
}>()
|
||||
|
||||
// 消息列表
|
||||
const messages = ref<Message[]>([])
|
||||
@@ -66,6 +72,13 @@ function updateLastTime(message: Message) {
|
||||
}
|
||||
}
|
||||
|
||||
// 请求父组件滚动,首屏历史消息需要强制到底,实时消息继续使用智能滚动。
|
||||
function requestScrollToEnd(force = false) {
|
||||
nextTick(() => {
|
||||
emit('scroll', { force })
|
||||
})
|
||||
}
|
||||
|
||||
// 合并消息到当前列表
|
||||
function mergeMessages(items: Message[]) {
|
||||
let hasNewMessage = false
|
||||
@@ -95,9 +108,7 @@ function handleSSEMessage(event: MessageEvent) {
|
||||
if (message) {
|
||||
const object = JSON.parse(message)
|
||||
if (mergeMessages([object])) {
|
||||
nextTick(() => {
|
||||
emit('scroll') // 新消息到达时触发智能滚动
|
||||
})
|
||||
requestScrollToEnd() // 新消息到达时触发智能滚动
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,9 +148,7 @@ async function loadMessages({ done }: { done: any }) {
|
||||
|
||||
// 首次加载时滚动到底部
|
||||
if (page.value === 1 && hasNewMessage) {
|
||||
nextTick(() => {
|
||||
emit('scroll')
|
||||
})
|
||||
requestScrollToEnd(true)
|
||||
}
|
||||
// 页码+1
|
||||
page.value++
|
||||
@@ -168,9 +177,7 @@ async function refreshLatestMessages() {
|
||||
})) as Message[]
|
||||
|
||||
if (mergeMessages(latestMessages)) {
|
||||
nextTick(() => {
|
||||
emit('scroll')
|
||||
})
|
||||
requestScrollToEnd()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('刷新最新消息失败:', error)
|
||||
@@ -206,7 +213,7 @@ function compareTime(time1: string, time2: string) {
|
||||
|
||||
// 图片加载完成时触发智能滚动
|
||||
function handleImageLoad() {
|
||||
emit('scroll')
|
||||
requestScrollToEnd()
|
||||
}
|
||||
|
||||
// 暂停SSE连接
|
||||
@@ -236,9 +243,7 @@ defineExpose({
|
||||
|
||||
onMounted(() => {
|
||||
// 组件挂载后触发一次滚动事件
|
||||
nextTick(() => {
|
||||
emit('scroll')
|
||||
})
|
||||
requestScrollToEnd()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user