update pay ui

This commit is contained in:
2025-12-03 12:47:32 +08:00
parent dd975a65b2
commit 01d0a06f6a
2 changed files with 34 additions and 13 deletions

View File

@@ -76,6 +76,13 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve
return; return;
} }
// 如果外部正在加载显示loading状态不发起单独请求
// 父组件StockTable会通过 preloadedData 传入数据
if (externalLoading) {
setLoading(true);
return;
}
// 如果已经请求过数据,不再重复请求 // 如果已经请求过数据,不再重复请求
if (dataFetchedRef.current) { if (dataFetchedRef.current) {
return; return;
@@ -86,12 +93,6 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve
return; return;
} }
// 如果外部正在加载,等待外部加载完成
if (externalLoading) {
setLoading(true);
return;
}
// 检查批量请求的函数 // 检查批量请求的函数
const checkBatchAndLoad = () => { const checkBatchAndLoad = () => {
// 再次检查缓存(批量请求可能已完成) // 再次检查缓存(批量请求可能已完成)
@@ -135,7 +136,8 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve
return; return;
} }
// 延迟一小段时间再检查(等待批量请求启动) // 延迟检查(等待批量请求启动)
// 注意:如果父组件正在批量加载,会传入 externalLoading=true不会执行到这里
setLoading(true); setLoading(true);
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
if (!mountedRef.current || dataFetchedRef.current) return; if (!mountedRef.current || dataFetchedRef.current) return;
@@ -145,7 +147,7 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve
return; return;
} }
// 仍然没有批量请求,发起单独请求(备用方案) // 仍然没有批量请求,发起单独请求(备用方案 - 用于非批量加载场景
dataFetchedRef.current = true; dataFetchedRef.current = true;
fetchKlineData(stockCode, stableEventTime) fetchKlineData(stockCode, stableEventTime)
@@ -163,7 +165,7 @@ const MiniTimelineChart = React.memo(function MiniTimelineChart({ stockCode, eve
loadedRef.current = true; loadedRef.current = true;
} }
}); });
}, 100); // 延迟 100ms 等待批量请求 }, 200); // 延迟 200ms 等待批量请求(增加等待时间)
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
}, [stockCode, stableEventTime, loadData, preloadedData, externalLoading]); // 添加 preloadedData 和 externalLoading 依赖 }, [stockCode, stableEventTime, loadData, preloadedData, externalLoading]); // 添加 preloadedData 和 externalLoading 依赖

View File

@@ -32,6 +32,8 @@ const StockTable = ({
// K线数据状态{ [stockCode]: data[] } // K线数据状态{ [stockCode]: data[] }
const [klineDataMap, setKlineDataMap] = useState({}); const [klineDataMap, setKlineDataMap] = useState({});
const [klineLoading, setKlineLoading] = useState(false); const [klineLoading, setKlineLoading] = useState(false);
// 用于追踪当前正在加载的 stocksKey解决时序问题
const [loadingStocksKey, setLoadingStocksKey] = useState('');
// 稳定的事件时间,避免重复渲染 // 稳定的事件时间,避免重复渲染
const stableEventTime = useMemo(() => { const stableEventTime = useMemo(() => {
@@ -44,12 +46,30 @@ const StockTable = ({
return stocks.map(s => s.stock_code).sort().join(','); return stocks.map(s => s.stock_code).sort().join(',');
}, [stocks]); }, [stocks]);
// 计算是否应该显示 loading当前 stocksKey 和 loadingStocksKey 不匹配,或者正在加载
// 这样可以在 stocks 变化时立即显示 loading不需要等 useEffect
const shouldShowLoading = useMemo(() => {
if (stocks.length === 0) return false;
// 如果 stocksKey 变化了但 klineDataMap 还没更新,说明需要加载
const currentDataKeys = Object.keys(klineDataMap).sort().join(',');
if (stocksKey !== currentDataKeys && stocksKey !== loadingStocksKey) {
return true;
}
return klineLoading;
}, [stocks.length, stocksKey, klineDataMap, loadingStocksKey, klineLoading]);
useEffect(() => { useEffect(() => {
if (stocks.length === 0) { if (stocks.length === 0) {
setKlineDataMap({}); setKlineDataMap({});
setKlineLoading(false);
setLoadingStocksKey('');
return; return;
} }
// 立即设置 loading 状态和正在加载的 key
setKlineLoading(true);
setLoadingStocksKey(stocksKey);
const stockCodes = stocks.map(s => s.stock_code); const stockCodes = stocks.map(s => s.stock_code);
// 先检查缓存,只请求未缓存的 // 先检查缓存,只请求未缓存的
@@ -68,6 +88,7 @@ const StockTable = ({
// 如果全部缓存命中,直接使用 // 如果全部缓存命中,直接使用
if (uncachedCodes.length === 0) { if (uncachedCodes.length === 0) {
setKlineDataMap(cachedData); setKlineDataMap(cachedData);
setKlineLoading(false);
logger.debug('StockTable', 'K线数据全部来自缓存', { stockCount: stockCodes.length }); logger.debug('StockTable', 'K线数据全部来自缓存', { stockCount: stockCodes.length });
return; return;
} }
@@ -79,8 +100,6 @@ const StockTable = ({
eventTime: stableEventTime eventTime: stableEventTime
}); });
setKlineLoading(true);
// 批量请求未缓存的数据 // 批量请求未缓存的数据
fetchBatchKlineData(stockCodes, stableEventTime, 'timeline') fetchBatchKlineData(stockCodes, stableEventTime, 'timeline')
.then((batchData) => { .then((batchData) => {
@@ -220,7 +239,7 @@ const StockTable = ({
stockCode={record.stock_code} stockCode={record.stock_code}
eventTime={stableEventTime} eventTime={stableEventTime}
preloadedData={klineDataMap[record.stock_code]} preloadedData={klineDataMap[record.stock_code]}
loading={klineLoading && !klineDataMap[record.stock_code]} loading={shouldShowLoading && !klineDataMap[record.stock_code]}
/> />
), ),
}, },
@@ -271,7 +290,7 @@ const StockTable = ({
); );
}, },
}, },
], [quotes, stableEventTime, expandedRows, toggleRowExpand, watchlistSet, onWatchlistToggle, klineDataMap, klineLoading]); ], [quotes, stableEventTime, expandedRows, toggleRowExpand, watchlistSet, onWatchlistToggle, klineDataMap, shouldShowLoading]);
return ( return (
<div style={{ position: 'relative' }}> <div style={{ position: 'relative' }}>