fix: 修改相关概念组件以匹配真实API数据结构
修改内容: - SimpleConceptCard.js: 改用 concept.concept 和 concept.score 字段 - DetailedConceptCard.js: 改用 concept.concept、concept.score 和 concept.price_info.avg_change_pct - RelatedConceptsSection/index.js: 导航时使用 concept.concept 字段 - events.js mock数据: 更新keywords生成函数,使用concept/score/price_info结构 数据结构变更: - name → concept (概念名称) - relevance (0-100) → score (0-1) - avg_change_pct → price_info.avg_change_pct (嵌套结构) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -696,17 +696,24 @@ function generateKeywords(industry, seed) {
|
|||||||
return selectedStocks;
|
return selectedStocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将字符串数组转换为对象数组,包含完整字段
|
// 将字符串数组转换为对象数组,匹配真实API数据结构
|
||||||
return keywordNames.map((name, index) => ({
|
return keywordNames.map((name, index) => {
|
||||||
name: name,
|
const score = (70 + Math.floor((seed * 7 + index * 11) % 30)) / 100; // 0.70-0.99的分数
|
||||||
|
const avgChangePct = (Math.random() * 15 - 5).toFixed(2); // -5% ~ +10% 的涨跌幅
|
||||||
|
|
||||||
|
return {
|
||||||
|
concept: name, // 使用 concept 字段而不是 name
|
||||||
stock_count: 10 + Math.floor((seed + index) % 30), // 10-39个相关股票
|
stock_count: 10 + Math.floor((seed + index) % 30), // 10-39个相关股票
|
||||||
relevance: 70 + Math.floor((seed * 7 + index * 11) % 30), // 70-99的相关度
|
score: parseFloat(score.toFixed(2)), // 0-1之间的分数,而不是0-100
|
||||||
description: descriptionTemplates[name] || `${name}相关概念,市场关注度较高,具有一定的投资价值。`,
|
description: descriptionTemplates[name] || `${name}相关概念,市场关注度较高,具有一定的投资价值。`,
|
||||||
avg_change_pct: (Math.random() * 15 - 5).toFixed(2), // -5% ~ +10% 的涨跌幅
|
price_info: { // 将 avg_change_pct 嵌套在 price_info 对象中
|
||||||
|
avg_change_pct: parseFloat(avgChangePct)
|
||||||
|
},
|
||||||
match_type: matchTypes[(seed + index) % 3], // 随机匹配类型
|
match_type: matchTypes[(seed + index) % 3], // 随机匹配类型
|
||||||
happened_times: generateHappenedTimes(seed + index), // 历史触发时间
|
happened_times: generateHappenedTimes(seed + index), // 历史触发时间
|
||||||
stocks: generateRelatedStocks(name, seed + index) // 核心相关股票
|
stocks: generateRelatedStocks(name, seed + index) // 核心相关股票
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,8 +35,11 @@ const DetailedConceptCard = ({ concept, onClick }) => {
|
|||||||
const headingColor = useColorModeValue('gray.700', 'gray.200');
|
const headingColor = useColorModeValue('gray.700', 'gray.200');
|
||||||
const stockCountColor = useColorModeValue('gray.500', 'gray.400');
|
const stockCountColor = useColorModeValue('gray.500', 'gray.400');
|
||||||
|
|
||||||
|
// 计算相关度百分比
|
||||||
|
const relevanceScore = Math.round((concept.score || 0) * 100);
|
||||||
|
|
||||||
// 计算涨跌幅颜色
|
// 计算涨跌幅颜色
|
||||||
const changePct = parseFloat(concept.avg_change_pct);
|
const changePct = parseFloat(concept.price_info?.avg_change_pct);
|
||||||
const changeColor = changePct > 0 ? 'red' : changePct < 0 ? 'green' : 'gray';
|
const changeColor = changePct > 0 ? 'red' : changePct < 0 ? 'green' : 'gray';
|
||||||
const changeSymbol = changePct > 0 ? '+' : '';
|
const changeSymbol = changePct > 0 ? '+' : '';
|
||||||
|
|
||||||
@@ -61,11 +64,11 @@ const DetailedConceptCard = ({ concept, onClick }) => {
|
|||||||
{/* 左侧:概念名称 + Badge */}
|
{/* 左侧:概念名称 + Badge */}
|
||||||
<VStack align="start" spacing={2} flex={1}>
|
<VStack align="start" spacing={2} flex={1}>
|
||||||
<Text fontSize="md" fontWeight="bold" color="blue.600">
|
<Text fontSize="md" fontWeight="bold" color="blue.600">
|
||||||
{concept.name}
|
{concept.concept}
|
||||||
</Text>
|
</Text>
|
||||||
<HStack spacing={2} flexWrap="wrap">
|
<HStack spacing={2} flexWrap="wrap">
|
||||||
<Badge colorScheme="purple" fontSize="xs">
|
<Badge colorScheme="purple" fontSize="xs">
|
||||||
相关度: {concept.relevance}%
|
相关度: {relevanceScore}%
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge colorScheme="orange" fontSize="xs">
|
<Badge colorScheme="orange" fontSize="xs">
|
||||||
{concept.stock_count} 只股票
|
{concept.stock_count} 只股票
|
||||||
@@ -74,7 +77,7 @@ const DetailedConceptCard = ({ concept, onClick }) => {
|
|||||||
</VStack>
|
</VStack>
|
||||||
|
|
||||||
{/* 右侧:涨跌幅 */}
|
{/* 右侧:涨跌幅 */}
|
||||||
{concept.avg_change_pct && (
|
{concept.price_info?.avg_change_pct && (
|
||||||
<Box textAlign="right">
|
<Box textAlign="right">
|
||||||
<Text fontSize="xs" color={stockCountColor} mb={1}>
|
<Text fontSize="xs" color={stockCountColor} mb={1}>
|
||||||
平均涨跌幅
|
平均涨跌幅
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ const SimpleConceptCard = ({ concept, onClick, getRelevanceColor }) => {
|
|||||||
const conceptNameColor = useColorModeValue('gray.800', 'gray.100');
|
const conceptNameColor = useColorModeValue('gray.800', 'gray.100');
|
||||||
const borderColor = useColorModeValue('gray.300', 'gray.600');
|
const borderColor = useColorModeValue('gray.300', 'gray.600');
|
||||||
|
|
||||||
const relevanceColors = getRelevanceColor(concept.relevance);
|
const relevanceScore = Math.round((concept.score || 0) * 100);
|
||||||
|
const relevanceColors = getRelevanceColor(relevanceScore);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -47,7 +48,7 @@ const SimpleConceptCard = ({ concept, onClick, getRelevanceColor }) => {
|
|||||||
>
|
>
|
||||||
{/* 左侧:概念名 + 数量 */}
|
{/* 左侧:概念名 + 数量 */}
|
||||||
<Text fontSize="sm" fontWeight="normal" color={conceptNameColor} mr={3}>
|
<Text fontSize="sm" fontWeight="normal" color={conceptNameColor} mr={3}>
|
||||||
{concept.name}{' '}
|
{concept.concept}{' '}
|
||||||
<Text as="span" color="gray.500">
|
<Text as="span" color="gray.500">
|
||||||
({concept.stock_count})
|
({concept.stock_count})
|
||||||
</Text>
|
</Text>
|
||||||
@@ -63,7 +64,7 @@ const SimpleConceptCard = ({ concept, onClick, getRelevanceColor }) => {
|
|||||||
flexShrink={0}
|
flexShrink={0}
|
||||||
>
|
>
|
||||||
<Text fontSize="xs" fontWeight="medium" whiteSpace="nowrap">
|
<Text fontSize="xs" fontWeight="medium" whiteSpace="nowrap">
|
||||||
相关度: {concept.relevance}%
|
相关度: {relevanceScore}%
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const RelatedConceptsSection = ({ keywords, effectiveTradingDate, eventTime }) =
|
|||||||
*/
|
*/
|
||||||
const handleConceptClick = (concept) => {
|
const handleConceptClick = (concept) => {
|
||||||
// 跳转到概念中心,并搜索该概念
|
// 跳转到概念中心,并搜索该概念
|
||||||
navigate(`/concepts?q=${encodeURIComponent(concept.name)}`);
|
navigate(`/concepts?q=${encodeURIComponent(concept.concept)}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user