Files
vf_react/src/components/Citation/CitedContent.js
2025-11-27 18:27:44 +08:00

162 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/components/Citation/CitedContent.js
import React from 'react';
import { Typography, Tag } from 'antd';
import { RobotOutlined } from '@ant-design/icons';
import CitationMark from './CitationMark';
import { processCitationData } from '../../utils/citationUtils';
import { logger } from '../../utils/logger';
const { Text } = Typography;
/**
* 带引用标注的内容组件(块级模式)
* 展示拼接的文本每句话后显示上标引用【1】【2】【3】
* 支持鼠标悬浮和点击查看引用来源
* AI 标识统一显示在右上角,不占用布局高度
*
* @param {Object} props
* @param {Object} props.data - API 返回的原始数据 { data: [...] }
* @param {string} props.title - 标题文本,默认 "AI 分析结果"
* @param {string} props.prefix - 内容前的前缀标签,如 "机制:"(可选)
* @param {Object} props.prefixStyle - 前缀标签的自定义样式(可选)
* @param {boolean} props.showAIBadge - 是否显示右上角 AI 标识,默认 true可选
* @param {Object} props.containerStyle - 容器额外样式(可选)
* @param {string} props.textColor - 文本颜色,默认自动判断背景色(可选)
* @param {string} props.titleColor - 标题颜色,默认继承 textColor可选
*
* @example
* <CitedContent
* data={apiData}
* title="关联描述"
* prefix="机制:"
* prefixStyle={{ color: '#666' }}
* showAIBadge={true}
* containerStyle={{ marginTop: 16 }}
* textColor="#E2E8F0"
* />
*/
const CitedContent = ({
data,
title = 'AI 分析结果',
prefix = '',
prefixStyle = {},
showAIBadge = true,
containerStyle = {},
textColor,
titleColor
}) => {
// 处理数据
const processed = processCitationData(data);
// 如果数据无效,不渲染
if (!processed) {
logger.warn('CitedContent', '无效数据,不渲染', {
hasData: !!data,
title
});
return null;
}
// 自动判断文本颜色:如果容器背景是深色,使用浅色文本
const bgColor = containerStyle.backgroundColor;
const isDarkBg = bgColor && (
bgColor.includes('rgba(0,0,0') ||
bgColor.includes('rgba(0, 0, 0') ||
bgColor === 'transparent' ||
bgColor.includes('#1A202C') ||
bgColor.includes('#171923')
);
const finalTextColor = textColor || (isDarkBg ? '#E2E8F0' : '#262626');
const finalTitleColor = titleColor || finalTextColor;
return (
<div
style={{
position: 'relative',
width: '100%',
backgroundColor: '#f5f5f5',
borderRadius: 6,
padding: 16,
paddingTop: title ? 16 : 20,
...containerStyle
}}
>
{/* 标题栏 */}
{title && (
<div style={{ marginBottom: 12 }}>
<Text strong style={{ fontSize: 14, color: finalTitleColor }}>
{title}
</Text>
</div>
)}
{/* 带引用的文本内容 */}
<div style={{ lineHeight: 1.8 }}>
{/* AI 标识 - 行内显示在文字前面 */}
{showAIBadge && (
<Tag
icon={<RobotOutlined />}
color="purple"
style={{
fontSize: 12,
padding: '2px 8px',
marginRight: 8,
verticalAlign: 'middle',
display: 'inline-flex',
}}
className="ai-badge-responsive"
>
AI合成
</Tag>
)}
{/* 前缀标签(如果有) */}
{prefix && (
<Text style={{
fontSize: 14,
fontWeight: 'bold',
display: 'inline',
marginRight: 4,
color: finalTextColor,
...prefixStyle
}}>
{prefix}
</Text>
)}
{processed.segments.map((segment, index) => (
<React.Fragment key={`segment-${segment.citationId}`}>
{/* 文本片段 */}
<Text style={{ fontSize: 14, display: 'inline', color: finalTextColor }}>
{segment.text}
</Text>
{/* 引用标记 */}
<CitationMark
citationId={segment.citationId}
citation={processed.citations[segment.citationId]}
/>
{/* 在片段之间添加逗号分隔符(最后一个不加) */}
{index < processed.segments.length - 1 && (
<Text style={{ fontSize: 14, display: 'inline', color: finalTextColor }}></Text>
)}
</React.Fragment>
))}
</div>
{/* 响应式样式 */}
<style jsx>{`
@media (max-width: 768px) {
.ai-badge-responsive {
font-size: 10px !important;
padding: 1px 6px !important;
}
}
`}</style>
</div>
);
};
export default CitedContent;