fix: 适配 watchlist 新数据结构
- CompactSearchBox: 改用 Redux 获取股票列表
- useWatchlist: 适配 { stock_code, stock_name }[] 结构
- Center: 修复 watchlist key + H5 评论 Badge 溢出
This commit is contained in:
@@ -14,6 +14,7 @@ import dayjs from 'dayjs';
|
|||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { fetchIndustryData, selectIndustryData, selectIndustryLoading } from '@store/slices/industrySlice';
|
import { fetchIndustryData, selectIndustryData, selectIndustryLoading } from '@store/slices/industrySlice';
|
||||||
|
import { loadAllStocks } from '@store/slices/stockSlice';
|
||||||
import { stockService } from '@services/stockService';
|
import { stockService } from '@services/stockService';
|
||||||
import { logger } from '@utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
import TradingTimeFilter from './TradingTimeFilter';
|
import TradingTimeFilter from './TradingTimeFilter';
|
||||||
@@ -61,6 +62,7 @@ const CompactSearchBox = ({
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const industryData = useSelector(selectIndustryData);
|
const industryData = useSelector(selectIndustryData);
|
||||||
const industryLoading = useSelector(selectIndustryLoading);
|
const industryLoading = useSelector(selectIndustryLoading);
|
||||||
|
const reduxAllStocks = useSelector((state) => state.stock.allStocks);
|
||||||
|
|
||||||
// 防抖搜索
|
// 防抖搜索
|
||||||
const debouncedSearchRef = useRef(null);
|
const debouncedSearchRef = useRef(null);
|
||||||
@@ -82,16 +84,19 @@ const CompactSearchBox = ({
|
|||||||
};
|
};
|
||||||
}, [triggerSearch]);
|
}, [triggerSearch]);
|
||||||
|
|
||||||
// 加载股票数据
|
// 加载股票数据(从 Redux 获取)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadStocks = async () => {
|
if (!reduxAllStocks || reduxAllStocks.length === 0) {
|
||||||
const response = await stockService.getAllStocks();
|
dispatch(loadAllStocks());
|
||||||
if (response.success && response.data) {
|
|
||||||
setAllStocks(response.data);
|
|
||||||
}
|
}
|
||||||
};
|
}, [dispatch, reduxAllStocks]);
|
||||||
loadStocks();
|
|
||||||
}, []);
|
// 同步 Redux 数据到本地状态
|
||||||
|
useEffect(() => {
|
||||||
|
if (reduxAllStocks && reduxAllStocks.length > 0) {
|
||||||
|
setAllStocks(reduxAllStocks);
|
||||||
|
}
|
||||||
|
}, [reduxAllStocks]);
|
||||||
|
|
||||||
// 预加载行业数据(解决第一次点击无数据问题)
|
// 预加载行业数据(解决第一次点击无数据问题)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// src/views/Community/components/StockDetailPanel/hooks/useWatchlist.js
|
// src/views/Community/components/StockDetailPanel/hooks/useWatchlist.js
|
||||||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||||
import { useEffect, useCallback, useMemo } from 'react';
|
import { useEffect, useCallback, useMemo } from 'react';
|
||||||
import { loadWatchlist, toggleWatchlist as toggleWatchlistAction } from '../../../../../store/slices/stockSlice';
|
import { loadWatchlist, toggleWatchlist as toggleWatchlistAction } from '@store/slices/stockSlice';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { logger } from '../../../../../utils/logger';
|
import { logger } from '@utils/logger';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标准化股票代码为6位格式
|
* 标准化股票代码为6位格式
|
||||||
@@ -41,8 +41,9 @@ export const useWatchlist = (shouldLoad = true) => {
|
|||||||
const loading = useSelector(state => state.stock.loading.watchlist);
|
const loading = useSelector(state => state.stock.loading.watchlist);
|
||||||
|
|
||||||
// 转换为 Set 方便快速查询(标准化为6位代码)
|
// 转换为 Set 方便快速查询(标准化为6位代码)
|
||||||
|
// 注意: watchlistArray 现在是 { stock_code, stock_name }[] 格式
|
||||||
const watchlistSet = useMemo(() => {
|
const watchlistSet = useMemo(() => {
|
||||||
return new Set(watchlistArray.map(normalizeStockCode));
|
return new Set(watchlistArray.map(item => normalizeStockCode(item.stock_code)));
|
||||||
}, [watchlistArray]);
|
}, [watchlistArray]);
|
||||||
|
|
||||||
// 初始化时加载自选股列表(只在 shouldLoad 为 true 时)
|
// 初始化时加载自选股列表(只在 shouldLoad 为 true 时)
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ export default function CenterDashboard() {
|
|||||||
<VStack align="stretch" spacing={2}>
|
<VStack align="stretch" spacing={2}>
|
||||||
{watchlist.slice(0, 10).map((stock) => (
|
{watchlist.slice(0, 10).map((stock) => (
|
||||||
<LinkBox
|
<LinkBox
|
||||||
key={stock.id}
|
key={stock.stock_code}
|
||||||
p={3}
|
p={3}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
_hover={{ bg: hoverBg }}
|
_hover={{ bg: hoverBg }}
|
||||||
@@ -568,15 +568,22 @@ export default function CenterDashboard() {
|
|||||||
<Text fontSize="sm" noOfLines={3}>
|
<Text fontSize="sm" noOfLines={3}>
|
||||||
{comment.content}
|
{comment.content}
|
||||||
</Text>
|
</Text>
|
||||||
<HStack justify="space-between" fontSize="xs" color={secondaryText}>
|
<HStack justify="space-between" fontSize="xs" color={secondaryText} spacing={2}>
|
||||||
<HStack>
|
<HStack flexShrink={0}>
|
||||||
<Icon as={FiClock} />
|
<Icon as={FiClock} />
|
||||||
<Text>{formatDate(comment.created_at)}</Text>
|
<Text>{formatDate(comment.created_at)}</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
{comment.event_title && (
|
{comment.event_title && (
|
||||||
<Tooltip label={comment.event_title}>
|
<Tooltip label={comment.event_title}>
|
||||||
<Badge variant="subtle" fontSize="xs">
|
<Badge
|
||||||
{comment.event_title.slice(0, 20)}...
|
variant="subtle"
|
||||||
|
fontSize="xs"
|
||||||
|
maxW={{ base: '120px', md: '180px' }}
|
||||||
|
overflow="hidden"
|
||||||
|
textOverflow="ellipsis"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
>
|
||||||
|
{comment.event_title}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user