mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
feature:
引入react-fontawesome,升级至v5.15; next/link补齐passHref; 替换img为next/Image,优化图片
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
- **页面渲染**: [React-notion-x](https://github.com/NotionX/react-notion-x)
|
||||
- **样式**: Tailwind CSS 和 `@tailwindcss/jit` compiler
|
||||
- **评论**: Gitalk,Cusdis,Utterances
|
||||
- **图标**:[fontawesome](https://fontawesome.com/v4.7/icons/?d=gallery)
|
||||
- **图标**:[fontawesome](https://fontawesome.com/v5.15/icons?d=gallery)
|
||||
|
||||
## 页面样式主题
|
||||
- 仿照 [fukasawa](https://andersnoren.se/themes/fukasawa) 分支-https://github.com/tangly1024/NotionNext/tree/theme-Fukasawa
|
||||
|
||||
@@ -2,32 +2,30 @@ import BLOG from '@/blog.config'
|
||||
import TagItemMini from '@/components/TagItemMini'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faFolderOpen } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const BlogPostCard = ({ post, tags }) => {
|
||||
return (
|
||||
<div key={post.id}
|
||||
className='animate__animated animate__fadeIn animate__faster xl:flex shadow-card border dark:border-gray-600 mb-6 w-full bg-white dark:bg-gray-800 dark:hover:bg-gray-700 overflow-hidden'>
|
||||
|
||||
{post.page_cover && post.page_cover.length > 1 && (
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`}>
|
||||
<img className='w-full max-h-72 xl:w-80 object-cover cursor-pointer transform hover:scale-110 duration-500'
|
||||
src={post.page_cover} alt={post.title} />
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<div className='px-4 py-4 w-full'>
|
||||
<div key={post.id} className='md:grid md:grid-cols-5 animate__animated animate__fadeIn animate__faster shadow-lg rounded border dark:border-gray-600 mb-6
|
||||
w-full bg-white dark:bg-gray-800 dark:hover:bg-gray-700'>
|
||||
<div className='w-full h-60 cursor-pointer transform col-span-2 border-r border-dashed'>
|
||||
<Image src={(post.page_cover && post.page_cover.length > 1) ? post.page_cover : BLOG.defaultImgCover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' />
|
||||
</div>
|
||||
|
||||
<div className='px-4 py-4 col-span-3'>
|
||||
<div>
|
||||
<Link href={`/category/${post.category}`}>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<span className='cursor-pointer dark:text-gray-200 text-gray-400 text-sm py-1.5 mr-1 hover:underline hover:text-blue-500 transform'>
|
||||
<i className='fa fa-folder-open-o mr-1' />{post.category}
|
||||
<FontAwesomeIcon icon={faFolderOpen} className=' mr-1' />{post.category}
|
||||
</span>
|
||||
</Link>
|
||||
<span className='mx-1 dark:text-gray-400'>|</span>
|
||||
<span className='mt-2 mx-2 text-gray-400 dark:text-gray-300 text-sm leading-4'>{post.date.start_date}</span>
|
||||
</div>
|
||||
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`}>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<div className='cursor-pointer my-3 text-lg leading-tight font-bold text-black dark:text-gray-100 hover:underline'>
|
||||
{post.title}
|
||||
</div>
|
||||
@@ -39,7 +37,7 @@ const BlogPostCard = ({ post, tags }) => {
|
||||
<div> {post.tagItems.map(tag => (<TagItemMini key={tag.name} tag={tag} />))}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
||||
const CategoryGroup = ({ currentCategory, categories }) => {
|
||||
return <div>
|
||||
<div id='category-list' className='dark:border-gray-600 dark:bg-gray-800 w-66'>
|
||||
<div id='category-list' className='dark:border-gray-600 dark:bg-gray-800'>
|
||||
{Object.keys(categories).map(category => {
|
||||
const selected = currentCategory === category
|
||||
return <Link key={category} href={`/category/${category}`}>
|
||||
<div className={(selected ? 'bg-gray-200 dark:bg-black dark:text-white text-black ' : 'dark:text-gray-400 text-gray-500 ') + ' hover:text-black dark:hover:text-white dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}><i className='fa fa-folder-open-o mr-4'/>{category}({categories[category]})</div>
|
||||
return <Link key={category} href={`/category/${category}`} passHref>
|
||||
<div className={(selected ? 'bg-gray-200 dark:bg-black dark:text-white text-black ' : 'dark:text-gray-400 text-gray-500 ') + ' hover:text-black dark:hover:text-white dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className='mr-2 text-gray-400'/>{category}({categories[category]})</div>
|
||||
</Link>
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faFolder, faFolderOpen, faThList } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const CategoryList = ({ currentCategory, categories }) => {
|
||||
if (!categories) {
|
||||
return <></>
|
||||
}
|
||||
return <ul className='flex py-1 space-x-3'>
|
||||
<li className='w-16 py-2 dark:text-gray-200'><i className='fa fa-th-list mr-2'/>分类:</li>
|
||||
<li className='w-16 py-2 dark:text-gray-200'><FontAwesomeIcon className='mr-2' icon={faThList} />分类:</li>
|
||||
{Object.keys(categories).map(category => {
|
||||
const selected = category === currentCategory
|
||||
return (
|
||||
<Link key={category} href={`/category/${category}`}>
|
||||
<Link key={category} href={`/category/${category}`} passHref>
|
||||
<li
|
||||
className={`cursor-pointer border rounded-xl duration-200 mr-1 my-1 px-2 py-1 font-medium font-light text-sm whitespace-nowrap dark:text-gray-300
|
||||
${selected
|
||||
? 'text-white bg-black dark:hover:bg-gray-900 dark:bg-black dark:border-gray-800'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-300 dark:bg-gray-600 dark:border-gray-600'
|
||||
}`}
|
||||
? 'text-white bg-black dark:hover:bg-gray-900 dark:bg-black dark:border-gray-800'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-300 dark:bg-gray-600 dark:border-gray-600'
|
||||
}`}
|
||||
>
|
||||
<a>
|
||||
<i className='fa fa-folder-open-o mr-1'/>
|
||||
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className='mr-1' />
|
||||
{`${category} `}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faInfo } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 悬浮在屏幕右下角,联系我的按钮
|
||||
@@ -12,7 +14,7 @@ const ContactButton = () => {
|
||||
<a className={'fixed right-10 bottom-40 animate__fadeInRight animate__animated animate__faster'}>
|
||||
<span
|
||||
className='dark:bg-black bg-white px-5 py-3 cursor-pointer shadow-card text-xl hover:bg-blue-500 transform duration-200 hover:text-white hover:shadow'>
|
||||
<span className='dark:text-gray-200 fa fa-info' title='about' />
|
||||
<FontAwesomeIcon icon={faInfo} className='dark:text-gray-200 ' title='about' />
|
||||
</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { loadUserThemeFromCookies, saveTheme, useGlobal } from '@/lib/global'
|
||||
import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
const DarkModeButton = () => {
|
||||
const { changeTheme } = useGlobal()
|
||||
@@ -10,7 +12,7 @@ const DarkModeButton = () => {
|
||||
changeTheme(newTheme)
|
||||
}
|
||||
return <div className='z-10 duration-200 text-xl cursor-pointer'>
|
||||
<i id='darkModeButton' className={'fa p-2.5 hover:scale-125 transform duration-200 ' + (userTheme === 'dark' ? 'fa-sun-o' : 'fa-moon-o')}
|
||||
<FontAwesomeIcon icon={userTheme === 'dark' ? faSun : faMoon} id='darkModeButton' className='fa mx-2.5 my-2 hover:scale-125 transform duration-200'
|
||||
onClick={handleChangeDarkMode} />
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { faCopyright, faEye, faShieldAlt, faUser } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
|
||||
const Footer = ({ fullWidth = true }) => {
|
||||
const d = new Date()
|
||||
@@ -7,23 +10,16 @@ const Footer = ({ fullWidth = true }) => {
|
||||
<footer
|
||||
className='bg-gray-800 dark:bg-black dark:border-gray-900 border-t flex-shrink-0 justify-center text-center m-auto w-full text-gray-400 text-sm p-6'
|
||||
>
|
||||
<span className='fa fa-copyright leading-6'> {` ${y}`} <span> <a href='https://www.tangly1024.com/article/about' className='underline font-bold text-gray-100'>tangly1024.com</a>. Powered by <a href='https://notion.so' className='underline font-bold text-gray-100'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-100'>NotionNext</a>.</span> </span>
|
||||
<FontAwesomeIcon icon={faCopyright} /> {` ${y}`} <span> <a href='https://www.tangly1024.com/article/about' className='underline font-bold text-gray-100'>tangly1024.com</a>. Powered by <a href='https://notion.so' className='underline font-bold text-gray-100'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-100'>NotionNext</a>.</span>
|
||||
<br />
|
||||
<span className='fa fa-shield leading-6 mr-2'> <a href='https://beian.miit.gov.cn/' className='ml-1 font-bold'>闽ICP备20010331号</a></span>
|
||||
<span > <a href='/article/privacy-policy' className='ml-1 font-bold underline'>隐私政策</a></span>
|
||||
<FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='ml-1 font-bold'>闽ICP备20010331号</a>
|
||||
<span > <Link href='/article/privacy-policy' ><a className='ml-1 font-bold underline'>隐私政策</a></Link></span>
|
||||
|
||||
<span id='busuanzi_container_site_pv' className='hidden'>
|
||||
<a id='busuanzi_container_site_pv' target='_blank' className='fa fa-eye' rel='noreferrer'
|
||||
href='/#'><span
|
||||
id='busuanzi_value_site_pv' className='px-1'> </span>pv</a>
|
||||
<FontAwesomeIcon icon={faEye}/><span id='busuanzi_value_site_pv' className='px-1'> </span>pv
|
||||
</span>
|
||||
<span id='busuanzi_container_site_uv' className='pl-2 hidden'>
|
||||
<a className='fa fa-user' rel='noreferrer' target='_blank'
|
||||
href='/#'>
|
||||
<span id='busuanzi_value_site_uv' className='px-1'> </span>uv</a>
|
||||
</span>
|
||||
<br/>
|
||||
|
||||
<FontAwesomeIcon icon={faUser}/> <span id='busuanzi_value_site_uv' className='px-1'> </span>uv </span>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faArrowUp } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 跳转到网页顶部
|
||||
@@ -40,7 +42,9 @@ const JumpToTopButton = ({ targetRef, showPercent = true }) => {
|
||||
style={{ boxShadow: 'rgba(41, 50, 60, 0.5) 0px 2px 16px', borderRadius: '28px' }}
|
||||
className={(show ? 'animate__fadeInUp' : 'animate__fadeOutUp') + ' bg-white dark:bg-gray-700 px-1 py-1 cursor-pointer animate__animated animate__faster shadow-2xl'}>
|
||||
<div className='text-center'>
|
||||
<div className='w-10 text-xl dark:text-gray-100 transform hover:scale-125 duration-200' title={locale.POST.TOP} ><i className='fa fa-arrow-up'/> </div>
|
||||
<div className='w-10 text-xl dark:text-gray-100 transform hover:scale-125 duration-200' title={locale.POST.TOP} >
|
||||
<FontAwesomeIcon icon={faArrowUp} />
|
||||
</div>
|
||||
{showPercent && (<div className='w-10 text-xs dark:text-gray-200'>{percent} </div>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import throttle from 'lodash.throttle'
|
||||
import DarkModeButton from '@/components/DarkModeButton'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faBars } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 左上角悬浮菜单栏
|
||||
@@ -30,7 +32,7 @@ const LeftFloatButton = () => {
|
||||
{/* 菜单折叠 */}
|
||||
<div className='p-1 border hover:shadow-xl duration-200 dark:border-gray-500 h-12 bg-white dark:bg-gray-600 dark:bg-opacity-70 bg-opacity-70
|
||||
dark:hover:bg-gray-100 text-xl cursor-pointer mr-2 my-2 dark:text-gray-300 dark:hover:text-black'>
|
||||
<i className='fa fa-bars p-2.5 hover:scale-125 transform duration-200'
|
||||
<FontAwesomeIcon icon={faBars} className='p-2.5 hover:scale-125 transform duration-200'
|
||||
onClick={() => changeCollapse(!collapse)} />
|
||||
</div>
|
||||
{/* 夜间模式 */}
|
||||
|
||||
@@ -3,13 +3,11 @@ import BLOG from '@/blog.config'
|
||||
import React from 'react'
|
||||
|
||||
const Logo = () => {
|
||||
return <Link href='/'>
|
||||
return <Link href='/' passHref>
|
||||
<div title={BLOG.title} className='mx-auto border dark:border-gray-600 text-center cursor-pointer text-xl dark:text-gray-300 font-semibold dark:hover:bg-gray-600 text-white p-2 hover:scale-105 hover:shadow-2xl duration-200 transform'>
|
||||
<span className='text-red-600'>Tangly</span>
|
||||
<span className='text-blue-400'>1024</span>
|
||||
</div>
|
||||
{/* <div className='transform hover:scale-110 duration-200 cursor-pointer'><img src='http://to-a.ru/DmOleR/img1' width={100} alt={BLOG.title} /></div> */}
|
||||
|
||||
</Link>
|
||||
}
|
||||
export default Logo
|
||||
|
||||
@@ -2,21 +2,23 @@ import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faHome, faInfoCircle } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const MenuButtonGroup = ({ allowCollapse = false }) => {
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const links = [
|
||||
{ id: 0, icon: 'fa-home', name: locale.NAV.INDEX, to: '/' || '/', show: true },
|
||||
{ id: 1, icon: 'fa-info-circle', name: locale.NAV.ABOUT, to: '/article/about', show: true }
|
||||
// { id: 7, icon: 'fa-github', name: 'Github', to: 'https://github.com/tangly1024', show: true },
|
||||
// { id: 5, icon: 'fa-weibo', name: '微博', to: 'https://weibo.com/tangly1024', show: true },
|
||||
// { id: 4, icon: 'fa-envelope', name: locale.NAV.MAIL, to: 'mailto:tlyong1992@hotmail.com', show: true }
|
||||
// { id: 2, icon: 'fa-rss-square', name: locale.NAV.RSS, to: '/feed', show: true },
|
||||
// { id: 3, icon: 'fa-compass', name: '发现', to: 'https://search.tangly1024.com/', show: true }
|
||||
// { id: 6, icon: 'fa-map-marker', name: 'Fuzhou', to: '#', show: true },
|
||||
// { id: 8, icon: 'fa-twitter', name: 'Twitter', to: 'https://twitter.com/troy1024_1', show: true },
|
||||
// { id: 9, icon: 'fa-telegram', name: 'Telegram', to: 'https://t.me/tangly_1024', show: true }
|
||||
{ id: 0, icon: faHome, name: locale.NAV.INDEX, to: '/' || '/', show: true },
|
||||
{ id: 1, icon: faInfoCircle, name: locale.NAV.ABOUT, to: '/article/about', show: true }
|
||||
// { id: 7, icon: 'faGithub', name: 'Github', to: 'https://github.com/tangly1024', show: true },
|
||||
// { id: 5, icon: 'faWeibo', name: '微博', to: 'https://weibo.com/tangly1024', show: true },
|
||||
// { id: 4, icon: 'faEnvelope', name: locale.NAV.MAIL, to: 'mailto:tlyong1992@hotmail.com', show: true }
|
||||
// { id: 2, icon: 'faRssSquare', name: locale.NAV.RSS, to: '/feed', show: true },
|
||||
// { id: 3, icon: 'faCompass', name: '发现', to: 'https://search.tangly1024.com/', show: true }
|
||||
// { id: 6, icon: 'faMapMarker', name: 'Fuzhou', to: '#', show: true },
|
||||
// { id: 8, icon: 'faTwitter', name: 'Twitter', to: 'https://twitter.com/troy1024_1', show: true },
|
||||
// { id: 9, icon: 'faTelegram', name: 'Telegram', to: 'https://t.me/tangly_1024', show: true }
|
||||
]
|
||||
return <nav id='nav'>
|
||||
<div className='leading-8 text-gray-500 dark:text-gray-400'>
|
||||
@@ -25,9 +27,9 @@ const MenuButtonGroup = ({ allowCollapse = false }) => {
|
||||
const selected = router.asPath === link.to
|
||||
return <Link key={link.id + link.icon} title={link.to} href={link.to} >
|
||||
<a className={'py-2 px-5 hover:text-black dark:hover:text-white hover:bg-gray-100 cursor-pointer dark:hover:bg-gray-600 duration-100 flex flex-nowrap align-middle' +
|
||||
(selected ? 'bg-gray-200 dark:bg-black dark:text-white text-black ' : '') } >
|
||||
<div className='my-auto w-5 text-2xl justify-center flex'>
|
||||
<i className={'fa ' + link.icon} />
|
||||
(selected ? 'bg-gray-200 dark:bg-black dark:text-white text-black ' : '')} >
|
||||
<div className='my-auto w-5 justify-center flex'>
|
||||
<FontAwesomeIcon icon={link.icon} />
|
||||
</div>
|
||||
<div className={'ml-4 w-32'}>{link.name}</div>
|
||||
</a>
|
||||
|
||||
@@ -2,6 +2,8 @@ import { useEffect, useRef } from 'react'
|
||||
import Link from 'next/link'
|
||||
import BLOG from '@/blog.config'
|
||||
import Image from 'next/image'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faBars } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const NavBar = () => {
|
||||
const links = []
|
||||
@@ -81,7 +83,7 @@ const Header = ({ navBarTitle, fullWidth = true }) => {
|
||||
|
||||
<div className='flex cursor-pointer'>
|
||||
<div className='px-2 text-xl'>
|
||||
<i className='fa fa-bars hover:scale-125 transform duration-200' />
|
||||
<FontAwesomeIcon icon={faBars} className='hover:scale-125 transform duration-200' />
|
||||
</div>
|
||||
<Image
|
||||
alt={BLOG.author}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faQrcode } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 赞赏按钮
|
||||
@@ -19,13 +22,13 @@ const RewardButton = () => {
|
||||
return (
|
||||
<div onMouseEnter={openPopover} onMouseLeave={closePopover} className='justify-center py-10'>
|
||||
<div className='bg-red-500 w-36 mx-auto animate__jello text-white hover:bg-green-400 duration-200 transform hover:scale-110 px-3 py-2 rounded cursor-pointer'>
|
||||
<span className='fa fa-qrcode mr-2' />
|
||||
<FontAwesomeIcon icon={faQrcode} className='mr-2' />
|
||||
<span>打赏一杯咖啡</span>
|
||||
</div>
|
||||
|
||||
<div id='reward-qrcode' className='hidden flex space-x-10 animate__animated animate__fadeIn duration-200 my-5 px-5 mx-auto py-6 justify-center bg-white dark:bg-black dark:text-gray-200'>
|
||||
<div><img className='md:w-72' src='/reward_code_alipay.png' /></div>
|
||||
<div><img className='md:w-72' src='/reward_code_wechat.png' /></div>
|
||||
<div className='w-72 bg-black'><Image width='auto' height='auto' layout='responsive' objectFit='fill' src='/reward_code_alipay.png' /></div>
|
||||
<div className='w-72 bg-black'><Image width='auto' height='auto' layout='responsive' objectFit='fill' src='/reward_code_wechat.png' /></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useRef, useState } from 'react'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const SearchInput = ({ currentTag, currentSearch }) => {
|
||||
const { locale } = useGlobal()
|
||||
@@ -45,11 +47,11 @@ const SearchInput = ({ currentTag, currentSearch }) => {
|
||||
onChange={e => updateSearchKey(e.target.value)}
|
||||
defaultValue={currentSearch}
|
||||
/>
|
||||
{ (searchKey && searchKey.length && <i className='fa fa-close text-gray-300 float-right p-4 cursor-pointer' onClick={ cleanSearch } />)}
|
||||
{(searchKey && searchKey.length && <FontAwesomeIcon icon={faTimes} className='text-gray-300 float-right m-4 cursor-pointer' onClick={cleanSearch} />)}
|
||||
|
||||
<div className='p-3 text-xl bg-gray-50 flex border-l dark:border-gray-700 dark:hover:bg-gray-800 dark:bg-gray-600 justify-center align-middle cursor-pointer'
|
||||
onClick={() => { handleSearch(searchKey) }}>
|
||||
<i className={`fa ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'} hover:scale-125 hover:text-black transform duration-200 dark:text-gray-300 dark:hover:text-white text-gray-600 cursor-pointer`}/>
|
||||
onClick={() => { handleSearch(searchKey) }}>
|
||||
<FontAwesomeIcon spin={onLoading} icon={onLoading ? faSpinner : faSearch} className='hover:scale-125 hover:text-black transform duration-200 dark:text-gray-300 dark:hover:text-white text-gray-600 cursor-pointer ' />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -5,6 +5,16 @@ import { createPopper } from '@popperjs/core'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import QRCode from 'qrcode.react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faFacebookSquare,
|
||||
faQq,
|
||||
faTelegram,
|
||||
faTwitterSquare,
|
||||
faWeibo,
|
||||
faWeixin
|
||||
} from '@fortawesome/free-brands-svg-icons'
|
||||
import { faLink, faStar } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const ShareBar = ({ post }) => {
|
||||
const router = useRouter()
|
||||
@@ -36,52 +46,52 @@ const ShareBar = ({ post }) => {
|
||||
className='py-2 text-gray-500 text-center space-x-2 flex inline-block my-1 dark:text-gray-200 overflow-visible'>
|
||||
<div className='hidden md:block text-gray-800 dark:text-gray-300 mr-2 my-2'>{locale.COMMON.SHARE}:</div>
|
||||
<div className='text-3xl cursor-pointer'>
|
||||
<a className='fa fa-facebook-square hover:text-red-600'
|
||||
href={`https://www.facebook.com/sharer.php?u=${shareUrl}`} />
|
||||
<a className='hover:text-blue-700' href={`https://www.facebook.com/sharer.php?u=${shareUrl}`} >
|
||||
<FontAwesomeIcon icon={faFacebookSquare}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='text-3xl cursor-pointer'>
|
||||
<a className='fa fa-twitter-square hover:text-red-600' target='_blank' rel='noreferrer'
|
||||
href={`https://twitter.com/intent/tweet?title=${post.title}&url${shareUrl}`} />
|
||||
<a className='hover:text-blue-400' target='_blank' rel='noreferrer' href={`https://twitter.com/intent/tweet?title=${post.title}&url${shareUrl}`} >
|
||||
<FontAwesomeIcon icon={faTwitterSquare}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='text-3xl cursor-pointer'>
|
||||
<a className='fa fa-telegram hover:text-red-600' href={`https://telegram.me/share/url?url=${shareUrl}&text=${post.title}`} />
|
||||
<a className='hover:text-blue-500' href={`https://telegram.me/share/url?url=${shareUrl}&text=${post.title}`} >
|
||||
<FontAwesomeIcon icon={faTelegram}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='cursor-pointer text-2xl'>
|
||||
<a className='fa fa-wechat hover:text-red-600' ref={btnRef}
|
||||
onMouseEnter={() => {
|
||||
openPopover()
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
closePopover()
|
||||
}}>
|
||||
<div ref={popoverRef}
|
||||
className={(qrCodeShow ? 'animate__animated animate__fadeIn ' : 'hidden') + ' text-center py-2'}>
|
||||
<a className='hover:text-green-600' ref={btnRef} onMouseEnter={openPopover} onMouseLeave={closePopover}>
|
||||
<FontAwesomeIcon icon={faWeixin}/>
|
||||
<div ref={popoverRef} className={(qrCodeShow ? 'animate__animated animate__fadeIn ' : 'hidden') + ' text-center py-2'}>
|
||||
<div className='p-2 bg-white border-0 duration-200 transform block z-50 font-normal shadow-xl mr-10'>
|
||||
<QRCode
|
||||
value={shareUrl}// 生成二维码的内容
|
||||
fgColor='#000000' // 二维码的颜色
|
||||
/>
|
||||
<QRCode value={shareUrl} fgColor='#000000' />
|
||||
</div>
|
||||
<span className='bg-white text-black font-semibold p-1 mb-0 rounded-t-lg text-sm mx-auto mr-10'>
|
||||
{locale.COMMON.SCAN_QR_CODE}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className='cursor-pointer text-2xl'>
|
||||
<a className='fa fa-weibo hover:text-red-600' target='_blank' rel='noreferrer'
|
||||
href={`https://service.weibo.com/share/share.php?url=${shareUrl}&title=${post.title}`} />
|
||||
<a className='hover:text-red-600' target='_blank' rel='noreferrer'href={`https://service.weibo.com/share/share.php?url=${shareUrl}&title=${post.title}`} >
|
||||
<FontAwesomeIcon icon={faWeibo}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='cursor-pointer text-2xl'>
|
||||
<a className='fa fa-qq hover:text-red-600' target='_blank' rel='noreferrer'
|
||||
href={`http://connect.qq.com/widget/shareqq/index.html?url=${shareUrl}&sharesource=qzone&title=${post.title}&desc=${post.summary}`} />
|
||||
<a className='hover:text-blue-400' target='_blank' rel='noreferrer'href={`http://connect.qq.com/widget/shareqq/index.html?url=${shareUrl}&sharesource=qzone&title=${post.title}&desc=${post.summary}`} >
|
||||
<FontAwesomeIcon icon={faQq}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='cursor-pointer text-2xl'>
|
||||
<a className='fa fa-star hover:text-red-600' target='_blank' rel='noreferrer'
|
||||
href={`https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=${shareUrl}&sharesource=qzone&title=${post.title}&summary=${post.summary}`} />
|
||||
<a className='hover:text-red-600' target='_blank' rel='noreferrer' href={`https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=${shareUrl}&sharesource=qzone&title=${post.title}&summary=${post.summary}`} >
|
||||
<FontAwesomeIcon icon={faStar}/>
|
||||
</a>
|
||||
</div>
|
||||
<div className='cursor-pointer text-2xl'>
|
||||
<a className='fa fa-link hover:text-red-600' onClick={copyUrl} />
|
||||
<a className='hover:text-red-600' onClick={copyUrl} >
|
||||
<FontAwesomeIcon icon={faLink}/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faShareAltSquare } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 悬浮在屏幕右下角,分享按钮
|
||||
@@ -25,7 +27,7 @@ const ShareButton = ({ post }) => {
|
||||
</div>
|
||||
<div ref={btnRef}
|
||||
className='z-20 border dark:border-gray-500 dark:bg-gray-600 bg-white cursor-pointer text-md hover:shadow-2xl shadow-lg'>
|
||||
<i className='transform duration-200 hover:scale-150 dark:text-gray-200 p-4 fa fa-share-alt' title='share' />
|
||||
<FontAwesomeIcon icon={faShareAltSquare} className='transform duration-200 hover:scale-150 dark:text-gray-200 p-4' title='share' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -8,6 +8,8 @@ import SearchInput from '@/components/SearchInput'
|
||||
import Link from 'next/link'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Toc from '@/components/Toc'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faAngleDoubleRight, faArchive, faTags, faThList } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 侧边栏
|
||||
@@ -30,25 +32,23 @@ const SideBar = ({ tags, currentTag, post, posts, categories, currentCategory, c
|
||||
|
||||
<div className={(!post ? 'sticky top-0' : '') + ' bg-white dark:bg-gray-800 pb-4'}>
|
||||
|
||||
{/* 搜索框 */}
|
||||
<section className='p-5'>
|
||||
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<hr className='dark:border-gray-700' />
|
||||
{/* <hr className='dark:border-gray-700' /> */}
|
||||
<MenuButtonGroup allowCollapse={true} />
|
||||
<hr className='dark:border-gray-700 my-2' />
|
||||
<section className='p-5'>
|
||||
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
|
||||
</section>
|
||||
<hr classNaÍme='dark:border-gray-700' />
|
||||
</section>
|
||||
|
||||
{/* 最新文章 */}
|
||||
{posts && (
|
||||
<section className='mt-3'>
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm font-bold py-2 px-5 flex flex-nowrap justify-between'>
|
||||
<div className='text-black font-bold dark:text-gray-200'><i className='fa fa-newspaper-o mr-4'/>{locale.COMMON.LATEST_POSTS}</div>
|
||||
<Link href='/archive'>
|
||||
<div className='text-gray-600 font-bold dark:text-gray-200'><FontAwesomeIcon icon={faArchive} className='mr-4' />{locale.COMMON.LATEST_POSTS}</div>
|
||||
<Link href='/archive' passHref>
|
||||
<div className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fa fa-angle-double-right'/>
|
||||
{locale.COMMON.MORE} <FontAwesomeIcon icon={faAngleDoubleRight} />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -58,14 +58,14 @@ const SideBar = ({ tags, currentTag, post, posts, categories, currentCategory, c
|
||||
|
||||
{/* 分类 */}
|
||||
{categories && (
|
||||
<section className='mt-2'>
|
||||
<section className='mt-5'>
|
||||
<div className='text-sm font-bold py-2 px-5 flex flex-nowrap justify-between'>
|
||||
<div className='text-black font-bold dark:text-gray-200'><i className='fa fa-th-list mr-4'/>{locale.COMMON.CATEGORY}</div>
|
||||
<Link href='/category'>
|
||||
<div className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fa fa-angle-double-right'/>
|
||||
</div>
|
||||
</Link>
|
||||
<div className='text-gray-600 font-bold dark:text-gray-200'><FontAwesomeIcon icon={faThList} className='mr-4' />{locale.COMMON.CATEGORY}</div>
|
||||
<Link href='/category' passHref>
|
||||
<div className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <FontAwesomeIcon icon={faAngleDoubleRight} />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup currentCategory={currentCategory} categories={categories} />
|
||||
</section>
|
||||
@@ -73,18 +73,18 @@ const SideBar = ({ tags, currentTag, post, posts, categories, currentCategory, c
|
||||
|
||||
{/* 标签云 */}
|
||||
{tags && (
|
||||
<section className='mt-3'>
|
||||
<section className='mt-5'>
|
||||
<div className='text-sm font-bold py-2 px-5 flex flex-nowrap justify-between'>
|
||||
<div className='text-black font-bold dark:text-gray-200'><i className='fa fa-tags mr-4'/>{locale.COMMON.TAGS}</div>
|
||||
<Link href='/tag'>
|
||||
<div className='text-gray-600 font-bold dark:text-gray-200'><FontAwesomeIcon icon={faTags} className='mr-4' />{locale.COMMON.TAGS}</div>
|
||||
<Link href='/tag' passHref>
|
||||
<div className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fa fa-angle-double-right'/>
|
||||
{locale.COMMON.MORE} <FontAwesomeIcon icon={faAngleDoubleRight} />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div className='px-5'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
<div className='px-5'>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@ const SideBar = ({ tags, currentTag, post, posts, categories, currentCategory, c
|
||||
</section>
|
||||
)}
|
||||
|
||||
<section id='blank' className='bg-white dark:bg-gray-800 py-20'/>
|
||||
<section id='blank' className='bg-white dark:bg-gray-800 py-20' />
|
||||
|
||||
</aside>
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { faGithub, faTelegram, faTwitter, faWeibo } from '@fortawesome/free-brands-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import React from 'react'
|
||||
|
||||
/**
|
||||
@@ -8,20 +10,17 @@ import React from 'react'
|
||||
const SocialButton = () => {
|
||||
return <div className='w-52'>
|
||||
<div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 px-6'>
|
||||
<a target='_blank' rel='noreferrer' title={'github'}
|
||||
href={'https://github.com/tangly1024'} >
|
||||
<div className='fa fa-github transform hover:scale-125 duration-150'/>
|
||||
<a target='_blank' rel='noreferrer' title={'github'} href={'https://github.com/tangly1024'} >
|
||||
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
|
||||
</a>
|
||||
<a target='_blank' rel='noreferrer' title={'twitter'}
|
||||
href={'https://twitter.com/troy1024_1'} >
|
||||
<div className='fa fa-twitter transform hover:scale-125 duration-150'/>
|
||||
<a target='_blank' rel='noreferrer' title={'twitter'} href={'https://twitter.com/troy1024_1'} >
|
||||
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
|
||||
</a>
|
||||
<a href={'https://t.me/tangly_1024'} title={'telegram'} >
|
||||
<div className='fa fa-telegram transform hover:scale-125 duration-150'/>
|
||||
<a target='_blank' rel='noreferrer' href={'https://t.me/tangly_1024'} title={'telegram'} >
|
||||
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
|
||||
</a>
|
||||
<a target='_blank' rel='noreferrer' title={'weibo'}
|
||||
href={'https://weibo.com/tangly1024'} >
|
||||
<div className='fa fa-weibo transform hover:scale-125 duration-150'/>
|
||||
<a target='_blank' rel='noreferrer' title={'weibo'} href={'https://weibo.com/tangly1024'} >
|
||||
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { faTag } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
||||
const TagItem = ({ tag, selected }) => {
|
||||
return (
|
||||
<Link href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}>
|
||||
<Link href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<li
|
||||
className={`notion-${tag.color}_background list-none cursor-pointer hover:bg-gray-300 rounded-md
|
||||
duration-200 mr-1 my-1 px-2 py-1 font-medium font-light text-sm whitespace-nowrap
|
||||
@@ -13,7 +15,7 @@ const TagItem = ({ tag, selected }) => {
|
||||
: ' text-gray-600'}`}
|
||||
>
|
||||
<a>
|
||||
{`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
|
||||
{selected && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
|
||||
</a>
|
||||
</li>
|
||||
</Link>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { faTag } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMini = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}>
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<div className={`cursor-pointer inline-block rounded hover:bg-gray-500 duration-200
|
||||
mr-2 my-1 py-1 px-2 font-medium font-light 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'
|
||||
: `text-gray-600 dark:text-gray-600 hover:shadow-xl hover:text-white dark:hover:bg-gray-600 dark:border-gray-600 notion-${tag.color}_background `}` }>
|
||||
<div>{tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
<div>{selected && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</div>
|
||||
</Link>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import TagItem from '@/components/TagItem'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faTags } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 横向的标签列表
|
||||
@@ -14,7 +15,7 @@ const TagList = ({ tags, currentTag }) => {
|
||||
return <></>
|
||||
}
|
||||
return <ul className='flex py-1 space-x-3'>
|
||||
<li className='w-16 py-2 dark:text-gray-200'><i className='fa fa-tags mr-2'/>标签:</li>
|
||||
<li className='w-20 py-2 dark:text-gray-200'><FontAwesomeIcon icon={faTags} className='mr-2'/>标签:</li>
|
||||
{tags.map(tag => {
|
||||
const selected = tag.name === currentTag
|
||||
return <TagItem key={tag.name} tag={tag} selected={selected}/>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faBook } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
/**
|
||||
* 点击召唤目录抽屉
|
||||
@@ -17,7 +19,7 @@ const TocDrawerButton = (props) => {
|
||||
<div style={{ borderRadius: '28px' }}
|
||||
className={'animate__fadeInUp bg-white dark:bg-gray-700 px-1 py-1 cursor-pointer animate__animated animate__faster shadow-xl'}>
|
||||
<div className='text-center dark:text-gray-100'>
|
||||
<div className='w-10 text-xl' title={locale.COMMON.TABLE_OF_CONTENTS} ><i className='fa fa-book'/> </div>
|
||||
<div className='w-10 text-xl' title={locale.COMMON.TABLE_OF_CONTENTS} ><FontAwesomeIcon icon={faBook} /> </div>
|
||||
<div className='text-xs'>{locale.COMMON.TABLE_OF_CONTENTS}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,8 @@ import { useRef } from 'react'
|
||||
import DarkModeButton from '@/components/DarkModeButton'
|
||||
import SearchInput from '@/components/SearchInput'
|
||||
import SideBarDrawer from '@/components/SideBarDrawer'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faBars } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const TopNav = ({ tags, currentTag, post, posts, currentSearch, categories, currentCategory }) => {
|
||||
const drawer = useRef()
|
||||
@@ -17,7 +19,7 @@ const TopNav = ({ tags, currentTag, post, posts, currentSearch, categories, curr
|
||||
<div className='flex ml-12'>
|
||||
<div onClick={() => { drawer.current.handleSwitchSideDrawerVisible() }}
|
||||
className='fixed top-3 left-0 z-30 py-1 px-5 text-gray-600 text-2xl cursor-pointer dark:text-gray-300'>
|
||||
<i className='fa hover:scale-125 transform duration-200 fa-bars '
|
||||
<FontAwesomeIcon icon={faBars} className='hover:scale-125 transform duration-200'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,9 +3,9 @@ module.exports = {
|
||||
webpack5: true
|
||||
},
|
||||
images: {
|
||||
domains: ['gravatar.com']
|
||||
domains: ['gravatar.com', 'www.notion.so', 'avatars.githubusercontent.com']
|
||||
},
|
||||
async headers() {
|
||||
async headers () {
|
||||
return [
|
||||
{
|
||||
source: '/:path*{/}?',
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
"postbuild": "next-sitemap --config next-sitemap.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@fortawesome/react-fontawesome": "^0.1.16",
|
||||
"@popperjs/core": "^2.9.3",
|
||||
"animate.css": "^4.1.1",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"feed": "^4.2.2",
|
||||
"font-awesome": "^4.7.0",
|
||||
"gitalk": "^1.7.2",
|
||||
"localStorage": "^1.0.4",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
|
||||
@@ -7,6 +7,8 @@ import { useEffect } from 'react'
|
||||
import BaseLayout from '@/layouts/BaseLayout'
|
||||
import BLOG from '@/blog.config'
|
||||
import { useRouter } from 'next/router'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export default function Custom404 () {
|
||||
const router = useRouter()
|
||||
@@ -26,7 +28,7 @@ export default function Custom404 () {
|
||||
<div
|
||||
className='text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
|
||||
<div>
|
||||
<h1 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><i className='fa fa-spinner mr-2 animate-spin'/>404</h1>
|
||||
<h1 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><FontAwesomeIcon icon={faSpinner} spin={true} className='mr-2'/>404</h1>
|
||||
<div className='inline-block text-left h-32 leading-10 align-middle'>
|
||||
<h2 className='m-0 p-0'>页面无法加载,即将返回首页</h2>
|
||||
</div>
|
||||
|
||||
@@ -3,8 +3,6 @@ import 'rc-dropdown/assets/index.css'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import '@/styles/globals.css'
|
||||
import 'animate.css'
|
||||
import 'font-awesome/css/font-awesome.min.css'
|
||||
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { GlobalContextProvider } from '@/lib/global'
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { getAllCategories, getAllPosts, getAllTags } from '@/lib/notion'
|
||||
import BLOG from '@/blog.config'
|
||||
import BaseLayout from '@/layouts/BaseLayout'
|
||||
import BlogPostListScroll from '@/components/BlogPostListScroll'
|
||||
import { getNotionPageData } from '@/lib/notion/getNotionData'
|
||||
import StickyBar from '@/components/StickyBar'
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BlogPostArchive from '@/components/BlogPostArchive'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faArchive } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export async function getStaticProps () {
|
||||
const from = 'index'
|
||||
@@ -58,7 +59,7 @@ const Index = ({ allPosts, tags, categories }) => {
|
||||
<BaseLayout meta={meta} tags={tags} categories={categories}>
|
||||
<div className='flex-grow bg-gray-200 dark:bg-black shadow-inner pt-16 '>
|
||||
<StickyBar>
|
||||
<div className='py-4 text-lg lg:mx-14 dark:text-gray-200'><i className='fa fa-newspaper-o mr-4'/>{locale.NAV.ARCHIVE}</div>
|
||||
<div className='py-4 text-lg lg:mx-14 dark:text-gray-200'><FontAwesomeIcon icon={faArchive} className='mr-4'/>{locale.NAV.ARCHIVE}</div>
|
||||
</StickyBar>
|
||||
<div className='mt-20 mx-2 lg:mx-20 bg-white p-12 dark:bg-gray-800'>
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
|
||||
@@ -13,6 +13,7 @@ import BaseLayout from '@/layouts/BaseLayout'
|
||||
import React, { useRef } from 'react'
|
||||
import Custom404 from '@/pages/404'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
|
||||
import 'prismjs/themes/prism-okaidia.css'
|
||||
import 'prismjs'
|
||||
@@ -26,6 +27,8 @@ import TocDrawer from '@/components/TocDrawer'
|
||||
import TocDrawerButton from '@/components/TocDrawerButton'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getNotionPageData } from '@/lib/notion/getNotionData'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faAngleDoubleLeft, faAngleDoubleRight, faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
@@ -49,35 +52,28 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, allPosts, categories
|
||||
<Progress targetRef={targetRef} />
|
||||
|
||||
<article id='article-wrapper' ref={targetRef} className='flex-grow bg-gray-200 dark:bg-black pt-16'>
|
||||
{/* 中央区域 wrapper */}
|
||||
{post.type && !post.type.includes('Page') && (<>
|
||||
{/* 封面图 */}
|
||||
{post.page_cover && post.page_cover.length > 1 && (
|
||||
<img className='bg-center object-cover w-full hover:shadow-2xl hover:scale-105 transform duration-200 mx-auto max-w-5xl mb-2 md:flex-shrink-0 animate__fadeIn animate__animated'
|
||||
style={{ maxHeight: '40rem' }}
|
||||
src={post.page_cover} alt={post.title} />
|
||||
)}
|
||||
</>)}
|
||||
|
||||
<div
|
||||
className='hover:shadow-2xl duration-200 shadow-card mb-20 w-screen md:w-full overflow-x-auto md:px-10 px-5 pt-10 max-w-5xl mx-auto dark:border-gray-700 bg-white dark:bg-gray-900'>
|
||||
|
||||
<div className='w-screen md:w-full pt-10 max-w-5xl mx-auto'>
|
||||
{post.type && !post.type.includes('Page') && (<>
|
||||
{/* 文章信息 */}
|
||||
<h1 className='font-bold text-4xl text-black my-5 dark:text-white animate__animated animate__fadeIn'> {post.title}</h1>
|
||||
<h2 className='text-gray-500 text-xs my-5 dark:text-gray-400 animate__animated animate__fadeIn'>{post.summary}</h2>
|
||||
<div className='justify-between flex flex-wrap bg-gray-100 p-2 dark:bg-gray-900 dark:text-white'>
|
||||
<div className='flex-nowrap flex'>
|
||||
<div className='py-2 opacity-50'>
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<div className='cursor-pointer text-md py-2 mx-3 hover:underline'><i
|
||||
className='fa fa-folder-open-o mr-1' />{post.category}</div>
|
||||
</Link>
|
||||
{/* 封面图 */}
|
||||
|
||||
<div style={{ height: '30rem' }} className='w-full transform duration-200 md:flex-shrink-0 animate__fadeIn animate__animated'>
|
||||
<Image src={(post.page_cover && post.page_cover.length > 1) ? post.page_cover : BLOG.defaultImgCover} loading='lazy' objectFit='cover' layout='fill' alt={post.title} />
|
||||
</div>
|
||||
|
||||
<div className='dark:border-gray-700 bg-white dark:bg-gray-800'>
|
||||
{/* 文章信息 */}
|
||||
<h1 className='font-bold text-2xl px-5 pt-5 text-black dark:text-white animate__animated animate__fadeIn'> {post.title}</h1>
|
||||
<h2 className='text-gray-500 px-5 pt-3 text-sm dark:text-gray-400 animate__animated animate__fadeIn'>{post.summary}</h2>
|
||||
<div className='justify-between mt-5 flex flex-wrap bg-gray-100 p-2 dark:bg-gray-700 dark:text-white border-b-2 dark:border-gray-500'>
|
||||
<div className='flex-nowrap flex'>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<div className='cursor-pointer text-md py-2 mx-3 text-gray-500 dark:text-gray-300 hover:text-black dark:hover:text-white'>
|
||||
<FontAwesomeIcon icon={faFolderOpen} className='mr-1' />{post.category}
|
||||
</div>
|
||||
</Link>
|
||||
{post.type[0] !== 'Page' && (
|
||||
<div className='flex items-start text-gray-500 dark:text-gray-400 leading-10'>
|
||||
<div className='flex items-start text-gray-500 dark:text-gray-300 leading-10'>
|
||||
{formatDate(
|
||||
post?.date?.start_date || post.createdTime,
|
||||
BLOG.lang
|
||||
@@ -85,25 +81,28 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, allPosts, categories
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 不蒜子 */}
|
||||
<div id='busuanzi_container_page_pv' className='hidden'>
|
||||
<div className='fa fa-eye text-gray-500 text-sm leading-none py-1 px-2'>
|
||||
<span id='busuanzi_value_page_pv' className='leading-6'></span>
|
||||
</div>
|
||||
<FontAwesomeIcon icon={faEye} className='text-gray-500 leading-none m-2.5' />
|
||||
<span id='busuanzi_value_page_pv' className='leading-6'></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>)}
|
||||
</div>
|
||||
|
||||
<div className='shadow-card w-screen md:w-full md:px-10 px-5 max-w-5xl mx-auto dark:border-gray-700 bg-white dark:bg-gray-900'>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{blockMap && (
|
||||
<NotionRenderer recordMap={blockMap} mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -125,14 +124,14 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, allPosts, categories
|
||||
|
||||
{/* 标签列表 */}
|
||||
<section className='md:flex md:justify-between'>
|
||||
{post.tagItems && (
|
||||
{post.tagItems && (
|
||||
<div className='flex flex-nowrap leading-8 p-1 py-4 overflow-x-auto'>
|
||||
<div className='hidden md:block dark:text-gray-300'>{locale.COMMON.TAGS}:</div>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
<div>
|
||||
<ShareBar post={post} />
|
||||
</div>
|
||||
@@ -142,13 +141,14 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, allPosts, categories
|
||||
<div className='text-gray-800 my-5 dark:text-gray-300'>
|
||||
<hr />
|
||||
<div className='flex flex-wrap lg:flex-nowrap lg:space-x-10 justify-between py-2'>
|
||||
<Link href={`/article/${prev.slug}`}>
|
||||
<div className='py-3 text-blue-500 text-lg hover:underline cursor-pointer'><i
|
||||
className='fa fa-angle-double-left mr-1' />{prev.title}</div>
|
||||
<Link href={`/article/${prev.slug}`} passHref>
|
||||
<div className='py-3 text-blue-500 text-lg hover:underline cursor-pointer'>
|
||||
<FontAwesomeIcon icon={faAngleDoubleLeft} className='mr-1' />{prev.title}</div>
|
||||
</Link>
|
||||
<Link href={`/article/${next.slug}`}>
|
||||
<div className='flex py-3 text-blue-500 text-lg hover:underline cursor-pointer'>{next.title}<i
|
||||
className='fa fa-angle-double-right ml-1' /></div>
|
||||
<Link href={`/article/${next.slug}`} passHref>
|
||||
<div className='flex py-3 text-blue-500 text-lg hover:underline cursor-pointer'>{next.title}
|
||||
<FontAwesomeIcon icon={faAngleDoubleRight} className='ml-1' />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -164,9 +164,7 @@ const ArticleDetail = ({ post, blockMap, tags, prev, next, allPosts, categories
|
||||
|
||||
{/* 悬浮目录按钮 */}
|
||||
<div className='block lg:hidden'>
|
||||
<TocDrawerButton onClick={() => {
|
||||
drawerRight.current.handleSwitchVisible()
|
||||
}} />
|
||||
<TocDrawerButton onClick={() => { drawerRight.current.handleSwitchVisible() }} />
|
||||
{/* 目录侧边栏 */}
|
||||
<TocDrawer post={post} cRef={drawerRight} />
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { getAllCategories, getAllPosts, getAllTags } from '@/lib/notion'
|
||||
import BLOG from '@/blog.config'
|
||||
import BaseLayout from '@/layouts/BaseLayout'
|
||||
import TagItem from '@/components/TagItem'
|
||||
import { getNotionPageData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import CategoryGroup from '@/components/CategoryGroup'
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faFolder, faThList } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export default function Category ({ tags, allPosts, categories }) {
|
||||
const { locale } = useGlobal()
|
||||
@@ -18,11 +18,12 @@ export default function Category ({ tags, allPosts, categories }) {
|
||||
return <BaseLayout meta={meta} totalPosts={allPosts} tags={tags}>
|
||||
<div className='flex-grow bg-gray-200 dark:bg-black shadow-inner p-2 lg:px-14'>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 mt-20 lg:mt-16'>
|
||||
<div className='dark:text-gray-200 mb-5'><i className='fa fa-th-list mr-4'/>{locale.COMMON.CATEGORY}:</div>
|
||||
<div className='dark:text-gray-200 mb-5'><FontAwesomeIcon icon={faThList} className='mr-4'/>{locale.COMMON.CATEGORY}:</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{Object.keys(categories).map(category => {
|
||||
return <Link key={category} href={`/category/${category}`}>
|
||||
<div className={'hover:text-black dark:hover:text-white dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}><i className='fa fa-folder-open-o mr-4'/>{category}({categories[category]})</div>
|
||||
return <Link key={category} href={`/category/${category}`} passHref>
|
||||
<div className={'hover:text-black dark:hover:text-white dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<FontAwesomeIcon icon={faFolder} className='mr-4'/>{category}({categories[category]})</div>
|
||||
</Link>
|
||||
})} </div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,8 @@ import BaseLayout from '@/layouts/BaseLayout'
|
||||
import StickyBar from '@/components/StickyBar'
|
||||
import BlogPostListScroll from '@/components/BlogPostListScroll'
|
||||
import { useRouter } from 'next/router'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faSearch } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export async function getStaticProps () {
|
||||
let posts = await getAllPosts({ from: 'index' })
|
||||
@@ -44,7 +46,7 @@ const Search = ({ posts, tags, meta, categories }) => {
|
||||
<BaseLayout meta={meta} tags={tags} totalPosts={posts} currentSearch={searchKey} categories={categories}>
|
||||
<div className='flex-grow bg-gray-200 dark:bg-black shadow-inner'>
|
||||
<StickyBar>
|
||||
<div className='p-4 dark:text-gray-200'><i className='fa fa-search mr-1'/> 搜索词: {searchKey}</div>
|
||||
<div className='p-4 dark:text-gray-200'><FontAwesomeIcon icon={faSearch} className='mr-1'/> 搜索词: {searchKey}</div>
|
||||
</StickyBar>
|
||||
<BlogPostListScroll posts={filteredPosts} tags={tags} currentSearch={searchKey} />
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,8 @@ import TagItem from '@/components/TagItem'
|
||||
import { getNotionPageData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import React from 'react'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faTags } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
export default function Tag ({ tags, allPosts, categories }) {
|
||||
const { locale } = useGlobal()
|
||||
@@ -16,13 +18,11 @@ export default function Tag ({ tags, allPosts, categories }) {
|
||||
return <BaseLayout meta={meta} categories={categories} totalPosts={allPosts}>
|
||||
<div className='flex-grow bg-gray-200 dark:bg-black shadow-inner p-2 lg:px-14'>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 mt-20 lg:mt-16'>
|
||||
<div className='dark:text-gray-200 mb-5'><i className='fa fa-tags mr-4'/>{locale.COMMON.TAGS}:</div>
|
||||
<div className='dark:text-gray-200 mb-5'><FontAwesomeIcon icon={faTags} className='mr-4'/>{locale.COMMON.TAGS}:</div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{
|
||||
tags.map(tag => {
|
||||
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>
|
||||
})
|
||||
}
|
||||
{ tags.map(tag => {
|
||||
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>
|
||||
}) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user