export default defineNuxtPlugin((nuxtApp) => { if (typeof window === 'undefined') return let observer: IntersectionObserver | null = null let headings: HTMLElement[] = [] function initScrollSpy() { // 清理旧的 observer if (observer) observer.disconnect() // 收集所有带 id 的标题 headings = Array.from(document.querySelectorAll('.prose h2[id], .prose h3[id]')) as HTMLElement[] if (headings.length === 0) return observer = new IntersectionObserver( (entries) => { for (const entry of entries) { if (entry.isIntersecting) { const id = entry.target.getAttribute('id') if (id) { history.replaceState(null, '', `#${id}`) } } } }, { rootMargin: '-80px 0px -70% 0px' } ) headings.forEach(h => observer!.observe(h)) } // 路由切换后重新初始化 const router = useRouter() router.afterEach(() => { nextTick(() => { setTimeout(initScrollSpy, 100) }) }) // 首次加载 nuxtApp.hook('app:mounted', () => { setTimeout(initScrollSpy, 100) }) })