mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-02 07:26:45 +00:00
Example主题支持配置:标题栏背景、文章页布局
This commit is contained in:
@@ -4,12 +4,13 @@ import { MenuList } from './MenuList'
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 网站顶部
|
* 网站顶部
|
||||||
|
* LOGO 和 菜单
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const Header = props => {
|
export const Header = props => {
|
||||||
return (
|
return (
|
||||||
<header className='w-full px-6 bg-white dark:bg-black relative z-20'>
|
<header className='w-full px-6 bg-white dark:bg-black relative z-20'>
|
||||||
<div className='container mx-auto max-w-4xl md:flex justify-between items-center'>
|
<div className='mx-auto max-w-4xl md:flex justify-between items-center'>
|
||||||
<Link
|
<Link
|
||||||
href='/'
|
href='/'
|
||||||
className='py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center'>
|
className='py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center'>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const MenuList = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className='w-full bg-white md:pt-0 px-6 relative z-20 border-t border-b border-gray-light dark:border-hexo-black-gray dark:bg-black'>
|
<nav className='w-full bg-white md:pt-0 px-6 relative z-20 border-t border-b border-gray-light dark:border-hexo-black-gray dark:bg-black'>
|
||||||
<div className='container mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start'>
|
<div className='mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start'>
|
||||||
<ul className='w-full text-center md:text-left flex flex-wrap justify-center items-stretch md:justify-start md:items-start'>
|
<ul className='w-full text-center md:text-left flex flex-wrap justify-center items-stretch md:justify-start md:items-start'>
|
||||||
{links.map((link, index) => (
|
{links.map((link, index) => (
|
||||||
<MenuItemDrop key={index} link={link} />
|
<MenuItemDrop key={index} link={link} />
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { siteConfig } from '@/lib/config'
|
|||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import CONFIG from '../config'
|
||||||
import Announcement from './Announcement'
|
import Announcement from './Announcement'
|
||||||
const ExampleRecentComments = dynamic(
|
const ExampleRecentComments = dynamic(
|
||||||
() => import('./RecentCommentListForExample')
|
() => import('./RecentCommentListForExample')
|
||||||
@@ -13,10 +14,26 @@ const ExampleRecentComments = dynamic(
|
|||||||
*/
|
*/
|
||||||
export const SideBar = props => {
|
export const SideBar = props => {
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
const { latestPosts, categoryOptions, notice } = props
|
const { latestPosts, categoryOptions, notice, post } = props
|
||||||
|
// 评论相关
|
||||||
|
const COMMENT_WALINE_SERVER_URL = siteConfig(
|
||||||
|
'COMMENT_WALINE_SERVER_URL',
|
||||||
|
false
|
||||||
|
)
|
||||||
|
const COMMENT_WALINE_RECENT = siteConfig('COMMENT_WALINE_RECENT', false)
|
||||||
|
|
||||||
|
// 文章详情页特殊布局
|
||||||
|
const HIDDEN_NOTIFICATION =
|
||||||
|
post && siteConfig('EXAMPLE_ARTICLE_HIDDEN_NOTIFICATION', false, CONFIG)
|
||||||
|
|
||||||
|
// 文章详情页左右布局改为上下布局
|
||||||
|
const LAYOUT_VERTICAL =
|
||||||
|
post && siteConfig('EXAMPLE_ARTICLE_LAYOUT_VERTICAL', false, CONFIG)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full md:w-64 sticky top-8'>
|
<>
|
||||||
<aside className='rounded shadow overflow-hidden mb-6'>
|
{/* 分类 */}
|
||||||
|
<aside className='w-full rounded shadow overflow-hidden mb-6'>
|
||||||
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
||||||
{locale.COMMON.CATEGORY}
|
{locale.COMMON.CATEGORY}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -34,7 +51,7 @@ export const SideBar = props => {
|
|||||||
{' '}
|
{' '}
|
||||||
<a
|
<a
|
||||||
href={`/category/${category.name}`}
|
href={`/category/${category.name}`}
|
||||||
className='text-gray-darkest text-sm'>
|
className='text-gray-darkest text-sm hover:underline'>
|
||||||
{category.name}({category.count})
|
{category.name}({category.count})
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -44,7 +61,9 @@ export const SideBar = props => {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
<aside className='rounded shadow overflow-hidden mb-6'>
|
|
||||||
|
{/* 最新文章 */}
|
||||||
|
<aside className='w-full rounded shadow overflow-hidden mb-6'>
|
||||||
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
||||||
{locale.COMMON.LATEST_POSTS}
|
{locale.COMMON.LATEST_POSTS}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -58,7 +77,7 @@ export const SideBar = props => {
|
|||||||
{' '}
|
{' '}
|
||||||
<a
|
<a
|
||||||
href={`/${p.slug}`}
|
href={`/${p.slug}`}
|
||||||
className='text-gray-darkest text-sm'>
|
className='text-gray-darkest text-sm hover:underline'>
|
||||||
{p.title}
|
{p.title}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -68,25 +87,29 @@ export const SideBar = props => {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
{/* 公告 */}
|
||||||
{/* 公告栏 */}
|
{/* 公告栏 */}
|
||||||
<Announcement post={notice} />
|
{!HIDDEN_NOTIFICATION && <Announcement post={notice} />}
|
||||||
|
|
||||||
{/* 最近评论 */}
|
{/* 最近评论 */}
|
||||||
{siteConfig('COMMENT_WALINE_SERVER_URL') &&
|
{COMMENT_WALINE_SERVER_URL && COMMENT_WALINE_RECENT && (
|
||||||
siteConfig('COMMENT_WALINE_RECENT') && (
|
<aside className='w-full rounded shadow overflow-hidden mb-6'>
|
||||||
<aside className='rounded shadow overflow-hidden mb-6'>
|
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
||||||
<h3 className='text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b'>
|
{locale.COMMON.RECENT_COMMENTS}
|
||||||
{locale.COMMON.RECENT_COMMENTS}
|
</h3>
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div className='p-4'>
|
<div className='p-4'>
|
||||||
<ExampleRecentComments />
|
<ExampleRecentComments />
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
)}
|
)}
|
||||||
<aside className='rounded overflow-hidden mb-6'>
|
|
||||||
|
{/* 宠物挂件 */}
|
||||||
|
<aside
|
||||||
|
className={`rounded overflow-hidden mb-6 ${LAYOUT_VERTICAL ? 'hidden md:fixed right-4 bottom-20' : ''}`}>
|
||||||
<Live2D />
|
<Live2D />
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
48
themes/example/components/TitleBar.js
Normal file
48
themes/example/components/TitleBar.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import NotionIcon from '@/components/NotionIcon'
|
||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题栏
|
||||||
|
*/
|
||||||
|
export default function TitleBar(props) {
|
||||||
|
const { post } = props
|
||||||
|
const { fullWidth, siteInfo } = useGlobal()
|
||||||
|
|
||||||
|
const title = post?.title || siteConfig('TITLE')
|
||||||
|
const description = post?.description || siteConfig('AUTHOR')
|
||||||
|
const headerImage = post?.pageCoverThumbnail
|
||||||
|
? post.pageCoverThumbnail
|
||||||
|
: siteInfo?.pageCover
|
||||||
|
|
||||||
|
const TITLE_BG = siteConfig('EXAMPLE_TITLE_IMAGE', false, CONFIG)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* 标题栏 */}
|
||||||
|
{!fullWidth && (
|
||||||
|
<div className='relative overflow-hidden text-center px-6 py-12 mb-6 bg-gray-100 dark:bg-hexo-black-gray dark:border-hexo-black-gray border-b'>
|
||||||
|
<h1 className='title-1 relative text-xl md:text-4xl pb-4 z-10'>
|
||||||
|
{siteConfig('POST_TITLE_ICON') && (
|
||||||
|
<NotionIcon icon={post?.pageIcon} />
|
||||||
|
)}
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
<p className='title-2 relative leading-loose text-gray-dark z-10'>
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
{TITLE_BG && (
|
||||||
|
<>
|
||||||
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
|
<img
|
||||||
|
src={headerImage}
|
||||||
|
className='absolute object-cover top-0 left-0 w-full h-full select-none opacity-70 z-0'
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,7 +8,12 @@ const CONFIG = {
|
|||||||
EXAMPLE_MENU_ARCHIVE: true, // 显示归档
|
EXAMPLE_MENU_ARCHIVE: true, // 显示归档
|
||||||
EXAMPLE_MENU_SEARCH: true, // 显示搜索
|
EXAMPLE_MENU_SEARCH: true, // 显示搜索
|
||||||
|
|
||||||
EXAMPLE_POST_LIST_COVER: true // 列表显示文章封面
|
EXAMPLE_POST_LIST_COVER: true, // 列表显示文章封面
|
||||||
|
|
||||||
|
EXAMPLE_TITLE_IMAGE: false, // 标题栏,是否背景图片
|
||||||
|
|
||||||
|
// 文章页面布局
|
||||||
|
EXAMPLE_ARTICLE_LAYOUT_VERTICAL: false, // 文章详情,左右布局改为上下布局
|
||||||
|
EXAMPLE_ARTICLE_HIDDEN_NOTIFICATION: false // 文章详情隐藏公告
|
||||||
}
|
}
|
||||||
export default CONFIG
|
export default CONFIG
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import Comment from '@/components/Comment'
|
import Comment from '@/components/Comment'
|
||||||
import replaceSearchResult from '@/components/Mark'
|
import replaceSearchResult from '@/components/Mark'
|
||||||
import NotionIcon from '@/components/NotionIcon'
|
|
||||||
import NotionPage from '@/components/NotionPage'
|
import NotionPage from '@/components/NotionPage'
|
||||||
import ShareBar from '@/components/ShareBar'
|
import ShareBar from '@/components/ShareBar'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
@@ -21,6 +20,7 @@ import { PostLock } from './components/PostLock'
|
|||||||
import { PostMeta } from './components/PostMeta'
|
import { PostMeta } from './components/PostMeta'
|
||||||
import SearchInput from './components/SearchInput'
|
import SearchInput from './components/SearchInput'
|
||||||
import { SideBar } from './components/SideBar'
|
import { SideBar } from './components/SideBar'
|
||||||
|
import TitleBar from './components/TitleBar'
|
||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
import { Style } from './style'
|
import { Style } from './style'
|
||||||
|
|
||||||
@@ -32,36 +32,15 @@ import { Style } from './style'
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const LayoutBase = props => {
|
const LayoutBase = props => {
|
||||||
const { children } = props
|
const { children, post } = props
|
||||||
const { onLoading, fullWidth, locale } = useGlobal()
|
const { onLoading, fullWidth, locale } = useGlobal()
|
||||||
const router = useRouter()
|
|
||||||
const { post, category, tag } = props
|
|
||||||
|
|
||||||
const title = post?.title || siteConfig('TITLE')
|
// 文章详情页左右布局改为上下布局
|
||||||
const description = post?.description || siteConfig('AUTHOR')
|
const LAYOUT_VERTICAL =
|
||||||
|
post && siteConfig('EXAMPLE_ARTICLE_LAYOUT_VERTICAL', false, CONFIG)
|
||||||
|
|
||||||
// 顶部如果是按照分类或标签查看文章列表,列表顶部嵌入一个横幅
|
// 网站左右布局颠倒
|
||||||
// 如果是搜索,则列表顶部嵌入 搜索框
|
const LAYOUT_SIDEBAR_REVERSE = siteConfig('LAYOUT_SIDEBAR_REVERSE', false)
|
||||||
let slotTop = null
|
|
||||||
if (category) {
|
|
||||||
slotTop = (
|
|
||||||
<div className='pb-12'>
|
|
||||||
<i className='mr-1 fas fa-folder-open' />
|
|
||||||
{category}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
} else if (tag) {
|
|
||||||
slotTop = <div className='pb-12'>#{tag}</div>
|
|
||||||
} else if (props.slotTop) {
|
|
||||||
slotTop = props.slotTop
|
|
||||||
} else if (router.route === '/search') {
|
|
||||||
// 嵌入一个搜索框在顶部
|
|
||||||
slotTop = (
|
|
||||||
<div className='pb-12'>
|
|
||||||
<SearchInput {...props} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -71,33 +50,20 @@ const LayoutBase = props => {
|
|||||||
|
|
||||||
{/* 页头 */}
|
{/* 页头 */}
|
||||||
<Header {...props} />
|
<Header {...props} />
|
||||||
|
{/* 标题栏 */}
|
||||||
|
<TitleBar {...props} />
|
||||||
|
|
||||||
{/* 主体 */}
|
{/* 主体 */}
|
||||||
<div id='container-inner' className='w-full relative z-10'>
|
<div id='container-inner' className='w-full relative z-10'>
|
||||||
{/* 标题栏 */}
|
|
||||||
{!fullWidth && (
|
|
||||||
<div className='text-center px-6 py-12 mb-6 bg-gray-100 dark:bg-hexo-black-gray dark:border-hexo-black-gray border-b'>
|
|
||||||
<h1 className='text-xl md:text-4xl pb-4'>
|
|
||||||
{siteConfig('POST_TITLE_ICON') && (
|
|
||||||
<NotionIcon icon={post?.pageIcon} />
|
|
||||||
)}
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
<p className='leading-loose text-gray-dark'>{description}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id='container-wrapper'
|
id='container-wrapper'
|
||||||
className={
|
className={`relative mx-auto justify-center md:flex py-8 px-2
|
||||||
(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE'))
|
${LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : ''}
|
||||||
? 'flex-row-reverse'
|
${LAYOUT_VERTICAL ? 'items-center flex-col' : 'items-start'}
|
||||||
: '') +
|
`}>
|
||||||
'relative container mx-auto justify-center md:flex items-start py-8 px-2'
|
|
||||||
}>
|
|
||||||
{/* 内容 */}
|
{/* 内容 */}
|
||||||
<div
|
<div
|
||||||
className={`w-full ${fullWidth ? '' : 'max-w-3xl'} xl:px-14 lg:px-4`}>
|
className={`${fullWidth ? '' : LAYOUT_VERTICAL ? 'max-w-5xl' : 'max-w-3xl'} w-full xl:px-14 lg:px-4`}>
|
||||||
<Transition
|
<Transition
|
||||||
show={!onLoading}
|
show={!onLoading}
|
||||||
appear={true}
|
appear={true}
|
||||||
@@ -109,13 +75,22 @@ const LayoutBase = props => {
|
|||||||
leaveTo='opacity-0 -translate-y-16'
|
leaveTo='opacity-0 -translate-y-16'
|
||||||
unmount={false}>
|
unmount={false}>
|
||||||
{/* 嵌入模块 */}
|
{/* 嵌入模块 */}
|
||||||
{slotTop}
|
{props.slotTop}
|
||||||
{children}
|
{children}
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 侧边栏 */}
|
{/* 侧边栏 */}
|
||||||
{!fullWidth && <SideBar {...props} />}
|
{!fullWidth && (
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
LAYOUT_VERTICAL
|
||||||
|
? 'flex space-x-0 md:space-x-2 md:flex-row flex-col w-full max-w-5xl justify-center xl:px-14 lg:px-4'
|
||||||
|
: 'md:w-64 sticky top-8'
|
||||||
|
}`}>
|
||||||
|
<SideBar {...props} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -150,8 +125,20 @@ const LayoutIndex = props => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const LayoutPostList = props => {
|
const LayoutPostList = props => {
|
||||||
|
const { category, tag } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* 显示分类 */}
|
||||||
|
{category && (
|
||||||
|
<div className='pb-12'>
|
||||||
|
<i className='mr-1 fas fa-folder-open' />
|
||||||
|
{category}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{/* 显示标签 */}
|
||||||
|
{tag && <div className='pb-12'>#{tag}</div>}
|
||||||
|
|
||||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||||
<BlogListPage {...props} />
|
<BlogListPage {...props} />
|
||||||
) : (
|
) : (
|
||||||
@@ -192,7 +179,7 @@ const LayoutSlug = props => {
|
|||||||
{lock ? (
|
{lock ? (
|
||||||
<PostLock validPassword={validPassword} />
|
<PostLock validPassword={validPassword} />
|
||||||
) : (
|
) : (
|
||||||
<div id='article-wrapper' className='px-2'>
|
<div id='article-wrapper'>
|
||||||
<PostMeta post={post} />
|
<PostMeta post={post} />
|
||||||
<NotionPage post={post} />
|
<NotionPage post={post} />
|
||||||
<ShareBar post={post} />
|
<ShareBar post={post} />
|
||||||
@@ -237,7 +224,14 @@ const LayoutSearch = props => {
|
|||||||
}
|
}
|
||||||
}, [router])
|
}, [router])
|
||||||
|
|
||||||
return <LayoutPostList {...props} />
|
return (
|
||||||
|
<>
|
||||||
|
<div className='pb-12'>
|
||||||
|
<SearchInput {...props} />
|
||||||
|
</div>
|
||||||
|
<LayoutPostList {...props} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user