plog-基础布局

This commit is contained in:
tangly1024.com
2023-07-11 13:39:53 +08:00
parent 463b35639a
commit 563b130e77
8 changed files with 133 additions and 21 deletions

View File

@@ -26,4 +26,10 @@ const User = ({ className }) => {
<path strokeLinecap="round" strokeLinejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
}
export { Moon, Sun, Home, User }
const ArrowPath = ({ className }) => {
return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className}>
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
}
export { Moon, Sun, Home, User, ArrowPath }

View File

@@ -6,7 +6,7 @@ import BLOG from '@/blog.config'
* 2. UnPlash 图片可以通过api q=50 控制压缩质量 width=400 控制图片尺寸
* @param {*} image
*/
const compressImage = (image, width = 300) => {
const compressImage = (image, width = 400, quality = 50, fmt = 'webp') => {
if (!image) {
return null
}
@@ -20,11 +20,12 @@ const compressImage = (image, width = 300) => {
// 获取URL参数
const params = new URLSearchParams(urlObj.search)
// 将q参数的值替换
params.set('q', '50')
params.set('q', quality)
// 尺寸
params.set('width', width)
// 格式
params.set('fmt', 'webp')
params.set('fmt', fmt)
params.set('fm', fmt)
// 生成新的URL
urlObj.search = params.toString()
return urlObj.toString()

View File

@@ -1950,14 +1950,6 @@ svg + .notion-page-title-text {
@apply bg-blue-500 text-gray-50 !important;
}
.dark img{
@apply opacity-80
}
.dark #live2d {
@apply opacity-80
}
/* https://github.com/kchen0x */
.notion-quote {
display: block;

View File

@@ -19,7 +19,7 @@ export const BlogListPage = props => {
return (
<div className="w-full">
<div id="posts-wrapper" className='grid lg:grid-cols-3 grid-cols-2'>
<div id="posts-wrapper" className='grid lg:grid-cols-3 grid-cols-1 md:grid-cols-2'>
{posts?.map(post => (
<BlogPost key={post.id} post={post} {...props}/>
))}

View File

@@ -1,3 +1,6 @@
import { compressImage } from '@/lib/notion/mapImage'
import Link from 'next/link'
import { usePlogGlobal } from '..'
/**
* 博客照片卡牌
@@ -6,15 +9,30 @@
*/
const BlogPost = (props) => {
const { post, siteInfo } = props
const pageThumbnail = post?.pageCoverThumbnail || siteInfo?.pageCover
console.log('缩略图', pageThumbnail, siteInfo)
const pageThumbnail = compressImage(post?.pageCoverThumbnail || siteInfo?.pageCover, 800, 80)
const { setModalContent, setShowModal } = usePlogGlobal()
const handleClick = () => {
setShowModal(true)
setModalContent(post)
}
return (
<article key={post?.id} className='cursor-pointer relative'>
<article
onClick={handleClick}
data-aos="fade-up"
data-aos-duration="500"
data-aos-once="true"
data-aos-anchor-placement="top-bottom"
key={post?.id} className='cursor-pointer relative'>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={pageThumbnail} className='aspect-[16/9] w-full h-full object-cover' />
<h2 className="text-md absolute left-0 bottom-0 mb-4 ml-4 text-black dark:text-gray-100 text-shadow">
<img src={pageThumbnail} className='aspect-[16/9] w-full h-full object-cover filter contrast-120' />
<h2 className="text-md absolute left-0 bottom-0 m-4 text-black dark:text-gray-100 text-shadow">
{post?.title}
</h2>
{post?.category && <div className='text-xs rounded-lg absolute left-0 top-0 m-4 px-2 py-1 bg-black bg-opacity-25 hover:bg-blue-700 hover:text-white duration-200'>
<Link href={`/category/${post?.category}`}>
{post?.category}
</Link>
</div>}
</article>
)

View File

@@ -15,7 +15,7 @@ const BottomNav = props => {
const { navBarTitle, siteInfo } = props
return <>
<div id="bottom-nav" className={'px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
<div id="bottom-nav" style={{ backgroundColor: '#00000063' }} className={'px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
<div className="flex items-center">
<Link href="/" aria-label={BLOG.title}>
<div className="h-6 w-6">

View File

@@ -0,0 +1,83 @@
import { Fragment, useRef, useState } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { usePlogGlobal } from '..'
import { ArrowPath } from '@/components/HeroIcons'
import Link from 'next/link'
/**
* 弹出框
*/
export default function Modal(props) {
const { showModal, setShowModal, modalContent } = usePlogGlobal()
const { siteInfo } = props
const cancelButtonRef = useRef(null)
const img = modalContent?.pageCover || siteInfo?.pageCover
const imgRef = useRef(null)
// 添加loading状态
const [loading, setLoading] = useState(true)
// 在图片加载完成时设置loading为false
async function handleImageLoad() {
setLoading(false)
}
// 关闭弹窗
function handleClose() {
setShowModal(false)
setLoading(true)
}
return (
<Transition.Root show={showModal} as={Fragment}>
<Dialog as="div" className="relative z-10" initialFocus={cancelButtonRef} onClose={handleClose}>
{/* 遮罩 */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div style={{ backgroundColor: '#00000063' }} className="fixed inset-0 glassmorphism transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full justify-center p-4 text-center items-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 scale-50 w-0"
enterTo={'opacity-100 translate-y-0 max-w-screen'}
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 scale-100 max-w-screen"
leaveTo="opacity-0 translate-y-4 scale-50 w-0"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-xl text-left shadow-xl transition-all ">
{/* 添加loading状态 */}
<div className={`bg-hexo-black-gray w-32 h-32 flex justify-center items-center ${loading ? '' : 'hidden'}`}>
<ArrowPath className='w-10 h-10 animate-spin text-gray-200' />
</div>
{/* 添加onLoad事件处理函数 */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={img} ref={imgRef} className={'w-full max-w-7xl max-h-[90vh] shadow-xl'} onLoad={handleImageLoad} style={{ display: loading ? 'none' : 'block' }} />
{!loading && <div className='absolute bottom-0 left-0 m-4'>
<div className='flex'>
<h2 style={{ textShadow: '0.1em 0.1em 0.2em black' }} className='text-5xl text-white mb-4 px-2 py-1 rounded-lg'>{modalContent?.title}</h2>
</div>
<div style={{ textShadow: '0.1em 0.1em 0.2em black' }} className={'text-gray-50 rounded-lg p-2'}>{modalContent?.summary}</div>
{modalContent?.category && <div className='flex '>
<Link href={`/category/${modalContent?.category}`} className='text-xs rounded-lg mt-3 px-2 py-1 bg-black bg-opacity-20 text-white hover:bg-blue-700 hover:text-white duration-200'>
{modalContent?.category}
</Link>
</div>}
</div>}
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}

View File

@@ -1,6 +1,6 @@
import CONFIG from './config'
import CommonHead from '@/components/CommonHead'
import React, { useEffect } from 'react'
import React, { createContext, useContext, useEffect, useState } from 'react'
import Nav from './components/Nav'
import { useGlobal } from '@/lib/global'
@@ -24,6 +24,11 @@ import Link from 'next/link'
import { Transition } from '@headlessui/react'
import BottomNav from './components/BottomNav'
import { saveDarkModeToCookies } from '@/themes/theme'
import Modal from './components/Modal'
// 主题全局状态
const ThemeGlobalPlog = createContext()
export const usePlogGlobal = () => useContext(ThemeGlobalPlog)
/**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
@@ -34,6 +39,8 @@ import { saveDarkModeToCookies } from '@/themes/theme'
const LayoutBase = props => {
const { children, meta, topSlot } = props
const { onLoading, updateDarkMode } = useGlobal()
const [showModal, setShowModal] = useState(false)
const [modalContent, setModalContent] = useState(null)
// 用户手动设置主题
const setDarkMode = () => {
@@ -52,6 +59,7 @@ const LayoutBase = props => {
}, [])
return (
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full bg-black min-h-screen'>
{/* SEO相关 */}
<CommonHead meta={meta} />
@@ -60,7 +68,7 @@ const LayoutBase = props => {
<Nav {...props} />
{/* 主区 */}
<main id='out-wrapper' className={'relative m-auto flex-grow w-full transition-all '}>
<main id='out-wrapper' className={'relative m-auto flex-grow w-full transition-all pb-12'}>
<Transition
show={!onLoading}
@@ -80,9 +88,13 @@ const LayoutBase = props => {
</main>
{/* 弹出框 */}
<Modal {...props}/>
{/* 桌面端底部导航栏 */}
<BottomNav {...props} />
</div>
</ThemeGlobalPlog.Provider >
)
}