<template>
<a
v-if="method === 'post' || outOfService"
:class="aClassName"
@click="click"
>
<div v-if="$scopedSlots.exportType">
<slot name="exportType" v-bind="{ handleSubmit }" />
</div>
<slot v-else><a-button>{{ btnText }}</a-button></slot>
<div v-if="userFormData" v-show="false">
<iframe :id="`__hidden_iframe_${id}__`" src="about:blank" :title="`__hidden_iframe_${id}__`" />
<form ref="handleRefForm" :action="hrefValue" :method="method" :target="`__hidden_iframe_${id}__`">
<input
v-for="key in Object.keys(params)"
:key="key"
type="hidden"
:name="key"
:value="params[key]"
>
</form>
</div>
</a>
<a v-else :href="hrefValue" :class="aClassName">
<slot><a-button>{{ btnText }}</a-button></slot>
</a>
</template>
<script>
import { stringify } from 'querystring'
import { axios } from '@/utils/request3'
const urlPrix = ''
export default {
props: {
// 是否使用form表单形式下载
userFormData: {
type: Boolean,
default: false
},
// 请求方式
method: {
type: String,
default: 'post'
},
// 请求地址
href: {
type: String,
required: true,
default: null
},
// 是否完整Url
isCompleteUrl: {
type: Boolean,
default: false
},
// 参数
params: {
type: Object,
default: () => ({})
},
// 样式
aClassName: {
type: String,
default: ''
},
// 文件名的前缀
fileNamePrix: {
type: String,
default: ''
},
// 导出按钮文字
btnText: {
type: String,
default: '导出Excel'
},
// 是否停用, 点击将提示 - 正在开发中,敬请期待
outOfService: {
type: Boolean,
default: false
}
},
data() {
const id = String(Math.random()).substring(2)
return {
id
}
},
computed: {
hrefValue() {
const { method, href, params } = this
if (this.isCompleteUrl) return href
return method === 'post' ? `${urlPrix}${href}` : `${urlPrix}${href}?${stringify(params)}`
}
},
methods: {
click() {
if (this.outOfService) {
return this.$message.info(this.$t('msg.underDevelopment'))
}
if (!this.$scopedSlots.exportType) {
this.handleSubmit()
}
},
handleSubmit(otherParams) {
if (this.userFormData) {
this.$refs.handleRefForm.submit()
} else {
this.axiosMethodDownload(otherParams)
}
},
async axiosMethodDownload(otherParams) {
try {
const { method, href, params } = this
const url = this.isCompleteUrl ? href : urlPrix + href
const res = await axios({
url,
method,
data: { ...params, ...otherParams },
responseType: 'arraybuffer' // blob(blob超过3M的文件无法下载)
})
if (res && res.data && (res.data instanceof Blob || res.data instanceof ArrayBuffer)) {
const { data, headers } = res
this.exportExcel(headers, data)
}
} catch (error) {
console.error(error)
}
},
exportExcel(headers = {}, response) {
const contentDisposition = headers['content-disposition']
const contentType = headers['content-type']
let fileName = 'unknown'
if (contentDisposition) {
fileName = window.decodeURIComponent(headers.filename || headers['content-disposition'].split('=')[1].split('?')[0])
}
if (this.fileNamePrix) {
fileName = `${this.fileNamePrix}-${fileName}`
}
const blob = new Blob([response], { type: contentType })
this.downFile(blob, fileName)
},
downFile(blob, fileName) {
// 非IE下载
if ('download' in document.createElement('a')) {
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob) // 创建下载的链接
link.download = fileName // 下载后文件名
link.style.display = 'none'
document.body.appendChild(link)
link.click() // 点击下载
window.URL.revokeObjectURL(link.href) // 释放掉blob对象
document.body.removeChild(link) // 下载完成移除元素
} else {
// IE10+下载
window.navigator.msSaveBlob(blob, fileName)
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
网友评论