From 40550ba188593fdec9358dcdd7fe9c4ccd27333a Mon Sep 17 00:00:00 2001
From: rain <1679827795@qq.com>
Date: Thu, 06 Mar 2025 18:56:01 +0800
Subject: [PATCH] 媒体文件打包下载

---
 src/views/resource/media.vue |  141 ++++++++++++++++++++++------------------------
 1 files changed, 67 insertions(+), 74 deletions(-)

diff --git a/src/views/resource/media.vue b/src/views/resource/media.vue
index ca24c27..6d5f575 100644
--- a/src/views/resource/media.vue
+++ b/src/views/resource/media.vue
@@ -4,6 +4,10 @@
       v-model="form" ref="crud" @row-del="rowDel" @search-change="searchChange" @search-reset="searchReset"
       @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
       @refresh-change="refreshChange" @on-load="onLoad">
+      <template #menu-left>
+        <el-button type="primary" icon="el-icon-download" plain :loading="isDownloading" @click="handleZipDownload">{{
+          isDownloading ? '压缩下载中...' : '压缩下载' }}</el-button>
+      </template>
       <template #menu="scope">
         <el-button type="primary" text icon="el-icon-view" v-if="permission.attach_delete"
           @click="handleRowView(scope.row)">查看
@@ -24,6 +28,7 @@
 </template>
 
 <script>
+import JSZip from 'jszip';
 import { getMedia, deleteAllFile } from '@/api/resource/media';
 import { getAirportList } from '@/api/device/device';
 import { mapGetters } from 'vuex';
