| 
					
				 | 
			
			
				@@ -0,0 +1,170 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  <el-upload 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ref="uploadRef" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    class="upload-demo" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :action="uploadUrl" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :headers="headers" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :data="extraData" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :multiple="multiple" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :limit="limit" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :accept="accept" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :show-file-list="showFileList" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :before-upload="beforeUpload" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :on-success="handleSuccess" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :on-error="handleError" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :on-exceed="handleExceed" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :on-change="handleChange" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :auto-upload="autoUpload" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :disabled="disabled" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <el-button :type="buttonType" :icon="buttonIcon" :size="buttonSize" :loading="loading"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      {{ buttonText }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </el-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <template #tip v-if="showTip"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <div class="el-upload__tip"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        {{ tipText || `请上传${accept ? accept.replace(/\*/g, '') : ''}格式文件,且不超过${fileSize}MB` }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  </el-upload> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<script setup lang="ts"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ref } from 'vue' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ElMessage } from 'element-plus' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+interface Props { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uploadUrl: string // 上传地址(必填) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  headers?: Record<string, string> // 请求头 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  extraData?: Record<string, any> // 额外参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  multiple?: boolean // 是否支持多选文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  limit?: number // 最大允许上传个数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  accept?: string // 接受上传的文件类型 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fileSize?: number // 文件大小限制(MB) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showFileList?: boolean // 是否显示已上传文件列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  autoUpload?: boolean // 是否自动上传 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  disabled?: boolean // 是否禁用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonText?: string // 按钮文字 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonType?: string // 按钮类型 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonIcon?: string // 按钮图标 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonSize?: string // 按钮尺寸 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showTip?: boolean // 是否显示提示文字 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tipText?: string // 自定义提示文字 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isHandleSuccess?: boolean // 是否处理成功回调 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isHandleError?: boolean // 是否处理错误回调 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const props = withDefaults(defineProps<Props>(), { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uploadUrl: '/file/upload', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  multiple: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  limit: 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fileSize: 10, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showFileList: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  autoUpload: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  disabled: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonText: '上传文件', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonType: 'primary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  buttonSize: 'default', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showTip: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isHandleSuccess: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isHandleError: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const emit = defineEmits(['success', 'error', 'change', 'exceed']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uploadRef = ref<UploadInstance>() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const loading = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 上传前校验 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (props.accept) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const fileType = rawFile.type 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const acceptTypes = props.accept.split(',') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const isValidType = acceptTypes.some(type => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (type.startsWith('.')) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return rawFile.name.toLowerCase().endsWith(type.toLowerCase()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return fileType.includes(type.replace(/\*/g, '')) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!isValidType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ElMessage.error(`只能上传${props.accept}格式的文件!`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (props.fileSize) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const isLtSize = rawFile.size / 1024 / 1024 < props.fileSize 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!isLtSize) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ElMessage.error(`文件大小不能超过${props.fileSize}MB!`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 文件上传成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleSuccess: UploadProps['onSuccess'] = (response, uploadFile, uploadFiles) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  loading.value = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (props.isHandleSuccess) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.success('上传成功') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  emit('success', { response, uploadFile, uploadFiles }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 文件上传失败 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleError: UploadProps['onError'] = (error, uploadFile, uploadFiles) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  loading.value = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (props.isHandleError) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.error('上传失败') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  emit('error', { error, uploadFile, uploadFiles }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 文件状态改变 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  loading.value = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  emit('change', { uploadFile, uploadFiles }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 文件超出个数限制 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.warning(`最多只能上传${props.limit}个文件`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  emit('exceed', { files, uploadFiles }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 手动上传 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const submitUpload = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uploadRef.value?.submit() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 清空已上传文件列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const clearFiles = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uploadRef.value?.clearFiles() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 手动触发文件选择 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleClick = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uploadRef.value?.$el.querySelector('.el-upload__input')?.click() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 暴露方法给父组件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+defineExpose({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  submitUpload, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  clearFiles, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  handleClick 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<style scoped> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.upload-demo { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: inline-block; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.el-upload__tip { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-top: 8px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-size: 12px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: var(--el-text-color-secondary); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</style> 
			 |