mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
fukasawa theme
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
|
||||
const ArchiveIndex = props => {
|
||||
const { siteInfo } = props
|
||||
@@ -12,6 +13,20 @@ const ArchiveIndex = props => {
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
useEffect(() => {
|
||||
if (isBrowser()) {
|
||||
const anchor = window.location.hash
|
||||
if (anchor) {
|
||||
setTimeout(() => {
|
||||
const anchorElement = document.getElementById(anchor.substring(1))
|
||||
if (anchorElement) {
|
||||
anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' })
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const meta = {
|
||||
title: `${locale.NAV.ARCHIVE} | ${siteInfo?.title}`,
|
||||
description: siteInfo?.description,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import BLOG, { LINK } from '@/blog.config'
|
||||
import BLOG from '@/blog.config'
|
||||
import Link from 'next/link'
|
||||
|
||||
/**
|
||||
* 按照日期将文章分组
|
||||
@@ -20,17 +21,12 @@ export default function BlogListGroupByDate({ archiveTitle, archivePosts }) {
|
||||
>
|
||||
<div id={post?.publishTime}>
|
||||
<span className="text-gray-400">
|
||||
{post.date?.start_date}
|
||||
{post?.publishTime}
|
||||
</span>{' '}
|
||||
|
||||
<LINK
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
{post.title}
|
||||
|
||||
</LINK>
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -13,10 +13,10 @@ export const Nav = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
|
||||
let links = [
|
||||
{ icon: 'fas fa-search', name: locale.NAV.SEARCH, to: '/search', show: CONFIG_EXAMPLE.MENU_SEARCH },
|
||||
{ icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_EXAMPLE.MENU_ARCHIVE },
|
||||
{ icon: 'fas fa-folder', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_EXAMPLE.MENU_CATEGORY },
|
||||
{ icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_EXAMPLE.MENU_TAG }
|
||||
{ id: 1, icon: 'fas fa-search', name: locale.NAV.SEARCH, to: '/search', show: CONFIG_EXAMPLE.MENU_SEARCH },
|
||||
{ id: 2, icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_EXAMPLE.MENU_ARCHIVE },
|
||||
{ id: 3, icon: 'fas fa-folder', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_EXAMPLE.MENU_CATEGORY },
|
||||
{ id: 4, icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_EXAMPLE.MENU_TAG }
|
||||
]
|
||||
|
||||
if (customNav) {
|
||||
|
||||
@@ -40,6 +40,7 @@ const LayoutBase = props => {
|
||||
|
||||
return (
|
||||
<div id='theme-example' className='dark:text-gray-300 bg-white dark:bg-black'>
|
||||
{/* 网页SEO信息 */}
|
||||
<CommonHead meta={meta} />
|
||||
|
||||
{/* 页头 */}
|
||||
@@ -97,6 +98,7 @@ const LayoutIndex = props => {
|
||||
*/
|
||||
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>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const Layout404 = props => {
|
||||
return <LayoutBase {...props}>404</LayoutBase>
|
||||
}
|
||||
|
||||
export default Layout404
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useEffect } from 'react'
|
||||
import BlogArchiveItem from './components/BlogPostArchive'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
|
||||
useEffect(() => {
|
||||
const anchor = window.location.hash
|
||||
if (anchor) {
|
||||
setTimeout(() => {
|
||||
const anchorElement = document.getElementById(anchor.substring(1))
|
||||
if (anchorElement) {
|
||||
anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' })
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
}, [])
|
||||
return <LayoutBase {...props}>
|
||||
<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
|
||||
key={archiveTitle}
|
||||
posts={archivePosts[archiveTitle]}
|
||||
archiveTitle={archiveTitle}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutArchive
|
||||
@@ -1,58 +0,0 @@
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
import TopNav from './components/TopNav'
|
||||
import AsideLeft from './components/AsideLeft'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
* @param children
|
||||
* @param layout
|
||||
* @param tags
|
||||
* @param meta
|
||||
* @param post
|
||||
* @param currentSearch
|
||||
* @param currentCategory
|
||||
* @param currentTag
|
||||
* @param categories
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, headerSlot, meta } = props
|
||||
const leftAreaSlot = <Live2D/>
|
||||
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-fukasawa.css', 'css')
|
||||
}
|
||||
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
const LoadingCover = <div id='cover-loading' className={`${onLoading ? 'z-50 opacity-50' : '-z-10 opacity-0'} pointer-events-none transition-all duration-300`}>
|
||||
<div className='w-full h-screen flex justify-center items-center'>
|
||||
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
return (<div id='theme-fukasawa' >
|
||||
<CommonHead meta={meta} />
|
||||
<TopNav {...props}/>
|
||||
|
||||
<div className={(BLOG.LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : '') + ' flex'}>
|
||||
<AsideLeft {...props} slot={leftAreaSlot}/>
|
||||
|
||||
<main id='wrapper' className='relative flex w-full py-8 justify-center bg-day dark:bg-night'>
|
||||
<div id='container-inner' className='2xl:max-w-6xl md:max-w-4xl w-full relative z-10'>
|
||||
<div> {headerSlot} </div>
|
||||
<div> {onLoading ? LoadingCover : children} </div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
</div>)
|
||||
}
|
||||
|
||||
export default LayoutBase
|
||||
@@ -1,12 +0,0 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutCategory = props => {
|
||||
return <LayoutBase {...props}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutCategory
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export 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}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
export default LayoutCategoryIndex
|
||||
@@ -1,12 +0,0 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutIndex = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutIndex
|
||||
@@ -1,12 +0,0 @@
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutPage = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
|
||||
<BlogListPage page={props.page} posts={props.posts} postCount={props.postCount}/>
|
||||
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutPage
|
||||
@@ -1,32 +0,0 @@
|
||||
import LayoutBase from './LayoutBase'
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import Mark from 'mark.js'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
|
||||
export const LayoutSearch = (props) => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
const currentSearch = keyword || router?.query?.s
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(currentSearch, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
return <LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutSearch
|
||||
@@ -1,15 +0,0 @@
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import LayoutBase from './LayoutBase'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
|
||||
export const LayoutSlug = (props) => {
|
||||
const { lock, validPassword } = props
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
{!lock && <ArticleDetail {...props} />}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
export default LayoutSlug
|
||||
@@ -1,12 +0,0 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutTag = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutTag
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutTagIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { tagOptions } = 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-tag'/>{locale.COMMON.TAGS}:</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export default LayoutTagIndex
|
||||
11
themes/fukasawa/components/LoadingCover.js
Normal file
11
themes/fukasawa/components/LoadingCover.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 加载过程的遮罩
|
||||
* @returns
|
||||
*/
|
||||
export default function LoadingCover () {
|
||||
return <div id='cover-loading' className={'z-50 opacity-50 pointer-events-none transition-all duration-300'}>
|
||||
<div className='w-full h-screen flex justify-center items-center'>
|
||||
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -1,14 +1,209 @@
|
||||
'use client'
|
||||
|
||||
import CONFIG_FUKA from './config_fuka'
|
||||
import LayoutIndex from './LayoutIndex'
|
||||
import LayoutSearch from './LayoutSearch'
|
||||
import LayoutArchive from './LayoutArchive'
|
||||
import LayoutSlug from './LayoutSlug'
|
||||
import Layout404 from './Layout404'
|
||||
import LayoutCategory from './LayoutCategory'
|
||||
import LayoutCategoryIndex from './LayoutCategoryIndex'
|
||||
import LayoutPage from './LayoutPage'
|
||||
import LayoutTag from './LayoutTag'
|
||||
import LayoutTagIndex from './LayoutTagIndex'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
import TopNav from './components/TopNav'
|
||||
import AsideLeft from './components/AsideLeft'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import LoadingCover from './components/LoadingCover'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import BlogArchiveItem from './components/BlogPostArchive'
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import Mark from 'mark.js'
|
||||
import Link from 'next/link'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
* @param children
|
||||
* @param layout
|
||||
* @param tags
|
||||
* @param meta
|
||||
* @param post
|
||||
* @param currentSearch
|
||||
* @param currentCategory
|
||||
* @param currentTag
|
||||
* @param categories
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children, headerSlot, meta } = props
|
||||
const leftAreaSlot = <Live2D />
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-fukasawa.css', 'css')
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='theme-fukasawa'>
|
||||
<CommonHead meta={meta} />
|
||||
<TopNav {...props} />
|
||||
|
||||
<div className={(BLOG.LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : '') + ' flex'}>
|
||||
{/* 侧边抽屉 */}
|
||||
<AsideLeft {...props} slot={leftAreaSlot} />
|
||||
|
||||
<main id='wrapper' className='relative flex w-full py-8 justify-center bg-day dark:bg-night'>
|
||||
<div id='container-inner' className='2xl:max-w-6xl md:max-w-4xl w-full relative z-10'>
|
||||
<div> {headerSlot} </div>
|
||||
<div> {onLoading ? <LoadingCover /> : children} </div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
</div>)
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页
|
||||
* @param {*} props notion数据
|
||||
* @returns 首页就是一个博客列表
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
return <LayoutPostList {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
* 博客列表
|
||||
* @param {*} props
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章详情
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const { lock, validPassword } = props
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
{lock ? <ArticleLock validPassword={validPassword} /> : <ArticleDetail {...props} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索页
|
||||
*/
|
||||
const LayoutSearch = (props) => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 300)
|
||||
}, [router])
|
||||
return <LayoutPostList />
|
||||
}
|
||||
|
||||
/**
|
||||
* 归档页面
|
||||
*/
|
||||
const LayoutArchive = (props) => {
|
||||
const { archivePosts } = props
|
||||
return <LayoutBase {...props}>
|
||||
<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
|
||||
key={archiveTitle}
|
||||
posts={archivePosts[archiveTitle]}
|
||||
archiveTitle={archiveTitle}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
/**
|
||||
* 404
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <LayoutBase {...props}>404</LayoutBase>
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类列表
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
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}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutTagIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { tagOptions } = 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-tag' />{locale.COMMON.TAGS}:</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG_FUKA as THEME_CONFIG,
|
||||
@@ -17,9 +212,7 @@ export {
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutPostList,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export const getLayoutByTheme = (router) => {
|
||||
const themeQuery = getQueryParam(router.asPath, 'theme') || BLOG.THEME
|
||||
const layout = getLayoutNameByPath(router.pathname)
|
||||
if (themeQuery !== BLOG.THEME) {
|
||||
return dynamic(() => import(`@/themes/${themeQuery}/${layout}`), { ssr: true })
|
||||
return dynamic(() => import(`@/themes/${themeQuery}`).then(m => m[layout]), { ssr: true })
|
||||
} else {
|
||||
return ThemeComponents[layout]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user