UNPKG

element-plus

Version:

A Component Library for Vue3.0

154 lines (135 loc) 3.92 kB
import { ref, watch } from 'vue' import { NOOP } from '@vue/shared' // Inline types import type { ListType, UploadFile, ElFile, ElUploadProgressEvent, IUseHandlersProps } from './upload.type' type UploadRef = { abort: (file: UploadFile) => void upload: (file: ElFile) => void } // helpers function getFile(rawFile: ElFile, uploadFiles: UploadFile[]) { return uploadFiles.find(file => file.uid === rawFile.uid) } function genUid(seed: number) { return Date.now() + seed } export default (props: IUseHandlersProps) => { const uploadFiles = ref<UploadFile[]>([]) const uploadRef = ref<UploadRef>(null) let tempIndex = 1 function abort(file: UploadFile) { uploadRef.value.abort(file) } function clearFiles() { uploadFiles.value = [] } function handleError(err: Error, rawFile: ElFile) { const file = getFile(rawFile, uploadFiles.value) file.status = 'fail' uploadFiles.value.splice(uploadFiles.value.indexOf(file), 1) props.onError(err, file, uploadFiles.value) props.onChange(file, uploadFiles.value) } function handleProgress(ev: ElUploadProgressEvent, rawFile: ElFile) { const file = getFile(rawFile, uploadFiles.value) props.onProgress(ev, file, uploadFiles.value) file.status = 'uploading' file.percentage = ev.percent || 0 } function handleSuccess(res: any, rawFile: ElFile) { const file = getFile(rawFile, uploadFiles.value) if (file) { file.status = 'success' file.response = res props.onSuccess(res, file, uploadFiles.value) props.onChange(file, uploadFiles.value) } } function handleStart(rawFile: ElFile) { const uid = genUid(tempIndex++) rawFile.uid = uid const file: UploadFile = { name: rawFile.name, percentage: 0, status: 'ready', size: rawFile.size, raw: rawFile, uid, } if (props.listType === 'picture-card' || props.listType === 'picture') { try { file.url = URL.createObjectURL(rawFile) } catch (err) { console.error('[Element Error][Upload]', err) props.onError(err, file, uploadFiles.value) } } uploadFiles.value.push(file) props.onChange(file, uploadFiles.value) } function handleRemove(file: UploadFile, raw: ElFile) { if (raw) { file = getFile(raw, uploadFiles.value) } const doRemove = () => { abort(file) const fileList = uploadFiles.value fileList.splice(fileList.indexOf(file), 1) props.onRemove(file, fileList) } if (!props.beforeRemove) { doRemove() } else if (typeof props.beforeRemove === 'function') { const before = props.beforeRemove(file, uploadFiles.value) if (before instanceof Promise) { before.then(() => { doRemove() }).catch(NOOP) } else if (before !== false) { doRemove() } } } function submit() { uploadFiles.value .filter(file => file.status === 'ready') .forEach(file => { uploadRef.value.upload(file.raw) }) } watch(() => props.listType, (val: ListType) => { if (val === 'picture-card' || val === 'picture') { uploadFiles.value = uploadFiles.value.map(file => { if (!file.url && file.raw) { try { file.url = URL.createObjectURL(file.raw) } catch (err) { props.onError(err, file, uploadFiles.value) } } return file }) } }) watch(() => props.fileList, (fileList: UploadFile[]) => { uploadFiles.value = fileList.map(file => { file.uid = file.uid || genUid(tempIndex++) file.status = file.status || 'success' return file }) }, { immediate: true, deep: true, }) return { clearFiles, handleError, handleProgress, handleStart, handleSuccess, handleRemove, submit, uploadFiles, uploadRef, } }