mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-20 23:16:49 +00:00
分页模式加载文章预览
This commit is contained in:
@@ -30,7 +30,7 @@ import WordCount from './WordCount'
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function ArticleDetail ({ post, blockMap, recommendPosts, prev, next }) {
|
||||
export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
|
||||
const targetRef = useRef(null)
|
||||
const drawerRight = useRef(null)
|
||||
const url = BLOG.link + useRouter().asPath
|
||||
@@ -125,9 +125,9 @@ export default function ArticleDetail ({ post, blockMap, recommendPosts, prev, n
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-1'>
|
||||
{blockMap && (
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={blockMap}
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
|
||||
@@ -3,24 +3,25 @@ import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faFolder } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faAngleDoubleRight, faFolder } from '@fortawesome/free-solid-svg-icons'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
|
||||
const BlogPostCard = ({ post }) => {
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<div key={post.id} className='shadow animate__animated animate__fadeIn flex xl:flex-row flex-col-reverse justify-between md:hover:shadow-xl duration-300
|
||||
<div key={post.id} className='shadow border animate__animated animate__fadeIn flex flex-col-reverse justify-between md:hover:shadow-xl duration-300
|
||||
w-full bg-white dark:bg-gray-800 dark:hover:bg-gray-700 dark:border-gray-600'>
|
||||
|
||||
<div className='p-8 flex flex-col justify-between w-full'>
|
||||
<div className='lg:p-8 p-4 flex flex-col justify-between w-full'>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<a className='cursor-pointer text-xl xl:text-2xl leading-tight text-black dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400'>
|
||||
<a className='cursor-pointer font-bold text-3xl text-center leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400'>
|
||||
{post.title}
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<p className='my-8 text-gray-700 dark:text-gray-300 text-md font-light leading-7'>{post.summary}</p>
|
||||
|
||||
<div className='flex items-center justify-between flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 '>
|
||||
<div className='flex mt-2 items-center justify-center flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 '>
|
||||
<div>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className='cursor-pointer font-light text-sm hover:underline transform'>
|
||||
@@ -37,11 +38,36 @@ const BlogPostCard = ({ post }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showSummary && <p className='mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7'>
|
||||
{post.summary}
|
||||
</p>}
|
||||
|
||||
{BLOG.home?.showPreview && post?.blockMap && <div className='max-h-screen overflow-hidden truncate max-w-full'>
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
</div> }
|
||||
|
||||
<div className='border-b-2 w-full border-dashed py-2'></div>
|
||||
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<div className='flex items-center cursor-pointer pt-6 justify-end leading-tight'>
|
||||
<a className='bg-black p-2 text-white'>{locale.COMMON.ARTICLE_DETAIL}
|
||||
<FontAwesomeIcon icon={faAngleDoubleRight} /></a>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{post?.page_cover && (
|
||||
{BLOG.home?.showPostCover && post?.page_cover && (
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<div className='h-60 w-full xl:max-w-xs relative xl:h-full duration-200 cursor-pointer transform overflow-hidden'>
|
||||
<div className='h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden'>
|
||||
<Image className='hover:scale-105 transform duration-500' src={post?.page_cover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' />
|
||||
</div>
|
||||
</Link>
|
||||
@@ -50,4 +76,8 @@ const BlogPostCard = ({ post }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -18,9 +18,9 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
||||
return <BlogPostListEmpty />
|
||||
} else {
|
||||
return (
|
||||
<div id="container" className='mt-10'>
|
||||
<div id="container">
|
||||
{/* 文章列表 */}
|
||||
<div className="flex flex-wrap space-y-8 mx-5 md:mx-0">
|
||||
<div className="flex flex-wrap lg:space-y-4 space-y-1">
|
||||
{posts.map(post => (
|
||||
<BlogPostCard key={post.id} post={post} />
|
||||
))}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import BlogPostCard from '@/components/BlogPostCard'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import throttle from 'lodash.throttle'
|
||||
import BlogPostCard from '@/components/BlogPostCard'
|
||||
import BlogPostListEmpty from '@/components/BlogPostListEmpty'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import throttle from 'lodash.throttle'
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
|
||||
/**
|
||||
* 博客列表滚动分页
|
||||
@@ -14,7 +13,7 @@ import { useGlobal } from '@/lib/global'
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const BlogPostListScroll = ({ posts = [], currentSearch, currentCategory, currentTag }) => {
|
||||
const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = BLOG.home.showSummary }) => {
|
||||
const postsPerPage = BLOG.postsPerPage
|
||||
const [page, updatePage] = useState(1)
|
||||
const postsToShow = getPostByPage(page, posts, postsPerPage)
|
||||
@@ -53,12 +52,12 @@ const BlogPostListScroll = ({ posts = [], currentSearch, currentCategory, curren
|
||||
if (!postsToShow || postsToShow.length === 0) {
|
||||
return <BlogPostListEmpty currentSearch={currentSearch} />
|
||||
} else {
|
||||
return <div id='container' className='mt-10' ref={targetRef}>
|
||||
return <div id='container' ref={targetRef}>
|
||||
|
||||
{/* 文章列表 */}
|
||||
<div className='flex flex-wrap space-y-8 mx-5 md:mx-0'>
|
||||
<div className='flex flex-wrap space-y-8'>
|
||||
{postsToShow.map(post => (
|
||||
<BlogPostCard key={post.id} post={post}/>
|
||||
<BlogPostCard key={post.id} post={post} showSummary={showSummary}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from 'react'
|
||||
|
||||
const Logo = () => {
|
||||
return <Link href='/' passHref>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer bg-gray-800 space-y-3 h-32 font-bold mb-4'>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer bg-black space-y-3 h-32 font-bold'>
|
||||
<div className='font-serif text-xl text-white'> {BLOG.title}</div>
|
||||
<div className='text-sm text-gray-300 font-light'> {BLOG.description}</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,9 @@ const SideAreaLeft = ({ title, tags, currentTag, post, postCount, categories, cu
|
||||
{/* 菜单 */}
|
||||
<section className='shadow hidden lg:block mb-5 pb-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
|
||||
<Logo/>
|
||||
<div className='pt-2'>
|
||||
<MenuButtonGroup allowCollapse={true} />
|
||||
</div>
|
||||
{BLOG.menu.showSearch && <div className='px-5 pt-2'>
|
||||
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
|
||||
</div>}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { faAngleDoubleRight, faTag, faThList } from '@fortawesome/free-solid-svg
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import Logo from './Logo'
|
||||
|
||||
/**
|
||||
* 侧边栏
|
||||
@@ -30,7 +29,6 @@ const SideBar = ({ title, tags, currentTag, post, slot, categories, currentCateg
|
||||
<InfoCard />
|
||||
</section>
|
||||
|
||||
<Logo/>
|
||||
{/* 分类 */}
|
||||
{categories && (
|
||||
<section className='mt-8'>
|
||||
|
||||
@@ -48,7 +48,7 @@ const SideBarDrawer = ({ post, currentTag, cRef, tags, slot, categories, current
|
||||
}
|
||||
|
||||
return <div id='sidebar-wrapper' className='hidden'>
|
||||
<div id='sidebar-drawer' className='-ml-80 bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-50 shadow-2xl'>
|
||||
<div id='sidebar-drawer' className='-ml-80 bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-50'>
|
||||
<SideBar tags={tags} post={post} slot={slot} categories={categories} currentCategory={currentCategory} />
|
||||
</div>
|
||||
{/* 背景蒙版 */}
|
||||
|
||||
@@ -36,7 +36,7 @@ const StickyBar = ({ children }) => {
|
||||
|
||||
return (
|
||||
<div id='sticky-bar' className='sticky flex-grow justify-center top-14 md:top-0 duration-500 z-10 pb-16'>
|
||||
<div className='glassmorphism dark:border-gray-600 px-5 absolute shadow-xl border w-full hidden-scroll'>
|
||||
<div className='glassmorphism dark:border-gray-600 px-5 absolute shadow-md border w-full hidden-scroll'>
|
||||
<div id='tag-container' className="md:pl-3 overflow-x-auto">
|
||||
{ children }
|
||||
</div>
|
||||
|
||||
@@ -3,10 +3,10 @@ import SideBarDrawer from '@/components/SideBarDrawer'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { faBars, faSearch } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
import throttle from 'lodash.throttle'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import Logo from './Logo'
|
||||
import SearchDrawer from './SearchDrawer'
|
||||
|
||||
let windowTop = 0
|
||||
|
||||
@@ -35,7 +35,7 @@ const TopNav = ({ tags, currentTag, post, slot, categories, currentCategory, aut
|
||||
|
||||
// 监听滚动
|
||||
useEffect(() => {
|
||||
if (BLOG.autoCollapsedNavBar) {
|
||||
if (BLOG.topNavType === 'autoCollapse') {
|
||||
scrollTrigger()
|
||||
window.addEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
@@ -43,30 +43,28 @@ const TopNav = ({ tags, currentTag, post, slot, categories, currentCategory, aut
|
||||
BLOG.autoCollapsedNavBar && window.removeEventListener('scroll', scrollTrigger)
|
||||
}
|
||||
}, [])
|
||||
return (<div id='top-nav' className='sticky top-0 z-40 block lg:hidden'>
|
||||
return (<div id='top-nav' className='z-40 block lg:hidden'>
|
||||
{/* 侧面抽屉 */}
|
||||
<SideBarDrawer post={post} currentTag={currentTag} cRef={drawer} tags={tags} slot={slot} categories={categories} currentCategory={currentCategory}/>
|
||||
<SearchDrawer cRef={searchDrawer}/>
|
||||
|
||||
{/* 导航栏 */}
|
||||
<div id='sticky-nav' className='flex animate__animated animate__fadeIn fixed lg:relative w-full top-0 z-20 transform duration-500'>
|
||||
<div className='w-full flex justify-between items-center p-4 glassmorphism'>
|
||||
<div id='sticky-nav' className={`${BLOG.topNavType !== 'normal' ? 'fixed' : ''} flex animate__animated animate__fadeIn lg:relative w-full top-0 z-20 transform duration-500`}>
|
||||
<div className='w-full flex justify-between items-center p-4 bg-black text-white'>
|
||||
{/* 左侧LOGO 标题 */}
|
||||
<div className='flex flex-none flex-grow-0'>
|
||||
<div onClick={() => { drawer.current.handleSwitchSideDrawerVisible() }}
|
||||
className='w-8 cursor-pointer dark:text-gray-300'>
|
||||
className='w-8 cursor-pointer'>
|
||||
<FontAwesomeIcon icon={faBars} size={'lg'}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Link href='/' passHref>
|
||||
<a>
|
||||
<h1 className='cursor-pointer ml-2 w-full hover:scale-105 duration-200 transform font-serif dark:text-gray-200 whitespace-nowrap overflow-x-hidden'>{ BLOG.title }</h1>
|
||||
</a>
|
||||
</Link>
|
||||
<div className='flex'>
|
||||
<Logo/>
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex flex-nowrap flex-grow justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div className='mr-1 flex justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div className="cursor-pointer block lg:hidden" onClick={() => { searchDrawer?.current?.show() }}>
|
||||
<FontAwesomeIcon icon={faSearch} className="mr-2" />{locale.NAV.SEARCH}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user