From 89fd9ab312c0aef9fcab89fbbaee4add5baa7c57 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期二, 27 十月 2026 09:43:22 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/plugins/download.js |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/src/plugins/download.js b/src/plugins/download.js
index e83e43c..f2903dc 100644
--- a/src/plugins/download.js
+++ b/src/plugins/download.js
@@ -4,6 +4,8 @@
 import { getToken } from '@/utils/auth'
 import errorCode from '@/utils/errorCode'
 import { blobValidate } from '@/utils/ruoyi'
+import { getJavaApi } from '@/utils/java-api'
+import { resolveAttachmentUrl, attachmentFileName, alternateImageAttachmentUrl, validateAttachmentBlob } from '@/utils/attachment'
 
 const baseURL = import.meta.env.VITE_APP_BASE_API
 let downloadLoadingInstance
@@ -67,7 +69,51 @@
     })
   },
   saveAs(text, name, opts) {
-    saveAs(text, name, opts)
+    if (typeof text === 'string') return this.url(text, name, opts)
+    return saveAs(text, name, opts)
+  },
+  attachment(file, name) {
+    try {
+      return this.url(resolveAttachmentUrl(file?.fileUrl, file?.type), name || file?.fileName, undefined,
+        ![1, 2].includes(Number(file?.type)))
+    } catch (error) {
+      ElMessage.error(error.message)
+      return Promise.resolve(false)
+    }
+  },
+  async url(path, name, opts, allowAlternative = true) {
+    try {
+      const url = resolveAttachmentUrl(path)
+      const backend = new URL(getJavaApi(), window.location.origin)
+      const target = new URL(url, window.location.origin)
+      const isBackend = target.origin === backend.origin
+        && (target.pathname === backend.pathname || target.pathname.startsWith(backend.pathname.replace(/\/$/, '') + '/'))
+      const filename = attachmentFileName(url, name)
+      // 澶栭儴闄勪欢娌跨敤娴忚鍣ㄤ笅杞斤紝鍏煎涓嶅厑璁歌法鍩熻鍙栫殑鏂囦欢鏈嶅姟銆�
+      if (!isBackend && /^https?:$/.test(target.protocol)) {
+        saveAs(url, filename, opts)
+        return true
+      }
+      const headers = isBackend && getToken() ? { Authorization: 'Bearer ' + getToken() } : {}
+      let response
+      try {
+        response = await axios.get(url, { responseType: 'blob', headers })
+      } catch (error) {
+        const alternative = isBackend && allowAlternative && error.response?.status === 404
+          ? alternateImageAttachmentUrl(url) : null
+        if (!alternative) throw error
+        response = await axios.get(alternative, { responseType: 'blob', headers })
+      }
+      const { data } = response
+      await validateAttachmentBlob(data, filename)
+      saveAs(data, filename, opts)
+      return true
+    } catch (error) {
+      const status = error.response?.status
+      ElMessage.error(status === 404 ? '闄勪欢涓嶅瓨鍦ㄦ垨宸茶鍒犻櫎' : status === 401 || status === 403
+        ? '鐧诲綍宸茶繃鏈熸垨娌℃湁闄勪欢涓嬭浇鏉冮檺' : error.message || '闄勪欢涓嬭浇澶辫触锛岃绋嶅悗閲嶈瘯')
+      return false
+    }
   },
   async printErrMsg(data) {
     const resText = await data.text()

--
Gitblit v1.9.3