diff --git a/blog.config.js b/blog.config.js index 382fdeb3..926b4f8a 100644 --- a/blog.config.js +++ b/blog.config.js @@ -1,6 +1,6 @@ const BLOG = { - title: '唐里1024', - author: '唐哼哼', + title: '唐力1024', + author: '唐力', email: 'tlyong1992@hotmail.com', link: 'https://tangly1024.com', description: '分享有趣的技术与思考', @@ -13,7 +13,7 @@ const BLOG = { darkBackground: '#111827', // use hex value, don't forget '#' path: '', // leave this empty unless you want to deploy in a folder since: 2020, // if leave this empty, current year will be used. - postsPerPage: 8, // post counts per page + postsPerPage: 6, // post counts per page sortByDate: false, showAbout: true, // WIP showArchive: true, // WIP diff --git a/components/BlogPost.js b/components/BlogPostCard.js similarity index 81% rename from components/BlogPost.js rename to components/BlogPostCard.js index 1e90765b..6f875623 100644 --- a/components/BlogPost.js +++ b/components/BlogPostCard.js @@ -1,8 +1,9 @@ import BLOG from '@/blog.config' import TagItemMini from '@/components/TagItemMini' import Link from 'next/link' +import React from 'react' -const BlogPost = ({ post }) => { +const BlogPostCard = ({ post }) => { return (
{/* 封面图 */} @@ -17,6 +18,9 @@ const BlogPost = ({ post }) => {
{post.title}
+ +
{post.category}
+ {post.tags.map(tag => ())} {post.date.start_date}
@@ -26,4 +30,4 @@ const BlogPost = ({ post }) => { ) } -export default BlogPost +export default BlogPostCard diff --git a/components/BlogPostMini.js b/components/BlogPostCardMini.js similarity index 92% rename from components/BlogPostMini.js rename to components/BlogPostCardMini.js index c71b5e57..bb87d885 100644 --- a/components/BlogPostMini.js +++ b/components/BlogPostCardMini.js @@ -1,7 +1,7 @@ import BLOG from '@/blog.config' import Link from 'next/link' -const BlogPostMini = ({ post }) => { +const BlogPostCardMini = ({ post }) => { return (
@@ -22,4 +22,4 @@ const BlogPostMini = ({ post }) => { ) } -export default BlogPostMini +export default BlogPostCardMini diff --git a/components/BlogPostListPage.js b/components/BlogPostListPage.js index bc706fd9..9903aac9 100644 --- a/components/BlogPostListPage.js +++ b/components/BlogPostListPage.js @@ -1,4 +1,4 @@ -import BlogPost from '@/components/BlogPost' +import BlogPostCard from '@/components/BlogPostCard' import Pagination from '@/components/Pagination' import BLOG from '@/blog.config' @@ -58,7 +58,7 @@ const BlogPostListPage = ({ page = 1, posts = [], tags }) => { {/* 文章列表 */}
{postsToShow.map(post => ( - + ))}
diff --git a/components/BlogPostListScroll.js b/components/BlogPostListScroll.js index fbd76f6b..1b8d396e 100644 --- a/components/BlogPostListScroll.js +++ b/components/BlogPostListScroll.js @@ -1,7 +1,7 @@ -import BlogPost from '@/components/BlogPost' +import BlogPostCard from '@/components/BlogPostCard' import BLOG from '@/blog.config' -import { useCallback, useEffect, useRef, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import throttle from 'lodash.throttle' import BlogPostListEmpty from '@/components/BlogPostListEmpty' @@ -13,7 +13,7 @@ import BlogPostListEmpty from '@/components/BlogPostListEmpty' * @returns {JSX.Element} * @constructor */ -const BlogPostListScroll = ({ posts = [], tags, currentSearch }) => { +const BlogPostListScroll = ({ posts = [], tags, currentSearch, currentCategory, currentTag }) => { const postsPerPage = BLOG.postsPerPage const [page, updatePage] = useState(1) const postsToShow = getPostByPage(page, posts, postsPerPage) @@ -52,10 +52,29 @@ const BlogPostListScroll = ({ posts = [], tags, currentSearch }) => { return } else { return
- {/* 文章列表 */} + + {currentCategory && ( +
+
{currentCategory}
+
+ )} + + {currentSearch && ( +
+
关键字:{currentSearch}
+
+ )} + + {currentTag && ( +
+
# {currentTag}
+
+ )} + + {/* 文章列表 */}
{postsToShow.map(post => ( - + ))}
diff --git a/components/Drawer.js b/components/Drawer.js index 3ac656be..fa809a99 100644 --- a/components/Drawer.js +++ b/components/Drawer.js @@ -20,16 +20,16 @@ const Drawer = ({ post, currentTag, cRef, tags, posts }) => { handleMenuClick: () => handleMenuClick() } }) - const [showDrawer, switchShowDrawer] = useState(false) + const [isHidden, changeHiddenStatus] = useState(true) // 点击按钮更改侧边抽屉状态 const handleMenuClick = () => { - switchShowDrawer(!showDrawer) + changeHiddenStatus(!isHidden) } return <>
{/* LOGO */}
+ className={(isHidden ? '-ml-72' : '') + ' duration-200 w-72 border-r dark:border-gray-600'}>
@@ -41,7 +41,7 @@ const Drawer = ({ post, currentTag, cRef, tags, posts }) => { {/* 侧边菜单 */}
+ className={(isHidden ? '-ml-72' : 'shadow-2xl') + ' overflow-y-scroll h-screen w-72 duration-200 overflow-y-auto'}>
{/* 搜索框 */}
@@ -79,7 +79,7 @@ const Drawer = ({ post, currentTag, cRef, tags, posts }) => {
{/* 背景蒙版 */} -
} diff --git a/components/MenuButtonGroup.js b/components/MenuButtonGroup.js index bd8cbb41..d4b34c5d 100644 --- a/components/MenuButtonGroup.js +++ b/components/MenuButtonGroup.js @@ -24,7 +24,7 @@ const MenuButtonGroup = ({ allowCollapse = false }) => { link => link.show && ( - +
diff --git a/components/PostsCategories.js b/components/PostsCategories.js new file mode 100644 index 00000000..76668adb --- /dev/null +++ b/components/PostsCategories.js @@ -0,0 +1,22 @@ +import Link from 'next/link' +import React from 'react' + +const PostsCategories = ({ currentCategory, categories }) => { + return <> +
+
文章分类
+
+
+
+ {Object.keys(categories).map(category => { + return +
{category} {categories[category]}
+ + })} +
+
+ +} + +export default PostsCategories diff --git a/components/SideBar.js b/components/SideBar.js index ab6632ee..dc18cdc7 100644 --- a/components/SideBar.js +++ b/components/SideBar.js @@ -3,8 +3,9 @@ import MenuButtonGroup from '@/components/MenuButtonGroup' import InfoCard from '@/components/InfoCard' import TagList from '@/components/TagList' import LatestPosts from '@/components/LatestPosts' +import PostsCategories from '@/components/PostsCategories' -const SideBar = ({ tags, currentTag, post, posts }) => { +const SideBar = ({ tags, currentTag, post, posts, categories, currentCategory }) => { // 按时间排序 if (posts) { posts = posts.sort((a, b) => { @@ -26,6 +27,13 @@ const SideBar = ({ tags, currentTag, post, posts }) => {
+ {/* 分类 */} + {categories && ( +
+ +
+ )} + {/* 最新文章 */} {posts && (
diff --git a/components/TagItemMini.js b/components/TagItemMini.js index 9523a4ba..149a2826 100644 --- a/components/TagItemMini.js +++ b/components/TagItemMini.js @@ -3,7 +3,7 @@ import Link from 'next/link' const TagItemMini = ({ tag, selected = false, count }) => ( diff --git a/layouts/BaseLayout.js b/layouts/BaseLayout.js index c0aedea3..522abf6a 100644 --- a/layouts/BaseLayout.js +++ b/layouts/BaseLayout.js @@ -9,7 +9,7 @@ import SideBar from '@/components/SideBar' import JumpToTop from '@/components/JumpToTop' import { useGlobal } from '@/lib/global' -const BaseLayout = ({ children, layout, fullWidth, tags, meta, post, totalPosts, currentSearch, ...customMeta }) => { +const BaseLayout = ({ children, layout, fullWidth, tags, meta, post, totalPosts, currentSearch, currentCategory, categories, ...customMeta }) => { let windowTop = 0 const scrollTrigger = useCallback(throttle(() => { const scrollS = window.scrollY @@ -40,7 +40,7 @@ const BaseLayout = ({ children, layout, fullWidth, tags, meta, post, totalPosts, {/* Middle Wrapper */}
- +
{children}
diff --git a/lib/notion.js b/lib/notion.js index 51c02180..a2f19e88 100644 --- a/lib/notion.js +++ b/lib/notion.js @@ -1,3 +1,4 @@ export { getAllPosts } from './notion/getAllPosts' export { getAllTags } from './notion/getAllTags' export { getPostBlocks } from './notion/getPostBlocks' +export { getAllCategories } from './notion/getAllCategories' diff --git a/lib/notion/getAllCategories.js b/lib/notion/getAllCategories.js new file mode 100644 index 00000000..8e94e8ba --- /dev/null +++ b/lib/notion/getAllCategories.js @@ -0,0 +1,22 @@ +/** + * 获取所有文章的分类 + * @param allPosts + * @returns {Promise<{}|*[]>} + */ +export async function getAllCategories (allPosts) { + if (!allPosts) { + return [] + } + + let categories = allPosts.map(p => p.category) + categories = [...categories.flat()] + const categoryObj = {} + categories.forEach(category => { + if (category in categoryObj) { + categoryObj[category]++ + } else { + categoryObj[category] = 1 + } + }) + return categoryObj +} diff --git a/pages/article/[slug].js b/pages/article/[slug].js index 71eb2e3e..bc1aa5d2 100644 --- a/pages/article/[slug].js +++ b/pages/article/[slug].js @@ -1,4 +1,4 @@ -import { getAllPosts, getAllTags, getPostBlocks } from '@/lib/notion' +import { getAllCategories, getAllPosts, getAllTags, getPostBlocks } from '@/lib/notion' import BLOG from '@/blog.config' import { getPageTableOfContents } from 'notion-utils' import { useRouter } from 'next/router' @@ -9,11 +9,11 @@ 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 BlogPostCardMini from '@/components/BlogPostCardMini' import Comment from '@/components/Comment' import TocBar from '@/components/TocBar' import BaseLayout from '@/layouts/BaseLayout' -import { useRef } from 'react' +import React, { useRef } from 'react' import Custom404 from '@/pages/404' import 'prismjs/themes/prism-okaidia.css' @@ -27,19 +27,19 @@ import 'prismjs/components/prism-typescript' const mapPageUrl = id => { return 'https://www.notion.so/' + id.replace(/-/g, '') } -const ArticleDetail = ({ post, blockMap, tags, prev, next, posts }) => { +const ArticleDetail = ({ post, blockMap, tags, prev, next, posts, categories }) => { if (!post) { return } const meta = { - title: post.title, + title: `${post.title} | ${BLOG.title}`, description: post.summary, type: 'article' } const targetRef = useRef(null) const url = BLOG.link + useRouter().asPath - return + return {/* 阅读进度条 */} @@ -65,25 +65,10 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, posts }) => { {post.summary} - {/* 文章信息 */} + {/* 文章作者等关联信息 */}
- - {post.slug !== 'about' && (<> - - {BLOG.author} - - )} - {post.tags && ( -
- {post.tags.map(tag => ( - - ))} -
- )} +
{post.category}
{post.type[0] !== 'Page' && (
@@ -93,6 +78,15 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, posts }) => { )}
)} + + {post.tags && ( +
+ {post.tags.map(tag => ( + + ))} +
+ )} +
{/* 不蒜子 */} @@ -141,10 +135,10 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, posts }) => {
-
继续阅读
+
其他文章
- - + +
{/* 评论互动 */} @@ -198,13 +192,15 @@ export async function getStaticProps ({ params: { slug } }) { } posts = posts.filter(post => post.type[0] === 'Post') const tags = await getAllTags(posts) + const categories = await getAllCategories(posts) + // 获取推荐文章 const index = posts.indexOf(post) const prev = posts.slice(index - 1, index)[0] ?? posts.slice(-1)[0] const next = posts.slice(index + 1, index + 2)[0] ?? posts[0] return { - props: { post, blockMap, tags, prev, next, posts }, + props: { post, blockMap, tags, prev, next, posts, categories }, revalidate: 1 } } diff --git a/pages/category/[category].js b/pages/category/[category].js new file mode 100644 index 00000000..64ebc902 --- /dev/null +++ b/pages/category/[category].js @@ -0,0 +1,56 @@ +import { getAllCategories, getAllPosts, getAllTags } from '@/lib/notion' +import BLOG from '@/blog.config' +import TagsBar from '@/components/TagsBar' +import BaseLayout from '@/layouts/BaseLayout' +import BlogPostListScroll from '@/components/BlogPostListScroll' + +export default function Category ({ tags, posts, category, categories }) { + const meta = { + title: `${BLOG.title} | ${category}`, + description: BLOG.description, + type: 'website' + } + return +
+ + +
+
+} + +export async function getStaticProps ({ params }) { + const category = params.category + let posts = await getAllPosts({ from: 'category-props' }) + posts = posts.filter( + post => post.status[0] === 'Published' && post.type[0] === 'Post' + ) + const tags = await getAllTags(posts) + const categories = await getAllCategories(posts) + const filteredPosts = posts.filter( + post => post && post.category && post.category.includes(category) + ) + return { + props: { + tags, + posts: filteredPosts, + category, + categories + }, + revalidate: 1 + } +} + +export async function getStaticPaths () { + if (BLOG.isProd) { + const tags = await getAllTags() + return { + paths: Object.keys(tags).map(tag => ({ params: { tag } })), + fallback: true + } + } else { + return { + paths: [], + fallback: true + } + } +} diff --git a/pages/index.js b/pages/index.js index f1fff823..86acb8c9 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,4 +1,4 @@ -import { getAllPosts, getAllTags } from '@/lib/notion' +import { getAllPosts, getAllTags, getAllCategories } from '@/lib/notion' import BLOG from '@/blog.config' import BaseLayout from '@/layouts/BaseLayout' import TagsBar from '@/components/TagsBar' @@ -10,6 +10,7 @@ export async function getStaticProps () { post => post.status[0] === 'Published' && post.type[0] === 'Post' ) const tags = await getAllTags(posts) + const categories = await getAllCategories(posts) const meta = { title: `${BLOG.title} | ${BLOG.description} `, description: BLOG.description, @@ -19,15 +20,16 @@ export async function getStaticProps () { props: { posts, tags, + categories, meta }, revalidate: 1 } } -const Index = ({ posts, tags, meta }) => { +const Index = ({ posts, tags, meta, categories }) => { return ( - +
diff --git a/pages/search.js b/pages/search.js index b462c9bf..b7095202 100644 --- a/pages/search.js +++ b/pages/search.js @@ -1,4 +1,4 @@ -import { getAllPosts, getAllTags } from '@/lib/notion' +import { getAllCategories, getAllPosts, getAllTags } from '@/lib/notion' import BLOG from '@/blog.config' import BaseLayout from '@/layouts/BaseLayout' import TagsBar from '@/components/TagsBar' @@ -11,6 +11,8 @@ export async function getStaticProps () { post => post.status[0] === 'Published' && post.type[0] === 'Post' ) const tags = await getAllTags(posts) + const categories = await getAllCategories(posts) + const meta = { title: `${BLOG.title} | ${BLOG.description} `, description: BLOG.description, @@ -20,13 +22,14 @@ export async function getStaticProps () { props: { posts, tags, - meta + meta, + categories }, revalidate: 1 } } -const Search = ({ posts, tags, meta }) => { +const Search = ({ posts, tags, meta, categories }) => { // 处理查询过滤 支持标签、关键词过滤 let filteredPosts = [] const searchKey = getSearchKey() @@ -38,10 +41,10 @@ const Search = ({ posts, tags, meta }) => { }) } return ( - +
- +
) diff --git a/pages/tag/[tag].js b/pages/tag/[tag].js index 06be98fe..74da8e04 100644 --- a/pages/tag/[tag].js +++ b/pages/tag/[tag].js @@ -1,19 +1,19 @@ -import { getAllPosts, getAllTags } from '@/lib/notion' +import { getAllCategories, getAllPosts, getAllTags } from '@/lib/notion' import BLOG from '@/blog.config' import TagsBar from '@/components/TagsBar' -import BlogPostListPage from '@/components/BlogPostListPage' import BaseLayout from '@/layouts/BaseLayout' +import BlogPostListScroll from '@/components/BlogPostListScroll' -export default function Tag ({ tags, posts, currentTag }) { +export default function Tag ({ tags, posts, currentTag, categories }) { const meta = { - title: `${BLOG.title} | ${currentTag}`, + title: `${BLOG.title} | #${currentTag}`, description: BLOG.description, type: 'website' } - return -
+ return +
- +
} @@ -25,6 +25,7 @@ export async function getStaticProps ({ params }) { post => post.status[0] === 'Published' && post.type[0] === 'Post' ) const tags = await getAllTags(posts) + const categories = await getAllCategories(posts) const filteredPosts = posts.filter( post => post && post.tags && post.tags.includes(currentTag) ) @@ -32,7 +33,8 @@ export async function getStaticProps ({ params }) { props: { tags, posts: filteredPosts, - currentTag + currentTag, + categories }, revalidate: 1 }