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

<script lang="ts" setup name="ThDownloadLink">
import { saveAs } from 'file-saver'

const props = withDefaults(defineProps<{
  /**
   * 自定义下载文件名
   *
   */
  fileName?: string
  /**
   * 下载文件的请求源
   *
   * 可以是文件名或URL。
   *
   */
  src?: number | string | FileVO
  /** 下载文件的请求参数的健名 */
  requestKey?: string
  /** 下载文件的请求函数 */
  request?: (...args: any) => Promise<Blob>
}>(), {
  fileName: '文件',
  requestKey: 'fileName',
  request: () => {
    throw new Error('请定义下载接口的请求函数')
  },
})

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

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

async function downloadByRequest(fileName: string | number) {
  if (url || loading)
    return
  loading = true
  try {
    const res = await props.request({ [props.requestKey]: fileName })
    url = URL.createObjectURL(res)
    saveAs(res)
  }
  catch (error) {
    type = 'danger'
  }
  finally {
    type = 'success'
    loading = false
  }
}

function download() {
  switch (typeof props.src) {
    case 'string':
      if (props.src.startsWith('http')) {
        url = props.src
        break
      }
      downloadByRequest(props.src)
      break
    case 'number':
      downloadByRequest(props.src)
      break
    case 'object':
      if (typeof props.src?.url === 'string')
        downloadByRequest(props.src.url)
      break
    default:
      break
  }
}

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