| | |
| | | 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)">查看 |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import JSZip from 'jszip'; |
| | | import { getMedia, deleteAllFile } from '@/api/resource/media'; |
| | | import { getAirportList } from '@/api/device/device'; |
| | | import { mapGetters } from 'vuex'; |
| | |
| | | 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' }, |
| | |
| | | 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 { |
| | |
| | | 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(); |
| | |
| | | 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); |
| | |
| | | }); |
| | | }, |
| | | rowDel(row) { |
| | | this.$confirm('确定将选择数据及对应的文件删除?', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning', |
| | | }) |
| | | this.$confirm('确定将选择数据及对应的文件删除?', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) |
| | | .then(() => deleteAllFile(row.id)) |
| | | .then(() => { |
| | | this.onLoad(this.page); |
| | |
| | | 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) { |
| | |
| | | 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> |