feat: 抽离关联描述组件

This commit is contained in:
zdl
2025-11-23 10:38:19 +08:00
parent f578969ee6
commit a4b8a13e6d
3 changed files with 129 additions and 36 deletions

View File

@@ -0,0 +1,121 @@
/**
* 关联描述组件
*
* 用于显示股票与事件的关联描述信息
* 固定标题为"关联描述:"
* 自动处理多种数据格式(字符串、对象数组)
*
* @example
* ```tsx
* // 基础使用 - 传入原始 relation_desc 数据
* <RelationDescription relationDesc={stock.relation_desc} />
*
* // 自定义样式
* <RelationDescription
* relationDesc={stock.relation_desc}
* fontSize="md"
* titleColor="blue.700"
* />
* ```
*/
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<RelationDescriptionProps> = ({
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 (
<Box
p={4}
borderTop="1px solid"
borderTopColor="gray.200"
{...containerProps}
>
<Text
fontSize={fontSize}
fontWeight="bold"
mb={2}
color={titleColor}
>
:
</Text>
<Text
fontSize={fontSize}
color={textColor}
lineHeight={lineHeight}
whiteSpace="pre-wrap"
>
{processedDesc}
</Text>
</Box>
);
};