From ca58ae7caf3100956e4a3595b1e946a8a3d7d7cf Mon Sep 17 00:00:00 2001 From: anghunk Date: Thu, 12 Feb 2026 16:30:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DS3=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E4=B8=8B=E8=BD=BDURL=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E5=AF=BC=E5=87=BAAPI=E5=9F=BA=E7=A1=80URL=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 导出`getApiBaseUrl`函数以便复用 - 修改`downloadS3BackupUrl`函数,使其使用正确的API基础URL - 重构S3备份下载处理,使用fetch API并添加授权头,支持blob下载 --- cwd-admin/src/api/admin.ts | 6 +++- cwd-admin/src/api/http.ts | 2 +- .../DataView/components/S3BackupModal.vue | 33 ++++++++++++++++--- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/cwd-admin/src/api/admin.ts b/cwd-admin/src/api/admin.ts index c0e0405..5838bba 100644 --- a/cwd-admin/src/api/admin.ts +++ b/cwd-admin/src/api/admin.ts @@ -424,5 +424,9 @@ export function deleteS3Backup(key: string): Promise<{ message: string }> { } export function downloadS3BackupUrl(key: string): string { - return `/admin/backup/s3/download?key=${encodeURIComponent(key)}`; + const rawEnvApiBaseUrl = (import.meta.env.VITE_API_BASE_URL || '').trim(); + const stored = (localStorage.getItem('cwd_admin_api_base_url') || '').trim(); + const source = stored || rawEnvApiBaseUrl; + const apiBaseUrl = source.replace(/\/+$/, ''); + return `${apiBaseUrl}/admin/backup/s3/download?key=${encodeURIComponent(key)}`; } diff --git a/cwd-admin/src/api/http.ts b/cwd-admin/src/api/http.ts index 1213f8d..ed97cce 100644 --- a/cwd-admin/src/api/http.ts +++ b/cwd-admin/src/api/http.ts @@ -1,6 +1,6 @@ const rawEnvApiBaseUrl = (import.meta.env.VITE_API_BASE_URL || '').trim(); -function getApiBaseUrl(): string { +export function getApiBaseUrl(): string { const stored = (localStorage.getItem('cwd_admin_api_base_url') || '').trim(); const source = stored || rawEnvApiBaseUrl; const apiBaseUrl = source.replace(/\/+$/, ''); diff --git a/cwd-admin/src/views/DataView/components/S3BackupModal.vue b/cwd-admin/src/views/DataView/components/S3BackupModal.vue index 3669341..d829951 100644 --- a/cwd-admin/src/views/DataView/components/S3BackupModal.vue +++ b/cwd-admin/src/views/DataView/components/S3BackupModal.vue @@ -57,9 +57,9 @@ import { useI18n } from "vue-i18n"; import { fetchS3BackupList, deleteS3Backup, - downloadS3BackupUrl, S3BackupItem, } from "../../../api/admin"; +import { getApiBaseUrl } from "../../../api/http"; const props = defineProps<{ visible: boolean; @@ -83,9 +83,34 @@ const handleClose = () => { emit("close"); }; -const handleDownload = (key: string) => { - const url = downloadS3BackupUrl(key); - window.open(url, "_blank"); +const handleDownload = async (key: string) => { + try { + const apiBaseUrl = getApiBaseUrl(); + const token = localStorage.getItem('cwd_admin_token'); + const url = `${apiBaseUrl}/admin/backup/s3/download?key=${encodeURIComponent(key)}`; + + const res = await fetch(url, { + method: 'GET', + headers: token ? { 'Authorization': `Bearer ${token}` } : {}, + }); + + if (!res.ok) { + throw new Error(`下载失败: ${res.status} ${res.statusText}`); + } + + const blob = await res.blob(); + const fileName = key; + + const a = document.createElement('a'); + a.href = window.URL.createObjectURL(blob); + a.download = fileName; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(a.href); + document.body.removeChild(a); + } catch (e: any) { + console.error('Download error:', e); + } }; const handleDelete = async (key: string) => {