feat(pc): 详情页增加吸顶返回列表按钮,首页按筛选签名恢复滚动位置
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { RouterLink, useRoute, useRouter } from 'vue-router'
|
||||
import { RouterLink, onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
defaultAWRecycleConfig,
|
||||
defaultHomeAnnouncements,
|
||||
@@ -164,6 +164,7 @@ async function loadHome() {
|
||||
publishOptions.value = emptyListingPublishOptions
|
||||
} finally {
|
||||
loading.value = false
|
||||
restorePcHomeScroll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +269,63 @@ function buildDesktopHomeQueryValues(): Record<string, HomeQueryValue> {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== PC 首页滚动位置持久化 ==========
|
||||
// 详情页返回/浏览器后退时,首页列表异步加载导致页面高度不足,
|
||||
// vue-router 的 savedPosition 恢复会被浏览器钳制到错误位置,
|
||||
// 因此按「筛选签名」显式保存/恢复滚动位置,确保回到上次筛选的位置。
|
||||
const pcHomeScrollStorageKey = 'hfb.home.scroll.desktop'
|
||||
|
||||
function savePcHomeScroll() {
|
||||
try {
|
||||
window.sessionStorage.setItem(
|
||||
pcHomeScrollStorageKey,
|
||||
JSON.stringify({ signature: desktopHomeStateSignature(), top: window.scrollY })
|
||||
)
|
||||
} catch {
|
||||
// sessionStorage 不可用时忽略,仅损失滚动恢复
|
||||
}
|
||||
}
|
||||
|
||||
function restorePcHomeScroll() {
|
||||
let savedTop = 0
|
||||
let savedSignature = ''
|
||||
try {
|
||||
const raw = window.sessionStorage.getItem(pcHomeScrollStorageKey)
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw) as { signature?: string; top?: number }
|
||||
if (typeof parsed.signature === 'string' && typeof parsed.top === 'number') {
|
||||
savedSignature = parsed.signature
|
||||
savedTop = parsed.top
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
// 仅当返回时的筛选条件与离开时一致才恢复,避免把滚动带到别的筛选结果上
|
||||
if (savedTop <= 0 || savedSignature !== desktopHomeStateSignature()) return
|
||||
|
||||
let attempts = 0
|
||||
const apply = () => {
|
||||
const maxTop = Math.max(0, document.documentElement.scrollHeight - window.innerHeight)
|
||||
if (savedTop <= maxTop) {
|
||||
window.scrollTo({ top: savedTop })
|
||||
return
|
||||
}
|
||||
// 首页无限滚动分页:已渲染高度不足时继续加载一页后重试,尽量恢复到位
|
||||
if (attempts < 5 && hasMoreListings.value && !loadingMore.value) {
|
||||
attempts += 1
|
||||
void loadListingsPage(false).then(() => requestAnimationFrame(apply))
|
||||
} else {
|
||||
window.scrollTo({ top: maxTop })
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(apply)
|
||||
}
|
||||
|
||||
onBeforeRouteLeave(() => {
|
||||
savePcHomeScroll()
|
||||
})
|
||||
|
||||
syncHomeQuery()
|
||||
loadHome()
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user