diff --git a/src/components/StockChart/StockChartModal.js b/src/components/StockChart/StockChartModal.js
index 96d553fe..f4b0ca80 100644
--- a/src/components/StockChart/StockChartModal.js
+++ b/src/components/StockChart/StockChartModal.js
@@ -7,6 +7,7 @@ import dayjs from 'dayjs';
import { stockService } from '../../services/eventService';
import { logger } from '../../utils/logger';
import RiskDisclaimer from '../RiskDisclaimer';
+import { RelationDescription } from '../StockRelation';
const StockChartModal = ({
isOpen,
@@ -24,27 +25,6 @@ const StockChartModal = ({
const [chartData, setChartData] = useState(null);
const [preloadedData, setPreloadedData] = useState({});
- // 处理关联描述(兼容对象和字符串格式)- 使用 useMemo 缓存计算结果
- const relationDesc = useMemo(() => {
- const desc = stock?.relation_desc;
-
- if (!desc) return null;
-
- if (typeof desc === 'string') {
- return desc;
- }
-
- if (typeof desc === 'object' && desc.data && Array.isArray(desc.data)) {
- // 新格式:{data: [{query_part: "...", sentences: "..."}]}
- return desc.data
- .map(item => item.query_part || item.sentences || '')
- .filter(s => s)
- .join(';') || null;
- }
-
- return null;
- }, [stock?.relation_desc]);
-
// 预加载数据
const preloadData = async (type) => {
if (!stock || preloadedData[type]) return;
@@ -563,21 +543,7 @@ const StockChartModal = ({
{/* 关联描述 */}
- {relationDesc && (
-
-
- 关联描述:
-
-
- {relationDesc}
-
-
- )}
+
{/* 风险提示 */}
diff --git a/src/components/StockRelation/RelationDescription.tsx b/src/components/StockRelation/RelationDescription.tsx
new file mode 100644
index 00000000..10f0f35e
--- /dev/null
+++ b/src/components/StockRelation/RelationDescription.tsx
@@ -0,0 +1,121 @@
+/**
+ * 关联描述组件
+ *
+ * 用于显示股票与事件的关联描述信息
+ * 固定标题为"关联描述:"
+ * 自动处理多种数据格式(字符串、对象数组)
+ *
+ * @example
+ * ```tsx
+ * // 基础使用 - 传入原始 relation_desc 数据
+ *
+ *
+ * // 自定义样式
+ *
+ * ```
+ */
+
+import React, { useMemo } from 'react';
+import { Box, Text, BoxProps } from '@chakra-ui/react';
+
+/**
+ * 关联描述数据类型
+ * - 字符串格式:直接的描述文本
+ * - 对象格式:包含多个句子的数组
+ */
+export type RelationDescType =
+ | string
+ | {
+ data: Array<{
+ query_part?: string;
+ sentences?: string;
+ }>;
+ }
+ | null
+ | undefined;
+
+export interface RelationDescriptionProps {
+ /** 原始关联描述数据(支持字符串或对象格式) */
+ relationDesc: RelationDescType;
+
+ /** 字体大小,默认 'sm' */
+ fontSize?: string;
+
+ /** 标题颜色,默认 'gray.700' */
+ titleColor?: string;
+
+ /** 文本颜色,默认 'gray.600' */
+ textColor?: string;
+
+ /** 行高,默认 '1.7' */
+ lineHeight?: string;
+
+ /** 容器额外属性 */
+ containerProps?: BoxProps;
+}
+
+export const RelationDescription: React.FC = ({
+ relationDesc,
+ fontSize = 'sm',
+ titleColor = 'gray.700',
+ textColor = 'gray.600',
+ lineHeight = '1.7',
+ containerProps = {}
+}) => {
+ // 处理关联描述(兼容对象和字符串格式)
+ const processedDesc = useMemo(() => {
+ if (!relationDesc) return null;
+
+ // 字符串格式:直接返回
+ if (typeof relationDesc === 'string') {
+ return relationDesc;
+ }
+
+ // 对象格式:提取并拼接文本
+ if (typeof relationDesc === 'object' && relationDesc.data && Array.isArray(relationDesc.data)) {
+ return (
+ relationDesc.data
+ .map((item) => item.query_part || item.sentences || '')
+ .filter((s) => s)
+ .join(';') || null
+ );
+ }
+
+ return null;
+ }, [relationDesc]);
+
+ // 如果没有有效的描述内容,不渲染组件
+ if (!processedDesc) {
+ return null;
+ }
+
+ return (
+
+
+ 关联描述:
+
+
+ {processedDesc}
+
+
+ );
+};
diff --git a/src/components/StockRelation/index.ts b/src/components/StockRelation/index.ts
new file mode 100644
index 00000000..890b0970
--- /dev/null
+++ b/src/components/StockRelation/index.ts
@@ -0,0 +1,6 @@
+/**
+ * StockRelation 组件导出入口
+ */
+
+export { RelationDescription } from './RelationDescription';
+export type { RelationDescriptionProps, RelationDescType } from './RelationDescription';