From b4590b35f59ee2a68d35281907afc1fc31d0037b Mon Sep 17 00:00:00 2001 From: 5g0Wp7Zy Date: Fri, 6 Jun 2025 16:08:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E8=BD=A6=E8=BE=86=E4=BA=8C=E7=BB=B4?= =?UTF-8?q?=E7=A0=81=E3=80=81=E7=94=B5=E6=B1=A0=E4=BA=8C=E7=BB=B4=E7=A0=81?= =?UTF-8?q?=E3=80=81=E5=A4=B4=E7=9B=94=E4=BA=8C=E7=BB=B4=E7=A0=81=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E4=B8=8B=E8=BD=BD=20(=E5=AE=8C=E6=88=90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ebike-operate/src/utils/tools.js | 91 +++++++++++++++++++ ebike-operate/src/views/Layout/index.vue | 18 +++- .../src/views/Produce/BatteryQRCode/index.vue | 44 +++++++-- .../src/views/Produce/BikeQRCode/index.vue | 50 ++++++++-- .../src/views/Produce/HelmetQRCode/index.vue | 42 ++++++++- 5 files changed, 223 insertions(+), 22 deletions(-) diff --git a/ebike-operate/src/utils/tools.js b/ebike-operate/src/utils/tools.js index 16468cb..af2821a 100644 --- a/ebike-operate/src/utils/tools.js +++ b/ebike-operate/src/utils/tools.js @@ -77,4 +77,95 @@ export function isNullOrEmpty(value){ return true; else return false; +} + + + +/** + * 批量下载图片(兼容IE10+及现代浏览器) + * @param {Array} imgList - 图片数据数组,支持base64或URL + */ +export function batchDownloadQRcodes(imgList) { + // 检查是否为 IE 浏览器,通过判断是否存在 msSaveBlob 方法 + const isIE = window.navigator.msSaveBlob!== undefined; + + // 下载单张图片的函数 + const downloadSingleImage = (imgObj) => { + const { base64QrCode, code } = imgObj; + // 拼接文件名,使用 bikeCode 作为主要标识 + const fileName = `${code}.png`; + + if (base64QrCode.startsWith('data:')) { + // 处理 Base64 格式的图片数据 + const [mime, data] = base64QrCode.split(';base64,'); + const mimeType = mime.replace('data:', ''); + const byteCharacters = atob(data); + const byteNumbers = new Array(byteCharacters.length); + + for (let i = 0; i < byteCharacters.length; i++) { + byteNumbers[i] = byteCharacters.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + const blob = new Blob([byteArray], { type: mimeType }); + + if (isIE) { + // IE 浏览器专用的下载方法 + window.navigator.msSaveBlob(blob, fileName); + } else { + // 现代浏览器的下载方式,创建 blob URL 并触发下载 + const url = URL.createObjectURL(blob); + triggerDownload(url, fileName); + URL.revokeObjectURL(url); + } + } else { + // 处理图片为普通 URL 格式的情况(跨域可能受限,需服务端配合设置跨域头) + if (isIE) { + // IE 下使用 XMLHttpRequest 下载 + const xhr = new XMLHttpRequest(); + xhr.open('GET', base64QrCode, true); + xhr.responseType = 'blob'; + + xhr.onload = function () { + if (xhr.status === 200) { + window.navigator.msSaveBlob(xhr.response, fileName); + } + }; + + xhr.send(); + } else { + // 现代浏览器使用 fetch 下载 + fetch(base64QrCode) + .then(res => res.blob()) + .then(blob => { + const url = URL.createObjectURL(blob); + triggerDownload(url, fileName); + URL.revokeObjectURL(url); + }) + .catch(err => console.error('下载失败:', err)); + } + } + }; + + // 创建下载链接并触发点击的函数 + const triggerDownload = (url, fileName) => { + const link = document.createElement('a'); + link.href = url; + link.download = fileName; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + // 按顺序下载图片,避免浏览器并发限制 + const downloadNext = (index) => { + if (index >= imgList.length) return; + + downloadSingleImage(imgList[index], index); + + // 间隔 500ms 下载下一个,可根据实际情况调整间隔时间 + setTimeout(() => downloadNext(index + 1), 500); + }; + + downloadNext(0); } \ No newline at end of file diff --git a/ebike-operate/src/views/Layout/index.vue b/ebike-operate/src/views/Layout/index.vue index e171239..228a2f1 100644 --- a/ebike-operate/src/views/Layout/index.vue +++ b/ebike-operate/src/views/Layout/index.vue @@ -107,9 +107,11 @@ - + - +
+ +
@@ -273,4 +275,16 @@ const onOperationClick = (e) => { opacity: 1; } } + +.custom-layout-content{ + height: calc(100vh - 64px); + overflow: hidden; +} + +.custom-layout-content .content-wrapper { + height: 100%; + overflow-y: auto; + padding: 24px; + box-sizing: border-box; +} diff --git a/ebike-operate/src/views/Produce/BatteryQRCode/index.vue b/ebike-operate/src/views/Produce/BatteryQRCode/index.vue index c5c1d00..ebf7ddb 100644 --- a/ebike-operate/src/views/Produce/BatteryQRCode/index.vue +++ b/ebike-operate/src/views/Produce/BatteryQRCode/index.vue @@ -104,6 +104,17 @@ 绑定 + + + + 批量下载 + + +const batchDownload = () => { + if( batchDownloadList.value.length === 0) { + message.error('请选择要下载的二维码') + return + } + + const urls = batchDownloadList.value.map(item => { + return { + base64QrCode:item.base64QrCode, + code:item.batteryCode + } + }); + batchDownloadQRcodes(urls) +} + + \ No newline at end of file diff --git a/ebike-operate/src/views/Produce/BikeQRCode/index.vue b/ebike-operate/src/views/Produce/BikeQRCode/index.vue index dfaa17c..c8667c0 100644 --- a/ebike-operate/src/views/Produce/BikeQRCode/index.vue +++ b/ebike-operate/src/views/Produce/BikeQRCode/index.vue @@ -1,6 +1,5 @@ - - + + +const batchDownload = () => { + if( batchDownloadList.value.length === 0) { + message.error('请选择要下载的二维码') + return + } + + const urls = batchDownloadList.value.map(item => { + return { + base64QrCode:item.base64QrCode, + code:item.bikeCode + } + }); + batchDownloadQRcodes(urls) +} + + \ No newline at end of file diff --git a/ebike-operate/src/views/Produce/HelmetQRCode/index.vue b/ebike-operate/src/views/Produce/HelmetQRCode/index.vue index 44fd9e4..1c5e5e3 100644 --- a/ebike-operate/src/views/Produce/HelmetQRCode/index.vue +++ b/ebike-operate/src/views/Produce/HelmetQRCode/index.vue @@ -104,6 +104,17 @@ 绑定 + + + + 批量下载 + + +const batchDownload = () => { + if( batchDownloadList.value.length === 0) { + message.error('请选择要下载的二维码') + return + } + + const urls = batchDownloadList.value.map(item => { + return { + base64QrCode:item.base64QrCode, + code:item.helmetCode + } + }); + batchDownloadQRcodes(urls) +} + + \ No newline at end of file