import React, { useState, useRef } from 'react'; import { Upload, Link as LinkIcon, X, Film, Music, Image as ImageIcon, ExternalLink } from 'lucide-react'; import { uploadAsset } from '../api'; import { filenameFromUrl, thumbUrl, localAsset } from '../utils'; export default function MediaUploader({ label, accept = 'image/*', type = 'image', // 'image' | 'video' | 'audio' multiple = false, maxCount = 99, value, // string | string[] onChange, hint, }) { const [urlInput, setUrlInput] = useState(''); const [isUploading, setIsUploading] = useState(false); const [isDragOver, setIsDragOver] = useState(false); const fileInputRef = useRef(null); const items = multiple ? (Array.isArray(value) ? value : []) : (value ? [value] : []); const handleFiles = async (files) => { if (!files || files.length === 0) return; setIsUploading(true); try { const newUrls = []; for (const file of Array.from(files)) { if (items.length + newUrls.length >= maxCount) break; const res = await uploadAsset(file); if (res.url) newUrls.push(res.url); } if (multiple) { onChange([...items, ...newUrls].slice(0, maxCount)); } else if (newUrls.length > 0) { onChange(newUrls[0]); } } catch (e) { alert('上传失败: ' + e.message); } finally { setIsUploading(false); if (fileInputRef.current) fileInputRef.current.value = ''; } }; const handleAddUrl = (e) => { if (e.key === 'Enter') { e.preventDefault(); const u = urlInput.trim(); if (!u) return; if (multiple) { if (items.length >= maxCount) { alert(`最多只允许添加 ${maxCount} 个`); return; } onChange([...items, u]); } else { onChange(u); } setUrlInput(''); } }; const handleRemove = (index) => { if (multiple) { const next = items.filter((_, i) => i !== index); onChange(next); } else { onChange(null); } }; // 支持键盘粘贴截图 const handlePaste = (e) => { const clipboardFiles = e.clipboardData?.files; if (clipboardFiles && clipboardFiles.length > 0) { e.preventDefault(); handleFiles(clipboardFiles); } }; return (