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';