mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
* docs: [el-upload]add example of seting on-exceed to cover the old file * Update packages/components/upload/src/useHandlers.ts Co-authored-by: btea <2356281422@qq.com> * Update docs/examples/upload/limit-cover.vue Co-authored-by: btea <2356281422@qq.com> Co-authored-by: btea <2356281422@qq.com>
182 lines
4.4 KiB
TypeScript
182 lines
4.4 KiB
TypeScript
import { ref, watch } from 'vue'
|
|
import { NOOP } from '@vue/shared'
|
|
import cloneDeep from 'lodash/cloneDeep'
|
|
|
|
// Inline types
|
|
import type {
|
|
ListType,
|
|
UploadFile,
|
|
UploadStatus,
|
|
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(
|
|
status: UploadStatus[] = ['ready', 'uploading', 'success', 'fail']
|
|
) {
|
|
uploadFiles.value = uploadFiles.value.filter((row) => {
|
|
return !status.includes(row.status)
|
|
})
|
|
}
|
|
|
|
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 revokeObjectURL = () => {
|
|
if (file.url && file.url.indexOf('blob:') === 0) {
|
|
URL.revokeObjectURL(file.url)
|
|
}
|
|
}
|
|
const doRemove = () => {
|
|
abort(file)
|
|
const fileList = uploadFiles.value
|
|
fileList.splice(fileList.indexOf(file), 1)
|
|
props.onRemove(file, fileList)
|
|
revokeObjectURL()
|
|
}
|
|
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) => {
|
|
const cloneFile = cloneDeep(file)
|
|
return {
|
|
...cloneFile,
|
|
uid: file.uid || genUid(tempIndex++),
|
|
status: file.status || 'success',
|
|
}
|
|
})
|
|
},
|
|
{
|
|
immediate: true,
|
|
deep: true,
|
|
}
|
|
)
|
|
|
|
return {
|
|
abort,
|
|
clearFiles,
|
|
handleError,
|
|
handleProgress,
|
|
handleStart,
|
|
handleSuccess,
|
|
handleRemove,
|
|
submit,
|
|
uploadFiles,
|
|
uploadRef,
|
|
}
|
|
}
|