100 lines
2.0 KiB
Vue
100 lines
2.0 KiB
Vue
<!--
|
|
* @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>
|