Skip to content

Commit 8a8668d

Browse files
authored
Merge pull request tangly1024#2410 from tangly1024/fix/toc-of-password-post
关于文章加锁和目录问题
2 parents 741528e + 3aa1e6f commit 8a8668d

File tree

3 files changed

+96
-70
lines changed

3 files changed

+96
-70
lines changed

pages/[prefix]/index.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { useEffect, useState } from 'react'
1818
*/
1919
const Slug = props => {
2020
const { post } = props
21+
const router = useRouter()
2122

2223
// 文章锁🔐
2324
const [lock, setLock] = useState(post?.password && post?.password !== '')
@@ -27,9 +28,14 @@ const Slug = props => {
2728
* @param {*} result
2829
*/
2930
const validPassword = passInput => {
30-
const encrypt = md5(post.slug + passInput)
31-
if (passInput && encrypt === post.password) {
31+
if (!post) {
32+
return false
33+
}
34+
const encrypt = md5(post?.slug + passInput)
35+
if (passInput && encrypt === post?.password) {
3236
setLock(false)
37+
// 输入密码存入localStorage,下次自动提交
38+
localStorage.setItem('password_' + router.asPath, passInput)
3339
return true
3440
}
3541
return false
@@ -49,8 +55,28 @@ const Slug = props => {
4955
post.toc = getPageTableOfContents(post, post.blockMap)
5056
}
5157
}
58+
59+
// 从localStorage中读取上次记录 自动提交密码
60+
const passInput = localStorage.getItem('password_' + router.asPath)
61+
if (passInput) {
62+
validPassword(passInput)
63+
}
5264
}, [post])
5365

66+
// 文章加载
67+
useEffect(() => {
68+
if (lock) {
69+
return
70+
}
71+
// 文章解锁后生成目录与内容
72+
if (post?.blockMap?.block) {
73+
post.content = Object.keys(post.blockMap.block).filter(
74+
key => post.blockMap.block[key]?.value?.parent_id === post.id
75+
)
76+
post.toc = getPageTableOfContents(post, post.blockMap)
77+
}
78+
}, [post, lock])
79+
5480
props = { ...props, lock, setLock, validPassword }
5581
// 根据页面路径加载不同Layout文件
5682
const Layout = getLayoutByTheme({

themes/gitbook/components/ArticleLock.js

-12
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,19 @@ export const ArticleLock = props => {
2020
*/
2121
const submitPassword = () => {
2222
const p = document.getElementById('password')
23-
2423
// 验证失败提示
2524
if (!validPassword(p?.value)) {
2625
const tips = document.getElementById('tips')
2726
if (tips) {
2827
tips.innerHTML = ''
2928
tips.innerHTML = `<div class='text-red-500 animate__shakeX animate__animated'>${locale.COMMON.PASSWORD_ERROR}</div>`
3029
}
31-
} else {
32-
// 输入密码存入localStorage,下次自动提交
33-
localStorage.setItem('password_' + router.asPath, p?.value)
3430
}
3531
}
3632

3733
useEffect(() => {
3834
// 选中密码输入框并将其聚焦
3935
passwordInputRef.current.focus()
40-
41-
// 从localStorage中读取上次记录 自动提交密码
42-
const p = localStorage.getItem('password_' + router.asPath)
43-
console.log('pp', p, document.getElementById('password'))
44-
if (p) {
45-
document.getElementById('password').value = p
46-
submitPassword()
47-
}
4836
}, [router])
4937

5038
return (

themes/gitbook/components/Catalog.js

+68-56
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { useCallback, useEffect, useState } from 'react'
1+
import { isBrowser } from '@/lib/utils'
22
import throttle from 'lodash.throttle'
33
import { uuidToId } from 'notion-utils'
4-
import { isBrowser } from '@/lib/utils'
4+
import { useCallback, useEffect, useState } from 'react'
55

66
/**
77
* 目录导航组件
@@ -24,66 +24,78 @@ const Catalog = ({ post }) => {
2424
}, [post])
2525

2626
const throttleMs = 200
27-
const actionSectionScrollSpy = useCallback(throttle(() => {
28-
const sections = document.getElementsByClassName('notion-h')
29-
let prevBBox = null
30-
let currentSectionId = null
31-
for (let i = 0; i < sections.length; ++i) {
32-
const section = sections[i]
33-
if (!section || !(section instanceof Element)) continue
34-
if (!currentSectionId) {
35-
currentSectionId = section.getAttribute('data-id')
27+
const actionSectionScrollSpy = useCallback(
28+
throttle(() => {
29+
const sections = document.getElementsByClassName('notion-h')
30+
let prevBBox = null
31+
let currentSectionId = null
32+
for (let i = 0; i < sections.length; ++i) {
33+
const section = sections[i]
34+
if (!section || !(section instanceof Element)) continue
35+
if (!currentSectionId) {
36+
currentSectionId = section.getAttribute('data-id')
37+
}
38+
const bbox = section.getBoundingClientRect()
39+
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
40+
const offset = Math.max(150, prevHeight / 4)
41+
// GetBoundingClientRect returns values relative to viewport
42+
if (bbox.top - offset < 0) {
43+
currentSectionId = section.getAttribute('data-id')
44+
prevBBox = bbox
45+
continue
46+
}
47+
// No need to continue loop, if last element has been detected
48+
break
3649
}
37-
const bbox = section.getBoundingClientRect()
38-
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
39-
const offset = Math.max(150, prevHeight / 4)
40-
// GetBoundingClientRect returns values relative to viewport
41-
if (bbox.top - offset < 0) {
42-
currentSectionId = section.getAttribute('data-id')
43-
prevBBox = bbox
44-
continue
50+
setActiveSection(currentSectionId)
51+
const tocIds = post?.toc?.map(t => uuidToId(t.id)) || []
52+
const index = tocIds.indexOf(currentSectionId) || 0
53+
if (isBrowser && tocIds?.length > 0) {
54+
for (const tocWrapper of document?.getElementsByClassName(
55+
'toc-wrapper'
56+
)) {
57+
tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' })
58+
}
4559
}
46-
// No need to continue loop, if last element has been detected
47-
break
48-
}
49-
setActiveSection(currentSectionId)
50-
const tocIds = post?.toc?.map((t) => uuidToId(t.id)) || []
51-
const index = tocIds.indexOf(currentSectionId) || 0
52-
if (isBrowser && tocIds?.length > 0) {
53-
for (const tocWrapper of document?.getElementsByClassName('toc-wrapper')) {
54-
tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' })
55-
}
56-
}
57-
}, throttleMs))
60+
}, throttleMs)
61+
)
5862

5963
// 无目录就直接返回空
60-
if (!toc || toc.length < 1) {
61-
return null
64+
if (!toc || toc?.length < 1) {
65+
return <></>
6266
}
6367

64-
return <>
65-
<div id='toc-wrapper' className='toc-wrapper overflow-y-auto my-2 max-h-80 overscroll-none scroll-hidden'>
66-
<nav className='h-full text-black'>
67-
{toc.map((tocItem) => {
68-
const id = uuidToId(tocItem.id)
69-
return (
70-
<a
71-
key={id}
72-
href={`#${id}`}
73-
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
74-
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
75-
>
76-
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
77-
className={`truncate ${activeSection === id ? 'font-bold text-gray-500 underline' : ''}`}
78-
>
79-
{tocItem.text}
80-
</span>
81-
</a>
82-
)
83-
})}
84-
</nav>
85-
</div>
86-
</>
68+
console.log('渲染toc', toc)
69+
70+
return (
71+
<>
72+
<div
73+
id='toc-wrapper'
74+
className='toc-wrapper overflow-y-auto my-2 max-h-80 overscroll-none scroll-hidden'>
75+
<nav className='h-full text-black'>
76+
{toc?.map(tocItem => {
77+
const id = uuidToId(tocItem.id)
78+
return (
79+
<a
80+
key={id}
81+
href={`#${id}`}
82+
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
83+
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}>
84+
<span
85+
style={{
86+
display: 'inline-block',
87+
marginLeft: tocItem.indentLevel * 16
88+
}}
89+
className={`truncate ${activeSection === id ? 'font-bold text-gray-500 underline' : ''}`}>
90+
{tocItem.text}
91+
</span>
92+
</a>
93+
)
94+
})}
95+
</nav>
96+
</div>
97+
</>
98+
)
8799
}
88100

89101
export default Catalog

0 commit comments

Comments
 (0)