diff --git a/src/api/report/index.ts b/src/api/report/index.ts index 075b432..c1fe4e1 100644 --- a/src/api/report/index.ts +++ b/src/api/report/index.ts @@ -93,3 +93,9 @@ export function uploadReport(data: UploadReportParams) { data, }) } + +/** GET /api/report/download/{reportId} 下载地址 */ +export function getReportDownloadUrl(reportId: number | string) { + const baseURL = (import.meta.env.VITE_API_BASE_URL || '').replace(/\/$/, '') + return `${baseURL}/api/report/download/${reportId}` +} diff --git a/src/pages/report/detail/index.vue b/src/pages/report/detail/index.vue index 1a78cf2..9390349 100644 --- a/src/pages/report/detail/index.vue +++ b/src/pages/report/detail/index.vue @@ -3,7 +3,7 @@ import type { ReportItem } from '@/api/report' import type { HistoryReport } from '@/service/historyReport' import { onLoad, onShow } from '@dcloudio/uni-app' import { ref } from 'vue' -import { getReportDetail } from '@/api/report' +import { getReportDetail, getReportDownloadUrl } from '@/api/report' import { useDbStore } from '@/store/modules/db' definePage({ @@ -34,7 +34,7 @@ const reportId = ref(null) const reportData = ref(null) const apiReport = ref(null) const rawReport = ref(null) -const uploading = ref(false) +const downloading = ref(false) function parseDate(value?: string | null) { if (!value) @@ -180,15 +180,111 @@ onShow(() => { loadReportDetail() }) +function resolveDownloadFileName(id: number) { + const reportNo = apiReport.value?.reportNo + const ext = apiReport.value?.filePath?.match(/\.[^./\\]+$/)?.[0] || '.pdf' + return `${reportNo || `report_${id}`}${ext.startsWith('.') ? ext : `.${ext}`}` +} + +/** H5:浏览器直接下载 */ +function downloadOnH5(url: string, fileName: string) { + const a = document.createElement('a') + a.href = url + a.download = fileName + a.target = '_blank' + a.rel = 'noopener' + document.body.appendChild(a) + a.click() + document.body.removeChild(a) +} + +/** App:下载到本地文件夹并提示路径 */ +function downloadOnApp(url: string, fileName: string) { + return new Promise((resolve, reject) => { + const relativePath = `_downloads/RoadRoller/${fileName}` + const task = plus.downloader.createDownload(url, { filename: relativePath }, (download, status) => { + if (status !== 200) { + reject(new Error('下载失败')) + return + } + const localPath = download.filename || relativePath + let displayPath = localPath + try { + displayPath = plus.io.convertLocalFileSystemURL(localPath) || localPath + } + catch { + // 转换失败时展示原始路径 + } + uni.showModal({ + title: '下载成功', + content: `文件已保存至:\n${displayPath}`, + showCancel: false, + }) + resolve() + }) + task.start() + }) +} + async function handleDownload() { - console.log('下载报告') + const id = reportId.value + if (!id) { + uni.showToast({ title: '报告ID缺失', icon: 'none' }) + return + } + if (downloading.value) + return + + const url = getReportDownloadUrl(id) + const fileName = resolveDownloadFileName(id) + + downloading.value = true + uni.showLoading({ title: '下载中...', mask: true }) + try { + // #ifdef H5 + downloadOnH5(url, fileName) + uni.showToast({ title: '已开始下载', icon: 'success' }) + // #endif + + // #ifdef APP-PLUS + await downloadOnApp(url, fileName) + // #endif + + // #ifndef H5 || APP-PLUS + await new Promise((resolve, reject) => { + uni.downloadFile({ + url, + success: (res) => { + if (res.statusCode !== 200) { + reject(new Error('下载失败')) + return + } + uni.openDocument({ + filePath: res.tempFilePath, + showMenu: true, + fail: () => uni.showToast({ title: '文件已下载', icon: 'success' }), + }) + resolve() + }, + fail: reject, + }) + }) + // #endif + } + catch (e: any) { + uni.showToast({ title: e?.message || '下载失败', icon: 'none' }) + } + finally { + downloading.value = false + uni.hideLoading() + } }