memowake-front/components/file-upload/upload-dropzone.tsx
2025-06-26 15:12:34 +08:00

78 lines
2.6 KiB
TypeScript

import SvgIcon from "@/components/svg-icon";
import { useTranslation } from "react-i18next";
import { DEFAULT_ALLOWED_FILE_TYPES, DEFAULT_MAX_FILE_SIZE } from "./file-uploader";
interface UploadDropzoneProps {
onClick: () => void;
disabled?: boolean;
allowedFileTypes?: string[];
maxFileSize?: number;
}
/**
* 上传区域组件 - 用于显示文件拖放和选择区域
*/
export default function UploadDropzone({
onClick,
disabled = false,
allowedFileTypes = DEFAULT_ALLOWED_FILE_TYPES,
maxFileSize = DEFAULT_MAX_FILE_SIZE
}: UploadDropzoneProps) {
const { t } = useTranslation();
// 格式化文件类型显示
const formatFileTypes = (types: string[]): string => {
return types.map(type => {
// 从 MIME 类型提取文件扩展名
const extensions: Record<string, string> = {
'video/mp4': 'MP4',
'video/quicktime': 'MOV',
'video/x-msvideo': 'AVI',
'video/x-matroska': 'MKV',
'image/jpeg': 'JPG',
'image/png': 'PNG',
'image/gif': 'GIF',
'image/webp': 'WEBP'
};
return extensions[type] || type.split('/')[1]?.toUpperCase() || type;
}).join(', ');
};
// 格式化文件大小显示
const formatFileSize = (bytes: number): string => {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
};
return (
<div
className={`border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-all
${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-primary/50'} h-full`}
onClick={disabled ? undefined : onClick}
>
<div className="flex flex-col items-center justify-center gap-3 h-full">
<div className="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center">
<SvgIcon name="upload" className="h-6 w-6 text-gray-500" />
</div>
<div>
<h3 className="text-base font-medium text-gray-900">
{t('fileUploader.dragAndDropFiles')}
</h3>
<p className="mt-1 text-sm text-gray-500">
{t('fileUploader.orClickToUpload')}
</p>
<p className="mt-1 text-xs text-gray-500">
{t('fileUploader.supportedFormats')}: {formatFileTypes(allowedFileTypes)}
</p>
<p className="text-xs text-gray-500">
{t('fileUploader.maxFileSize')}: {formatFileSize(maxFileSize)}
</p>
</div>
</div>
</div>
);
}