封装Layout组件

This commit is contained in:
tangly1024
2021-10-18 12:31:53 +08:00
parent e023aa98e6
commit 710762281c
14 changed files with 246 additions and 353 deletions

View File

@@ -73,6 +73,7 @@
## 页面样式主题
- 仿照 [fukasawa](https://andersnoren.se/themes/fukasawa)
- 仿照 [youtube](https://youtube.com)
## License

View File

@@ -14,7 +14,7 @@ import BlogPostListEmpty from '@/components/BlogPostListEmpty'
* @returns {JSX.Element}
* @constructor
*/
const BlogPostListScrollPagination = ({ posts = [], tags, targetRef }) => {
const BlogPostListScroll = ({ posts = [], tags }) => {
let filteredBlogPosts = posts
// 处理查询过滤 支持标签、关键词过滤
@@ -61,10 +61,12 @@ const BlogPostListScrollPagination = ({ posts = [], tags, targetRef }) => {
}
})
const targetRef = useRef(null)
if (!postsToShow || postsToShow.length === 0) {
return <BlogPostListEmpty />
} else {
return <div id='post-list-wrapper' className='pt-16 md:pt-28 px-2 md:px-20'>
return <div id='post-list-wrapper' className='pt-16 md:pt-28 px-2 md:px-20' ref={targetRef}>
<div>
{/* 文章列表 */}
<div className='grid 2xl:grid-cols-4 xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-3'>
@@ -100,4 +102,4 @@ const getPostByPage = function (page, totalPosts, postsPerPage) {
postsPerPage * page
)
}
export default BlogPostListScrollPagination
export default BlogPostListScroll

View File

@@ -26,11 +26,11 @@ const DrawerRight = ({ post, cRef }) => {
className={(showDrawer ? 'shadow-2xl' : '-mr-72') + ' overflow-y-auto duration-200 w-72 h-full bg-white dark:bg-gray-700 border-r dark:border-gray-600'}>
{/* LOGO */}
<div className='sticky top-0 z-20 bg-white w-72 flex space-x-4 px-5 py-3.5 dark:border-gray-500 border-b dark:bg-gray-900 '>
<div className='flex text-lg justify-center font-bold font-semibold px-2 py-1 duration-200 dark:text-gray-300'>文章目录
<div className='text-lg font-bold font-semibold px-2 py-1 duration-200 dark:text-gray-300'>文章目录
</div>
<div
className='z-10 p-1 duration-200 mr-2 absolute right-6 text-gray-600 text-xl cursor-pointer dark:text-gray-300'>
<i className='fa hover:scale-125 transform duration-200 fa-bookmark-o ' onClick={handleMenuClick} />
<i className='fa hover:scale-125 transform duration-200 fa-bookmark ' onClick={handleMenuClick} />
</div>
</div>
</div>

View File

@@ -4,11 +4,11 @@ import InfoCard from '@/components/InfoCard'
import TagList from '@/components/TagList'
const SideBar = ({ tags, currentTag, post }) => {
return <aside className='z-10 dark:border-gray-500 border-gray-200 bg-white hidden md:block'>
return <aside className='z-10 dark:border-gray-500 border-gray-200 bg-white hidden lg:block'>
<div
className='dark:bg-gray-800 border-r dark:border-gray-700 h-full scroll-hidden left-0 duration-500 ease-in-out min-h-screen'>
<div id='sidebar' className='hidden md:block sticky top-20 duration-500'>
<div className={post ? 'block' : 'hidden xl:block'}>
<div >
<InfoCard />
<hr className='dark:border-gray-700' />
<MenuButtonGroup allowCollapse={true} />

View File

@@ -41,9 +41,11 @@ const TopNav = ({ tags, currentTag, post }) => {
{/* 右侧功能 */}
<div className='flex flex-nowrap space-x-1'>
<DarkModeButton />
{post && <div className='block xl:hidden z-10 p-1 duration-200 mr-2 h-12 text-xl cursor-pointer dark:text-gray-300 '>
<i className='fa p-2.5 hover:scale-125 transform duration-200 fa-bookmark' onClick={() => { drawerRight.current.handleMenuClick() }}/>
</div>}
{post && (
<div className='block xl:hidden z-10 p-1 duration-200 mr-2 h-12 text-xl cursor-pointer dark:text-gray-300 '>
<i className='fa p-2.5 hover:scale-125 transform duration-200 fa-bookmark-o' onClick={() => { drawerRight.current.handleMenuClick() }}/>
</div>
)}
</div>
</div>
</div>

View File

@@ -1,194 +0,0 @@
import TagItem from '@/components/TagItem'
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
import BLOG from '@/blog.config'
import formatDate from '@/lib/formatDate'
import 'gitalk/dist/gitalk.css'
import Comment from '@/components/Comment'
import Progress from '@/components/Progress'
import React, { useRef } from 'react'
import Image from 'next/image'
import RewardButton from '@/components/RewardButton'
import BlogPostMini from '@/components/BlogPostMini'
import { useRouter } from 'next/router'
import JumpToTop from '@/components/JumpToTop'
import SideBar from '@/components/SideBar'
import Footer from '@/components/Footer'
import Container from '@/components/Container'
import TocBar from '@/components/TocBar'
import TopNav from '@/components/TopNav'
import ShareBar from '@/components/ShareBar'
const mapPageUrl = id => {
return 'https://www.notion.so/' + id.replace(/-/g, '')
}
const ArticleLayout = ({
children,
blockMap,
post,
emailHash,
fullWidth = true,
tags,
prev,
next
}) => {
const meta = {
title: post.title,
description: post.summary,
type: 'article'
}
const targetRef = useRef(null)
const url = BLOG.link + useRouter().asPath
return (
<Container meta={meta} tags={tags}>
{/* live2d 看板娘 */}
{/* <script async src='https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/autoload.js' /> */}
<Progress targetRef={targetRef} />
<TopNav tags={tags} post={post} />
{/* Wrapper */}
<div className='flex justify-between bg-gray-100'>
<SideBar tags={tags} post={post} />
{/* 主体区块 */}
<main className='bg-gray-100 w-full dark:bg-gray-800' ref={targetRef}>
{/* 中央区域 wrapper */}
<header
className='hover:scale-105 hover:shadow-2xl duration-200 transform mx-auto max-w-5xl mt-16 lg:mt-20 md:flex-shrink-0 animate__fadeIn animate__animated'>
{/* 封面图 */}
{post.page_cover && post.page_cover.length > 1 && (
<img className='bg-center object-cover w-full' style={{ maxHeight: '40rem' }}
src={post.page_cover} alt={post.title} />
)}
</header>
<article
className='overflow-x-auto md:px-10 px-5 py-10 max-w-5xl mx-auto bg-white dark:border-gray-700 dark:bg-gray-700'>
{/* 文章标题 */}
<h1 className='font-bold text-4xl text-black my-5 dark:text-white animate__animated animate__fadeIn'>
{post.title}
</h1>
{/* 文章信息 */}
<div className='justify-between flex flex-wrap bg-gray-50 p-2 dark:bg-gray-700 dark:text-white'>
<div className='flex-nowrap flex'>
{post.slug !== 'about' && (<>
<a
className='hidden md:block duration-200 px-1' href='/article/about'
>
<Image alt={BLOG.author} width={33} height={33} src='/avatar.svg'
className='rounded-full cursor-pointer transform hover:scale-125 duration-200' />
</a>
</>)}
{post.tags && (
<div className='flex flex-nowrap leading-8 p-1'>
{post.tags.map(tag => (
<TagItem key={tag} tag={tag} />
))}
</div>
)}
{post.type[0] !== 'Page' && (
<div className='flex items-start text-gray-500 dark:text-gray-400 leading-10'>
{formatDate(
post?.date?.start_date || post.createdTime,
BLOG.lang
)}
</div>
)}
</div>
{/* 不蒜子 */}
<div id='busuanzi_container_page_pv' className='hidden'>
<a href='https://analytics.google.com/analytics/web/#/p273013569/reports/reportinghub'
className='fa fa-eye text-gray-500 text-sm leading-none py-1 px-2'>
&nbsp;<span id='busuanzi_value_page_pv' className='leading-6'></span>
</a>
</div>
</div>
{/* Notion文章主体 */}
{blockMap && (
<NotionRenderer recordMap={blockMap} mapPageUrl={mapPageUrl}
components={{
equation: Equation,
code: Code,
collectionRow: CollectionRow,
collection: Collection
}}
/>
)}
<div className='flex justify-center pt-5'>
<RewardButton />
</div>
<p className='flex justify-center py-5 dark:text-gray-200'>
- 💖 😚 💖 -
</p>
{/* 版权声明 */}
<section
className='overflow-auto dark:bg-gray-700 dark:text-gray-300 bg-gray-100 p-5 leading-8 border-l-4 border-red-500'>
<ul>
<li><strong>本文作者</strong>{BLOG.author}</li>
<li><strong>本文链接</strong> <a href={url}>{url}</a> {post.title}</li>
<li><strong>版权声明</strong> BY-NC-SA </li>
</ul>
</section>
<section className='flex'>
<div className='text-gray-800 my-5 dark:text-gray-300 font-bold my-5 mr-2'>分享本文&nbsp;</div>
<ShareBar post={post} />
</section>
<div className='text-gray-800 my-5 dark:text-gray-300'>
<div className='mt-4 font-bold'>继续阅读</div>
<div className='flex flex-wrap lg:flex-nowrap lg:space-x-10 justify-between py-2'>
<BlogPostMini post={prev} />
<BlogPostMini post={next} />
</div>
</div>
{/* 评论互动 */}
<Comment frontMatter={post} />
</article>
</main>
{/* 右侧目录 */}
<aside className='dark:bg-gray-800 bg-white'>
<section className='h-full xl:static xl:block hidden top-0 right-0 fixed h-full w-52 dark:bg-gray-800 duration-500'>
<div id='right-toc' className='sticky top-16 duration-500'>
<div
className='border-t dark:border-gray-600 border-b text-2xl bg-white font-bold text-black dark:bg-gray-900 dark:text-white py-6 px-6'>
文章目录
</div>
<TocBar toc={post.toc} />
</div>
</section>
</aside>
{/* 下方菜单组 */}
<div
className='right-0 space-x-2 fixed flex bottom-24 px-5 py-1 duration-500'>
<div className='flex-wrap'>
{/* 分享按钮 */}
{/* <ShareButton post={post} /> */}
{/* 跳回顶部 */}
<JumpToTop targetRef={targetRef} />
</div>
</div>
</div>
<Footer />
</Container>
)
}
export default ArticleLayout

View File

@@ -1,11 +1,15 @@
import PropTypes from 'prop-types'
import React, { useCallback, useEffect } from 'react'
import React, { useCallback, useEffect, useRef } from 'react'
import CommonHead from '@/components/CommonHead'
import throttle from 'lodash.throttle'
import BLOG from '@/blog.config'
import { useTheme } from '@/lib/theme'
import TopNav from '@/components/TopNav'
import Footer from '@/components/Footer'
import SideBar from '@/components/SideBar'
import JumpToTop from '@/components/JumpToTop'
const Container = ({ children, layout, fullWidth, tags, meta, ...customMeta }) => {
const BaseLayout = ({ children, layout, fullWidth, tags, meta, post, ...customMeta }) => {
let windowTop = 0
const scrollTrigger = useCallback(throttle(() => {
const scrollS = window.scrollY
@@ -36,16 +40,30 @@ const Container = ({ children, layout, fullWidth, tags, meta, ...customMeta }) =
}
})
const { theme } = useTheme()
const targetRef = useRef(null)
return (
<div className={[BLOG.font, theme].join(' ')}>
<div id='wrapper' className={[BLOG.font, theme].join(' ')}>
<CommonHead meta={meta} />
{children}
<TopNav tags={tags} post={post} />
{/* Middle Wrapper */}
<main className='flex bg-gray-100'>
<SideBar tags={tags} post={post} />
<div className='flex flex-grow' ref={targetRef} >
{children}
</div>
<JumpToTop targetRef={targetRef} showPercent={false} />
</main>
<Footer />
</div>
)
}
Container.propTypes = {
BaseLayout.propTypes = {
children: PropTypes.node
}
export default Container
export default BaseLayout

View File

@@ -1,38 +0,0 @@
import PropTypes from 'prop-types'
import BLOG from '@/blog.config'
import TagsBar from '@/components/TagsBar'
import Footer from '@/components/Footer'
import React, { useRef } from 'react'
import Container from '@/components/Container'
import JumpToTop from '@/components/JumpToTop'
import SideBar from '@/components/SideBar'
import TopNav from '@/components/TopNav'
import BlogPostListScrollPagination from '@/components/BlogPostListScrollPagination'
const IndexLayout = ({ tags, posts, page, currentTag, meta, ...customMeta }) => {
const targetRef = useRef(null)
return (
<Container id='wrapper' meta={meta} tags={tags}>
<TopNav tags={tags} />
{/* middle */}
<div ref={targetRef} className={`${BLOG.font} flex justify-between bg-gray-100 dark:bg-black min-h-screen`}>
<SideBar />
<main className='flex-grow'>
<TagsBar tags={tags} currentTag={currentTag} />
<BlogPostListScrollPagination posts={posts} tags={tags} targetRef={targetRef} />
<JumpToTop targetRef={targetRef} showPercent={false} />
</main>
</div>
<Footer />
</Container>
)
}
IndexLayout.propTypes = {
posts: PropTypes.array.isRequired,
tags: PropTypes.object.isRequired,
currentTag: PropTypes.string
}
export default IndexLayout

View File

@@ -1,39 +0,0 @@
import PropTypes from 'prop-types'
import BLOG from '@/blog.config'
import TagsBar from '@/components/TagsBar'
import Footer from '@/components/Footer'
import React, { useRef } from 'react'
import Container from '@/components/Container'
import JumpToTop from '@/components/JumpToTop'
import SideBar from '@/components/SideBar'
import TopNav from '@/components/TopNav'
import BlogPostList from '@/components/BlogPostList'
const PageLayout = ({ tags, posts, page, currentTag, meta, ...customMeta }) => {
const targetRef = useRef(null)
return (
<Container id='wrapper' meta={meta} tags={tags}>
<TopNav tags={tags} />
{/* middle */}
<div ref={targetRef} className={`${BLOG.font} flex justify-between bg-gray-100 dark:bg-black min-h-screen`}>
<SideBar />
<main className='flex-grow'>
<TagsBar tags={tags} currentTag={currentTag} />
<BlogPostList posts={posts} tags={tags} page={page} />
</main>
<JumpToTop targetRef={targetRef} showPercent={false} />
</div>
<Footer />
</Container>
)
}
PageLayout.propTypes = {
posts: PropTypes.array.isRequired,
tags: PropTypes.object.isRequired,
currentTag: PropTypes.string
}
export default PageLayout

View File

@@ -7,18 +7,11 @@ import { useRouter } from 'next/router'
import { useEffect } from 'react'
export default function Custom404 () {
const route = useRouter()
if (route.asPath.indexOf('/article') < 0 && route.asPath.indexOf('/404') < 0) {
// article 重定向,处理旧文章链接迁移。
const redirectUrl = '/article' + route.asPath
route.push(redirectUrl)
} else {
useEffect(() => {
setTimeout(() => {
window.location.href = '/'
}, 3000)
})
}
useEffect(() => {
setTimeout(() => {
window.location.href = '/'
}, 3000)
})
return <div
className='text-black bg-white h-screen text-center justify-center content-center items-center flex flex-col'>

View File

@@ -1,24 +1,173 @@
import ArticleLayout from '@/layouts/ArticleLayout'
import { getAllPosts, getAllTags, getPostBlocks } from '@/lib/notion'
import BLOG from '@/blog.config'
import { createHash } from 'crypto'
import { getPageTableOfContents } from 'notion-utils'
import Custom404 from '@/pages/404'
import { useRouter } from 'next/router'
import Progress from '@/components/Progress'
import Image from 'next/image'
import TagItem from '@/components/TagItem'
import formatDate from '@/lib/formatDate'
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
import RewardButton from '@/components/RewardButton'
import ShareBar from '@/components/ShareBar'
import BlogPostMini from '@/components/BlogPostMini'
import Comment from '@/components/Comment'
import TocBar from '@/components/TocBar'
import JumpToTop from '@/components/JumpToTop'
import BaseLayout from '@/layouts/BaseLayout'
import { useRef } from 'react'
const mapPageUrl = id => {
return 'https://www.notion.so/' + id.replace(/-/g, '')
}
const BlogPost = ({ post, blockMap, emailHash, tags, prev, next }) => {
if (!post) {
return <Custom404 />
return <>空白页</>
}
return (
<ArticleLayout
blockMap={blockMap}
post={post}
emailHash={emailHash}
tags={tags}
prev={prev}
next={next}
></ArticleLayout>
)
const meta = {
title: post.title,
description: post.summary,
type: 'article'
}
const targetRef = useRef(null)
const url = BLOG.link + useRouter().asPath
return <BaseLayout meta={meta} tags={tags} post={post}>
{/* 阅读进度条 */}
<Progress targetRef={targetRef} />
{/* 主体区块 */}
<div ref={targetRef} className='flex flex-grow'>
<div id='article-wrapper' className='flex-grow bg-gray-100 dark:bg-gray-800'>
{/* 中央区域 wrapper */}
<header
className='hover:scale-105 hover:shadow-2xl duration-200 transform mx-auto max-w-5xl mt-16 lg:mt-20 md:flex-shrink-0 animate__fadeIn animate__animated'>
{/* 封面图 */}
{post.page_cover && post.page_cover.length > 1 && (
<img className='bg-center object-cover w-full' style={{ maxHeight: '40rem' }}
src={post.page_cover} alt={post.title} />
)}
</header>
<article
className='overflow-x-auto md:px-10 px-5 py-10 max-w-5xl mx-auto bg-white dark:border-gray-700 dark:bg-gray-700'>
{/* 文章标题 */}
<h1 className='font-bold text-4xl text-black my-5 dark:text-white animate__animated animate__fadeIn'>
{post.title}
</h1>
{/* 文章信息 */}
<div className='justify-between flex flex-wrap bg-gray-50 p-2 dark:bg-gray-700 dark:text-white'>
<div className='flex-nowrap flex'>
{post.slug !== 'about' && (<>
<a
className='hidden md:block duration-200 px-1' href='/article/about'
>
<Image alt={BLOG.author} width={33} height={33} src='/avatar.svg'
className='rounded-full cursor-pointer transform hover:scale-125 duration-200' />
</a>
</>)}
{post.tags && (
<div className='flex flex-nowrap leading-8 p-1'>
{post.tags.map(tag => (
<TagItem key={tag} tag={tag} />
))}
</div>
)}
{post.type[0] !== 'Page' && (
<div className='flex items-start text-gray-500 dark:text-gray-400 leading-10'>
{formatDate(
post?.date?.start_date || post.createdTime,
BLOG.lang
)}
</div>
)}
</div>
{/* 不蒜子 */}
<div id='busuanzi_container_page_pv' className='hidden'>
<a href='https://analytics.google.com/analytics/web/#/p273013569/reports/reportinghub'
className='fa fa-eye text-gray-500 text-sm leading-none py-1 px-2'>
&nbsp;<span id='busuanzi_value_page_pv' className='leading-6'></span>
</a>
</div>
</div>
{/* Notion文章主体 */}
{blockMap && (
<NotionRenderer recordMap={blockMap} mapPageUrl={mapPageUrl}
components={{
equation: Equation,
code: Code,
collectionRow: CollectionRow,
collection: Collection
}}
/>
)}
<div className='flex justify-center pt-5'>
<RewardButton />
</div>
<p className='flex justify-center py-5 dark:text-gray-200'>
- 💖 😚 💖 -
</p>
{/* 版权声明 */}
<section
className='overflow-auto dark:bg-gray-700 dark:text-gray-300 bg-gray-100 p-5 leading-8 border-l-4 border-red-500'>
<ul>
<li><strong>本文作者</strong>{BLOG.author}</li>
<li><strong>本文链接</strong> <a href={url}>{url}</a> {post.title}</li>
<li><strong>版权声明</strong> BY-NC-SA </li>
</ul>
</section>
<section className='flex'>
<div className='text-gray-800 my-5 dark:text-gray-300 font-bold my-5 mr-2'>分享本文&nbsp;</div>
<ShareBar post={post} />
</section>
<div className='text-gray-800 my-5 dark:text-gray-300'>
<div className='mt-4 font-bold'>继续阅读</div>
<div className='flex flex-wrap lg:flex-nowrap lg:space-x-10 justify-between py-2'>
<BlogPostMini post={prev} />
<BlogPostMini post={next} />
</div>
</div>
{/* 评论互动 */}
<Comment frontMatter={post} />
</article>
</div>
{/* 右侧目录 */}
<aside className='dark:bg-gray-800 bg-white'>
<section
className='h-full xl:static xl:block hidden top-0 right-0 fixed h-full w-52 dark:bg-gray-800 duration-500'>
<div id='right-toc' className='sticky top-16 duration-500'>
<div
className='border-t dark:border-gray-600 border-b text-2xl bg-white font-bold text-black dark:bg-gray-900 dark:text-white py-6 px-6'>
文章目录
</div>
<TocBar toc={post.toc} />
</div>
</section>
</aside>
{/* 右下角悬浮菜单 */}
<div className='right-0 space-x-2 fixed flex bottom-24 px-5 py-1 duration-500'>
<div className='flex-wrap'>
{/* 分享按钮 */}
{/* <ShareButton post={post} /> */}
{/* 跳回顶部 */}
<JumpToTop targetRef={targetRef} />
</div>
</div>
</div>
</BaseLayout>
}
export async function getStaticPaths () {

View File

@@ -1,6 +1,8 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import IndexLayout from '@/layouts/IndexLayout'
import BLOG from '@/blog.config'
import BaseLayout from '@/layouts/BaseLayout'
import TagsBar from '@/components/TagsBar'
import BlogPostListScroll from '@/components/BlogPostListScroll'
export async function getStaticProps () {
let posts = await getAllPosts()
@@ -15,7 +17,6 @@ export async function getStaticProps () {
}
return {
props: {
page: 1, // current page is 1
posts,
tags,
meta
@@ -24,9 +25,14 @@ export async function getStaticProps () {
}
}
const index = ({ posts, page, tags, meta }) => {
const index = ({ posts, tags, meta }) => {
return (
<IndexLayout tags={tags} posts={posts} page={page} meta={meta} />
<BaseLayout meta={meta} tags={tags}>
<div className='flex-grow'>
<TagsBar tags={tags} />
<BlogPostListScroll posts={posts} tags={tags} />
</div>
</BaseLayout>
)
}

View File

@@ -1,49 +1,36 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import BLOG from '@/blog.config'
import { useRouter } from 'next/router'
import PageLayout from '@/layouts/PageLayout'
import BaseLayout from '@/layouts/BaseLayout'
import TagsBar from '@/components/TagsBar'
import BlogPostList from '@/components/BlogPostList'
const Page = ({ posts, tags, page }) => {
let filteredBlogPosts = posts
if (posts) {
const router = useRouter()
if (router.query && router.query.s) {
filteredBlogPosts = posts.filter(post => {
const tagContent = post.tags ? post.tags.join(' ') : ''
const searchContent = post.title + post.summary + tagContent
return searchContent.toLowerCase().includes(router.query.s.toLowerCase())
})
}
}
const meta = {
title: `${BLOG.title} | 博客列表`,
description: BLOG.description,
type: 'website'
}
return <PageLayout tags={tags} posts={filteredBlogPosts} page={page} meta={meta} />
return <BaseLayout meta={meta} tags={tags}>
<div className='flex-grow'>
<TagsBar tags={tags} />
<BlogPostList posts={posts} tags={tags} page={page} />
</div>
</BaseLayout>
}
export async function getStaticPaths () {
if (BLOG.isProd) {
// 预渲染
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const totalPosts = posts.length
const totalPages = Math.ceil(totalPosts / BLOG.postsPerPage)
return {
// remove first page, we 're not gonna handle that.
paths: Array.from({ length: totalPages - 1 }, (_, i) => ({
params: { page: '' + (i + 2) }
})),
fallback: true
}
} else {
return {
paths: [],
fallback: true
}
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const totalPosts = posts.length
const totalPages = Math.ceil(totalPosts / BLOG.postsPerPage)
return {
// remove first page, we 're not gonna handle that.
paths: Array.from({ length: totalPages - 1 }, (_, i) => ({
params: { page: '' + (i + 2) }
})),
fallback: true
}
}

View File

@@ -1,6 +1,8 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import BLOG from '@/blog.config'
import PageLayout from '@/layouts/PageLayout'
import TagsBar from '@/components/TagsBar'
import BlogPostList from '@/components/BlogPostList'
import BaseLayout from '@/layouts/BaseLayout'
export default function Tag ({ tags, posts, currentTag }) {
const meta = {
@@ -8,7 +10,12 @@ export default function Tag ({ tags, posts, currentTag }) {
description: BLOG.description,
type: 'website'
}
return <PageLayout tags={tags} posts={posts} currentTag={currentTag} meta={meta} />
return <BaseLayout meta={meta} tags={tags} currentTag={currentTag}>
<div className='flex-grow'>
<TagsBar tags={tags} currentTag={currentTag}/>
<BlogPostList posts={posts} tags={tags}/>
</div>
</BaseLayout>
}
export async function getStaticProps ({ params }) {
@@ -33,7 +40,6 @@ export async function getStaticProps ({ params }) {
export async function getStaticPaths () {
if (BLOG.isProd) {
// 预渲染
const tags = await getAllTags()
return {
paths: Object.keys(tags).map(tag => ({ params: { tag } })),