import React, { useCallback, useRef, useEffect } from 'react' import { useSearchStore } from '../../stores/searchStore' import { useTabStore } from '../../stores/tabStore' import { findMatches } from '../../lib/searchEngine' import { ChevronUp, ChevronDown, X } from '../Icons' export function SearchBar() { const searchInputRef = useRef(null) const isVisible = useSearchStore(s => s.isVisible) const showReplace = useSearchStore(s => s.showReplace) const searchText = useSearchStore(s => s.searchText) const replaceText = useSearchStore(s => s.replaceText) const matches = useSearchStore(s => s.matches) const currentIndex = useSearchStore(s => s.currentIndex) const options = useSearchStore(s => s.options) const setSearchText = useSearchStore(s => s.setSearchText) const setReplaceText = useSearchStore(s => s.setReplaceText) const setShowReplace = useSearchStore(s => s.setShowReplace) const setMatches = useSearchStore(s => s.setMatches) const findNext = useSearchStore(s => s.findNext) const findPrev = useSearchStore(s => s.findPrev) const toggleCaseSensitive = useSearchStore(s => s.toggleCaseSensitive) const toggleRegex = useSearchStore(s => s.toggleRegex) const close = useSearchStore(s => s.close) const getActiveTab = useTabStore(s => s.getActiveTab) const doSearch = useCallback((text: string) => { const tab = getActiveTab() if (!tab || !text) { setMatches([]) return } const found = findMatches(tab.content, text, options) setMatches(found) }, [getActiveTab, options, setMatches]) const handleSearchChange = useCallback((e: React.ChangeEvent) => { const text = e.target.value setSearchText(text) // Editor 会监听 searchText 变化并执行搜索和高亮 }, [setSearchText]) const handleReplaceCurrent = useCallback(() => { const tab = getActiveTab() if (!tab || matches.length === 0 || currentIndex < 0) return const m = matches[currentIndex] const newContent = tab.content.substring(0, m.start) + replaceText + tab.content.substring(m.end) useTabStore.getState().updateTabContent(tab.id, newContent) doSearch(searchText) }, [getActiveTab, matches, currentIndex, replaceText, searchText, doSearch]) // B-02: 全部替换(从后向前逐个替换) const handleReplaceAll = useCallback(() => { const tab = getActiveTab() if (!tab || matches.length === 0) return let result = tab.content for (let i = matches.length - 1; i >= 0; i--) { const m = matches[i] result = result.substring(0, m.start) + replaceText + result.substring(m.end) } useTabStore.getState().updateTabContent(tab.id, result) doSearch(searchText) }, [getActiveTab, matches, replaceText, searchText, doSearch]) useEffect(() => { if (isVisible && searchInputRef.current) { searchInputRef.current.focus() } }, [isVisible]) if (!isVisible) return null return ( ) }