From e24d2cf9b0f5c87619b99b7c1c29866fc0e77186 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 3 Feb 2026 14:39:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=9B=BE=E7=89=87=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E4=B8=8A=E4=BC=A0=E5=9B=BE=E7=89=87=E5=85=88=E4=BC=A0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E8=8E=B7=E5=8F=96URL=EF=BC=8C?= =?UTF-8?q?=E5=BD=BB=E5=BA=95=E7=A6=81=E6=AD=A2base64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/image-annotator.tsx | 109 +++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/components/image-annotator.tsx b/components/image-annotator.tsx index 945befd..bff7830 100644 --- a/components/image-annotator.tsx +++ b/components/image-annotator.tsx @@ -78,8 +78,23 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod const fileInputRef = useRef(null); - // 处理拖拽上传 - const handleDrop = useCallback((e: React.DragEvent) => { + // 上传图片到服务器获取 URL 的辅助函数 + const uploadImageFile = async (file: File): Promise => { + const formData = new FormData(); + formData.append("file", file); + const response = await fetch("/api/files/upload", { + method: "POST", + body: formData, + }); + if (!response.ok) { + throw new Error("上传失败"); + } + const result = await response.json(); + return result.url; + }; + + // 处理拖拽上传 - 先上传到服务器获取URL + const handleDrop = useCallback(async (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); @@ -94,11 +109,13 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod toast.error("图片大小不能超过 10MB"); return; } - const reader = new FileReader(); - reader.onload = (e) => { - const result = e.target?.result as string; - setOriginalImageUrl(result); + + try { setIsLoading(true); + toast.info("正在上传图片..."); + const imageUrl = await uploadImageFile(file); + + setOriginalImageUrl(imageUrl); setProcessedImageUrl(null); setProcessedImageBase64(null); setProcessType(null); @@ -106,9 +123,22 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod setCurrentAction(null); const img = new window.Image(); - img.src = result; - }; - reader.readAsDataURL(file); + img.crossOrigin = "anonymous"; + img.onload = () => { + setImage(img); + setIsLoading(false); + }; + img.onerror = () => { + setIsLoading(false); + toast.error("图片加载失败"); + }; + img.src = imageUrl; + toast.success("图片上传成功"); + } catch (error) { + console.error("上传图片失败:", error); + toast.error("上传失败,请重试"); + setIsLoading(false); + } } }, []); @@ -117,11 +147,11 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod e.stopPropagation(); }, []); - // 处理粘贴上传 + // 处理粘贴上传 - 先上传到服务器获取URL useEffect(() => { if (!mounted || originalImageUrl) return; - const handlePaste = (e: ClipboardEvent) => { + const handlePaste = async (e: ClipboardEvent) => { const items = e.clipboardData?.items; if (!items) return; @@ -135,11 +165,12 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod return; } - const reader = new FileReader(); - reader.onload = (e) => { - const result = e.target?.result as string; - setOriginalImageUrl(result); + try { setIsLoading(true); + toast.info("正在上传图片..."); + const imageUrl = await uploadImageFile(file); + + setOriginalImageUrl(imageUrl); setProcessedImageUrl(null); setProcessedImageBase64(null); setProcessType(null); @@ -147,9 +178,22 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod setCurrentAction(null); const img = new window.Image(); - img.src = result; - }; - reader.readAsDataURL(file); + img.crossOrigin = "anonymous"; + img.onload = () => { + setImage(img); + setIsLoading(false); + }; + img.onerror = () => { + setIsLoading(false); + toast.error("图片加载失败"); + }; + img.src = imageUrl; + toast.success("图片上传成功"); + } catch (error) { + console.error("上传图片失败:", error); + toast.error("上传失败,请重试"); + setIsLoading(false); + } break; } } @@ -255,19 +299,22 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod }); }, []); - // 处理本地图片上传 - const handleImageUpload = (e: React.ChangeEvent) => { + // 处理本地图片上传 - 先上传到服务器获取URL + const handleImageUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { if (file.size > 10 * 1024 * 1024) { toast.error("图片大小不能超过 10MB"); + e.target.value = ""; return; } - const reader = new FileReader(); - reader.onload = (e) => { - const result = e.target?.result as string; - setOriginalImageUrl(result); + + try { setIsLoading(true); + toast.info("正在上传图片..."); + const imageUrl = await uploadImageFile(file); + + setOriginalImageUrl(imageUrl); // 重置状态 setProcessedImageUrl(null); setProcessedImageBase64(null); @@ -282,9 +329,17 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel, initialResizeMod setImage(img); setIsLoading(false); }; - img.src = result; - }; - reader.readAsDataURL(file); + img.onerror = () => { + setIsLoading(false); + toast.error("图片加载失败"); + }; + img.src = imageUrl; + toast.success("图片上传成功"); + } catch (error) { + console.error("上传图片失败:", error); + toast.error("上传失败,请重试"); + setIsLoading(false); + } } // 重置 input e.target.value = "";