From beeed7f632c5a6ab015a3c4503613335965ec5e9 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 28 Jul 2023 20:42:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6CommenHead=EF=BC=9B=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4Algolia=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/AlgoliaSearchModal.js | 153 ++++++++++++++++++++++---- components/Mark.js | 5 +- lib/global.js | 9 +- pages/_app.js | 5 +- themes/example/index.js | 5 +- themes/fukasawa/index.js | 4 +- themes/gitbook/index.js | 4 +- themes/heo/components/NavBar.js | 4 +- themes/heo/components/SearchButton.js | 4 +- themes/heo/index.js | 4 +- themes/medium/index.js | 5 +- themes/next/index.js | 6 +- themes/nobelium/index.js | 4 +- themes/plog/index.js | 7 +- themes/simple/index.js | 4 +- themes/theme.js | 1 - 16 files changed, 156 insertions(+), 68 deletions(-) diff --git a/components/AlgoliaSearchModal.js b/components/AlgoliaSearchModal.js index 32d0401d..ff372733 100644 --- a/components/AlgoliaSearchModal.js +++ b/components/AlgoliaSearchModal.js @@ -1,7 +1,10 @@ -import { useState, useImperativeHandle } from 'react' +import { useState, useImperativeHandle, useRef } from 'react' import BLOG from '@/blog.config' import algoliasearch from 'algoliasearch' import replaceSearchResult from '@/components/Mark' +import Link from 'next/link' +import { useGlobal } from '@/lib/global' +import throttle from 'lodash/throttle' /** * 结合 Algolia 实现的弹出式搜索框 @@ -11,6 +14,12 @@ import replaceSearchResult from '@/components/Mark' export default function AlgoliaSearchModal({ cRef }) { const [searchResults, setSearchResults] = useState([]) const [isModalOpen, setIsModalOpen] = useState(false) + const [page, setPage] = useState(0) + const [keyword, setKeyword] = useState(null) + const [totalPage, setTotalPage] = useState(0) + const [totalHit, setTotalHit] = useState(0) + const [useTime, setUseTime] = useState(0) + /** * 对外暴露方法 */ @@ -22,40 +31,80 @@ export default function AlgoliaSearchModal({ cRef }) { } }) - if (!BLOG.ALGOLIA_APP_ID) { - return <> - } - const client = algoliasearch(BLOG.ALGOLIA_APP_ID, BLOG.ALGOLIA_SEARCH_ONLY_APP_KEY) const index = client.initIndex(BLOG.ALGOLIA_INDEX) - const handleSearch = async (query) => { + /** + * 搜索 + * @param {*} query + */ + const handleSearch = async (query, page) => { + setKeyword(query) + setPage(page) + setSearchResults([]) + setUseTime(0) + setTotalPage(0) + setTotalHit(0) + if (!query || query === '') { + return + } + try { - const res = await index.search(query) - console.log(res) - const { hits } = res + const res = await index.search(query, { page, hitsPerPage: 10 }) + const { hits, nbHits, nbPages, processingTimeMS } = res + setUseTime(processingTimeMS) + setTotalPage(nbPages) + setTotalHit(nbHits) setSearchResults(hits) + const doms = document.getElementById('search-wrapper').getElementsByClassName('replace') - replaceSearchResult({ - doms, - search: query, - target: { - element: 'span', - className: 'text-blue-600 border-b border-dashed' - } - }) + + setTimeout(() => { + replaceSearchResult({ + doms, + search: query, + target: { + element: 'span', + className: 'text-blue-600 border-b border-dashed' + } + }) + }, 150) } catch (error) { console.error('Algolia search error:', error) } } + const throttledHandleSearch = useRef(throttle(handleSearch, 300)) // 设置节流延迟时间 + + // 修改input的onChange事件处理函数 + const handleInputChange = (e) => { + const query = e.target.value + throttledHandleSearch.current(query, 0) + } + + /** + * 切换页码 + * @param {*} page + */ + const switchPage = (page) => { + throttledHandleSearch.current(keyword, page) + } + + /** + * 关闭弹窗 + */ const closeModal = () => { setIsModalOpen(false) } + if (!BLOG.ALGOLIA_APP_ID) { + return <> + } + return ( -
- {/* 内容 */} +
+ + {/* 模态框 */}
@@ -63,12 +112,12 @@ export default function AlgoliaSearchModal({ cRef }) {
- handleSearch(e.target.value)} + handleInputChange(e)} className="bg-gray-50 dark:bg-gray-600 outline-blue-500 w-full px-4 my-2 py-1 mb-4 border rounded-md" /> {/* 标签组 */} -
- +
+
    @@ -81,7 +130,9 @@ export default function AlgoliaSearchModal({ cRef }) { ))}
