diff --git a/components/AlgoliaSearchModal.js b/components/AlgoliaSearchModal.js index 26ed7d88..6554e353 100644 --- a/components/AlgoliaSearchModal.js +++ b/components/AlgoliaSearchModal.js @@ -1,10 +1,11 @@ -import { useState, useImperativeHandle, useRef } from 'react' +import { useState, useImperativeHandle, useRef, useEffect } 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' +import { useHotkeys } from 'react-hotkeys-hook'; /** * 结合 Algolia 实现的弹出式搜索框 @@ -19,7 +20,62 @@ export default function AlgoliaSearchModal({ cRef }) { const [totalPage, setTotalPage] = useState(0) const [totalHit, setTotalHit] = useState(0) const [useTime, setUseTime] = useState(0) + const inputRef = useRef(null) + const [activeIndex, setActiveIndex] = useState(0) + useHotkeys('ctrl+k', (e) => { + e.preventDefault() + setIsModalOpen(true) + }) + // 方向键调整选中 + useHotkeys('down', (e) => { + e.preventDefault() + if (activeIndex < searchResults.length - 1) { + setActiveIndex(activeIndex + 1) + } + }, { enableOnFormTags: true }) + useHotkeys('up', (e) => { + e.preventDefault() + if (activeIndex > 0) { + setActiveIndex(activeIndex - 1) + } + }, { enableOnFormTags: true }) + // esc关闭 + useHotkeys('esc', (e) => { + e.preventDefault() + setIsModalOpen(false) + }, { enableOnFormTags: true }) + // 跳转Search结果 + const onJumpSearchResult = () => { + if (searchResults.length > 0) { + window.location.href = `${siteConfig('SUB_PATH', '')}/${searchResults[activeIndex].slug}` + } + } + // enter跳转 + useHotkeys('enter', (e) => { + if (searchResults.length > 0) { + onJumpSearchResult(index) + } + }, { enableOnFormTags: true }) + const resetSearch = () => { + setActiveIndex(0) + setKeyword('') + setSearchResults([]) + setUseTime(0) + setTotalPage(0) + setTotalHit(0) + if (inputRef.current) inputRef.current.value = '' + } + + useEffect(() => { + if (isModalOpen) { + setTimeout(() => { + inputRef.current?.focus() + }, 100) + } else { + resetSearch() + } + }, [isModalOpen]) /** * 对外暴露方法 */ @@ -45,6 +101,7 @@ export default function AlgoliaSearchModal({ cRef }) { setUseTime(0) setTotalPage(0) setTotalHit(0) + setActiveIndex(0) if (!query || query === '') { return } @@ -56,7 +113,6 @@ export default function AlgoliaSearchModal({ cRef }) { setTotalPage(nbPages) setTotalHit(nbHits) setSearchResults(hits) - const doms = document.getElementById('search-wrapper').getElementsByClassName('replace') setTimeout(() => { @@ -65,7 +121,7 @@ export default function AlgoliaSearchModal({ cRef }) { search: query, target: { element: 'span', - className: 'text-blue-600 border-b border-dashed' + className: 'font-bold border-b border-dashed' } }) }, 200) // 延时高亮 @@ -75,8 +131,8 @@ export default function AlgoliaSearchModal({ cRef }) { } // 定义节流函数,确保在用户停止输入一段时间后才会调用处理搜索的方法 - const throttledHandleInputChange = useRef(throttle((query) => { - handleSearch(query, 0); + const throttledHandleInputChange = useRef(throttle((query, page = 0) => { + handleSearch(query, page); }, 1000)); // 用于存储搜索延迟的计时器 @@ -115,19 +171,16 @@ export default function AlgoliaSearchModal({ cRef }) { if (!siteConfig('ALGOLIA_APP_ID')) { return <>> } - return (
无法找到相关结果 + "{keyword}"
++ 共搜索到 {totalHit} 条结果,用时 {useTime} 毫秒 +
+ )} +