import React, { useState } from 'react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; interface MarkdownRendererProps { content: string; className?: string; onCitationClick?: (index: number) => void; } const extractTextFromNode = (node: React.ReactNode): string => { if (typeof node === 'string' || typeof node === 'number') return String(node); if (Array.isArray(node)) return node.map(extractTextFromNode).join(''); if (React.isValidElement<{ children?: React.ReactNode }>(node)) return extractTextFromNode(node.props.children); return ''; }; const CodeBlock: React.FC<{ children: React.ReactNode; className?: string }> = ({ children, className = '' }) => { const [copied, setCopied] = useState(false); const codeText = extractTextFromNode(children).replace(/\n$/, ''); const language = className?.match(/language-(\w+)/)?.[1]; const handleCopy = async () => { try { await navigator.clipboard.writeText(codeText); setCopied(true); window.setTimeout(() => setCopied(false), 1500); } catch (error) { console.error('复制代码失败:', error); } }; return (
{language || 'code'}
        {children}
      
); }; const MarkdownRenderer: React.FC = ({ content, className = '', onCitationClick }) => { const contentWithCitationBadge = content.replace( /\[\[(\d+)\]\]/g, '', ); return (
{ if (!onCitationClick) return; const target = event.target as HTMLElement; const button = target.closest('[data-citation-index]') as HTMLElement | null; if (!button) return; const index = Number(button.dataset.citationIndex || '0'); if (Number.isNaN(index) || index <= 0) return; onCitationClick(index); }} >

, h2: ({ node, ...props }) =>

, h3: ({ node, ...props }) =>

, h4: ({ node, ...props }) =>

, h5: ({ node, ...props }) =>

, h6: ({ node, ...props }) =>
, p: ({ node, ...props }) =>

, ul: ({ node, ...props }) =>