From 67019e9477cbe81f48aa7ccd09dd0e109c0518dd Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Mon, 4 Nov 2024 16:11:27 +0800 Subject: [PATCH] theme-photo --- lib/db/getSiteData.js | 4 +- styles/globals.css | 4 + themes/photo/components/Header.js | 4 +- themes/photo/components/MenuHierarchical.js | 42 +++-- themes/photo/components/MenuItemCollapse.js | 12 +- themes/photo/components/PostItemCard.js | 50 +++--- themes/photo/components/Swiper.js | 168 +++++++++----------- themes/photo/index.js | 25 ++- themes/photo/style.js | 40 ++--- 9 files changed, 169 insertions(+), 180 deletions(-) diff --git a/lib/db/getSiteData.js b/lib/db/getSiteData.js index 951bdaac..4d615824 100755 --- a/lib/db/getSiteData.js +++ b/lib/db/getSiteData.js @@ -65,8 +65,8 @@ export async function getNotionPageData({ pageId, from }) { const cacheKey = 'page_block_' + pageId let data = await getDataFromCache(cacheKey) if (data && data.pageIds?.length > 0) { - // console.log('[API<<--缓存]', `from:${from}`, `root-page-id:${pageId}`) - // return data + console.debug('[API<<--缓存]', `from:${from}`, `root-page-id:${pageId}`) + return data } else { // 从接口读取 data = await getDataBaseInfoByNotionAPI({ pageId, from }) diff --git a/styles/globals.css b/styles/globals.css index 7c215c46..5c86cecf 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -2,6 +2,10 @@ @tailwind components; @tailwind utilities; +html { + overflow-x: hidden; +} + .wrapper { min-height: 100vh; display: flex; diff --git a/themes/photo/components/Header.js b/themes/photo/components/Header.js index a6856db4..9a2c31ff 100644 --- a/themes/photo/components/Header.js +++ b/themes/photo/components/Header.js @@ -9,7 +9,7 @@ import MenuHierarchical from './MenuHierarchical' export const Header = props => { return ( <> -
+
{/* 左侧Logo */} { {/* 右侧使用一个三级菜单 */} -
+
diff --git a/themes/photo/components/MenuHierarchical.js b/themes/photo/components/MenuHierarchical.js index 978e262e..397bca4e 100644 --- a/themes/photo/components/MenuHierarchical.js +++ b/themes/photo/components/MenuHierarchical.js @@ -2,7 +2,7 @@ import Collapse from '@/components/Collapse' import { siteConfig } from '@/lib/config' import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { usePhotoGlobal } from '..' import CONFIG from '../config' import { MenuItemCollapse } from './MenuItemCollapse' @@ -20,6 +20,9 @@ export default function MenuHierarchical(props) { const toggleMenuOpen = () => { setIsOpen(!isOpen) } + const closeModal = () => { + setIsOpen(false) + } let links = [ { id: 1, @@ -59,19 +62,31 @@ export default function MenuHierarchical(props) { links = customMenu } + const [title, setTitle] = useState(siteConfig('BIO')) + + useEffect(() => { + const currentLink = links.find(link => link.href === router.pathname) + if (currentLink) { + setTitle(currentLink.name) + } + closeModal() + }, [router]) + return ( -
+
{/* 菜单按钮 */} -
- {isOpen ? ( - - ) : ( - - )} +
+ {title}
- + {/* 移动端菜单 */} - + {links?.map( (link, index) => link && @@ -87,6 +102,13 @@ export default function MenuHierarchical(props) { )} + {/* 遮罩 */} + {isOpen && ( +
+ )}
) } diff --git a/themes/photo/components/MenuItemCollapse.js b/themes/photo/components/MenuItemCollapse.js index b11dbd57..6778fecf 100644 --- a/themes/photo/components/MenuItemCollapse.js +++ b/themes/photo/components/MenuItemCollapse.js @@ -28,14 +28,12 @@ export const MenuItemCollapse = props => { return ( <> -
+
{!hasSubMenu && ( + className='flex justify-between dark:text-gray-200 no-underline tracking-widest'> {link?.icon && } {link?.name} @@ -45,7 +43,7 @@ export const MenuItemCollapse = props => { {hasSubMenu && (
+ className='flex items-center justify-between cursor-pointer dark:text-gray-200 no-underline tracking-widest'> {link?.icon && } {link?.name} @@ -66,9 +64,9 @@ export const MenuItemCollapse = props => { return (
+ className='dark:text-gray-200 text-left px-3 justify-start py-1 tracking-widest transition-all duration-200 pr-6'> - + {link?.icon && }{' '} {sLink.title} diff --git a/themes/photo/components/PostItemCard.js b/themes/photo/components/PostItemCard.js index c43854e1..41b57f5b 100644 --- a/themes/photo/components/PostItemCard.js +++ b/themes/photo/components/PostItemCard.js @@ -3,51 +3,49 @@ import NotionIcon from '@/components/NotionIcon' import { siteConfig } from '@/lib/config' import { useGlobal } from '@/lib/global' import { formatDateFmt } from '@/lib/utils/formatDate' +import Link from 'next/link' /** * 普通的博客卡牌 * 带封面图 */ -const PostItemCard = ({ post }) => { +const PostItemCard = ({ post, className }) => { const { siteInfo } = useGlobal() const cover = post?.pageCoverThumbnail || siteInfo?.pageCover return ( -
-
- {/* */} -
+
+
+
- {/* */} -
- {/* + */} -

- {siteConfig('POST_TITLE_ICON') && ( - - )} - {post.title} -

- {/* */} + 'cursor-pointer hover:underline leading-tight dark:text-gray-300 ' + }> +

+ {siteConfig('POST_TITLE_ICON') && ( + + )} + {post?.title} +

+ -
- {formatDateFmt(post.publishDate, 'yyyy-MM')} -
+ {/* 发布日期 */} + + {formatDateFmt(post?.publishDate, 'yyyy-MM')} +
diff --git a/themes/photo/components/Swiper.js b/themes/photo/components/Swiper.js index 02b61da9..381e00c8 100644 --- a/themes/photo/components/Swiper.js +++ b/themes/photo/components/Swiper.js @@ -1,111 +1,101 @@ -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import PostItemCard from './PostItemCard' -const Swiper = ({ posts }) => { - const [currentIndex, setCurrentIndex] = useState(0) - const containerRef = useRef(null) +const InertiaCarousel = ({ posts }) => { + const carouselRef = useRef(null) + const [isDragging, setIsDragging] = useState(false) + const [startX, setStartX] = useState(0) + const [scrollLeft, setScrollLeft] = useState(0) + const [lastX, setLastX] = useState(0) // 上一次的位置 + const [velocity, setVelocity] = useState(0) + const animationRef = useRef(null) - const touchStartPos = useRef({ x: 0, y: 0 }) - const isDragging = useRef(false) - const scrollStartLeft = useRef(0) // 记录拖拽开始时的滚动位置 - - // 处理鼠标和触摸开始事件 - const handleDragStart = e => { - const x = e.touches ? e.touches[0].clientX : e.clientX - touchStartPos.current = { x } - isDragging.current = true - scrollStartLeft.current = containerRef.current.scrollLeft - - // 更新鼠标样式 - containerRef.current.style.cursor = 'grabbing' + // 开始拖拽事件 + const startDrag = e => { + e.preventDefault() + setIsDragging(true) + const startPosition = e.pageX || e.touches[0].pageX + setStartX(startPosition - carouselRef.current.offsetLeft) + setScrollLeft(carouselRef.current.scrollLeft) + setLastX(startPosition) // 初始化上一次的位置 + cancelInertiaScroll() // 停止任何正在进行的惯性动画 } - // 处理鼠标和触摸移动事件 - const handleDragMove = e => { - if (!isDragging.current) return + // 拖拽中事件 + const duringDrag = e => { + if (!isDragging) return + e.preventDefault() + const currentPosition = e.pageX || e.touches[0].pageX + const distance = currentPosition - startX + carouselRef.current.scrollLeft = scrollLeft - distance - const x = e.touches ? e.touches[0].clientX : e.clientX - const deltaX = touchStartPos.current.x - x - - // 根据拖动的距离更新滚动位置 - containerRef.current.scrollLeft = scrollStartLeft.current + deltaX + // 计算当前速度 + const deltaX = currentPosition - lastX + setVelocity(deltaX) // 更新速度 + setLastX(currentPosition) // 更新 lastX 为当前位置 } - // 处理鼠标和触摸结束事件 - const handleDragEnd = () => { - isDragging.current = false - containerRef.current.style.cursor = 'grab' + // 结束拖拽事件,启动惯性滚动 + const endDrag = () => { + setIsDragging(false) + startInertiaScroll(velocity) // 根据最终速度启动惯性滚动 } - // 处理指示器点击事件 - const handleIndicatorClick = index => { - setCurrentIndex(index) - scrollToCard(index) + // 惯性滚动函数 + const startInertiaScroll = initialVelocity => { + let currentVelocity = initialVelocity + const decay = 0.95 // 惯性衰减系数 + const animate = () => { + if (Math.abs(currentVelocity) > 0.5) { + // 仅当速度足够大时继续滚动 + carouselRef.current.scrollLeft -= currentVelocity + currentVelocity *= decay // 速度衰减 + animationRef.current = requestAnimationFrame(animate) + } else { + cancelAnimationFrame(animationRef.current) + } + } + animate() } - // 滚动到特定卡片 - const scrollToCard = index => { - const container = containerRef.current - if (!container) return - const cardWidth = container.scrollWidth / posts.length - container.scrollTo({ - left: index * cardWidth - cardWidth / 6, // 调整位置以居中 - behavior: 'smooth' - }) + // 取消惯性滚动 + const cancelInertiaScroll = () => { + if (animationRef.current) { + cancelAnimationFrame(animationRef.current) + } } + useEffect(() => { + return () => cancelInertiaScroll() // 清除动画 + }, []) + return ( -
-
- handleIndicatorClick( - currentIndex === 0 ? posts.length - 1 : currentIndex - 1 - ) - }>
+
+ {/* Carousel items */} -
- handleIndicatorClick( - currentIndex === posts.length - 1 ? 0 : currentIndex + 1 - ) - }>
- -
-
- {posts.map((item, index) => ( -
- -
- ))} -
-
- -
- {posts.map((_, index) => ( - + post={post} + /> ))} -
) } -export default Swiper +export default InertiaCarousel diff --git a/themes/photo/index.js b/themes/photo/index.js index ea74aeb0..190bac80 100644 --- a/themes/photo/index.js +++ b/themes/photo/index.js @@ -65,7 +65,7 @@ const LayoutBase = props => {
)