"use client"; import React, { useState } from "react"; import { DiffEditor } from "@monaco-editor/react"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Diff, RotateCcw, ArrowRightLeft } from "lucide-react"; import { toast } from "sonner"; import { useTheme } from "next-themes"; const LANGUAGES = [ { value: "plaintext", label: "纯文本" }, { value: "json", label: "JSON" }, { value: "javascript", label: "JavaScript" }, { value: "typescript", label: "TypeScript" }, { value: "html", label: "HTML" }, { value: "css", label: "CSS" }, { value: "sql", label: "SQL" }, { value: "xml", label: "XML" }, { value: "yaml", label: "YAML" }, { value: "markdown", label: "Markdown" }, ]; export default function DiffPage() { const { theme } = useTheme(); const [original, setOriginal] = useState(""); const [modified, setModified] = useState(""); const [language, setLanguage] = useState("plaintext"); // Default to side-by-side view (false means side-by-side in Monaco Diff Editor options usually, wait, let's just control options) const [renderSideBySide, setRenderSideBySide] = useState(true); const handleClear = () => { if (confirm("确定要清空所有内容吗?")) { setOriginal(""); setModified(""); toast.info("已清空"); } }; const handleSwap = () => { const temp = original; setOriginal(modified); setModified(temp); toast.success("已交换原始内容和修改内容"); }; return (
{/* Header */}

文本 Diff 对比

比较两段文本的差异,支持代码高亮

{/* Language Selector */} {/* View Mode Toggle */}
{/* Main Editor Area */}
原始内容
修改内容
{ // Determine initial values if needed, but state is controlled slightly differently in DiffEditor // actually DiffEditor is better uncontrolled for values usually or we need to manage models. // But @monaco-editor/react handles `original` and `modified` props updates well. // Listening to changes is a bit more complex if we want 2-way binding, // but for a diff tool, usually users paste into it. // Alternatively, we can use the modifiedModel to get content changes if we really needed // but for a simple comparison tool, just passing props is often enough IF we provide a way to input. // WAIT. The DiffEditor is often read-only for the comparison result, OR editable. // By default originalEditable: false. // Let's set originalEditable: true so users can paste into both sides. }} theme={theme === 'dark' ? "vs-dark" : "light"} options={{ renderSideBySide: renderSideBySide, originalEditable: true, // Allow editing left side readOnly: false, // Allow editing right side minimap: { enabled: false }, scrollBeyondLastLine: false, fontSize: 14, wordWrap: "on", }} /> {/* Overlay hints if empty? Monaco editor keeps state internally. If we want to bind state, we might need a standard Editor first to input? No, DiffEditor with `originalEditable: true` is fine for direct input. */}
💡 提示:您可以直接在左右两侧编辑器中粘贴或输入文本进行通过。上方工具栏可切换语言高亮和对比模式。
); }