mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-25 07:26:49 +00:00
@@ -23,7 +23,7 @@ const Comment = ({ frontMatter }) => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (
|
return (
|
||||||
<div className='comment mt-5 text-gray-800 dark:text-gray-300'>
|
<div id='comment' className='comment mt-5 text-gray-800 dark:text-gray-300'>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
{BLOG.COMMENT_UTTERRANCES_REPO && (<div key='Utterance'>
|
{BLOG.COMMENT_UTTERRANCES_REPO && (<div key='Utterance'>
|
||||||
<UtterancesComponent issueTerm={frontMatter.id} className='px-2' />
|
<UtterancesComponent issueTerm={frontMatter.id} className='px-2' />
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export default {
|
|||||||
AUTHOR: 'Author',
|
AUTHOR: 'Author',
|
||||||
URL: 'URL',
|
URL: 'URL',
|
||||||
POSTS: 'Posts',
|
POSTS: 'Posts',
|
||||||
|
ARTICLE: 'Article',
|
||||||
VISITORS: 'Visitors',
|
VISITORS: 'Visitors',
|
||||||
VIEWS: 'Views',
|
VIEWS: 'Views',
|
||||||
COPYRIGHT_NOTICE: 'All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!',
|
COPYRIGHT_NOTICE: 'All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!',
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export default {
|
|||||||
URL: '链接',
|
URL: '链接',
|
||||||
ANALYTICS: '统计',
|
ANALYTICS: '统计',
|
||||||
POSTS: '篇文章',
|
POSTS: '篇文章',
|
||||||
|
ARTICLE: '文章',
|
||||||
VISITORS: '位访客',
|
VISITORS: '位访客',
|
||||||
VIEWS: '次查看',
|
VIEWS: '次查看',
|
||||||
COPYRIGHT_NOTICE: '本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。',
|
COPYRIGHT_NOTICE: '本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。',
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ async function getCustomNav ({ notionPageData }) {
|
|||||||
const customNav = []
|
const customNav = []
|
||||||
if (allPage && allPage.length > 0) {
|
if (allPage && allPage.length > 0) {
|
||||||
allPage.forEach(p => {
|
allPage.forEach(p => {
|
||||||
customNav.push({ icon: p.icon || null, name: p.title, to: '/' + p.slug, show: true })
|
if (p?.slug?.indexOf('http') === 0) {
|
||||||
|
customNav.push({ icon: p.icon || null, name: p.title, to: p.slug, show: true })
|
||||||
|
} else {
|
||||||
|
customNav.push({ icon: p.icon || null, name: p.title, to: '/' + p.slug, show: true })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return customNav
|
return customNav
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ export async function getStaticPaths () {
|
|||||||
|
|
||||||
const from = 'slug-paths'
|
const from = 'slug-paths'
|
||||||
const { allPosts } = await getGlobalNotionData({ from, pageType: ['Page'] })
|
const { allPosts } = await getGlobalNotionData({ from, pageType: ['Page'] })
|
||||||
|
const filterPosts = allPosts?.filter(e => e?.slug?.indexOf('http') !== 0) || []
|
||||||
|
|
||||||
return {
|
return {
|
||||||
paths: allPosts.map(row => ({ params: { slug: row.slug } })),
|
paths: filterPosts.map(row => ({ params: { slug: row.slug } })),
|
||||||
fallback: true
|
fallback: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import JumpToTopButton from './components/JumpToTopButton'
|
|||||||
import SideRight from './components/SideRight'
|
import SideRight from './components/SideRight'
|
||||||
import TopNav from './components/TopNav'
|
import TopNav from './components/TopNav'
|
||||||
import smoothscroll from 'smoothscroll-polyfill'
|
import smoothscroll from 'smoothscroll-polyfill'
|
||||||
|
import FloatDarkModeButton from './components/FloatDarkModeButton'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||||
@@ -54,10 +55,11 @@ const LayoutBase = (props) => {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
{/* 右下角悬浮 */}
|
{/* 右下角悬浮 */}
|
||||||
<div className='right-8 bottom-12 lg:right-2 fixed justify-end z-20 font-sans'>
|
<div className='bottom-12 right-0 fixed justify-end z-20 font-sans'>
|
||||||
<div className={(show ? 'animate__animated ' : 'hidden') + ' animate__fadeInUp rounded-md glassmorphism justify-center duration-500 animate__faster flex space-x-2 items-center cursor-pointer '}>
|
<div className={(show ? 'animate__animated ' : 'hidden') + ' animate__fadeInUp justify-center duration-500 animate__faster flex flex-col items-center cursor-pointer '}>
|
||||||
<JumpToTopButton percent={percent}/>
|
<FloatDarkModeButton/>
|
||||||
{floatSlot}
|
{floatSlot}
|
||||||
|
<JumpToTopButton percent={percent}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'prismjs/components/prism-typescript'
|
|||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
import ArticleDetail from './components/ArticleDetail'
|
import ArticleDetail from './components/ArticleDetail'
|
||||||
import HeaderArticle from './components/HeaderArticle'
|
import HeaderArticle from './components/HeaderArticle'
|
||||||
|
import JumpToCommentButton from './components/JumpToCommentButton'
|
||||||
import TocDrawer from './components/TocDrawer'
|
import TocDrawer from './components/TocDrawer'
|
||||||
import TocDrawerButton from './components/TocDrawerButton'
|
import TocDrawerButton from './components/TocDrawerButton'
|
||||||
import LayoutBase from './LayoutBase'
|
import LayoutBase from './LayoutBase'
|
||||||
@@ -31,18 +32,16 @@ export const LayoutSlug = props => {
|
|||||||
const drawerRight = useRef(null)
|
const drawerRight = useRef(null)
|
||||||
const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null
|
const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null
|
||||||
|
|
||||||
const floatSlot =
|
const floatSlot = <>
|
||||||
post?.toc?.length > 1
|
{post?.toc?.length > 1 && <div className="block lg:hidden">
|
||||||
? (
|
|
||||||
<div className="block lg:hidden">
|
|
||||||
<TocDrawerButton
|
<TocDrawerButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
drawerRight?.current?.handleSwitchVisible()
|
drawerRight?.current?.handleSwitchVisible()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>}
|
||||||
)
|
<JumpToCommentButton/>
|
||||||
: null
|
</>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutBase
|
<LayoutBase
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
|
|
||||||
<div className='lg:p-8 p-4 flex flex-col w-full'>
|
<div className='lg:p-8 p-4 flex flex-col w-full'>
|
||||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||||
<a className={`cursor-pointer font-bold hover:underline text-3xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
<a className={`cursor-pointer hover:underline text-3xl font-sans ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
||||||
{post.title}
|
{post.title}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -22,7 +22,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
<div className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'} 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 ${showPreview ? 'justify-center' : 'justify-start'} flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 `}>
|
||||||
<div>
|
<div>
|
||||||
<Link href={`/archive#${post?.date?.start_date?.substr(0, 7)}`} passHref>
|
<Link href={`/archive#${post?.date?.start_date?.substr(0, 7)}`} passHref>
|
||||||
<a className='font-light hover:underline cursor-pointer text-sm leading-4 mr-3'>{post.date.start_date}</a>
|
<a className='font-light hover:underline cursor-pointer text-sm leading-4 mr-3'><i className="far fa-calendar-alt mr-1"/>{post.date.start_date}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,7 +49,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
|
|
||||||
<Link href={`/category/${post.category}`} passHref>
|
<Link href={`/category/${post.category}`} passHref>
|
||||||
<a className='cursor-pointer font-light text-sm hover:underline transform'>
|
<a className='cursor-pointer font-light text-sm hover:underline transform'>
|
||||||
<i className='mr-1 fas fa-folder' />{post.category}
|
<i className='mr-1 far fa-folder' />{post.category}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<div className='md:flex-nowrap flex-wrap md:justify-start inline-block'>
|
<div className='md:flex-nowrap flex-wrap md:justify-start inline-block'>
|
||||||
|
|||||||
30
themes/Hexo/components/FloatDarkModeButton.js
Normal file
30
themes/Hexo/components/FloatDarkModeButton.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||||
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
|
|
||||||
|
export default function FloatDarkModeButton () {
|
||||||
|
if (!CONFIG_HEXO.WIDGET_DARK_MODE) {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||||
|
// 用户手动设置主题
|
||||||
|
const handleChangeDarkMode = () => {
|
||||||
|
const newStatus = !isDarkMode
|
||||||
|
saveDarkModeToCookies(newStatus)
|
||||||
|
updateDarkMode(newStatus)
|
||||||
|
const htmlElement = document.getElementsByTagName('html')[0]
|
||||||
|
htmlElement.classList?.remove(newStatus ? 'light' : 'dark')
|
||||||
|
htmlElement.classList?.add(newStatus ? 'dark' : 'light')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={handleChangeDarkMode}
|
||||||
|
className={'justify-center items-center text-white bg-gray-400 w-7 h-7 text-center transform hover:scale-105 duration-200'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i id="darkModeButton" className={`${isDarkMode ? 'fa-sun' : 'fa-moon'} fas text-xs`}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -7,14 +7,15 @@ const Footer = ({ title }) => {
|
|||||||
const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
|
const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
|
||||||
return (
|
return (
|
||||||
<footer
|
<footer
|
||||||
className='dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-gray-400 text-sm p-6'
|
className='font-sans dark:bg-gray-900 flex-shrink-0 bg-blue-400 justify-center text-center m-auto w-full leading-6 text-gray-100 text-sm p-6'
|
||||||
>
|
>
|
||||||
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
|
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={BLOG.LINK} className='underline font-bold text-gray-50 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<span>Powered by <a href='https://notion.so' className='underline font-bold text-gray-500 dark:text-gray-300'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-500 dark:text-gray-300'>NotionNext</a>.</span></span>
|
<span>Powered by <a href='https://notion.so' className='underline font-bold text-gray-50 dark:text-gray-300'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-50 dark:text-gray-300'>NotionNext</a>.</span></span>
|
||||||
|
|
||||||
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
|
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
|
||||||
|
<br/>
|
||||||
<span className='hidden busuanzi_container_site_pv'>
|
<span className='hidden busuanzi_container_site_pv'>
|
||||||
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
|
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
|
||||||
<span className='pl-2 hidden busuanzi_container_site_uv'>
|
<span className='pl-2 hidden busuanzi_container_site_uv'>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export default function HeaderArticle ({ post }) {
|
|||||||
passHref
|
passHref
|
||||||
>
|
>
|
||||||
<a className="pl-1 mr-2 cursor-pointer hover:underline border-b dark:border-gray-500 border-dashed">
|
<a className="pl-1 mr-2 cursor-pointer hover:underline border-b dark:border-gray-500 border-dashed">
|
||||||
{date}
|
<i className="far fa-calendar-alt mr-1"/> {date}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
|
|||||||
29
themes/Hexo/components/InfoCard.js
Normal file
29
themes/Hexo/components/InfoCard.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import BLOG from '@/blog.config'
|
||||||
|
import Image from 'next/image'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import Card from './Card'
|
||||||
|
import SocialButton from './SocialButton'
|
||||||
|
import MenuGroupCard from './MenuGroupCard'
|
||||||
|
export function InfoCard (props) {
|
||||||
|
const router = useRouter()
|
||||||
|
return <Card>
|
||||||
|
<div
|
||||||
|
className='justify-center items-center flex hover:rotate-45 py-6 hover:scale-105 transform duration-200 cursor-pointer'
|
||||||
|
onClick={() => {
|
||||||
|
router.push('/')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
alt={BLOG.AUTHOR}
|
||||||
|
width={120}
|
||||||
|
height={120}
|
||||||
|
loading='lazy'
|
||||||
|
src='/avatar.jpg'
|
||||||
|
className='rounded-full'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-center font-sans text-xl pb-4 dark:text-gray-300'>{BLOG.TITLE}</div>
|
||||||
|
<MenuGroupCard {...props}/>
|
||||||
|
<SocialButton />
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
25
themes/Hexo/components/JumpToCommentButton.js
Normal file
25
themes/Hexo/components/JumpToCommentButton.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到评论区
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const JumpToCommentButton = () => {
|
||||||
|
if (!CONFIG_HEXO.WIDGET_TO_COMMENT) {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
function navToComment () {
|
||||||
|
const commentElement = document.getElementById('comment')
|
||||||
|
if (commentElement) {
|
||||||
|
commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<div className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 text-white bg-gray-400 w-7 h-7 text-center' onClick={navToComment} >
|
||||||
|
<i className='fas fa-comment text-xs' />
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default JumpToCommentButton
|
||||||
@@ -15,11 +15,9 @@ const JumpToTopButton = ({ showPercent = true, percent }) => {
|
|||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (<div className='flex space-x-1 items-center transform hover:scale-105 duration-200 py-2 px-3' onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} >
|
return (<div className='space-x-1 items-center justify-center transform hover:scale-105 duration-200 text-white bg-gray-400 w-7 h-auto pb-1 text-center' onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} >
|
||||||
<div className='dark:text-gray-200' title={locale.POST.TOP} >
|
<div title={locale.POST.TOP} ><i className='fas fa-arrow-up text-xs' /></div>
|
||||||
<i className='fas fa-arrow-up' />
|
{showPercent && (<div className='text-xs hidden lg:block'>{percent}</div>)}
|
||||||
</div>
|
|
||||||
{showPercent && (<div className='text-xs dark:text-gray-200 block lg:hidden'>{percent}%</div>)}
|
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
themes/Hexo/components/MenuButtonGroupTop.js
Normal file
37
themes/Hexo/components/MenuButtonGroupTop.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
|
|
||||||
|
const MenuButtonGroupTop = (props) => {
|
||||||
|
const { customNav } = props
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
|
let links = [
|
||||||
|
{ icon: 'fas fa-archive', name: locale.COMMON.ARTICLE, to: '/archive', show: CONFIG_HEXO.MENU_ARCHIVE },
|
||||||
|
{ icon: 'fas fa-folder', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_HEXO.MENU_CATEGORY },
|
||||||
|
{ icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_HEXO.MENU_TAG }
|
||||||
|
]
|
||||||
|
|
||||||
|
if (customNav) {
|
||||||
|
links = links.concat(customNav)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <nav id='nav' className='leading-8 flex justify-center font-sans w-full'>
|
||||||
|
{links.map(link => {
|
||||||
|
if (link.show) {
|
||||||
|
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||||
|
<a className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'} >
|
||||||
|
<div className='w-full flex dark:text-white text-sm items-center justify-center hover:scale-105 duration-200 transform'>
|
||||||
|
<i className={`${link.icon} mr-1`}/>
|
||||||
|
<div className='text-center'>{link.name}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
|
export default MenuButtonGroupTop
|
||||||
36
themes/Hexo/components/MenuGroupCard.js
Normal file
36
themes/Hexo/components/MenuGroupCard.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
|
|
||||||
|
const MenuGroupCard = (props) => {
|
||||||
|
const { postCount, categories, tags } = props
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
const archiveSlot = <div className='text-center'>{postCount}</div>
|
||||||
|
const categorySlot = <div className='text-center'>{categories?.length}</div>
|
||||||
|
const tagSlot = <div className='text-center'>{tags?.length}</div>
|
||||||
|
|
||||||
|
const links = [
|
||||||
|
{ name: locale.COMMON.ARTICLE, to: '/archive', slot: archiveSlot, show: CONFIG_HEXO.MENU_ARCHIVE },
|
||||||
|
{ name: locale.COMMON.CATEGORY, to: '/category', slot: categorySlot, show: CONFIG_HEXO.MENU_CATEGORY },
|
||||||
|
{ name: locale.COMMON.TAGS, to: '/tag', slot: tagSlot, show: CONFIG_HEXO.MENU_TAG }
|
||||||
|
]
|
||||||
|
|
||||||
|
return <nav id='nav' className='leading-8 flex justify-center text-gray-500 dark:text-gray-400 font-sans w-full'>
|
||||||
|
{links.map(link => {
|
||||||
|
if (link.show) {
|
||||||
|
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||||
|
<a className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'} >
|
||||||
|
<div className='w-full items-center justify-center hover:scale-105 duration-200 transform'>
|
||||||
|
<div className='text-center'>{link.name}</div>
|
||||||
|
<div className='text-center font-semibold'>{link.slot}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
|
export default MenuGroupCard
|
||||||
@@ -4,11 +4,11 @@ import { useRouter } from 'next/router'
|
|||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import CONFIG_HEXO from '../config_hexo'
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
|
|
||||||
const MenuButtonGroup = (props) => {
|
const MenuList = (props) => {
|
||||||
const { postCount, customNav } = props
|
const { postCount, customNav } = props
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const archiveSlot = <div className='bg-blue-300 dark:bg-blue-400 rounded-md text-gray-50 px-1 text-xs'>{postCount}</div>
|
const archiveSlot = <div className='bg-gray-300 dark:bg-gray-500 rounded-md text-gray-50 px-1 text-xs'>{postCount}</div>
|
||||||
|
|
||||||
let links = [
|
let links = [
|
||||||
{ icon: 'fas fa-home', name: locale.NAV.INDEX, to: '/' || '/', show: true },
|
{ icon: 'fas fa-home', name: locale.NAV.INDEX, to: '/' || '/', show: true },
|
||||||
@@ -20,13 +20,14 @@ const MenuButtonGroup = (props) => {
|
|||||||
if (customNav) {
|
if (customNav) {
|
||||||
links = links.concat(customNav)
|
links = links.concat(customNav)
|
||||||
}
|
}
|
||||||
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans w-full'>
|
|
||||||
|
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans'>
|
||||||
{links.map(link => {
|
{links.map(link => {
|
||||||
if (link.show) {
|
if (link && link.show) {
|
||||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||||
<a className={'py-1.5 my-1 px-5 duration-300 text-base justify-between hover:bg-blue-400 rounded-md hover:text-white hover:shadow-lg cursor-pointer flex flex-nowrap items-center ' +
|
<a className={'py-1.5 px-5 duration-300 text-base justify-between hover:bg-blue-400 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||||
(selected ? 'bg-blue-400 rounded-md text-white' : ' ')} >
|
(selected ? 'bg-gray-200 text-black' : ' ')} >
|
||||||
<div className='my-auto items-center justify-center flex '>
|
<div className='my-auto items-center justify-center flex '>
|
||||||
<i className={`${link.icon} w-4 text-center`} />
|
<i className={`${link.icon} w-4 text-center`} />
|
||||||
<div className={'ml-4'}>{link.name}</div>
|
<div className={'ml-4'}>{link.name}</div>
|
||||||
@@ -40,4 +41,4 @@ const MenuButtonGroup = (props) => {
|
|||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
export default MenuButtonGroup
|
export default MenuList
|
||||||
@@ -48,7 +48,7 @@ const PaginationNumber = ({ page, totalPage }) => {
|
|||||||
|
|
||||||
function getPageElement (page, currentPage) {
|
function getPageElement (page, currentPage) {
|
||||||
return <Link href={page === 1 ? '/' : `/page/${page}`} key={page} passHref>
|
return <Link href={page === 1 ? '/' : `/page/${page}`} key={page} passHref>
|
||||||
<a className={(page + '' === currentPage + '' ? 'font-bold bg-blue-500 dark:bg-blue-400 text-white ' : 'border-t-2 duration-500 border-white hover:border-blue-400 ') +
|
<a className={(page + '' === currentPage + '' ? 'font-bold bg-blue-400 dark:bg-blue-500 text-white ' : 'border-t-2 duration-500 border-white hover:border-blue-400 ') +
|
||||||
' border-white dark:border-blue-700 dark:hover:border-blue-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'}>
|
' border-white dark:border-blue-700 dark:hover:border-blue-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'}>
|
||||||
{page}
|
{page}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
import Router from 'next/router'
|
|
||||||
import Image from 'next/image'
|
|
||||||
import BLOG from '@/blog.config'
|
|
||||||
import Card from './Card'
|
import Card from './Card'
|
||||||
import MenuButtonGroup from './MenuButtonGroup'
|
|
||||||
import SearchInput from './SearchInput'
|
|
||||||
import CategoryGroup from './CategoryGroup'
|
import CategoryGroup from './CategoryGroup'
|
||||||
import LatestPostsGroup from './LatestPostsGroup'
|
import LatestPostsGroup from './LatestPostsGroup'
|
||||||
import TagGroups from './TagGroups'
|
import TagGroups from './TagGroups'
|
||||||
import SocialButton from './SocialButton'
|
|
||||||
import Catalog from './Catalog'
|
import Catalog from './Catalog'
|
||||||
|
import { InfoCard } from './InfoCard'
|
||||||
|
|
||||||
export default function SideRight (props) {
|
export default function SideRight (props) {
|
||||||
const {
|
const {
|
||||||
@@ -24,29 +19,7 @@ export default function SideRight (props) {
|
|||||||
} = props
|
} = props
|
||||||
return (
|
return (
|
||||||
<div className='w-96 space-y-4 hidden lg:block'>
|
<div className='w-96 space-y-4 hidden lg:block'>
|
||||||
<Card>
|
<InfoCard {...props}/>
|
||||||
<div
|
|
||||||
className='justify-center items-center flex hover:rotate-45 py-6 hover:scale-105 transform duration-200 cursor-pointer'
|
|
||||||
onClick={() => {
|
|
||||||
Router.push('/')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
alt={BLOG.AUTHOR}
|
|
||||||
width={120}
|
|
||||||
height={120}
|
|
||||||
loading='lazy'
|
|
||||||
src='/avatar.jpg'
|
|
||||||
className='rounded-full'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='text-center font-sans text-xl pb-4 dark:text-gray-300'>{BLOG.TITLE}</div>
|
|
||||||
<SocialButton />
|
|
||||||
</Card>
|
|
||||||
<Card>
|
|
||||||
<MenuButtonGroup {...props}/>
|
|
||||||
<SearchInput {...props}/>
|
|
||||||
</Card>
|
|
||||||
<Card>
|
<Card>
|
||||||
<div className='ml-2 mb-3 font-sans'>
|
<div className='ml-2 mb-3 font-sans'>
|
||||||
<i className='fas fa-chart-area' /> 统计
|
<i className='fas fa-chart-area' /> 统计
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ const TocDrawer = ({ post, cRef }) => {
|
|||||||
{/* 侧边菜单 */}
|
{/* 侧边菜单 */}
|
||||||
<div
|
<div
|
||||||
className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') +
|
className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') +
|
||||||
' shadow-card animate__animated animate__faster max-h-36 ' +
|
' shadow-card animate__animated animate__faster h-36 ' +
|
||||||
' w-60 duration-200 fixed right-8 bottom-24 rounded overflow-y-auto py-2 bg-white dark:bg-gray-600'}>
|
' w-60 duration-200 fixed right-12 bottom-12 rounded overflow-y-auto py-2 bg-white dark:bg-gray-600'}>
|
||||||
{post && <>
|
{post && <>
|
||||||
<div className='dark:text-gray-400 text-gray-600 dark:bg-gray-800'>
|
<div className='dark:text-gray-400 text-gray-600'>
|
||||||
<Catalog toc={post.toc}/>
|
<Catalog toc={post.toc}/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const TocDrawerButton = (props) => {
|
|||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (<div onClick={props.onClick} className='py-2 px-3 cursor-pointer dark:text-gray-200 text-center transform hover:scale-150 duration-200 flex justify-center items-center' title={locale.POST.TOP} >
|
return (<div onClick={props.onClick} className='py-2 px-3 cursor-pointer text-white transform duration-200 flex justify-center items-center bg-gray-400 w-7 h-7 text-center' title={locale.POST.TOP} >
|
||||||
<i className='fas fa-list-ol'/>
|
<i className='fas fa-list-ol text-xs'/>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { useEffect, useRef, useState } from 'react'
|
|||||||
import CategoryGroup from './CategoryGroup'
|
import CategoryGroup from './CategoryGroup'
|
||||||
import Collapse from './Collapse'
|
import Collapse from './Collapse'
|
||||||
import Logo from './Logo'
|
import Logo from './Logo'
|
||||||
import MenuButtonGroup from './MenuButtonGroup'
|
|
||||||
import SearchDrawer from './SearchDrawer'
|
import SearchDrawer from './SearchDrawer'
|
||||||
import TagGroups from './TagGroups'
|
import TagGroups from './TagGroups'
|
||||||
import CONFIG_HEXO from '../config_hexo'
|
import CONFIG_HEXO from '../config_hexo'
|
||||||
import SearchInput from './SearchInput'
|
import MenuButtonGroupTop from './MenuButtonGroupTop'
|
||||||
|
import MenuList from './MenuList'
|
||||||
|
|
||||||
let windowTop = 0
|
let windowTop = 0
|
||||||
|
|
||||||
@@ -18,7 +18,8 @@ let windowTop = 0
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) => {
|
const TopNav = (props) => {
|
||||||
|
const { tags, currentTag, categories, currentCategory } = props
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
const searchDrawer = useRef()
|
const searchDrawer = useRef()
|
||||||
|
|
||||||
@@ -26,13 +27,13 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
|
|||||||
const scrollS = window.scrollY
|
const scrollS = window.scrollY
|
||||||
const nav = document.querySelector('#sticky-nav')
|
const nav = document.querySelector('#sticky-nav')
|
||||||
const header = document.querySelector('#header')
|
const header = document.querySelector('#header')
|
||||||
const showNav = (scrollS > 10 && scrollS >= windowTop) || (header && scrollS < 5) // 非首页无大图时影藏顶部 滚动条置顶时隐藏
|
const showNav = (scrollS > 0 && scrollS < windowTop) || (header && scrollS < 5) // 非首页无大图时影藏顶部 滚动条置顶时隐藏
|
||||||
|
|
||||||
if (!showNav) {
|
if (!showNav) {
|
||||||
nav && nav.classList.replace('top-0', '-top-16')
|
nav && nav.classList.replace('top-0', '-top-20')
|
||||||
windowTop = scrollS
|
windowTop = scrollS
|
||||||
} else {
|
} else {
|
||||||
nav && nav.classList.replace('-top-16', 'top-0')
|
nav && nav.classList.replace('-top-20', 'top-0')
|
||||||
windowTop = scrollS
|
windowTop = scrollS
|
||||||
}
|
}
|
||||||
}, 200)
|
}, 200)
|
||||||
@@ -90,24 +91,24 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
|
|||||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot}/>
|
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot}/>
|
||||||
|
|
||||||
{/* 导航栏 */}
|
{/* 导航栏 */}
|
||||||
<div id='sticky-nav' className={`${CONFIG_HEXO.NAV_TYPE !== 'normal' ? 'fixed bg-white' : ' bg-none -mb-10'} dark:bg-black dark:bg-opacity-50 dark:text-gray-200 bg-opacity-70 text-black w-full top-0 z-20 transform duration-500 font-sans`}>
|
<div id='sticky-nav' className={`${CONFIG_HEXO.NAV_TYPE !== 'normal' ? 'fixed bg-white' : ' bg-none -mb-10'} dark:bg-black dark:bg-opacity-50 dark:text-gray-200 bg-opacity-80 text-black w-full top-0 z-20 transform duration-500 font-sans`}>
|
||||||
<div className='w-full flex justify-between items-center px-4 py-2 shad'>
|
<div className='w-full flex justify-between items-center px-4 py-4 shadow'>
|
||||||
<div className='flex'>
|
<div className='flex'>
|
||||||
<Logo/>
|
<Logo/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 右侧功能 */}
|
{/* 右侧功能 */}
|
||||||
<div className='mr-1 flex lg:hidden justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
<div className='mr-1 justify-end items-center space-x-4 font-serif dark:text-gray-200'>
|
||||||
<div onClick={toggleMenuOpen} className='w-8 cursor-pointer'>
|
<div className='hidden lg:flex'> <MenuButtonGroupTop {...props}/></div>
|
||||||
|
<div onClick={toggleMenuOpen} className='w-8 cursor-pointer flex lg:hidden'>
|
||||||
{ isOpen ? <i className='fas fa-times'/> : <i className='fas fa-bars'/> }
|
{ isOpen ? <i className='fas fa-times'/> : <i className='fas fa-bars'/> }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Collapse isOpen={isOpen} className='shadow-xl rounded-b-xl'>
|
<Collapse isOpen={isOpen} className='shadow-xl'>
|
||||||
<div className='bg-white pt-1 py-2 px-5'>
|
<div className='bg-white pt-1 py-2 px-5'>
|
||||||
<MenuButtonGroup postCount={postCount}/>
|
<MenuList {...props}/>
|
||||||
<SearchInput/>
|
|
||||||
</div>
|
</div>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ const CONFIG_HEXO = {
|
|||||||
HOME_BANNER_GREETINGS: ['Hi,我是一个程序员', 'Hi,我是一个打工人', 'Hi,我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
|
HOME_BANNER_GREETINGS: ['Hi,我是一个程序员', 'Hi,我是一个打工人', 'Hi,我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
|
||||||
HOME_BANNER_IMAGE: './bg_image.jpg', // see /public/bg_image.jpg
|
HOME_BANNER_IMAGE: './bg_image.jpg', // see /public/bg_image.jpg
|
||||||
|
|
||||||
// 菜单
|
// 菜单配置
|
||||||
MENU_ABOUT: false, // 显示关于
|
|
||||||
MENU_CATEGORY: true, // 显示分类
|
MENU_CATEGORY: true, // 显示分类
|
||||||
MENU_TAG: true, // 显示标签
|
MENU_TAG: true, // 显示标签
|
||||||
MENU_ARCHIVE: true, // 显示归档
|
MENU_ARCHIVE: true, // 显示归档
|
||||||
@@ -16,6 +15,8 @@ const CONFIG_HEXO = {
|
|||||||
NAV_TYPE: 'autoCollapse', // ['fixed','autoCollapse','normal'] 分别是固定屏幕顶部、屏幕顶部自动折叠,不固定
|
NAV_TYPE: 'autoCollapse', // ['fixed','autoCollapse','normal'] 分别是固定屏幕顶部、屏幕顶部自动折叠,不固定
|
||||||
|
|
||||||
WIDGET_TO_TOP: true,
|
WIDGET_TO_TOP: true,
|
||||||
|
WIDGET_TO_COMMENT: true, // 跳到评论区
|
||||||
|
WIDGET_DARK_MODE: true, // 夜间模式
|
||||||
WIDGET_TOC: true // 移动端悬浮目录
|
WIDGET_TOC: true // 移动端悬浮目录
|
||||||
}
|
}
|
||||||
export default CONFIG_HEXO
|
export default CONFIG_HEXO
|
||||||
|
|||||||
Reference in New Issue
Block a user