diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js index b2ef8f19..ee4fae68 100644 --- a/lib/notion/getPostBlocks.js +++ b/lib/notion/getPostBlocks.js @@ -2,7 +2,7 @@ import BLOG from '@/blog.config' import { NotionAPI } from 'notion-client' import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager' -export async function getPostBlocks (id, from, slice) { +export async function getPostBlocks (id, from, slice, retryCount = 3) { const cacheKey = 'page_block_' + id let pageBlock = await getDataFromCache(cacheKey) if (pageBlock) { @@ -17,6 +17,10 @@ export async function getPostBlocks (id, from, slice) { console.log('[请求成功]', `from:${from}`, `id:${id}`) } catch (error) { console.error('[请求失败]', `from:${from}`, `id:${id}`, `error:${error}`) + if (retryCount && retryCount > 0) { // 重试 + console.error('[重试请求]', `from:${from}`, `id:${id}`, `剩余次数:${retryCount}`) + return getPostBlocks(id, from, slice, retryCount - 1) + } return null } diff --git a/pages/index.js b/pages/index.js index be549212..599b3cf9 100644 --- a/pages/index.js +++ b/pages/index.js @@ -27,7 +27,6 @@ export async function getStaticProps () { BLOG.POSTS_PER_PAGE * page ) if (THEME_CONFIG.POST_LIST_PREVIEW || BLOG.POST_LIST_PREVIEW) { - console.log('加载预览') for (const i in postsToShow) { const post = postsToShow[i] const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES) diff --git a/pages/page/[page].js b/pages/page/[page].js index f0f67312..211a2f92 100644 --- a/pages/page/[page].js +++ b/pages/page/[page].js @@ -45,7 +45,6 @@ export async function getStaticProps ({ params: { page } }) { ) // 加载预览 if (THEME_CONFIG.POST_LIST_PREVIEW || BLOG.POST_LIST_PREVIEW) { - console.log('加载预览') for (const i in postsToShow) { const post = postsToShow[i] const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES) diff --git a/pages/search/[keyword].js b/pages/search/[keyword].js new file mode 100644 index 00000000..01f3a46b --- /dev/null +++ b/pages/search/[keyword].js @@ -0,0 +1,120 @@ +import { getGlobalNotionData } from '@/lib/notion/getNotionData' +import { LayoutSearch } from '@/themes' +import BLOG from '@/blog.config' +import { useGlobal } from '@/lib/global' +import { getDataFromCache } from '@/lib/cache/cache_manager' + +export async function getStaticPaths () { + return { + paths: [], + 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') { + let result = '' + textArray.forEach(textObj => { + result = result + getTextContent(textObj) + }) + return result + } else if (typeof textArray === 'string') { + return textArray + } +} + +export async function getStaticProps ({ params: { keyword } }) { + const { + allPosts, + categories, + tags, + postCount, + latestPosts, + customNav + } = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] }) + + const filterPosts = [] + for (const post of allPosts) { + const cacheKey = 'page_block_' + post.id + const page = await getDataFromCache(cacheKey) + const tagContent = post.tags ? post.tags.join(' ') : '' + const categoryContent = post.category ? post.category.join(' ') : '' + let indexContent = [post.title, post.summary, tagContent, categoryContent] + console.log('搜索是否命中缓存', page !== null) + if (page !== null) { + 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') + }) + } + post.results = [] + let hit = false + const re = new RegExp(`${keyword}`, 'g') + indexContent.forEach(c => { + const index = c.toLowerCase().indexOf(keyword.toLowerCase()) + if (index > -1) { + hit = true + const referText = c?.replace(re, `${keyword}`) + post.results.push(`${referText}`) + } else { + post.results.push(`${c}`) + } + }) + + if (hit) { + filterPosts.push(post) + } + } + + return { + props: { + posts: filterPosts, + tags, + categories, + postCount, + latestPosts, + customNav, + keyword + }, + revalidate: 1 + } +} + +const Index = (props) => { + const { keyword } = props + const { locale } = useGlobal() + const meta = { + title: `${keyword || ''} | ${locale.NAV.SEARCH} | ${BLOG.TITLE} `, + description: BLOG.DESCRIPTION, + type: 'website' + } + return +} + +export default Index diff --git a/pages/search.js b/pages/search/index.js similarity index 100% rename from pages/search.js rename to pages/search/index.js diff --git a/themes/NEXT/Layout404.js b/themes/NEXT/Layout404.js index 9c51b293..2fcfc7aa 100644 --- a/themes/NEXT/Layout404.js +++ b/themes/NEXT/Layout404.js @@ -23,7 +23,7 @@ export const Layout404 = (props) => {
-

404

+

404

页面无法加载,即将返回首页

diff --git a/themes/NEXT/components/BlogPostCard.js b/themes/NEXT/components/BlogPostCard.js index d2f2c9be..2e104601 100644 --- a/themes/NEXT/components/BlogPostCard.js +++ b/themes/NEXT/components/BlogPostCard.js @@ -41,10 +41,16 @@ const BlogPostCard = ({ post, showSummary }) => {
- {(!showPreview || showSummary) &&

+ {(!showPreview || showSummary) && !post.results &&

{post.summary}

} + {/* 搜索结果 */} + {post.results &&

+ {post.results.map(r => ...)} +

+ } + {showPreview && post?.blockMap &&
{ handleGetMore() }} - className='w-full my-4 py-4 text-center cursor-pointer glassmorphism shadow-xl rounded-xl dark:text-gray-200' + className='w-full my-4 py-4 text-center cursor-pointer glassmorphism shadow hover:shadow-xl duration-200 dark:text-gray-200' > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}
diff --git a/themes/NEXT/components/SearchInput.js b/themes/NEXT/components/SearchInput.js index 48399f85..2b4e88be 100644 --- a/themes/NEXT/components/SearchInput.js +++ b/themes/NEXT/components/SearchInput.js @@ -4,7 +4,7 @@ import { useImperativeHandle, useRef, useState } from 'react' const SearchInput = ({ currentTag, currentSearch, cRef }) => { const { locale } = useGlobal() - const [searchKey, setSearchKey] = useState(currentSearch || '') + // const [searchKey, setSearchKey] = useState(currentSearch || '') const [onLoading, setLoadingState] = useState(false) const router = useRouter() const searchInputRef = useRef() @@ -18,9 +18,10 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => { const handleSearch = (key) => { if (key && key !== '') { setLoadingState(true) - router.push({ pathname: '/search', query: { s: key } }).then(r => { - setLoadingState(false) - }) + // router.push({ pathname: '/search/' + key }).then(r => { + // setLoadingState(false) + // }) + location.href = '/search/' + key } else { router.push({ pathname: '/' }).then(r => { }) @@ -35,11 +36,17 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => { } const cleanSearch = () => { searchInputRef.current.value = '' - setSearchKey('') + setShowClean(false) } + const [showClean, setShowClean] = useState(false) const updateSearchKey = (val) => { - setSearchKey(val) + searchInputRef.current.value = val + if (val) { + setShowClean(true) + } else { + setShowClean(false) + } } return
@@ -50,12 +57,12 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => { className={'w-full text-sm pl-4 transition focus:shadow-lg font-light leading-10 border-gray-300 text-black bg-gray-100 dark:bg-gray-900 dark:text-white'} onKeyUp={handleKeyUp} onChange={e => updateSearchKey(e.target.value)} - defaultValue={searchKey} + defaultValue={currentSearch} /> - {(searchKey && searchKey.length && )} + {(showClean && )}
{ handleSearch(searchKey) }}> + onClick={handleSearch}>
diff --git a/themes/NEXT/components/SideAreaLeft.js b/themes/NEXT/components/SideAreaLeft.js index e59662be..9eb9a372 100644 --- a/themes/NEXT/components/SideAreaLeft.js +++ b/themes/NEXT/components/SideAreaLeft.js @@ -19,7 +19,7 @@ import CONFIG_NEXT from '../config_next' * @constructor */ const SideAreaLeft = (props) => { - const { currentTag, post, postCount, currentSearch } = props + const { post, postCount } = props const { locale } = useGlobal() const showToc = post && post.toc && post.toc.length > 1 return