diff --git a/src/components/StockRelation/RelationDescription.tsx b/src/components/StockRelation/RelationDescription.tsx index 10f0f35e..56f5bf65 100644 --- a/src/components/StockRelation/RelationDescription.tsx +++ b/src/components/StockRelation/RelationDescription.tsx @@ -4,6 +4,7 @@ * 用于显示股票与事件的关联描述信息 * 固定标题为"关联描述:" * 自动处理多种数据格式(字符串、对象数组) + * 支持悬停显示来源信息 * * @example * ```tsx @@ -20,7 +21,20 @@ */ import React, { useMemo } from 'react'; -import { Box, Text, BoxProps } from '@chakra-ui/react'; +import { Box, Text, BoxProps, Tooltip } from '@chakra-ui/react'; + +/** + * 关联描述数据项类型 + */ +export interface RelationDescItem { + query_part?: string; + sentences?: string; + organization?: string; + report_title?: string; + declare_date?: string; + author?: string; + match_score?: string; +} /** * 关联描述数据类型 @@ -30,10 +44,7 @@ import { Box, Text, BoxProps } from '@chakra-ui/react'; export type RelationDescType = | string | { - data: Array<{ - query_part?: string; - sentences?: string; - }>; + data: Array; } | null | undefined; @@ -66,33 +77,45 @@ export const RelationDescription: React.FC = ({ lineHeight = '1.7', containerProps = {} }) => { - // 处理关联描述(兼容对象和字符串格式) - const processedDesc = useMemo(() => { + // 判断是否为对象格式(带来源信息) + const isObjectFormat = useMemo(() => { + return typeof relationDesc === 'object' && relationDesc?.data && Array.isArray(relationDesc.data); + }, [relationDesc]); + + // 处理关联描述数据 + const descData = useMemo(() => { if (!relationDesc) return null; // 字符串格式:直接返回 if (typeof relationDesc === 'string') { - return relationDesc; + return { type: 'string' as const, content: 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 - ); + // 对象格式:返回数据数组 + if (isObjectFormat && relationDesc && typeof relationDesc === 'object') { + const items = relationDesc.data.filter((item) => item.query_part); + if (items.length === 0) return null; + return { type: 'array' as const, items }; } return null; - }, [relationDesc]); + }, [relationDesc, isObjectFormat]); // 如果没有有效的描述内容,不渲染组件 - if (!processedDesc) { + if (!descData) { return null; } + // 格式化日期 + const formatDate = (dateStr?: string) => { + if (!dateStr) return ''; + try { + return new Date(dateStr).toLocaleDateString('zh-CN'); + } catch { + return dateStr; + } + }; + return ( = ({ > 关联描述: - - {processedDesc} - + {descData.type === 'string' ? ( + + {descData.content} + + ) : ( + + {descData.items.map((item, index, arr) => ( + + + {item.sentences && ( + + {item.sentences} + + )} + + 来源:{item.organization || '未知'} + + {item.report_title && ( + + {item.report_title} + + )} + {item.declare_date && ( + + {formatDate(item.declare_date)} + + )} + + } + placement="top" + hasArrow + bg="rgba(20, 20, 20, 0.95)" + maxW="420px" + > + + {item.query_part} + + + {index < arr.length - 1 && ';'} + + ))} + + )} ); }; diff --git a/src/views/Community/components/DynamicNewsDetail/StockListItem.js b/src/views/Community/components/DynamicNewsDetail/StockListItem.js index fa789387..ebb02cd2 100644 --- a/src/views/Community/components/DynamicNewsDetail/StockListItem.js +++ b/src/views/Community/components/DynamicNewsDetail/StockListItem.js @@ -325,14 +325,61 @@ const StockListItem = ({ > AI合成 - {/* 直接渲染文字内容 */} + {/* 渲染 query_part,每句带来源悬停提示 */} - {stock.relation_desc?.data?.map(item => item.sentences || item.query_part).filter(Boolean).join(',')} + {stock.relation_desc?.data?.filter(item => item.query_part).map((item, index, arr) => ( + + + {item.sentences && ( + + {item.sentences} + + )} + + 来源:{item.organization || '未知'} + + {item.report_title && ( + + {item.report_title} + + )} + {item.declare_date && ( + + {new Date(item.declare_date).toLocaleDateString('zh-CN')} + + )} + + } + placement="top" + hasArrow + bg="rgba(20, 20, 20, 0.95)" + color="white" + maxW="420px" + > + + {item.query_part} + + + {index < arr.length - 1 && ';'} + + ))}