import { useState, useImperativeHandle, useRef } from 'react' import algoliasearch from 'algoliasearch' import replaceSearchResult from '@/components/Mark' import Link from 'next/link' import { useGlobal } from '@/lib/global' import throttle from 'lodash/throttle' import { siteConfig } from '@/lib/config' /** * 结合 Algolia 实现的弹出式搜索框 * 打开方式 cRef.current.openSearch() * https://www.algolia.com/doc/api-reference/search-api-parameters/ */ 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) /** * 对外暴露方法 */ useImperativeHandle(cRef, () => { return { openSearch: () => { setIsModalOpen(true) } } }) const client = algoliasearch(siteConfig('ALGOLIA_APP_ID'), siteConfig('ALGOLIA_SEARCH_ONLY_APP_KEY')) const index = client.initIndex(siteConfig('ALGOLIA_INDEX')) /** * 搜索 * @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, { 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') 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 (!siteConfig('ALGOLIA_APP_ID')) { return <> } return (
{/* 模态框 */}
搜索
handleInputChange(e)} className="text-black dark:text-gray-200 bg-gray-50 dark:bg-gray-600 outline-blue-500 w-full px-4 my-2 py-1 mb-4 border rounded-md" /> {/* 标签组 */}
{totalHit > 0 && (
共搜索到 {totalHit} 条结果,用时 {useTime} 毫秒
)}
Algolia 提供搜索服务 {' '}
{/* 遮罩 */}
) } /** * 标签组 */ 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}
}