Browse Source

feat: 为文件下载添加进度提示与关闭按钮

yusheng 3 weeks ago
parent
commit
8321eb779c
1 changed files with 107 additions and 11 deletions
  1. 107 11
      src/api/system/file/index.js

+ 107 - 11
src/api/system/file/index.js

@@ -1,5 +1,73 @@
 import request from '@/utils/request';
-import {download } from '@/utils/file';
+import { download } from '@/utils/file';
+import { Loading } from 'element-ui';
+
+let currentGetFileLoading = null;
+let closeBtnEl = null;
+
+/**
+ * 移除关闭按钮
+ */
+function removeCloseBtn () {
+  if (closeBtnEl && closeBtnEl.parentNode) {
+    closeBtnEl.parentNode.removeChild(closeBtnEl);
+    closeBtnEl = null;
+  }
+}
+
+/**
+ * 创建关闭按钮并插入到 body(fixed 定位避免被裁剪)
+ */
+function injectCloseBtn () {
+  removeCloseBtn();
+
+  const btn = document.createElement('button');
+  btn.id = 'getFileCloseBtn';
+  btn.innerText = '隐藏';
+  btn.style.cssText = `
+    position: fixed;
+    top: calc(50% + 50px);
+    left: 50%;
+    transform: translateX(-50%);
+    padding: 8px 28px;
+    font-size: 14px;
+    color: #fff;
+    background: rgba(255,255,255,0.2);
+    border: 1px solid rgba(255,255,255,0.5);
+    border-radius: 20px;
+    cursor: pointer;
+    backdrop-filter: blur(4px);
+    transition: all 0.2s;
+    outline: none;
+    z-index: 99999;
+    pointer-events: auto;
+  `;
+  btn.onmouseenter = () => {
+    btn.style.background = 'rgba(255,255,255,0.35)';
+    btn.style.borderColor = 'rgba(255,255,255,0.8)';
+  };
+  btn.onmouseleave = () => {
+    btn.style.background = 'rgba(255,255,255,0.2)';
+    btn.style.borderColor = 'rgba(255,255,255,0.5)';
+  };
+  btn.onclick = () => {
+    closeGetFileLoading();
+  };
+
+  document.body.appendChild(btn);
+  closeBtnEl = btn;
+}
+
+/**
+ * 关闭 getFile 的 loading
+ */
+export function closeGetFileLoading () {
+  removeCloseBtn();
+  if (currentGetFileLoading) {
+    currentGetFileLoading.close();
+    currentGetFileLoading = null;
+  }
+}
 
 /**
  * 上传文件
@@ -60,18 +128,46 @@ export async function getPathAddress () {
 }
 /**
  * 获取文件
+ * @param params 请求参数
+ * @param fileName 文件名
+ * @param onProgress 进度回调 (progressEvent) => void
  */
-export async function getFile (params, fileName) {
-  const res = await request.get('/main/file/getFile', {
-    params,
-    responseType: 'blob'
+export async function getFile (params, fileName, onProgress) {
+  // 关闭之前的 loading
+  closeGetFileLoading();
+
+  // 创建全屏 loading
+  currentGetFileLoading = Loading.service({
+    lock: true,
+    text: '文件下载中...',
+    spinner: 'el-icon-loading',
+    background: 'rgba(0, 0, 0, 0.6)'
   });
-  const arr = params.objectName.split('/');
-  download(res.data, fileName || arr[arr.length - 1]);
-  // if (res.data.code === '0') {
-  //   return res.data.data;
-  // }
-  // return Promise.reject();
+
+  // loading 渲染到 DOM 后注入关闭按钮
+  setTimeout(() => {
+    injectCloseBtn();
+  }, 50);
+
+  try {
+    const res = await request.get('/main/file/getFile', {
+      params,
+      responseType: 'blob',
+      onDownloadProgress: (progressEvent) => {
+        if (progressEvent.total && currentGetFileLoading) {
+          const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
+          currentGetFileLoading.setText(`文件下载中... ${percent}%`);
+        }
+        if (onProgress) {
+          onProgress(progressEvent);
+        }
+      }
+    });
+    const arr = params.objectName.split('/');
+    download(res.data, fileName || arr[arr.length - 1]);
+  } finally {
+    closeGetFileLoading();
+  }
 }
 /**
  * 删除文件