'use client' import * as React from 'react' import { Copy, Check, Maximize2 } from 'lucide-react' import copy from 'copy-to-clipboard' import { Button } from '@/components/ui/button' import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { cn } from '@/lib/utils' import { toast } from 'sonner' import { Highlight, themes } from 'prism-react-renderer' import { useTheme } from 'next-themes' export interface DetailCodeBlockProps { code: string language?: string title?: string copyable?: boolean showLineNumbers?: boolean maxHeight?: string className?: string } /** * 代码块组件 * 展示代码或JSON数据,支持复制和行号显示功能 */ export function DetailCodeBlock({ code, language = 'text', title, copyable = true, showLineNumbers = true, maxHeight = '400px', className, }: DetailCodeBlockProps) { const [copied, setCopied] = React.useState(false) const [fullscreenOpen, setFullscreenOpen] = React.useState(false) const { theme } = useTheme() const handleCopy = () => { const success = copy(code) if (success) { setCopied(true) toast.success('已复制到剪贴板') setTimeout(() => setCopied(false), 2000) } else { toast.error('复制失败') } } // 根据主题选择合适的代码高亮主题 const prismTheme = theme === 'dark' ? themes.vsDark : themes.vsLight // 渲染代码高亮内容 const renderCodeContent = (isFullscreen = false) => ( {({ className: highlightClassName, style, tokens, getLineProps, getTokenProps }) => { // 提取背景色用于外层容器 const backgroundColor = style?.backgroundColor // 计算行号的最大宽度 const lineNumberWidth = String(tokens.length).length return (
              {tokens.map((line, i) => (
                
{showLineNumbers && ( {i + 1} )} {line.map((token, key) => ( ))}
))}
) }}
) return ( <>
{(title || copyable) && (
{title && (
{title}
)}
{copyable && ( )}
)} {renderCodeContent()}
{/* 全屏对话框 */} {title || '代码查看'} 全屏查看代码 {renderCodeContent(true)} ) }