diff --git a/app/Module/Base.php b/app/Module/Base.php index 1eb402f41..f2b8cb1ad 100755 --- a/app/Module/Base.php +++ b/app/Module/Base.php @@ -1404,7 +1404,12 @@ class Base */ public static function ajaxError($msg, $data = [], $ret = 0, $abortCode = 404) { - abort_if(Request::header('Content-Type') !== 'application/json', $abortCode, Doo::translate($msg)); + if (Request::header('Content-Type') !== 'application/json') { + $translateMsg = Doo::translate($msg); + abort($abortCode, $translateMsg, [ + 'X-Error-Message-Base64' => base64_encode($translateMsg), + ]); + } return Base::retError($msg, $data, $ret); } diff --git a/electron/electron-down.js b/electron/electron-down.js index 696ff0bed..3217c1f6d 100644 --- a/electron/electron-down.js +++ b/electron/electron-down.js @@ -31,6 +31,12 @@ function initialize(onStarted= null) { onInterrupted: (item) => { downloadManager.refresh(item.getSavePath()); syncDownloadItems(); + // 尝试更新下载项的错误信息 + downloadManager.updateError(item).then(success => { + if (success) { + syncDownloadItems(); + } + }); }, onProgress: (item) => { downloadManager.refresh(item.path); diff --git a/electron/render/download/index.html b/electron/render/download/index.html index 6feb6ba3f..e48b6c95f 100644 --- a/electron/render/download/index.html +++ b/electron/render/download/index.html @@ -70,7 +70,7 @@ {{ formatTime(item.startTime) }} - {{ getStateText(item) }} + {{ getStateText(item) }}{{item.error ? `: ${item.error}` : ''}} diff --git a/electron/render/download/style.css b/electron/render/download/style.css index 19e50749b..2c37c87a5 100644 --- a/electron/render/download/style.css +++ b/electron/render/download/style.css @@ -498,11 +498,13 @@ body.win32 { /* Toast 提示框样式 */ .toast { position: fixed; + left: 0; + right: 0; bottom: 20px; - left: 50%; - transform: translateX(-50%); z-index: 1000; animation: toast-slide-up 0.3s ease-out; + display: flex; + justify-content: center; } .toast-content { @@ -516,7 +518,7 @@ body.win32 { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); font-size: 13px; min-width: 200px; - white-space: nowrap; + max-width: 90vw; } .toast.success .toast-content { @@ -529,15 +531,17 @@ body.win32 { .toast-message { flex: 1; + max-height: 200px; + overflow-y: auto; } @keyframes toast-slide-up { from { opacity: 0; - transform: translate(-50%, 20px); + transform: translateY(20px); } to { opacity: 1; - transform: translate(-50%, 0); + transform: translateY(0); } } diff --git a/electron/utils/download.js b/electron/utils/download.js index 339a64c40..f9b85b661 100644 --- a/electron/utils/download.js +++ b/electron/utils/download.js @@ -60,6 +60,7 @@ class DownloadManager { // 添加下载项 this.downloadHistory.unshift({ ...this.convert(downloadItem), + error: null, _source: downloadItem, }); if (this.downloadHistory.length > 1000) { @@ -101,6 +102,41 @@ class DownloadManager { store.set('downloadHistory', this.downloadHistory); } + /** + * 尝试更新下载项的错误信息 + * @param {Electron.DownloadItem} downloadItem + */ + async updateError(downloadItem) { + const urls = downloadItem.getURLChain() + const url = urls.length > 0 ? urls[0] : downloadItem.getURL() + const path = downloadItem.getSavePath() + + const item = this.downloadHistory.find(d => d.path === path) + if (!item) { + return; + } + + try { + const res = await fetch(url, { + method: 'HEAD', + }) + let error = null + if (res.headers.get('X-Error-Message-Base64')) { + error = Buffer.from(res.headers.get('X-Error-Message-Base64'), 'base64').toString('utf-8') + } else if (res.headers.get('X-Error-Message')) { + error = res.headers.get('X-Error-Message') + } + if (error) { + Object.assign(item, {error}); + store.set('downloadHistory', this.downloadHistory); + return true; + } + } catch { + // 忽略错误 + } + return false + } + /** * 暂停下载项 * @param {string} path