mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
@@ -26,6 +26,7 @@ const BLOG = {
|
||||
POST_LIST_STYLE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
|
||||
POST_LIST_PREVIEW: process.env.NEXT_PUBLIC_POST_PREVIEW || 'false', // 是否在列表加载文章预览
|
||||
POST_PREVIEW_LINES: 12, // 预览博客行数
|
||||
POST_RECOMMEND_COUNT: 6, // 推荐文章数量
|
||||
POSTS_PER_PAGE: 6, // post counts per page
|
||||
POSTS_SORT_BY: 'notion', // 排序方式 'date'按时间,'notion'由notion控制
|
||||
|
||||
|
||||
@@ -54,8 +54,10 @@ async function getLatestPosts ({ notionPageData, from, latestPostCount }) {
|
||||
let latestPosts = Object.create(allPosts)
|
||||
// 时间排序
|
||||
latestPosts.sort((a, b) => {
|
||||
const dateA = new Date(a?.lastEditedTime || a.createdTime)
|
||||
const dateB = new Date(b?.lastEditedTime || b.createdTime)
|
||||
// const dateA = new Date(a?.lastEditedTime || a.createdTime)
|
||||
// const dateB = new Date(b?.lastEditedTime || b.createdTime)
|
||||
const dateA = new Date(a.date?.start_date)
|
||||
const dateB = new Date(b.date?.start_date)
|
||||
return dateB - dateA
|
||||
})
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export async function getStaticProps ({ params: { slug } }) {
|
||||
const prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
|
||||
const next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
|
||||
|
||||
const recommendPosts = getRecommendPost(post, allPosts)
|
||||
const recommendPosts = getRecommendPost(post, allPosts, BLOG.POST_RECOMMEND_COUNT)
|
||||
|
||||
return {
|
||||
props: {
|
||||
@@ -76,25 +76,32 @@ export async function getStaticProps ({ params: { slug } }) {
|
||||
* @param {*} count
|
||||
* @returns
|
||||
*/
|
||||
function getRecommendPost (post, allPosts, count = 5) {
|
||||
let filteredPosts = []
|
||||
for (const i in allPosts) {
|
||||
function getRecommendPost (post, allPosts, count = 6) {
|
||||
let recommendPosts = []
|
||||
const postIds = []
|
||||
const currentTags = post.tags
|
||||
for (let i = 0; i < allPosts.length; i++) {
|
||||
const p = allPosts[i]
|
||||
filteredPosts.push(Object.assign(p))
|
||||
if (p.id === post.id || p.type.indexOf('Post') < 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (let j = 0; j < currentTags.length; j++) {
|
||||
const t = currentTags[j]
|
||||
if (postIds.indexOf(p.id) > -1) {
|
||||
continue
|
||||
}
|
||||
if (p.tags && p.tags.indexOf(t) > -1) {
|
||||
recommendPosts.push(p)
|
||||
postIds.push(p.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (post.tags && post.tags.length) {
|
||||
const currentTag = post.tags[0]
|
||||
filteredPosts = filteredPosts.filter(
|
||||
p => p && p.slug !== post.slug && p.tags && p.tags?.includes(currentTag) && p.type === ['Post']
|
||||
)
|
||||
if (recommendPosts.length > count) {
|
||||
recommendPosts = recommendPosts.slice(0, count)
|
||||
}
|
||||
|
||||
// 筛选前5个
|
||||
if (filteredPosts.length > count) {
|
||||
filteredPosts = filteredPosts.slice(0, count)
|
||||
}
|
||||
return filteredPosts
|
||||
return recommendPosts
|
||||
}
|
||||
|
||||
export default Slug
|
||||
|
||||
@@ -51,10 +51,10 @@ const LayoutBase = (props) => {
|
||||
|
||||
{headerSlot}
|
||||
|
||||
<main id='wrapper' className='w-full justify-center py-8 min-h-screen'>
|
||||
<main id='wrapper' className='w-full py-8 min-h-screen'>
|
||||
|
||||
<div id='container-inner' className='pt-14 w-full mx-auto lg:flex justify-between md:space-x-4 max-w-7xl'>
|
||||
<div className='flex-grow w-full'>
|
||||
<div id='container-inner' className='pt-14 w-full mx-auto lg:flex justify-center md:space-x-4'>
|
||||
<div className='flex-grow w-full max-w-4xl'>
|
||||
{onLoading ? <LoadingCover/> : children}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,15 +10,15 @@ export default function ArticleAdjacent ({ prev, next }) {
|
||||
if (!prev || !next || !CONFIG_HEXO.ARTICLE_ADJACENT) {
|
||||
return <></>
|
||||
}
|
||||
return <section className='text-gray-800 h-14 flex items-center justify-between space-x-5 my-1'>
|
||||
return <section className='text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
|
||||
<Link href={`/article/${prev.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer hover:underline justify-start items-center flex w-full h-full duration-200'>
|
||||
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
|
||||
<a className='py-1 cursor-pointer hover:underline justify-start items-center dark:text-white flex w-full h-full duration-200'>
|
||||
<i className='mr-1 fas fa-angle-left' />{prev.title}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={`/article/${next.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer hover:underline justify-end items-center flex w-full h-full duration-200'>{next.title}
|
||||
<i className='ml-1 my-1 fas fa-angle-double-right' />
|
||||
<a className='py-1 cursor-pointer hover:underline justify-end items-center dark:text-white flex w-full h-full duration-200'>{next.title}
|
||||
<i className='ml-1 my-1 fas fa-angle-right' />
|
||||
</a>
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function ArticleCopyright () {
|
||||
})
|
||||
|
||||
const { locale } = useGlobal()
|
||||
return <section className="dark:text-gray-300 mt-6">
|
||||
return <section className="dark:text-gray-300 mt-6 mx-1 font-sans">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-700 bg-gray-100 p-5 leading-8 border-l-2 border-blue-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useEffect, useRef } from 'react'
|
||||
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import ArticleAdjacent from './ArticleAdjacent'
|
||||
import ArticleCopyright from './ArticleCopyright'
|
||||
import ArticleRecommend from './ArticleRecommend'
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -67,6 +68,7 @@ export default function ArticleDetail (props) {
|
||||
</section>
|
||||
|
||||
<ArticleCopyright {...props}/>
|
||||
<ArticleRecommend {...props}/>
|
||||
<ArticleAdjacent {...props}/>
|
||||
|
||||
</article>
|
||||
|
||||
52
themes/hexo/components/ArticleRecommend.js
Normal file
52
themes/hexo/components/ArticleRecommend.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import Link from 'next/link'
|
||||
import CONFIG_HEXO from '../config_hexo'
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
|
||||
/**
|
||||
* 关联推荐文章
|
||||
* @param {prev,next} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function ArticleRecommend ({ recommendPosts }) {
|
||||
if (!CONFIG_HEXO.ARTICLE_RECOMMEND || !recommendPosts || recommendPosts.length === 0) {
|
||||
return <></>
|
||||
}
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<div className="p-2">
|
||||
<div className="font-sans mb-2 px-1 flex flex-nowrap justify-between">
|
||||
<div>
|
||||
<i className="mr-2 fas fa-thumbs-up" />
|
||||
{locale.COMMON.RELATE_POSTS}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{recommendPosts.map(post => {
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("/${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
|
||||
|
||||
return (
|
||||
<Link key={post.id} title={post.title} href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
|
||||
<a key={post.id} className="flex h-40 cursor-pointer overflow-hidden">
|
||||
<div
|
||||
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<div className='flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 '>
|
||||
<div className="font-sans text-sm text-white text-center shadow-text">
|
||||
<div><i className='fas fa-calendar-alt mr-1'/>{post.date?.start_date}</div>
|
||||
<div className='hover:underline'>{post.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import CONFIG_HEXO from '../config_hexo'
|
||||
|
||||
/**
|
||||
* 最新文章列表
|
||||
@@ -19,16 +20,24 @@ const LatestPostsGroup = ({ posts }) => {
|
||||
|
||||
return <>
|
||||
<div className='font-sans mb-2 px-1 flex flex-nowrap justify-between'>
|
||||
<div><i className='mr-2 fas fa-archive' />{locale.COMMON.LATEST_POSTS}</div>
|
||||
<div><i className='mr-2 fas fas fa-history' />{locale.COMMON.LATEST_POSTS}</div>
|
||||
</div>
|
||||
{posts.map(post => {
|
||||
const selected = currentPath === `${BLOG.PATH}/article/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("/${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
|
||||
|
||||
return (
|
||||
<Link key={post.id} title={post.title} href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className={ 'my-1 flex '}>
|
||||
<div className={ (selected ? 'text-white bg-blue-400 ' : 'text-gray-500 dark:text-gray-400 ') + ' text-xs py-1.5 flex overflow-x-hidden whitespace-nowrap hover:bg-blue-400 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-white cursor-pointer items-center'}>
|
||||
<div className='truncate'>{post.title}</div>
|
||||
<div className='w-20 h-16 bg-cover bg-center bg-no-repeat' style={{ backgroundImage: headerImage }}/>
|
||||
<div className={ (selected ? ' text-blue-400 ' : 'dark:text-gray-400 ') + ' text-sm py-1.5 overflow-x-hidden hover:text-blue-400 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-white cursor-pointer items-center flex'}>
|
||||
<div>
|
||||
<div style={{ WebkitLineClamp: 2 }}>{post.title}</div>
|
||||
<div className='text-gray-500'>{post.date?.start_date}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
@@ -5,7 +5,7 @@ import TagGroups from './TagGroups'
|
||||
import Catalog from './Catalog'
|
||||
import { InfoCard } from './InfoCard'
|
||||
import { AnalyticsCard } from './AnalyticsCard'
|
||||
|
||||
import CONFIG_HEXO from '../config_hexo'
|
||||
export default function SideRight (props) {
|
||||
const {
|
||||
post, currentCategory, categories, latestPosts, tags,
|
||||
@@ -13,9 +13,9 @@ export default function SideRight (props) {
|
||||
} = props
|
||||
|
||||
return (
|
||||
<div className={'md:w-80 p-2 space-y-4'}>
|
||||
<div className={'lg:w-80 p-2 space-y-4'}>
|
||||
<InfoCard {...props}/>
|
||||
<AnalyticsCard {...props}/>
|
||||
{ CONFIG_HEXO.WIDGET_ANALYTICS && <AnalyticsCard {...props}/>}
|
||||
|
||||
{showCategory && (
|
||||
<Card>
|
||||
@@ -33,7 +33,7 @@ export default function SideRight (props) {
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</Card>
|
||||
)}
|
||||
{latestPosts && <Card>
|
||||
{CONFIG_HEXO.WIDGET_LATEST_POSTS && latestPosts && <Card>
|
||||
<LatestPostsGroup posts={latestPosts} />
|
||||
</Card>}
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@ const CONFIG_HEXO = {
|
||||
|
||||
ARTICLE_ADJACENT: true, // 显示上一篇下一篇文章推荐
|
||||
ARTICLE_COPYRIGHT: true, // 显示文章版权声明
|
||||
ARTICLE_RECOMMEND: true, // 文章关联推荐
|
||||
|
||||
WIDGET_LATEST_POSTS: true, // 显示最新文章卡
|
||||
WIDGET_ANALYTICS: false, // 显示统计卡
|
||||
WIDGET_TO_TOP: true,
|
||||
WIDGET_TO_COMMENT: true, // 跳到评论区
|
||||
WIDGET_DARK_MODE: true, // 夜间模式
|
||||
|
||||
Reference in New Issue
Block a user