mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-07 23:16:52 +00:00
Merge pull request #1857 from tangly1024/feat/some-little-improvement
Feat/some-little-improvement
This commit is contained in:
@@ -37,6 +37,8 @@ const BLOG = {
|
|||||||
|
|
||||||
BLOG_FAVICON: process.env.NEXT_PUBLIC_FAVICON || '/favicon.ico', // blog favicon 配置, 默认使用 /public/favicon.ico,支持在线图片,如 https://img.imesong.com/favicon.png
|
BLOG_FAVICON: process.env.NEXT_PUBLIC_FAVICON || '/favicon.ico', // blog favicon 配置, 默认使用 /public/favicon.ico,支持在线图片,如 https://img.imesong.com/favicon.png
|
||||||
|
|
||||||
|
IMAGE_COMPRESS_WIDTH: process.env.NEXT_PUBLIC_IMAGE_COMPRESS_WIDTH || 800, // 图片压缩宽度默认值,作用于博客封面和文章内容 越小加载图片越快
|
||||||
|
IMAGE_ZOOM_IN_WIDTH: process.env.NEXT_PUBLIC_IMAGE_ZOOM_IN_WIDTH || 1200, // 文章图片点击放大后的画质宽度,不代表在网页中的实际展示宽度
|
||||||
RANDOM_IMAGE_URL: process.env.NEXT_PUBLIC_RANDOM_IMAGE_URL || '', // 随机图片API,如果未配置下面的关键字,主页封面,头像,文章封面图都会被替换为随机图片
|
RANDOM_IMAGE_URL: process.env.NEXT_PUBLIC_RANDOM_IMAGE_URL || '', // 随机图片API,如果未配置下面的关键字,主页封面,头像,文章封面图都会被替换为随机图片
|
||||||
RANDOM_IMAGE_REPLACE_TEXT: process.env.NEXT_PUBLIC_RANDOM_IMAGE_NOT_REPLACE_TEXT || 'images.unsplash.com', // 触发替换图片的 url 关键字(多个支持用英文逗号分开),只有图片地址中包含此关键字才会替换为上方随机图片url
|
RANDOM_IMAGE_REPLACE_TEXT: process.env.NEXT_PUBLIC_RANDOM_IMAGE_NOT_REPLACE_TEXT || 'images.unsplash.com', // 触发替换图片的 url 关键字(多个支持用英文逗号分开),只有图片地址中包含此关键字才会替换为上方随机图片url
|
||||||
// eg: images.unsplash.com(notion图床的所有图片都会替换),如果你在 notion 里已经添加了一个随机图片 url,恰巧那个服务跑路或者挂掉,想一键切换所有配图可以将该 url 配置在这里
|
// eg: images.unsplash.com(notion图床的所有图片都会替换),如果你在 notion 里已经添加了一个随机图片 url,恰巧那个服务跑路或者挂掉,想一键切换所有配图可以将该 url 配置在这里
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import dynamic from 'next/dynamic'
|
|||||||
import mediumZoom from '@fisch0920/medium-zoom'
|
import mediumZoom from '@fisch0920/medium-zoom'
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import 'katex/dist/katex.min.css'
|
import 'katex/dist/katex.min.css'
|
||||||
import { mapImgUrl } from '@/lib/notion/mapImage'
|
import { compressImage, mapImgUrl } from '@/lib/notion/mapImage'
|
||||||
import { isBrowser } from '@/lib/utils'
|
import { isBrowser } from '@/lib/utils'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { NotionRenderer } from 'react-notion-x'
|
import { NotionRenderer } from 'react-notion-x'
|
||||||
@@ -61,6 +61,11 @@ const Tweet = ({ id }) => {
|
|||||||
return <TweetEmbed tweetId={id} />
|
return <TweetEmbed tweetId={id} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notin渲染成网页的核心组件
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
const NotionPage = ({ post, className }) => {
|
const NotionPage = ({ post, className }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
autoScrollToTarget()
|
autoScrollToTarget()
|
||||||
@@ -74,6 +79,8 @@ const NotionPage = ({ post, className }) => {
|
|||||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!isBrowser) return;
|
||||||
|
|
||||||
// 将相册gallery下的图片加入放大功能
|
// 将相册gallery下的图片加入放大功能
|
||||||
if (siteConfig('POST_DISABLE_GALLERY_CLICK')) {
|
if (siteConfig('POST_DISABLE_GALLERY_CLICK')) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -111,6 +118,30 @@ const NotionPage = ({ post, className }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 放大图片:调整图片质量
|
||||||
|
const observer = new MutationObserver((mutationsList, observer) => {
|
||||||
|
mutationsList.forEach(mutation => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||||
|
if (mutation.target.classList.contains('medium-zoom-image--opened')) {
|
||||||
|
// 等待动画完成后替换为更高清的图像
|
||||||
|
setTimeout(() => {
|
||||||
|
// 获取该元素的 src 属性
|
||||||
|
const src = mutation?.target?.getAttribute('src');
|
||||||
|
// 替换为更高清的图像
|
||||||
|
mutation?.target?.setAttribute('src', compressImage(src, siteConfig('IMAGE_ZOOM_IN_WIDTH', 1200)));
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监视整个文档中的元素和属性的变化
|
||||||
|
observer.observe(document.body, { attributes: true, subtree: true, attributeFilter: ['class'] });
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (!post || !post.blockMap) {
|
if (!post || !post.blockMap) {
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ const ThemeSwitch = () => {
|
|||||||
const query = router.query
|
const query = router.query
|
||||||
query.theme = newTheme
|
query.theme = newTheme
|
||||||
router.push({ pathname: router.pathname, query }).then(() => {
|
router.push({ pathname: router.pathname, query }).then(() => {
|
||||||
setIsLoading(false)
|
setTimeout(() => {
|
||||||
|
setIsLoading(false)
|
||||||
|
}, 500);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +74,8 @@ const ThemeSwitch = () => {
|
|||||||
</Draggable>
|
</Draggable>
|
||||||
|
|
||||||
{/* 切换主题加载时的全屏遮罩 */}
|
{/* 切换主题加载时的全屏遮罩 */}
|
||||||
<div className={`${isLoading ? 'opacity-50 ' : 'opacity-0'}
|
<div className={`${isLoading ? 'opacity-90 ' : 'opacity-0'}
|
||||||
w-screen h-screen bg-black text-white shadow-text flex justify-center items-center
|
w-screen h-screen glassmorphism bg-black text-white shadow-text flex justify-center items-center
|
||||||
transition-all fixed top-0 left-0 pointer-events-none duration-1000 z-50 shadow-inner`}>
|
transition-all fixed top-0 left-0 pointer-events-none duration-1000 z-50 shadow-inner`}>
|
||||||
<i className='text-3xl mr-5 fas fa-spinner animate-spin' />
|
<i className='text-3xl mr-5 fas fa-spinner animate-spin' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { getAllCategories } from './getAllCategories'
|
|||||||
import getAllPageIds from './getAllPageIds'
|
import getAllPageIds from './getAllPageIds'
|
||||||
import { getAllTags } from './getAllTags'
|
import { getAllTags } from './getAllTags'
|
||||||
import getPageProperties from './getPageProperties'
|
import getPageProperties from './getPageProperties'
|
||||||
import { mapImgUrl, compressImage } from './mapImage'
|
import { compressImage, mapImgUrl } from './mapImage'
|
||||||
import { getConfigMapFromConfigPage } from './getNotionConfig'
|
import { getConfigMapFromConfigPage } from './getNotionConfig'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import BLOG from '@/blog.config'
|
import BLOG from '@/blog.config'
|
||||||
|
import { siteConfig } from '../config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片映射
|
* 图片映射
|
||||||
@@ -58,7 +59,7 @@ const mapImgUrl = (img, block, type = 'block', from = 'post') => {
|
|||||||
|
|
||||||
// 统一压缩图片
|
// 统一压缩图片
|
||||||
if (from === 'pageCoverThumbnail' || block.type === 'image' || block.type === 'page') {
|
if (from === 'pageCoverThumbnail' || block.type === 'image' || block.type === 'page') {
|
||||||
const width = block?.format?.block_width || 200
|
const width = block?.format?.block_width
|
||||||
ret = compressImage(ret, width)
|
ret = compressImage(ret, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,19 +82,29 @@ function isEmoji(str) {
|
|||||||
* 2. UnPlash 图片可以通过api q=50 控制压缩质量 width=400 控制图片尺寸
|
* 2. UnPlash 图片可以通过api q=50 控制压缩质量 width=400 控制图片尺寸
|
||||||
* @param {*} image
|
* @param {*} image
|
||||||
*/
|
*/
|
||||||
const compressImage = (image, width = 800, quality = 50, fmt = 'webp') => {
|
const compressImage = (image, width, quality = 50, fmt = 'webp') => {
|
||||||
if (!image) {
|
if (!image || image.indexOf('http') !== 0) {
|
||||||
return null
|
return image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!width || width === 0) {
|
||||||
|
width = siteConfig('IMAGE_COMPRESS_WIDTH')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将URL解析为一个对象
|
||||||
|
const urlObj = new URL(image)
|
||||||
|
// 获取URL参数
|
||||||
|
const params = new URLSearchParams(urlObj.search)
|
||||||
|
|
||||||
|
// Notion图床
|
||||||
if (image.indexOf(BLOG.NOTION_HOST) === 0 && image.indexOf('amazonaws.com') > 0) {
|
if (image.indexOf(BLOG.NOTION_HOST) === 0 && image.indexOf('amazonaws.com') > 0) {
|
||||||
return `${image}&width=${width}&cache=v2`
|
params.set('width', width)
|
||||||
}
|
params.set('cache', 'v2')
|
||||||
// 压缩unsplash图片
|
// 生成新的URL
|
||||||
if (image.indexOf('https://images.unsplash.com/') === 0) {
|
urlObj.search = params.toString()
|
||||||
// 将URL解析为一个对象
|
return urlObj.toString()
|
||||||
const urlObj = new URL(image)
|
} else if (image.indexOf('https://images.unsplash.com/') === 0) {
|
||||||
// 获取URL参数
|
// 压缩unsplash图片
|
||||||
const params = new URLSearchParams(urlObj.search)
|
|
||||||
// 将q参数的值替换
|
// 将q参数的值替换
|
||||||
params.set('q', quality)
|
params.set('q', quality)
|
||||||
// 尺寸
|
// 尺寸
|
||||||
@@ -104,11 +115,9 @@ const compressImage = (image, width = 800, quality = 50, fmt = 'webp') => {
|
|||||||
// 生成新的URL
|
// 生成新的URL
|
||||||
urlObj.search = params.toString()
|
urlObj.search = params.toString()
|
||||||
return urlObj.toString()
|
return urlObj.toString()
|
||||||
}
|
} else if (image.indexOf('https://your_picture_bed') === 0) {
|
||||||
|
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
||||||
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
|
||||||
// .e.g
|
// .e.g
|
||||||
if (image.indexOf('https://your_picture_bed') === 0) {
|
|
||||||
return 'do_somethin_here'
|
return 'do_somethin_here'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
lib/utils.js
27
lib/utils.js
@@ -30,6 +30,33 @@ export const memorize = (Component) => {
|
|||||||
}
|
}
|
||||||
return memo(MemoizedComponent)
|
return memo(MemoizedComponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 转换外链
|
||||||
|
export function sliceUrlFromHttp(str) {
|
||||||
|
// 检查字符串是否包含http
|
||||||
|
if (str.includes('http')) {
|
||||||
|
// 如果包含,找到http的位置
|
||||||
|
const index = str.indexOf('http');
|
||||||
|
// 返回http之后的部分
|
||||||
|
return str.slice(index, str.length);
|
||||||
|
} else {
|
||||||
|
// 如果不包含,返回原字符串
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否外链
|
||||||
|
export function checkContainHttp(str) {
|
||||||
|
// 检查字符串是否包含http
|
||||||
|
if (str.includes('http')) {
|
||||||
|
// 如果包含,找到http的位置
|
||||||
|
return str.indexOf('http') > -1
|
||||||
|
} else {
|
||||||
|
// 不包含
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载外部资源
|
* 加载外部资源
|
||||||
* @param url 地址 例如 https://xx.com/xx.js
|
* @param url 地址 例如 https://xx.com/xx.js
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class MyDocument extends Document {
|
|||||||
})}
|
})}
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<body className={`${BLOG.FONT_STYLE} font-light scroll-smooth`}>
|
<body className={`${BLOG.FONT_STYLE} dark:bg-black font-light scroll-smooth`}>
|
||||||
<Main />
|
<Main />
|
||||||
<NextScript />
|
<NextScript />
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,8 +15,10 @@ export default function BlogListGroupByDate({ archiveTitle, archivePosts }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle].map(post => (
|
{archivePosts[archiveTitle].map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -24,12 +27,12 @@ export default function BlogListGroupByDate({ archiveTitle, archivePosts }) {
|
|||||||
{post?.publishDay}
|
{post?.publishDay}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
<Link href={url} className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ import CONFIG from '../config'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ post }) => {
|
const BlogPostCard = ({ post }) => {
|
||||||
const showPageCover = siteConfig('EXAMPLE_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
const showPageCover = siteConfig('EXAMPLE_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return <article className={`${showPageCover ? 'flex md:flex-row flex-col-reverse' : ''} replace mb-12 `}>
|
return <article className={`${showPageCover ? 'flex md:flex-row flex-col-reverse' : ''} replace mb-12 `}>
|
||||||
<div className={`${showPageCover ? 'md:w-7/12' : ''}`}>
|
<div className={`${showPageCover ? 'md:w-7/12' : ''}`}>
|
||||||
@@ -41,7 +43,7 @@ const BlogPostCard = ({ post }) => {
|
|||||||
{/* 图片封面 */}
|
{/* 图片封面 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<div className="md:w-5/12 w-full h-44 overflow-hidden p-1">
|
<div className="md:w-5/12 w-full h-44 overflow-hidden p-1">
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<LazyImage src={post?.pageCoverThumbnail} className='w-full bg-cover hover:scale-110 duration-200' />
|
<LazyImage src={post?.pageCoverThumbnail} className='w-full bg-cover hover:scale-110 duration-200' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ import Announcement from './Announcement'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import DarkModeButton from '@/components/DarkModeButton'
|
import DarkModeButton from '@/components/DarkModeButton'
|
||||||
import SocialButton from './SocialButton'
|
import SocialButton from './SocialButton'
|
||||||
import { useFukasawaGlobal } from '..'
|
|
||||||
import CONFIG from '@/themes/fukasawa/config'
|
import CONFIG from '@/themes/fukasawa/config'
|
||||||
import { AdSlot } from '@/components/GoogleAdsense'
|
import { AdSlot } from '@/components/GoogleAdsense'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import MailChimpForm from './MailChimpForm'
|
import MailChimpForm from './MailChimpForm'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { isBrowser } from '@/lib/utils'
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 侧边栏
|
* 侧边栏
|
||||||
@@ -23,39 +26,59 @@ import MailChimpForm from './MailChimpForm'
|
|||||||
function AsideLeft(props) {
|
function AsideLeft(props) {
|
||||||
const { tagOptions, currentTag, categoryOptions, currentCategory, post, slot, notice } = props
|
const { tagOptions, currentTag, categoryOptions, currentCategory, post, slot, notice } = props
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { isCollapsed, setIsCollapse } = useFukasawaGlobal()
|
const { fullWidth } = useGlobal()
|
||||||
|
|
||||||
|
const FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT = fullWidth || siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT', null, CONFIG)
|
||||||
|
|
||||||
|
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
||||||
|
const [isCollapsed, setIsCollapse] = useState(() => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
return localStorage.getItem('fukasawa-sidebar-collapse') === 'true' || FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||||
|
}
|
||||||
|
return FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||||
|
})
|
||||||
|
|
||||||
|
// 在组件卸载时保存 open 状态到本地存储中
|
||||||
|
useEffect(() => {
|
||||||
|
if (isBrowser) {
|
||||||
|
localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed)
|
||||||
|
}
|
||||||
|
}, [isCollapsed])
|
||||||
|
|
||||||
// 折叠侧边栏
|
// 折叠侧边栏
|
||||||
const toggleOpen = () => {
|
const toggleOpen = () => {
|
||||||
setIsCollapse(!isCollapsed)
|
setIsCollapse(!isCollapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动折叠侧边栏 onResize 窗口宽度小于1366 || 滚动条滚动至页面的300px时 ; 将open设置为false
|
// 自动折叠侧边栏 onResize 窗口宽度小于1366 || 滚动条滚动至页面的300px时 ; 将open设置为false
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// const handleResize = debounce(() => {
|
if (!siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_ON_SCROLL', false, CONFIG)) {
|
||||||
// if (window.innerWidth < 1366 || window.scrollY >= 100) {
|
return
|
||||||
// setIsCollapse(true)
|
}
|
||||||
// } else {
|
const handleResize = debounce(() => {
|
||||||
// setIsCollapse(false)
|
if (window.innerWidth < 1366 || window.scrollY >= 1366) {
|
||||||
// }
|
setIsCollapse(true)
|
||||||
// }, 100)
|
} else {
|
||||||
|
setIsCollapse(false)
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
|
||||||
// console.log('router', router)
|
if (post) {
|
||||||
// if (router.pathname === '/[...slug]') {
|
window.addEventListener('resize', handleResize)
|
||||||
// window.addEventListener('resize', handleResize)
|
window.addEventListener('scroll', handleResize, { passive: true })
|
||||||
// window.addEventListener('scroll', handleResize, { passive: true })
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// return () => {
|
return () => {
|
||||||
// if (router.pathname === '/[...slug]') {
|
if (post) {
|
||||||
// window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
// window.removeEventListener('scroll', handleResize, { passive: true })
|
window.removeEventListener('scroll', handleResize, { passive: true })
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }, [])
|
}, [])
|
||||||
|
|
||||||
return <div className={`sideLeft relative ${isCollapsed ? 'w-0' : 'w-80'} duration-150 transition-all bg-white dark:bg-hexo-black-gray min-h-screen hidden lg:block z-20`}>
|
return <div className={`sideLeft relative ${isCollapsed ? 'w-0' : 'w-80'} duration-300 transition-all bg-white dark:bg-hexo-black-gray min-h-screen hidden lg:block z-20`}>
|
||||||
{/* 折叠按钮 */}
|
{/* 折叠按钮 */}
|
||||||
{siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_BUTTON', null, CONFIG) && <div className={`${isCollapsed ? '' : 'ml-80'} hidden lg:block sticky top-0 mx-2 cursor-pointer hover:scale-110 duration-150 px-3 py-2`} onClick={toggleOpen}>
|
{siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_BUTTON', null, CONFIG) && <div className={`${isCollapsed ? '' : 'ml-80'} hidden lg:block sticky top-0 mx-2 cursor-pointer hover:scale-110 duration-300 px-3 py-2`} onClick={toggleOpen}>
|
||||||
{isCollapsed ? <i className="fa-solid fa-indent text-xl"></i> : <i className='fas fa-bars text-xl'></i>}
|
{isCollapsed ? <i className="fa-solid fa-indent text-xl"></i> : <i className='fas fa-bars text-xl'></i>}
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,13 @@ import Link from 'next/link'
|
|||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章列表卡片
|
||||||
|
* @param {*} param0
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||||
const showPreview = siteConfig('FUKASAWA_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('FUKASAWA_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
// fukasawa 强制显示图片
|
// fukasawa 强制显示图片
|
||||||
@@ -11,22 +17,29 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||||
}
|
}
|
||||||
const showPageCover = siteConfig('FUKASAWA_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
const showPageCover = siteConfig('FUKASAWA_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||||
const SUB_PATH = siteConfig('SUB_PATH', '')
|
const FUKASAWA_POST_LIST_ANIMATION = siteConfig('FUKASAWA_POST_LIST_ANIMATION', null, CONFIG)
|
||||||
|
|
||||||
|
// 动画样式 首屏卡片不用,后面翻出来的加动画
|
||||||
|
const aosProps = FUKASAWA_POST_LIST_ANIMATION
|
||||||
|
? {
|
||||||
|
'data-aos': 'fade-up',
|
||||||
|
'data-aos-duration': '300',
|
||||||
|
'data-aos-once': 'true',
|
||||||
|
'data-aos-anchor-placement': 'top-bottom'
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div {...aosProps} style={{ maxHeight: '60rem' }}
|
||||||
data-aos="fade-up"
|
|
||||||
data-aos-duration="600"
|
|
||||||
data-aos-once="true"
|
|
||||||
data-aos-anchor-placement="top-bottom"
|
|
||||||
style={{ maxHeight: '60rem' }}
|
|
||||||
className="w-full lg:max-w-sm p-3 shadow mb-4 mx-2 bg-white dark:bg-hexo-black-gray hover:shadow-lg duration-200"
|
className="w-full lg:max-w-sm p-3 shadow mb-4 mx-2 bg-white dark:bg-hexo-black-gray hover:shadow-lg duration-200"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col justify-between h-full">
|
<div className="flex flex-col justify-between h-full">
|
||||||
{/* 封面图 */}
|
{/* 封面图 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<div className="flex-grow mb-3 w-full duration-200 cursor-pointer transform overflow-hidden">
|
<div className="flex-grow mb-3 w-full duration-200 cursor-pointer transform overflow-hidden">
|
||||||
<Link href={`${SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<LazyImage
|
<LazyImage
|
||||||
src={post?.pageCoverThumbnail}
|
src={post?.pageCoverThumbnail}
|
||||||
alt={post?.title || siteConfig('TITLE')}
|
alt={post?.title || siteConfig('TITLE')}
|
||||||
@@ -38,7 +51,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
|
|
||||||
{/* 文字部分 */}
|
{/* 文字部分 */}
|
||||||
<div className="flex flex-col w-full">
|
<div className="flex flex-col w-full">
|
||||||
<Link passHref href={`${SUB_PATH}/${post.slug}`}
|
<Link passHref href={url}
|
||||||
className={`break-words cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
|
className={`break-words cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
|
||||||
>
|
>
|
||||||
{post.title}
|
{post.title}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客归档
|
* 博客归档
|
||||||
@@ -21,8 +22,9 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{posts?.map(post => (
|
{posts?.map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -30,7 +32,7 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
|||||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const MenuItemCollapse = (props) => {
|
|||||||
<div><div className={`${link.icon} text-center w-4 mr-4`} />{link.name}</div>
|
<div><div className={`${link.icon} text-center w-4 mr-4`} />{link.name}</div>
|
||||||
<div className='inline-flex items-center '><i className={`px-2 fas fa-chevron-right transition-all duration-200 ${isOpen ? 'rotate-90' : ''}`}></i></div>
|
<div className='inline-flex items-center '><i className={`px-2 fas fa-chevron-right transition-all duration-200 ${isOpen ? 'rotate-90' : ''}`}></i></div>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>f
|
||||||
|
|
||||||
{/* 折叠子菜单 */}
|
{/* 折叠子菜单 */}
|
||||||
{hasSubMenu && <Collapse isOpen={isOpen} onHeightChange={props.onHeightChange}>
|
{hasSubMenu && <Collapse isOpen={isOpen} onHeightChange={props.onHeightChange}>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const CONFIG = {
|
|||||||
FUKASAWA_POST_LIST_COVER: true, // 文章列表显示图片封面
|
FUKASAWA_POST_LIST_COVER: true, // 文章列表显示图片封面
|
||||||
FUKASAWA_POST_LIST_COVER_FORCE: false, // 即使没有封面也将站点背景图设置为封面
|
FUKASAWA_POST_LIST_COVER_FORCE: false, // 即使没有封面也将站点背景图设置为封面
|
||||||
FUKASAWA_POST_LIST_PREVIEW: false, // 显示文章预览
|
FUKASAWA_POST_LIST_PREVIEW: false, // 显示文章预览
|
||||||
|
FUKASAWA_POST_LIST_ANIMATION: false, // 博客列表淡入动画
|
||||||
|
|
||||||
// 菜单
|
// 菜单
|
||||||
FUKASAWA_MENU_CATEGORY: true, // 显示分类
|
FUKASAWA_MENU_CATEGORY: true, // 显示分类
|
||||||
@@ -12,7 +13,8 @@ const CONFIG = {
|
|||||||
FUKASAWA_MENU_SEARCH: false, // 显示搜索
|
FUKASAWA_MENU_SEARCH: false, // 显示搜索
|
||||||
|
|
||||||
FUKASAWA_SIDEBAR_COLLAPSE_BUTTON: true, // 侧边栏折叠按钮
|
FUKASAWA_SIDEBAR_COLLAPSE_BUTTON: true, // 侧边栏折叠按钮
|
||||||
FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT: false // 侧边栏默认折叠收起
|
FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT: false, // 侧边栏默认折叠收起
|
||||||
|
FUKASAWA_SIDEBAR_COLLAPSE_ON_SCROLL: false // 侧边栏滚动时折叠 仅文章阅读页有效
|
||||||
|
|
||||||
}
|
}
|
||||||
export default CONFIG
|
export default CONFIG
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import ArticleDetail from './components/ArticleDetail'
|
|||||||
import ArticleLock from './components/ArticleLock'
|
import ArticleLock from './components/ArticleLock'
|
||||||
import TagItemMini from './components/TagItemMini'
|
import TagItemMini from './components/TagItemMini'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { createContext, useContext, useEffect, useState } from 'react'
|
import { createContext, useContext, useEffect } from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Transition } from '@headlessui/react'
|
import { Transition } from '@headlessui/react'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
@@ -48,25 +48,8 @@ const LayoutBase = (props) => {
|
|||||||
const leftAreaSlot = <Live2D />
|
const leftAreaSlot = <Live2D />
|
||||||
const { onLoading, fullWidth } = useGlobal()
|
const { onLoading, fullWidth } = useGlobal()
|
||||||
|
|
||||||
const FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT = fullWidth || siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT', null, CONFIG)
|
|
||||||
|
|
||||||
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
|
||||||
const [isCollapsed, setIsCollapse] = useState(() => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
return localStorage.getItem('fukasawa-sidebar-collapse') === 'true' || FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
|
||||||
}
|
|
||||||
return FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
|
||||||
})
|
|
||||||
|
|
||||||
// 在组件卸载时保存 open 状态到本地存储中
|
|
||||||
useEffect(() => {
|
|
||||||
if (isBrowser) {
|
|
||||||
localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed)
|
|
||||||
}
|
|
||||||
}, [isCollapsed])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeGlobalFukasawa.Provider value={{ isCollapsed, setIsCollapse }}>
|
<ThemeGlobalFukasawa.Provider value={{}}>
|
||||||
|
|
||||||
<div id='theme-fukasawa'>
|
<div id='theme-fukasawa'>
|
||||||
{/* SEO信息 */}
|
{/* SEO信息 */}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组
|
* 归档分组
|
||||||
@@ -13,8 +14,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle]?.map(post => (
|
{archivePosts[archiveTitle]?.map(post => {
|
||||||
<li key={post.id}
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
<div id={post?.publishDay}>
|
<div id={post?.publishDay}>
|
||||||
@@ -23,13 +26,13 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
|
|
||||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
<Link passHref href={url}
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ post, className }) => {
|
const BlogPostCard = ({ post, className }) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const currentSelected = router.asPath.split('?')[0] === '/' + post.slug
|
const currentSelected = router.asPath.split('?')[0] === '/' + post.slug
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
return (
|
return (
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref> <div key={post.id} className={`${className} py-1.5 cursor-pointer px-1.5 hover:bg-gray-50 rounded-md dark:hover:bg-gray-600 ${currentSelected ? 'bg-green-50 text-green-500' : ''}`}>
|
<Link href={url} passHref> <div key={post.id} className={`${className} py-1.5 cursor-pointer px-1.5 hover:bg-gray-50 rounded-md dark:hover:bg-gray-600 ${currentSelected ? 'bg-green-50 text-green-500' : ''}`}>
|
||||||
<div className="flex flex-col w-full select-none">
|
<div className="flex flex-col w-full select-none">
|
||||||
{post.title}
|
{post.title}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
|||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关联推荐文章
|
* 关联推荐文章
|
||||||
@@ -38,12 +39,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
|||||||
const headerImage = post?.pageCoverThumbnail
|
const headerImage = post?.pageCoverThumbnail
|
||||||
? post.pageCoverThumbnail
|
? post.pageCoverThumbnail
|
||||||
: siteInfo?.pageCover
|
: siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="flex h-40 cursor-pointer overflow-hidden rounded-2xl">
|
className="flex h-40 cursor-pointer overflow-hidden rounded-2xl">
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import CONFIG from '../config'
|
|||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客归档列表
|
* 博客归档列表
|
||||||
* @param posts 所有文章
|
* @param posts 所有文章
|
||||||
@@ -24,6 +26,8 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
|||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{posts?.map(post => {
|
{posts?.map(post => {
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
if (post && !post.pageCoverThumbnail && siteConfig('HEO_POST_LIST_COVER_DEFAULT', null, CONFIG)) {
|
if (post && !post.pageCoverThumbnail && siteConfig('HEO_POST_LIST_COVER_DEFAULT', null, CONFIG)) {
|
||||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||||
@@ -34,7 +38,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
|||||||
{/* 图片封面 */}
|
{/* 图片封面 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<div>
|
<div>
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<LazyImage className={'rounded-xl bg-center bg-cover w-40 h-24'} src={post?.pageCoverThumbnail}/>
|
<LazyImage className={'rounded-xl bg-center bg-cover w-40 h-24'} src={post?.pageCoverThumbnail}/>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,7 +57,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
|||||||
|
|
||||||
{/* 标题 */}
|
{/* 标题 */}
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={' group-hover:text-indigo-700 group-hover:dark:text-indigo-400 text-black dark:text-gray-100 dark:group-hover:text-yellow-600 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
className={' group-hover:text-indigo-700 group-hover:dark:text-indigo-400 text-black dark:text-gray-100 dark:group-hover:text-yellow-600 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
||||||
<span className='menu-link '>{post.title}</span>
|
<span className='menu-link '>{post.title}</span>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
|||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||||
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
@@ -10,6 +11,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||||
}
|
}
|
||||||
const showPageCover = siteConfig('HEO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
const showPageCover = siteConfig('HEO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
return (
|
return (
|
||||||
<div className={` ${siteConfig('HEO_POST_LIST_COVER_HOVER_ENLARGE', null, CONFIG) ? ' hover:scale-110 transition-all duration-150' : ''}`} >
|
<div className={` ${siteConfig('HEO_POST_LIST_COVER_HOVER_ENLARGE', null, CONFIG) ? ' hover:scale-110 transition-all duration-150' : ''}`} >
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
|
|
||||||
{/* 图片封面 */}
|
{/* 图片封面 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<div className="w-full md:w-5/12 2xl:w-full overflow-hidden">
|
<div className="w-full md:w-5/12 2xl:w-full overflow-hidden">
|
||||||
<LazyImage priority={index === 0} src={post?.pageCoverThumbnail} alt={post?.title} className='h-60 w-full object-cover group-hover:scale-105 group-hover:brightness-75 transition-all duration-300' />
|
<LazyImage priority={index === 0} src={post?.pageCoverThumbnail} alt={post?.title} className='h-60 w-full object-cover group-hover:scale-105 group-hover:brightness-75 transition-all duration-300' />
|
||||||
</div>
|
</div>
|
||||||
@@ -42,7 +44,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
|
|
||||||
{/* 标题 */}
|
{/* 标题 */}
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={' group-hover:text-indigo-700 dark:hover:text-yellow-700 dark:group-hover:text-yellow-600 text-black dark:text-gray-100 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
className={' group-hover:text-indigo-700 dark:hover:text-yellow-700 dark:group-hover:text-yellow-600 text-black dark:text-gray-100 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
||||||
<span className='menu-link '>{post.title}</span>
|
<span className='menu-link '>{post.title}</span>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最新文章列表
|
* 最新文章列表
|
||||||
@@ -18,11 +19,12 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
|||||||
return <div className='grid grid-cols-2 gap-4'>
|
return <div className='grid grid-cols-2 gap-4'>
|
||||||
{latestPosts.map(post => {
|
{latestPosts.map(post => {
|
||||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link key={post.id} passHref
|
(<Link key={post.id} passHref
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
|
|
||||||
className={'my-3 flex flex-col w-full'}>
|
className={'my-3 flex flex-col w-full'}>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global'
|
|||||||
// import Image from 'next/image'
|
// import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最新文章列表
|
* 最新文章列表
|
||||||
@@ -29,14 +30,14 @@ export default function LatestPostsGroupMini ({ latestPosts, siteInfo }) {
|
|||||||
</div>
|
</div>
|
||||||
{latestPosts.map(post => {
|
{latestPosts.map(post => {
|
||||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={'my-3 flex'}>
|
className={'my-3 flex'}>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关联推荐文章
|
* 关联推荐文章
|
||||||
@@ -33,12 +34,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
|||||||
const headerImage = post?.pageCoverThumbnail
|
const headerImage = post?.pageCoverThumbnail
|
||||||
? post.pageCoverThumbnail
|
? post.pageCoverThumbnail
|
||||||
: siteInfo?.pageCover
|
: siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="flex h-40 cursor-pointer overflow-hidden">
|
className="flex h-40 cursor-pointer overflow-hidden">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客归档列表
|
* 博客归档列表
|
||||||
@@ -21,8 +22,9 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{posts?.map(post => (
|
{posts?.map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -30,7 +32,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import CONFIG from '../config'
|
|||||||
import { BlogPostCardInfo } from './BlogPostCardInfo'
|
import { BlogPostCardInfo } from './BlogPostCardInfo'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
// import Image from 'next/image'
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||||
const showPreview = siteConfig('HEXO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('HEXO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
@@ -12,6 +12,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
}
|
}
|
||||||
const showPageCover = siteConfig('HEXO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
const showPageCover = siteConfig('HEXO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
||||||
// const delay = (index % 2) * 200
|
// const delay = (index % 2) * 200
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
{/* 图片封面 */}
|
{/* 图片封面 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<div className="md:w-5/12 overflow-hidden">
|
<div className="md:w-5/12 overflow-hidden">
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<LazyImage priority={index === 1} src={post?.pageCoverThumbnail} className='h-56 w-full object-cover object-center group-hover:scale-110 duration-500' />
|
<LazyImage priority={index === 1} src={post?.pageCoverThumbnail} className='h-56 w-full object-cover object-center group-hover:scale-110 duration-500' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import TagItemMini from './TagItemMini'
|
|||||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { formatDateFmt } from '@/lib/formatDate'
|
import { formatDateFmt } from '@/lib/formatDate'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客列表的文字内容
|
* 博客列表的文字内容
|
||||||
@@ -11,11 +12,12 @@ import { formatDateFmt } from '@/lib/formatDate'
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary }) => {
|
export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary }) => {
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
return <div className={`flex flex-col justify-between lg:p-6 p-4 ${showPageCover && !showPreview ? 'md:w-7/12 w-full md:max-h-60' : 'w-full'}`}>
|
return <div className={`flex flex-col justify-between lg:p-6 p-4 ${showPageCover && !showPreview ? 'md:w-7/12 w-full md:max-h-60' : 'w-full'}`}>
|
||||||
<div>
|
<div>
|
||||||
{/* 标题 */}
|
{/* 标题 */}
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={`line-clamp-2 replace cursor-pointer text-2xl ${showPreview ? 'text-center' : ''
|
className={`line-clamp-2 replace cursor-pointer text-2xl ${showPreview ? 'text-center' : ''
|
||||||
} leading-tight font-normal text-gray-600 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}>
|
} leading-tight font-normal text-gray-600 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global'
|
|||||||
// import Image from 'next/image'
|
// import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最新文章列表
|
* 最新文章列表
|
||||||
@@ -28,15 +29,15 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{latestPosts.map(post => {
|
{latestPosts.map(post => {
|
||||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
|
||||||
|
|
||||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
const selected = currentPath === url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={'my-3 flex'}>
|
className={'my-3 flex'}>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关联推荐文章
|
* 关联推荐文章
|
||||||
@@ -33,12 +34,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
|||||||
const headerImage = post?.pageCoverThumbnail
|
const headerImage = post?.pageCoverThumbnail
|
||||||
? post.pageCoverThumbnail
|
? post.pageCoverThumbnail
|
||||||
: siteInfo?.pageCover
|
: siteInfo?.pageCover
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="flex h-40 cursor-pointer overflow-hidden">
|
className="flex h-40 cursor-pointer overflow-hidden">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客归档列表
|
* 博客归档列表
|
||||||
@@ -21,17 +22,17 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{posts?.map(post => (
|
{posts?.map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
||||||
>
|
>
|
||||||
<div id={post?.publishDay}>
|
<div id={post?.publishDay}>
|
||||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link href={url} passHref
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
|
||||||
passHref
|
|
||||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
{post.title}
|
{post.title}
|
||||||
@@ -39,7 +40,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import CONFIG from '../config'
|
|||||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
import { formatDateFmt } from '@/lib/formatDate'
|
import { formatDateFmt } from '@/lib/formatDate'
|
||||||
// import Image from 'next/image'
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||||
const showPreview = siteConfig('MATERY_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('MATERY_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
@@ -15,6 +15,8 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
}
|
}
|
||||||
const showPageCover = siteConfig('MATERY_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
const showPageCover = siteConfig('MATERY_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||||
const delay = (index % 3) * 300
|
const delay = (index % 3) * 300
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-aos="zoom-in"
|
data-aos="zoom-in"
|
||||||
@@ -29,7 +31,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
|||||||
|
|
||||||
{/* 头部图片 填充卡片 */}
|
{/* 头部图片 填充卡片 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<div className="flex flex-grow w-full relative duration-200 = rounded-t-md cursor-pointer transform overflow-hidden">
|
<div className="flex flex-grow w-full relative duration-200 = rounded-t-md cursor-pointer transform overflow-hidden">
|
||||||
<LazyImage
|
<LazyImage
|
||||||
src={post?.pageCoverThumbnail}
|
src={post?.pageCoverThumbnail}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组
|
* 归档分组
|
||||||
@@ -13,23 +14,25 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle]?.map(post => (
|
{archivePosts[archiveTitle]?.map(post => {
|
||||||
<li key={post.id}
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
<div id={post?.publishDay}>
|
<div id={post?.publishDay}>
|
||||||
<span className="text-gray-400">
|
<span className="text-gray-400">
|
||||||
{post.date?.start_date}
|
{post.date?.start_date}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
|
|
||||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
<Link passHref href={url}
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import CategoryItem from './CategoryItem'
|
|||||||
import TagItemMini from './TagItemMini'
|
import TagItemMini from './TagItemMini'
|
||||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ post, showSummary }) => {
|
const BlogPostCard = ({ post, showSummary }) => {
|
||||||
const showPreview = siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
const showPreview = siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={post.id}
|
key={post.id}
|
||||||
@@ -23,7 +25,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
|
|
||||||
<div className="lg:py-8 py-4 flex flex-col w-full">
|
<div className="lg:py-8 py-4 flex flex-col w-full">
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={
|
className={
|
||||||
'cursor-pointer font-bold hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-green-500 dark:hover:text-green-400'
|
'cursor-pointer font-bold hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-green-500 dark:hover:text-green-400'
|
||||||
@@ -62,7 +64,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
|||||||
<div className="pointer-events-none border-t pt-8 border-dashed">
|
<div className="pointer-events-none border-t pt-8 border-dashed">
|
||||||
<div className="w-full justify-start flex">
|
<div className="w-full justify-start flex">
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="hover:bg-opacity-100 hover:scale-105 duration-200 pointer-events-auto transform font-bold text-green-500 cursor-pointer">
|
className="hover:bg-opacity-100 hover:scale-105 duration-200 pointer-events-auto transform font-bold text-green-500 cursor-pointer">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组
|
* 归档分组
|
||||||
@@ -13,8 +14,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle]?.map(post => (
|
{archivePosts[archiveTitle]?.map(post => {
|
||||||
<li key={post.id}
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
<div id={post?.publishDay}>
|
<div id={post?.publishDay}>
|
||||||
@@ -23,13 +26,13 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
|
|
||||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
<Link passHref href={url}
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Link from 'next/link'
|
|||||||
import NotionIcon from './NotionIcon'
|
import NotionIcon from './NotionIcon'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ post, className }) => {
|
const BlogPostCard = ({ post, className }) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -22,30 +23,6 @@ const BlogPostCard = ({ post, className }) => {
|
|||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
|
|
||||||
// 检查连接是否是外链
|
|
||||||
function sliceUrlFromHttp(str) {
|
|
||||||
// 检查字符串是否包含http
|
|
||||||
if (str.includes('http')) {
|
|
||||||
// 如果包含,找到http的位置
|
|
||||||
const index = str.indexOf('http');
|
|
||||||
// 返回http之后的部分
|
|
||||||
return str.slice(index, str.length);
|
|
||||||
} else {
|
|
||||||
// 如果不包含,返回原字符串
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function checkContainHttp(str) {
|
|
||||||
// 检查字符串是否包含http
|
|
||||||
if (str.includes('http')) {
|
|
||||||
// 如果包含,找到http的位置
|
|
||||||
return str.indexOf('http') > -1
|
|
||||||
} else {
|
|
||||||
// 不包含
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogPostCard
|
export default BlogPostCard
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 博客归档列表
|
* 博客归档列表
|
||||||
@@ -21,8 +22,10 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
{archiveTitle}
|
{archiveTitle}
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{posts?.map(post => (
|
{posts?.map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -30,7 +33,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
<span className="text-gray-500">{post.date?.start_date}</span>{' '}
|
<span className="text-gray-500">{post.date?.start_date}</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -39,7 +42,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import NotionIcon from '@/components/NotionIcon'
|
|||||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||||
import { formatDateFmt } from '@/lib/formatDate'
|
import { formatDateFmt } from '@/lib/formatDate'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPostCard = ({ post, index, showSummary }) => {
|
const BlogPostCard = ({ post, index, showSummary }) => {
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
@@ -22,6 +23,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
|||||||
'data-aos-anchor-placement': 'top-bottom'
|
'data-aos-anchor-placement': 'top-bottom'
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="w-full">
|
<Card className="w-full">
|
||||||
@@ -34,7 +36,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
|||||||
{/* 文章标题 */}
|
{/* 文章标题 */}
|
||||||
<Link
|
<Link
|
||||||
{...aosProps}
|
{...aosProps}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={`cursor-pointer text-3xl ${showPreview ? 'text-center' : ''} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
className={`cursor-pointer text-3xl ${showPreview ? 'text-center' : ''} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
||||||
|
|
||||||
@@ -99,7 +101,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
|||||||
|
|
||||||
<div className="text-right border-t pt-8 border-dashed">
|
<div className="text-right border-t pt-8 border-dashed">
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
className="hover:bg-opacity-100 hover:underline transform duration-300 p-3 text-white bg-gray-800 cursor-pointer">
|
className="hover:bg-opacity-100 hover:underline transform duration-300 p-3 text-white bg-gray-800 cursor-pointer">
|
||||||
|
|
||||||
{locale.COMMON.ARTICLE_DETAIL}
|
{locale.COMMON.ARTICLE_DETAIL}
|
||||||
@@ -110,7 +112,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{siteConfig('NEXT_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && (
|
{siteConfig('NEXT_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && (
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||||
<Image
|
<Image
|
||||||
className="hover:scale-105 transform duration-500"
|
className="hover:scale-105 transform duration-500"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { siteConfig } from '@/lib/config'
|
|||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最新文章列表
|
* 最新文章列表
|
||||||
@@ -27,11 +28,12 @@ const LatestPostsGroup = ({ latestPosts }) => {
|
|||||||
</div>
|
</div>
|
||||||
{latestPosts.map(post => {
|
{latestPosts.map(post => {
|
||||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
return (
|
return (
|
||||||
(<Link
|
(<Link
|
||||||
key={post.id}
|
key={post.id}
|
||||||
title={post.title}
|
title={post.title}
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className={'my-1 flex font-light'}>
|
className={'my-1 flex font-light'}>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组文章
|
* 归档分组文章
|
||||||
@@ -14,8 +15,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle].map(post => (
|
{archivePosts[archiveTitle].map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -25,7 +28,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -34,7 +37,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
const BlogPost = ({ post }) => {
|
const BlogPost = ({ post }) => {
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}>
|
(<Link href={url}>
|
||||||
|
|
||||||
<article key={post.id} className="mb-6 md:mb-8">
|
<article key={post.id} className="mb-6 md:mb-8">
|
||||||
<header className="flex flex-col justify-between md:flex-row md:items-baseline">
|
<header className="flex flex-col justify-between md:flex-row md:items-baseline">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组文章
|
* 归档分组文章
|
||||||
@@ -14,8 +15,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle].map(post => (
|
{archivePosts[archiveTitle].map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -25,7 +28,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -34,7 +37,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import LazyImage from '@/components/LazyImage'
|
|||||||
*/
|
*/
|
||||||
const BlogPost = (props) => {
|
const BlogPost = (props) => {
|
||||||
const { post, index, siteInfo } = props
|
const { post, index, siteInfo } = props
|
||||||
const pageThumbnail = compressImage(post?.pageCoverThumbnail || siteInfo?.pageCover, 800, 80)
|
const pageThumbnail = compressImage(post?.pageCoverThumbnail || siteInfo?.pageCover)
|
||||||
const { setModalContent, setShowModal } = usePlogGlobal()
|
const { setModalContent, setShowModal } = usePlogGlobal()
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setShowModal(true)
|
setShowModal(true)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const LayoutBase = props => {
|
|||||||
|
|
||||||
// 页面切换关闭遮罩
|
// 页面切换关闭遮罩
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const closeModal = ()=>{
|
const closeModal = () => {
|
||||||
setShowModal(false)
|
setShowModal(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,6 @@ const LayoutBase = props => {
|
|||||||
}
|
}
|
||||||
}, [router.events])
|
}, [router.events])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
||||||
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen'>
|
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen'>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档分组文章
|
* 归档分组文章
|
||||||
@@ -14,8 +15,9 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{archivePosts[archiveTitle].map(post => (
|
{archivePosts[archiveTitle].map(post => {
|
||||||
<li
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
return <li
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||||
>
|
>
|
||||||
@@ -25,7 +27,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
passHref
|
passHref
|
||||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||||
|
|
||||||
@@ -34,7 +36,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import TwikooCommentCount from '@/components/TwikooCommentCount'
|
|||||||
import { formatDateFmt } from '@/lib/formatDate'
|
import { formatDateFmt } from '@/lib/formatDate'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import LazyImage from '@/components/LazyImage'
|
import LazyImage from '@/components/LazyImage'
|
||||||
|
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||||
|
|
||||||
export const BlogItem = props => {
|
export const BlogItem = props => {
|
||||||
const { post } = props
|
const { post } = props
|
||||||
const showPageCover = siteConfig('SIMPLE_POST_COVER_ENABLE', false, CONFIG)
|
const showPageCover = siteConfig('SIMPLE_POST_COVER_ENABLE', false, CONFIG)
|
||||||
|
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||||
|
|
||||||
return <div key={post.id} className="h-42 my-6 pb-12 border-b dark:border-gray-800" >
|
return <div key={post.id} className="h-42 my-6 pb-12 border-b dark:border-gray-800" >
|
||||||
{/* 文章标题 */}
|
{/* 文章标题 */}
|
||||||
@@ -17,7 +19,7 @@ export const BlogItem = props => {
|
|||||||
{/* 图片封面 */}
|
{/* 图片封面 */}
|
||||||
{showPageCover && (
|
{showPageCover && (
|
||||||
<div className="overflow-hidden mr-2 w-56 h-full">
|
<div className="overflow-hidden mr-2 w-56 h-full">
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
<Link href={url} passHref legacyBehavior>
|
||||||
<LazyImage src={post?.pageCoverThumbnail} className='w-56 h-full object-cover object-center group-hover:scale-110 duration-500' />
|
<LazyImage src={post?.pageCoverThumbnail} className='w-56 h-full object-cover object-center group-hover:scale-110 duration-500' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,7 +29,7 @@ export const BlogItem = props => {
|
|||||||
<div className='article-info'>
|
<div className='article-info'>
|
||||||
<h2 className="mb-2">
|
<h2 className="mb-2">
|
||||||
<Link
|
<Link
|
||||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
href={url}
|
||||||
className="blog-item-title font-bold text-black text-2xl menu-link">
|
className="blog-item-title font-bold text-black text-2xl menu-link">
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
@@ -60,7 +62,7 @@ export const BlogItem = props => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='block'>
|
<div className='block'>
|
||||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} className='inline-block rounded-sm text-blue-600 text-xs dark:border-gray-800 border hover:text-red-400 transition-all duration-200 hover:border-red-300 h-9 leading-8 px-5'>
|
<Link href={url} className='inline-block rounded-sm text-blue-600 text-xs dark:border-gray-800 border hover:text-red-400 transition-all duration-200 hover:border-red-300 h-9 leading-8 px-5'>
|
||||||
Continue Reading <i className="fa-solid fa-angle-right align-middle"></i>
|
Continue Reading <i className="fa-solid fa-angle-right align-middle"></i>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import Link from 'next/link'
|
|||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
import SocialButton from './SocialButton'
|
import SocialButton from './SocialButton'
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
import { compressImage } from '@/lib/notion/mapImage'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网站顶部
|
* 网站顶部
|
||||||
@@ -11,7 +10,6 @@ import { compressImage } from '@/lib/notion/mapImage'
|
|||||||
*/
|
*/
|
||||||
export default function Header (props) {
|
export default function Header (props) {
|
||||||
const { siteInfo } = props
|
const { siteInfo } = props
|
||||||
const avatar = compressImage(siteInfo?.icon || siteConfig('AVATAR'), 200)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="text-center justify-between items-center px-6 bg-white h-80 dark:bg-black relative z-10">
|
<header className="text-center justify-between items-center px-6 bg-white h-80 dark:bg-black relative z-10">
|
||||||
@@ -20,7 +18,7 @@ export default function Header (props) {
|
|||||||
{/* 可使用一张单图作为logo */}
|
{/* 可使用一张单图作为logo */}
|
||||||
<div className='flex space-x-6'>
|
<div className='flex space-x-6'>
|
||||||
<div className='hover:rotate-45 hover:scale-125 transform duration-200 cursor-pointer justify-center items-center flex'>
|
<div className='hover:rotate-45 hover:scale-125 transform duration-200 cursor-pointer justify-center items-center flex'>
|
||||||
<LazyImage priority={true} src={avatar} className='rounded-full' width={100} height={100} alt={siteConfig('AUTHOR')} />
|
<LazyImage priority={true} src={siteInfo?.icon} className='rounded-full' width={100} height={100} alt={siteConfig('AUTHOR')} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex-col flex justify-center'>
|
<div className='flex-col flex justify-center'>
|
||||||
|
|||||||
Reference in New Issue
Block a user