118 lines
3.0 KiB
Vue
118 lines
3.0 KiB
Vue
<!--
|
||
* @Author: zhaojinfeng 121016171@qq.com
|
||
* @Date: 2023-08-16 17:33:41
|
||
* @LastEditors: peerless_hero peerless_hero@outlook.com
|
||
* @LastEditTime: 2023-08-30 15:24:13
|
||
* @FilePath: \vue3\packages\upload-list\index.vue
|
||
* @Description:
|
||
*
|
||
-->
|
||
<template>
|
||
<el-upload
|
||
v-model:file-list="userFiles"
|
||
:accept="accept"
|
||
:disabled="disabled"
|
||
:before-upload="beforeUpload"
|
||
:http-request="httpRequest"
|
||
@preview="preview"
|
||
@success="success"
|
||
@remove="remove"
|
||
>
|
||
<slot>
|
||
<el-button type="primary" plain :disabled="disabled">
|
||
点击上传
|
||
</el-button>
|
||
</slot>
|
||
</el-upload>
|
||
</template>
|
||
|
||
<script lang="ts" setup name="ThUploadList">
|
||
import type { UploadFile, UploadFiles, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
|
||
|
||
const props = withDefaults(
|
||
defineProps<{
|
||
/** 可上传的文件类型 */
|
||
accept?: string
|
||
/** 文件集合 */
|
||
fileList?: FileVO[]
|
||
/** 文件上传的请求函数 */
|
||
request: (formData: FormData, args?: any) => Promise<FileVO>
|
||
/** 自定义文件上传路径前缀 */
|
||
filePath?: string
|
||
/** 禁用组件 */
|
||
disabled?: boolean
|
||
/** 最大上传大小(Mb) */
|
||
maxsize?: number
|
||
}>(), {
|
||
fileList: () => [],
|
||
maxsize: 100,
|
||
},
|
||
)
|
||
|
||
const emit = defineEmits<{
|
||
(event: 'update:file-list', file: FileVO[]): void
|
||
(event: 'preview', file: UploadFile): void
|
||
}>()
|
||
|
||
const userFiles = ref<UploadUserFile[]>([])
|
||
|
||
function beforeUpload(rawFile: UploadRawFile) {
|
||
if (rawFile.size > props.maxsize * 1024 * 1024) {
|
||
const err = `文件大小不能超过${props.maxsize}Mb`
|
||
ElMessage.error(err)
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
async function httpRequest({ file, onProgress, onSuccess, onError }: UploadRequestOptions) {
|
||
const formData = new FormData()
|
||
formData.append('file', file)
|
||
if (props.filePath)
|
||
formData.append('filePath', props.filePath)
|
||
try {
|
||
const res = await props.request(formData, {
|
||
onUploadProgress(e: ProgressEvent) {
|
||
onProgress({ ...e, percent: Math.floor(e.loaded * 100 / e.total) })
|
||
},
|
||
})
|
||
onSuccess(res)
|
||
}
|
||
catch (err) {
|
||
onError(err)
|
||
}
|
||
}
|
||
|
||
function preview(uploadFile: UploadFile) {
|
||
emit('preview', uploadFile)
|
||
}
|
||
|
||
const { pause, resume } = watchPausable(
|
||
() => props.fileList, (fileList) => {
|
||
userFiles.value = fileList.map(file => ({
|
||
...file,
|
||
status: 'success',
|
||
percentage: 100,
|
||
uid: file.id,
|
||
}))
|
||
},
|
||
{ immediate: true },
|
||
)
|
||
|
||
function success(response: FileVO, uploadFile: UploadFile, uploadFiles: UploadFiles) {
|
||
// 将返回响应合并到文件上
|
||
Object.assign(uploadFile, response)
|
||
// 手动更新,暂停监听,避免因props.fileList更新再次更新uploadFile
|
||
pause()
|
||
emit('update:file-list', uploadFiles)
|
||
resume()
|
||
}
|
||
|
||
function remove(_uploadFile: UploadFile, uploadFiles: UploadFiles) {
|
||
userFiles.value = uploadFiles
|
||
// 手动更新,暂停监听,避免因props.fileList更新再次更新uploadFile
|
||
pause()
|
||
emit('update:file-list', uploadFiles)
|
||
resume()
|
||
}
|
||
</script>
|