diff --git a/blog.config.js b/blog.config.js
index 81c91c5e..2ca1c0fc 100644
--- a/blog.config.js
+++ b/blog.config.js
@@ -3,8 +3,7 @@
const BLOG = {
// Important page_id!!!Duplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5
NOTION_PAGE_ID:
- process.env.NOTION_PAGE_ID ||
- '02ab3b8678004aa69e9e415905ef32a5,en:7c1d570661754c8fbc568e00a01fd70e',
+ process.env.NOTION_PAGE_ID || '20cb7f4f464a80db8541cbd0da70a64b',
THEME: process.env.NEXT_PUBLIC_THEME || 'typography', // 当前主题,在 themes 文件夹下可找到所有支持的主题;主题名称就是文件夹名,例如 example,fukasawa,gitbook,heo,hexo,landing,matery,medium,next,nobelium,plog,simple
LANG: process.env.NEXT_PUBLIC_LANG || 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.
SINCE: process.env.NEXT_PUBLIC_SINCE || 2021, // e.g if leave this empty, current year will be used.
@@ -20,7 +19,8 @@ const BLOG = {
KEYWORDS: process.env.NEXT_PUBLIC_KEYWORD || 'Notion, 博客', // 网站关键词 英文逗号隔开
BLOG_FAVICON: process.env.NEXT_PUBLIC_FAVICON || '/favicon.ico', // blog favicon 配置,默认使用 /public/favicon.ico,支持在线图片,如 https://img.imesong.com/favicon.png
BEI_AN: process.env.NEXT_PUBLIC_BEI_AN || '', // 备案号 闽 ICP 备 XXXXXX
- BEI_AN_LINK: process.env.NEXT_PUBLIC_BEI_AN_LINK || 'https://beian.miit.gov.cn/', // 备案查询链接,如果用了萌备等备案请在这里填写
+ BEI_AN_LINK:
+ process.env.NEXT_PUBLIC_BEI_AN_LINK || 'https://beian.miit.gov.cn/', // 备案查询链接,如果用了萌备等备案请在这里填写
// RSS 订阅
ENABLE_RSS: process.env.NEXT_PUBLIC_ENABLE_RSS || true, // 是否开启 RSS 订阅功能
diff --git a/themes/typography/components/BlogItem.js b/themes/typography/components/BlogItem.js
index b880f1fe..195f9be2 100644
--- a/themes/typography/components/BlogItem.js
+++ b/themes/typography/components/BlogItem.js
@@ -14,7 +14,6 @@ export const BlogItem = props => {
const showPageCover = siteConfig('SIMPLE_POST_COVER_ENABLE', false, CONFIG)
const showPreview =
siteConfig('POST_LIST_PREVIEW', false, NOTION_CONFIG) && post.blockMap
- console.log(post);
return (
+
{posts?.map((p, index) => (
diff --git a/themes/typography/components/Catalog.js b/themes/typography/components/Catalog.js
index 6bea8bab..e92e586a 100644
--- a/themes/typography/components/Catalog.js
+++ b/themes/typography/components/Catalog.js
@@ -18,38 +18,71 @@ const Catalog = ({ post }) => {
// 监听滚动事件
useEffect(() => {
- const throttleMs = 200
+ // 如果没有文章或目录,不执行任何操作
+ if (!post || !post?.toc || post?.toc?.length < 1) {
+ return
+ }
+
+ const throttleMs = 100 // 降低节流时间提高响应速度
+
const actionSectionScrollSpy = throttle(() => {
const sections = document.getElementsByClassName('notion-h')
+ if (!sections || sections.length === 0) return
+
let prevBBox = null
- let currentSectionId = activeSection
+ let currentSectionId = null
+
+ // 先检查当前视口中的所有标题
for (let i = 0; i < sections.length; ++i) {
const section = sections[i]
if (!section || !(section instanceof Element)) continue
- if (!currentSectionId) {
- currentSectionId = section.getAttribute('data-id')
- }
+
const bbox = section.getBoundingClientRect()
- const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
- const offset = Math.max(150, prevHeight / 4)
+ const offset = 100 // 固定偏移量,避免计算不稳定
+
+ // 如果标题在视口上方或接近顶部,认为是当前标题
if (bbox.top - offset < 0) {
currentSectionId = section.getAttribute('data-id')
prevBBox = bbox
- continue
+ } else {
+ // 找到第一个在视口下方的标题就停止
+ break
+ }
+ }
+
+ // 如果没找到任何标题在视口上方,使用第一个标题
+ if (!currentSectionId && sections.length > 0) {
+ currentSectionId = sections[0].getAttribute('data-id')
+ }
+
+ // 只有当 ID 变化时才更新状态,减少不必要的渲染
+ if (currentSectionId !== activeSection) {
+ setActiveSection(currentSectionId)
+
+ // 查找目录中对应的索引并滚动
+ const index = post?.toc?.findIndex(
+ obj => uuidToId(obj.id) === currentSectionId
+ )
+
+ if (index !== -1 && tRef?.current) {
+ tRef.current.scrollTo({ top: 28 * index, behavior: 'smooth' })
}
- break
}
- setActiveSection(currentSectionId)
- const index = post?.toc?.findIndex(
- obj => uuidToId(obj.id) === currentSectionId
- )
- tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
}, throttleMs)
-
- window.addEventListener('scroll', actionSectionScrollSpy)
- actionSectionScrollSpy()
+
+ const content = document.querySelector('#container-inner')
+ if (!content) return // 防止 content 不存在
+
+ // 添加滚动和内容变化的监听
+ content.addEventListener('scroll', actionSectionScrollSpy)
+
+ // 初始执行一次
+ setTimeout(() => {
+ actionSectionScrollSpy()
+ }, 300) // 延迟执行确保 DOM 已完全加载
+
return () => {
- window.removeEventListener('scroll', actionSectionScrollSpy)
+ content?.removeEventListener('scroll', actionSectionScrollSpy)
}
}, [post])
@@ -68,21 +101,27 @@ const Catalog = ({ post }) => {
-