diff --git a/components/CustomContextMenu.js b/components/CustomContextMenu.js index 74fafbe8a83..8402f20e55a 100644 --- a/components/CustomContextMenu.js +++ b/components/CustomContextMenu.js @@ -57,12 +57,10 @@ export default function CustomContextMenu(props) { } /** - * 鼠标点击事件 + * 鼠标点击即关闭菜单 */ const handleClick = event => { - if (menuRef.current && !menuRef.current.contains(event.target)) { - setShow(false) - } + setShow(false) } window.addEventListener('contextmenu', handleContextMenu) @@ -88,7 +86,6 @@ export default function CustomContextMenu(props) { function handleScrollTop() { window.scrollTo({ top: 0, behavior: 'smooth' }) - setShow(false) } function handleCopyLink() { @@ -96,12 +93,12 @@ export default function CustomContextMenu(props) { navigator.clipboard .writeText(url) .then(() => { - console.log('页面地址已复制') + // console.log('页面地址已复制') + alert(`${locale.COMMON.PAGE_URL_COPIED} : ${url}`) }) .catch(error => { console.error('复制页面地址失败:', error) }) - setShow(false) } /** @@ -130,8 +127,6 @@ export default function CustomContextMenu(props) { } else { // alert("Please select some text first."); } - - setShow(false) } function handleChangeDarkMode() { diff --git a/components/LazyImage.js b/components/LazyImage.js index 4e353ad8527..73a20f89dde 100644 --- a/components/LazyImage.js +++ b/components/LazyImage.js @@ -20,6 +20,8 @@ export default function LazyImage({ style }) { const maxWidth = siteConfig('IMAGE_COMPRESS_WIDTH') + const defaultPlaceholderSrc = siteConfig('IMG_LAZY_LOAD_PLACEHOLDER') + const imageRef = useRef(null) const [adjustedSrc, setAdjustedSrc] = useState( placeholderSrc || siteConfig('IMG_LAZY_LOAD_PLACEHOLDER') @@ -37,6 +39,14 @@ export default function LazyImage({ onLoad() // 触发传递的onLoad回调函数 } } + /** + * 图片加载失败回调 + */ + const handleImageError = () => { + if (imageRef.current) { + imageRef.current.src = defaultPlaceholderSrc + } + } useEffect(() => { const adjustedImageSrc = adjustImgSize(src, maxWidth) @@ -71,7 +81,8 @@ export default function LazyImage({ ref: imageRef, src: priority ? adjustedSrc : placeholderSrc, alt: alt, - onLoad: handleImageLoad + onLoad: handleImageLoad, + onError: handleImageError // 添加onError处理函数 } if (id) { diff --git a/lib/lang/en-US.js b/lib/lang/en-US.js index 985e0a24e54..f60b375ae13 100644 --- a/lib/lang/en-US.js +++ b/lib/lang/en-US.js @@ -33,10 +33,14 @@ export default { COPYRIGHT: 'Copyright', AUTHOR: 'Author', URL: 'URL', + NOW: 'NOW', + RECOMMEND_BADGES: 'Recommend', + BLOG: 'Blog', POSTS: 'Posts', ARTICLE: 'Article', VISITORS: 'Visitors', VIEWS: 'Views', + PAGE_URL_COPIED: 'Page URL copied', COPYRIGHT_NOTICE: 'All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!', RESULT_OF_SEARCH: 'Results Found', diff --git a/lib/lang/zh-CN.js b/lib/lang/zh-CN.js index e38a27bf669..4dd1962e764 100644 --- a/lib/lang/zh-CN.js +++ b/lib/lang/zh-CN.js @@ -35,10 +35,14 @@ export default { AUTHOR: '作者', URL: '链接', ANALYTICS: '统计', + RECOMMEND_BADGES: '荐', + BLOG: '博客', + NOW: '此刻', POSTS: '篇文章', ARTICLE: '文章', VISITORS: '位访客', VIEWS: '次查看', + PAGE_URL_COPIED: '页面地址已复制', COPYRIGHT_NOTICE: '本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。', RESULT_OF_SEARCH: '篇搜索到的结果', NO_RESULTS_FOUND: '没有找到文章', diff --git a/styles/notion.css b/styles/notion.css index e5f8c14ff1b..ba794f88772 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -1451,6 +1451,7 @@ code[class*='language-'] { .notion-collection-card-property .notion-page-title-text { border-bottom: 0 none; + @apply dark:text-gray-200; } .notion-collection-card-property diff --git a/themes/heo/components/BlogPostCard.js b/themes/heo/components/BlogPostCard.js index 3a1cf6893a6..b26256e4d27 100644 --- a/themes/heo/components/BlogPostCard.js +++ b/themes/heo/components/BlogPostCard.js @@ -50,11 +50,11 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => { {/* 分类 */} {post?.category && ( diff --git a/themes/heo/components/CategoryBar.js b/themes/heo/components/CategoryBar.js index eccd9685621..9879d8a78cd 100644 --- a/themes/heo/components/CategoryBar.js +++ b/themes/heo/components/CategoryBar.js @@ -29,23 +29,40 @@ export default function CategoryBar(props) { } } - return
+
+ + {categoryOptions?.map((c, index) => ( + + ))} +
-
- - {categoryOptions?.map((c, index) => )} -
- -
- - - {locale.MENU.CATEGORY} - +
+ + + {locale.MENU.CATEGORY} + +
+ ) } /** @@ -57,7 +74,10 @@ const MenuItem = ({ href, name }) => { const router = useRouter() const { category } = router.query const selected = category === name - return
- {name} + return ( +
+ {name}
+ ) } diff --git a/themes/heo/components/Footer.js b/themes/heo/components/Footer.js index 8a4499a8404..a4018b7456f 100644 --- a/themes/heo/components/Footer.js +++ b/themes/heo/components/Footer.js @@ -1,49 +1,66 @@ -import SocialButton from './SocialButton' import { siteConfig } from '@/lib/config' +import SocialButton from './SocialButton' const Footer = ({ title }) => { const d = new Date() const currentYear = d.getFullYear() const since = siteConfig('SINCE') - const copyrightDate = parseInt(since) < currentYear ? since + '-' + currentYear : currentYear + const copyrightDate = + parseInt(since) < currentYear ? since + '-' + currentYear : currentYear return ( -
- - {/* 颜色过度区 */} -
- -
+
+ {/* 颜色过度区 */} +
- {/* 社交按钮 */} -
- -
+ {/* 社交按钮 */} +
+ +
-
+
- {/* 底部页面信息 */} -
+
+ ) } diff --git a/themes/heo/components/Header.js b/themes/heo/components/Header.js index 35b6f058de0..f0b823dc994 100644 --- a/themes/heo/components/Header.js +++ b/themes/heo/components/Header.js @@ -1,6 +1,7 @@ import { siteConfig } from '@/lib/config' import { isBrowser } from '@/lib/utils' import throttle from 'lodash.throttle' +import { useRouter } from 'next/router' import { useCallback, useEffect, useRef, useState } from 'react' import DarkModeButton from './DarkModeButton' import Logo from './Logo' @@ -21,6 +22,7 @@ const Header = props => { const [navBgWhite, setBgWhite] = useState(false) const [activeIndex, setActiveIndex] = useState(0) + const router = useRouter() const slideOverRef = useRef() const toggleMenuOpen = () => { @@ -34,15 +36,15 @@ const Header = props => { throttle(() => { const scrollS = window.scrollY // 导航栏设置 白色背景 - if (scrollS <= 0) { + if (scrollS <= 1) { setFixedNav(false) setBgWhite(false) + setTextWhite(false) // 文章详情页特殊处理 - if (document.querySelector('#post-bg')) { + if (document?.querySelector('#post-bg')) { setFixedNav(true) setTextWhite(true) - setBgWhite(false) } } else { // 向下滚动后的导航样式 @@ -50,19 +52,21 @@ const Header = props => { setTextWhite(false) setBgWhite(true) } - }, 200) + }, 100) ) + useEffect(() => { + scrollTrigger() + }, [router]) // 监听滚动 useEffect(() => { - scrollTrigger() window.addEventListener('scroll', scrollTrigger) return () => { window.removeEventListener('scroll', scrollTrigger) } }, []) - // 监听导航栏显示文字 + // 导航栏根据滚动轮播菜单内容 useEffect(() => { let prevScrollY = 0 let ticking = false @@ -71,17 +75,14 @@ const Header = props => { if (!ticking) { window.requestAnimationFrame(() => { const currentScrollY = window.scrollY - if (currentScrollY > prevScrollY) { setActiveIndex(1) // 向下滚动时设置activeIndex为1 } else { setActiveIndex(0) // 向上滚动时设置activeIndex为0 } - prevScrollY = currentScrollY ticking = false }) - ticking = true } } @@ -131,6 +132,11 @@ const Header = props => { } `} + {/* fixed时留白高度 */} + {fixedNav && !document?.querySelector('#post-bg') && ( +
+ )} + {/* 顶部导航菜单栏 */}
{/* 右侧固定 */} -
+
{!JSON.parse(siteConfig('THEME_SWITCH')) && ( diff --git a/themes/heo/components/Hero.js b/themes/heo/components/Hero.js index 656bca55950..b43987e67d0 100644 --- a/themes/heo/components/Hero.js +++ b/themes/heo/components/Hero.js @@ -2,6 +2,7 @@ import { ArrowSmallRight, PlusSmall } from '@/components/HeroIcons' import LazyImage from '@/components/LazyImage' import { siteConfig } from '@/lib/config' +import { useGlobal } from '@/lib/global' import Link from 'next/link' import { useRouter } from 'next/router' import { useImperativeHandle, useRef, useState } from 'react' @@ -206,6 +207,7 @@ function GroupMenu() { */ function TopGroup(props) { const { latestPosts, allNavPages, siteInfo } = props + const { locale } = useGlobal() const todayCardRef = useRef() function handleMouseLeave() { todayCardRef.current.coverUp() @@ -238,7 +240,7 @@ function TopGroup(props) {
{/* hover 悬浮的 ‘荐’ 字 */}
- 荐 + {locale.COMMON.RECOMMEND_BADGES}
@@ -304,6 +306,7 @@ function getTopPosts({ latestPosts, allNavPages }) { function TodayCard({ cRef, siteInfo }) { const router = useRouter() const link = siteConfig('HEO_HERO_TITLE_LINK', null, CONFIG) + const { locale } = useGlobal() // 卡牌是否盖住下层 const [isCoverUp, setIsCoverUp] = useState(true) @@ -348,7 +351,7 @@ function TodayCard({ cRef, siteInfo }) { isCoverUp ? 'opacity-100 cursor-pointer' : 'opacity-0 transform scale-110 pointer-events-none' - } shadow transition-all duration-200 today-card h-full bg-[#0E57D5] rounded-xl relative overflow-hidden flex items-end`}> + } shadow transition-all duration-200 today-card h-full bg-[#0E57D5] dark:bg-yellow-500 rounded-xl relative overflow-hidden flex items-end`}>
@@ -364,12 +367,14 @@ function TodayCard({ cRef, siteInfo }) { onClick={handleClickMore} className={`'${ isCoverUp ? '' : 'hidden pointer-events-none ' - } flex items-center px-3 h-10 justify-center bg-[#425aef] hover:bg-[#4259efcb] transition-colors duration-100 rounded-3xl`}> + } flex items-center px-3 h-10 justify-center bg-[#425aef] hover:bg-[#4259efcb] dark:bg-yellow-500 dark:hover:bg-yellow-600 transition-colors duration-100 rounded-3xl`}>
- 更多推荐 + {locale.COMMON.MORE}
diff --git a/themes/heo/components/LatestPostsGroupMini.js b/themes/heo/components/LatestPostsGroupMini.js index 7bc65df3a5f..c8f0dcf4ef9 100644 --- a/themes/heo/components/LatestPostsGroupMini.js +++ b/themes/heo/components/LatestPostsGroupMini.js @@ -50,13 +50,13 @@ export default function LatestPostsGroupMini({ latestPosts, siteInfo }) {
{post.title}
-
{post.lastEditedDay}
+
{post.lastEditedDay}
diff --git a/themes/heo/components/MenuItemCollapse.js b/themes/heo/components/MenuItemCollapse.js index f0f9486b769..6278cebe346 100644 --- a/themes/heo/components/MenuItemCollapse.js +++ b/themes/heo/components/MenuItemCollapse.js @@ -28,7 +28,7 @@ export const MenuItemCollapse = ({ link }) => { return ( <>
{!hasSubMenu && ( { return (
+ className='dark:bg-hexo-black-gray dark:text-gray-200 text-left px-3 justify-start bg-gray-50 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 py-3 pr-6'> {link?.icon && }{' '} diff --git a/themes/heo/components/MenuItemDrop.js b/themes/heo/components/MenuItemDrop.js index 2e6929a7e34..4f8241fc131 100644 --- a/themes/heo/components/MenuItemDrop.js +++ b/themes/heo/components/MenuItemDrop.js @@ -36,12 +36,12 @@ export const MenuItemDrop = ({ link }) => { {hasSubMenu && (
    + className={`${show ? 'visible opacity-100 top-14' : 'invisible opacity-0 top-20'} drop-shadow-md overflow-hidden rounded-xl bg-white dark:bg-[#1e1e1e] border dark:border-gray-700 transition-all duration-300 z-20 absolute`}> {link.subMenus.map((sLink, index) => { return (
  • + className='cursor-pointer hover:bg-blue-600 dark:hover:bg-yellow-600 hover:text-white text-gray-900 dark:text-gray-100 tracking-widest transition-all duration-200 dark:border-gray-700 py-1 pr-6 pl-3'> {link?.icon &&   } diff --git a/themes/heo/components/MenuListSide.js b/themes/heo/components/MenuListSide.js index 5716d5b8be7..50bec3c2499 100644 --- a/themes/heo/components/MenuListSide.js +++ b/themes/heo/components/MenuListSide.js @@ -48,7 +48,7 @@ export const MenuListSide = props => { } return ( -