Skip to content

Commit 7c68d1a

Browse files
committed
移动端适配
1 parent 1feba5b commit 7c68d1a

16 files changed

+308
-44
lines changed

themes/Fukasawa/LayoutArchive.js

+56-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,61 @@
1+
import BLOG from '@/blog.config'
2+
import { useGlobal } from '@/lib/global'
3+
import { useEffect } from 'react'
4+
import BlogArchiveItem from './components/BlogPostArchive'
15
import LayoutBase from './LayoutBase'
26

37
export const LayoutArchive = (props) => {
4-
return <LayoutBase {...props}>
5-
Archive Page
8+
const { locale } = useGlobal()
9+
const { posts } = props
10+
// 深拷贝
11+
const postsSortByDate = Object.create(posts)
12+
13+
// 时间排序
14+
postsSortByDate.sort((a, b) => {
15+
const dateA = new Date(a?.date.start_date || a.createdTime)
16+
const dateB = new Date(b?.date.start_date || b.createdTime)
17+
return dateB - dateA
18+
})
19+
20+
const meta = {
21+
title: `${locale.NAV.ARCHIVE} | ${BLOG.title}`,
22+
description: BLOG.description,
23+
type: 'website'
24+
}
25+
26+
const archivePosts = {}
27+
28+
postsSortByDate.forEach(post => {
29+
const date = post.date.start_date.slice(0, 7)
30+
if (archivePosts[date]) {
31+
archivePosts[date].push(post)
32+
} else {
33+
archivePosts[date] = [post]
34+
}
35+
})
36+
37+
useEffect(() => {
38+
if (window) {
39+
const anchor = window.location.hash
40+
if (anchor) {
41+
setTimeout(() => {
42+
const anchorElement = document.getElementById(anchor.substring(1))
43+
if (anchorElement) {
44+
anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' })
45+
}
46+
}, 300)
47+
}
48+
}
49+
}, [])
50+
return <LayoutBase {...props} meta={meta}>
51+
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-gray-800 shadow-md min-h-full">
52+
{Object.keys(archivePosts).map(archiveTitle => (
53+
<BlogArchiveItem
54+
key={archiveTitle}
55+
posts={archivePosts[archiveTitle]}
56+
archiveTitle={archiveTitle}
57+
/>
58+
))}
59+
</div>
660
</LayoutBase>
761
}

themes/Fukasawa/LayoutBase.js

+15-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import CommonHead from '@/components/CommonHead'
2+
import TopNav from './components/TopNav'
23
import AsideLeft from './components/AsideLeft'
34

