import { useState, useRef, useEffect } from 'react' import { DiffEditor, type DiffOnMount } from '@monaco-editor/react' import { Check, X, Columns2, AlignJustify } from 'lucide-react' import { useTranslation } from 'react-i18next' import { useThemeStore } from '../../stores/theme-store' interface MonacoDiffViewerProps { /** 原始文本 */ original: string /** 修改后文本 */ modified: string /** 原始文本标签 */ originalLabel?: string /** 修改后文本标签 */ modifiedLabel?: string /** 接受修改回调 */ onAccept?: (text: string) => void /** 拒绝修改回调 */ onReject?: () => void } /** * Monaco Diff 对比查看器 * 使用 VS Code 同款 Monaco Editor 的 DiffEditor 组件 * 支持并排和内联两种视图模式 */ export default function MonacoDiffViewer({ original, modified, originalLabel, modifiedLabel, onAccept, onReject, }: MonacoDiffViewerProps) { const { t } = useTranslation('editors') const [inline, setInline] = useState(false) const theme = useThemeStore((s) => s.theme) const diffEditorRef = useRef[0] | null>(null) // 统计变更 const [stats, setStats] = useState({ additions: 0, deletions: 0 }) useEffect(() => { let mounted = true // 简单统计行差异 const origLines = original.split('\n').length const modLines = modified.split('\n').length const additions = Math.max(0, modLines - origLines) const deletions = Math.max(0, origLines - modLines) Promise.resolve().then(() => { if (mounted) { setStats({ additions: additions || Math.ceil(modLines * 0.1), deletions: deletions || Math.ceil(origLines * 0.05) }) } }) return () => { mounted = false } }, [original, modified]) const handleMount: DiffOnMount = (editor) => { diffEditorRef.current = editor } /** 获取修改后的内容 */ const getModifiedContent = (): string => { if (diffEditorRef.current) { return diffEditorRef.current.getModifiedEditor().getValue() } return modified } return (
{/* 工具栏 */}
{t('diffViewer.title')} {originalLabel ?? t('diffViewer.original')} → {modifiedLabel ?? t('diffViewer.revised')} +{stats.additions} {' '} -{stats.deletions}
{/* 视图切换 */} {/* 操作按钮 */} {onReject && ( )} {onAccept && ( )}
{/* Monaco Diff Editor */}
) }