fix: support sms signature file download
This commit is contained in:
@@ -288,8 +288,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="detail-file-row">
|
<div class="detail-file-row">
|
||||||
<span class="detail-img-label">申请文件</span>
|
<span class="detail-img-label">申请文件</span>
|
||||||
<el-link v-if="detailData.application_file_url" type="primary" :href="detailData.application_file_url" target="_blank">查看申请文件</el-link>
|
<el-button
|
||||||
<span v-else class="detail-empty-text">未上传</span>
|
v-if="getApplicationFileUrl(detailData)"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
:loading="applicationFileDownloading"
|
||||||
|
@click="downloadApplicationFile(detailData)"
|
||||||
|
>
|
||||||
|
<el-icon v-if="!applicationFileDownloading"><Download /></el-icon>
|
||||||
|
下载申请文件
|
||||||
|
</el-button>
|
||||||
|
<span v-else class="detail-empty-text">暂无可下载文件</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -314,8 +323,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus, User, Close, Picture } from '@element-plus/icons-vue'
|
import { Plus, User, Close, Picture, Download } from '@element-plus/icons-vue'
|
||||||
import { formatDate } from '@/utils/tool'
|
import { formatDate } from '@/utils/tool'
|
||||||
import {
|
import {
|
||||||
getSmsServiceList,
|
getSmsServiceList,
|
||||||
@@ -392,6 +402,7 @@ const currentRow = ref(null)
|
|||||||
|
|
||||||
const detailVisible = ref(false)
|
const detailVisible = ref(false)
|
||||||
const detailData = ref(null)
|
const detailData = ref(null)
|
||||||
|
const applicationFileDownloading = ref(false)
|
||||||
|
|
||||||
const userSelectorVisible = ref(false)
|
const userSelectorVisible = ref(false)
|
||||||
const selectedUserInfo = ref(null)
|
const selectedUserInfo = ref(null)
|
||||||
@@ -466,6 +477,83 @@ const handleDetail = (row) => {
|
|||||||
detailVisible.value = true
|
detailVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSignatureService = (row) => {
|
||||||
|
const serviceId = row.service_id || queryParams.service_id
|
||||||
|
return serviceOptions.value.find(item => String(item.id) === String(serviceId))
|
||||||
|
}
|
||||||
|
|
||||||
|
const getApplicationFileUrl = (row) => {
|
||||||
|
if (!row?.ID || !row?.application_file_url) return ''
|
||||||
|
const service = getSignatureService(row)
|
||||||
|
const endpoint = String(service?.host || '').replace(/\/+$/, '')
|
||||||
|
if (!endpoint) return ''
|
||||||
|
return `${endpoint}/api/sms/admin/signature/${row.ID}/application-file`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDownloadFilename = (headers, signatureId) => {
|
||||||
|
const disposition = headers?.['content-disposition'] || ''
|
||||||
|
const utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i)
|
||||||
|
const plainMatch = disposition.match(/filename="?([^";]+)"?/i)
|
||||||
|
const encodedName = utf8Match?.[1] || plainMatch?.[1]
|
||||||
|
if (!encodedName) return `签名申请文件_${signatureId}.xlsx`
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(encodedName)
|
||||||
|
} catch {
|
||||||
|
return encodedName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadApplicationFile = async (row) => {
|
||||||
|
const url = getApplicationFileUrl(row)
|
||||||
|
if (!url || applicationFileDownloading.value) return
|
||||||
|
|
||||||
|
const service = getSignatureService(row)
|
||||||
|
const endpoint = String(service?.host || '').replace(/\/+$/, '')
|
||||||
|
const serviceToken = service?.serviceToken || service?.service_token
|
||||||
|
if (!serviceToken) {
|
||||||
|
ElMessage.error('当前短信平台未配置 Service Token')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationFileDownloading.value = true
|
||||||
|
try {
|
||||||
|
const loginResponse = await axios.post(
|
||||||
|
`${endpoint}/api/auth/service-token-login`,
|
||||||
|
{ service_token: serviceToken },
|
||||||
|
{ timeout: 15000 }
|
||||||
|
)
|
||||||
|
const loginBody = loginResponse.data || {}
|
||||||
|
const platformToken = loginBody.data?.token
|
||||||
|
if (loginBody.code !== 200 || !platformToken) {
|
||||||
|
throw new Error(loginBody.message || '短信平台 Token 获取失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.get(url, {
|
||||||
|
headers: { Authorization: `Bearer ${platformToken}` },
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60000
|
||||||
|
})
|
||||||
|
const contentType = response.headers?.['content-type'] || ''
|
||||||
|
if (contentType.includes('application/json')) {
|
||||||
|
const body = JSON.parse(await response.data.text())
|
||||||
|
throw new Error(body.message || body.msg || '下载申请文件失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectUrl = window.URL.createObjectURL(response.data)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = objectUrl
|
||||||
|
link.download = getDownloadFilename(response.headers, row.ID)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
link.remove()
|
||||||
|
window.URL.revokeObjectURL(objectUrl)
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error(error.message || '下载申请文件失败')
|
||||||
|
} finally {
|
||||||
|
applicationFileDownloading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
dialogType.value = 'add'
|
dialogType.value = 'add'
|
||||||
selectedUserInfo.value = null
|
selectedUserInfo.value = null
|
||||||
|
|||||||
Reference in New Issue
Block a user