@@ -64,31 +69,8 @@
         dialogClickModal: false,
         delBtn: false,
         column: [
-          {
-            label: '机场选择',
-            prop: 'airportNickname',
-            type: 'select',
-            search: true,
-            searchSpan: 5,
-            dicData: [],
-            props: { label: 'nickname', value: 'nickname' },
-            hide: true,
-          },
-          {
-            label: '创建日期',
-            prop: 'daterange',
-            type: 'daterange',
-            search: true,
-            searchRange: true,
-            searchSpan: 6,
-            format: 'YYYY-MM-DD',
-            valueFormat: 'YYYY-MM-DD',
-            startPlaceholder: '开始时间',
-            endPlaceholder: '结束时间',
-            viewDisplay: false,
-            hide: true,
-            searchValue: [defaultStartDate, defaultEndDate]
-          },
+          { label: '机场选择', prop: 'airportNickname', type: 'select', search: true, searchSpan: 5, dicData: [], props: { label: 'nickname', value: 'nickname' }, hide: true },
+          { label: '创建日期', prop: 'daterange', type: 'daterange', search: true, searchRange: true, searchSpan: 6, format: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD', startPlaceholder: '开始时间', endPlaceholder: '结束时间', viewDisplay: false, hide: true, searchValue: [defaultStartDate, defaultEndDate] },
           { label: '任务名称', prop: 'job_name' },
           { label: '文件名称', prop: 'file_name' },
           { label: '拍摄时间', prop: 'create_time' },
@@ -102,25 +84,15 @@
         submitBtn: false,
         emptyBtn: false,
         column: [
-          {
-            label: '任务上传',
-            prop: 'taskFile',
-            type: 'upload',
-            drag: true,
-            loadText: '任务上传中,请稍等',
-            span: 24,
-            propsHttp: { res: 'data' },
-            action: '/blade-resource/oss/endpoint/put-file-task',
-          },
+          { label: '任务上传', prop: 'taskFile', type: 'upload', drag: true, loadText: '任务上传中,请稍等', span: 24, propsHttp: { res: 'data' }, action: '/blade-resource/oss/endpoint/put-file-task' },
         ],
       },
       domainUrl: '',
+      isDownloading: false, // 控制按钮加载状态
     };
   },
   computed: {
-    func() {
-      return func;
-    },
+    func() { return func; },
     ...mapGetters(['permission']),
     permissionList() {
       return {
@@ -130,9 +102,7 @@
         delBtn: this.validData(this.permission.attach_delete, false),
       };
     },
-    ids() {
-      return this.selectionList.map(ele => ele.id).join(',');
-    },
+    ids() { return this.selectionList.map(ele => ele.id).join(','); },
   },
   mounted() {
     this.loadAirportList();
@@ -165,38 +135,25 @@
     async handleRowDownload(row) {
       const mediaUrl = this.domainUrl + row.object_key;
       try {
-        // 使用 fetch 获取文件,确保触发下载而不是查看
         const response = await fetch(mediaUrl);
         if (!response.ok) throw new Error('文件下载失败');
-
         const blob = await response.blob();
         const url = window.URL.createObjectURL(blob);
         const link = document.createElement('a');
         link.href = url;
-        link.download = row.file_name || 'download'; // 设置下载文件名
+        link.download = row.file_name || 'download';
         document.body.appendChild(link);
         link.click();
         document.body.removeChild(link);
-        window.URL.revokeObjectURL(url); // 释放 URL 对象
-
-        this.$message({
-          type: 'success',
-          message: '文件下载成功: ' + row.file_name
-        });
+        window.URL.revokeObjectURL(url);
+        this.$message({ type: 'success', message: '文件下载成功: ' + row.file_name });
       } catch (error) {
         console.error('下载文件时出错:', error);
-        this.$message({
-          type: 'error',
-          message: '下载失败: ' + error.message
-        });
+        this.$message({ type: 'error', message: '下载失败: ' + error.message });
       }
     },
     handleRowDelete(row) {
-      this.$confirm('确定删除此文件?', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning',
-      })
+      this.$confirm('确定删除此文件?', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
         .then(() => deleteAllFile(row.id))
         .then(() => {
           this.onLoad(this.page);
@@ -208,11 +165,7 @@
         });
     },
     rowDel(row) {
-      this.$confirm('确定将选择数据及对应的文件删除?', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning',
-      })
+      this.$confirm('确定将选择数据及对应的文件删除?', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
         .then(() => deleteAllFile(row.id))
         .then(() => {
           this.onLoad(this.page);
@@ -321,7 +274,7 @@
       const mediaUrl = this.domainUrl + row.object_key;
       const mediaType = this.getMediaType(row.object_key);
       if (mediaType === 'image' || mediaType === 'video') {
-        window.open(mediaUrl, '_blank'); // 查看功能,打开新窗口
+        window.open(mediaUrl, '_blank');
       }
     },
     getMediaType(objectKey) {
@@ -337,22 +290,62 @@
         submitBtn: false,
         emptyBtn: false,
         column: [
-          {
-            label: '视频播放',
-            prop: 'videoUrl',
-            type: 'video',
-            span: 24,
-            props: { controls: true, autoplay: false },
-          },
+          { label: '视频播放', prop: 'videoUrl', type: 'video', span: 24, props: { controls: true, autoplay: false } },
         ],
       };
     },
     validData(val, def) {
       return typeof val !== 'undefined' ? val : def;
     },
+    async handleZipDownload() {
+      if (this.selectionList.length === 0) {
+        this.$message({ type: 'warning', message: '请先选择需要下载的文件' });
+        return;
+      }
+
+      this.isDownloading = true;
+
+      try {
+        const zip = new JSZip();
+        const files = this.selectionList.map(item => ({
+          url: this.domainUrl + item.object_key,
+          name: item.file_name
+        }));
+
+        const fetchPromises = files.map(async file => {
+          const response = await fetch(file.url, { cache: 'force-cache' });
+          if (!response.ok) throw new Error(`下载文件 ${file.name} 失败`);
+          const blob = await response.blob();
+          zip.file(file.name, blob);
+        });
+
+        await Promise.all(fetchPromises);
+
+        const content = await zip.generateAsync({
+          type: 'blob',
+          compression: 'DEFLATE',
+          compressionOptions: { level: 1 }
+        });
+
+        const url = window.URL.createObjectURL(content);
+        const link = document.createElement('a');
+        link.href = url;
+        link.download = `media_files_${new Date().toISOString().slice(0, 10)}_${new Date().getTime()}.zip`;
+        document.body.appendChild(link);
+        link.click();
+        document.body.removeChild(link);
+        window.URL.revokeObjectURL(url);
+
+        this.$message({ type: 'success', message: `成功下载 ${this.selectionList.length} 个文件` });
+      } catch (error) {
+        console.error('压缩下载失败:', error);
+        this.$message({ type: 'error', message: '压缩下载失败: ' + error.message });
+      } finally {
+        this.isDownloading = false;
+      }
+    },
   },
 };
 </script>
 
-<style>
-</style>
\ No newline at end of file
+<style></style>
\ No newline at end of file

--
Gitblit v1.9.3