From 7b647cfe94d77e6e247a37084496791129824c09 Mon Sep 17 00:00:00 2001 From: cwchen <1048842385@qq.com> Date: Fri, 31 Oct 2025 15:55:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=AC=E5=85=B1=E4=B8=8B=E8=BD=BD=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/styles/index.scss | 37 ++++++++++ src/utils/download.js | 82 ++++++++++++++++++++++ src/views/enterpriseLibrary/tool/index.vue | 14 ++-- 3 files changed, 128 insertions(+), 5 deletions(-) diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss index bb87292..68b8ac5 100644 --- a/src/assets/styles/index.scss +++ b/src/assets/styles/index.scss @@ -176,3 +176,40 @@ aside { margin-bottom: 10px; } } + +// 下载加载提示样式优化 +::v-deep .download-loading-mask { + .el-loading-spinner { + margin-top: -30px; + + .el-loading-text { + color: #409EFF; + font-size: 16px; + font-weight: 500; + margin-top: 15px; + letter-spacing: 0.5px; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + } + + .circular { + width: 50px; + height: 50px; + } + + .path { + stroke: #409EFF; + stroke-width: 3.5; + } + + .el-icon-loading { + font-size: 50px; + color: #409EFF; + } + } + + // 背景渐变效果 + .el-loading-mask { + backdrop-filter: blur(2px); + -webkit-backdrop-filter: blur(2px); + } +} diff --git a/src/utils/download.js b/src/utils/download.js index aba2d53..0db7128 100644 --- a/src/utils/download.js +++ b/src/utils/download.js @@ -1,3 +1,9 @@ +import axios from 'axios' +import { Loading, Message } from 'element-ui' +import { getToken } from '@/utils/auth' +import { blobValidate } from '@/utils/bonus' +import { saveAs } from 'file-saver' + // 下载blob文件 export const downloadFile = ({ fileData, fileType, fileName }) => { const blob = new Blob([fileData], { @@ -24,3 +30,79 @@ export const downloadFileByUrl = (url) => { URL.revokeObjectURL(link.href) document.body.removeChild(link) } + +/** + * 通用文件下载方法(带加载提示) + * @param {string} path - 下载路径 + * @param {string} defaultFileName - 默认文件名(可选,如果响应头没有文件名则使用此名称) + * @param {string} loadingText - 加载提示文本(可选,默认为'正在下载文件,请稍候...') + * @returns {Promise} - 返回 Promise + */ +export const downloadFileWithLoading = (path, defaultFileName = '文件.xlsx', loadingText = '正在下载文件,请稍候...') => { + const baseURL = process.env.VUE_APP_BASE_API + const url = path.startsWith('http') ? path : `${baseURL}/${path}` + + // 显示下载中提示(优化样式) + const downloadLoadingInstance = Loading.service({ + lock: true, // 锁定屏幕,防止用户操作 + text: loadingText, + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.1)', // 稍微降低透明度,更柔和 + customClass: 'download-loading-mask' // 自定义样式类 + }) + + return axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { + 'Authorization': 'Bearer ' + getToken(), + 'encryptResponse':false + } + }).then((res) => { + // 验证是否为blob格式 + const isBlob = blobValidate(res.data) + if (isBlob) { + // 从响应头获取文件名,如果没有则使用默认名称 + const fileName = res.headers['download-filename'] + ? decodeURIComponent(res.headers['download-filename']) + : defaultFileName + + // 创建blob并下载 + const blob = new Blob([res.data], { + type: res.data.type || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }) + saveAs(blob, fileName) + Message.success('文件下载成功') + return Promise.resolve(fileName) + } else { + // 如果不是blob,尝试解析错误信息 + return printErrMsg(res.data) + } + }).catch((error) => { + console.error('文件下载失败:', error) + Message.error('文件下载失败,请稍后重试') + return Promise.reject(error) + }).finally(() => { + // 关闭加载提示 + if (downloadLoadingInstance) { + downloadLoadingInstance.close() + } + }) +} + +/** + * 打印错误信息 + * @param {Blob} data - 错误响应的blob数据 + */ +async function printErrMsg(data) { + try { + const resText = await data.text() + const rspObj = JSON.parse(resText) + Message.error(rspObj.msg || '下载失败,请稍后重试') + return Promise.reject(new Error(rspObj.msg || '下载失败')) + } catch (e) { + Message.error('下载失败,请稍后重试') + return Promise.reject(e) + } +} diff --git a/src/views/enterpriseLibrary/tool/index.vue b/src/views/enterpriseLibrary/tool/index.vue index 646dbdd..669e296 100644 --- a/src/views/enterpriseLibrary/tool/index.vue +++ b/src/views/enterpriseLibrary/tool/index.vue @@ -53,7 +53,7 @@ import { columnsList, formLabel } from './config' import ToolForm from './components/ToolForm.vue' import { listAPI, delDataAPI } from '@/api/enterpriseLibrary/tool/tool' import { encryptWithSM4, decryptWithSM4 } from '@/utils/sm' - +import { downloadFileWithLoading } from '@/utils/download' export default { name: 'Tool', components: { @@ -111,14 +111,18 @@ export default { /* 查看操作 */ handleDetail(row){ - this.title = "查看工器具"; + this.title = "查看详情"; this.isAdd = 'detail'; this.row = row; this.isflag = true; }, // 模板下载 - handleModelExport(){ - + handleModelExport() { + downloadFileWithLoading( + 'smartBid/commonDownload/downLoadToolModel', + '工器具导入模板.xlsx', + '正在下载模板,请稍候...' + ) }, // 批量导入 handleBathchImport(){ @@ -143,7 +147,7 @@ export default { }).then(() => { delDataAPI( { - toolId: raw.toolId, + toolId: row.toolId, enterpriseId: this.enterpriseId } ).then(res => {