mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-16 15:09:28 +00:00
搜索页面分页处理
This commit is contained in:
@@ -38,6 +38,13 @@ export async function getStaticProps({ params: { keyword } }) {
|
||||
const { allPages } = props
|
||||
const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published')
|
||||
props.posts = await filterByMemCache(allPosts, keyword)
|
||||
props.postCount = props.posts.length
|
||||
// 处理分页
|
||||
if (BLOG.POST_LIST_STYLE === 'scroll') {
|
||||
// 滚动列表 给前端返回所有数据
|
||||
} else if (BLOG.POST_LIST_STYLE === 'page') {
|
||||
props.posts = props.posts?.slice(0, BLOG.POSTS_PER_PAGE - 1)
|
||||
}
|
||||
props.keyword = keyword
|
||||
return {
|
||||
props,
|
||||
156
pages/search/[keyword]/page/[page].js
Normal file
156
pages/search/[keyword]/page/[page].js
Normal file
@@ -0,0 +1,156 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getDataFromCache } from '@/lib/cache/cache_manager'
|
||||
import * as ThemeMap from '@/themes'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
const Index = props => {
|
||||
const { keyword, siteInfo } = props
|
||||
const { locale } = useGlobal()
|
||||
const meta = {
|
||||
title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`,
|
||||
description: siteInfo?.title,
|
||||
image: siteInfo?.pageCover,
|
||||
slug: 'search/' + (keyword || ''),
|
||||
type: 'website'
|
||||
}
|
||||
const { theme } = useGlobal()
|
||||
const ThemeComponents = ThemeMap[theme]
|
||||
return (
|
||||
<ThemeComponents.LayoutSearch
|
||||
{...props}
|
||||
meta={meta}
|
||||
currentSearch={keyword}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端搜索
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export async function getStaticProps({ params: { keyword, page } }) {
|
||||
const props = await getGlobalNotionData({
|
||||
from: 'search-props',
|
||||
pageType: ['Post']
|
||||
})
|
||||
const { allPages } = props
|
||||
const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published')
|
||||
props.posts = await filterByMemCache(allPosts, keyword)
|
||||
props.postCount = props.posts.length
|
||||
// 处理分页
|
||||
props.posts = props.posts.slice(BLOG.POSTS_PER_PAGE * (page - 1), BLOG.POSTS_PER_PAGE * page - 1)
|
||||
props.keyword = keyword
|
||||
props.page = page
|
||||
return {
|
||||
props,
|
||||
revalidate: 1
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [{ params: { keyword: BLOG.TITLE, page: '1' } }],
|
||||
fallback: true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象的指定字段拼接到字符串
|
||||
* @param sourceTextArray
|
||||
* @param targetObj
|
||||
* @param key
|
||||
* @returns {*}
|
||||
*/
|
||||
function appendText(sourceTextArray, targetObj, key) {
|
||||
if (!targetObj) {
|
||||
return sourceTextArray
|
||||
}
|
||||
const textArray = targetObj[key]
|
||||
const text = textArray ? getTextContent(textArray) : ''
|
||||
if (text && text !== 'Untitled') {
|
||||
return sourceTextArray.concat(text)
|
||||
}
|
||||
return sourceTextArray
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归获取层层嵌套的数组
|
||||
* @param {*} textArray
|
||||
* @returns
|
||||
*/
|
||||
function getTextContent(textArray) {
|
||||
if (typeof textArray === 'object' && isIterable(textArray)) {
|
||||
let result = ''
|
||||
for (const textObj of textArray) {
|
||||
result = result + getTextContent(textObj)
|
||||
}
|
||||
return result
|
||||
} else if (typeof textArray === 'string') {
|
||||
return textArray
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象是否可以遍历
|
||||
* @param {*} obj
|
||||
* @returns
|
||||
*/
|
||||
const isIterable = obj =>
|
||||
obj != null && typeof obj[Symbol.iterator] === 'function'
|
||||
|
||||
/**
|
||||
* 在内存缓存中进行全文索引
|
||||
* @param {*} allPosts
|
||||
* @param keyword 关键词
|
||||
* @returns
|
||||
*/
|
||||
async function filterByMemCache(allPosts, keyword) {
|
||||
const filterPosts = []
|
||||
if (keyword) {
|
||||
keyword = keyword.trim()
|
||||
}
|
||||
for (const post of allPosts) {
|
||||
const cacheKey = 'page_block_' + post.id
|
||||
const page = await getDataFromCache(cacheKey, true)
|
||||
const tagContent = post.tags && Array.isArray(post.tags) ? post.tags.join(' ') : ''
|
||||
const categoryContent = post.category && Array.isArray(post.category) ? post.category.join(' ') : ''
|
||||
const articleInfo = post.title + post.summary + tagContent + categoryContent
|
||||
let hit = articleInfo.indexOf(keyword) > -1
|
||||
let indexContent = [post.summary]
|
||||
if (page && page.block) {
|
||||
const contentIds = Object.keys(page.block)
|
||||
contentIds.forEach(id => {
|
||||
const properties = page?.block[id]?.value?.properties
|
||||
indexContent = appendText(indexContent, properties, 'title')
|
||||
indexContent = appendText(indexContent, properties, 'caption')
|
||||
})
|
||||
}
|
||||
// console.log('全文搜索缓存', cacheKey, page != null)
|
||||
post.results = []
|
||||
let hitCount = 0
|
||||
for (const i in indexContent) {
|
||||
const c = indexContent[i]
|
||||
if (!c) {
|
||||
continue
|
||||
}
|
||||
const index = c.toLowerCase().indexOf(keyword.toLowerCase())
|
||||
if (index > -1) {
|
||||
hit = true
|
||||
hitCount += 1
|
||||
post.results.push(c)
|
||||
} else {
|
||||
if ((post.results.length - 1) / hitCount < 3 || i === 0) {
|
||||
post.results.push(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hit) {
|
||||
filterPosts.push(post)
|
||||
}
|
||||
}
|
||||
return filterPosts
|
||||
}
|
||||
|
||||
export default Index
|
||||
@@ -1,11 +1,13 @@
|
||||
|
||||
import BLOG from '@/blog.config'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutIndex = props => {
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<BlogListPage {...props} page={1} />
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import LayoutBase from './LayoutBase'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
|
||||
export const LayoutSearch = props => {
|
||||
const { keyword, posts } = props
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -21,22 +21,6 @@ export const LayoutSearch = props => {
|
||||
}, 100)
|
||||
}, [router.events])
|
||||
|
||||
const { locale } = useGlobal()
|
||||
|
||||
const [page, updatePage] = useState(1)
|
||||
let hasMore = false
|
||||
const postsToShow = posts
|
||||
? Object.assign(posts).slice(0, BLOG.POSTS_PER_PAGE * page)
|
||||
: []
|
||||
|
||||
if (posts) {
|
||||
const totalCount = posts.length
|
||||
hasMore = page * BLOG.POSTS_PER_PAGE < totalCount
|
||||
}
|
||||
const handleGetMore = () => {
|
||||
if (!hasMore) return
|
||||
updatePage(page + 1)
|
||||
}
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (keyword) {
|
||||
@@ -59,36 +43,7 @@ export const LayoutSearch = props => {
|
||||
<SearchInput {...props} />
|
||||
</div>
|
||||
|
||||
{postsToShow.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link href={`/${p.slug}`}>
|
||||
<a className="text-black text-xl md:text-2xl no-underline hover:underline replace"> {p.title}</a>
|
||||
</Link>
|
||||
</h2>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
|
||||
<div className="mb-4 text-sm text-gray-700">
|
||||
by <a href="#" className="text-gray-700">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700">{p.category}</a>
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
<p className="text-gray-700 leading-normal replace">
|
||||
{p.summary}
|
||||
</p>
|
||||
</article>
|
||||
))}
|
||||
|
||||
<div>
|
||||
<div
|
||||
onClick={handleGetMore}
|
||||
className="w-full my-4 py-4 text-center cursor-pointer "
|
||||
>
|
||||
{' '}
|
||||
{hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
@@ -17,35 +17,37 @@ export const BlogListPage = props => {
|
||||
|
||||
return <div className="w-full md:pr-12 mb-12">
|
||||
|
||||
{posts.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link href={`/${p.slug}`}>
|
||||
<a className="text-black dark:text-gray-100 text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
|
||||
</Link>
|
||||
</h2>
|
||||
<div id="container">
|
||||
{posts?.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link href={`/${p.slug}`}>
|
||||
<a className="text-black dark:text-gray-100 text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
<div className="mb-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700 dark:text-gray-300">{p.category}</a>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
<div className="mb-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700 dark:text-gray-300">{p.category}</a>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
<p className="text-gray-700 dark:text-gray-400 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
{/* 搜索结果 */}
|
||||
{p.results && (
|
||||
<p className="mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{p.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
))}
|
||||
<p className="text-gray-700 dark:text-gray-400 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
{/* 搜索结果 */}
|
||||
{p.results && (
|
||||
<p className="mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{p.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between text-xs">
|
||||
<Link href={{ pathname: currentPage - 1 === 1 ? `${BLOG.SUB_PATH || pagePrefix}` : `${pagePrefix}/page/${currentPage - 1}`, query: router.query.s ? { s: router.query.s } : {} }}>
|
||||
|
||||
@@ -43,7 +43,7 @@ export const BlogListScroll = props => {
|
||||
}
|
||||
})
|
||||
|
||||
return <div className="w-full md:pr-12 mb-12" ref={targetRef}>
|
||||
return <div id="container" className="w-full md:pr-12 mb-12" ref={targetRef}>
|
||||
{postsToShow.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import LayoutBase from './LayoutBase'
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
@@ -18,6 +20,6 @@ export const LayoutSearch = (props) => {
|
||||
}, 100)
|
||||
})
|
||||
return <LayoutBase {...props} currentSearch={currentSearch}>
|
||||
<BlogListPage {...props} />
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogListPage from './components/BlogListPage'
|
||||
import BlogListScroll from './components/BlogListScroll'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutTag = (props) => {
|
||||
return <LayoutBase {...props}>
|
||||
<BlogListPage {...props} />
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props}/>}
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ const BlogListPage = ({ page = 1, posts = [], postCount }) => {
|
||||
return <BlogPostListEmpty />
|
||||
} else {
|
||||
return (
|
||||
<div id="container">
|
||||
<div>
|
||||
{/* 文章列表 */}
|
||||
<div style={{ columnCount: colCount }}>
|
||||
<div id="container" style={{ columnCount: colCount }}>
|
||||
{posts?.map(post => (
|
||||
<div key={post.id} className='justify-center flex' style={{ breakInside: 'avoid' }}>
|
||||
<BlogCard key={post.id} post={post} />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import LayoutBase from './LayoutBase'
|
||||
import SearchInput from './components/SearchInput'
|
||||
@@ -25,8 +27,7 @@ export const LayoutSearch = props => {
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(`${currentSearch}`, 'gim')
|
||||
container.innerHTML = container.innerHTML.replace(
|
||||
re,
|
||||
`<span class='text-red-500 border-b border-dashed'>${currentSearch}</span>`
|
||||
re, `<span class='text-red-500 border-b border-dashed'>${currentSearch}</span>`
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -34,56 +35,62 @@ export const LayoutSearch = props => {
|
||||
}, 100)
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
<div className="my-6 px-2">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{!currentSearch && <>
|
||||
<div className="my-6 px-2">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div id="container">
|
||||
<BlogPostListPage {...props} />
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</>}
|
||||
|
||||
{currentSearch && <>
|
||||
<div id="container">
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</>}
|
||||
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import SearchInput from './components/SearchInput'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import TagGroups from './components/TagGroups'
|
||||
import CategoryGroup from './components/CategoryGroup'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import { useEffect } from 'react'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
|
||||
export const LayoutSearch = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
@@ -27,8 +29,8 @@ export const LayoutSearch = (props) => {
|
||||
<TagGroups {...props} />
|
||||
<CategoryGroup {...props} />
|
||||
</div>
|
||||
<div id='container'>
|
||||
<BlogPostListScroll {...props} />
|
||||
<div>
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import LayoutBase from './LayoutBase'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BLOG from '@/blog.config'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
|
||||
export const LayoutTag = (props) => {
|
||||
|
||||
@@ -18,11 +18,13 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
||||
return <BlogPostListEmpty />
|
||||
} else {
|
||||
return (
|
||||
<div id="container" className='w-full justify-center'>
|
||||
<div className='w-full justify-center'>
|
||||
<div id='container'>
|
||||
{/* 文章列表 */}
|
||||
{posts.map(post => (
|
||||
<BlogPostCard key={post.id} post={post} />
|
||||
))}
|
||||
</div>
|
||||
<PaginationSimple page={page} totalPage={totalPage} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import LayoutBase from './LayoutBase'
|
||||
import StickyBar from './components/StickyBar'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
export const LayoutSearch = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
@@ -23,8 +25,10 @@ export const LayoutSearch = (props) => {
|
||||
</div>
|
||||
</StickyBar>
|
||||
<div className="md:mt-5">
|
||||
<BlogPostListScroll {...props} showSummary={true} />
|
||||
</div>
|
||||
{BLOG.POST_LIST_STYLE !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
} </div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ export const LayoutTag = (props) => {
|
||||
const { tags, tag } = props
|
||||
|
||||
return <LayoutBase currentTag={tag} {...props}>
|
||||
<StickyBar>
|
||||
<TagList tags={tags} currentTag={tag}/>
|
||||
</StickyBar>
|
||||
<div className='md:mt-8'>
|
||||
{BLOG.POST_LIST_STYLE !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
<StickyBar>
|
||||
<TagList tags={tags} currentTag={tag} />
|
||||
</StickyBar>
|
||||
<div className='md:mt-8'>
|
||||
{BLOG.POST_LIST_STYLE !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
|
||||
return <BlogPostListEmpty />
|
||||
} else {
|
||||
return (
|
||||
<div id="container">
|
||||
<div>
|
||||
{/* 文章列表 */}
|
||||
<div className="flex flex-wrap lg:space-y-4 space-y-1">
|
||||
<div id="container" className="flex flex-wrap lg:space-y-4 space-y-1">
|
||||
{posts.map(post => (
|
||||
<BlogPostCard key={post.id} post={post} />
|
||||
))}
|
||||
|
||||
@@ -52,10 +52,10 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_NE
|
||||
if (!postsToShow || postsToShow.length === 0) {
|
||||
return <BlogPostListEmpty currentSearch={currentSearch} />
|
||||
} else {
|
||||
return <div id='container' ref={targetRef}>
|
||||
return <div ref={targetRef}>
|
||||
|
||||
{/* 文章列表 */}
|
||||
<div className='flex flex-wrap space-y-1 lg:space-y-4'>
|
||||
<div id='container' className='flex flex-wrap space-y-1 lg:space-y-4'>
|
||||
{postsToShow.map(post => (
|
||||
<BlogPostCard key={post.id} post={post} showSummary={showSummary} />
|
||||
))}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
@@ -13,79 +12,78 @@ const PaginationNumber = ({ page, totalPage }) => {
|
||||
const router = useRouter()
|
||||
const currentPage = +page
|
||||
const showNext = page !== totalPage
|
||||
const pages = generatePages(page, currentPage, totalPage)
|
||||
const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '')
|
||||
const pages = generatePages(pagePrefix, page, currentPage, totalPage)
|
||||
|
||||
return (
|
||||
<div className="my-5 flex justify-center items-end font-medium text-black hover:shadow-xl duration-500 bg-white dark:bg-gray-700 dark:text-gray-300 py-3 shadow space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname:
|
||||
currentPage - 1 === 1
|
||||
? `${BLOG.SUB_PATH || '/'}`
|
||||
: `/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
rel="prev"
|
||||
className={`${
|
||||
currentPage === 1 ? 'invisible' : 'block'
|
||||
} border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-left" />
|
||||
</div>
|
||||
</Link>
|
||||
<div className="my-5 flex justify-center items-end font-medium text-black hover:shadow-xl duration-500 bg-white dark:bg-gray-700 dark:text-gray-300 py-3 shadow space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname:
|
||||
currentPage - 1 === 1
|
||||
? `${pagePrefix}}`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
rel="prev"
|
||||
className={`${currentPage === 1 ? 'invisible' : 'block'
|
||||
} border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-left" />
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{pages}
|
||||
{pages}
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
rel="next"
|
||||
className={`${
|
||||
+showNext ? 'block' : 'invisible'
|
||||
} border-t-2 border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-right" />
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<div
|
||||
rel="next"
|
||||
className={`${+showNext ? 'block' : 'invisible'
|
||||
} border-t-2 border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-right" />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getPageElement(page, currentPage) {
|
||||
function getPageElement(pagePrefix, page, currentPage) {
|
||||
console.log(pagePrefix, page, currentPage)
|
||||
|
||||
return (
|
||||
<Link href={page === 1 ? '/' : `/page/${page}`} key={page} passHref>
|
||||
<a
|
||||
className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-gray-500 dark:bg-gray-400 text-white '
|
||||
: 'border-t-2 duration-500 border-white hover:border-gray-400 ') +
|
||||
' border-white dark:border-gray-700 dark:hover:border-gray-400 cursor-pointer w-6 text-center font-light hover:font-bold'
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={page === 1 ? `${pagePrefix}` : `${pagePrefix}/page/${page}`} key={page} passHref>
|
||||
<a className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-gray-500 dark:bg-gray-400 text-white '
|
||||
: 'border-t-2 duration-500 border-white hover:border-gray-400 ') +
|
||||
' border-white dark:border-gray-700 dark:hover:border-gray-400 cursor-pointer w-6 text-center font-light hover:font-bold'
|
||||
} >
|
||||
{page}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
function generatePages(page, currentPage, totalPage) {
|
||||
function generatePages(pagePrefix, page, currentPage, totalPage) {
|
||||
const pages = []
|
||||
const groupCount = 7 // 最多显示页签数
|
||||
if (totalPage <= groupCount) {
|
||||
for (let i = 1; i <= totalPage; i++) {
|
||||
pages.push(getPageElement(i, page))
|
||||
pages.push(getPageElement(pagePrefix, i, page))
|
||||
}
|
||||
} else {
|
||||
pages.push(getPageElement(1, page))
|
||||
pages.push(getPageElement(pagePrefix, 1, page))
|
||||
const dynamicGroupCount = groupCount - 2
|
||||
let startPage = currentPage - 2
|
||||
if (startPage <= 1) {
|
||||
@@ -100,7 +98,7 @@ function generatePages(page, currentPage, totalPage) {
|
||||
|
||||
for (let i = 0; i < dynamicGroupCount; i++) {
|
||||
if (startPage + i < totalPage) {
|
||||
pages.push(getPageElement(startPage + i, page))
|
||||
pages.push(getPageElement(pagePrefix, startPage + i, page))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +106,7 @@ function generatePages(page, currentPage, totalPage) {
|
||||
pages.push(<div key={-2}>... </div>)
|
||||
}
|
||||
|
||||
pages.push(getPageElement(totalPage, page))
|
||||
pages.push(getPageElement(pagePrefix, totalPage, page))
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user