refactor: 自动获取文件对象

This commit is contained in:
2023-07-22 14:39:03 +08:00
parent db2e8dd6d5
commit f5dc4b2068
2 changed files with 44 additions and 22 deletions

View File

@ -2,13 +2,13 @@
* @Author: zhaojinfeng 121016171@qq.com * @Author: zhaojinfeng 121016171@qq.com
* @Date: 2023-07-21 01:21:34 * @Date: 2023-07-21 01:21:34
* @LastEditors: zhaojinfeng 121016171@qq.com * @LastEditors: zhaojinfeng 121016171@qq.com
* @LastEditTime: 2023-07-22 12:46:07 * @LastEditTime: 2023-07-22 14:15:32
* @FilePath: \vue3\packages\download-link\index.vue * @FilePath: \vue3\packages\download-link\index.vue
* @Description: 现在组件 * @Description: 现在组件
* *
--> -->
<template> <template>
<el-link v-loading="loading" :href="url" :type="type" :download="url && fileName" target="_blank" @click="download"> <el-link v-loading="loading" :href="url" :type="type" :download="url && fileName" target="_blank">
<slot> <slot>
{{ fileName }} {{ fileName }}
</slot> </slot>
@ -16,13 +16,7 @@
</template> </template>
<script lang="ts" setup name="ThDownloadLink"> <script lang="ts" setup name="ThDownloadLink">
import { saveAs } from 'file-saver'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
/**
* 自定义下载文件名
*
*/
fileName?: string fileName?: string
/** /**
* 下载文件的请求源 * 下载文件的请求源
@ -31,31 +25,29 @@ const props = withDefaults(defineProps<{
* *
*/ */
src?: number | string | FileVO src?: number | string | FileVO
/** 下载文件的请求参数的健名 */ /** 文件信息请求函数 */
requestKey?: string request?: (...args: any) => Promise<FileVO>
/** 下载文件的请求函数 */
request?: (...args: any) => Promise<Blob>
}>(), { }>(), {
fileName: '文件', fileName: '',
requestKey: 'fileName',
request: () => { request: () => {
throw new Error('请定义下载接口的请求函数') throw new Error('请定义下载接口的请求函数')
}, },
}) })
let url = $ref('') let url = $ref('')
let fileName = $ref('')
let loading = $ref(false) let loading = $ref(false)
let type = $ref<'success' | 'primary' | 'danger'>('primary') let type = $ref<'success' | 'primary' | 'danger'>('primary')
async function downloadByRequest(fileName: string | number) { async function reload(id: string | number) {
if (url || loading) if (url || loading)
return return
loading = true loading = true
try { try {
const res = await props.request({ [props.requestKey]: fileName }) const res = await props.request(id)
url = URL.createObjectURL(res) url = res.url
saveAs(res) fileName = res.name
} }
catch (error) { catch (error) {
type = 'danger' type = 'danger'
@ -66,23 +58,27 @@ async function downloadByRequest(fileName: string | number) {
} }
} }
function download() { function init() {
switch (typeof props.src) { switch (typeof props.src) {
case 'string': case 'string':
if (props.src.startsWith('http')) { if (props.src.startsWith('http')) {
url = props.src url = props.src
fileName = props.fileName
break break
} }
downloadByRequest(props.src) reload(props.src)
break break
case 'number': case 'number':
downloadByRequest(props.src) reload(props.src)
break break
case 'object': case 'object':
if (typeof props.src?.url === 'string') { if (typeof props.src?.url === 'string') {
url = props.src.url url = props.src.url
fileName = props.src.name
type = 'success' type = 'success'
saveAs(props.src.url, props.src.name) }
else {
type = 'danger'
} }
break break
default: default:
@ -90,6 +86,8 @@ function download() {
} }
} }
watch(() => props.src, init)
tryOnUnmounted(() => { tryOnUnmounted(() => {
if (url.startsWith('blob:')) { if (url.startsWith('blob:')) {
// revoke object URL after use to avoid memory leak. // revoke object URL after use to avoid memory leak.

View File

@ -1,10 +1,34 @@
/*
* @Author: zhaojinfeng 121016171@qq.com
* @Date: 2023-07-21 12:25:52
* @LastEditors: zhaojinfeng 121016171@qq.com
* @LastEditTime: 2023-07-22 14:38:22
* @FilePath: \vue3\stories\DownloadLink.stories.ts
* @Description:
*
*/
import type { Meta, StoryObj } from '@storybook/vue3' import type { Meta, StoryObj } from '@storybook/vue3'
import ThDownloadLink from '../packages/download-link/index.vue' import ThDownloadLink from '../packages/download-link/index.vue'
import avatar from './assets/avatar.jpeg'
const meta = { const meta = {
title: '数据展示/DownloadLink', title: '数据展示/DownloadLink',
component: ThDownloadLink, component: ThDownloadLink,
tags: ['autodocs'], tags: ['autodocs'],
args: {
fileName: '文件名',
/**
* 下载文件的请求源
*
* 可以是文件名或URL。
*
*/
src: '文件ID',
/** 文件信息请求函数 */
request: () => Promise.resolve({
url: avatar,
}),
},
} satisfies Meta<typeof ThDownloadLink> } satisfies Meta<typeof ThDownloadLink>
export default meta export default meta