Files
vue3/packages/download-link/index.vue
2023-07-21 03:58:45 +08:00

100 lines
2.1 KiB
Vue

<!--
* @Author: zhaojinfeng 121016171@qq.com
* @Date: 2023-07-21 01:21:34
* @LastEditors: zhaojinfeng 121016171@qq.com
* @LastEditTime: 2023-07-21 03:57:13
* @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') {
url = props.src.url
type = 'success'
saveAs(props.src.url, props.src.name)
}
break
default:
break
}
}
tryOnUnmounted(() => {
if (url.startsWith('blob:')) {
// revoke object URL after use to avoid memory leak.
URL.revokeObjectURL(url)
}
})
</script>