import { useRef, useState } from 'react'; import { uploadFileToOss, type OssMediaType } from '../lib/upload'; import { enqueueUpload } from '../lib/upload-lock'; import { toastError } from '../lib/toast'; type OssUploadFieldProps = { value?: string; onChange?: (url: string) => void; bizType: string; mediaType?: OssMediaType; accept?: string; wide?: boolean; compact?: boolean; label?: string; }; const DEFAULT_MAX_MB = 10; export default function OssUploadField({ value, onChange, bizType, mediaType = 'IMAGE', accept, wide, compact, label, }: OssUploadFieldProps) { const inputRef = useRef(null); const [uploading, setUploading] = useState(false); const [error, setError] = useState(''); function showUploadError(text: string) { setError(text); toastError(text); } const resolvedAccept = accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? 'image/*,.pdf' : 'image/*'); async function persistUpload(file: File) { if (!file.size) { showUploadError('图片读取失败,请重新选择'); return; } if (file.size > DEFAULT_MAX_MB * 1024 * 1024) { showUploadError(`文件不能超过 ${DEFAULT_MAX_MB}MB`); return; } const result = await uploadFileToOss(file, { bizType, mediaType }); onChange?.(result.url); } async function uploadSelectedFile(file: File) { setUploading(true); setError(''); try { await enqueueUpload(() => persistUpload(file)); } catch (e) { showUploadError(e instanceof Error ? e.message : '上传失败'); } finally { setUploading(false); if (inputRef.current) inputRef.current.value = ''; } } function pickFile() { if (uploading) return; setError(''); inputRef.current?.click(); } const isImage = mediaType === 'IMAGE' && value; const isFile = mediaType === 'FILE' && value; const busy = uploading; const pickerLabel = label ?? (mediaType === 'IMAGE' ? '从系统相册选择' : '点击上传'); const triggerProps = { type: 'button' as const, disabled: busy, onClick: pickFile, }; return (
{ const file = e.target.files?.[0]; if (file) { void uploadSelectedFile(file); } }} /> {isImage ? ( ) : isFile ? ( ) : ( )} {error &&

{error}

}
); }