import { get, defaults, findIndex } from 'lodash-es'; import { ref } from 'vue'; import { ElMessage } from 'element-plus'; type keyPath = Array<string> | string; type uOptions = { limit: number }; export function useUpload<T>( uApi: (params: any, formData: any) => Promise<T>, dApi?: (id: string) => Promise<T>, uOptions?: uOptions, uParams: object | (() => object) = {}, // format: (data: { fileName: string; suffix: string }) => fFIle, options: { path?: { data?: keyPath }; } = {} ) { defaults(options, { path: { data: 'data.result', }, immediate: false, }); // defaults(format, (data: bFile) => { // return { ...data, name: `${data.fileName}${data.suffix}`, type: 'image' }; // }); // 统一数据格式 const format = (data: any): any => { const type = getFileType(data.suffix); return { ...data, name: `${data.fileName}${data.suffix}`, type }; }; const getFileType = (suffix: string) => { const suffixType: any = { '.jpg': 'image', '.jpeg': 'image', '.bmp': 'image', '.png': 'image', '.webp': 'image', '.mp4': 'video', '.webm': 'video', '.mp3': 'audio', }; return suffixType[suffix]; }; let uFileList = ref<any>([]); // 初始化文件列表 const initFileList = (fileList: Array<any> = []) => { fileList = fileList || []; uFileList.value = fileList.map((file) => format(file)); }; // 文件上传 const onChange = async (uploadFile: any) => { const requestData = {}; if (uParams) { if (typeof uParams === 'function') { Object.assign(requestData, uParams()); } else { Object.assign(requestData, uParams); } } const uid = uploadFile.uid; let formData = new FormData(); formData.append('files', uploadFile.raw); try { const res = await uApi(requestData, formData); const result = get(res, options!.path?.data, []); if (!result) return; // 没有返回数据就不更新本地文件列表 // 上传成功文件用新数据更新文件列表 const curIndex = findIndex(uFileList.value, function (o: { uid: string }) { return o.uid == uid; }); uFileList.value.splice(curIndex, 1, format(result[0])); } catch (error: any) { // 上传不成功移除文件 const curIndex = findIndex(uFileList.value, function (o: { uid: string }) { return o.uid == uid; }); uFileList.value.splice(curIndex, 1); } }; // 文件移除 const onRemove = async (file: { id: string }) => { if (!dApi) return; await dApi(file.id); }; // 文件异常处理 const onExceed = (files: any, uploadFiles: any) => { const total = files.length + uploadFiles.length; if (total > uOptions.limit) { ElMessage.error(`最多只能上传 ${uOptions.limit} 个文件,请删除后再上传!`); } }; return { fileList: uFileList, initFileList, onChange, onRemove, onExceed }; }