<!--
 * @Author: zhaojinfeng 121016171@qq.com
 * @Date: 2023-07-21 01:21:34
 * @LastEditors: zhaojinfeng 121016171@qq.com
 * @LastEditTime: 2023-07-23 01:34:25
 * @FilePath: \vue3\packages\download-link\index.vue
 * @Description: 现在组件
 *
-->
<template>
  <el-link v-loading="loading" :href="url" :type="type" :download="url && fileName" target="_blank">
    <slot>
      {{ fileName }}
    </slot>
  </el-link>
</template>

<script lang="ts" setup name="ThDownloadLink">
const props = withDefaults(defineProps<{
  fileName?: string
  /**
   * 下载文件的请求源
   *
   * 可以是文件名或URL。
   *
   */
  src?: number | string | FileVO
  /** 文件信息请求函数 */
  request?: (...args: any) => Promise<FileVO>
}>(), {
  fileName: '',
  request: () => {
    throw new Error('请定义下载接口的请求函数')
  },
})

let url = $ref('')
let fileName = $ref('')
let loading = $ref(false)

let type = $ref<'success' | 'primary' | 'danger'>('primary')

async function reload(id: string | number) {
  if (url || loading)
    return
  loading = true
  try {
    const res = await props.request(id)
    url = res.url
    fileName = res.name
    type = 'primary'
  }
  catch (error) {
    type = 'danger'
  }
  finally {
    loading = false
  }
}

function init() {
  switch (typeof props.src) {
    case 'string':
      if (props.src.startsWith('http')) {
        url = props.src
        fileName = props.fileName
        break
      }
      reload(props.src)
      break
    case 'number':
      reload(props.src)
      break
    case 'object':
      if (typeof props.src?.url === 'string') {
        url = props.src.url
        fileName = props.src.name
        type = 'success'
      }
      else {
        type = 'danger'
      }
      break
    default:
      break
  }
}

watch(() => props.src, init)

tryOnMounted(init)

tryOnUnmounted(() => {
  if (url.startsWith('blob:')) {
  // revoke object URL after use to avoid memory leak.
    URL.revokeObjectURL(url)
  }
})
</script>
