fix:修改批量下载

This commit is contained in:
5g0Wp7Zy 2026-02-09 16:48:46 +08:00
parent 79e846fae6
commit 222835c762
6 changed files with 53 additions and 32 deletions

View File

@ -39,6 +39,7 @@
"@codemirror/lang-vue": "^0.1.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@fingerprintjs/fingerprintjs": "^4.6.2",
"@types/file-saver": "^2.0.7",
"@visactor/vchart": "^1.11.0",
"@visactor/vchart-arco-theme": "^1.11.0",
"@vueuse/core": "^12.4.0",
@ -47,8 +48,10 @@
"axios": "^1.6.8",
"codemirror": "^6.0.1",
"driver.js": "^1.3.1",
"file-saver": "^2.0.5",
"fingerprintjs2": "^2.1.4",
"jsbarcode": "^3.11.6",
"jszip": "^3.10.1",
"nprogress": "^0.2.0",
"pinia": "^2.3.0",
"pinia-plugin-persistedstate": "^3.2.1",

1
src/components.d.ts vendored
View File

@ -7,7 +7,6 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
copy: typeof import('./components/s-layout-search/index copy.vue')['default']
'Index copy': typeof import('./components/s-layout-search/index copy.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']

View File

@ -1,4 +1,6 @@
import { ref, Ref } from "vue";
import JSZip from "jszip";
import { saveAs } from "file-saver";
type DownloadStatus = "idle" | "loading" | "success" | "error";
@ -56,35 +58,48 @@ export function useImageDownloader(): any {
};
// 批量下载(并行)
const downloadImages = async (urls: string[], customFileNames?: string[]): Promise<DownloadResult[]> => {
downloadStatus.value = "loading";
batchResults.value = [];
const downloadImages = async (urls: string[], customFileNames?: string[]): Promise<void> => {
// 可选:更新状态(如果你用 Vue 的 ref
// downloadStatus.value = "loading";
const promises = urls.map(async (url, index) => {
const zip = new JSZip();
const errors: string[] = [];
// 并发获取所有图片(可加并发控制,但 30 个一般没问题)
await Promise.all(
urls.map(async (url, index) => {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const blob = await response.blob();
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = customFileNames?.[index] || extractFileName(url);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
return { url, status: "success" } as DownloadResult;
} catch (error) {
console.error(`Failed to download ${url}:`, error);
return { url, status: "error", message: (error as Error).message } as DownloadResult;
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const blob = await res.blob();
let fileName = customFileNames?.[index] || extractFileName(url);
// 防止文件名重复(简单处理)
if (zip.file(fileName)) {
const ext = fileName.includes(".") ? fileName.split(".").pop() : "";
const name = fileName.replace(new RegExp(`\\.${ext}$`), "");
fileName = `${name}_${Date.now()}.${ext || "jpg"}`;
}
});
zip.file(fileName, blob);
} catch (err) {
console.error("Download failed:", url, err);
errors.push(url);
}
})
);
const results = await Promise.all(promises);
batchResults.value = results;
downloadStatus.value = "success";
return results;
// 生成 ZIP Blob
const zipBlob = await zip.generateAsync({ type: "blob" });
// 触发下载 —— 这是安全的、用户可见的一次性下载
saveAs(zipBlob, "车辆二维码.zip");
// 可选:提示错误
if (errors.length > 0) {
alert(`成功打包 ${urls.length - errors.length} 张图片。\n失败${errors.length}`);
}
// downloadStatus.value = "success";
};
return {
downloadStatus,
batchResults,

View File

@ -132,7 +132,8 @@ const handleDownloadImage = async (record: any) => {
//
const batchDownload = async () => {
const urls = select_list.value.map(item => item.bikeQr);
const names = select_list.value.map(item => `电池二维码-${item.bikeQrCode}.png`);
const names = select_list.value.map(item => `车辆二维码-${item.bikeQrCode}.png`);
console.log(urls, names);
await downloadImages(urls, names);
};

View File

@ -173,9 +173,12 @@ const handleOk = async () => {
//
async function copyFileUrl(record: any) {
const { fileUrl } = record;
console.log(navigator.clipboard);
if (navigator.clipboard) {
const res: any = await navigator.clipboard.writeText(fileUrl);
arcoMessage("success", "复制成功");
}
}
async function getImageList() {
loading.value = true;

View File

@ -124,9 +124,9 @@ const handleUpdate = (record: any) => {
};
const handleDelete = async (record: any) => {
const { regionId } = record;
const { siteId } = record;
try {
const res: any = await deleteSiteAPI(regionId);
const res: any = await deleteSiteAPI(siteId);
if (res.code === 200) {
arcoMessage("success", "删除成功");
getRegionPage();