'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 (
); }