From 8eba7f2a5f54500f632511d8db114c2a9931b916 Mon Sep 17 00:00:00 2001
From: rain <167982779@qq.com>
Date: Thu, 27 Feb 2025 17:30:43 +0800
Subject: [PATCH] 媒体文件页面
---
src/api/media/media.js | 33 ++++
src/api/device/device.js | 10
src/views/resource/media.vue | 378 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 418 insertions(+), 3 deletions(-)
diff --git a/src/api/device/device.js b/src/api/device/device.js
index cd84c9a..f21e186 100644
--- a/src/api/device/device.js
+++ b/src/api/device/device.js
@@ -66,8 +66,6 @@
});
};
-
-
export const getDeviceUpgradeInfo = (params) => {
return request({
url: '/drone-yw/manage/api/v1/workspaces/firmware-release-notes/latest',
@@ -83,7 +81,6 @@
data: row,
});
};
-
export const getDeviceFirmwareList = (current, size, params) => {
return request({
@@ -129,4 +126,11 @@
url: `/drone-yw/manage/api/v1/devices/${workspace_id}/devices/${device_sn}`,
method: 'get',
});
+};
+
+export const getAirportList = () => {
+ return request({
+ url: '/drone-yw/manage/api/v1/devices/getAirportList',
+ method: 'get',
+ });
};
\ No newline at end of file
diff --git a/src/api/media/media.js b/src/api/media/media.js
new file mode 100644
index 0000000..1c16745
--- /dev/null
+++ b/src/api/media/media.js
@@ -0,0 +1,33 @@
+import request from '@/axios';
+
+export const getMedia = (page, page_size, workspace_id = null, create_time = null, end_time = null) => {
+ return request({
+ url: '/drone-yw/media/api/v1/files/filesByUser',
+ method: 'get',
+ params: {
+ page,
+ page_size,
+ workspace_id,
+ create_time,
+ end_time,
+ },
+ });
+};
+
+export const getFilesByWorkspace = (workspace_id, page, page_size) => {
+ return request({
+ url: `/drone-yw/media/api/v1/files/${workspace_id}/files`,
+ method: 'get',
+ params: {
+ page,
+ page_size,
+ },
+ });
+};
+
+export const deleteAllFile = (id) => {
+ return request({
+ url: `/drone-yw/media/api/v1/files/deleteAllFile?id=${id}`,
+ method: 'delete',
+ });
+};
diff --git a/src/views/resource/media.vue b/src/views/resource/media.vue
new file mode 100644
index 0000000..205dfe0
--- /dev/null
+++ b/src/views/resource/media.vue
@@ -0,0 +1,378 @@
+<template>
+ <basic-container>
+ <avue-crud :option="option" :table-loading="loading" :data="data" v-model:page="page" :permission="permissionList"
+ 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="scope">
+ <el-button type="primary" text icon="el-icon-view" v-if="permission.attach_delete"
+ @click="handleRowView(scope.row)">查看
+ </el-button>
+ <el-button type="danger" text icon="el-icon-delete" v-if="permission.attach_delete"
+ @click="handleRowDelete(scope.row)">删除
+ </el-button>
+ </template>
+ </avue-crud>
+ <el-dialog title="媒体文件" append-to-body v-model="taskBox" width="555px">
+ <avue-form ref="form" :option="taskOption" v-model="taskForm" :upload-after="uploadAfter">
+ </avue-form>
+ </el-dialog>
+ </basic-container>
+</template>
+
+<script>
+import { getMedia, deleteAllFile } from '@/api/media/media'; // 导入媒体相关的 API 方法
+import { getAirportList } from '@/api/device/device'; // 导入设备相关的 API 方法
+import { mapGetters } from 'vuex'; // 从 Vuex 导入 mapGetters
+import func from '@/utils/func'; // 导入工具函数
+
+export default {
+ data() {
+ return {
+ form: {}, // 表单数据对象
+ query: {}, // 搜索查询条件
+ loading: true, // 表格加载状态
+ page: { // 分页数据
+ pageSize: 10, // 每页显示数量
+ currentPage: 1, // 当前页码
+ total: 0, // 总记录数
+ },
+ taskBox: false, // 控制弹窗显示状态
+ selectionList: [], // 选中的行数据列表
+ selectedWorkspaceId: null, // 选中的工作区 ID
+ option: { // Avue CRUD 表格配置
+ height: 'auto', // 表格高度自动调整
+ calcHeight: 32, // 计算高度的偏移量
+ tip: false, // 不显示提示
+ searchShow: true, // 显示搜索栏
+ searchMenuSpan: 6,// 搜索栏宽度占比
+ border: true, // 显示边框
+ index: true, // 显示序号列
+ viewBtn: true, // 显示查看按钮
+ selection: true, // 允许多选
+ 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, // 默认隐藏
+ value: [new Date(new Date().setMonth(new Date().getMonth() - 1)), new Date()], // 默认值:过去一个月至今
+ },
+ { label: '任务名称', prop: 'job_name' }, // 任务名称列
+ { label: '文件名称', prop: 'file_name' }, // 文件名称列
+ { label: '拍摄时间', prop: 'create_time' }, // 拍摄时间列
+ { label: '文件路径', prop: 'object_key' }, // 文件路径列
+ { label: '设备负载', prop: 'payload' }, // 设备负载列
+ ],
+ },
+ data: [], // 表格数据
+ taskForm: {}, // 弹窗表单数据
+ taskOption: { // 弹窗表单配置
+ submitBtn: false, // 不显示提交按钮
+ emptyBtn: false, // 不显示清空按钮
+ column: [ // 表单列配置
+ {
+ label: '任务上传', // 上传字段标题
+ prop: 'taskFile', // 数据字段
+ type: 'upload', // 上传类型
+ drag: true, // 支持拖拽上传
+ loadText: '任务上传中,请稍等', // 上传中提示
+ span: 24, // 占用整行
+ propsHttp: { // HTTP 响应映射
+ res: 'data',
+ },
+ action: '/blade-resource/oss/endpoint/put-file-task', // 上传接口地址
+ },
+ ],
+ },
+ domainUrl: '', // 媒体文件域名,从 API 获取
+ };
+ },
+ computed: {
+ func() { // 计算属性,返回工具函数
+ return func;
+ },
+ ...mapGetters(['permission']), // 从 Vuex 获取权限数据
+ permissionList() { // 计算权限列表
+ return {
+ addBtn: false, // 不显示添加按钮
+ editBtn: false, // 不显示编辑按钮
+ viewBtn: this.validData(this.permission.attach_view, false), // 查看权限
+ delBtn: this.validData(this.permission.attach_delete, false), // 删除权限
+ };
+ },
+ ids() { // 计算选中的行 ID 列表
+ let ids = [];
+ this.selectionList.forEach(ele => {
+ ids.push(ele.id);
+ });
+ return ids.join(',');
+ },
+ },
+ mounted() { // 组件挂载时执行
+ this.loadAirportList(); // 加载机场列表
+ this.onLoad(this.page); // 加载初始数据
+ },
+ methods: {
+ // 加载机场下拉列表数据
+ loadAirportList() {
+ getAirportList().then(res => {
+ const airportData = res.data.data || [];
+ const airportColumn = this.option.column.find(col => col.prop === 'airportNickname');
+ if (airportColumn) {
+ airportColumn.dicData = airportData.map(item => ({
+ nickname: item.nickname,
+ workspace_id: item.workspace_id,
+ }));
+ }
+ }).catch(error => {
+ console.error('加载机场列表时出错:', error);
+ });
+ },
+ // 打开上传弹窗
+ handleUpload() {
+ this.taskBox = true;
+ },
+ // 处理上传完成后的操作
+ uploadAfter(res, done) {
+ this.taskBox = false; // 关闭弹窗
+ this.refreshChange(); // 刷新表格
+ done(); // 完成上传
+ },
+ // 删除单行数据
+ handleRowDelete(row) {
+ this.$confirm('确定删除此文件?', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then(() => {
+ return deleteAllFile(row.id); // 调用删除 API
+ })
+ .then(() => {
+ this.onLoad(this.page); // 重新加载数据
+ this.$message({
+ type: 'success',
+ message: '删除成功!',
+ });
+ })
+ .catch(error => {
+ console.error('删除文件时出错:', error);
+ this.$message({
+ type: 'error',
+ message: '删除失败,请稍后重试!',
+ });
+ });
+ },
+ // 删除行(由 avue-crud 触发)
+ rowDel(row) {
+ this.$confirm('确定将选择数据及对应的文件删除?', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then(() => {
+ return deleteAllFile(row.id); // 调用删除 API
+ })
+ .then(() => {
+ this.onLoad(this.page); // 重新加载数据
+ this.$message({
+ type: 'success',
+ message: '操作成功!',
+ });
+ });
+ },
+ // 重置搜索条件
+ searchReset() {
+ this.query = {};
+ this.selectedWorkspaceId = null;
+ this.onLoad(this.page);
+ },
+ // 处理搜索条件变化
+ searchChange(params, done) {
+ this.query = params;
+ this.page.currentPage = 1;
+
+ const airportColumn = this.option.column.find(col => col.prop === 'airportNickname');
+ const selectedAirport = airportColumn.dicData.find(item => item.nickname === params.airportNickname);
+ this.selectedWorkspaceId = selectedAirport ? selectedAirport.workspace_id : null;
+
+ this.onLoad(this.page, params);
+ done();
+ },
+ // 更新选中的行列表
+ selectionChange(list) {
+ this.selectionList = list;
+ },
+ // 清空选择
+ selectionClear() {
+ this.selectionList = [];
+ this.$refs.crud.toggleSelection();
+ },
+ // 处理页码变化
+ currentChange(currentPage) {
+ this.page.currentPage = currentPage;
+ this.onLoad(this.page, this.query);
+ },
+ // 处理每页数量变化
+ sizeChange(pageSize) {
+ this.page.pageSize = pageSize;
+ this.onLoad(this.page, this.query);
+ },
+ // 刷新表格数据
+ refreshChange() {
+ this.onLoad(this.page, this.query);
+ },
+ // 从 API 加载表格数据
+ onLoad(page, params = {}) {
+ this.loading = true;
+ const { daterange } = params;
+ let create_time = this.create_time;
+ let end_time = this.end_time;
+
+ if (daterange && Array.isArray(daterange) && daterange.length === 2) {
+ const startStr = daterange[0];
+ const endStr = daterange[1];
+ const startDate = new Date(startStr + ' 00:00:00').getTime();
+ const endDate = new Date(endStr + ' 23:59:59').getTime();
+ if (!isNaN(startDate) && !isNaN(endDate)) {
+ create_time = startDate;
+ end_time = endDate;
+ }
+ }
+
+ let values = {
+ ...params,
+ ...this.query,
+ };
+ if (daterange) {
+ values.daterange = null;
+ }
+
+ getMedia(
+ page.currentPage,
+ page.pageSize,
+ this.selectedWorkspaceId || null,
+ create_time,
+ end_time
+ ).then(res => {
+ const data = res.data;
+ if (data && data.data && data.data.list) {
+ this.page.total = data.data.pagination.total;
+ this.data = data.data.list.map(item => ({
+ job_name: item.job_name,
+ file_name: item.file_name,
+ create_time: this.formatCreateTime(item.create_time),
+ object_key: item.object_key,
+ payload: item.payload,
+ airportNickname: item.airportNickname,
+ id: item.id,
+ }));
+ this.domainUrl = data.data.list.length > 0 ? data.data.list[0].domain_url : 'http://localhost:2888/manage/resource'; // 设置域名
+ } else {
+ this.data = [];
+ }
+ this.loading = false;
+ this.selectionClear();
+ this.$refs.crud.refreshTable();
+ }).catch(error => {
+ this.loading = false;
+ console.error('加载媒体数据时出错:', error);
+ });
+ },
+ // 格式化时间戳为可读日期
+ formatCreateTime(createTime) {
+ if (typeof createTime !== 'number' || isNaN(createTime)) {
+ return '';
+ }
+ const timestamp = createTime < 10000000000 ? createTime * 1000 : createTime;
+ const date = new Date(timestamp);
+ if (isNaN(date.getTime())) {
+ return '';
+ }
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+ const seconds = String(date.getSeconds()).padStart(2, '0');
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+ },
+ // 处理查看行(打开图片或视频)
+ handleRowView(row) {
+ const mediaUrl = this.domainUrl + row.object_key; // 拼接完整媒体 URL
+ const mediaType = this.getMediaType(row.object_key); // 判断媒体类型
+
+ if (mediaType === 'image') {
+ window.open(mediaUrl, '_blank'); // 图片在新窗口打开
+ } else if (mediaType === 'video') {
+ // 临时测试:视频也在新窗口打开
+ window.open(mediaUrl, '_blank');
+ // this.showVideo(mediaUrl); // 原逻辑:视频在弹窗中播放
+ }
+ },
+ // 判断文件是图片还是视频
+ getMediaType(objectKey) {
+ const extension = objectKey.split('.').pop().toLowerCase(); // 获取文件扩展名
+ if (['jpg', 'jpeg', 'png', 'gif'].includes(extension)) {
+ return 'image'; // 是图片
+ } else if (['mp4', 'avi', 'mov'].includes(extension)) {
+ return 'video'; // 是视频
+ }
+ return 'unknown'; // 未知类型
+ },
+ // 在弹窗中显示视频
+ showVideo(url) {
+ this.taskBox = true; // 打开弹窗
+ this.taskForm = {
+ videoUrl: url, // 设置视频 URL
+ };
+ this.taskOption = { // 配置视频播放选项
+ submitBtn: false,
+ emptyBtn: false,
+ column: [
+ {
+ label: '视频播放',
+ prop: 'videoUrl',
+ type: 'video',
+ span: 24,
+ props: {
+ controls: true, // 显示控制条
+ autoplay: false, // 不自动播放
+ },
+ },
+ ],
+ };
+ },
+ // 检查权限有效性(假设这是定义在其他地方的工具方法)
+ validData(val, def) {
+ return typeof val !== 'undefined' ? val : def;
+ },
+ },
+};
+</script>
+
+<style></style>
\ No newline at end of file
--
Gitblit v1.9.3