<!--
 * @Author: zhaojinfeng 121016171@qq.com
 * @Date: 2023-07-21 00:37:46
 * @LastEditors: zhaojinfeng 121016171@qq.com
 * @LastEditTime: 2023-07-21 03:31:04
 * @FilePath: \vue3\packages\upload-single-file\index.vue
 * @Description:
 *
-->
<template>
  <div v-loading="loading" @click="startUpload">
    <slot :loading="loading">
      <el-button type="primary" plain :text="text">
        点击上传
      </el-button>
    </slot>
  </div>
</template>

<script lang="ts" setup name="ThUploadSingleFile">
const props = withDefaults(defineProps<{
  /** 文件id */
  modelValue?: string | number
  /** 自动上传 */
  autoUpload?: boolean
  /** 可接受的文件类型 */
  accept?: string
  disabled?: boolean
  /** 激活默认按钮的text属性 */
  text?: boolean
  /** 文件上传的请求函数 */
  request?: (formData: FormData) => Promise<FileVO>
  /** 自定义的上传文件名称，不带后缀名 */
  fileName?: string
  /** 最大上传大小，单位Mb */
  maxsize?: number
}>(), {
  modelValue: '',
  autoUpload: false,
  accept: '',
  disabled: false,
  maxsize: 20,
  text: false,
  request: () => {
    throw new Error('请定义接口请求函数')
  },
})

const emit = defineEmits<{
  (event: 'update:modelValue', id?: number): void
  (event: 'onChange', file: File): void
  (event: 'onSuccess', file: FileVO): void
  (event: 'onError', error: Error): void
}>()

let loading = $ref(false)

const { open, files, onChange } = useFileDialog({
  accept: props.accept,
  reset: true,
})
function startUpload() {
  if (!props.disabled)
    open()
}

async function upload() {
  const file = files.value?.item(0)
  if (!file) {
    const err = '请选择上传文件'
    ElMessage.error(err)
    emit('onError', new Error(err))
    return
  }
  if (file.size > props.maxsize * 1024 * 1024) {
    const err = `文件大小不能超过${props.maxsize}Mb`
    ElMessage.error(err)
    emit('onError', new Error(err))
    return
  }
  loading = true
  try {
    const formData = new FormData()
    formData.append('file', file)
    if (props.fileName)
      formData.append('name', props.fileName)

    const res = await props.request(formData)
    emit('update:modelValue', res.id)
    emit('onSuccess', res)
  }
  catch (err: any) {
    emit('onError', err)
  }
  finally {
    loading = false
  }
}

onChange((param) => {
  const file = param.item(0)
  emit('onChange', file)
  if (props.autoUpload)
    upload()
})

watch(() => props.autoUpload,
  (autoupload) => {
    if (autoupload)
      upload()
  })
</script>
