'use client';
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Image from '@tiptap/extension-image';
import Link from '@tiptap/extension-link';
import {
Bold,
Italic,
Strikethrough,
Code,
Heading1,
Heading2,
Heading3,
List,
ListOrdered,
Quote,
Undo,
Redo,
Link as LinkIcon,
Image as ImageIcon
} from 'lucide-react';
import { useCallback, useState } from 'react';
interface RichTextEditorProps {
content: string;
onChange: (content: string) => void;
}
export default function RichTextEditor({ content, onChange }: RichTextEditorProps) {
const [uploading, setUploading] = useState(false);
const editor = useEditor({
extensions: [
StarterKit,
Image.configure({
HTMLAttributes: {
class: 'max-w-full h-auto rounded-lg',
},
}),
Link.configure({
openOnClick: false,
HTMLAttributes: {
class: 'text-[#C41E3A] underline',
},
}),
],
content,
onUpdate: ({ editor }) => {
onChange(editor.getHTML());
},
});
const handleImageUpload = useCallback(async () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = async (e) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (!file) return;
setUploading(true);
try {
const formData = new FormData();
formData.append('file', file);
formData.append('type', 'image');
const res = await fetch('/api/admin/upload', {
method: 'POST',
body: formData,
});
const data = await res.json();
if (res.ok && editor) {
editor.chain().focus().setImage({ src: data.file.url }).run();
}
} catch (error) {
console.error('上传图片失败:', error);
} finally {
setUploading(false);
}
};
input.click();
}, [editor]);
const addLink = useCallback(() => {
if (!editor) return;
const url = window.prompt('输入链接地址:');
if (url) {
editor.chain().focus().setLink({ href: url }).run();
}
}, [editor]);
if (!editor) {
return null;
}
return (
);
}