< ! -- 属性1 . multiple多选2 . action上传文件服务器地址3 . before-upload上传前校检格式和大小4 . file-list上传的文件列表5 . limit数量限制6 . on-error上传失败触发7 . on-exceed文件个数超出触发8 . on-success上传成功触发9 . show-file-list是否显示已上传文件列表( 我这块点击文件名要展示文件,所以自定义了一个文件列表,加了触发事件) 10 .headers 设置上传的请求头部--> 
< template> < div class = "upload-file" > < el-upload multiple :action= "uploadFileUrl"  :before-upload= "handleBeforeUpload"  :file-list= "fileList"  :limit= "limit" :on-error= "handleUploadError"  :on-exceed= "handleExceed"  :on-success= "handleUploadSuccess"  :show-file-list= "false" :headers= "headers"  class = "upload-file-uploader"  ref = "fileUpload" > < ! -- 上传按钮 --> < el-button type = "primary" > 选取文件< /el-button> < /el-upload> < ! -- 上传提示 --> < div class = "el-upload__tip"  v-if= "showTip" > 请上传< template v-if= "fileSize" >  大小不超过 < b style = "color: #f56c6c" > { {  fileSize } } MB< /b>  < /template> < template v-if= "fileType" >  格式为 < b class = "auto-wrap" > { {  fileType.join( "/" )  } } < /b>  < /template> 的文件< /div> < ! -- 文件列表 --> < transition-group class = "upload-file-list el-upload-list el-upload-list--text"  name = "el-fade-in-linear"  tag = "ul" > < li :key= "file.uid"  class = "el-upload-list__item ele-upload-list__item-content"  v-for= "(file, index) in fileList" > < ! -- 打开新窗口预览文件 --> < el-link :href= "` ${ baseUrl} ${ file.url} `   :underline= "false"  target = "_blank" > < span class = "el-icon-document" >  { {  file.name } }  < /span> < /el-link> < div class = "ele-upload-list__item-content-action" > < el-link :underline= "false"  @click= "handleDelete(index)"  type = "danger" > 删除< /el-link> < /div> < /li> < /transition-group> < /div> 
< /template> < script setup> 
import  {  getToken }  from "@/utils/auth" ; const props =  defineProps( { modelValue: [ String, Object, Array] , //默认文件列表数据// 数量限制limit: { type: Number,default: 5 ,} ,// 大小限制( MB) fileSize: { type: Number,default: 500 ,} ,// 文件类型, 例如[ 'png' , 'jpg' , 'jpeg' ] fileType: { type: Array,default: ( )  = >  [ "doc" , "xls" , "ppt" , "txt" , "pdf" ] ,} ,// 是否显示提示isShowTip: { type: Boolean,default: true } 
} ) ; const {  proxy }  =  getCurrentInstance( ) ; 
const emit =  defineEmits( ) ; 
const number =  ref( 0 ) ;  // 只要通过上传校验就给number+1;上传成功一个-1个,都上传成功后重置为0
const uploadList =  ref( [ ] ) ; 
const baseUrl =  import.meta.env.VITE_APP_BASE_API;  //访问的文件前缀
const uploadFileUrl =  ref( import.meta.env.VITE_APP_BASE_API + "/common/upload4model" ) ;  // 上传文件服务器地址
const headers =  ref( {  Authorization: "Bearer "  + getToken( )  } ) ; 
const fileList =  ref( [ ] ) ; 
const showTip =  computed( ( )  = >  props.isShowTip &&  ( props.fileType ||  props.fileSize) 
) ; watch(( )  = >  props.modelValue, val = >  { if  ( val)  { let  temp =  1 ; // 首先将值转为数组const list =  Array.isArray( val)  ? val :  props.modelValue.split( ',' ) ; // 然后将数组转为对象数组fileList.value =  list.map( item = >  { if  ( typeof item == =  "string" )  { item =  {  name: item, url: item } ; } if  ( ! item.url)  { item.url =  baseUrl + item.fileName; } item.uid =  item.uid ||  new Date( ) .getTime( )  + temp++; return  item; } ) ; }  else  { fileList.value =  [ ] ; return  [ ] ; } 
} , {  deep: true, immediate: true  } ) ; // 上传前校检格式和大小
function  handleBeforeUpload( file)  { // 校检文件类型if  ( props.fileType.length)  { const fileName =  file.name.split( '.' ) ; const fileExt =  fileName[ fileName.length - 1 ] ; const isTypeOk =  props.fileType.indexOf( fileExt)  >=  0 ; if  ( ! isTypeOk)  { proxy.$modal .msgError( ` 文件格式不正确, 请上传${ props.fileType.join( "/" ) } 格式文件! ` ) ; return  false ; } } // 校检文件大小if  ( props.fileSize)  { const isLt =  file.size / 1024  / 1024  <  props.fileSize; if  ( ! isLt)  { proxy.$modal .msgError( ` 上传文件大小不能超过 ${ props.fileSize}  MB! ` ) ; return  false ; } } // proxy.$modal .loading( "正在上传文件,请稍候..." ) ; number.value++; return  true ; 
} // 文件个数超出
function  handleExceed ( )  { proxy.$modal .msgError( ` 上传文件数量不能超过${ props.limit} 个!` ) ; 
} // 上传失败
function  handleUploadError( err)  { proxy.$modal .msgError( "上传文件失败" ) ; 
} // 上传成功回调
function  handleUploadSuccess( res, file )  { if  ( res.code == =  200 )  { uploadList.value.push( res) ; uploadedSuccessfully( ) ; }  else  { number.value--; // proxy.$modal .closeLoading( ) ; proxy.$modal .msgError( res.msg) ; proxy.$refs .fileUpload.handleRemove( file) ;  // 上传失败时手动触发组件的外部方法handleRemoveuploadedSuccessfully( ) ; } 
} // 删除文件
function  handleDelete( index)  { fileList.value.splice( index, 1 ) ; emit( "update:modelValue" , fileList.value) ;  // 删除文件后更新父组件文件列表
} // 上传结束处理
function  uploadedSuccessfully ( )  { if  ( number.value >  0  &&  uploadList.value.length == =  number.value)  { fileList.value =  fileList.value.filter( f = >  f.url != =  undefined) .concat( uploadList.value) ; uploadList.value =  [ ] ; number.value =  0 ; emit( "update:modelValue" , fileList.value) ;  //更新父组件文件列表fileList数据// proxy.$modal .closeLoading( ) ; } 
} < /script> < style scoped lang = "scss" > 
.upload-file-uploader { margin-bottom: 5px; 
} .upload-file-list .el-upload-list__item { border: 1px solid line-height: 2 ; margin-bottom: 10px; position: relative; 
} .upload-file-list .ele-upload-list__item-content { display: flex; justify-content: space-between; align-items: center; color: inherit; 
} .ele-upload-list__item-content-action .el-link { margin-right: 10px; 
} .auto-wrap { width: 100 %; word-wrap: break-word; /* 旧版本浏览器支持 */overflow-wrap: break-word; /* 标准属性 */word-break: break-all; color: 
} 
< /style> 
< ! -- 1 . modelValue对应的文件列表数据2 . limit限制文件上传数量3 . fileType限制上传的文件类型4 . @update:modelValue更新文件列表数据
--> 
< FileUpload :modelValue= "form.attachmentList"  @update:modelValue= "fileUploadInput" :fileType= "fileType[form.dataType]"  :limit= "form.dataType == 2 ? 20 : 1" > < /FileUpload>