| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- <script setup lang="ts">
- import { ref, watch } from 'vue'
- import { Plus, Upload } from '@element-plus/icons-vue'
- import { ElButton, ElUpload, } from 'element-plus'
- import type {UploadProgressEvent, UploadFile, UploadFiles } from 'element-plus'
- import { toast } from 'vue-sonner'
- import { BASE_URL } from '@/api/index'
- const props = withDefaults(defineProps<{
- modelValue?: UploadFile | null | undefined
- action?: string
- method?: string
- headers?: Headers | Record<string, any>
- data?: Record<string, any>
- name?: string
- afterUpload?: (response: any) => string | Promise<string>
- multiple?: boolean
- ext?: string[]
- max?: number
- width?: number
- height?: number
- dimension?: {
- width: number
- height: number
- }
- size?: number
- hideTips?: boolean
- disabled?: boolean
- }>(), {
- method: 'post',
- headers: () => {
- const userStore = useUserStore()
- if (userStore.isLogin) {
- return {
- accessToken: userStore.token
- }
- }
- return {}
- },
- data: () => ({}),
- name: 'file',
- multiple: false,
- ext: () => [],
- max: 1,
- width: 100,
- height: 100,
- size: 5 * 1024 * 1024,
- hideTips: false,
- disabled: false,
- })
- const emit = defineEmits<{
- // 上传成功时 emit 事件
- 'success': [response: any, file: UploadFile, fileList: UploadFiles]
- // 更新 v-model: 必须命名为 'update:modelValue' 以支持 v-model
- 'update:modelValue': [value: UploadFile | null]
- }>()
- const internalFileList = ref<UploadFiles>(props.modelValue ? [props.modelValue] : [])
- watch(
- () => props.modelValue,
- (newVal) => {
- // 如果父组件的 modelValue 变为 null/undefined,清空内部列表
- if (!newVal) {
- internalFileList.value = []
- } else {
- // 如果有新值,更新(避免重复添加)
- if (internalFileList.value[0]?.uid !== newVal.uid) {
- internalFileList.value = [newVal]
- }
- }
- }
- )
- const loading = ref(false)
- function handleUploadSuccess(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) {
- console.log('【上传成功】响应:', response)
- console.log('【上传成功】文件对象:', uploadFile) // 这是最新的文件对象 (包含 url 等)
- loading.value = false
- emit('update:modelValue', uploadFile)
- // 7. 触发成功事件
- emit('success', response, uploadFile, uploadFiles)
- }
- // 8. 上传失败的回调
- function handleUploadError(error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) {
- console.error('【上传失败】:', error, uploadFile)
- emit('update:modelValue', null) // 失败时也通知父组件
- toast.error('文件上传失败')
- }
- function handleProgress (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) {
- loading.value = true
- console.log(evt, uploadFile, uploadFiles)
- }
- // 添加文件选择变化的处理
- function handleFileChange(file: UploadFile, fileList: UploadFiles) {
- console.log(file, fileList)
- // 当有新文件被选择时,清空现有列表,允许新文件上传
- if (file.status === 'success') {
- internalFileList.value = [];
- }
- }
- </script>
- <template>
- <ElUpload
- v-model:file-list="internalFileList"
- :action="`${BASE_URL}/anycall/import`"
- :show-file-list="false"
- :limit="1"
- :headers="props.headers"
- @success="handleUploadSuccess"
- @progress="handleProgress"
- @change="handleFileChange"
- @error="handleUploadError"
- :auto-upload="true"
- >
- <ElButton :loading="loading" type="primary" :icon="Upload">Import</ElButton>
- </ElUpload>
- </template>
|