mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
Merge branch 'main' into pr/siuze/1817
This commit is contained in:
@@ -352,6 +352,9 @@ const BLOG = {
|
||||
SEO_BAIDU_SITE_VERIFICATION:
|
||||
process.env.NEXT_PUBLIC_SEO_BAIDU_SITE_VERIFICATION || '', // Remove the value or replace it with your own google site verification code
|
||||
|
||||
// 微软 Clarity 站点分析
|
||||
CLARITY_ID: process.env.NEXT_PUBLIC_CLARITY_ID || null , // 只需要复制Clarity脚本中的ID部分,ID是一个十位的英文数字组合
|
||||
|
||||
// <---- 站点统计
|
||||
|
||||
// START---->营收相关
|
||||
|
||||
@@ -2,14 +2,14 @@ import busuanzi from '@/lib/busuanzi'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
// import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
let path = ''
|
||||
|
||||
export default function Busuanzi () {
|
||||
const { theme } = useGlobal()
|
||||
const Router = useRouter()
|
||||
Router.events.on('routeChangeComplete', (url, option) => {
|
||||
const router = useRouter()
|
||||
router.events.on('routeChangeComplete', (url, option) => {
|
||||
if (url !== path) {
|
||||
path = url
|
||||
busuanzi.fetch()
|
||||
@@ -17,7 +17,7 @@ export default function Busuanzi () {
|
||||
})
|
||||
|
||||
// 更换主题时更新
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (theme) {
|
||||
busuanzi.fetch()
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ const ExternalPlugin = (props) => {
|
||||
const DIFY_CHATBOT_ENABLED = siteConfig('DIFY_CHATBOT_ENABLED')
|
||||
const TIANLI_KEY = siteConfig('TianliGPT_KEY')
|
||||
const GLOBAL_JS = siteConfig('GLOBAL_JS')
|
||||
const CLARITY_ID = siteConfig('CLARITY_ID')
|
||||
|
||||
// 自定义样式css和js引入
|
||||
if (isBrowser) {
|
||||
@@ -167,6 +168,18 @@ const ExternalPlugin = (props) => {
|
||||
}} />
|
||||
</>)}
|
||||
|
||||
{CLARITY_ID && (<>
|
||||
<script async dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function(c,l,a,r,i,t,y){
|
||||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
||||
})(window, document, "clarity", "script", "${CLARITY_ID}");
|
||||
`
|
||||
}} />
|
||||
</>)}
|
||||
|
||||
{COMMENT_DAO_VOICE_ID && (<>
|
||||
{/* DaoVoice 反馈 */}
|
||||
<script async dangerouslySetInnerHTML={{
|
||||
|
||||
@@ -33,7 +33,7 @@ const Tabs = ({ className, children }) => {
|
||||
{validChildren.map((item, index) => (
|
||||
<section
|
||||
key={index}
|
||||
className={`${currentTab === index ? 'opacity-100 static h-auto' : 'opacity-0 absolute h-0 pointer-events-none'}`}>
|
||||
className={`${currentTab === index ? 'opacity-100 static h-auto' : 'opacity-0 absolute h-0 pointer-events-none overflow-hidden'}`}>
|
||||
{item}
|
||||
</section>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
// import { loadExternalResource } from '@/lib/utils'
|
||||
import { useEffect } from 'react'
|
||||
import { loadExternalResource } from '@/lib/utils'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Giscus评论 @see https://giscus.app/zh-CN
|
||||
@@ -12,23 +12,46 @@ import { useEffect } from 'react'
|
||||
const Twikoo = ({ isDarkMode }) => {
|
||||
const envId = siteConfig('COMMENT_TWIKOO_ENV_ID')
|
||||
const el = siteConfig('COMMENT_TWIKOO_ELEMENT_ID', '#twikoo')
|
||||
|
||||
const twikooCDNURL = siteConfig('COMMENT_TWIKOO_CDN_URL')
|
||||
const lang = siteConfig('LANG')
|
||||
useEffect(() => {
|
||||
const twikoo = window?.twikoo
|
||||
if (typeof twikoo !== 'undefined' && twikoo && typeof twikoo.init === 'function') {
|
||||
twikoo.init({
|
||||
envId: envId, // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
|
||||
el: el, // 容器元素
|
||||
lang: lang // 用于手动设定评论区语言,支持的语言列表 https://github.com/imaegoo/twikoo/blob/main/src/client/utils/i18n/index.js
|
||||
// region: 'ap-guangzhou', // 环境地域,默认为 ap-shanghai,腾讯云环境填 ap-shanghai 或 ap-guangzhou;Vercel 环境不填
|
||||
// path: location.pathname, // 用于区分不同文章的自定义 js 路径,如果您的文章路径不是 location.pathname,需传此参数
|
||||
})
|
||||
const [isInit] = useState(useRef(false))
|
||||
|
||||
const loadTwikoo = async () => {
|
||||
try {
|
||||
await loadExternalResource(twikooCDNURL, 'js')
|
||||
const twikoo = window?.twikoo
|
||||
if (
|
||||
typeof twikoo !== 'undefined' &&
|
||||
twikoo &&
|
||||
typeof twikoo.init === 'function'
|
||||
) {
|
||||
twikoo.init({
|
||||
envId: envId, // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
|
||||
el: el, // 容器元素
|
||||
lang: lang // 用于手动设定评论区语言,支持的语言列表 https://github.com/imaegoo/twikoo/blob/main/src/client/utils/i18n/index.js
|
||||
// region: 'ap-guangzhou', // 环境地域,默认为 ap-shanghai,腾讯云环境填 ap-shanghai 或 ap-guangzhou;Vercel 环境不填
|
||||
// path: location.pathname, // 用于区分不同文章的自定义 js 路径,如果您的文章路径不是 location.pathname,需传此参数
|
||||
})
|
||||
console.log('twikoo init', twikoo)
|
||||
isInit.current = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('twikoo 加载失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (isInit.current) {
|
||||
console.log('twioo init! clear interval')
|
||||
clearInterval(interval)
|
||||
} else {
|
||||
loadTwikoo()
|
||||
}
|
||||
}, 1000)
|
||||
return () => clearInterval(interval)
|
||||
}, [isDarkMode])
|
||||
return (
|
||||
<div id="twikoo"></div>
|
||||
)
|
||||
return <div id="twikoo"></div>
|
||||
}
|
||||
|
||||
export default Twikoo
|
||||
|
||||
33
hooks/useAdjustStyle.js
Normal file
33
hooks/useAdjustStyle.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { isBrowser } from '@/lib/utils';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const useAdjustStyle = () => {
|
||||
/**
|
||||
* 避免 callout 含有图片时溢出撑开父容器
|
||||
*/
|
||||
const adjustCalloutImg = () => {
|
||||
const callOuts = document.querySelectorAll('.notion-callout-text');
|
||||
callOuts.forEach((callout) => {
|
||||
const images = callout.querySelectorAll('figure.notion-asset-wrapper.notion-asset-wrapper-image > div');
|
||||
const calloutWidth = callout.offsetWidth;
|
||||
images.forEach((container) => {
|
||||
const imageWidth = container.offsetWidth;
|
||||
if (imageWidth + 50 > calloutWidth) {
|
||||
container.style.setProperty('width', '100%');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
adjustCalloutImg();
|
||||
window.addEventListener('resize', adjustCalloutImg);
|
||||
return () => {
|
||||
window.removeEventListener('resize', adjustCalloutImg);
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
export default useAdjustStyle;
|
||||
@@ -9,17 +9,41 @@ import '@/styles/notion.css' // 重写部分样式
|
||||
import 'aos/dist/aos.css' // You can also use <link> for styles
|
||||
|
||||
import { GlobalContextProvider } from '@/lib/global'
|
||||
import { getGlobalLayoutByTheme } from '@/themes/theme'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { getQueryParam } from '../lib/utils'
|
||||
import useAdjustStyle from '@/hooks/useAdjustStyle'
|
||||
|
||||
// 各种扩展插件 这个要阻塞引入
|
||||
import ExternalPlugins from '@/components/ExternalPlugins'
|
||||
import { THEME } from '@/blog.config'
|
||||
|
||||
const MyApp = ({ Component, pageProps }) => {
|
||||
// 一些可能出现 bug 的样式,可以统一放入该钩子进行调整
|
||||
useAdjustStyle();
|
||||
|
||||
const route = useRouter()
|
||||
const queryParam = useMemo(() => {
|
||||
return getQueryParam(route.asPath, 'theme') || THEME
|
||||
}, [route])
|
||||
|
||||
const GLayout = useCallback(
|
||||
props => {
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getGlobalLayoutByTheme(queryParam)
|
||||
return <Layout {...props} />
|
||||
},
|
||||
[queryParam]
|
||||
)
|
||||
|
||||
return (
|
||||
<GlobalContextProvider {...pageProps}>
|
||||
<Component {...pageProps} />
|
||||
{/* 全局插件 , 自定义样式、组件等在这里统一引入 */}
|
||||
<ExternalPlugins {...pageProps} />
|
||||
</GlobalContextProvider>
|
||||
<GlobalContextProvider {...pageProps}>
|
||||
<GLayout {...pageProps}>
|
||||
<Component {...pageProps} />
|
||||
</GLayout>
|
||||
<ExternalPlugins {...pageProps} />
|
||||
</GlobalContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ class MyDocument extends Document {
|
||||
</>}
|
||||
|
||||
{BLOG.FONT_URL?.map((fontUrl, index) => {
|
||||
console.log(fontUrl)
|
||||
if (fontUrl.endsWith('.css')) {
|
||||
return <link key={index} rel="stylesheet" href={fontUrl} />
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@ const BlogPostCard = ({ post }) => {
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{siteConfig('AUTHOR')}</a> on {post.date?.start_date || post.createdTime}
|
||||
<TwikooCommentCount post={post} className='pl-1'/>
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href={`/category${post.category}`} className="text-gray-700 dark:text-gray-300 hover:underline">{post.category}</a>
|
||||
<Link href={`/category/${post.category}`} className="text-gray-700 dark:text-gray-300 hover:underline">{post.category}</Link>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
@@ -36,8 +36,23 @@ import { siteConfig } from '@/lib/config'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, slotTop, meta } = props
|
||||
const { children, meta } = props
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
const router = useRouter()
|
||||
const { category, tag } = props
|
||||
// 顶部如果是按照分类或标签查看文章列表,列表顶部嵌入一个横幅
|
||||
// 如果是搜索,则列表顶部嵌入 搜索框
|
||||
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>
|
||||
}
|
||||
|
||||
// 增加一个状态以触发 Transition 组件的动画
|
||||
// const [showTransition, setShowTransition] = useState(true)
|
||||
@@ -121,21 +136,11 @@ const LayoutIndex = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
const { category, tag } = props
|
||||
// 顶部如果是按照分类或标签查看文章列表,列表顶部嵌入一个横幅
|
||||
// 如果是搜索,则列表顶部嵌入 搜索框
|
||||
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
|
||||
}
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} slotTop={slotTop}>
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,7 +152,7 @@ const LayoutPostList = props => {
|
||||
const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
{lock
|
||||
? <ArticleLock validPassword={validPassword} />
|
||||
: <div id="article-wrapper" className="px-2">
|
||||
@@ -156,7 +161,7 @@ const LayoutSlug = props => {
|
||||
<ShareBar post={post} />
|
||||
<Comment frontMatter={post} />
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -166,7 +171,7 @@ const LayoutSlug = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <LayoutBase {...props}>404 Not found.</LayoutBase>
|
||||
return <>404 Not found.</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,8 +181,6 @@ const Layout404 = (props) => {
|
||||
*/
|
||||
const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
// 嵌入一个搜索框在顶部
|
||||
const slotTop = <div className='pb-12'><SearchInput {...props} /></div>
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
@@ -196,7 +199,7 @@ const LayoutSearch = props => {
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return <LayoutPostList slotTop={slotTop} {...props} />
|
||||
return <LayoutPostList {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,15 +209,13 @@ const LayoutSearch = props => {
|
||||
*/
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
return (<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogListGroupByDate key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
</>)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,11 +226,11 @@ const LayoutArchive = props => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => <CategoryItem key={category.name} category={category} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -241,16 +242,17 @@ const LayoutCategoryIndex = props => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => <TagItem key={tag.name} tag={tag} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
|
||||
@@ -126,12 +126,10 @@ const LayoutIndex = (props) => {
|
||||
* @param {*} props
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
|
||||
return <>
|
||||
<div className='w-full p-2'><WWAds className='w-full' orientation='horizontal'/></div>
|
||||
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,9 +140,9 @@ const LayoutPostList = (props) => {
|
||||
const LayoutSlug = (props) => {
|
||||
const { lock, validPassword } = props
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
{lock ? <ArticleLock validPassword={validPassword} /> : <ArticleDetail {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -174,7 +172,7 @@ const LayoutSearch = props => {
|
||||
*/
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-gray-800 shadow-md min-h-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogArchiveItem
|
||||
@@ -184,7 +182,7 @@ const LayoutArchive = (props) => {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +191,7 @@ const LayoutArchive = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <LayoutBase {...props}>404</LayoutBase>
|
||||
return <>404</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +203,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { categoryOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
@@ -227,7 +225,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -239,7 +237,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { tagOptions } = props
|
||||
return <LayoutBase {...props} >
|
||||
return <>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
|
||||
<div className='dark:text-gray-200 mb-5'><i className='mr-4 fas fa-tag' />{locale.COMMON.TAGS}:</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
@@ -252,11 +250,12 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -17,7 +17,7 @@ const Footer = ({ siteInfo }) => {
|
||||
© {`${copyrightDate}`}
|
||||
</div>
|
||||
|
||||
<div className='text-xs font-serif'>Powered By <a href='https://github.com/tangly1024/NotionNext' className='underline text-gray-500 dark:text-gray-300'>NotionNext</a></div>
|
||||
<div className='text-xs font-serif'>Powered By <a href='https://github.com/tangly1024/NotionNext' className='underline text-gray-500 dark:text-gray-300'>NotionNext {siteConfig('VERSION')}</a></div>
|
||||
|
||||
{siteConfig('BEI_AN') && <><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{siteConfig('BEI_AN')}</a><br /></>}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ const LayoutIndex = (props) => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <LayoutBase {...props} />
|
||||
return <></>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,9 +203,7 @@ const LayoutIndex = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <LayoutBase {...props} >
|
||||
<div className='mt-10'><BlogPostListPage {...props} /></div>
|
||||
</LayoutBase>
|
||||
return <></>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,7 +215,7 @@ const LayoutSlug = (props) => {
|
||||
const { post, prev, next, lock, validPassword } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
{/* 文章锁 */}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -250,7 +248,7 @@ const LayoutSlug = (props) => {
|
||||
|
||||
<TocDrawer {...props} />
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -261,7 +259,7 @@ const LayoutSlug = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSearch = (props) => {
|
||||
return <LayoutBase {...props}></LayoutBase>
|
||||
return <></>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,20 +271,20 @@ const LayoutSearch = (props) => {
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className="mb-10 pb-20 md:py-12 py-3 min-h-full">
|
||||
{Object.keys(archivePosts)?.map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
* 404
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='w-full h-96 py-80 flex justify-center items-center'>404 Not found.</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +293,7 @@ const Layout404 = props => {
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
@@ -317,7 +315,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +325,7 @@ const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className="bg-white dark:bg-gray-700 py-10">
|
||||
<div className="dark:text-gray-200 mb-5">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
@@ -343,11 +341,12 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -50,15 +50,38 @@ import { siteConfig } from '@/lib/config'
|
||||
const LayoutBase = props => {
|
||||
const {
|
||||
children,
|
||||
headerSlot,
|
||||
slotTop,
|
||||
slotRight,
|
||||
className,
|
||||
meta
|
||||
} = props
|
||||
|
||||
// 全屏模式下的最大宽度
|
||||
const { fullWidth } = useGlobal()
|
||||
const router = useRouter()
|
||||
console.log(router)
|
||||
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
{/* 通知横幅 */}
|
||||
{router.route==='/' ? <>
|
||||
<NoticeBar />
|
||||
<Hero {...props} />
|
||||
</>
|
||||
: null}
|
||||
<div className="max-w-[86rem] mx-auto px-3">
|
||||
<WWAds className="w-full" orientation="horizontal" />
|
||||
</div>
|
||||
{fullWidth ? null : <PostHeader {...props} />}
|
||||
</header>
|
||||
)
|
||||
|
||||
// 右侧栏 用户信息+标签列表
|
||||
const slotRight = fullWidth ? null : <SideRight {...props} />
|
||||
|
||||
const maxWidth = fullWidth ? 'max-w-[96rem] mx-auto' : 'max-w-[86rem]' // 普通最大宽度是86rem和顶部菜单栏对齐,留空则与窗口对齐
|
||||
|
||||
const HEO_HERO_BODY_REVERSE = siteConfig('HEO_HERO_BODY_REVERSE', false, CONFIG)
|
||||
@@ -115,26 +138,7 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = props => {
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
{/* 通知横幅 */}
|
||||
<NoticeBar />
|
||||
<Hero {...props} />
|
||||
<div className="max-w-[86rem] mx-auto px-3">
|
||||
<WWAds className="w-full" orientation="horizontal" />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
// 右侧栏 用户信息+标签列表
|
||||
const slotRight = <SideRight {...props} />
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
|
||||
<div id="post-outer-wrapper" className="px-5 md:px-0">
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} />
|
||||
@@ -146,7 +150,6 @@ const LayoutIndex = props => {
|
||||
<BlogPostListScroll {...props} />
|
||||
)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -156,19 +159,8 @@ const LayoutIndex = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
// 右侧栏
|
||||
const slotRight = <SideRight {...props} />
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
|
||||
<div id="post-outer-wrapper" className="px-5 md:px-0">
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} />
|
||||
@@ -180,7 +172,6 @@ const LayoutPostList = props => {
|
||||
<BlogPostListScroll {...props} />
|
||||
)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -193,16 +184,7 @@ const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
const currentSearch = keyword || router?.query?.s
|
||||
const headerSlot = (
|
||||
<header className="post-bg">
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
<PostHeader {...props} />
|
||||
</header>
|
||||
)
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// 高亮搜索结果
|
||||
if (currentSearch) {
|
||||
@@ -219,10 +201,9 @@ const LayoutSearch = props => {
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<LayoutBase
|
||||
<div
|
||||
{...props}
|
||||
currentSearch={currentSearch}
|
||||
headerSlot={headerSlot}
|
||||
>
|
||||
<div id="post-outer-wrapper" className="px-5 md:px-0">
|
||||
{!currentSearch
|
||||
@@ -241,7 +222,7 @@ const LayoutSearch = props => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -253,21 +234,9 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
|
||||
// 右侧栏
|
||||
const slotRight = <SideRight {...props} />
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
// 归档页顶部显示条,如果是默认归档则不显示。分类详情页显示分类列表,标签详情页显示当前标签
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
|
||||
<div className="p-5 rounded-xl border dark:border-gray-600 max-w-6xl w-full bg-white dark:bg-[#1e1e1e]">
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} border={false} />
|
||||
@@ -282,7 +251,6 @@ const LayoutArchive = props => {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -302,34 +270,16 @@ const LayoutSlug = props => {
|
||||
setHasCode(hasCode)
|
||||
}, [])
|
||||
|
||||
// 右侧栏
|
||||
const slotRight = fullWidth ? null : <SideRight {...props} />
|
||||
const headerSlot = (
|
||||
<header
|
||||
data-aos="fade-up"
|
||||
data-aos-duration="300"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="post-bg"
|
||||
>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
{fullWidth ? null : <PostHeader {...props} />}
|
||||
</header>
|
||||
)
|
||||
|
||||
const commentEnable = siteConfig('COMMENT_TWIKOO_ENV_ID') || siteConfig('COMMENT_WALINE_SERVER_URL') || siteConfig('COMMENT_VALINE_APP_ID') ||
|
||||
siteConfig('COMMENT_GISCUS_REPO') || siteConfig('COMMENT_CUSDIS_APP_ID') || siteConfig('COMMENT_UTTERRANCES_REPO') ||
|
||||
siteConfig('COMMENT_GITALK_CLIENT_ID') || siteConfig('COMMENT_WEBMENTION_ENABLE')
|
||||
|
||||
return (
|
||||
<LayoutBase
|
||||
<div
|
||||
{...props}
|
||||
headerSlot={headerSlot}
|
||||
showCategory={false}
|
||||
showTag={false}
|
||||
slotRight={slotRight}
|
||||
>
|
||||
<div className={`w-full ${fullWidth ? '' : 'xl:max-w-5xl'} ${hasCode ? 'xl:w-[73.15vw]' : ''} lg:hover:shadow lg:border rounded-2xl lg:px-2 lg:py-4 bg-white dark:bg-[#18171d] dark:border-gray-600 article`}>
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
@@ -390,7 +340,7 @@ const LayoutSlug = props => {
|
||||
)}
|
||||
</div>
|
||||
<FloatTocButton {...props} />
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -477,18 +427,10 @@ const Layout404 = props => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} className="mt-8" headerSlot={headerSlot}>
|
||||
<div id="category-outer-wrapper" className="px-5 md:px-0">
|
||||
<div id="category-outer-wrapper" className="mt-8 px-5 md:px-0">
|
||||
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
|
||||
{locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
@@ -520,7 +462,6 @@ const LayoutCategoryIndex = props => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -532,17 +473,9 @@ const LayoutCategoryIndex = props => {
|
||||
const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
const headerSlot = (
|
||||
<header>
|
||||
{/* 顶部导航 */}
|
||||
<div id="nav-bar-wrapper" className="h-16">
|
||||
<NavBar {...props} />
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} className="mt-8" headerSlot={headerSlot}>
|
||||
<div id="tag-outer-wrapper" className="px-5 md:px-0">
|
||||
<div id="tag-outer-wrapper" className="px-5 mt-8 md:px-0">
|
||||
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
|
||||
{locale.COMMON.TAGS}
|
||||
</div>
|
||||
@@ -574,12 +507,12 @@ const LayoutTagIndex = props => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -46,9 +46,25 @@ export const useHexoGlobal = () => useContext(ThemeGlobalHexo)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, headerSlot, floatSlot, slotTop, meta, className } = props
|
||||
const { post , children, slotTop, meta, className } = props
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
|
||||
const router = useRouter()
|
||||
const headerSlot = post
|
||||
? <PostHeader {...props} /> : (router.route==='/' && siteConfig('HEXO_HOME_BANNER_ENABLE', null, CONFIG)
|
||||
? <Hero {...props} /> : null)
|
||||
|
||||
const floatSlot = <>
|
||||
{post?.toc?.length > 1 && <div className="block lg:hidden">
|
||||
<TocDrawerButton
|
||||
onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}}
|
||||
/>
|
||||
</div>}
|
||||
<JumpToCommentButton />
|
||||
</>
|
||||
|
||||
// Algolia搜索框
|
||||
const searchModal = useRef(null)
|
||||
|
||||
@@ -125,8 +141,7 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const headerSlot = siteConfig('HEXO_HOME_BANNER_ENABLE', null, CONFIG) && <Hero {...props} />
|
||||
return <LayoutPostList {...props} headerSlot={headerSlot} className='pt-8' />
|
||||
return <LayoutPostList {...props} className='pt-8' />
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,10 +150,10 @@ const LayoutIndex = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <LayoutBase {...props} className='pt-8'>
|
||||
return <div className='pt-8'>
|
||||
<SlotBar {...props} />
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</div>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +180,11 @@ const LayoutSearch = props => {
|
||||
})
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch} className='pt-8'>
|
||||
<div className='pt-8'>
|
||||
{!currentSearch
|
||||
? <SearchNav {...props} />
|
||||
: <div id="posts-wrapper"> {siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />} </div>}
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -180,7 +195,7 @@ const LayoutSearch = props => {
|
||||
*/
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
return <LayoutBase {...props} className='pt-8'>
|
||||
return <div className='pt-8'>
|
||||
<Card className='w-full'>
|
||||
<div className="mb-10 pb-20 bg-white md:p-12 p-3 min-h-full dark:bg-hexo-black-gray">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
@@ -192,7 +207,7 @@ const LayoutArchive = (props) => {
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,22 +218,10 @@ const LayoutArchive = (props) => {
|
||||
const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
const drawerRight = useRef(null)
|
||||
|
||||
const targetRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||
|
||||
const floatSlot = <>
|
||||
{post?.toc?.length > 1 && <div className="block lg:hidden">
|
||||
<TocDrawerButton
|
||||
onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}}
|
||||
/>
|
||||
</div>}
|
||||
<JumpToCommentButton />
|
||||
</>
|
||||
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<PostHeader {...props} />} showCategory={false} showTag={false} floatSlot={floatSlot} >
|
||||
<>
|
||||
<div className="w-full lg:hover:shadow lg:border rounded-t-xl lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black article">
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -250,10 +253,10 @@ const LayoutSlug = props => {
|
||||
</div>
|
||||
|
||||
<div className='block lg:hidden'>
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={targetRef} />
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={tocRef} />
|
||||
</div>
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -278,7 +281,7 @@ const Layout404 = props => {
|
||||
}, 3000)
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="text-black w-full h-screen text-center justify-center content-center items-center flex flex-col">
|
||||
<div className="dark:text-gray-200">
|
||||
<h2 className="inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top">
|
||||
@@ -289,7 +292,7 @@ const Layout404 = props => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -302,7 +305,7 @@ const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase {...props} className='mt-8'>
|
||||
<div className='mt-8'>
|
||||
<Card className="w-full min-h-screen">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" /> {locale.COMMON.CATEGORY}:
|
||||
@@ -319,7 +322,7 @@ const LayoutCategoryIndex = props => {
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -332,7 +335,7 @@ const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase {...props} className='mt-8'>
|
||||
<div className='mt-8'>
|
||||
<Card className='w-full'>
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" /> {locale.COMMON.TAGS}:
|
||||
@@ -343,12 +346,13 @@ const LayoutTagIndex = props => {
|
||||
</div>)}
|
||||
</div>
|
||||
</Card>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -57,13 +57,13 @@ const LayoutBase = (props) => {
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<Hero />
|
||||
<Features />
|
||||
<FeaturesBlocks />
|
||||
<Testimonials />
|
||||
<Newsletter />
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -81,24 +81,24 @@ const LayoutSlug = (props) => {
|
||||
return <div id='theme-landing'><Loading /></div>
|
||||
}
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
|
||||
return <>
|
||||
<div id='container-inner' className='mx-auto max-w-screen-lg p-12'>
|
||||
<NotionPage {...props} />
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
// 其他布局暂时留空
|
||||
const LayoutSearch = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const LayoutArchive = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const Layout404 = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const LayoutCategoryIndex = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const LayoutPostList = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const LayoutTagIndex = (props) => <LayoutBase {...props}><Hero /></LayoutBase>
|
||||
const LayoutSearch = (props) => <><Hero /></>
|
||||
const LayoutArchive = (props) => <><Hero /></>
|
||||
const Layout404 = (props) => <><Hero /></>
|
||||
const LayoutCategoryIndex = (props) => <><Hero /></>
|
||||
const LayoutPostList = (props) => <><Hero /></>
|
||||
const LayoutTagIndex = (props) => <><Hero /></>
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -40,8 +40,14 @@ import { siteConfig } from '@/lib/config'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, headerSlot, meta, siteInfo, containerSlot, post } = props
|
||||
const { children, meta, siteInfo, post } = props
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
const router = useRouter()
|
||||
const containerSlot= router.route==='/' ? <Announcement {...props} /> : <BlogListBar {...props} />
|
||||
const headerSlot= siteConfig('MATERY_HOME_BANNER_ENABLE', null, CONFIG) && router.route==='/'
|
||||
? <Hero {...props} /> : (post && !fullWidth ? <PostHeader {...props} /> : null)
|
||||
|
||||
const floatRightBottom = post ? <JumpToCommentButton /> : null
|
||||
|
||||
return (
|
||||
<div id='theme-matery' className="min-h-screen flex flex-col justify-between bg-hexo-background-gray dark:bg-black w-full">
|
||||
@@ -58,7 +64,7 @@ const LayoutBase = props => {
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 -translate-y-16"
|
||||
enterTo="opacity-100"
|
||||
enterTo="opacity-100 w-full"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-16"
|
||||
@@ -79,7 +85,7 @@ const LayoutBase = props => {
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100"
|
||||
enterTo="opacity-100 w-full"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
@@ -98,7 +104,7 @@ const LayoutBase = props => {
|
||||
</div>
|
||||
|
||||
{/* 右下角悬浮 */}
|
||||
<RightFloatButtons {...props} />
|
||||
<RightFloatButtons {...props} floatRightBottom={floatRightBottom}/>
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
@@ -113,7 +119,7 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
return <LayoutPostList {...props} containerSlot={<Announcement {...props} />} headerSlot={siteConfig('MATERY_HOME_BANNER_ENABLE', null, CONFIG) && <Hero {...props} />} />
|
||||
return <LayoutPostList {...props}/>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,9 +129,9 @@ const LayoutIndex = (props) => {
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return (
|
||||
<LayoutBase {...props} containerSlot={<BlogListBar {...props} />}>
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -152,13 +158,13 @@ const LayoutSearch = props => {
|
||||
}
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
<>
|
||||
{!currentSearch
|
||||
? <SearchNave {...props} />
|
||||
: <div id="posts-wrapper">
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -169,7 +175,7 @@ const LayoutSearch = props => {
|
||||
*/
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
return <LayoutBase {...props} headerSlot={<PostHeader {...props} />} >
|
||||
return <>
|
||||
<Card className='w-full -mt-32'>
|
||||
<div className="mb-10 pb-20 bg-white md:p-12 p-3 min-h-full dark:bg-hexo-black-gray">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
@@ -181,7 +187,7 @@ const LayoutArchive = (props) => {
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,9 +198,8 @@ const LayoutArchive = (props) => {
|
||||
const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
const { fullWidth } = useGlobal()
|
||||
const headerSlot = fullWidth ? null : <PostHeader {...props} />
|
||||
|
||||
return (<LayoutBase {...props} headerSlot={headerSlot} showCategory={false} showTag={false} floatRightBottom={<JumpToCommentButton />}>
|
||||
|
||||
return (<>
|
||||
|
||||
<div id='inner-wrapper' className={`w-full ${fullWidth ? '' : 'lg:max-w-3xl 2xl:max-w-4xl'}`} >
|
||||
|
||||
@@ -257,7 +262,7 @@ const LayoutSlug = props => {
|
||||
|
||||
</div>
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -280,7 +285,7 @@ const Layout404 = props => {
|
||||
}, 3000)
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="text-black w-full h-screen text-center justify-center content-center items-center flex flex-col">
|
||||
<div className="dark:text-gray-200">
|
||||
<h2 className="inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top">
|
||||
@@ -291,7 +296,7 @@ const Layout404 = props => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -304,7 +309,7 @@ const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<PostHeader {...props} />} >
|
||||
<>
|
||||
|
||||
<div id='inner-wrapper' className='w-full'>
|
||||
<div className="drop-shadow-xl -mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black dark:text-gray-300">
|
||||
@@ -321,7 +326,7 @@ const LayoutCategoryIndex = props => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -334,7 +339,7 @@ const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<PostHeader {...props} />} >
|
||||
<>
|
||||
<div id='inner-wrapper' className='w-full drop-shadow-xl'>
|
||||
|
||||
<div className="-mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
@@ -354,12 +359,13 @@ const LayoutTagIndex = props => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
|
||||
@@ -47,12 +47,14 @@ export const useMediumGlobal = () => useContext(ThemeGlobalMedium)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, showInfoCard = true, slotRight, slotTop, notice, meta } = props
|
||||
const { children, showInfoCard = true, slotRight, notice, meta } = props
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [tocVisible, changeTocVisible] = useState(false)
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
|
||||
const slotTop = <BlogPostBar {...props} />
|
||||
|
||||
return (
|
||||
<ThemeGlobalMedium.Provider value={{ tocVisible, changeTocVisible }}>
|
||||
{/* SEO相关 */}
|
||||
@@ -137,10 +139,9 @@ const LayoutIndex = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
const slotTop = <BlogPostBar {...props} />
|
||||
return <LayoutBase {...props} slotTop={slotTop}>
|
||||
return <>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +159,7 @@ const LayoutSlug = props => {
|
||||
)
|
||||
|
||||
return (
|
||||
<LayoutBase showInfoCard={true} slotRight={slotRight} {...props} >
|
||||
<div showInfoCard={true} slotRight={slotRight} {...props} >
|
||||
{/* 文章锁 */}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -192,7 +193,7 @@ const LayoutSlug = props => {
|
||||
{/* 移动端目录 */}
|
||||
<TocDrawer {...props} />
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -220,7 +221,7 @@ const LayoutSearch = (props) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
|
||||
{/* 搜索导航栏 */}
|
||||
<div className='py-12'>
|
||||
@@ -236,7 +237,7 @@ const LayoutSearch = (props) => {
|
||||
{currentSearch && <div>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,12 +248,12 @@ const LayoutSearch = (props) => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 py-3 min-h-full">
|
||||
{Object.keys(archivePosts)?.map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />
|
||||
)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -262,9 +263,9 @@ const LayoutArchive = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='w-full h-96 py-80 flex justify-center items-center'>404 Not found.</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,7 +277,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
@@ -298,7 +299,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -311,7 +312,7 @@ const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="bg-white dark:bg-gray-700 py-10">
|
||||
<div className="dark:text-gray-200 mb-5">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
@@ -327,12 +328,13 @@ const LayoutTagIndex = props => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
|
||||
@@ -50,9 +50,9 @@ export const MenuItem = ({ link }) => {
|
||||
{
|
||||
link?.subMenus?.map((sLink, index) => (
|
||||
<div key={index} className='nav-submenu'>
|
||||
<a href={sLink?.to}>
|
||||
<Link href={sLink?.to}>
|
||||
<span className='dark:text-neutral-400 text-gray-500 hover:text-black dark:hover:text-white text-xs font-bold'><i className={`text-xs mr-1 ${sLink?.icon ? sLink?.icon : 'fas fa-hashtag'}`} />{sLink.title}</span>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -172,10 +172,10 @@ const LayoutPostListIndex = props => {
|
||||
// const { customMenu, children, post, allNavPages, categoryOptions, slotLeft, slotRight, slotTop, meta } = props
|
||||
// const [filteredNavPages, setFilteredNavPages] = useState(allNavPages)
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
<Announcement {...props} />
|
||||
<BlogPostListAll { ...props } />
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ const LayoutPostList = props => {
|
||||
// 顶部如果是按照分类或标签查看文章列表,列表顶部嵌入一个横幅
|
||||
// 如果是搜索,则列表顶部嵌入 搜索框
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
<div className='w-full max-w-7xl mx-auto justify-center mt-8'>
|
||||
<div id='posts-wrapper' class='card-list grid gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5'>
|
||||
{posts?.map(post => (
|
||||
@@ -197,7 +197,7 @@ const LayoutPostList = props => {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ const LayoutSlug = (props) => {
|
||||
const { post, lock, validPassword } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
{/* 文章锁 */}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -244,7 +244,7 @@ const LayoutSlug = (props) => {
|
||||
|
||||
<TocDrawer {...props} />
|
||||
</div>}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ const LayoutSlug = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSearch = (props) => {
|
||||
return <LayoutBase {...props}></LayoutBase>
|
||||
return <></>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,20 +267,20 @@ const LayoutSearch = (props) => {
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className="mb-10 pb-20 md:py-12 py-3 min-h-full">
|
||||
{Object.keys(archivePosts)?.map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
* 404
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='w-full h-96 py-80 flex justify-center items-center'>404 Not found.</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,7 +289,7 @@ const Layout404 = props => {
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
@@ -311,7 +311,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +321,7 @@ const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className="bg-white dark:bg-gray-700 py-10">
|
||||
<div className="dark:text-gray-200 mb-5">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
@@ -337,11 +337,12 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -14,6 +14,7 @@ import NotionIcon from '@/components/NotionIcon'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import WWAds from '@/components/WWAds'
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -79,7 +80,9 @@ export default function ArticleDetail(props) {
|
||||
|
||||
{/* Notion内容主体 */}
|
||||
<article className='mx-auto'>
|
||||
<WWAds className="w-full" orientation="horizontal" />
|
||||
{post && (<NotionPage post={post} />)}
|
||||
<WWAds className="w-full" orientation="horizontal" />
|
||||
</article>
|
||||
|
||||
{showArticleInfo && <>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/**
|
||||
* 卡片组件
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const Card = (props) => {
|
||||
const { children, headerSlot } = props
|
||||
return <div {...props}>
|
||||
<>{headerSlot}</>
|
||||
<section className="shadow px-2 py-4 bg-white dark:bg-hexo-black-gray hover:shadow-xl duration-200">
|
||||
{children}
|
||||
</section>
|
||||
</div>
|
||||
const { children, headerSlot, className } = props
|
||||
return <div className={className}>
|
||||
<>{headerSlot}</>
|
||||
<section className="shadow px-2 py-4 bg-white dark:bg-hexo-black-gray hover:shadow-xl duration-200">
|
||||
{children}
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
export default Card
|
||||
|
||||
@@ -33,13 +33,12 @@ import { siteConfig } from '@/lib/config'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, headerSlot, floatSlot, rightAreaSlot, meta } = props
|
||||
const { children, headerSlot, rightAreaSlot, meta, post } = props
|
||||
const { onLoading } = useGlobal()
|
||||
const targetRef = useRef(null)
|
||||
const floatButtonGroup = useRef(null)
|
||||
const [showRightFloat, switchShow] = useState(false)
|
||||
const [percent, changePercent] = useState(0) // 页面阅读百分比
|
||||
|
||||
const scrollListener = () => {
|
||||
const targetRef = document.getElementById('wrapper')
|
||||
const clientHeight = targetRef?.clientHeight
|
||||
@@ -68,6 +67,15 @@ const LayoutBase = (props) => {
|
||||
return () => document.removeEventListener('scroll', scrollListener)
|
||||
}, [showRightFloat])
|
||||
|
||||
// 悬浮抽屉
|
||||
const drawerRight = useRef(null)
|
||||
const floatSlot = <div className='block lg:hidden'>
|
||||
<TocDrawerButton onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}} />
|
||||
</div>
|
||||
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||
|
||||
return (
|
||||
<div id='theme-next'>
|
||||
{/* SEO相关 */}
|
||||
@@ -106,8 +114,14 @@ const LayoutBase = (props) => {
|
||||
|
||||
{/* 右侧栏样式 */}
|
||||
{siteConfig('NEXT_RIGHT_BAR', null, CONFIG) && <SideAreaRight targetRef={targetRef} slot={rightAreaSlot} {...props} />}
|
||||
|
||||
</main>
|
||||
|
||||
{/* 悬浮目录按钮 */}
|
||||
{post && <div className='block lg:hidden'>
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={tocRef} />
|
||||
</div>}
|
||||
|
||||
{/* 右下角悬浮 */}
|
||||
<div ref={floatButtonGroup} className='right-8 bottom-12 lg:right-2 fixed justify-end z-20 font-sans'>
|
||||
<div className={(showRightFloat ? 'animate__animated ' : 'hidden') + ' animate__fadeInUp rounded-md glassmorphism justify-center duration-500 animate__faster flex space-x-2 items-center cursor-pointer '}>
|
||||
@@ -140,7 +154,7 @@ const LayoutIndex = (props) => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <LayoutBase {...props} >
|
||||
return <>
|
||||
|
||||
<BlogListBar {...props} />
|
||||
|
||||
@@ -148,7 +162,7 @@ const LayoutPostList = (props) => {
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +188,7 @@ const LayoutSearch = (props) => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<>
|
||||
<StickyBar>
|
||||
<div className="p-4 dark:text-gray-200">
|
||||
<i className="mr-1 fas fa-search" />{' '}
|
||||
@@ -187,7 +201,7 @@ const LayoutSearch = (props) => {
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -210,7 +224,7 @@ const Layout404 = props => {
|
||||
}, 3000)
|
||||
}, [])
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
|
||||
<div className='dark:text-gray-200'>
|
||||
<h2 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><i className='mr-2 fas fa-spinner animate-spin' />404</h2>
|
||||
@@ -219,7 +233,7 @@ const Layout404 = props => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +245,7 @@ const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-hexo-black-gray shadow-md min-h-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogPostArchive
|
||||
@@ -241,7 +255,7 @@ const LayoutArchive = (props) => {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -252,27 +266,14 @@ const LayoutArchive = (props) => {
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const { post, lock, validPassword } = props
|
||||
const drawerRight = useRef(null)
|
||||
const targetRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||
const floatSlot = <div className='block lg:hidden'>
|
||||
<TocDrawerButton onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}} />
|
||||
</div>
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} floatSlot={floatSlot}>
|
||||
<>
|
||||
|
||||
{post && !lock && <ArticleDetail {...props} />}
|
||||
|
||||
{post && lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{/* 悬浮目录按钮 */}
|
||||
{post && <div className='block lg:hidden'>
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={targetRef} />
|
||||
</div>}
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -285,7 +286,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const { allPosts, categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<LayoutBase totalPosts={allPosts} {...props}>
|
||||
<div totalPosts={allPosts} {...props}>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:
|
||||
@@ -307,7 +308,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -319,7 +320,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'><i className='fas fa-tags mr-4' />{locale.COMMON.TAGS}:</div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
@@ -328,11 +329,12 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
@@ -340,5 +342,5 @@ export {
|
||||
Layout404,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPostList,
|
||||
LayoutTagIndex
|
||||
LayoutTagIndex,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useNobeliumGlobal } from '..'
|
||||
import Tags from './Tags'
|
||||
|
||||
export default function BlogListBar(props) {
|
||||
const { tag, setFilterKey } = props
|
||||
const { tag, setFilterKey } = useNobeliumGlobal()
|
||||
const handleSearchChange = (val) => {
|
||||
setFilterKey(val)
|
||||
}
|
||||
|
||||
@@ -37,14 +37,16 @@ export const useNobeliumGlobal = () => useContext(ThemeGlobalNobelium)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, post, topSlot, meta } = props
|
||||
|
||||
const { children, post, meta } = props
|
||||
const fullWidth = post?.fullWidth ?? false
|
||||
const { onLoading } = useGlobal()
|
||||
const searchModal = useRef(null)
|
||||
// 在列表中进行实时过滤
|
||||
const [filterKey, setFilterKey] = useState('')
|
||||
const topSlot= <BlogListBar {...props}/>
|
||||
|
||||
return (
|
||||
<ThemeGlobalNobelium.Provider value={{ searchModal }}>
|
||||
<ThemeGlobalNobelium.Provider value={{ searchModal, filterKey, setFilterKey }}>
|
||||
<div id='theme-nobelium' className='nobelium relative dark:text-gray-300 w-full bg-white dark:bg-black min-h-screen flex flex-col'>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta} />
|
||||
@@ -114,10 +116,8 @@ const LayoutIndex = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
const { posts, topSlot } = props
|
||||
|
||||
// 在列表中进行实时过滤
|
||||
const [filterKey, setFilterKey] = useState('')
|
||||
const { posts, topSlot,tag } = props
|
||||
const { filterKey } = useNobeliumGlobal()
|
||||
let filteredBlogPosts = []
|
||||
if (filterKey && posts) {
|
||||
filteredBlogPosts = posts.filter(post => {
|
||||
@@ -130,10 +130,11 @@ const LayoutPostList = props => {
|
||||
}
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} topSlot={<BlogListBar {...props} setFilterKey={setFilterKey} />}>
|
||||
<>
|
||||
{topSlot}
|
||||
{tag && <SearchNavBar {...props} />}
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts} /> : <BlogListScroll {...props} posts={filteredBlogPosts} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ const LayoutSearch = props => {
|
||||
}, [])
|
||||
|
||||
// 在列表中进行实时过滤
|
||||
const [filterKey, setFilterKey] = useState('')
|
||||
const {filterKey} = useNobeliumGlobal()
|
||||
let filteredBlogPosts = []
|
||||
if (filterKey && posts) {
|
||||
filteredBlogPosts = posts.filter(post => {
|
||||
@@ -171,10 +172,10 @@ const LayoutSearch = props => {
|
||||
filteredBlogPosts = deepClone(posts)
|
||||
}
|
||||
|
||||
return <LayoutBase {...props} topSlot={<BlogListBar {...props} setFilterKey={setFilterKey} />}>
|
||||
return <>
|
||||
<SearchNavBar {...props} />
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts} /> : <BlogListScroll {...props} posts={filteredBlogPosts} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,11 +186,11 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -202,7 +203,7 @@ const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -216,7 +217,7 @@ const LayoutSlug = props => {
|
||||
</>
|
||||
</div>}
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -226,9 +227,9 @@ const LayoutSlug = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
404 Not found.
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +241,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const { categoryOptions } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
@@ -257,7 +258,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -269,7 +270,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
@@ -284,12 +285,13 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import Tags from './Tags'
|
||||
|
||||
export default function BlogListBar(props) {
|
||||
const { tag, setFilterKey } = props
|
||||
const handleSearchChange = (val) => {
|
||||
setFilterKey(val)
|
||||
}
|
||||
if (tag) {
|
||||
return (<div className="mb-4">
|
||||
<div className='relative'>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={
|
||||
tag ? `Search in #${tag}` : 'Search Articles'
|
||||
}
|
||||
className="outline-none block w-full border px-4 py-2 border-black bg-white text-black dark:bg-night dark:border-white dark:text-white"
|
||||
onChange={e => handleSearchChange(e.target.value)}
|
||||
/>
|
||||
<svg
|
||||
className="absolute right-3 top-3 h-5 w-5 text-black dark:text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<Tags {...props} />
|
||||
</div>)
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { ArrowPath, ChevronLeft, ChevronRight } from '@/components/HeroIcons'
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { compressImage } from '@/lib/notion/mapImage'
|
||||
|
||||
/**
|
||||
* 弹出框
|
||||
@@ -13,7 +14,7 @@ export default function Modal(props) {
|
||||
const { showModal, setShowModal, modalContent, setModalContent } = usePlogGlobal()
|
||||
const { siteInfo, posts } = props
|
||||
const cancelButtonRef = useRef(null)
|
||||
const img = modalContent?.pageCover || siteInfo?.pageCover
|
||||
const img = compressImage(modalContent?.pageCover || siteInfo?.pageCover, 1200, 85, 'webp')
|
||||
const imgRef = useRef(null)
|
||||
|
||||
// 添加loading状态
|
||||
|
||||
@@ -98,9 +98,9 @@ const LayoutIndex = props => {
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -137,11 +137,11 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -168,7 +168,7 @@ const LayoutSlug = props => {
|
||||
</>
|
||||
</div>}
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -178,9 +178,9 @@ const LayoutSlug = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
404 Not found.
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +192,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const { categoryOptions } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
@@ -209,7 +209,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ const LayoutCategoryIndex = (props) => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
@@ -236,12 +236,13 @@ const LayoutTagIndex = (props) => {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
|
||||
@@ -8,6 +8,7 @@ import Catalog from './Catalog'
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
let counter = 0;
|
||||
export default function SideBar (props) {
|
||||
const { notice } = props
|
||||
return (<>
|
||||
|
||||
@@ -120,9 +120,9 @@ const LayoutIndex = props => {
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -161,11 +161,11 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ const LayoutSlug = props => {
|
||||
const { fullWidth } = useGlobal()
|
||||
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -208,7 +208,7 @@ const LayoutSlug = props => {
|
||||
|
||||
</div>
|
||||
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -218,9 +218,9 @@ const LayoutSlug = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
return <>
|
||||
404 Not found.
|
||||
</LayoutBase>
|
||||
</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +231,7 @@ const Layout404 = (props) => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
@@ -248,7 +248,7 @@ const LayoutCategoryIndex = props => {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ const LayoutCategoryIndex = props => {
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
@@ -276,12 +276,13 @@ const LayoutTagIndex = (props) => {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
@@ -289,5 +290,5 @@ export {
|
||||
Layout404,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPostList,
|
||||
LayoutTagIndex
|
||||
LayoutTagIndex,
|
||||
}
|
||||
|
||||
@@ -6,6 +6,22 @@ import getConfig from 'next/config'
|
||||
import * as ThemeComponents from '@theme-components'
|
||||
// 所有主题在next.config.js中扫描
|
||||
export const { THEMES = [] } = getConfig().publicRuntimeConfig
|
||||
|
||||
/**
|
||||
* 加载全局布局
|
||||
* 如果是
|
||||
* @param {*} themeQuery
|
||||
* @returns
|
||||
*/
|
||||
export const getGlobalLayoutByTheme = (themeQuery) => {
|
||||
const layout = getLayoutNameByPath(-1)
|
||||
if (themeQuery !== BLOG.THEME) {
|
||||
return dynamic(() => import(`@/themes/${themeQuery}`).then(m => m[layout]), { ssr: true })
|
||||
} else {
|
||||
return ThemeComponents[layout]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载主题文件
|
||||
* 如果是
|
||||
@@ -54,6 +70,8 @@ const checkThemeDOM = () => {
|
||||
*/
|
||||
export const getLayoutNameByPath = (path) => {
|
||||
switch (path) {
|
||||
case -1:
|
||||
return 'LayoutBase'
|
||||
case '/':
|
||||
return 'LayoutIndex'
|
||||
case '/archive':
|
||||
|
||||
Reference in New Issue
Block a user