diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/ConceptStockItem.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/ConceptStockItem.js
new file mode 100644
index 00000000..9268b53b
--- /dev/null
+++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/ConceptStockItem.js
@@ -0,0 +1,65 @@
+// src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/ConceptStockItem.js
+// 概念股票列表项组件
+
+import React from 'react';
+import {
+ Box,
+ HStack,
+ Text,
+ Badge,
+ useColorModeValue,
+} from '@chakra-ui/react';
+
+/**
+ * 概念股票列表项组件
+ * @param {Object} props
+ * @param {Object} props.stock - 股票对象
+ * - stock_name: 股票名称
+ * - stock_code: 股票代码
+ * - change_pct: 涨跌幅
+ * - reason: 关联原因
+ */
+const ConceptStockItem = ({ stock }) => {
+ const sectionBg = useColorModeValue('gray.50', 'gray.750');
+ const conceptNameColor = useColorModeValue('gray.800', 'gray.100');
+ const stockCountColor = useColorModeValue('gray.500', 'gray.400');
+
+ const stockChangePct = parseFloat(stock.change_pct);
+ const stockChangeColor = stockChangePct > 0 ? 'red' : stockChangePct < 0 ? 'green' : 'gray';
+ const stockChangeSymbol = stockChangePct > 0 ? '+' : '';
+
+ return (
+
+
+
+
+ {stock.stock_name}
+
+
+ {stock.stock_code}
+
+
+ {stock.change_pct && (
+
+ {stockChangeSymbol}{stockChangePct.toFixed(2)}%
+
+ )}
+
+ {stock.reason && (
+
+ {stock.reason}
+
+ )}
+
+ );
+};
+
+export default ConceptStockItem;
diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/DetailedConceptCard.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/DetailedConceptCard.js
new file mode 100644
index 00000000..21a97aff
--- /dev/null
+++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/DetailedConceptCard.js
@@ -0,0 +1,150 @@
+// src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/DetailedConceptCard.js
+// 详细概念卡片组件
+
+import React from 'react';
+import {
+ Box,
+ HStack,
+ VStack,
+ Text,
+ Badge,
+ Card,
+ CardBody,
+ Divider,
+ SimpleGrid,
+ useColorModeValue,
+} from '@chakra-ui/react';
+import ConceptStockItem from './ConceptStockItem';
+
+/**
+ * 详细概念卡片组件
+ * @param {Object} props
+ * @param {Object} props.concept - 概念对象
+ * - name: 概念名称
+ * - stock_count: 相关股票数量
+ * - relevance: 相关度(0-100)
+ * - avg_change_pct: 平均涨跌幅
+ * - description: 概念描述
+ * - happened_times: 历史触发时间数组
+ * - stocks: 相关股票数组
+ * @param {Function} props.onClick - 点击回调
+ */
+const DetailedConceptCard = ({ concept, onClick }) => {
+ const cardBg = useColorModeValue('white', 'gray.700');
+ const borderColor = useColorModeValue('gray.200', 'gray.600');
+ const headingColor = useColorModeValue('gray.700', 'gray.200');
+ const stockCountColor = useColorModeValue('gray.500', 'gray.400');
+
+ // 计算涨跌幅颜色
+ const changePct = parseFloat(concept.avg_change_pct);
+ const changeColor = changePct > 0 ? 'red' : changePct < 0 ? 'green' : 'gray';
+ const changeSymbol = changePct > 0 ? '+' : '';
+
+ return (
+ onClick(concept)}
+ >
+
+
+ {/* 头部信息 */}
+
+ {/* 左侧:概念名称 + Badge */}
+
+
+ {concept.name}
+
+
+
+ 相关度: {concept.relevance}%
+
+
+ {concept.stock_count} 只股票
+
+
+
+
+ {/* 右侧:涨跌幅 */}
+ {concept.avg_change_pct && (
+
+
+ 平均涨跌幅
+
+
+ {changeSymbol}{changePct.toFixed(2)}%
+
+
+ )}
+
+
+
+
+ {/* 概念描述 */}
+ {concept.description && (
+
+ {concept.description}
+
+ )}
+
+ {/* 历史触发时间 */}
+ {concept.happened_times && concept.happened_times.length > 0 && (
+
+
+ 历史触发时间:
+
+
+ {concept.happened_times.map((time, idx) => (
+
+ {time}
+
+ ))}
+
+
+ )}
+
+ {/* 核心相关股票 */}
+ {concept.stocks && concept.stocks.length > 0 && (
+
+
+
+ 核心相关股票
+
+
+ 共 {concept.stock_count} 只
+
+
+
+
+ {concept.stocks.slice(0, 4).map((stock, idx) => (
+
+ ))}
+
+
+ )}
+
+
+
+ );
+};
+
+export default DetailedConceptCard;
diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/SimpleConceptCard.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/SimpleConceptCard.js
new file mode 100644
index 00000000..6d09ecea
--- /dev/null
+++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/SimpleConceptCard.js
@@ -0,0 +1,73 @@
+// src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/SimpleConceptCard.js
+// 简单概念卡片组件(横向卡片)
+
+import React from 'react';
+import {
+ Flex,
+ Box,
+ Text,
+ useColorModeValue,
+} from '@chakra-ui/react';
+
+/**
+ * 简单概念卡片组件
+ * @param {Object} props
+ * @param {Object} props.concept - 概念对象
+ * - name: 概念名称
+ * - stock_count: 相关股票数量
+ * - relevance: 相关度(0-100)
+ * @param {Function} props.onClick - 点击回调
+ * @param {Function} props.getRelevanceColor - 获取相关度颜色的函数
+ */
+const SimpleConceptCard = ({ concept, onClick, getRelevanceColor }) => {
+ const cardBg = useColorModeValue('white', 'gray.700');
+ const conceptNameColor = useColorModeValue('gray.800', 'gray.100');
+ const borderColor = useColorModeValue('gray.300', 'gray.600');
+
+ const relevanceColors = getRelevanceColor(concept.relevance);
+
+ return (
+ onClick(concept)}
+ >
+ {/* 左侧:概念名 + 数量 */}
+
+ {concept.name}{' '}
+
+ ({concept.stock_count})
+
+
+
+ {/* 右侧:相关度标签 */}
+
+
+ 相关度: {concept.relevance}%
+
+
+
+ );
+};
+
+export default SimpleConceptCard;
diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js
new file mode 100644
index 00000000..068ae3d2
--- /dev/null
+++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js
@@ -0,0 +1,46 @@
+// src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/TradingDateInfo.js
+// 交易日期信息提示组件
+
+import React from 'react';
+import {
+ Box,
+ HStack,
+ Text,
+ useColorModeValue,
+} from '@chakra-ui/react';
+import { FaCalendarAlt } from 'react-icons/fa';
+import moment from 'moment';
+
+/**
+ * 交易日期信息提示组件
+ * @param {Object} props
+ * @param {string} props.effectiveTradingDate - 有效交易日期(涨跌幅数据日期)
+ * @param {string|Object} props.eventTime - 事件发生时间
+ */
+const TradingDateInfo = ({ effectiveTradingDate, eventTime }) => {
+ const sectionBg = useColorModeValue('gray.50', 'gray.750');
+ const headingColor = useColorModeValue('gray.700', 'gray.200');
+ const stockCountColor = useColorModeValue('gray.500', 'gray.400');
+
+ if (!effectiveTradingDate) {
+ return null;
+ }
+
+ return (
+
+
+
+
+ 涨跌幅数据日期:{effectiveTradingDate}
+ {eventTime && effectiveTradingDate !== moment(eventTime).format('YYYY-MM-DD') && (
+
+ (事件发生于 {typeof eventTime === 'object' ? moment(eventTime).format('YYYY-MM-DD HH:mm') : moment(eventTime).format('YYYY-MM-DD HH:mm')},显示下一交易日数据)
+
+ )}
+
+
+
+ );
+};
+
+export default TradingDateInfo;
diff --git a/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js
new file mode 100644
index 00000000..39e8377b
--- /dev/null
+++ b/src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js
@@ -0,0 +1,122 @@
+// src/views/Community/components/DynamicNewsDetail/RelatedConceptsSection/index.js
+// 相关概念区组件(主组件)
+
+import React, { useState } from 'react';
+import {
+ Box,
+ SimpleGrid,
+ Flex,
+ Button,
+ Collapse,
+ Heading,
+ useColorModeValue,
+} from '@chakra-ui/react';
+import { ChevronDownIcon, ChevronUpIcon } from '@chakra-ui/icons';
+import { useNavigate } from 'react-router-dom';
+import SimpleConceptCard from './SimpleConceptCard';
+import DetailedConceptCard from './DetailedConceptCard';
+import TradingDateInfo from './TradingDateInfo';
+
+/**
+ * 相关概念区组件
+ * @param {Object} props
+ * @param {Array