Merge branch 'feature_bugfix/251201_vf_h5_ui' into feature_bugfix/251201_py_h5_ui
* feature_bugfix/251201_vf_h5_ui: feat: Company 页面搜索框添加股票模糊搜索功能 fix: 个股中心bug修复
This commit is contained in:
@@ -544,11 +544,19 @@ const InvestmentCalendar = () => {
|
|||||||
render: (concepts) => (
|
render: (concepts) => (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{concepts && concepts.length > 0 ? (
|
{concepts && concepts.length > 0 ? (
|
||||||
concepts.slice(0, 3).map((concept, index) => (
|
concepts.slice(0, 3).map((concept, index) => {
|
||||||
|
// 兼容多种数据格式:字符串、数组、对象
|
||||||
|
const conceptName = typeof concept === 'string'
|
||||||
|
? concept
|
||||||
|
: Array.isArray(concept)
|
||||||
|
? concept[0]
|
||||||
|
: concept?.concept || concept?.name || '';
|
||||||
|
return (
|
||||||
<Tag key={index} icon={<TagsOutlined />}>
|
<Tag key={index} icon={<TagsOutlined />}>
|
||||||
{Array.isArray(concept) ? concept[0] : concept}
|
{conceptName}
|
||||||
</Tag>
|
</Tag>
|
||||||
))
|
);
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<Text type="secondary">无</Text>
|
<Text type="secondary">无</Text>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2426,7 +2426,7 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => {
|
|||||||
<>
|
<>
|
||||||
{event.keywords.slice(0, 4).map((keyword, kidx) => (
|
{event.keywords.slice(0, 4).map((keyword, kidx) => (
|
||||||
<Tag key={kidx} size="sm" colorScheme="cyan" variant="subtle">
|
<Tag key={kidx} size="sm" colorScheme="cyan" variant="subtle">
|
||||||
{keyword}
|
{typeof keyword === 'string' ? keyword : keyword.concept}
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
import { loadAllStocks } from '@store/slices/stockSlice';
|
||||||
|
import { AutoComplete } from 'antd';
|
||||||
|
import { stockService } from '@services/stockService';
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Heading,
|
Heading,
|
||||||
@@ -12,10 +16,7 @@ import {
|
|||||||
TabPanel,
|
TabPanel,
|
||||||
HStack,
|
HStack,
|
||||||
VStack,
|
VStack,
|
||||||
Input,
|
|
||||||
Button,
|
Button,
|
||||||
InputGroup,
|
|
||||||
InputLeftElement,
|
|
||||||
Text,
|
Text,
|
||||||
Badge,
|
Badge,
|
||||||
Divider,
|
Divider,
|
||||||
@@ -41,10 +42,22 @@ const CompanyIndex = () => {
|
|||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const [stockCode, setStockCode] = useState(searchParams.get('scode') || '000001');
|
const [stockCode, setStockCode] = useState(searchParams.get('scode') || '000001');
|
||||||
const [inputCode, setInputCode] = useState(stockCode);
|
const [inputCode, setInputCode] = useState(stockCode);
|
||||||
|
const [stockOptions, setStockOptions] = useState([]);
|
||||||
const { colorMode, toggleColorMode } = useColorMode();
|
const { colorMode, toggleColorMode } = useColorMode();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
|
|
||||||
|
// 从 Redux 获取股票列表数据
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const allStocks = useSelector((state) => state.stock.allStocks);
|
||||||
|
|
||||||
|
// 确保股票数据已加载
|
||||||
|
useEffect(() => {
|
||||||
|
if (!allStocks || allStocks.length === 0) {
|
||||||
|
dispatch(loadAllStocks());
|
||||||
|
}
|
||||||
|
}, [dispatch, allStocks]);
|
||||||
|
|
||||||
// 🎯 PostHog 事件追踪
|
// 🎯 PostHog 事件追踪
|
||||||
const {
|
const {
|
||||||
trackStockSearched,
|
trackStockSearched,
|
||||||
@@ -113,6 +126,31 @@ const CompanyIndex = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 模糊搜索股票(由 onSearch 触发)
|
||||||
|
const handleStockSearch = (value) => {
|
||||||
|
if (!value || !allStocks || allStocks.length === 0) {
|
||||||
|
setStockOptions([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const results = stockService.fuzzySearch(value, allStocks, 10);
|
||||||
|
const options = results.map((stock) => ({
|
||||||
|
value: stock.code,
|
||||||
|
label: `${stock.code} ${stock.name}`,
|
||||||
|
}));
|
||||||
|
setStockOptions(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选中股票
|
||||||
|
const handleStockSelect = (value) => {
|
||||||
|
setInputCode(value);
|
||||||
|
setStockOptions([]);
|
||||||
|
if (value !== stockCode) {
|
||||||
|
trackStockSearched(value, stockCode);
|
||||||
|
setStockCode(value);
|
||||||
|
setSearchParams({ scode: value });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleWatchlistToggle = async () => {
|
const handleWatchlistToggle = async () => {
|
||||||
if (!stockCode) {
|
if (!stockCode) {
|
||||||
logger.warn('CompanyIndex', 'handleWatchlistToggle', '无效的股票代码', { stockCode });
|
logger.warn('CompanyIndex', 'handleWatchlistToggle', '无效的股票代码', { stockCode });
|
||||||
@@ -190,22 +228,21 @@ const CompanyIndex = () => {
|
|||||||
</VStack>
|
</VStack>
|
||||||
|
|
||||||
<HStack spacing={3}>
|
<HStack spacing={3}>
|
||||||
<InputGroup size="lg" maxW="300px">
|
<AutoComplete
|
||||||
<InputLeftElement pointerEvents="none">
|
|
||||||
<SearchIcon color="gray.400" />
|
|
||||||
</InputLeftElement>
|
|
||||||
<Input
|
|
||||||
placeholder="输入股票代码"
|
|
||||||
value={inputCode}
|
value={inputCode}
|
||||||
onChange={(e) => setInputCode(e.target.value)}
|
options={stockOptions}
|
||||||
onKeyPress={handleKeyPress}
|
onSearch={handleStockSearch}
|
||||||
borderRadius="md"
|
onSelect={handleStockSelect}
|
||||||
_focus={{
|
onChange={(value) => setInputCode(value)}
|
||||||
borderColor: 'blue.500',
|
placeholder="输入股票代码或名称"
|
||||||
boxShadow: '0 0 0 1px #3182ce'
|
style={{ width: 260 }}
|
||||||
|
size="large"
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
handleSearch();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
|
||||||
<Button
|
<Button
|
||||||
colorScheme="blue"
|
colorScheme="blue"
|
||||||
size="lg"
|
size="lg"
|
||||||
|
|||||||
Reference in New Issue
Block a user