45
/**
@@ -15,27 +16,23 @@ import AsideLeft from './components/AsideLeft'
1516
* @returns {JSX.Element}
1617
* @constructor
1718
*/
18-
const LayoutBase = ({
19-
children,
20-
headerSlot,
21-
tags,
22-
meta,
23-
post,
24-
postCount,
25-
sideBarSlot,
26-
floatSlot,
27-
rightAreaSlot,
28-
currentSearch,
29-
currentCategory,
30-
currentTag,
31-
categories
32-
}) => {
19+
const LayoutBase = (props) => {
20+
const {
21+
children,
22+
headerSlot,
23+
tags,
24+
meta,
25+
currentCategory,
26+
currentTag,
27+
categories
28+
} = props
3329
return (<>
3430
<CommonHead meta={meta} />
35-
<div className='flex flex-between'>
31+
<TopNav {...props}/>
32+
<div className='flex'>
3633
<AsideLeft tags={tags} currentTag={currentTag} categories={categories} currentCategory={currentCategory}/>
37-
<main id='wrapper' className='flex flex-grow py-8 justify-center'>
38-
<div className='2xl:max-w-6xl md:max-w-3xl max-w-md w-full'>
34+
<main id='wrapper' className='flex w-full py-8 justify-center'>
35+
<div className='2xl:max-w-6xl md:max-w-3xl w-full'>
3936
<div> {headerSlot} </div>
4037
<div>{children}</div>
4138
</div>

themes/Fukasawa/LayoutCategory.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import BlogListPage from './components/BlogListPage'
12
import LayoutBase from './LayoutBase'
23

34
export const LayoutCategory = (props) => {
45
return <LayoutBase {...props}>
5-
Category
6+
<BlogListPage page={props.page} posts={props.posts} postCount={props.postCount} />
67
</LayoutBase>
78
}
+28-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
1+
import BLOG from '@/blog.config'
2+
import { useGlobal } from '@/lib/global'
3+
import { faFolder, faTh } from '@fortawesome/free-solid-svg-icons'
4+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
5+
import Link from 'next/link'
16
import LayoutBase from './LayoutBase'
27

38
export const LayoutCategoryIndex = (props) => {
4-
return <LayoutBase {...props}>
5-
Category
6-
</LayoutBase>
9+
const { locale } = useGlobal()
10+
const { categories } = props
11+
const meta = {
12+
title: `${locale.COMMON.CATEGORY} | ${BLOG.title}`,
13+
description: BLOG.description,
14+
type: 'website'
15+
}
16+
return <LayoutBase {...props} meta={meta}>
17+
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
18+
<div className='dark:text-gray-200 mb-5'>
19+
<FontAwesomeIcon icon={faTh} className='mr-4' />{locale.COMMON.CATEGORY}:
20+
</div>
21+
<div id='category-list' className='duration-200 flex flex-wrap'>
22+
{Object.keys(categories).map(category => {
23+
return <Link key={category} href={`/category/${category}`} passHref>
24+
<div
25+
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
26+
<FontAwesomeIcon icon={faFolder} className='mr-4' />{category}({categories[category]})
27+
</div>
28+
</Link>
29+
})}
30+
</div>
31+
</div> </LayoutBase>
732
}

themes/Fukasawa/LayoutTag.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import BlogListPage from './components/BlogListPage'
12
import LayoutBase from './LayoutBase'
23

34
export const LayoutTag = (props) => {
45
return <LayoutBase {...props}>
5-
Tag - {props.tag}
6+
<BlogListPage {...props} />
67
</LayoutBase>
78
}

themes/Fukasawa/LayoutTagIndex.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1+
import BLOG from '@/blog.config'
2+
import { useGlobal } from '@/lib/global'
3+
import { faTag } from '@fortawesome/free-solid-svg-icons'
4+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
5+
import TagItem from './components/TagItem'
16
import LayoutBase from './LayoutBase'
27

38
export const LayoutTagIndex = (props) => {
4-
return <LayoutBase {...props}>
5-
Tag - {props.tag}
9+
const { locale } = useGlobal()
10+
const { tags } = props
11+
const meta = {
12+
title: `${locale.COMMON.TAGS} | ${BLOG.title}`,
13+
description: BLOG.description,
14+
type: 'website'
15+
}
16+
17+
return <LayoutBase {...props} meta={meta}>
18+
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
19+
<div className='dark:text-gray-200 mb-5'><FontAwesomeIcon icon={faTag} className='mr-4'/>{locale.COMMON.TAGS}:</div>
20+
<div id='tags-list' className='duration-200 flex flex-wrap'>
21+
{ tags.map(tag => {
22+
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>
23+
}) }
24+
</div>
25+
</div>
626
</LayoutBase>
727
}

themes/Fukasawa/components/ArticleArount.js themes/Fukasawa/components/ArticleAround.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ export default function ArticleAround ({ prev, next }) {
1313
}
1414
return <section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
1515
<Link href={`/article/${prev.slug}`} passHref>
16-
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-50 hover:bg-gray-700 hover:text-white duration-300'>
16+
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>
1717
<FontAwesomeIcon icon={faAngleDoubleLeft} className='mr-1' />{prev.title}
1818
</a>
1919
</Link>
2020
<Link href={`/article/${next.slug}`} passHref>
21-
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-50 hover:bg-gray-700 hover:text-white duration-300'>{next.title}
21+
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>{next.title}
2222
<FontAwesomeIcon icon={faAngleDoubleRight} className='ml-1 my-1' />
2323
</a>
2424
</Link>

themes/Fukasawa/components/ArticleDetail.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import 'prismjs/components/prism-python'
1313
import 'prismjs/components/prism-typescript'
1414
import { useEffect, useRef } from 'react'
1515
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
16-
import ArticleAround from './ArticleArount'
16+
import ArticleAround from './ArticleAround'
1717

1818
/**
1919
*
@@ -42,17 +42,18 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
4242
}
4343
})
4444

45-
return (<div id="container" className=" max-w-4xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
45+
return (<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
46+
{post.type && !post.type.includes('Page') && post?.page_cover && (
47+
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
48+
{/* eslint-disable-next-line @next/next/no-img-element */}
49+
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
50+
</div>
51+
)}
4652
<article itemScope itemType="https://schema.org/Movie"
47-
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-gray-800"
53+
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-gray-800"
4854
>
4955

5056
<header className='animate__slideInDown animate__animated'>
51-
{post.type && !post.type.includes('Page') && post?.page_cover && (
52-
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
53-
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
54-
</div>
55-
)}
5657

5758
{/* 文章Title */}
5859
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">

themes/Fukasawa/components/AsideLeft.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import SearchInput from './SearchInput'
77
import SiteInfo from './SiteInfo'
88

