目录组件百分比进度
This commit is contained in:
tangly1024
2021-12-22 16:22:17 +08:00
parent 0ef9da886f
commit 565b3ac194
9 changed files with 33 additions and 23 deletions

View File

@@ -165,10 +165,13 @@ export default function ArticleDetail ({ post, blockMap, recommendPosts, prev, n
{/* 悬浮目录按钮 */} {/* 悬浮目录按钮 */}
<div className="block lg:hidden"> <div className="block lg:hidden">
<TocDrawerButton onClick={() => { drawerRight.current.handleSwitchVisible() }} /> <TocDrawerButton onClick={() => { drawerRight.current.handleSwitchVisible() }} />
<TocDrawer post={post} cRef={drawerRight} /> <TocDrawer post={post} cRef={drawerRight} targetRef={targetRef} />
</div> </div>
<Progress targetRef={targetRef} /> {/* 移动端顶部进度条 */}
{/* <div className='fixed left-0 top-0 w-full z-40 block md:hidden'>
<Progress targetRef={targetRef} />
</div> */}
</>) </>)
} }

View File

@@ -12,7 +12,7 @@ import smoothscroll from 'smoothscroll-polyfill'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const JumpToBottomButton = ({ targetRef, showPercent = true }) => { const JumpToBottomButton = ({ targetRef, showPercent = false }) => {
const { locale } = useGlobal() const { locale } = useGlobal()
const [show, switchShow] = useState(false) const [show, switchShow] = useState(false)
const [percent, changePercent] = useState(0) const [percent, changePercent] = useState(0)

View File

@@ -12,7 +12,7 @@ import smoothscroll from 'smoothscroll-polyfill'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const JumpToTopButton = ({ targetRef, showPercent = true }) => { const JumpToTopButton = ({ targetRef, showPercent = false }) => {
const { locale } = useGlobal() const { locale } = useGlobal()
const [show, switchShow] = useState(false) const [show, switchShow] = useState(false)
const [percent, changePercent] = useState(0) const [percent, changePercent] = useState(0)
@@ -39,7 +39,7 @@ const JumpToTopButton = ({ targetRef, showPercent = true }) => {
return (<div id='jump-to-top' className='right-3 fixed flex bottom-48 duration-500 z-20'> return (<div id='jump-to-top' className='right-3 fixed flex bottom-48 duration-500 z-20'>
<div onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} <div onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
className={(show ? '' : 'hidden') + ' animate__fadeInRight animate__animated animate__faster shadow-card rounded-xl glassmorphism py-1 cursor-pointer '}> className={(show ? '' : 'hidden') + ' animate__fadeInRight animate__animated animate__faster shadow-card rounded-xl glassmorphism py-3 cursor-pointer '}>
<div className='text-center'> <div className='text-center'>
<div className='w-10 dark:text-gray-200 transform hover:scale-150 duration-200 text-xs' title={locale.POST.TOP} > <div className='w-10 dark:text-gray-200 transform hover:scale-150 duration-200 text-xs' title={locale.POST.TOP} >
<FontAwesomeIcon icon={faArrowUp} /> <FontAwesomeIcon icon={faArrowUp} />

View File

@@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react'
const Progress = ({ targetRef }) => { const Progress = ({ targetRef }) => {
const [percent, changePercent] = useState(0) const [percent, changePercent] = useState(0)
const scrollListener = () => { const scrollListener = () => {
if (targetRef.current) { if (targetRef?.current) {
const clientHeight = targetRef ? (targetRef.current.clientHeight) : 0 const clientHeight = targetRef ? (targetRef.current.clientHeight) : 0
const scrollY = window.pageYOffset const scrollY = window.pageYOffset
const fullHeight = clientHeight - window.outerHeight const fullHeight = clientHeight - window.outerHeight
@@ -23,8 +23,9 @@ const Progress = ({ targetRef }) => {
return () => document.removeEventListener('scroll', scrollListener) return () => document.removeEventListener('scroll', scrollListener)
}, [percent]) }, [percent])
return (<div className='h-1 fixed left-0 top-0 w-full shadow-2xl z-40 bg-blue-200'> return (<div className='h-4 w-full shadow-2xl bg-purple-400'>
<div className='h-1 bg-blue-600 fixed left-0 top-0 duration-200 rounded' style={{ width: `${percent}%` }}/> <div className='text-center w-full absolute text-white text-xs'>{percent}%</div>
<div className='h-4 bg-purple-700 duration-200 rounded-r' style={{ width: `${percent}%` }}/>
</div>) </div>)
} }

View File

@@ -8,6 +8,7 @@ import { faAngleDoubleRight, faChartBar, faThList } from '@fortawesome/free-soli
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link' import Link from 'next/link'
import React from 'react' import React from 'react'
import Progress from './Progress'
/** /**
* 侧边平铺 * 侧边平铺
@@ -21,7 +22,7 @@ import React from 'react'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const SideAreaLeft = ({ title, tags, currentTag, post, posts, categories, currentCategory, currentSearch }) => { const SideAreaLeft = ({ title, tags, currentTag, post, posts, categories, currentCategory, currentSearch, targetRef }) => {
const { locale } = useGlobal() const { locale } = useGlobal()
const showToc = post && post.toc && post.toc.length > 1 const showToc = post && post.toc && post.toc.length > 1
const postCount = posts?.length || 0 const postCount = posts?.length || 0
@@ -71,10 +72,10 @@ const SideAreaLeft = ({ title, tags, currentTag, post, posts, categories, curren
{showToc && ( {showToc && (
<section className='sticky top-8 pb-20 rounded-xl shadow-md bg-white dark:bg-gray-800 hover:shadow-2xl duration-200'> <section className='sticky top-8 pb-20 rounded-xl shadow-md bg-white dark:bg-gray-800 hover:shadow-2xl duration-200'>
<div className='border-b text-2xl bg-white text-black rounded-t-xl dark:border-gray-700 dark:bg-gray-700 dark:text-white py-6 px-6'> <div className='border-b text-center text-2xl bg-white text-black rounded-t-xl dark:border-gray-700 dark:bg-gray-700 dark:text-white py-6 px-6'>
{locale.COMMON.TABLE_OF_CONTENTS} {locale.COMMON.TABLE_OF_CONTENTS}
</div> </div>
<Toc toc={post.toc} /> <Toc toc={post.toc} targetRef={targetRef} />
</section> </section>
)} )}
</> </>

View File

@@ -1,6 +1,7 @@
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import throttle from 'lodash.throttle' import throttle from 'lodash.throttle'
import { uuidToId } from 'notion-utils' import { uuidToId } from 'notion-utils'
import Progress from './Progress'
// import { cs } from 'react-notion-x' // import { cs } from 'react-notion-x'
/** /**
@@ -9,7 +10,7 @@ import { uuidToId } from 'notion-utils'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const Toc = ({ toc }) => { const Toc = ({ toc, targetRef }) => {
// 无目录就直接返回空 // 无目录就直接返回空
if (!toc || toc.length < 1) return <></> if (!toc || toc.length < 1) return <></>
@@ -51,6 +52,9 @@ const Toc = ({ toc }) => {
}, throttleMs)) }, throttleMs))
return <> return <>
<div className='w-full'>
<Progress targetRef={targetRef}/>
</div>
<nav className=' dark:text-gray-100 bg-white dark:bg-gray-800 overflow-y-auto scroll-hidden p-6'> <nav className=' dark:text-gray-100 bg-white dark:bg-gray-800 overflow-y-auto scroll-hidden p-6'>
{toc.map((tocItem) => { {toc.map((tocItem) => {
const id = uuidToId(tocItem.id) const id = uuidToId(tocItem.id)
@@ -58,9 +62,9 @@ const Toc = ({ toc }) => {
<a <a
key={id} key={id}
href={`#${id}`} href={`#${id}`}
className={`notion-table-of-contents-item duration-300 transform font-light className={`notion-table-of-contents-item duration-300 transform font-mono
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} notion-table-of-contents-item-indent-level-${tocItem.indentLevel}
${activeSection === id && ' font-bold text-blue-400 dark:text-white'}`} ${activeSection === id && ' font-bold text-purple-500 dark:text-purple-400'}`}
> >
<span <span
style={{ style={{

View File

@@ -9,7 +9,7 @@ import { useGlobal } from '@/lib/global'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const TocDrawer = ({ post, cRef }) => { const TocDrawer = ({ post, cRef, targetRef }) => {
// 暴露给父组件 通过cRef.current.handleMenuClick 调用 // 暴露给父组件 通过cRef.current.handleMenuClick 调用
useImperativeHandle(cRef, () => { useImperativeHandle(cRef, () => {
return { return {
@@ -26,13 +26,13 @@ const TocDrawer = ({ post, cRef }) => {
{/* 侧边菜单 */} {/* 侧边菜单 */}
<div <div
className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') + className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') +
' shadow-xl animate__animated animate__faster max-h-96 ' + ' shadow-card animate__animated animate__faster max-h-96 ' +
' w-60 duration-200 fixed right-4 top-16 rounded overflow-y-auto'}> ' w-60 duration-200 fixed right-4 top-16 rounded overflow-y-auto'}>
{post && <> {post && <>
<div className='text-xl font-bold text-black dark:text-white bg-gray-200 dark:bg-gray-600 py-2 px-6'> <div className='text-xl font-bold text-center text-black dark:text-white bg-white dark:bg-gray-600 py-2 px-6'>
{locale.COMMON.TABLE_OF_CONTENTS} {locale.COMMON.TABLE_OF_CONTENTS}
</div> </div>
<Toc toc={post.toc}/> <Toc toc={post.toc} targetRef={targetRef}/>
</> </>
} }
</div> </div>

View File

@@ -75,7 +75,7 @@ const BaseLayout = ({
<div className='flex justify-center flex-1 mx-auto md:pt-8 pb-12'> <div className='flex justify-center flex-1 mx-auto md:pt-8 pb-12'>
<div id='left' className='hidden lg:block flex-col w-72'> <div id='left' className='hidden lg:block flex-col w-72'>
<SideAreaLeft title={meta.title} post={post} posts={totalPosts} tags={tags} currentSearch={currentSearch} currentTag={currentTag} categories={categories} currentCategory={currentCategory} /> <SideAreaLeft targetRef={targetRef} title={meta.title} post={post} posts={totalPosts} tags={tags} currentSearch={currentSearch} currentTag={currentTag} categories={categories} currentCategory={currentCategory} />
</div> </div>
<div id='center' className='flex-grow max-w-4xl min-h-screen md:mx-10' ref={targetRef}> <div id='center' className='flex-grow max-w-4xl min-h-screen md:mx-10' ref={targetRef}>
@@ -94,7 +94,7 @@ const BaseLayout = ({
</div> </div>
<Footer title={meta.title}/> <Footer title={meta.title}/>
<JumpToTopButton targetRef={targetRef} showPercent={true} /> <JumpToTopButton targetRef={targetRef} showPercent={false} />
<JumpToBottomButton targetRef={targetRef} showPercent={false}/> <JumpToBottomButton targetRef={targetRef} showPercent={false}/>
<FloatDarkModeButton/> <FloatDarkModeButton/>
</div> </div>

View File

@@ -1,4 +1,5 @@
import { getCacheFromMemory, setCacheToMemory } from '@/lib/cache/memory_cache' // import { getCacheFromMemory, setCacheToMemory } from '@/lib/cache/memory_cache'
import { getCacheFromFile, setCacheToFile } from './local_file_cache'
const enableCache = true // 生产环境禁用 const enableCache = true // 生产环境禁用
/** /**
@@ -10,7 +11,7 @@ export async function getDataFromCache (key) {
if (!enableCache) { if (!enableCache) {
return null return null
} }
const dataFromCache = await getCacheFromMemory(key) const dataFromCache = await getCacheFromFile(key)
if (JSON.stringify(dataFromCache) === '[]') { if (JSON.stringify(dataFromCache) === '[]') {
return null return null
} }
@@ -21,5 +22,5 @@ export async function setDataToCache (key, data) {
if (!enableCache || !data) { if (!enableCache || !data) {
return return
} }
await setCacheToMemory(key, data) await setCacheToFile(key, data)
} }