无人机管理后台前端(已迁走)
rain
2025-03-06 40550ba188593fdec9358dcdd7fe9c4ccd27333a
媒体文件打包下载
1 files modified
141 ■■■■ changed files
src/views/resource/media.vue 141 ●●●● patch | view | raw | blame | history
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>
<style></style>