-
Algolia 提供搜索服务
+ +
{totalHit > 0 &&
共搜索到 {totalHit} 条结果,用时 {useTime} 毫秒
}
+
Algolia 提供搜索服务
{/* 遮罩 */} @@ -90,3 +141,59 @@ export default function AlgoliaSearchModal({ cRef }) {
) } + +/** + * 标签组 + */ +function TagGroups(props) { + const { tagOptions } = useGlobal() + // 获取tagOptions数组前十个 + const firstTenTags = tagOptions.slice(0, 10) + + return
+ { + firstTenTags?.map((tag, index) => { + return +
+
{tag.name}
{tag.count ? {tag.count} : <>} +
+ + + }) + } +
+} + +/** + * 分页 + * @param {*} param0 + */ +function Pagination(props) { + const { totalPage, page, switchPage } = props + if (totalPage <= 0) { + return <> + } + const pagesElement = [] + + for (let i = 0; i < totalPage; i++) { + const selected = page === i + pagesElement.push(getPageElement(i, selected, switchPage)) + } + return
+ {pagesElement.map(p => p)} +
+} + +/** + * 获取分页按钮 + * @param {*} i + * @param {*} selected + */ +function getPageElement(i, selected, switchPage) { + return
switchPage(i)} className={`${selected ? 'font-bold text-white bg-blue-600 rounded' : 'hover:text-blue-600 hover:font-bold'} text-center cursor-pointer w-6 h-6 `}> + {i + 1} +
+} diff --git a/components/Mark.js b/components/Mark.js index 1defca32..ec2a7901 100644 --- a/components/Mark.js +++ b/components/Mark.js @@ -9,10 +9,7 @@ export default async function replaceSearchResult({ doms, search, target }) { } try { - const url = await loadExternalResource('https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js', 'js') - console.log('markjs 加载成功', url, window.Mark) - console.log('------', doms) - + await loadExternalResource('https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js', 'js') const Mark = window.Mark if (doms instanceof HTMLCollection) { for (const container of doms) { diff --git a/lib/global.js b/lib/global.js index 04b40cbe..0aba42d0 100644 --- a/lib/global.js +++ b/lib/global.js @@ -14,7 +14,9 @@ const GlobalContext = createContext() * @returns {JSX.Element} * @constructor */ -export function GlobalContextProvider({ children }) { +export function GlobalContextProvider(props) { + console.log('global', props) + const { children, siteInfo, categoryOptions, tagOptions } = props const router = useRouter() const [lang, updateLang] = useState(BLOG.LANG) // 默认语言 const [locale, updateLocale] = useState(generateLocaleDict(BLOG.LANG)) // 默认语言 @@ -75,7 +77,10 @@ export function GlobalContextProvider({ children }) { updateDarkMode, theme, setTheme, - switchTheme + switchTheme, + siteInfo, + categoryOptions, + tagOptions }}> {children} diff --git a/pages/_app.js b/pages/_app.js index a6a11399..57c4047a 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -17,6 +17,7 @@ import dynamic from 'next/dynamic' // 自定义样式css和js引入 import ExternalScript from '@/components/ExternalScript' +import CommonHead from '@/components/CommonHead' // 各种扩展插件 动画等 const ExternalPlugins = dynamic(() => import('@/components/ExternalPlugins')) @@ -25,9 +26,11 @@ const MyApp = ({ Component, pageProps }) => { useEffect(() => { AOS.init() }, []) + const { meta } = pageProps return ( - + + diff --git a/themes/example/index.js b/themes/example/index.js index d14bc570..8dffec78 100644 --- a/themes/example/index.js +++ b/themes/example/index.js @@ -2,7 +2,6 @@ import BLOG from '@/blog.config' import CONFIG from './config' -import CommonHead from '@/components/CommonHead' import { useEffect } from 'react' import { Header } from './components/Header' import { Nav } from './components/Nav' @@ -36,7 +35,7 @@ import { Style } from './style' * @constructor */ const LayoutBase = props => { - const { children, meta, slotTop } = props + const { children, slotTop } = props const { onLoading } = useGlobal() // 增加一个状态以触发 Transition 组件的动画 @@ -49,8 +48,6 @@ const LayoutBase = props => { return (
- {/* 网页SEO信息 */} -