99
function AsideLeft ({ tags, currentTag, categories, currentCategory }) {
10-
return <div className='w-72 bg-white min-h-screen px-10 py-14'>
10+
return <div className='w-72 bg-white min-h-screen px-10 py-14 hidden lg:block'>
1111

1212
<Logo />
1313

themes/Fukasawa/components/BlogCard.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Card from './Card'
88
const BlogCard = ({ post, showSummary }) => {
99
const showPreview = CONFIG_FUKA.POST_LIST_PREVIEW && post.blockMap
1010
return (
11-
<Card className='w-full max-w-sm p-2'>
11+
<Card className='w-full lg:max-w-sm p-2'>
1212
<div key={post.id} className='animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300'>
1313

1414
<div className='p-2 flex flex-col w-full'>

themes/Fukasawa/components/BlogListPage.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import BLOG from '@/blog.config'
2+
import { useEffect, useState } from 'react'
23
import BlogCard from './BlogCard'
34
import BlogPostListEmpty from './BlogListEmpty'
45
import PaginationSimple from './PaginationSimple'
@@ -13,14 +14,32 @@ import PaginationSimple from './PaginationSimple'
1314
*/
1415
const BlogListPage = ({ page = 1, posts = [], postCount }) => {
1516
const totalPage = Math.ceil(postCount / BLOG.postsPerPage)
16-
const showNext = page < totalPage
17+
const showNext = page < totalPage && posts.length < postCount
18+
const [colCount, changeCol] = useState(3)
19+
20+
function updateCol () {
21+
if (window.outerWidth > 1200) {
22+
changeCol(3)
23+
} else {
24+
changeCol(1)
25+
}
26+
}
27+
28+
useEffect(() => {
29+
updateCol()
30+
window.addEventListener('resize', updateCol)
31+
return () => {
32+
window.removeEventListener('resize', updateCol)
33+
}
34+
})
35+
1736
if (!posts || posts.length === 0) {
1837
return <BlogPostListEmpty />
1938
} else {
2039
return (
2140
<div id="container">
2241
{/* 文章列表 */}
23-
<div style={{ columnCount: 3 }}>
42+
<div style={{ columnCount: colCount }}>
2443
{posts.map(post => (
2544
<div key={post.id} className='justify-center flex' style={{ breakInside: 'avoid' }}>
2645
<BlogCard key={post.id} post={post} />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react'
2+
import Link from 'next/link'
3+
import BLOG from '@/blog.config'
4+
/**
5+
* 博客归档
6+
* @param posts 所有文章
7+
* @param archiveTitle 归档标题
8+
* @returns {JSX.Element}
9+
* @constructor
10+
*/
11+
const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
12+
if (!posts || posts.length === 0) {
13+
return <></>
14+
} else {
15+
return <div>
16+
<div className='pt-16 pb-4 text-3xl dark:text-gray-300' id={archiveTitle}>{archiveTitle}</div>
17+
<ul>
18+
{posts.map(post => (
19+
<li key={post.id} className='border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500'>
20+
<div name={post?.date?.start_date}><span className='text-gray-400'>{post.date.start_date}</span> &nbsp;
21+
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
22+
<a className='dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600'>{post.title}</a>
23+
</Link>
24+
</div>
25+
</li>
26+
))}
27+
</ul>
28+
</div>
29+
}
30+
}
31+
32+
export default BlogArchiveItem
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { useEffect, useRef } from 'react'
2+
3+
const Collapse = props => {
4+
const collapseRef = useRef(null)
5+
const collapseSection = element => {
6+
const sectionHeight = element.scrollHeight
7+
requestAnimationFrame(function () {
8+
element.style.height = sectionHeight + 'px'
9+
requestAnimationFrame(function () {
10+
element.style.height = 0 + 'px'
11+
})
12+
})
13+
}
14+
const expandSection = element => {
15+
const sectionHeight = element.scrollHeight
16+
element.style.height = sectionHeight + 'px'
17+
const clearTime = setTimeout(() => {
18+
element.style.height = 'auto'
19+
}, 400)
20+
clearTimeout(clearTime)
21+
}
22+
useEffect(() => {
23+
const element = collapseRef.current
24+
if (props.isOpen) {
25+
expandSection(element)
26+
} else {
27+
collapseSection(element)
28+
}
29+
}, [props.isOpen])
30+
return (
31+
<div ref={collapseRef} style={{ height: '0px' }} className='overflow-hidden duration-200'>
32+
{props.children}
33+
</div>
34+
)
35+
}
36+
Collapse.defaultProps = { isOpen: false }
37+
38+
export default Collapse

0 commit comments

Comments
 (0)