diff --git a/src/views/Company/components/CompanyHeader/SearchBar.js b/src/views/Company/components/CompanyHeader/SearchBar.js index 677ebe00..f6989923 100644 --- a/src/views/Company/components/CompanyHeader/SearchBar.js +++ b/src/views/Company/components/CompanyHeader/SearchBar.js @@ -13,6 +13,7 @@ import { VStack, } from '@chakra-ui/react'; import { SearchIcon } from '@chakra-ui/icons'; +import { useStockSearch } from '../../hooks/useStockSearch'; /** * 股票搜索栏组件(带模糊搜索下拉) @@ -31,27 +32,18 @@ const SearchBar = ({ }) => { // 下拉状态 const [showDropdown, setShowDropdown] = useState(false); - const [filteredStocks, setFilteredStocks] = useState([]); const containerRef = useRef(null); // 从 Redux 获取全部股票列表 const allStocks = useSelector(state => state.stock.allStocks); - // 模糊搜索过滤 + // 使用共享的搜索 Hook + const filteredStocks = useStockSearch(allStocks, inputCode, { limit: 10 }); + + // 根据搜索结果更新下拉显示状态 useEffect(() => { - if (inputCode && inputCode.trim()) { - const searchTerm = inputCode.trim().toLowerCase(); - const filtered = allStocks.filter(stock => - stock.code.toLowerCase().includes(searchTerm) || - stock.name.includes(inputCode.trim()) - ).slice(0, 10); // 限制显示10条 - setFilteredStocks(filtered); - setShowDropdown(filtered.length > 0); - } else { - setFilteredStocks([]); - setShowDropdown(false); - } - }, [inputCode, allStocks]); + setShowDropdown(filteredStocks.length > 0 && !!inputCode?.trim()); + }, [filteredStocks, inputCode]); // 点击外部关闭下拉 useEffect(() => { diff --git a/src/views/Company/components/StockQuoteCard/components/CompareStockInput.tsx b/src/views/Company/components/StockQuoteCard/components/CompareStockInput.tsx index 94bf667e..92d9885e 100644 --- a/src/views/Company/components/StockQuoteCard/components/CompareStockInput.tsx +++ b/src/views/Company/components/StockQuoteCard/components/CompareStockInput.tsx @@ -18,6 +18,7 @@ import { } from '@chakra-ui/react'; import { SearchIcon } from '@chakra-ui/icons'; import { BarChart2 } from 'lucide-react'; +import { useStockSearch, type Stock } from '../../../hooks/useStockSearch'; interface CompareStockInputProps { onCompare: (stockCode: string) => void; @@ -25,11 +26,6 @@ interface CompareStockInputProps { currentStockCode?: string; } -interface Stock { - code: string; - name: string; -} - interface RootState { stock: { allStocks: Stock[]; @@ -43,7 +39,6 @@ const CompareStockInput: React.FC = ({ }) => { const [inputValue, setInputValue] = useState(''); const [showDropdown, setShowDropdown] = useState(false); - const [filteredStocks, setFilteredStocks] = useState([]); const [selectedStock, setSelectedStock] = useState(null); const containerRef = useRef(null); @@ -55,25 +50,16 @@ const CompareStockInput: React.FC = ({ const goldColor = '#F4D03F'; const bgColor = '#1A202C'; - // 模糊搜索过滤 + // 使用共享的搜索 Hook(排除当前股票) + const filteredStocks = useStockSearch(allStocks, inputValue, { + excludeCode: currentStockCode, + limit: 8, + }); + + // 根据搜索结果更新下拉显示状态 useEffect(() => { - if (inputValue && inputValue.trim()) { - const searchTerm = inputValue.trim().toLowerCase(); - const filtered = allStocks - .filter( - (stock) => - stock.code !== currentStockCode && // 排除当前股票 - (stock.code.toLowerCase().includes(searchTerm) || - stock.name.includes(inputValue.trim())) - ) - .slice(0, 8); // 限制显示8条 - setFilteredStocks(filtered); - setShowDropdown(filtered.length > 0); - } else { - setFilteredStocks([]); - setShowDropdown(false); - } - }, [inputValue, allStocks, currentStockCode]); + setShowDropdown(filteredStocks.length > 0 && !!inputValue?.trim()); + }, [filteredStocks, inputValue]); // 点击外部关闭下拉 useEffect(() => { diff --git a/src/views/Company/hooks/useStockSearch.ts b/src/views/Company/hooks/useStockSearch.ts new file mode 100644 index 00000000..cd7b7ff2 --- /dev/null +++ b/src/views/Company/hooks/useStockSearch.ts @@ -0,0 +1,59 @@ +/** + * useStockSearch - 股票模糊搜索 Hook + * + * 提取自 SearchBar.js 和 CompareStockInput.tsx 的共享搜索逻辑 + * 支持按代码或名称搜索,可选排除指定股票 + */ + +import { useMemo } from 'react'; + +export interface Stock { + code: string; + name: string; +} + +interface UseStockSearchOptions { + excludeCode?: string; + limit?: number; +} + +/** + * 股票模糊搜索 Hook + * + * @param allStocks - 全部股票列表 + * @param searchTerm - 搜索关键词 + * @param options - 可选配置 + * @param options.excludeCode - 排除的股票代码(用于对比场景) + * @param options.limit - 返回结果数量限制,默认 10 + * @returns 过滤后的股票列表 + */ +export const useStockSearch = ( + allStocks: Stock[], + searchTerm: string, + options: UseStockSearchOptions = {} +): Stock[] => { + const { excludeCode, limit = 10 } = options; + + return useMemo(() => { + const trimmed = searchTerm?.trim(); + if (!trimmed) return []; + + const term = trimmed.toLowerCase(); + + return allStocks + .filter((stock) => { + // 排除指定股票 + if (excludeCode && stock.code === excludeCode) { + return false; + } + // 按代码或名称匹配 + return ( + stock.code.toLowerCase().includes(term) || + stock.name.includes(trimmed) + ); + }) + .slice(0, limit); + }, [allStocks, searchTerm, excludeCode, limit]); +}; + +export default useStockSearch;