update pay ui

This commit is contained in:
2025-12-03 12:52:27 +08:00
parent 01d0a06f6a
commit 5042d1ee46
3 changed files with 98 additions and 6 deletions

View File

@@ -1,9 +1,12 @@
// src/views/Community/components/DynamicNewsDetail/RelatedStocksSection.js
// 相关股票列表区组件(纯内容,不含标题)
import React from 'react';
import React, { useState, useEffect, useMemo } from 'react';
import { VStack } from '@chakra-ui/react';
import dayjs from 'dayjs';
import StockListItem from './StockListItem';
import { fetchBatchKlineData, klineDataCache, getCacheKey } from '../StockDetailPanel/utils/klineDataCache';
import { logger } from '../../../../utils/logger';
/**
* 相关股票列表区组件(纯内容部分)
@@ -22,6 +25,85 @@ const RelatedStocksSection = ({
watchlistSet = new Set(),
onWatchlistToggle
}) => {
// K线数据状态{ [stockCode]: data[] }
const [klineDataMap, setKlineDataMap] = useState({});
const [klineLoading, setKlineLoading] = useState(false);
// 稳定的事件时间
const stableEventTime = useMemo(() => {
return eventTime ? dayjs(eventTime).format('YYYY-MM-DD HH:mm') : '';
}, [eventTime]);
// 稳定的股票列表 key
const stocksKey = useMemo(() => {
if (!stocks || stocks.length === 0) return '';
return stocks.map(s => s.stock_code).sort().join(',');
}, [stocks]);
// 计算是否应该显示 loading
const shouldShowLoading = useMemo(() => {
if (!stocks || stocks.length === 0) return false;
const currentDataKeys = Object.keys(klineDataMap).sort().join(',');
if (stocksKey !== currentDataKeys) {
return true;
}
return klineLoading;
}, [stocks, stocksKey, klineDataMap, klineLoading]);
// 批量加载K线数据
useEffect(() => {
if (!stocks || stocks.length === 0) {
setKlineDataMap({});
setKlineLoading(false);
return;
}
// 立即设置 loading 状态
setKlineLoading(true);
const stockCodes = stocks.map(s => s.stock_code);
// 先检查缓存
const cachedData = {};
const uncachedCodes = [];
stockCodes.forEach(code => {
const cacheKey = getCacheKey(code, stableEventTime, 'timeline');
const cached = klineDataCache.get(cacheKey);
if (cached !== undefined) {
cachedData[code] = cached;
} else {
uncachedCodes.push(code);
}
});
// 如果全部缓存命中,直接使用
if (uncachedCodes.length === 0) {
setKlineDataMap(cachedData);
setKlineLoading(false);
logger.debug('RelatedStocksSection', 'K线数据全部来自缓存', { stockCount: stockCodes.length });
return;
}
logger.debug('RelatedStocksSection', '批量加载K线数据', {
totalCount: stockCodes.length,
cachedCount: Object.keys(cachedData).length,
uncachedCount: uncachedCodes.length,
eventTime: stableEventTime
});
// 批量请求
fetchBatchKlineData(stockCodes, stableEventTime, 'timeline')
.then((batchData) => {
setKlineDataMap({ ...cachedData, ...batchData });
setKlineLoading(false);
})
.catch((error) => {
logger.error('RelatedStocksSection', '批量加载K线数据失败', error);
setKlineDataMap(cachedData);
setKlineLoading(false);
});
}, [stocksKey, stableEventTime]);
// 如果没有股票数据,不渲染
if (!stocks || stocks.length === 0) {
return null;
@@ -37,6 +119,8 @@ const RelatedStocksSection = ({
eventTime={eventTime}
isInWatchlist={watchlistSet.has(stock.stock_code)}
onWatchlistToggle={onWatchlistToggle}
klineData={klineDataMap[stock.stock_code]}
klineLoading={shouldShowLoading && !klineDataMap[stock.stock_code]}
/>
))}
</VStack>