import { env } from "@web/src/env"; import { message, Progress, Spin, theme } from "antd"; import React, { useState, useEffect, useRef } from "react"; import { useTusUpload } from "@web/src/hooks/useTusUpload"; export interface AvatarUploaderProps { value?: string; placeholder?: string; className?: string; onChange?: (value: string) => void; style?: React.CSSProperties; // 添加style属性 } interface UploadingFile { name: string; progress: number; status: "uploading" | "done" | "error"; fileId?: string; fileKey?: string; } const AvatarUploader: React.FC = ({ value, onChange, className, placeholder = "点击上传", style, // 解构style属性 }) => { const { handleFileUpload, uploadProgress } = useTusUpload(); const [file, setFile] = useState(null); const [previewUrl, setPreviewUrl] = useState(value || ""); const [uploading, setUploading] = useState(false); const inputRef = useRef(null); const { token } = theme.useToken(); const handleChange = async (event: React.ChangeEvent) => { const selectedFile = event.target.files?.[0]; if (!selectedFile) return; setFile({ name: selectedFile.name, progress: 0, status: "uploading", fileKey: `${selectedFile.name}-${Date.now()}`, }); setUploading(true); try { const fileId = await new Promise((resolve, reject) => { handleFileUpload( selectedFile, (result) => { setFile((prev) => ({ ...prev!, progress: 100, status: "done", fileId: result.fileId, })); resolve(result.fileId); }, (error) => { reject(error); }, file?.fileKey ); }); setPreviewUrl(`${env.SERVER_IP}/uploads/${fileId}`); onChange?.(fileId); message.success("头像上传成功"); } catch (error) { console.error("上传错误:", error); message.error("头像上传失败"); setFile((prev) => ({ ...prev!, status: "error" })); } finally { setUploading(false); } }; const triggerUpload = () => { inputRef.current?.click(); }; return (
{previewUrl ? ( Avatar ) : (
{placeholder}
)} {uploading && (
)} {file && file.status === "uploading" && (
)}
); }; export default AvatarUploader;