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