feat: 优化css

This commit is contained in:
Blackberry009
2025-06-09 17:46:08 +08:00
parent f7ceb2f9ec
commit a8192e0179
7 changed files with 100 additions and 41 deletions

View File

@@ -3,8 +3,7 @@
const BLOG = {
// Important page_idDuplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5
NOTION_PAGE_ID:
process.env.NOTION_PAGE_ID ||
'02ab3b8678004aa69e9e415905ef32a5,en:7c1d570661754c8fbc568e00a01fd70e',
process.env.NOTION_PAGE_ID || '20cb7f4f464a80db8541cbd0da70a64b',
THEME: process.env.NEXT_PUBLIC_THEME || 'typography', // 当前主题,在 themes 文件夹下可找到所有支持的主题;主题名称就是文件夹名,例如 example,fukasawa,gitbook,heo,hexo,landing,matery,medium,next,nobelium,plog,simple
LANG: process.env.NEXT_PUBLIC_LANG || 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.
SINCE: process.env.NEXT_PUBLIC_SINCE || 2021, // e.g if leave this empty, current year will be used.
@@ -20,7 +19,8 @@ const BLOG = {
KEYWORDS: process.env.NEXT_PUBLIC_KEYWORD || 'Notion, 博客', // 网站关键词 英文逗号隔开
BLOG_FAVICON: process.env.NEXT_PUBLIC_FAVICON || '/favicon.ico', // blog favicon 配置,默认使用 /public/favicon.ico支持在线图片如 https://img.imesong.com/favicon.png
BEI_AN: process.env.NEXT_PUBLIC_BEI_AN || '', // 备案号 闽 ICP 备 XXXXXX
BEI_AN_LINK: process.env.NEXT_PUBLIC_BEI_AN_LINK || 'https://beian.miit.gov.cn/', // 备案查询链接,如果用了萌备等备案请在这里填写
BEI_AN_LINK:
process.env.NEXT_PUBLIC_BEI_AN_LINK || 'https://beian.miit.gov.cn/', // 备案查询链接,如果用了萌备等备案请在这里填写
// RSS 订阅
ENABLE_RSS: process.env.NEXT_PUBLIC_ENABLE_RSS || true, // 是否开启 RSS 订阅功能

View File

@@ -14,7 +14,6 @@ export const BlogItem = props => {
const showPageCover = siteConfig('SIMPLE_POST_COVER_ENABLE', false, CONFIG)
const showPreview =
siteConfig('POST_LIST_PREVIEW', false, NOTION_CONFIG) && post.blockMap
console.log(post);
return (
<div
key={post.id}

View File

@@ -35,7 +35,7 @@ export default function BlogListPage(props) {
.replace('.html', '')
return (
<div className='w-full md:pr-8 mb-12 md:mt-20'>
<div className='w-full md:pr-8 mb-12'>
<div id='posts-wrapper'>
{posts?.map((p, index) => (
<div key={p.id}>

View File

@@ -18,38 +18,71 @@ const Catalog = ({ post }) => {
// 监听滚动事件
useEffect(() => {
const throttleMs = 200
// 如果没有文章或目录,不执行任何操作
if (!post || !post?.toc || post?.toc?.length < 1) {
return
}
const throttleMs = 100 // 降低节流时间提高响应速度
const actionSectionScrollSpy = throttle(() => {
const sections = document.getElementsByClassName('notion-h')
if (!sections || sections.length === 0) return
let prevBBox = null
let currentSectionId = activeSection
let currentSectionId = null
// 先检查当前视口中的所有标题
for (let i = 0; i < sections.length; ++i) {
const section = sections[i]
if (!section || !(section instanceof Element)) continue
if (!currentSectionId) {
currentSectionId = section.getAttribute('data-id')
}
const bbox = section.getBoundingClientRect()
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
const offset = Math.max(150, prevHeight / 4)
const offset = 100 // 固定偏移量,避免计算不稳定
// 如果标题在视口上方或接近顶部,认为是当前标题
if (bbox.top - offset < 0) {
currentSectionId = section.getAttribute('data-id')
prevBBox = bbox
continue
} else {
// 找到第一个在视口下方的标题就停止
break
}
}
// 如果没找到任何标题在视口上方,使用第一个标题
if (!currentSectionId && sections.length > 0) {
currentSectionId = sections[0].getAttribute('data-id')
}
// 只有当 ID 变化时才更新状态,减少不必要的渲染
if (currentSectionId !== activeSection) {
setActiveSection(currentSectionId)
// 查找目录中对应的索引并滚动
const index = post?.toc?.findIndex(
obj => uuidToId(obj.id) === currentSectionId
)
if (index !== -1 && tRef?.current) {
tRef.current.scrollTo({ top: 28 * index, behavior: 'smooth' })
}
break
}
setActiveSection(currentSectionId)
const index = post?.toc?.findIndex(
obj => uuidToId(obj.id) === currentSectionId
)
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
}, throttleMs)
window.addEventListener('scroll', actionSectionScrollSpy)
actionSectionScrollSpy()
const content = document.querySelector('#container-inner')
if (!content) return // 防止 content 不存在
// 添加滚动和内容变化的监听
content.addEventListener('scroll', actionSectionScrollSpy)
// 初始执行一次
setTimeout(() => {
actionSectionScrollSpy()
}, 300) // 延迟执行确保 DOM 已完全加载
return () => {
window.removeEventListener('scroll', actionSectionScrollSpy)
content?.removeEventListener('scroll', actionSectionScrollSpy)
}
}, [post])
@@ -68,21 +101,27 @@ const Catalog = ({ post }) => {
<div
className='overflow-y-auto overscroll-none max-h-36 lg:max-h-96 scroll-hidden'
ref={tRef}>
<nav className='h-full text-black'>
<nav className='h-full text-black group'>
{post?.toc?.map(tocItem => {
const id = uuidToId(tocItem.id)
return (
<a
key={id}
href={`#${id}`}
className={`${activeSection === id && 'dark:border-white border-red-700 text-red-700 font-bold'} hover:font-semibold border-l pl-4 block hover:text-red-600 border-lduration-300 transform dark:text-red-400 dark:border-red-400
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} catalog-item `}>
className={`${activeSection === id
? 'dark:border-white border-red-700 text-red-700 font-bold'
: 'text-[var(--primary-color)] dark:text-gray-500 filter blur-[1px] opacity-50 group-hover:filter-none group-hover:blur-0 group-hover:opacity-100'}
hover:font-semibold hover:text-red-600 hover:filter-none hover:blur-0 hover:opacity-100
border-l pl-4 block border-lduration-300 transform
dark:hover:text-red-400 dark:border-gray-600
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} catalog-item
transition-all duration-300 ease-in-out`}>
<span
style={{
display: 'inline-block',
marginLeft: tocItem.indentLevel * 16
}}
className={`truncate ${activeSection === id ? ' font-bold text-red-600 dark:text-white underline' : ''}`}>
className={`truncate ${activeSection === id ? 'font-bold text-red-600 dark:text-white underline' : ''}`}>
{tocItem.text}
</span>
</a>

View File

@@ -14,11 +14,15 @@ import Link from 'next/link'
export default function NavBar(props) {
return (
<div className='flex flex-col justify-between md:mt-20 md:h-[70vh]'>
<header className='md:pb-8 md:border-l-2 md:border-gray-700 text-[var(--primary-color)] md:[writing-mode:vertical-lr] px-4'>
<header className='w-fit self-center md:self-start md:pb-8 md:border-l-2 md:border-[var(--primary-color)] text-[var(--primary-color)] md:[writing-mode:vertical-lr] px-4 hover:bg-[var(--primary-color)] hover:text-white ease-in-out duration-700 md:hover:pt-4 md:hover:pb-4'>
<Link href='/'>
<div className='flex flex-col-reverse md:flex-col items-center md:items-start'>
<div className='font-bold text-4xl text-center' id='blog-name'>活版印字</div>
<div className='font-bold text-xl text-center' id='blog-name-en'>Typography</div>
<div className='font-bold text-4xl text-center' id='blog-name'>
活版印字
</div>
<div className='font-bold text-xl text-center' id='blog-name-en'>
Typography
</div>
</div>
</Link>
</header>

View File

@@ -12,6 +12,7 @@ import { createContext, useContext, useEffect, useRef } from 'react'
import BlogPostBar from './components/BlogPostBar'
import CONFIG from './config'
import { Style } from './style'
import Catalog from './components/Catalog'
const AlgoliaSearchModal = dynamic(
() => import('@/components/AlgoliaSearchModal'),
@@ -19,9 +20,7 @@ const AlgoliaSearchModal = dynamic(
)
// 主题组件
const BlogListScroll = dynamic(() => import('./components/BlogListScroll'), {
ssr: false
})
const BlogArchiveItem = dynamic(() => import('./components/BlogArchiveItem'), {
ssr: false
})
@@ -35,9 +34,7 @@ const Comment = dynamic(() => import('@/components/Comment'), { ssr: false })
const ArticleAround = dynamic(() => import('./components/ArticleAround'), {
ssr: false
})
const ShareBar = dynamic(() => import('@/components/ShareBar'), { ssr: false })
const TopBar = dynamic(() => import('./components/TopBar'), { ssr: false })
const Header = dynamic(() => import('./components/Header'), { ssr: false })
const NavBar = dynamic(() => import('./components/NavBar'), { ssr: false })
const JumpToTopButton = dynamic(() => import('./components/JumpToTopButton'), {
ssr: false
@@ -66,9 +63,11 @@ export const useSimpleGlobal = () => useContext(ThemeGlobalSimple)
*/
const LayoutBase = props => {
const { children, slotTop } = props
const { onLoading, fullWidth } = useGlobal()
// const { onLoading, fullWidth } = useGlobal()
const onLoading = true
const searchModal = useRef(null)
console.log('aa', props)
return (
<ThemeGlobalSimple.Provider value={{ searchModal }}>
<div
@@ -78,13 +77,19 @@ const LayoutBase = props => {
{siteConfig('SIMPLE_TOP_BAR', null, CONFIG) && <TopBar {...props} />}
<div className='flex flex-1 gap-24 mx-auto overflow-hidden p-8 md:p-0 md:max-w-7xl md:w-8/12 w-screen'>
<div className='flex flex-1 mx-auto overflow-hidden p-8 md:p-0 md:max-w-7xl md:w-8/12 w-screen'>
{/* 主体 - 使用 flex 布局 */}
<div className='overflow-hidden'>
{/* 文章详情才显示 */}
{props.post && (
<div className='mt-20 hidden md:block'>
<Catalog {...props} />
</div>
)}
<div className='overflow-hidden mt-20'>
{/* 左侧内容区域 - 可滚动 */}
<div
id='container-inner'
className='flex-1 h-full w-full overflow-y-auto scroll-hidden'>
className='flex-1 h-full w-full px-24 overflow-y-auto scroll-hidden'>
{/* 移动端导航 - 显示在顶部 */}
<div className='md:hidden'>
<NavBar {...props} />
@@ -103,6 +108,17 @@ const LayoutBase = props => {
{children}
</Transition>
{onLoading && (
<div className="flex flex-col justify-center items-center min-h-[50vh]">
<div className="flex space-x-2">
<div className="w-2 h-2 bg-gray-500 dark:bg-gray-300 rounded-full animate-bounce [animation-delay:-0.3s]"></div>
<div className="w-2 h-2 bg-gray-500 dark:bg-gray-300 rounded-full animate-bounce [animation-delay:-0.15s]"></div>
<div className="w-2 h-2 bg-gray-500 dark:bg-gray-300 rounded-full animate-bounce"></div>
</div>
<div className="text-xl font-medium text-gray-600 dark:text-gray-300">别着急坐和放宽</div>
</div>
)}
<AdSlot type='native' />
{/* 移动端页脚 - 显示在底部 */}
<div className='md:hidden z-30 dark:bg-black'>
@@ -110,6 +126,7 @@ const LayoutBase = props => {
</div>
</div>
</div>
{/* 右侧导航和页脚 - 固定不滚动 */}
<div className='hidden md:flex md:flex-col md:flex-shrink-0 md:h-[100vh] sticky top-20'>
<NavBar {...props} />
@@ -217,7 +234,7 @@ const LayoutSlug = props => {
{!lock && post && (
<div
className={`px-2 md:pt-20 pt-3 ${fullWidth ? '' : 'xl:max-w-4xl 2xl:max-w-6xl'}`}>
className={`px-2 pt-3 ${fullWidth ? '' : 'xl:max-w-4xl 2xl:max-w-6xl'}`}>
{/* 文章信息 */}
<ArticleInfo post={post} />

View File

@@ -39,7 +39,7 @@ const Style = () => {
#theme-typography {
--primary-color: #2e405b;
background-color: rgb(255 255 255) / 1;
color: rgb(46, 64, 91);
color: #2e405b;
background-size: 7px 7px;
text-shadow: 1px 1px 1px rgb(0 0 0 / 0.04);
background-image: linear-gradient(