'use client'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { memo, useState, useCallback } from 'react'; /** * 聊天消息 Markdown 渲染组件 * 支持:GFM (表格/删除线/任务列表) + 数学公式 (KaTeX) + 代码块 */ function ChatMarkdownInner({ content }) { if (!content) return null; return ( {children}; } const lang = className?.replace('language-', '') || ''; return ; }, // 链接:新窗口打开 a({ href, children, ...props }) { return ( {children} ); }, // 表格样式 table({ children, ...props }) { return (
{children}
); }, // 段落 p({ children, ...props }) { return

{children}

; }, // 列表 ul({ children, ...props }) { return ; }, ol({ children, ...props }) { return
    {children}
; }, // 引用 blockquote({ children, ...props }) { return
{children}
; }, // 标题 h1({ children, ...props }) { return

{children}

; }, h2({ children, ...props }) { return

{children}

; }, h3({ children, ...props }) { return
{children}
; }, }} > {content}
); } // 代码块子组件(带复制按钮) function CodeBlock({ lang, code }) { const [copied, setCopied] = useState(false); const handleCopy = useCallback(() => { navigator.clipboard.writeText(code).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }); }, [code]); return (
{lang || 'text'}
{code}
); } const ChatMarkdown = memo(ChatMarkdownInner); export default ChatMarkdown;