// src/views/AgentChat/hooks/useFileUpload.ts // 文件上传 Hook - 处理文件选择、预览、删除 import { useState, useRef } from 'react'; import type { ChangeEvent, RefObject } from 'react'; /** * 上传文件数据结构 */ export interface UploadedFile { /** 文件名 */ name: string; /** 文件大小(字节) */ size: number; /** 文件 MIME 类型 */ type: string; /** 文件预览 URL(使用 URL.createObjectURL 创建) */ url: string; } /** * useFileUpload Hook 返回值 */ export interface UseFileUploadReturn { /** 已上传文件列表 */ uploadedFiles: UploadedFile[]; /** 文件输入框引用(用于触发文件选择) */ fileInputRef: RefObject; /** 处理文件选择事件 */ handleFileSelect: (event: ChangeEvent) => void; /** 删除指定文件 */ removeFile: (index: number) => void; /** 清空所有文件 */ clearFiles: () => void; } /** * useFileUpload Hook * * 处理文件上传相关逻辑(选择、预览、删除) * * @returns UseFileUploadReturn * * @example * ```tsx * const { uploadedFiles, fileInputRef, handleFileSelect, removeFile } = useFileUpload(); * * return ( * <> * * * {uploadedFiles.map((file, idx) => ( * * {file.name} * removeFile(idx)} /> * * ))} * * ); * ``` */ export const useFileUpload = (): UseFileUploadReturn => { const [uploadedFiles, setUploadedFiles] = useState([]); const fileInputRef = useRef(null); /** * 处理文件选择事件 */ const handleFileSelect = (event: ChangeEvent) => { const files = Array.from(event.target.files || []); const fileData: UploadedFile[] = files.map((file) => ({ name: file.name, size: file.size, type: file.type, // 创建本地预览 URL(实际上传时需要转换为 base64 或上传到服务器) url: URL.createObjectURL(file), })); setUploadedFiles((prev) => [...prev, ...fileData]); // 清空 input value,允许重复选择同一文件 if (event.target) { event.target.value = ''; } }; /** * 删除指定索引的文件 */ const removeFile = (index: number) => { setUploadedFiles((prev) => { // 释放 URL.createObjectURL 创建的内存 const file = prev[index]; if (file?.url) { URL.revokeObjectURL(file.url); } return prev.filter((_, i) => i !== index); }); }; /** * 清空所有文件 */ const clearFiles = () => { // 释放所有 URL 内存 uploadedFiles.forEach((file) => { if (file.url) { URL.revokeObjectURL(file.url); } }); setUploadedFiles([]); }; return { uploadedFiles, fileInputRef, handleFileSelect, removeFile, clearFiles, }; };