/** * Company 页面顶部搜索栏组件 - FUI 科幻风格 * * 设计特点: * - 左侧固定标题 + 副标题 * - 右侧简洁搜索框 * - 深色背景 + 金色强调色 */ import React, { memo, useMemo, useCallback, useState } from 'react'; import { Box, Flex, HStack, VStack, Text, } from '@chakra-ui/react'; import { AutoComplete, Input, Spin } from 'antd'; import { SearchOutlined } from '@ant-design/icons'; import { useStockSearch } from '@hooks/useStockSearch'; import { THEME } from '../../config'; import { FUI_COLORS, FUI_GLOW, FUI_ANIMATION, FUI_GLASS } from '../../theme/fui'; import type { CompanyHeaderProps, StockSearchResult } from '../../types'; /** * 页面标题组件 */ const PageTitle = memo(() => ( 个股详情 查看股票实时行情、财务数据和盈利预测 )); PageTitle.displayName = 'PageTitle'; /** * 搜索框组件(状态自管理,减少父组件重渲染) */ const SearchBox = memo<{ stockCode: string; onStockChange: (value: string) => void; }>(({ stockCode, onStockChange, }) => { // 输入状态 - 默认为空,显示 placeholder const [inputCode, setInputCode] = useState(''); // 股票搜索 Hook const searchHook = useStockSearch({ limit: 10, debounceMs: 300, onSearch: () => {}, // 空回调,追踪在父组件处理 }) as { searchResults: StockSearchResult[]; isSearching: boolean; handleSearch: (query: string) => void; clearSearch: () => void; }; const { searchResults, isSearching, handleSearch: doSearch, clearSearch } = searchHook; // 转换为 AutoComplete options const stockOptions = useMemo(() => { return searchResults.map((stock: StockSearchResult) => ({ value: stock.stock_code, label: ( {stock.stock_code} {stock.stock_name} {stock.pinyin_abbr && ( {stock.pinyin_abbr.toUpperCase()} )} ), })); }, [searchResults]); // 选中股票 const handleSelect = useCallback((value: string) => { clearSearch(); setInputCode(value); if (value !== stockCode) { onStockChange(value); } }, [clearSearch, stockCode, onStockChange]); // 键盘事件 - 回车搜索 const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === 'Enter' && inputCode && inputCode !== stockCode) { onStockChange(inputCode); } }, [inputCode, stockCode, onStockChange]); return ( : null} > } onKeyDown={handleKeyDown} style={{ backgroundColor: 'transparent', borderColor: FUI_COLORS.gold[400], borderRadius: 6, height: 44, color: FUI_COLORS.gold[400], }} /> ); }); SearchBox.displayName = 'SearchBox'; /** * Company 页面顶部组件 */ const CompanyHeader: React.FC = memo(({ stockCode, onStockChange, }) => { return ( {/* 左侧:页面标题 */} {/* 右侧:搜索框 */} ); }); CompanyHeader.displayName = 'CompanyHeader'; export default CompanyHeader;