"use client" import { useRef, useState } from "react" import { UploadIcon, XIcon } from "lucide-react" import { toast } from "sonner" import { uploadAsset } from "@/lib/api/admin" import { cn } from "@/lib/utils" export type ImageInputProps = { value?: string onChange?: (value: string) => void disabled?: boolean accept?: string maxSize?: number prefix?: string placeholder?: string className?: string } export function ImageInput({ value, onChange, disabled, accept = "image/*", maxSize = 5 * 1024 * 1024, prefix, placeholder = "点击上传图片", className, }: ImageInputProps) { const [uploading, setUploading] = useState(false) const fileInputRef = useRef(null) function handleClick() { if (disabled || uploading) { return } fileInputRef.current?.click() } function handleClear(event: React.MouseEvent) { event.stopPropagation() onChange?.("") } async function handleFileChange(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) { return } if (!file.type.startsWith("image/")) { toast.error("请选择图片文件") return } if (file.size > maxSize) { const maxSizeMB = (maxSize / 1024 / 1024).toFixed(0) toast.error(`图片大小不能超过 ${maxSizeMB}MB`) return } setUploading(true) try { const result = await uploadAsset(file, prefix) onChange?.(result.url) toast.success("图片上传成功") } catch (error) { toast.error(error instanceof Error ? error.message : "上传图片失败") } finally { setUploading(false) if (fileInputRef.current) { fileInputRef.current.value = "" } } } const isDisabled = disabled || uploading return (
{ if (e.key === "Enter" || e.key === " ") { e.preventDefault() handleClick() } }} role="button" aria-label={value ? "更换图片" : placeholder} > {value ? ( <> 已上传图片
更换图片
) : (
{uploading ? "上传中..." : placeholder}
)} {uploading && (
)}
{value && !isDisabled && ( )}
) }