mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
Merge pull request #1371 from tangly1024/feat/heo-top-posts
Feat/heo top posts
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
|
||||
NEXT_PUBLIC_VERSION=4.0.6
|
||||
NEXT_PUBLIC_VERSION=4.0.7
|
||||
@@ -376,7 +376,7 @@ const BLOG = {
|
||||
// 开发相关
|
||||
NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public
|
||||
DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮
|
||||
ENABLE_CACHE: process.env.ENABLE_CACHE || false, // 开启缓存会将Notion数据缓存在内存中,通常在开发调试中使用,正式部署开启此功能意义不大。
|
||||
ENABLE_CACHE: process.env.ENABLE_CACHE || process.env.npm_lifecycle_event === 'build', // 缓存在开发调试和打包过程中选择性开启,正式部署开启此功能意义不大。
|
||||
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
|
||||
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ export default function AlgoliaSearchModal({ cRef }) {
|
||||
|
||||
<Pagination totalPage={totalPage} page={page} switchPage={switchPage}/>
|
||||
<div>{totalHit > 0 && <div>共搜索到 {totalHit} 条结果,用时 {useTime} 毫秒</div> }</div>
|
||||
<div className='text-gray-600 mt-2'><span><i class="fa-brands fa-algolia"></i> Algolia 提供搜索服务</span> </div>
|
||||
<div className='text-gray-600 mt-2'><span><i className="fa-brands fa-algolia"></i> Algolia 提供搜索服务</span> </div>
|
||||
</div>
|
||||
|
||||
{/* 遮罩 */}
|
||||
|
||||
@@ -174,8 +174,8 @@ function getSiteInfo({ collection, block }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导航pages
|
||||
* 转为gitbook这类文档主题设计,精减的标题和内容
|
||||
* 获取导航用的精减文章列表
|
||||
* gitbook主题用到,只保留文章的标题分类标签分类信息,精减掉摘要密码日期等数据
|
||||
* 导航页面的条件,必须是Posts
|
||||
* @param {*} param0
|
||||
*/
|
||||
@@ -183,22 +183,8 @@ export function getNavPages({ allPages }) {
|
||||
const allNavPages = allPages.filter(post => {
|
||||
return post && post?.slug && (!post?.slug?.startsWith('http')) && post?.type === 'Post' && post?.status === 'Published'
|
||||
})
|
||||
const result = allNavPages.map(item => ({ id: item.id, title: item.title || '', category: item.category || null, tags: item.tags || null, summary: item.summary || null, slug: item.slug }))
|
||||
|
||||
const groupedArray = result.reduce((groups, item) => {
|
||||
const categoryName = item?.category ? item?.category : '' // 将category转换为字符串
|
||||
const lastGroup = groups[groups.length - 1] // 获取最后一个分组
|
||||
|
||||
if (!lastGroup || lastGroup?.category !== categoryName) { // 如果当前元素的category与上一个元素不同,则创建新分组
|
||||
groups.push({ category: categoryName, items: [] })
|
||||
}
|
||||
|
||||
groups[groups.length - 1].items.push(item) // 将元素加入对应的分组
|
||||
|
||||
return groups
|
||||
}, [])
|
||||
|
||||
return groupedArray
|
||||
return allNavPages.map(item => ({ id: item.id, title: item.title || '', pageCoverThumbnail: item.pageCoverThumbnail || '', category: item.category || null, tags: item.tags || null, summary: item.summary || null, slug: item.slug }))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "notion-next",
|
||||
"version": "4.0.6",
|
||||
"version": "4.0.7",
|
||||
"homepage": "https://github.com/tangly1024/NotionNext.git",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -17,8 +17,6 @@ import dynamic from 'next/dynamic'
|
||||
|
||||
// 自定义样式css和js引入
|
||||
import ExternalScript from '@/components/ExternalScript'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
// 各种扩展插件 动画等
|
||||
const ExternalPlugins = dynamic(() => import('@/components/ExternalPlugins'))
|
||||
|
||||
@@ -26,11 +24,9 @@ const MyApp = ({ Component, pageProps }) => {
|
||||
useEffect(() => {
|
||||
AOS.init()
|
||||
}, [])
|
||||
const { meta } = pageProps
|
||||
|
||||
return (
|
||||
<GlobalContextProvider {...pageProps}>
|
||||
<CommonHead meta={meta}/>
|
||||
<ExternalScript />
|
||||
<Component {...pageProps} />
|
||||
<ExternalPlugins {...pageProps} />
|
||||
|
||||
@@ -3,7 +3,6 @@ import { getPostBlocks } from '@/lib/notion'
|
||||
import { getGlobalData } from '@/lib/notion/getNotionData'
|
||||
import { generateRss } from '@/lib/rss'
|
||||
import { generateRobotsTxt } from '@/lib/robots.txt'
|
||||
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
@@ -12,7 +11,6 @@ import { getLayoutByTheme } from '@/themes/theme'
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
|
||||
const Index = props => {
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
@@ -26,6 +26,7 @@ import TagItem from './components/TagItem'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
/**
|
||||
* 基础布局框架
|
||||
@@ -35,7 +36,7 @@ import { Style } from './style'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, slotTop } = props
|
||||
const { children, slotTop, meta } = props
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
// 增加一个状态以触发 Transition 组件的动画
|
||||
@@ -48,6 +49,10 @@ const LayoutBase = props => {
|
||||
|
||||
return (
|
||||
<div id='theme-example' className='dark:text-gray-300 bg-white dark:bg-black'>
|
||||
|
||||
{/* SEO信息 */}
|
||||
<CommonHead meta={meta}/>
|
||||
|
||||
<Style/>
|
||||
|
||||
{/* 页头 */}
|
||||
|
||||
@@ -20,6 +20,7 @@ import dynamic from 'next/dynamic'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
const Live2D = dynamic(() => import('@/components/Live2D'))
|
||||
|
||||
@@ -42,7 +43,7 @@ export const useFukasawaGlobal = () => useContext(ThemeGlobalFukasawa)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, headerSlot } = props
|
||||
const { children, headerSlot, meta } = props
|
||||
const leftAreaSlot = <Live2D />
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
@@ -65,6 +66,8 @@ const LayoutBase = (props) => {
|
||||
<ThemeGlobalFukasawa.Provider value={{ isCollapsed, setIsCollapse }}>
|
||||
|
||||
<div id='theme-fukasawa'>
|
||||
{/* SEO信息 */}
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
<TopNav {...props} />
|
||||
|
||||
@@ -10,12 +10,24 @@ import NavPostItem from './NavPostItem'
|
||||
* @constructor
|
||||
*/
|
||||
const NavPostList = (props) => {
|
||||
const { filteredPostGroups } = props
|
||||
const { filteredNavPages } = props
|
||||
const router = useRouter()
|
||||
let selectedSth = false
|
||||
const groupedArray = filteredNavPages?.reduce((groups, item) => {
|
||||
const categoryName = item?.category ? item?.category : '' // 将category转换为字符串
|
||||
const lastGroup = groups[groups.length - 1] // 获取最后一个分组
|
||||
|
||||
if (!lastGroup || lastGroup?.category !== categoryName) { // 如果当前元素的category与上一个元素不同,则创建新分组
|
||||
groups.push({ category: categoryName, items: [] })
|
||||
}
|
||||
|
||||
groups[groups.length - 1].items.push(item) // 将元素加入对应的分组
|
||||
|
||||
return groups
|
||||
}, [])
|
||||
|
||||
// 处理是否选中
|
||||
filteredPostGroups?.map((group) => {
|
||||
groupedArray?.map((group) => {
|
||||
let groupSelected = false
|
||||
for (const post of group?.items) {
|
||||
if (router.asPath.split('?')[0] === '/' + post.slug) {
|
||||
@@ -28,16 +40,16 @@ const NavPostList = (props) => {
|
||||
})
|
||||
|
||||
// 如果都没有选中默认打开第一个
|
||||
if (!selectedSth && filteredPostGroups && filteredPostGroups?.length > 0) {
|
||||
filteredPostGroups[0].selected = true
|
||||
if (!selectedSth && groupedArray && groupedArray?.length > 0) {
|
||||
groupedArray[0].selected = true
|
||||
}
|
||||
|
||||
if (!filteredPostGroups || filteredPostGroups.length === 0) {
|
||||
if (!groupedArray || groupedArray.length === 0) {
|
||||
return <NavPostListEmpty />
|
||||
} else {
|
||||
return <div id='posts-wrapper' className='w-full flex-grow'>
|
||||
{/* 文章列表 */}
|
||||
{filteredPostGroups?.map((group, index) => <NavPostItem key={index} group={group} onHeightChange={props.onHeightChange}/>)}
|
||||
{groupedArray?.map((group, index) => <NavPostItem key={index} group={group} onHeightChange={props.onHeightChange}/>)}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,21 @@ import NavPostList from './NavPostList'
|
||||
*/
|
||||
const PageNavDrawer = (props) => {
|
||||
const { pageNavVisible, changePageNavVisible } = useGitBookGlobal()
|
||||
const { filteredPostGroups } = props
|
||||
const { filteredNavPages } = props
|
||||
|
||||
const groupedArray = filteredNavPages.reduce((groups, item) => {
|
||||
const categoryName = item?.category ? item?.category : '' // 将category转换为字符串
|
||||
const lastGroup = groups[groups.length - 1] // 获取最后一个分组
|
||||
|
||||
if (!lastGroup || lastGroup?.category !== categoryName) { // 如果当前元素的category与上一个元素不同,则创建新分组
|
||||
groups.push({ category: categoryName, items: [] })
|
||||
}
|
||||
|
||||
groups[groups.length - 1].items.push(item) // 将元素加入对应的分组
|
||||
|
||||
return groups
|
||||
}, [])
|
||||
|
||||
const switchVisible = () => {
|
||||
changePageNavVisible(!pageNavVisible)
|
||||
}
|
||||
@@ -23,7 +37,7 @@ const PageNavDrawer = (props) => {
|
||||
' overflow-y-hidden shadow-card w-72 duration-200 fixed left-1 top-16 rounded py-2 bg-white dark:bg-gray-600'}>
|
||||
<div className='dark:text-gray-400 text-gray-600 h-96 overflow-y-scroll p-3'>
|
||||
{/* 所有文章列表 */}
|
||||
<NavPostList filteredPostGroups={filteredPostGroups} />
|
||||
<NavPostList groupedArray={groupedArray} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ let lock = false
|
||||
|
||||
const SearchInput = ({ currentSearch, cRef, className }) => {
|
||||
const searchInputRef = useRef()
|
||||
const { setFilterPosts, allNavPages } = useGitBookGlobal()
|
||||
const { setFilteredNavPages, allNavPages } = useGitBookGlobal()
|
||||
|
||||
useImperativeHandle(cRef, () => {
|
||||
return {
|
||||
@@ -17,31 +17,44 @@ const SearchInput = ({ currentSearch, cRef, className }) => {
|
||||
|
||||
const handleSearch = () => {
|
||||
let keyword = searchInputRef.current.value
|
||||
const filterPosts = []
|
||||
if (keyword) {
|
||||
keyword = keyword.trim()
|
||||
} else {
|
||||
setFilterPosts(allNavPages)
|
||||
setFilteredNavPages(allNavPages)
|
||||
}
|
||||
const filterAllNavPages = deepClone(allNavPages)
|
||||
for (const filterGroup of filterAllNavPages) {
|
||||
for (let i = filterGroup.items.length - 1; i >= 0; i--) {
|
||||
const post = filterGroup.items[i]
|
||||
const articleInfo = post.title + ''
|
||||
const hit = articleInfo.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
||||
if (!hit) {
|
||||
// 删除
|
||||
filterGroup.items.splice(i, 1)
|
||||
}
|
||||
}
|
||||
if (filterGroup.items && filterGroup.items.length > 0) {
|
||||
filterPosts.push(filterGroup)
|
||||
// for (const filterGroup of filterAllNavPages) {
|
||||
// for (let i = filterGroup.items.length - 1; i >= 0; i--) {
|
||||
// const post = filterGroup.items[i]
|
||||
// const articleInfo = post.title + ''
|
||||
// const hit = articleInfo.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
||||
// if (!hit) {
|
||||
// // 删除
|
||||
// filterGroup.items.splice(i, 1)
|
||||
// }
|
||||
// }
|
||||
// if (filterGroup.items && filterGroup.items.length > 0) {
|
||||
// filterPosts.push(filterGroup)
|
||||
// }
|
||||
// }
|
||||
for (let i = filterAllNavPages.length - 1; i >= 0; i--) {
|
||||
const post = filterAllNavPages[i]
|
||||
const articleInfo = post.title + ''
|
||||
const hit = articleInfo.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
||||
if (!hit) {
|
||||
// 删除
|
||||
filterAllNavPages.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新完
|
||||
setFilterPosts(filterPosts)
|
||||
setFilteredNavPages(filterAllNavPages)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回车键
|
||||
* @param {*} e
|
||||
*/
|
||||
const handleKeyUp = (e) => {
|
||||
if (e.keyCode === 13) { // 回车
|
||||
handleSearch(searchInputRef.current.value)
|
||||
@@ -49,6 +62,10 @@ const SearchInput = ({ currentSearch, cRef, className }) => {
|
||||
cleanSearch()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理搜索
|
||||
*/
|
||||
const cleanSearch = () => {
|
||||
searchInputRef.current.value = ''
|
||||
handleSearch()
|
||||
|
||||
@@ -30,6 +30,7 @@ import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
// 主题全局变量
|
||||
const ThemeGlobalGitbook = createContext()
|
||||
@@ -42,21 +43,23 @@ export const useGitBookGlobal = () => useContext(ThemeGlobalGitbook)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, post, allNavPages, slotLeft, slotRight, slotTop } = props
|
||||
const { children, post, allNavPages, slotLeft, slotRight, slotTop, meta } = props
|
||||
const { onLoading } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [tocVisible, changeTocVisible] = useState(false)
|
||||
const [pageNavVisible, changePageNavVisible] = useState(false)
|
||||
const [filteredPostGroups, setFilteredPostGroups] = useState(allNavPages)
|
||||
const [filteredNavPages, setFilteredNavPages] = useState(allNavPages)
|
||||
|
||||
const showTocButton = post?.toc?.length > 1
|
||||
|
||||
useEffect(() => {
|
||||
setFilteredPostGroups(allNavPages)
|
||||
console.log('更新导航', allNavPages)
|
||||
setFilteredNavPages(allNavPages)
|
||||
}, [post])
|
||||
|
||||
return (
|
||||
<ThemeGlobalGitbook.Provider value={{ tocVisible, changeTocVisible, filteredPostGroups, setFilteredPostGroups, allNavPages, pageNavVisible, changePageNavVisible }}>
|
||||
<ThemeGlobalGitbook.Provider value={{ tocVisible, changeTocVisible, filteredNavPages, setFilteredNavPages, allNavPages, pageNavVisible, changePageNavVisible }}>
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
<div id='theme-gitbook' className='bg-white dark:bg-hexo-black-gray w-full h-full min-h-screen justify-center dark:text-gray-300'>
|
||||
@@ -72,7 +75,7 @@ const LayoutBase = (props) => {
|
||||
<SearchInput className='my-3 rounded-md' />
|
||||
<div className='mb-20'>
|
||||
{/* 所有文章列表 */}
|
||||
<NavPostList filteredPostGroups={filteredPostGroups} />
|
||||
<NavPostList filteredNavPages={filteredNavPages} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -146,7 +149,7 @@ const LayoutBase = (props) => {
|
||||
</div>}
|
||||
|
||||
{/* 移动端导航抽屉 */}
|
||||
<PageNavDrawer {...props} filteredPostGroups={filteredPostGroups} />
|
||||
<PageNavDrawer {...props} filteredNavPages={filteredNavPages} />
|
||||
|
||||
{/* 移动端底部导航栏 */}
|
||||
{/* <BottomMenuBar {...props} className='block md:hidden' /> */}
|
||||
|
||||
@@ -19,7 +19,7 @@ const Hero = props => {
|
||||
return (
|
||||
<div id="hero-wrapper" className='recent-top-post-group w-full overflow-hidden select-none px-5 mb-4'>
|
||||
|
||||
<div id="hero" style={{ zIndex: 1 }} className={'animate__animated animate__fadeIn animate__fast recent-post-top rounded-[12px] 2xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex relative space-x-3'} >
|
||||
<div id="hero" style={{ zIndex: 1 }} className={'animate__animated animate__fadeIn animate__fast recent-post-top rounded-[12px] xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex xl:space-x-3 relative'} >
|
||||
|
||||
{/* 左侧banner组 */}
|
||||
<BannerGroup {...props} />
|
||||
@@ -116,22 +116,22 @@ function TagsGroupBar() {
|
||||
*/
|
||||
function GroupMenu() {
|
||||
return (
|
||||
<div className="h-[165px] select-none xl:h-20 flex flex-col w-48 justify-between xl:space-y-0 xl:flex-row xl:w-full xl:flex-nowrap xl:space-x-3">
|
||||
<div className="h-[165px] select-none xl:h-20 flex flex-col justify-between xl:space-y-0 xl:flex-row w-28 lg:w-48 xl:w-full xl:flex-nowrap xl:space-x-3">
|
||||
<Link href={CONFIG.HERO_CATEGORY_1?.url} className="group relative overflow-hidden bg-gradient-to-r from-blue-500 to-blue-400 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in">
|
||||
<div className="font-bold text-lg pl-5 relative -mt-2">
|
||||
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
|
||||
{CONFIG.HERO_CATEGORY_1?.title}
|
||||
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
|
||||
</div>
|
||||
<div className='absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
|
||||
<div className='hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
|
||||
<i className="fa-solid fa-star text-4xl"></i>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={CONFIG.HERO_CATEGORY_2?.url} className="group relative overflow-hidden bg-gradient-to-r from-red-500 to-yellow-500 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in">
|
||||
<div className="font-bold text-lg pl-5 relative -mt-2">
|
||||
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
|
||||
{CONFIG.HERO_CATEGORY_2?.title}
|
||||
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
|
||||
</div>
|
||||
<div className='absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
|
||||
<div className='hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
|
||||
<i className="fa-solid fa-fire-flame-curved text-4xl"></i>
|
||||
</div>
|
||||
</Link>
|
||||
@@ -154,16 +154,33 @@ function GroupMenu() {
|
||||
* 置顶文章区域
|
||||
*/
|
||||
function TopGroup(props) {
|
||||
const { latestPosts, siteInfo } = props
|
||||
const { latestPosts, allNavPages, siteInfo } = props
|
||||
const todayCardRef = useRef()
|
||||
function handleMouseLeave() {
|
||||
todayCardRef.current.coverUp()
|
||||
}
|
||||
|
||||
let topPosts = []
|
||||
// 默认展示最近更新
|
||||
if (!CONFIG.HERO_RECOMMEND_POST_TAG || CONFIG.HERO_RECOMMEND_POST_TAG === '') {
|
||||
topPosts = latestPosts
|
||||
} else {
|
||||
// 展示特定标签文章
|
||||
for (const post of allNavPages) {
|
||||
if (topPosts.length === 6) {
|
||||
break
|
||||
}
|
||||
// 查找标签
|
||||
if (post.tags.indexOf(CONFIG.HERO_RECOMMEND_POST_TAG) >= 0) {
|
||||
topPosts.push(post)
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div id='hero-right-wrapper' onMouseLeave={handleMouseLeave} className='flex-1 relative w-full'>
|
||||
{/* 置顶最新文章 */}
|
||||
{/* 置顶推荐文章 */}
|
||||
<div id='top-group' className='w-full flex space-x-3 xl:space-x-0 xl:grid xl:grid-cols-3 xl:gap-3 xl:h-[342px]'>
|
||||
{latestPosts?.map((p, index) => {
|
||||
{topPosts?.map((p, index) => {
|
||||
return <Link href={`${BLOG.SUB_PATH}/${p?.slug}`} key={index}>
|
||||
<div className='cursor-pointer h-[164px] group relative flex flex-col w-52 xl:w-full overflow-hidden shadow bg-white dark:bg-black dark:text-white rounded-xl'>
|
||||
<LazyImage priority={index === 0} className='h-24 object-cover' alt={p?.title} src={p?.pageCoverThumbnail || siteInfo?.pageCover} />
|
||||
|
||||
@@ -22,6 +22,9 @@ const CONFIG = {
|
||||
HERO_CATEGORY_2: { title: '热门文章', url: '/tag/热门文章' },
|
||||
HERO_CATEGORY_3: { title: '实用教程', url: '/tag/实用教程' },
|
||||
|
||||
// 英雄区右侧推荐文章标签, 例如 [推荐] , 最多六篇文章; 若留空白'',则推荐最近更新文章
|
||||
HERO_RECOMMEND_POST_TAG: '推荐',
|
||||
|
||||
// 右侧个人资料卡牌欢迎语,点击可自动切换
|
||||
INFOCARD_GREETINGS: [
|
||||
'你好!我是',
|
||||
|
||||
@@ -39,10 +39,12 @@ import LazyImage from '@/components/LazyImage'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, headerSlot, slotTop, slotRight, siteInfo, className } = props
|
||||
const { children, headerSlot, slotTop, slotRight, siteInfo, className, meta } = props
|
||||
|
||||
return (
|
||||
<div id='theme-heo' className='bg-[#f7f9fe] dark:bg-[#18171d] h-full min-h-screen flex flex-col'>
|
||||
{/* SEO信息 */}
|
||||
<CommonHead meta={meta}/>
|
||||
<Style />
|
||||
|
||||
{/* 顶部嵌入 导航栏,首页放hero,文章页放文章详情 */}
|
||||
@@ -91,7 +93,7 @@ const LayoutIndex = (props) => {
|
||||
const slotRight = <SideRight {...props} />
|
||||
|
||||
return <LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
|
||||
<div id='post-outer-wrapper' className='px-5 lg:px-0'>
|
||||
<div id='post-outer-wrapper' className='px-5 md:px-0'>
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} />
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
@@ -113,7 +115,7 @@ const LayoutPostList = (props) => {
|
||||
</header>
|
||||
|
||||
return <LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
|
||||
<div id='post-outer-wrapper' className='px-5 lg:px-0'>
|
||||
<div id='post-outer-wrapper' className='px-5 md:px-0'>
|
||||
{/* 文章分类条 */}
|
||||
<CategoryBar {...props} />
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
@@ -153,7 +155,7 @@ const LayoutSearch = props => {
|
||||
}, [])
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch} headerSlot={headerSlot}>
|
||||
<div id='post-outer-wrapper' className='px-5 lg:px-0'>
|
||||
<div id='post-outer-wrapper' className='px-5 md:px-0'>
|
||||
{!currentSearch
|
||||
? <SearchNav {...props} />
|
||||
: <div id="posts-wrapper"> {BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />} </div>}
|
||||
@@ -346,7 +348,7 @@ const LayoutCategoryIndex = props => {
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} className='mt-8' headerSlot={headerSlot}>
|
||||
<div id='category-outer-wrapper' className='px-5 lg:px-0'>
|
||||
<div id='category-outer-wrapper' className='px-5 md:px-0'>
|
||||
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
|
||||
{locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
@@ -384,7 +386,7 @@ const LayoutTagIndex = props => {
|
||||
</header>
|
||||
return (
|
||||
<LayoutBase {...props} className='mt-8' headerSlot={headerSlot}>
|
||||
<div id='tag-outer-wrapper' className='px-5 lg:px-0'>
|
||||
<div id='tag-outer-wrapper' className='px-5 md:px-0'>
|
||||
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
|
||||
{locale.COMMON.TAGS}
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,7 @@ const LayoutBase = props => {
|
||||
return (
|
||||
<div id='theme-hexo'>
|
||||
{/* 网页SEO */}
|
||||
<CommonHead meta={meta} siteInfo={siteInfo} />
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
{/* 顶部导航 */}
|
||||
|
||||
@@ -35,6 +35,7 @@ import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import ArticleInfo from './components/ArticleInfo'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalMedium = createContext()
|
||||
@@ -47,7 +48,7 @@ export const useMediumGlobal = () => useContext(ThemeGlobalMedium)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, showInfoCard = true, slotRight, slotTop, siteInfo, notice } = props
|
||||
const { children, showInfoCard = true, slotRight, slotTop, siteInfo, notice, meta } = props
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [tocVisible, changeTocVisible] = useState(false)
|
||||
@@ -55,6 +56,8 @@ const LayoutBase = props => {
|
||||
|
||||
return (
|
||||
<ThemeGlobalMedium.Provider value={{ tocVisible, changeTocVisible }}>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta}/>
|
||||
{/* CSS样式 */}
|
||||
<Style/>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左中右三栏布局,移动端使用顶部导航栏
|
||||
@@ -32,7 +33,7 @@ import replaceSearchResult from '@/components/Mark'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, headerSlot, floatSlot, rightAreaSlot, siteInfo } = props
|
||||
const { children, headerSlot, floatSlot, rightAreaSlot, siteInfo, meta } = props
|
||||
const { onLoading } = useGlobal()
|
||||
const targetRef = useRef(null)
|
||||
const floatButtonGroup = useRef(null)
|
||||
@@ -69,6 +70,8 @@ const LayoutBase = (props) => {
|
||||
|
||||
return (
|
||||
<div id='theme-next'>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
{/* 移动端顶部导航栏 */}
|
||||
|
||||
@@ -23,6 +23,7 @@ import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -31,13 +32,15 @@ import replaceSearchResult from '@/components/Mark'
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, post, topSlot } = props
|
||||
const { children, post, topSlot, meta } = props
|
||||
|
||||
const fullWidth = post?.fullWidth ?? false
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
return (
|
||||
<div id='theme-nobelium' className='nobelium relative dark:text-gray-300 w-full bg-white dark:bg-black min-h-screen'>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta}/>
|
||||
{/* SEO相关 */}
|
||||
<Style/>
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import Modal from './components/Modal'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalPlog = createContext()
|
||||
@@ -34,7 +35,7 @@ export const usePlogGlobal = () => useContext(ThemeGlobalPlog)
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, topSlot } = props
|
||||
const { children, topSlot, meta } = props
|
||||
const { onLoading, updateDarkMode } = useGlobal()
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [modalContent, setModalContent] = useState(null)
|
||||
@@ -58,6 +59,8 @@ const LayoutBase = props => {
|
||||
return (
|
||||
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
||||
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full bg-black min-h-screen'>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
{/* 移动端顶部导航栏 */}
|
||||
|
||||
@@ -24,6 +24,7 @@ import SearchInput from './components/SearchInput'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
@@ -32,7 +33,7 @@ import replaceSearchResult from '@/components/Mark'
|
||||
* @returns
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, slotTop } = props
|
||||
const { children, slotTop, meta } = props
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
if (isBrowser()) {
|
||||
@@ -40,6 +41,8 @@ const LayoutBase = props => {
|
||||
}
|
||||
return (
|
||||
<div id='theme-simple' className='min-h-screen flex flex-col dark:text-gray-300 bg-white dark:bg-black'>
|
||||
{/* SEO相关 */}
|
||||
<CommonHead meta={meta}/>
|
||||
<Style/>
|
||||
|
||||
{CONFIG.TOP_BAR && <TopBar {...props} />}
|
||||
|
||||
Reference in New Issue
Block a user