mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-08 15:10:37 +00:00
magzine基本组件
This commit is contained in:
@@ -1664,9 +1664,8 @@ code[class*='language-'] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NOTION CSS OVERRIDE */
|
/* NOTION CSS OVERRIDE */
|
||||||
|
|
||||||
.notion {
|
.notion {
|
||||||
@apply dark:text-gray-300;
|
@apply dark:text-gray-100;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
.notion,
|
.notion,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const Announcement = ({ post, className }) => {
|
|||||||
<div className={className}>
|
<div className={className}>
|
||||||
<section
|
<section
|
||||||
id='announcement-wrapper'
|
id='announcement-wrapper'
|
||||||
className='dark:text-gray-300 rounded-xl px-2 py-4'>
|
className='dark:text-gray-300 rounded-xl px-2'>
|
||||||
{/* <div><i className='mr-2 fas fa-bullhorn' />{locale.COMMON.ANNOUNCEMENT}</div> */}
|
{/* <div><i className='mr-2 fas fa-bullhorn' />{locale.COMMON.ANNOUNCEMENT}</div> */}
|
||||||
{post && (
|
{post && (
|
||||||
<div id='announcement-content'>
|
<div id='announcement-content'>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Link from 'next/link'
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
export default function ArchiveItem({ archiveTitle, archivePosts }) {
|
||||||
return (
|
return (
|
||||||
<div key={archiveTitle}>
|
<div key={archiveTitle}>
|
||||||
<div id={archiveTitle} className='pt-16 pb-4 text-3xl dark:text-gray-300'>
|
<div id={archiveTitle} className='pt-16 pb-4 text-3xl dark:text-gray-300'>
|
||||||
@@ -32,7 +32,7 @@ export default function ArticleInfo(props) {
|
|||||||
<i className='far fa-calendar-check mr-2' />
|
<i className='far fa-calendar-check mr-2' />
|
||||||
{post?.lastEditedDay}
|
{post?.lastEditedDay}
|
||||||
</span>
|
</span>
|
||||||
<div className='hidden busuanzi_container_page_pv font-light mr-2 whitespace-nowrap'>
|
<div className='hidden busuanzi_container_page_pv mr-2 whitespace-nowrap'>
|
||||||
<i className='mr-1 fas fa-eye' />
|
<i className='mr-1 fas fa-eye' />
|
||||||
<span className='busuanzi_value_page_pv' />
|
<span className='busuanzi_value_page_pv' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export const ArticleLock = props => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
ref={passwordInputRef} // 绑定ref到passwordInputRef变量
|
ref={passwordInputRef} // 绑定ref到passwordInputRef变量
|
||||||
className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg dark:text-gray-300 font-light leading-10 text-black bg-gray-100 dark:bg-gray-500'></input>
|
className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg dark:text-gray-300 leading-10 text-black bg-gray-100 dark:bg-gray-500'></input>
|
||||||
<div
|
<div
|
||||||
onClick={submitPassword}
|
onClick={submitPassword}
|
||||||
className='px-3 whitespace-nowrap cursor-pointer items-center justify-center py-2 bg-gray-500 hover:bg-gray-400 text-white rounded-r duration-300'>
|
className='px-3 whitespace-nowrap cursor-pointer items-center justify-center py-2 bg-gray-500 hover:bg-gray-400 text-white rounded-r duration-300'>
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import { useGlobal } from '@/lib/global'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 空白博客 列表
|
|
||||||
* @returns {JSX.Element}
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
const BlogPostListEmpty = ({ currentSearch }) => {
|
|
||||||
const { locale } = useGlobal()
|
|
||||||
return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
|
|
||||||
<p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
export default BlogPostListEmpty
|
|
||||||
@@ -77,7 +77,7 @@ const Catalog = ({ toc }) => {
|
|||||||
<a
|
<a
|
||||||
key={id}
|
key={id}
|
||||||
href={`#${id}`}
|
href={`#${id}`}
|
||||||
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
|
className={`notion-table-of-contents-item duration-300 transform dark:text-gray-300
|
||||||
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}>
|
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ export default function CategoryItem({ selected, category, categoryCount }) {
|
|||||||
className={
|
className={
|
||||||
(selected
|
(selected
|
||||||
? ' bg-gray-600 text-white '
|
? ' bg-gray-600 text-white '
|
||||||
: 'dark:text-gray-400 text-gray-500 ') +
|
: 'dark:text-gray-400 text-gray-900 ') +
|
||||||
' flex text-sm items-center duration-300 cursor-pointer py-1 font-light px-2 whitespace-nowrap'
|
' hover:underline flex text-sm items-center duration-300 cursor-pointer py-1 whitespace-nowrap'
|
||||||
}>
|
}>
|
||||||
<div>
|
<div>
|
||||||
<i
|
{/* <i
|
||||||
className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`}
|
className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`}
|
||||||
/>
|
/> */}
|
||||||
{category} {categoryCount && `(${categoryCount})`}
|
{category} {categoryCount && `(${categoryCount})`}
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,28 +1,56 @@
|
|||||||
import DarkModeButton from '@/components/DarkModeButton'
|
import DarkModeButton from '@/components/DarkModeButton'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import SocialButton from './SocialButton'
|
||||||
|
|
||||||
const Footer = ({ title }) => {
|
const Footer = ({ title }) => {
|
||||||
const d = new Date()
|
const d = new Date()
|
||||||
const currentYear = d.getFullYear()
|
const currentYear = d.getFullYear()
|
||||||
const since = siteConfig('SINCE')
|
const since = siteConfig('SINCE')
|
||||||
const copyrightDate = parseInt(since) < currentYear ? since + '-' + currentYear : currentYear
|
const copyrightDate =
|
||||||
|
parseInt(since) < currentYear ? since + '-' + currentYear : currentYear
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer
|
<footer className='z-10 bg-black text-white flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-sm p-6 relative'>
|
||||||
className='z-10 dark:bg-hexo-black-gray flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-sm p-6 relative'
|
<DarkModeButton />
|
||||||
>
|
<i className='fas fa-copyright' /> {`${copyrightDate}`}{' '}
|
||||||
<DarkModeButton/>
|
<span>
|
||||||
<i className='fas fa-copyright' /> {`${copyrightDate}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={siteConfig('LINK')} className='underline font-bold text-gray-500 dark:text-gray-300 '>{siteConfig('AUTHOR')}</a>.<br/>
|
<i className='mx-1 animate-pulse fas fa-heart' />{' '}
|
||||||
|
<a
|
||||||
{siteConfig('BEI_AN') && <><i className='fas fa-shield-alt'/> <a href='https://beian.miit.gov.cn/' className='mr-2'>{siteConfig('BEI_AN')}</a><br/></>}
|
href={siteConfig('LINK')}
|
||||||
|
className='underline font-bold justify-start '>
|
||||||
<span className='hidden busuanzi_container_site_pv'>
|
{siteConfig('AUTHOR')}
|
||||||
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
|
</a>
|
||||||
<span className='pl-2 hidden busuanzi_container_site_uv'>
|
.<br />
|
||||||
<i className='fas fa-users'/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
|
{siteConfig('BEI_AN') && (
|
||||||
<br/>
|
<>
|
||||||
|
<i className='fas fa-shield-alt' />{' '}
|
||||||
|
<a href='https://beian.miit.gov.cn/' className='mr-2'>
|
||||||
|
{siteConfig('BEI_AN')}
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<span className='hidden busuanzi_container_site_pv'>
|
||||||
|
<i className='fas fa-eye' />
|
||||||
|
<span className='px-1 busuanzi_value_site_pv'> </span>{' '}
|
||||||
|
</span>
|
||||||
|
<span className='pl-2 hidden busuanzi_container_site_uv'>
|
||||||
|
<i className='fas fa-users' />{' '}
|
||||||
|
<span className='px-1 busuanzi_value_site_uv'> </span>{' '}
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
<span 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>.</span></span>
|
<span className='text-xs font-serif'>
|
||||||
|
Powered by{' '}
|
||||||
|
<a
|
||||||
|
href='https://github.com/tangly1024/NotionNext'
|
||||||
|
className='underline justify-start text-white'>
|
||||||
|
NotionNext {siteConfig('VERSION')}
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<SocialButton />
|
||||||
</footer>
|
</footer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export default function Header(props) {
|
|||||||
const { customNav, customMenu } = props
|
const { customNav, customMenu } = props
|
||||||
const [isOpen, changeShow] = useState(false)
|
const [isOpen, changeShow] = useState(false)
|
||||||
const collapseRef = useRef(null)
|
const collapseRef = useRef(null)
|
||||||
|
const lastScrollY = useRef(0) // 用于存储上一次的滚动位置
|
||||||
|
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
@@ -66,16 +67,39 @@ export default function Header(props) {
|
|||||||
|
|
||||||
const scrollTrigger = throttle(() => {
|
const scrollTrigger = throttle(() => {
|
||||||
const scrollS = window.scrollY
|
const scrollS = window.scrollY
|
||||||
const nav = document.querySelector('#top-navbar')
|
if (scrollS === lastScrollY.current) return // 如果滚动位置没有变化,则不做任何操作
|
||||||
|
|
||||||
const narrowNav = scrollS > 50
|
const nav = document.querySelector('#top-navbar')
|
||||||
|
const narrowNav = scrollS > 60
|
||||||
if (narrowNav) {
|
if (narrowNav) {
|
||||||
nav && nav.classList.replace('h-20', 'h-14')
|
nav && nav.classList.replace('h-20', 'h-14')
|
||||||
} else {
|
} else {
|
||||||
nav && nav.classList.replace('h-14', 'h-20')
|
nav && nav.classList.replace('h-14', 'h-20')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastScrollY.current = scrollS // 更新上一次的滚动位置
|
||||||
}, throttleMs)
|
}, throttleMs)
|
||||||
|
|
||||||
|
const [showSearchInput, changeShowSearchInput] = useState(false)
|
||||||
|
|
||||||
|
// 展示搜索框
|
||||||
|
const toggleShowSearchInput = () => {
|
||||||
|
if (siteConfig('ALGOLIA_APP_ID')) {
|
||||||
|
searchModal.current.openSearch()
|
||||||
|
} else {
|
||||||
|
changeShowSearchInput(!showSearchInput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onKeyUp = e => {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
const search = document.getElementById('simple-search').value
|
||||||
|
if (search) {
|
||||||
|
router.push({ pathname: '/search/' + search })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 如果 开启自定义菜单,则覆盖Page生成的菜单
|
// 如果 开启自定义菜单,则覆盖Page生成的菜单
|
||||||
if (siteConfig('CUSTOM_MENU')) {
|
if (siteConfig('CUSTOM_MENU')) {
|
||||||
links = customMenu
|
links = customMenu
|
||||||
@@ -94,25 +118,61 @@ export default function Header(props) {
|
|||||||
{/* 导航栏菜单内容 */}
|
{/* 导航栏菜单内容 */}
|
||||||
<div
|
<div
|
||||||
id='top-navbar'
|
id='top-navbar'
|
||||||
className='px-4 flex w-full mx-auto max-w-screen-xl h-20 transition-all duration-200 items-between'>
|
className='flex w-full mx-auto max-w-7xl h-20 transition-all duration-200 items-center justify-between'>
|
||||||
{/* 左侧图标Logo */}
|
{/* 搜索栏 */}
|
||||||
<LogoBar {...props} />
|
{showSearchInput && (
|
||||||
|
<input
|
||||||
|
autoFocus
|
||||||
|
id='simple-search'
|
||||||
|
onKeyUp={onKeyUp}
|
||||||
|
className='outline-none flex flex-row text-base relative w-full border-b py-2'
|
||||||
|
aria-label='Submit search'
|
||||||
|
type='search'
|
||||||
|
name='s'
|
||||||
|
autoComplete='off'
|
||||||
|
placeholder='Type then hit enter to search...'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 移动端折叠按钮 */}
|
{/* 默认菜单 */}
|
||||||
<div className='mr-1 flex md:hidden justify-end items-center text-lg space-x-4 font-serif dark:text-gray-200'>
|
{!showSearchInput && (
|
||||||
<div onClick={toggleMenuOpen} className='cursor-pointer'>
|
<>
|
||||||
{isOpen ? (
|
{/* 左侧图标Logo */}
|
||||||
<i className='fas fa-times' />
|
<div className='flex gap-x-8 h-full'>
|
||||||
) : (
|
<LogoBar {...props} />
|
||||||
<i className='fas fa-bars' />
|
{/* 桌面端顶部菜单 */}
|
||||||
)}
|
<div className='hidden md:flex items-center gap-x-2'>
|
||||||
|
{links &&
|
||||||
|
links?.map(link => (
|
||||||
|
<MenuItemDrop key={link?.id} link={link} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 右侧移动端折叠按钮 */}
|
||||||
|
<div className='flex items-center gap-x-2'>
|
||||||
|
<div className='mr-1 flex md:hidden justify-end items-center text-lg space-x-4 font-serif dark:text-gray-200'>
|
||||||
|
<div onClick={toggleMenuOpen} className='cursor-pointer'>
|
||||||
|
{isOpen ? (
|
||||||
|
<i className='fas fa-times' />
|
||||||
|
) : (
|
||||||
|
<i className='fas fa-bars' />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 桌面端顶部菜单 */}
|
{/* 搜索按钮 */}
|
||||||
<div className='hidden md:flex items-center'>
|
<div className='text-center items-center cursor-pointer'>
|
||||||
{links &&
|
<i
|
||||||
links?.map(link => <MenuItemDrop key={link?.id} link={link} />)}
|
className={
|
||||||
|
showSearchInput
|
||||||
|
? 'fa-regular fa-circle-xmark'
|
||||||
|
: 'fa-solid fa-magnifying-glass' + ' align-middle'
|
||||||
|
}
|
||||||
|
onClick={toggleShowSearchInput}></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
62
themes/magzine/components/Hero.js
Normal file
62
themes/magzine/components/Hero.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// import { useGlobal } from '@/lib/global'
|
||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import PostItemCardTop from './PostItemCardTop'
|
||||||
|
import PostItemCardWide from './PostItemCardWide'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页主宣传
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const Hero = ({ posts }) => {
|
||||||
|
// 获取置顶文章与次要文章
|
||||||
|
const postTop = posts[0]
|
||||||
|
const post1 = posts[1]
|
||||||
|
const post2 = posts[2]
|
||||||
|
// 首屏信息栏按钮文字
|
||||||
|
const banner = siteConfig('MAGZINE_HOME_BANNER_ENABLE')
|
||||||
|
const button = siteConfig('MAGZINE_HOME_BUTTON')
|
||||||
|
const text = siteConfig('MAGZINE_HOME_BUTTON_TEXT')
|
||||||
|
const url = siteConfig('MAGZINE_HOME_BUTTON_URL')
|
||||||
|
const title = siteConfig('MAGZINE_HOME_TITLE')
|
||||||
|
const description = siteConfig('MAGZINE_HOME_DESCRIPTION')
|
||||||
|
const tips = siteConfig('MAGZINE_HOME_TIPS')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='w-full mx-auto max-w-7xl xl:flex justify-between'>
|
||||||
|
{/* 左侧一篇主要置顶文章 */}
|
||||||
|
<div className='basis-1/2 mb-6'>
|
||||||
|
<PostItemCardTop post={postTop} />
|
||||||
|
</div>
|
||||||
|
{/* 右侧 */}
|
||||||
|
<div>
|
||||||
|
{/* 首屏介绍 */}
|
||||||
|
{banner && (
|
||||||
|
<div className='flex flex-col p-5 gap-y-5 dark items-center justify-between w-full bg-black text-white'>
|
||||||
|
{/* 首屏导航按钮 */}
|
||||||
|
<h2 className='text-2xl font-semibold'>{title}</h2>
|
||||||
|
<h3 className='text-sm'>{description}</h3>
|
||||||
|
{button && (
|
||||||
|
<div className='mt-2 text-center px-6 py-3 font-semibold rounded-3xl text-black bg-[#7BE986] hover:bg-[#62BA6B]'>
|
||||||
|
<Link href={url}>{text}</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<span className='text-xs'>{tips}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 两篇次要文章 */}
|
||||||
|
<div className='py-4'>
|
||||||
|
<hr className='mb-8' />
|
||||||
|
<PostItemCardWide post={post1} />
|
||||||
|
<hr className='mb-8' />
|
||||||
|
<PostItemCardWide post={post2} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Hero
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Router from 'next/router'
|
|
||||||
import SocialButton from './SocialButton'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户信息卡
|
* 用户信息卡
|
||||||
@@ -10,8 +8,9 @@ import SocialButton from './SocialButton'
|
|||||||
*/
|
*/
|
||||||
const InfoCard = props => {
|
const InfoCard = props => {
|
||||||
const { siteInfo } = props
|
const { siteInfo } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='info-card' className='py-4'>
|
<div id='info-card'>
|
||||||
<div className='items-center justify-start'>
|
<div className='items-center justify-start'>
|
||||||
<div
|
<div
|
||||||
className='hover:scale-105 transform duration-200 cursor-pointer flex justify-start'
|
className='hover:scale-105 transform duration-200 cursor-pointer flex justify-start'
|
||||||
@@ -24,13 +23,12 @@ const InfoCard = props => {
|
|||||||
alt={siteConfig('AUTHOR')}
|
alt={siteConfig('AUTHOR')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='text-xl py-2 hover:scale-105 transform duration-200 flex justify-start dark:text-gray-300'>
|
<div className='text-xl py-2 hover:scale-105 transform duration-200 flex justify-start '>
|
||||||
{siteConfig('AUTHOR')}
|
{siteConfig('AUTHOR')}
|
||||||
</div>
|
</div>
|
||||||
<div className='font-light text-gray-600 mb-2 hover:scale-105 transform duration-200 flex justify-start dark:text-gray-400'>
|
<div className='text-gray-100 mb-2 hover:scale-105 transform duration-200 flex justify-start'>
|
||||||
{siteConfig('BIO')}
|
{siteConfig('BIO')}
|
||||||
</div>
|
</div>
|
||||||
<SocialButton />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import CONFIG from '../config'
|
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到网页顶部
|
* 跳转到网页顶部
|
||||||
@@ -10,18 +10,23 @@ import { siteConfig } from '@/lib/config'
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const JumpToTopButton = ({ showPercent = false, percent, className }) => {
|
const JumpToTopButton = ({ showPercent = false, percent, className }) => {
|
||||||
if (!siteConfig('MEDIUM_WIDGET_TO_TOP', null, CONFIG)) {
|
if (!siteConfig('MAGZINE_WIDGET_TO_TOP', null, CONFIG)) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="jump-to-top"
|
id='jump-to-top'
|
||||||
data-aos="fade-up"
|
data-aos='fade-up'
|
||||||
data-aos-duration="300"
|
data-aos-duration='300'
|
||||||
data-aos-once="false"
|
data-aos-once='false'
|
||||||
data-aos-anchor-placement="top-center"
|
data-aos-anchor-placement='top-center'
|
||||||
className='fixed xl:right-80 right-2 mr-10 bottom-24 z-20'>
|
className='fixed xl:right-80 right-2 mr-10 bottom-24 z-20'>
|
||||||
<i className='fas fa-chevron-up cursor-pointer p-2 rounded-full border bg-white dark:bg-hexo-black-gray' onClick={() => { window.scrollTo({ top: 0, behavior: 'smooth' }) }} />
|
<i
|
||||||
|
className='fas fa-chevron-up cursor-pointer p-2 rounded-full border bg-white dark:bg-hexo-black-gray'
|
||||||
|
onClick={() => {
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ export default function LogoBar(props) {
|
|||||||
const { siteInfo } = props
|
const { siteInfo } = props
|
||||||
return (
|
return (
|
||||||
<div id='top-wrapper' className='w-full flex items-center '>
|
<div id='top-wrapper' className='w-full flex items-center '>
|
||||||
<Link href='/' className='flex text-md md:text-xl dark:text-gray-200'>
|
<Link
|
||||||
|
href='/'
|
||||||
|
className='flex text-md font-semibold md:text-xl hover:bg-black hover:text-white p-2 rounded-xl duration-200 dark:text-gray-200'>
|
||||||
{/* <LazyImage
|
{/* <LazyImage
|
||||||
src={siteInfo?.icon}
|
src={siteInfo?.icon}
|
||||||
width={24}
|
width={24}
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ export const MenuBarMobile = props => {
|
|||||||
{
|
{
|
||||||
name: locale.COMMON.CATEGORY,
|
name: locale.COMMON.CATEGORY,
|
||||||
href: '/category',
|
href: '/category',
|
||||||
show: siteConfig('MEDIUM_MENU_CATEGORY', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_CATEGORY', null, CONFIG)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: locale.COMMON.TAGS,
|
name: locale.COMMON.TAGS,
|
||||||
href: '/tag',
|
href: '/tag',
|
||||||
show: siteConfig('MEDIUM_MENU_TAG', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_TAG', null, CONFIG)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: locale.NAV.ARCHIVE,
|
name: locale.NAV.ARCHIVE,
|
||||||
href: '/archive',
|
href: '/archive',
|
||||||
show: siteConfig('MEDIUM_MENU_ARCHIVE', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_ARCHIVE', null, CONFIG)
|
||||||
}
|
}
|
||||||
// { name: locale.NAV.SEARCH, href: '/search', show: siteConfig('MENU_SEARCH', null, CONFIG) }
|
// { name: locale.NAV.SEARCH, href: '/search', show: siteConfig('MENU_SEARCH', null, CONFIG) }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -16,22 +16,22 @@ export const MenuItemDrop = ({ link }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className='cursor-pointer list-none items-center flex mx-2'
|
className='cursor-pointer list-none items-center h-full'
|
||||||
onMouseOver={() => changeShow(true)}
|
onMouseOver={() => changeShow(true)}
|
||||||
onMouseOut={() => changeShow(false)}>
|
onMouseOut={() => changeShow(false)}>
|
||||||
{hasSubMenu && (
|
{hasSubMenu && (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'px-3 h-full whitespace-nowrap duration-300 text-sm justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
'h-full whitespace-nowrap duration-300 text-md justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
||||||
(selected
|
(selected
|
||||||
? 'bg-gray-600 text-white hover:text-white'
|
? 'bg-gray-600 text-white hover:text-white'
|
||||||
: 'hover:text-gray-600')
|
: 'hover:text-gray-600')
|
||||||
}>
|
}>
|
||||||
<div>
|
<div className='items-center flex gap-x-1'>
|
||||||
{link?.icon && <i className={link?.icon} />} {link?.name}
|
{link?.icon && <i className={link?.icon} />} {link?.name}
|
||||||
{hasSubMenu && (
|
{hasSubMenu && (
|
||||||
<i
|
<i
|
||||||
className={`px-2 fas fa-chevron-down duration-500 transition-all ${show ? ' rotate-180' : ''}`}></i>
|
className={`px-1 fas fa-chevron-down duration-500 transition-all ${show ? ' rotate-180' : ''}`}></i>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +40,7 @@ export const MenuItemDrop = ({ link }) => {
|
|||||||
{!hasSubMenu && (
|
{!hasSubMenu && (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'px-3 h-full whitespace-nowrap duration-300 text-sm justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
'px-3 gap-x-1 h-full whitespace-nowrap duration-300 text-sm justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
||||||
(selected
|
(selected
|
||||||
? 'bg-gray-600 text-white hover:text-white'
|
? 'bg-gray-600 text-white hover:text-white'
|
||||||
: 'hover:text-gray-600')
|
: 'hover:text-gray-600')
|
||||||
@@ -54,14 +54,14 @@ export const MenuItemDrop = ({ link }) => {
|
|||||||
{/* 子菜单 */}
|
{/* 子菜单 */}
|
||||||
{hasSubMenu && (
|
{hasSubMenu && (
|
||||||
<ul
|
<ul
|
||||||
className={`${show ? 'visible opacity-100 top-12 ' : 'invisible opacity-0 top-10 '} border-gray-100 bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 absolute block drop-shadow-lg `}>
|
className={`${show ? 'visible opacity-100 top-14 ' : 'invisible opacity-0 top-10 '} absolute border bg-white dark:bg-black dark:border-gray-800 transition-all duration-300 z-20 block rounded-lg drop-shadow-lg p-4 `}>
|
||||||
{link?.subMenus?.map(sLink => {
|
{link?.subMenus?.map(sLink => {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={sLink.id}
|
key={sLink.id}
|
||||||
className='not:last-child:border-b-0 border-b text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
className='text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 dark:border-gray-800 py-3 pr-6 pl-3'>
|
||||||
<Link href={sLink.href} target={link?.target}>
|
<Link href={sLink.href} target={link?.target}>
|
||||||
<span className='text-xs font-extralight'>
|
<span className='text-sm hover:underline'>
|
||||||
{link?.icon && <i className={sLink?.icon}> </i>}
|
{link?.icon && <i className={sLink?.icon}> </i>}
|
||||||
{sLink.title}
|
{sLink.title}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import CONFIG from '../config'
|
|||||||
import CategoryItem from './CategoryItem'
|
import CategoryItem from './CategoryItem'
|
||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
|
|
||||||
const BlogPostCard = ({ post, showSummary }) => {
|
const PostItemCard = ({ post, showSummary }) => {
|
||||||
const showPreview =
|
const showPreview =
|
||||||
siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
siteConfig('MAGZINE_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -29,7 +29,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
'cursor-pointer font-bold hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-gray-500 dark:hover:text-gray-400'
|
'cursor-pointer font-bold hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-gray-500 dark:hover:text-gray-400'
|
||||||
}>
|
}>
|
||||||
<h2>
|
<h2>
|
||||||
{siteConfig('MEDIUM_POST_LIST_COVER', null, CONFIG) && (
|
{siteConfig('MAGZINE_POST_LIST_COVER', null, CONFIG) && (
|
||||||
<div className='w-full max-h-96 object-cover overflow-hidden mb-2'>
|
<div className='w-full max-h-96 object-cover overflow-hidden mb-2'>
|
||||||
<LazyImage
|
<LazyImage
|
||||||
src={post.pageCoverThumbnail}
|
src={post.pageCoverThumbnail}
|
||||||
@@ -50,10 +50,10 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
'flex mt-2 items-center justify-start flex-wrap space-x-3 text-gray-400'
|
'flex mt-2 items-center justify-start flex-wrap space-x-3 text-gray-400'
|
||||||
}>
|
}>
|
||||||
<div className='text-sm py-1'>{post.date?.start_date}</div>
|
<div className='text-sm py-1'>{post.date?.start_date}</div>
|
||||||
{siteConfig('MEDIUM_POST_LIST_CATEGORY', null, CONFIG) && (
|
{siteConfig('MAGZINE_POST_LIST_CATEGORY', null, CONFIG) && (
|
||||||
<CategoryItem category={post.category} />
|
<CategoryItem category={post.category} />
|
||||||
)}
|
)}
|
||||||
{siteConfig('MEDIUM_POST_LIST_TAG', null, CONFIG) &&
|
{siteConfig('MAGZINE_POST_LIST_TAG', null, CONFIG) &&
|
||||||
post?.tagItems?.map(tag => (
|
post?.tagItems?.map(tag => (
|
||||||
<TagItemMini key={tag.name} tag={tag} />
|
<TagItemMini key={tag.name} tag={tag} />
|
||||||
))}
|
))}
|
||||||
@@ -63,7 +63,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
<div className='flex'></div>
|
<div className='flex'></div>
|
||||||
|
|
||||||
{(!showPreview || showSummary) && (
|
{(!showPreview || showSummary) && (
|
||||||
<main className='my-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7'>
|
<main className='my-4 text-gray-700 dark:text-gray-300 text-sm leading-7'>
|
||||||
{post.summary}
|
{post.summary}
|
||||||
</main>
|
</main>
|
||||||
)}
|
)}
|
||||||
@@ -89,4 +89,4 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostCard
|
export default PostItemCard
|
||||||
45
themes/magzine/components/PostItemCardSimple.js
Normal file
45
themes/magzine/components/PostItemCardSimple.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import NotionIcon from '@/components/NotionIcon'
|
||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
import CategoryItem from './CategoryItem'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不带图片
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const PostItemCardSimple = ({ post, showSummary }) => {
|
||||||
|
const showPreview =
|
||||||
|
siteConfig('MAGZINE_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={post.id}
|
||||||
|
className='mb-6 max-w-7xl border-t mr-8 py-2 gap-y-4 flex flex-col dark:border-gray-800 '>
|
||||||
|
<div className='flex mr-2 items-center'>
|
||||||
|
{siteConfig('MAGZINE_POST_LIST_CATEGORY', null, CONFIG) && (
|
||||||
|
<CategoryItem category={post.category} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 文章标题 */}
|
||||||
|
<Link
|
||||||
|
href={post?.href}
|
||||||
|
passHref
|
||||||
|
className={
|
||||||
|
'cursor-pointer hover:underline text-lg leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
||||||
|
}>
|
||||||
|
<h2>
|
||||||
|
{siteConfig('POST_TITLE_ICON') && <NotionIcon icon={post.pageIcon} />}
|
||||||
|
{post.title}
|
||||||
|
</h2>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className='text-sm py-2 text-gray-700'>{post.date?.start_date}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostItemCardSimple
|
||||||
@@ -13,9 +13,9 @@ import TagItemMini from './TagItemMini'
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const BlogPostCardTop = ({ post, showSummary }) => {
|
const PostItemCardTop = ({ post, showSummary }) => {
|
||||||
const showPreview =
|
const showPreview =
|
||||||
siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
siteConfig('MAGZINE_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -26,12 +26,12 @@ const BlogPostCardTop = ({ post, showSummary }) => {
|
|||||||
data-aos-anchor-placement='top-bottom'
|
data-aos-anchor-placement='top-bottom'
|
||||||
className='mb-6 max-w-7xl '>
|
className='mb-6 max-w-7xl '>
|
||||||
<div className='flex flex-col w-full'>
|
<div className='flex flex-col w-full'>
|
||||||
{siteConfig('MEDIUM_POST_LIST_COVER', null, CONFIG) && (
|
{siteConfig('MAGZINE_POST_LIST_COVER', null, CONFIG) && (
|
||||||
<Link
|
<Link
|
||||||
href={post?.href}
|
href={post?.href}
|
||||||
passHref
|
passHref
|
||||||
className={
|
className={
|
||||||
'cursor-pointer hover:underline font-bold text-3xl leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
'cursor-pointer hover:underline text-4xl leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
||||||
}>
|
}>
|
||||||
<div className='w-full max-h-80 object-cover overflow-hidden mb-2'>
|
<div className='w-full max-h-80 object-cover overflow-hidden mb-2'>
|
||||||
<LazyImage
|
<LazyImage
|
||||||
@@ -43,15 +43,15 @@ const BlogPostCardTop = ({ post, showSummary }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className='flex py-2 items-center'>
|
<div className='flex py-2 mr-2 items-center'>
|
||||||
{siteConfig('MEDIUM_POST_LIST_CATEGORY', null, CONFIG) && (
|
{siteConfig('MAGZINE_POST_LIST_CATEGORY', null, CONFIG) && (
|
||||||
<CategoryItem category={post.category} />
|
<CategoryItem category={post.category} />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'flex items-center justify-start flex-wrap space-x-3 text-gray-400'
|
'flex items-center justify-start flex-wrap space-x-3 text-gray-400'
|
||||||
}>
|
}>
|
||||||
{siteConfig('MEDIUM_POST_LIST_TAG', null, CONFIG) &&
|
{siteConfig('MAGZINE_POST_LIST_TAG', null, CONFIG) &&
|
||||||
post?.tagItems?.map(tag => (
|
post?.tagItems?.map(tag => (
|
||||||
<TagItemMini key={tag.name} tag={tag} />
|
<TagItemMini key={tag.name} tag={tag} />
|
||||||
))}
|
))}
|
||||||
@@ -62,9 +62,9 @@ const BlogPostCardTop = ({ post, showSummary }) => {
|
|||||||
href={post?.href}
|
href={post?.href}
|
||||||
passHref
|
passHref
|
||||||
className={
|
className={
|
||||||
'cursor-pointer hover:underline font-bold text-3xl leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
'cursor-pointer hover:underline leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
||||||
}>
|
}>
|
||||||
<h2 className='text-2xl'>
|
<h2 className='text-4xl'>
|
||||||
{siteConfig('POST_TITLE_ICON') && (
|
{siteConfig('POST_TITLE_ICON') && (
|
||||||
<NotionIcon icon={post.pageIcon} />
|
<NotionIcon icon={post.pageIcon} />
|
||||||
)}
|
)}
|
||||||
@@ -75,7 +75,7 @@ const BlogPostCardTop = ({ post, showSummary }) => {
|
|||||||
<div className='flex'></div>
|
<div className='flex'></div>
|
||||||
|
|
||||||
{(!showPreview || showSummary) && (
|
{(!showPreview || showSummary) && (
|
||||||
<main className='my-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7'>
|
<main className='my-4 text-gray-900 dark:text-gray-300 text-lg leading-7'>
|
||||||
{post.summary}
|
{post.summary}
|
||||||
</main>
|
</main>
|
||||||
)}
|
)}
|
||||||
@@ -103,4 +103,4 @@ const BlogPostCardTop = ({ post, showSummary }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostCardTop
|
export default PostItemCardTop
|
||||||
@@ -8,21 +8,24 @@ import CONFIG from '../config'
|
|||||||
import CategoryItem from './CategoryItem'
|
import CategoryItem from './CategoryItem'
|
||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
|
|
||||||
const BlogPostCardHorizontal = ({ post, showSummary }) => {
|
/**
|
||||||
|
* 水平左右布局的博客卡片
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const PostItemCardWide = ({ post, showSummary }) => {
|
||||||
const showPreview =
|
const showPreview =
|
||||||
siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
siteConfig('MAGZINE_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
return (
|
return (
|
||||||
<div
|
<div key={post.id} className='flex justify-between space-x-6 mb-6 '>
|
||||||
key={post.id}
|
|
||||||
className='flex justify-between space-x-6 mb-6 border-top border-gray-200'>
|
|
||||||
{/* 卡牌左侧 */}
|
{/* 卡牌左侧 */}
|
||||||
<div className='h-40 w-96'>
|
<div className='h-40 w-96'>
|
||||||
<Link
|
<Link
|
||||||
href={post?.href}
|
href={post?.href}
|
||||||
passHref
|
passHref
|
||||||
className={
|
className={
|
||||||
' cursor-pointer font-bold hover:underline text-xl leading-tight text-gray-700 dark:text-gray-300 hover:text-gray-500 dark:hover:text-gray-400'
|
' cursor-pointer font-semibold hover:underline text-xl leading-tight dark:text-gray-300 dark:hover:text-gray-400'
|
||||||
}>
|
}>
|
||||||
<h3 className='max-w-80 break-words'>
|
<h3 className='max-w-80 break-words'>
|
||||||
{siteConfig('POST_TITLE_ICON') && (
|
{siteConfig('POST_TITLE_ICON') && (
|
||||||
@@ -32,22 +35,8 @@ const BlogPostCardHorizontal = ({ post, showSummary }) => {
|
|||||||
</h3>
|
</h3>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div
|
|
||||||
className={
|
|
||||||
'flex mt-2 items-center justify-start flex-wrap space-x-3 text-gray-400'
|
|
||||||
}>
|
|
||||||
<div className='text-sm py-1'>{post.date?.start_date}</div>
|
|
||||||
{siteConfig('MEDIUM_POST_LIST_CATEGORY', null, CONFIG) && (
|
|
||||||
<CategoryItem category={post.category} />
|
|
||||||
)}
|
|
||||||
{siteConfig('MEDIUM_POST_LIST_TAG', null, CONFIG) &&
|
|
||||||
post?.tagItems?.map(tag => (
|
|
||||||
<TagItemMini key={tag.name} tag={tag} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{(!showPreview || showSummary) && (
|
{(!showPreview || showSummary) && (
|
||||||
<main className='my-4 line-clamp-2 text-gray-700 dark:text-gray-300 text-sm font-light leading-7'>
|
<main className='my-4 line-clamp-2 text-gray-900 dark:text-gray-300 text-sm'>
|
||||||
{post.summary}
|
{post.summary}
|
||||||
</main>
|
</main>
|
||||||
)}
|
)}
|
||||||
@@ -68,6 +57,20 @@ const BlogPostCardHorizontal = ({ post, showSummary }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
'flex mt-2 items-center justify-start flex-wrap space-x-3 text-gray-400'
|
||||||
|
}>
|
||||||
|
{siteConfig('MAGZINE_POST_LIST_CATEGORY', null, CONFIG) && (
|
||||||
|
<CategoryItem category={post.category} />
|
||||||
|
)}
|
||||||
|
{siteConfig('MAGZINE_POST_LIST_TAG', null, CONFIG) &&
|
||||||
|
post?.tagItems?.map(tag => (
|
||||||
|
<TagItemMini key={tag.name} tag={tag} />
|
||||||
|
))}
|
||||||
|
<div className='text-sm py-1'>{post.date?.start_date}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 卡牌右侧图片 */}
|
{/* 卡牌右侧图片 */}
|
||||||
@@ -82,4 +85,4 @@ const BlogPostCardHorizontal = ({ post, showSummary }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostCardHorizontal
|
export default PostItemCardWide
|
||||||
19
themes/magzine/components/PostListEmpty.js
Normal file
19
themes/magzine/components/PostListEmpty.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空白博客 列表
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const PostListEmpty = ({ currentSearch }) => {
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
return (
|
||||||
|
<div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
|
||||||
|
<p className='text-gray-500 dark:text-gray-300'>
|
||||||
|
{locale.COMMON.NO_RESULTS_FOUND}{' '}
|
||||||
|
{currentSearch && <div>{currentSearch}</div>}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default PostListEmpty
|
||||||
38
themes/magzine/components/PostListHorizontal.js
Normal file
38
themes/magzine/components/PostListHorizontal.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
import PostItemCardSimple from './PostItemCardSimple'
|
||||||
|
import PostListEmpty from './PostListEmpty'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 博文水平列表
|
||||||
|
* 含封面
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const PostListHorizontal = ({ title, href, posts }) => {
|
||||||
|
if (!posts || posts.length === 0) {
|
||||||
|
return <PostListEmpty />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full py-10 bg-[#F6F6F1]'>
|
||||||
|
<div className='max-w-7xl w-full mx-auto'>
|
||||||
|
{/* 标题 */}
|
||||||
|
<div className='flex justify-between items-center py-6'>
|
||||||
|
<h3 className='text-2xl'>{title}</h3>
|
||||||
|
<Link className='text-lg underline' href={href}>
|
||||||
|
<span>查看全部</span>
|
||||||
|
<i className='ml-2 fas fa-arrow-right' />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
{/* 列表 */}
|
||||||
|
<ul className='flex'>
|
||||||
|
{posts?.map(p => {
|
||||||
|
return <PostItemCardSimple key={p.id} post={p} />
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostListHorizontal
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import BlogPostCard from './BlogPostCard'
|
|
||||||
import BlogPostListEmpty from './BlogPostListEmpty'
|
|
||||||
import PaginationSimple from './PaginationSimple'
|
import PaginationSimple from './PaginationSimple'
|
||||||
|
import PostItemCard from './PostItemCard'
|
||||||
|
import PostListEmpty from './PostListEmpty'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文章列表分页表格
|
* 文章列表分页表格
|
||||||
@@ -12,13 +12,13 @@ import PaginationSimple from './PaginationSimple'
|
|||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
const PostListPage = ({ page = 1, posts = [], postCount }) => {
|
||||||
const { NOTION_CONFIG } = useGlobal()
|
const { NOTION_CONFIG } = useGlobal()
|
||||||
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
||||||
const totalPage = Math.ceil(postCount / POSTS_PER_PAGE)
|
const totalPage = Math.ceil(postCount / POSTS_PER_PAGE)
|
||||||
|
|
||||||
if (!posts || posts.length === 0) {
|
if (!posts || posts.length === 0) {
|
||||||
return <BlogPostListEmpty />
|
return <PostListEmpty />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -26,7 +26,7 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
|||||||
<div id='posts-wrapper'>
|
<div id='posts-wrapper'>
|
||||||
{/* 文章列表 */}
|
{/* 文章列表 */}
|
||||||
{posts?.map(post => (
|
{posts?.map(post => (
|
||||||
<BlogPostCard key={post.id} post={post} />
|
<PostItemCard key={post.id} post={post} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<PaginationSimple page={page} totalPage={totalPage} />
|
<PaginationSimple page={page} totalPage={totalPage} />
|
||||||
@@ -34,4 +34,4 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostListPage
|
export default PostListPage
|
||||||
@@ -3,8 +3,8 @@ import { useGlobal } from '@/lib/global'
|
|||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import BlogPostCard from './BlogPostCard'
|
import PostItemCard from './PostItemCard'
|
||||||
import BlogPostListEmpty from './BlogPostListEmpty'
|
import PostListEmpty from './PostListEmpty'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客列表滚动分页
|
* 博客列表滚动分页
|
||||||
@@ -13,7 +13,7 @@ import BlogPostListEmpty from './BlogPostListEmpty'
|
|||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const BlogPostListScroll = ({ posts = [], currentSearch }) => {
|
const PostListScroll = ({ posts = [], currentSearch }) => {
|
||||||
const { NOTION_CONFIG } = useGlobal()
|
const { NOTION_CONFIG } = useGlobal()
|
||||||
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
||||||
const [page, updatePage] = useState(1)
|
const [page, updatePage] = useState(1)
|
||||||
@@ -67,14 +67,14 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => {
|
|||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
if (!postsToShow || postsToShow.length === 0) {
|
if (!postsToShow || postsToShow.length === 0) {
|
||||||
return <BlogPostListEmpty currentSearch={currentSearch} />
|
return <PostListEmpty currentSearch={currentSearch} />
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div id='posts-wrapper' ref={targetRef} className='w-full'>
|
<div id='posts-wrapper' ref={targetRef} className='w-full'>
|
||||||
{/* 文章列表 */}
|
{/* 文章列表 */}
|
||||||
<div className='space-y-1 lg:space-y-4'>
|
<div className='space-y-1 lg:space-y-4'>
|
||||||
{postsToShow?.map(post => (
|
{postsToShow?.map(post => (
|
||||||
<BlogPostCard key={post.id} post={post} showSummary={true} />
|
<PostItemCard key={post.id} post={post} showSummary={true} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -104,4 +104,4 @@ const getPostByPage = function (page, totalPosts, POSTS_PER_PAGE) {
|
|||||||
return totalPosts.slice(0, POSTS_PER_PAGE * page)
|
return totalPosts.slice(0, POSTS_PER_PAGE * page)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostListScroll
|
export default PostListScroll
|
||||||
37
themes/magzine/components/PostListSimpleHorizontal.js
Normal file
37
themes/magzine/components/PostListSimpleHorizontal.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
import PostItemCardSimple from './PostItemCardSimple'
|
||||||
|
import PostListEmpty from './PostListEmpty'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 博文水平列表;不带封面图
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
const PostSimpleListHorizontal = ({ title, href, posts }) => {
|
||||||
|
if (!posts || posts.length === 0) {
|
||||||
|
return <PostListEmpty />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full py-10 bg-[#F6F6F1]'>
|
||||||
|
<div className='max-w-7xl w-full mx-auto'>
|
||||||
|
{/* 标题 */}
|
||||||
|
<div className='flex justify-between items-center py-6'>
|
||||||
|
<h3 className='text-2xl'>{title}</h3>
|
||||||
|
<Link className='text-lg underline' href={href}>
|
||||||
|
<span>查看全部</span>
|
||||||
|
<i className='ml-2 fas fa-arrow-right' />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
{/* 列表 */}
|
||||||
|
<ul className='flex'>
|
||||||
|
{posts?.map(p => {
|
||||||
|
return <PostItemCardSimple key={p.id} post={p} />
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostSimpleListHorizontal
|
||||||
@@ -5,7 +5,7 @@ import { useGlobal } from '@/lib/global'
|
|||||||
* @param {*} props
|
* @param {*} props
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export default function BlogPostBar(props) {
|
export default function PostListSlotBar(props) {
|
||||||
const { tag, category } = props
|
const { tag, category } = props
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
@@ -21,14 +21,15 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
|
|||||||
setLoadingState(true)
|
setLoadingState(true)
|
||||||
location.href = '/search/' + key
|
location.href = '/search/' + key
|
||||||
} else {
|
} else {
|
||||||
router.push({ pathname: '/' }).then(r => {
|
router.push({ pathname: '/' }).then(r => {})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const handleKeyUp = (e) => {
|
const handleKeyUp = e => {
|
||||||
if (e.keyCode === 13) { // 回车
|
if (e.keyCode === 13) {
|
||||||
|
// 回车
|
||||||
handleSearch(searchInputRef.current.value)
|
handleSearch(searchInputRef.current.value)
|
||||||
} else if (e.keyCode === 27) { // ESC
|
} else if (e.keyCode === 27) {
|
||||||
|
// ESC
|
||||||
cleanSearch()
|
cleanSearch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [showClean, setShowClean] = useState(false)
|
const [showClean, setShowClean] = useState(false)
|
||||||
const updateSearchKey = (val) => {
|
const updateSearchKey = val => {
|
||||||
if (lock) {
|
if (lock) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -49,38 +50,48 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
|
|||||||
setShowClean(false)
|
setShowClean(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function lockSearchInput () {
|
function lockSearchInput() {
|
||||||
lock = true
|
lock = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function unLockSearchInput () {
|
function unLockSearchInput() {
|
||||||
lock = false
|
lock = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className={'flex w-full bg-gray-100 ' + className}>
|
return (
|
||||||
<input
|
<div className={'flex w-full bg-gray-100 ' + className}>
|
||||||
ref={searchInputRef}
|
<input
|
||||||
type='text'
|
ref={searchInputRef}
|
||||||
className={'outline-none w-full text-sm pl-2 transition focus:shadow-lg font-light leading-10 text-black bg-gray-100 dark:bg-gray-900 dark:text-white'}
|
type='text'
|
||||||
onKeyUp={handleKeyUp}
|
className={
|
||||||
onCompositionStart={lockSearchInput}
|
'outline-none w-full text-sm pl-2 transition focus:shadow-lg leading-10 text-black bg-gray-100 dark:bg-gray-900 dark:text-white'
|
||||||
onCompositionUpdate={lockSearchInput}
|
}
|
||||||
onCompositionEnd={unLockSearchInput}
|
onKeyUp={handleKeyUp}
|
||||||
onChange={e => updateSearchKey(e.target.value)}
|
onCompositionStart={lockSearchInput}
|
||||||
defaultValue={currentSearch}
|
onCompositionUpdate={lockSearchInput}
|
||||||
/>
|
onCompositionEnd={unLockSearchInput}
|
||||||
|
onChange={e => updateSearchKey(e.target.value)}
|
||||||
|
defaultValue={currentSearch}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className='-ml-8 cursor-pointer float-right items-center justify-center py-2'
|
<div
|
||||||
onClick={handleSearch}>
|
className='-ml-8 cursor-pointer float-right items-center justify-center py-2'
|
||||||
<i className={`hover:text-black transform duration-200 text-gray-500 dark:hover:text-gray-300 cursor-pointer fas ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'} `} />
|
onClick={handleSearch}>
|
||||||
</div>
|
<i
|
||||||
|
className={`hover:text-black transform duration-200 text-gray-500 dark:hover:text-gray-300 cursor-pointer fas ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'} `}
|
||||||
{(showClean &&
|
/>
|
||||||
<div className='-ml-12 cursor-pointer float-right items-center justify-center py-2'>
|
|
||||||
<i className='fas fa-times hover:text-black transform duration-200 text-gray-400 cursor-pointer dark:hover:text-gray-300' onClick={cleanSearch} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showClean && (
|
||||||
|
<div className='-ml-12 cursor-pointer float-right items-center justify-center py-2'>
|
||||||
|
<i
|
||||||
|
className='fas fa-times hover:text-black transform duration-200 text-gray-400 cursor-pointer dark:hover:text-gray-300'
|
||||||
|
onClick={cleanSearch}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SearchInput
|
export default SearchInput
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ const TagItemMini = ({ tag, selected = false }) => {
|
|||||||
passHref
|
passHref
|
||||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||||
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white
|
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white
|
||||||
${selected
|
${
|
||||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-gray-900'
|
selected
|
||||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}` }>
|
? 'text-white dark:text-gray-300 dark:hover:bg-gray-900'
|
||||||
|
: `text-gray-900 hover:shadow-xl dark:border-gray-400 dark:bg-gray-800`
|
||||||
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fas fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
}`}>
|
||||||
|
<div className=' dark:text-gray-400'>
|
||||||
|
{/* {selected && <i className='mr-1 fas fa-tag'/>} */}#
|
||||||
|
{tag.name + (tag.count ? `(${tag.count})` : '')}{' '}
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,25 +24,25 @@ export default function TopNavBar(props) {
|
|||||||
icon: 'fas fa-th',
|
icon: 'fas fa-th',
|
||||||
name: locale.COMMON.CATEGORY,
|
name: locale.COMMON.CATEGORY,
|
||||||
href: '/category',
|
href: '/category',
|
||||||
show: siteConfig('MEDIUM_MENU_CATEGORY', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_CATEGORY', null, CONFIG)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'fas fa-tag',
|
icon: 'fas fa-tag',
|
||||||
name: locale.COMMON.TAGS,
|
name: locale.COMMON.TAGS,
|
||||||
href: '/tag',
|
href: '/tag',
|
||||||
show: siteConfig('MEDIUM_MENU_TAG', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_TAG', null, CONFIG)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'fas fa-archive',
|
icon: 'fas fa-archive',
|
||||||
name: locale.NAV.ARCHIVE,
|
name: locale.NAV.ARCHIVE,
|
||||||
href: '/archive',
|
href: '/archive',
|
||||||
show: siteConfig('MEDIUM_MENU_ARCHIVE', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_ARCHIVE', null, CONFIG)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'fas fa-search',
|
icon: 'fas fa-search',
|
||||||
name: locale.NAV.SEARCH,
|
name: locale.NAV.SEARCH,
|
||||||
href: '/search',
|
href: '/search',
|
||||||
show: siteConfig('MEDIUM_MENU_SEARCH', null, CONFIG)
|
show: siteConfig('MAGZINE_MENU_SEARCH', null, CONFIG)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,35 @@
|
|||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
|
// 首屏信息栏按钮文字
|
||||||
|
MAGZINE_HOME_BANNER_ENABLE: true, // 首屏右上角的宣传位
|
||||||
|
MAGZINE_HOME_BUTTON: true,
|
||||||
|
MAGZINE_HOME_BUTTON_URL: '/about',
|
||||||
|
MAGZINE_HOME_BUTTON_TEXT: '了解更多',
|
||||||
|
|
||||||
|
MAGZINE_HOME_TITLE: '立即开创您的在线业务。完全免费。',
|
||||||
|
MAGZINE_HOME_DESCRIPTION:
|
||||||
|
'借助NotionNext,获得助您开创、经营和扩展业务所需的全部工具和帮助。',
|
||||||
|
MAGZINE_HOME_TIPS: 'AI时代来临,这是属于超级个体的狂欢盛宴!',
|
||||||
|
|
||||||
// Style
|
// Style
|
||||||
MEDIUM_RIGHT_PANEL_DARK: process.env.NEXT_PUBLIC_MEDIUM_RIGHT_DARK || false, // 右侧面板深色模式
|
MAGZINE_RIGHT_PANEL_DARK: process.env.NEXT_PUBLIC_MAGZINE_RIGHT_DARK || false, // 右侧面板深色模式
|
||||||
|
|
||||||
MEDIUM_POST_LIST_COVER: true, // 文章列表显示图片封面
|
MAGZINE_POST_LIST_COVER: true, // 文章列表显示图片封面
|
||||||
MEDIUM_POST_LIST_PREVIEW: true, // 列表显示文章预览
|
MAGZINE_POST_LIST_PREVIEW: true, // 列表显示文章预览
|
||||||
MEDIUM_POST_LIST_CATEGORY: true, // 列表显示文章分类
|
MAGZINE_POST_LIST_CATEGORY: true, // 列表显示文章分类
|
||||||
MEDIUM_POST_LIST_TAG: true, // 列表显示文章标签
|
MAGZINE_POST_LIST_TAG: true, // 列表显示文章标签
|
||||||
|
|
||||||
MEDIUM_POST_DETAIL_CATEGORY: true, // 文章显示分类
|
MAGZINE_POST_DETAIL_CATEGORY: true, // 文章显示分类
|
||||||
MEDIUM_POST_DETAIL_TAG: true, // 文章显示标签
|
MAGZINE_POST_DETAIL_TAG: true, // 文章显示标签
|
||||||
|
|
||||||
// 菜单
|
// 菜单
|
||||||
MEDIUM_MENU_CATEGORY: true, // 显示分类
|
MAGZINE_MENU_CATEGORY: true, // 显示分类
|
||||||
MEDIUM_MENU_TAG: true, // 显示标签
|
MAGZINE_MENU_TAG: true, // 显示标签
|
||||||
MEDIUM_MENU_ARCHIVE: true, // 显示归档
|
MAGZINE_MENU_ARCHIVE: true, // 显示归档
|
||||||
MEDIUM_MENU_SEARCH: true, // 显示搜索
|
MAGZINE_MENU_SEARCH: true, // 显示搜索
|
||||||
|
|
||||||
// Widget
|
// Widget
|
||||||
MEDIUM_WIDGET_REVOLVER_MAPS: process.env.NEXT_PUBLIC_WIDGET_REVOLVER_MAPS || 'false', // 地图插件
|
MAGZINE_WIDGET_REVOLVER_MAPS:
|
||||||
MEDIUM_WIDGET_TO_TOP: true // 跳回顶部
|
process.env.NEXT_PUBLIC_WIDGET_REVOLVER_MAPS || 'false', // 地图插件
|
||||||
|
MAGZINE_WIDGET_TO_TOP: true // 跳回顶部
|
||||||
}
|
}
|
||||||
export default CONFIG
|
export default CONFIG
|
||||||
|
|||||||
@@ -8,21 +8,20 @@ import { isBrowser } from '@/lib/utils'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { createContext, useContext, useEffect, useState } from 'react'
|
import { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import Announcement from './components/Announcement'
|
import ArchiveItem from './components/ArchiveItem'
|
||||||
import ArticleAround from './components/ArticleAround'
|
import ArticleAround from './components/ArticleAround'
|
||||||
import ArticleInfo from './components/ArticleInfo'
|
import ArticleInfo from './components/ArticleInfo'
|
||||||
import { ArticleLock } from './components/ArticleLock'
|
import { ArticleLock } from './components/ArticleLock'
|
||||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
|
||||||
import BlogPostCardHorizontal from './components/BlogPostCardHorizontal'
|
|
||||||
import BlogPostCardTop from './components/BlogPostCardTop'
|
|
||||||
import BlogPostListPage from './components/BlogPostListPage'
|
|
||||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
|
||||||
import Catalog from './components/Catalog'
|
import Catalog from './components/Catalog'
|
||||||
import CategoryGroup from './components/CategoryGroup'
|
import CategoryGroup from './components/CategoryGroup'
|
||||||
import CategoryItem from './components/CategoryItem'
|
import CategoryItem from './components/CategoryItem'
|
||||||
import Footer from './components/Footer'
|
import Footer from './components/Footer'
|
||||||
import Header from './components/Header'
|
import Header from './components/Header'
|
||||||
import InfoCard from './components/InfoCard'
|
import Hero from './components/Hero'
|
||||||
|
import PostListHorizontal from './components/PostListHorizontal'
|
||||||
|
import PostListPage from './components/PostListPage'
|
||||||
|
import PostListScroll from './components/PostListScroll'
|
||||||
|
import PostSimpleListHorizontal from './components/PostListSimpleHorizontal'
|
||||||
import SearchInput from './components/SearchInput'
|
import SearchInput from './components/SearchInput'
|
||||||
import TagGroups from './components/TagGroups'
|
import TagGroups from './components/TagGroups'
|
||||||
import TagItemMini from './components/TagItemMini'
|
import TagItemMini from './components/TagItemMini'
|
||||||
@@ -81,33 +80,72 @@ const LayoutBase = props => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const LayoutIndex = props => {
|
const LayoutIndex = props => {
|
||||||
const { posts, notice } = props
|
const { posts, allNavPages } = props
|
||||||
const top = posts[0]
|
// 最新文章 从第4个元素开始截取出4个
|
||||||
const post1 = posts[1]
|
const newPosts = posts.slice(3, 7)
|
||||||
const post2 = posts[2]
|
|
||||||
return (
|
|
||||||
<div className='container mx-auto max-w-7xl'>
|
|
||||||
{/* 首屏文章 */}
|
|
||||||
|
|
||||||
<div className='md:flex justify-between py-10 md:py-16'>
|
// 按分类将文章分组成文件夹
|
||||||
<div className='basis-1/2 mb-6'>
|
const categoryFolders = groupArticles(allNavPages.slice(8))
|
||||||
<BlogPostCardTop post={top} />
|
|
||||||
</div>
|
return (
|
||||||
<div className='px-10'>
|
<div className='py-10 md:py-18'>
|
||||||
<div className='flex justify-between px-4 w-full'>
|
{/* 首屏宣传区块 */}
|
||||||
<InfoCard {...props} />
|
<Hero posts={posts} />
|
||||||
<Announcement post={notice} />
|
|
||||||
</div>
|
{/* 最新文章区块 */}
|
||||||
{/* 两篇主要文章 */}
|
<PostSimpleListHorizontal
|
||||||
<div>
|
title='最新文章'
|
||||||
<BlogPostCardHorizontal post={post1} />
|
href='/archive'
|
||||||
<BlogPostCardHorizontal post={post2} />
|
posts={newPosts}
|
||||||
</div>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
{/* 不同的分类文章列表 */}
|
||||||
|
{categoryFolders?.map((categoryGroup, index) => {
|
||||||
|
if (
|
||||||
|
!categoryGroup ||
|
||||||
|
!categoryGroup.items ||
|
||||||
|
categoryGroup.items.length < 1
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PostListHorizontal
|
||||||
|
title={categoryGroup?.category}
|
||||||
|
href={`/category/${categoryGroup?.category}`}
|
||||||
|
posts={categoryGroup?.items}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
// 按照分类将文章分组成文件夹
|
||||||
|
function groupArticles(allPosts) {
|
||||||
|
if (!allPosts) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const groups = []
|
||||||
|
|
||||||
|
for (let i = 0; i < allPosts.length; i++) {
|
||||||
|
const item = allPosts[i]
|
||||||
|
const categoryName = item?.category ? item?.category : '' // 将 category 转换为字符串
|
||||||
|
|
||||||
|
let existingGroup = groups.find(group => group.category === categoryName) // 搜索同名的最后一个分组
|
||||||
|
|
||||||
|
if (existingGroup && existingGroup.category === categoryName) {
|
||||||
|
// 如果分组已存在,并且该分组中的文章数量小于4,添加文章
|
||||||
|
if (existingGroup.items.length < 4) {
|
||||||
|
existingGroup.items.push(item)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 新建分组,并添加当前文章
|
||||||
|
groups.push({ category: categoryName, items: [item] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客列表
|
* 博客列表
|
||||||
@@ -117,9 +155,9 @@ const LayoutPostList = props => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||||
<BlogPostListPage {...props} />
|
<PostListPage {...props} />
|
||||||
) : (
|
) : (
|
||||||
<BlogPostListScroll {...props} />
|
<PostListScroll {...props} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@@ -180,10 +218,10 @@ const LayoutSlug = props => {
|
|||||||
<ShareBar post={post} />
|
<ShareBar post={post} />
|
||||||
{/* 文章分类和标签信息 */}
|
{/* 文章分类和标签信息 */}
|
||||||
<div className='flex justify-between'>
|
<div className='flex justify-between'>
|
||||||
{siteConfig('MEDIUM_POST_DETAIL_CATEGORY', null, CONFIG) &&
|
{siteConfig('MAGZINE_POST_DETAIL_CATEGORY', null, CONFIG) &&
|
||||||
post?.category && <CategoryItem category={post?.category} />}
|
post?.category && <CategoryItem category={post?.category} />}
|
||||||
<div>
|
<div>
|
||||||
{siteConfig('MEDIUM_POST_DETAIL_TAG', null, CONFIG) &&
|
{siteConfig('MAGZINE_POST_DETAIL_TAG', null, CONFIG) &&
|
||||||
post?.tagItems?.map(tag => (
|
post?.tagItems?.map(tag => (
|
||||||
<TagItemMini key={tag.name} tag={tag} />
|
<TagItemMini key={tag.name} tag={tag} />
|
||||||
))}
|
))}
|
||||||
@@ -245,9 +283,9 @@ const LayoutSearch = props => {
|
|||||||
{currentSearch && (
|
{currentSearch && (
|
||||||
<div>
|
<div>
|
||||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||||
<BlogPostListPage {...props} />
|
<PostListPage {...props} />
|
||||||
) : (
|
) : (
|
||||||
<BlogPostListScroll {...props} />
|
<PostListScroll {...props} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -266,7 +304,7 @@ const LayoutArchive = props => {
|
|||||||
<>
|
<>
|
||||||
<div className='mb-10 pb-20 md:py-12 py-3 min-h-full'>
|
<div className='mb-10 pb-20 md:py-12 py-3 min-h-full'>
|
||||||
{Object.keys(archivePosts)?.map(archiveTitle => (
|
{Object.keys(archivePosts)?.map(archiveTitle => (
|
||||||
<BlogArchiveItem
|
<ArchiveItem
|
||||||
key={archiveTitle}
|
key={archiveTitle}
|
||||||
archiveTitle={archiveTitle}
|
archiveTitle={archiveTitle}
|
||||||
archivePosts={archivePosts}
|
archivePosts={archivePosts}
|
||||||
|
|||||||
Reference in New Issue
Block a user