Files
vue3/packages/upload-list/index.vue
2023-09-15 12:54:39 +08:00

136 lines
3.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
* @Author: zhaojinfeng 121016171@qq.com
* @Date: 2023-08-16 17:33:41
* @LastEditors: Hefeng 1057605508@qq.com
* @LastEditTime: 2023-09-15 12:51:29
* @FilePath: \th-components-vue3\packages\upload-list\index.vue
* @Description:
*
-->
<template>
<el-upload
v-model:file-list="userFiles"
:class="{ 'user-files': listType === 'picture-card' && userFiles.length >= limit }"
:accept="accept"
:disabled="disabled"
:before-upload="beforeUpload"
:http-request="httpRequest"
:list-type="listType"
:limit="limit"
@preview="preview"
@success="success"
@remove="remove"
>
<slot>
<el-icon v-if="listType === 'picture-card'">
<Plus />
</el-icon>
<el-button v-if="listType !== 'picture-card' && userFiles.length < limit" type="primary" plain :disabled="disabled">
点击上传
</el-button>
</slot>
</el-upload>
</template>
<script lang="ts" setup name="ThUploadList">
import { Plus } from '@element-plus/icons-vue'
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
/** 文件列表的类型 */
listType?: 'text' | 'picture' | 'picture-card'
/** 允许上传文件的最大数量 */
limit?: number
}>(), {
fileList: () => [],
maxsize: 100,
limit: Infinity,
},
)
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>
<style>
.user-files .el-upload--picture-card{
display: none;
}
</style>