mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-04 07:26:47 +00:00
Merge pull request #2474 from tangly1024/hexo/jump-random
hexo 微调,添加随机跳转按钮
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import { saveDarkModeToLocalStorage } from '@/themes/theme'
|
import { saveDarkModeToLocalStorage } from '@/themes/theme'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
import { siteConfig } from '@/lib/config'
|
|
||||||
|
|
||||||
export default function FloatDarkModeButton () {
|
/**
|
||||||
|
* 深色模式按钮
|
||||||
|
*/
|
||||||
|
export default function ButtonDarkModeFloat() {
|
||||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||||
|
|
||||||
if (!siteConfig('HEXO_WIDGET_DARK_MODE', null, CONFIG)) {
|
if (!siteConfig('HEXO_WIDGET_DARK_MODE', null, CONFIG)) {
|
||||||
@@ -23,10 +26,13 @@ export default function FloatDarkModeButton () {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={handleChangeDarkMode}
|
onClick={handleChangeDarkMode}
|
||||||
className={'justify-center items-center w-7 h-7 text-center transform hover:scale-105 duration-200'
|
className={
|
||||||
}
|
'justify-center items-center w-7 h-7 text-center transform hover:scale-105 duration-200'
|
||||||
>
|
}>
|
||||||
<i id="darkModeButton" className={`${isDarkMode ? 'fa-sun' : 'fa-moon'} fas text-xs`}/>
|
<i
|
||||||
|
id='darkModeButton'
|
||||||
|
className={`${isDarkMode ? 'fa-sun' : 'fa-moon'} fas text-xs`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
import CONFIG from '../config'
|
|
||||||
import { siteConfig } from '@/lib/config'
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到评论区
|
* 跳转到评论区
|
||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const JumpToCommentButton = () => {
|
const ButtonJumpToComment = () => {
|
||||||
if (!siteConfig('HEXO_WIDGET_TO_COMMENT', null, CONFIG)) {
|
if (!siteConfig('HEXO_WIDGET_TO_COMMENT', null, CONFIG)) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
function navToComment() {
|
function navToComment() {
|
||||||
if (document.getElementById('comment')) {
|
if (document.getElementById('comment')) {
|
||||||
window.scrollTo({ top: document.getElementById('comment').offsetTop, behavior: 'smooth' })
|
window.scrollTo({
|
||||||
|
top: document.getElementById('comment').offsetTop,
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// 兼容性不好
|
// 兼容性不好
|
||||||
// const commentElement = document.getElementById('comment')
|
// const commentElement = document.getElementById('comment')
|
||||||
@@ -21,9 +24,13 @@ const JumpToCommentButton = () => {
|
|||||||
// commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
|
// commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<div className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center' onClick={navToComment} >
|
return (
|
||||||
<i className='fas fa-comment text-xs' />
|
<div
|
||||||
</div>)
|
className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center'
|
||||||
|
onClick={navToComment}>
|
||||||
|
<i className='fas fa-comment text-xs' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JumpToCommentButton
|
export default ButtonJumpToComment
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
import { useGlobal } from '@/lib/global'
|
import { useGlobal } from '@/lib/global'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
import { siteConfig } from '@/lib/config'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到网页顶部
|
* 跳转到网页顶部
|
||||||
@@ -10,7 +10,7 @@ import { siteConfig } from '@/lib/config'
|
|||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const JumpToTopButton = ({ showPercent = true, percent }) => {
|
const ButtonJumpToTop = ({ showPercent = true, percent }) => {
|
||||||
const { locale } = useGlobal()
|
const { locale } = useGlobal()
|
||||||
|
|
||||||
if (!siteConfig('HEXO_WIDGET_TO_TOP', null, CONFIG)) {
|
if (!siteConfig('HEXO_WIDGET_TO_TOP', null, CONFIG)) {
|
||||||
@@ -22,4 +22,4 @@ const JumpToTopButton = ({ showPercent = true, percent }) => {
|
|||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JumpToTopButton
|
export default ButtonJumpToTop
|
||||||
29
themes/hexo/components/ButtonRandomPost.js
Normal file
29
themes/hexo/components/ButtonRandomPost.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机跳转到一个文章
|
||||||
|
*/
|
||||||
|
export default function ButtonRandomPost(props) {
|
||||||
|
const { latestPosts } = props
|
||||||
|
const router = useRouter()
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
/**
|
||||||
|
* 随机跳转文章
|
||||||
|
*/
|
||||||
|
function handleClick() {
|
||||||
|
const randomIndex = Math.floor(Math.random() * latestPosts.length)
|
||||||
|
const randomPost = latestPosts[randomIndex]
|
||||||
|
router.push(`${siteConfig('SUB_PATH', '')}/${randomPost?.slug}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
title={locale.MENU.WALK_AROUND}
|
||||||
|
className='cursor-pointer hover:bg-black hover:bg-opacity-10 rounded-full w-10 h-10 flex justify-center items-center duration-200 transition-all'
|
||||||
|
onClick={handleClick}>
|
||||||
|
<i className='fa-solid fa-podcast'></i>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
29
themes/hexo/components/ButtonRandomPostMini.js
Normal file
29
themes/hexo/components/ButtonRandomPostMini.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { siteConfig } from '@/lib/config'
|
||||||
|
import { useGlobal } from '@/lib/global'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机跳转到一个文章
|
||||||
|
*/
|
||||||
|
export default function ButtonRandomPostMini(props) {
|
||||||
|
const { latestPosts } = props
|
||||||
|
const router = useRouter()
|
||||||
|
const { locale } = useGlobal()
|
||||||
|
/**
|
||||||
|
* 随机跳转文章
|
||||||
|
*/
|
||||||
|
function handleClick() {
|
||||||
|
const randomIndex = Math.floor(Math.random() * latestPosts.length)
|
||||||
|
const randomPost = latestPosts[randomIndex]
|
||||||
|
router.push(`${siteConfig('SUB_PATH', '')}/${randomPost?.slug}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
title={locale.MENU.WALK_AROUND}
|
||||||
|
className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center'
|
||||||
|
onClick={handleClick}>
|
||||||
|
<i className='fa-solid fa-podcast'></i>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import Link from 'next/link'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
|
import ButtonRandomPost from './ButtonRandomPost'
|
||||||
import CategoryGroup from './CategoryGroup'
|
import CategoryGroup from './CategoryGroup'
|
||||||
import Logo from './Logo'
|
import Logo from './Logo'
|
||||||
import { MenuListTop } from './MenuListTop'
|
import { MenuListTop } from './MenuListTop'
|
||||||
@@ -28,6 +29,7 @@ const Header = props => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [isOpen, changeShow] = useState(false)
|
const [isOpen, changeShow] = useState(false)
|
||||||
const showSearchButton = siteConfig('HEXO_MENU_SEARCH', false, CONFIG)
|
const showSearchButton = siteConfig('HEXO_MENU_SEARCH', false, CONFIG)
|
||||||
|
const showRandomButton = siteConfig('HEXO_MENU_RANDOM', false, CONFIG)
|
||||||
|
|
||||||
const toggleMenuOpen = () => {
|
const toggleMenuOpen = () => {
|
||||||
changeShow(!isOpen)
|
changeShow(!isOpen)
|
||||||
@@ -172,6 +174,7 @@ const Header = props => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showSearchButton && <SearchButton />}
|
{showSearchButton && <SearchButton />}
|
||||||
|
{showRandomButton && <ButtonRandomPost {...props} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import FloatDarkModeButton from './FloatDarkModeButton'
|
import ButtonDarkModeFloat from './ButtonFloatDarkMode'
|
||||||
import JumpToTopButton from './JumpToTopButton'
|
import ButtonJumpToTop from './ButtonJumpToTop'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 悬浮在右下角的按钮,当页面向下滚动100px时会出现
|
* 悬浮在右下角的按钮,当页面向下滚动100px时会出现
|
||||||
@@ -10,20 +10,22 @@ import JumpToTopButton from './JumpToTopButton'
|
|||||||
*/
|
*/
|
||||||
export default function RightFloatArea({ floatSlot }) {
|
export default function RightFloatArea({ floatSlot }) {
|
||||||
const [showFloatButton, switchShow] = useState(false)
|
const [showFloatButton, switchShow] = useState(false)
|
||||||
const scrollListener = useCallback(throttle(() => {
|
const scrollListener = useCallback(
|
||||||
const targetRef = document.getElementById('wrapper')
|
throttle(() => {
|
||||||
const clientHeight = targetRef?.clientHeight
|
const targetRef = document.getElementById('wrapper')
|
||||||
const scrollY = window.pageYOffset
|
const clientHeight = targetRef?.clientHeight
|
||||||
const fullHeight = clientHeight - window.outerHeight
|
const scrollY = window.pageYOffset
|
||||||
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
|
const fullHeight = clientHeight - window.outerHeight
|
||||||
if (per > 100) per = 100
|
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
|
||||||
const shouldShow = scrollY > 100 && per > 0
|
if (per > 100) per = 100
|
||||||
|
const shouldShow = scrollY > 100 && per > 0
|
||||||
|
|
||||||
// 右下角显示悬浮按钮
|
// 右下角显示悬浮按钮
|
||||||
if (shouldShow !== showFloatButton) {
|
if (shouldShow !== showFloatButton) {
|
||||||
switchShow(shouldShow)
|
switchShow(shouldShow)
|
||||||
}
|
}
|
||||||
}, 200))
|
}, 200)
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('scroll', scrollListener)
|
document.addEventListener('scroll', scrollListener)
|
||||||
@@ -31,12 +33,17 @@ export default function RightFloatArea({ floatSlot }) {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') + ' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'}>
|
<div
|
||||||
<div className={'justify-center flex flex-col items-center cursor-pointer'}>
|
className={
|
||||||
<FloatDarkModeButton />
|
(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') +
|
||||||
{floatSlot}
|
' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'
|
||||||
<JumpToTopButton />
|
}>
|
||||||
</div>
|
<div
|
||||||
</div>
|
className={'justify-center flex flex-col items-center cursor-pointer'}>
|
||||||
|
<ButtonDarkModeFloat />
|
||||||
|
{floatSlot}
|
||||||
|
<ButtonJumpToTop />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
HEXO_HOME_BANNER_ENABLE: true,
|
HEXO_HOME_BANNER_ENABLE: true,
|
||||||
// 3.14.1以后的版本中,欢迎语在blog.config.js中配置,用英文逗号','隔开多个。
|
// 3.14.1以后的版本中,欢迎语在blog.config.js中配置,用英文逗号','隔开多个。
|
||||||
HEXO_HOME_BANNER_GREETINGS: ['Hi,我是一个程序员', 'Hi,我是一个打工人', 'Hi,我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
|
HEXO_HOME_BANNER_GREETINGS: [
|
||||||
|
'Hi,我是一个程序员',
|
||||||
|
'Hi,我是一个打工人',
|
||||||
|
'Hi,我是一个干饭人',
|
||||||
|
'欢迎来到我的博客🎉'
|
||||||
|
], // 首页大图标语文字
|
||||||
|
|
||||||
HEXO_HOME_NAV_BUTTONS: true, // 首页是否显示分类大图标按钮
|
HEXO_HOME_NAV_BUTTONS: true, // 首页是否显示分类大图标按钮
|
||||||
// 已知未修复bug, 在移动端开启true后会加载不出图片; 暂时建议设置为false。
|
// 已知未修复bug, 在移动端开启true后会加载不出图片; 暂时建议设置为false。
|
||||||
@@ -15,6 +20,7 @@ const CONFIG = {
|
|||||||
HEXO_MENU_TAG: true, // 显示标签
|
HEXO_MENU_TAG: true, // 显示标签
|
||||||
HEXO_MENU_ARCHIVE: true, // 显示归档
|
HEXO_MENU_ARCHIVE: true, // 显示归档
|
||||||
HEXO_MENU_SEARCH: true, // 显示搜索
|
HEXO_MENU_SEARCH: true, // 显示搜索
|
||||||
|
HEXO_MENU_RANDOM: true, // 显示随机跳转按钮
|
||||||
|
|
||||||
HEXO_POST_LIST_COVER: true, // 列表显示文章封面
|
HEXO_POST_LIST_COVER: true, // 列表显示文章封面
|
||||||
HEXO_POST_LIST_COVER_HOVER_ENLARGE: false, // 列表鼠标悬停放大
|
HEXO_POST_LIST_COVER_HOVER_ENLARGE: false, // 列表鼠标悬停放大
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ import ArticleRecommend from './components/ArticleRecommend'
|
|||||||
import BlogPostArchive from './components/BlogPostArchive'
|
import BlogPostArchive from './components/BlogPostArchive'
|
||||||
import BlogPostListPage from './components/BlogPostListPage'
|
import BlogPostListPage from './components/BlogPostListPage'
|
||||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||||
|
import ButtonJumpToComment from './components/ButtonJumpToComment'
|
||||||
|
import ButtonRandomPostMini from './components/ButtonRandomPostMini'
|
||||||
import Card from './components/Card'
|
import Card from './components/Card'
|
||||||
import Footer from './components/Footer'
|
import Footer from './components/Footer'
|
||||||
import Header from './components/Header'
|
import Header from './components/Header'
|
||||||
import Hero from './components/Hero'
|
import Hero from './components/Hero'
|
||||||
import JumpToCommentButton from './components/JumpToCommentButton'
|
|
||||||
import PostHero from './components/PostHero'
|
import PostHero from './components/PostHero'
|
||||||
import RightFloatArea from './components/RightFloatArea'
|
import RightFloatArea from './components/RightFloatArea'
|
||||||
import SearchNav from './components/SearchNav'
|
import SearchNav from './components/SearchNav'
|
||||||
@@ -51,8 +52,9 @@ export const useHexoGlobal = () => useContext(ThemeGlobalHexo)
|
|||||||
const LayoutBase = props => {
|
const LayoutBase = props => {
|
||||||
const { post, children, slotTop, className } = props
|
const { post, children, slotTop, className } = props
|
||||||
const { onLoading, fullWidth } = useGlobal()
|
const { onLoading, fullWidth } = useGlobal()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const showRandomButton = siteConfig('HEXO_MENU_RANDOM', false, CONFIG)
|
||||||
|
|
||||||
const headerSlot = post ? (
|
const headerSlot = post ? (
|
||||||
<PostHero {...props} />
|
<PostHero {...props} />
|
||||||
) : router.route === '/' &&
|
) : router.route === '/' &&
|
||||||
@@ -63,6 +65,7 @@ const LayoutBase = props => {
|
|||||||
const drawerRight = useRef(null)
|
const drawerRight = useRef(null)
|
||||||
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
|
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||||
|
|
||||||
|
// 悬浮按钮内容
|
||||||
const floatSlot = (
|
const floatSlot = (
|
||||||
<>
|
<>
|
||||||
{post?.toc?.length > 1 && (
|
{post?.toc?.length > 1 && (
|
||||||
@@ -74,7 +77,8 @@ const LayoutBase = props => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{post && <JumpToCommentButton />}
|
{post && <ButtonJumpToComment />}
|
||||||
|
{showRandomButton && <ButtonRandomPostMini {...props} />}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user