Commit 18ed921e authored by jiyonggang's avatar jiyonggang

添加上传资源页面

parent b71750aa
...@@ -530,23 +530,45 @@ export function updateDirectory() { ...@@ -530,23 +530,45 @@ export function updateDirectory() {
}) })
} }
export function getCount() { export function getMaterialCount(params) {
return request({ return request({
url: 'http://localhost:8567/material/count', url: 'http://localhost:8567/material/count',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/updateDirectory', // url: 'https://putinapi.zhangxindiet.com/business/youtube/updateDirectory',
method: 'get', method: 'get',
params
}) })
} }
export function movematerial(params) {
return request({
url: 'http://localhost:8567/material/business/youtube/movematerial',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/updateDirectory',
method: 'get',
params
})
}
export function deleteDirectory() { export function deleteDirectory(params) {
return request({ return request({
url: 'http://localhost:8567/business/youtube/deleteDirectory', url: 'http://localhost:8567/material/business/youtube/deleteDirectory',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/deleteDirectory', // url: 'https://putinapi.zhangxindiet.com/business/youtube/deleteDirectory',
method: 'get', method: 'get',
params
}) })
} }
export function uploadMaterial(body,params){
return request({
url: 'http://localhost:8567/material/business/youtube/uploadVideo',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/deleteDirectory',
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: body, // Body 数据
params: params // 查询参数
})
}
// ---------------------------------------- // ----------------------------------------
...@@ -5,11 +5,7 @@ ...@@ -5,11 +5,7 @@
<el-aside width="250px" class="aside"> <el-aside width="250px" class="aside">
<div class="directory-header"> <div class="directory-header">
<span>素材目录</span> <span>素材目录</span>
<el-button <el-button type="text" size="small" @click="showNewDirDialog(null)">
type="text"
size="small"
@click="showNewDirDialog(null)"
>
<i class="el-icon-plus"></i> 新建目录 <i class="el-icon-plus"></i> 新建目录
</el-button> </el-button>
</div> </div>
...@@ -49,28 +45,11 @@ ...@@ -49,28 +45,11 @@
<div class="current-path"> <div class="current-path">
当前位置:{{ currentPath }} 当前位置:{{ currentPath }}
</div> </div>
<el-upload <el-button type="primary" @click="showUploadVideoDialog">上传视频</el-button>
ref="upload"
:action="uploadUrl"
:data="{ directoryId: currentDirectory }"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:before-upload="beforeUpload"
multiple
:show-file-list="false"
>
<el-button type="primary" :disabled="!currentDirectory">
<i class="el-icon-upload"></i> 上传文件
</el-button>
</el-upload>
</div> </div>
<!-- 文件列表 --> <!-- 文件列表 -->
<el-table <el-table v-loading="loading" :data="materials" style="width: 100%">
v-loading="loading"
:data="materials"
style="width: 100%"
>
<el-table-column label="预览" width="120"> <el-table-column label="预览" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<div class="preview-container"> <div class="preview-container">
...@@ -78,7 +57,7 @@ ...@@ -78,7 +57,7 @@
v-if="scope.row.resType === 1" v-if="scope.row.resType === 1"
:src="scope.row.url" :src="scope.row.url"
class="preview-image" class="preview-image"
> />
<video <video
v-else-if="scope.row.resType === 2" v-else-if="scope.row.resType === 2"
:src="scope.row.url" :src="scope.row.url"
...@@ -95,11 +74,6 @@ ...@@ -95,11 +74,6 @@
{{ scope.row.resType === 1 ? '图片' : scope.row.resType === 2 ? '视频' : '' }} {{ scope.row.resType === 1 ? '图片' : scope.row.resType === 2 ? '视频' : '' }}
</template> </template>
</el-table-column> </el-table-column>
<!-- <el-table-column prop="size" label="大小" width="100">-->
<!-- <template slot-scope="scope">-->
<!-- {{ formatFileSize(scope.row.size) }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="createdAt" label="上传时间" width="180"> <el-table-column prop="createdAt" label="上传时间" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
{{ formatDate(scope.row.createdAt) }} {{ formatDate(scope.row.createdAt) }}
...@@ -108,25 +82,35 @@ ...@@ -108,25 +82,35 @@
<el-table-column prop="realName" label="创作者"></el-table-column> <el-table-column prop="realName" label="创作者"></el-table-column>
<el-table-column label="操作" width="150"> <el-table-column label="操作" width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button size="mini" type="text" @click="showMoveDialog(scope.row)">
size="mini" 移动
type="text" </el-button>
@click="showMoveDialog(scope.row)" <el-button size="mini" type="text" @click="handlePreview(scope.row)">
>移动</el-button> 预览
<el-button </el-button>
size="mini"
type="text"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
class="delete-btn" class="delete-btn"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
>删除</el-button> >
删除
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 -->
<el-pagination
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalCount"
>
</el-pagination>
</el-main> </el-main>
</el-container> </el-container>
...@@ -148,11 +132,7 @@ ...@@ -148,11 +132,7 @@
</el-dialog> </el-dialog>
<!-- 移动文件弹窗 --> <!-- 移动文件弹窗 -->
<el-dialog <el-dialog title="移动到" :visible.sync="moveDialogVisible" width="30%">
title="移动到"
:visible.sync="moveDialogVisible"
width="30%"
>
<el-tree <el-tree
ref="moveTree" ref="moveTree"
:data="directories" :data="directories"
...@@ -175,28 +155,82 @@ ...@@ -175,28 +155,82 @@
> >
<div class="preview-content"> <div class="preview-content">
<img <img
v-if="previewFile && previewFile.type === 'image'" v-if="previewFile && previewFile.resType === 1"
:src="previewFile.url" :src="previewFile.url"
class="preview-image" class="preview-image"
> />
<video <video
v-else-if="previewFile && previewFile.type === 'video'" v-else-if="previewFile && previewFile.resType === 2"
:src="previewFile.url" :src="previewFile.url"
controls controls
class="preview-video" class="preview-video"
></video> >
</video>
</div> </div>
</el-dialog> </el-dialog>
<!-- 上传视频弹窗 -->
<el-dialog title="上传视频" :visible.sync="uploadVideoDialogVisible" width="40%">
<el-form ref="uploadVideoForm" :model="uploadVideoForm" label-width="120px">
<el-form-item label="选择文件" prop="file" :rules="[{ required: true, message: '请选择文件', trigger: 'change' }]">
<el-upload
class="upload-demo"
ref="uploadVideo"
:action="uploadVideoUrl"
:on-change="handleFileChange"
:auto-upload="false"
:file-list="fileList"
:limit="1"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能上传视频文件,且不超过100MB</div>
</el-upload>
</el-form-item>
<el-form-item label="素材名称" prop="materialName" :rules="[{ required: true, message: '请输入素材名称', trigger: 'blur' }]">
<el-input v-model="uploadVideoForm.materialName" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="标签" prop="tags">
<el-input v-model="uploadVideoForm.tags" autocomplete="off" placeholder="多个标签请用英文逗号分隔"></el-input>
</el-form-item>
<el-form-item label="创作者" prop="director">
<el-input-number v-model="uploadVideoForm.director" :min="0" placeholder="请输入创作者ID"></el-input-number>
</el-form-item>
<el-form-item label="类型" prop="resType" :rules="[{ required: true, message: '请选择类型', trigger: 'change' }]">
<el-select v-model="uploadVideoForm.resType" placeholder="请选择">
<el-option label="图片" :value="1"></el-option>
<el-option label="视频" :value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目录" prop="directoryId" :rules="[{ required: true, message: '请选择目录', trigger: 'change' }]">
<el-cascader
v-model="selectedDirectoryIds"
:options="directories"
:props="{ expandTrigger: 'hover', value:'id',label:'name', children:'children' }"
clearable
@change="handleDirectoryChange"
placeholder="请选择目录"
style="width: 100%;"
></el-cascader>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="uploadVideoDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitUpload">确 定</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { import {
getMaterialDirectoriesTree, getMaterialDirectoriesTree,
getDirectoryById,
createDirectory, createDirectory,
updateDirectory, deleteDirectory,
deleteDirectory getDirectoryById,
getMaterialCount,
movematerial,
uploadMaterial
} from '@/api/report'; } from '@/api/report';
export default { export default {
...@@ -241,94 +275,118 @@ export default { ...@@ -241,94 +275,118 @@ export default {
previewFile: null, previewFile: null,
// 上传相关 // 上传相关
uploadUrl: '/api/materials/upload'
}
// 分页相关
currentPage: 1,
pageSize: 10,
totalCount: 0,
includeSubdirectories: true,
selectedDirectoryIds: [],
uploadVideoDialogVisible: false, // 控制上传视频弹窗的显示和隐藏
uploadVideoForm: { // 上传视频表单数据
file: null,
materialName: '',
tags: '',
director: null,
resType: null,
directoryId: null
},
fileList:[],
uploadVideoUrl: 'http://localhost:8567/material/business/youtube/uploadVideo',
};
}, },
created() { created() {
this.fetchDirectories() this.fetchDirectories();
}, },
methods: { methods: {
fetchDirectories(){ fetchDirectories() {
getMaterialDirectoriesTree().then(res => { getMaterialDirectoriesTree().then(res => {
if (res.status === 200) { if (res.status === 200) {
this.directories= res.result.data this.directories = res.result.data;
}else { } else {
this.$message.error('获取目录失败') this.$message.error('获取目录失败');
} }
}); });
},
// 获取当前目录下的文件
async fetchMaterials(directoryId) {
this.loading = true
try {
const response = await this.request({
url: '/api/materials',
method: 'get',
params: { directoryId }
})
this.materials = response.data
} catch (error) {
this.$message.error('获取文件列表失败')
console.error('获取文件列表失败:', error)
} finally {
this.loading = false
}
}, },
handleSizeChange(val) {
this.pageSize = val;
this.currentPage = 1; // 改变每页条数后,通常需要重置当前页码为 1
this.fetchMaterialsByDirectoryId(this.currentDirectory);
},
// 处理目录点击 // 处理目录点击
handleNodeClick(data) { handleNodeClick(data) {
this.currentDirectory = data.id this.currentDirectory = data.id;
this.currentPath = this.getNodePath(data) this.currentPath = this.getNodePath(data);
this.currentPage = 1; // 重置当前页码为 1
this.fetchMaterialsByDirectoryId(data.id); this.fetchMaterialsByDirectoryId(data.id);
}, },
fetchMaterialsByDirectoryId(directoryId) {
// 获取数据(包含总数和分页数据)
async fetchMaterialsByDirectoryId(directoryId) {
this.loading = true; this.loading = true;
getDirectoryById({ try {
directoryId: directoryId, // 先获取总数
pageNum: 1, const countResponse = await getMaterialCount({
pageSize: 10, directoryId: directoryId,
includeSubdirectories: true includeSubdirectories: this.includeSubdirectories
})
.then(response => {
if (response && response.status === 200) {
this.materials = response.result.data;
} else {
this.$message.error(response.msg || '获取素材列表失败');
console.error('获取素材列表失败:', response);
}
})
.catch(error => {
this.$message.error('获取素材列表失败');
console.error('获取素材列表失败:', error);
})
.finally(() => {
this.loading = false;
}); });
}, console.log("getMaterialCount response:", countResponse);
if (countResponse && countResponse.status === 200) {
this.totalCount = countResponse.result;
} else {
this.$message.error(countResponse.msg || '获取总数失败');
console.error('获取总数失败:', countResponse);
}
// 再获取数据
const dataResponse = await getDirectoryById({
directoryId: directoryId,
pageNum: this.currentPage,
pageSize: this.pageSize,
includeSubdirectories: this.includeSubdirectories
});
if (dataResponse && dataResponse.status === 200) {
this.materials = dataResponse.result.data;
} else {
this.$message.error(dataResponse.msg || '获取素材列表失败');
console.error('获取素材列表失败:', dataResponse);
}
} catch (error) {
this.$message.error('获取数据失败');
console.error('获取数据失败:', error);
} finally {
this.loading = false;
}
},
// 翻页
handleCurrentChange(val) {
this.currentPage = val;
this.fetchMaterialsByDirectoryId(this.currentDirectory);
},
// 获取节点路径 // 获取节点路径
getNodePath(node) { getNodePath(node) {
const path = [] const path = [];
let currentNode = node let currentNode = node;
while (currentNode) { while (currentNode) {
path.unshift(currentNode.name) path.unshift(currentNode.name);
currentNode = currentNode.parent currentNode = currentNode.parent;
} }
return path.join(' / ') return path.join(' / ');
}, },
// 显示新建目录弹窗 // 显示新建目录弹窗
showNewDirDialog(parentId) { showNewDirDialog(parentId) {
this.parentId = parentId this.parentId = parentId;
this.newDirForm.name = '' this.newDirForm.name = '';
this.newDirForm.parentId = parentId this.newDirForm.parentId = parentId;
this.newDirDialogVisible = true this.newDirDialogVisible = true;
}, },
// 创建目录 // 创建目录
...@@ -340,7 +398,12 @@ export default { ...@@ -340,7 +398,12 @@ export default {
parentId: this.newDirForm.parentId parentId: this.newDirForm.parentId
}) })
.then(response => { .then(response => {
if (response && response.status === 200 && response.result && response.result.data) { if (
response &&
response.status === 200 &&
response.result &&
response.result.data
) {
this.$message.success('创建成功'); this.$message.success('创建成功');
this.newDirDialogVisible = false; this.newDirDialogVisible = false;
this.fetchDirectories(); this.fetchDirectories();
...@@ -358,102 +421,101 @@ export default { ...@@ -358,102 +421,101 @@ export default {
// 删除目录 // 删除目录
handleDeleteDirectory(node, data) { handleDeleteDirectory(node, data) {
this.$confirm('确认删除该目录吗?其下的所有文件将被移动到根目录', '提示', { this.$confirm('确认删除该目录吗?其下的所有文件将被删除', '提示', {
type: 'warning' type: 'warning'
}).then(async () => { })
try { .then(async () => {
const response = await deleteDirectory(data.id); try {
if (response.code === 0) { // Assuming your API uses a code for success/failure const response = await deleteDirectory({id:data.id});
this.$message.success('删除成功'); if (response.code === 0) {
await this.fetchDirectories(); // 重新获取目录树 this.$message.success('删除成功');
// 如果删除的是当前选中的目录,清空文件列表 await this.fetchDirectories(); // 重新获取目录树
if (data.id === this.currentDirectory) { // 如果删除的是当前选中的目录,清空文件列表
this.materials = []; if (data.id === this.currentDirectory) {
this.currentDirectory = null; this.materials = [];
this.currentPath = '根目录'; this.currentDirectory = null;
this.currentPath = '根目录';
}
} else {
this.$message.error(response.message || '删除失败');
} }
} else { } catch (error) {
this.$message.error(response.message || '删除失败'); this.$message.error('删除失败');
console.error('删除目录失败:', error);
} }
} catch (error) { })
this.$message.error('删除失败'); .catch(() => {});
console.error('删除目录失败:', error);
}
}).catch(() => { });
}, },
// 上传前验证 // 上传前验证
beforeUpload(file) { beforeUpload(file) {
const isImage = file.type.startsWith('image/') const isImage = file.type.startsWith('image/');
const isVideo = file.type.startsWith('video/') const isVideo = file.type.startsWith('video/');
const isLt100M = file.size / 1024 / 1024 < 100 const isLt100M = file.size / 1024 / 1024 < 100;
if (!isImage && !isVideo) { if (!isImage && !isVideo) {
this.$message.error('只能上传图片或视频文件!') this.$message.error('只能上传图片或视频文件!');
return false return false;
} }
if (!isLt100M) { if (!isLt100M) {
this.$message.error('文件大小不能超过 100MB!') this.$message.error('文件大小不能超过 100MB!');
return false return false;
} }
return true return true;
}, },
// 处理上传成功 // 处理上传成功
async handleUploadSuccess(response, file, fileList) { async handleUploadSuccess(response, file, fileList) {
// Assuming your upload API returns the uploaded file data on success if (response.code === 0) {
if (response.code === 0) { // Check for success code from your API this.$message.success('上传成功');
this.$message.success('上传成功') await this.fetchMaterials(this.currentDirectory); // 重新获取文件列表
await this.fetchMaterials(this.currentDirectory) // 重新获取文件列表
} else { } else {
this.$message.error(response.message || '上传失败') this.$message.error(response.message || '上传失败');
} }
}, },
// 处理上传失败 // 处理上传失败
handleUploadError(err) { handleUploadError(err) {
this.$message.error('上传失败') this.$message.error('上传失败');
console.error('上传文件失败:', err) console.error('上传文件失败:', err);
}, },
// 显示移动文件弹窗 // 显示移动文件弹窗
showMoveDialog(file) { showMoveDialog(file) {
this.currentMoveFile = file this.currentMoveFile = file;
this.selectedMoveDirectory = null this.selectedMoveDirectory = null;
this.moveDialogVisible = true this.moveDialogVisible = true;
}, },
// 处理移动目标目录选择 // 处理移动目标目录选择
handleMoveNodeClick(data) { handleMoveNodeClick(data) {
this.selectedMoveDirectory = data.id this.selectedMoveDirectory = data.id;
}, },
// 确认移动文件 // 确认移动文件
async confirmMove() { async confirmMove() {
if (!this.selectedMoveDirectory) { if (!this.selectedMoveDirectory) {
this.$message.warning('请选择目标目录') this.$message.warning('请选择目标目录');
return return;
} }
try { try {
const response = await this.request({ const response = await movematerial({
url: '/api/materials/move', materialId: this.currentMoveFile.id, // 素材的 ID
method: 'post', targetDirectoryId: this.selectedMoveDirectory // 目标目录的 ID
data: {
fileId: this.currentMoveFile.id,
targetDirectoryId: this.selectedMoveDirectory
}
}); });
if (response.code === 0) {
this.$message.success('移动成功') // 移动成功
this.moveDialogVisible = false if (response && response.status === 200) {
await this.fetchMaterials(this.currentDirectory) // 重新获取当前目录的文件列表 this.$message.success("移动成功");
this.moveDialogVisible = false;
this.fetchMaterialsByDirectoryId(this.currentDirectory);
} else { } else {
this.$message.error(response.message || '移动失败') this.$message.error(response.msg || "移动失败");
} }
} catch (error) { } catch (error) {
this.$message.error('移动失败') this.$message.error('移动失败');
console.error('移动文件失败:', error) console.error('移动文件失败:', error);
} }
}, },
...@@ -461,49 +523,108 @@ export default { ...@@ -461,49 +523,108 @@ export default {
handleDelete(file) { handleDelete(file) {
this.$confirm('确认删除该文件吗?', '提示', { this.$confirm('确认删除该文件吗?', '提示', {
type: 'warning' type: 'warning'
}).then(async () => { })
try { .then(async () => {
const response = await this.request({ try {
url: '/api/materials/delete', const response = await this.request({
method: 'post', url: '/api/materials/delete',
params: { fileId: file.id } method: 'post',
}); params: { fileId: file.id }
if (response.code === 0) { });
this.$message.success('删除成功') if (response.code === 0) {
await this.fetchMaterials(this.currentDirectory) // 重新获取文件列表 this.$message.success('删除成功');
} else { await this.fetchMaterials(this.currentDirectory); // 重新获取文件列表
this.$message.error(response.message || '删除失败') } else {
this.$message.error(response.message || '删除失败');
}
} catch (error) {
this.$message.error('删除失败');
console.error('删除文件失败:', error);
} }
} catch (error) { })
this.$message.error('删除失败') .catch(() => {});
console.error('删除文件失败:', error)
}
}).catch(() => { })
}, },
// 预览文件 // 预览文件
handlePreview(file) { handlePreview(file) {
this.previewFile = file this.previewFile = file;
this.previewDialogVisible = true this.previewDialogVisible = true;
}, },
// 工具方法 - 格式化文件大小 // 工具方法 - 格式化文件大小
formatFileSize(size) { formatFileSize(size) {
if (size < 1024) { if (size < 1024) {
return size + ' B' return size + ' B';
} else if (size < 1024 * 1024) { } else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + ' KB' return (size / 1024).toFixed(2) + ' KB';
} else { } else {
return (size / 1024 / 1024).toFixed(2) + ' MB' return (size / 1024 / 1024).toFixed(2) + ' MB';
} }
}, },
// 工具方法 - 格式化日期 // 工具方法 - 格式化日期
formatDate(date) { formatDate(date) {
return new Date(date).toLocaleString() return new Date(date).toLocaleString();
} },
handleFileChange(file, fileList) {
if (fileList.length > 0) {
this.fileList = [fileList[0]]; // 只保留一个文件
this.uploadVideoForm.file = fileList[0].raw; // 将选中的文件赋值给 file 字段
}
},
async submitUpload() {
this.$refs.uploadVideoForm.validate(async (valid) => {
if (valid) {
const formData = new FormData();
formData.append('file', this.uploadVideoForm.file);
formData.append('materialName', this.uploadVideoForm.materialName);
formData.append('tags', this.uploadVideoForm.tags);
formData.append('director', this.uploadVideoForm.director);
formData.append('resType', this.uploadVideoForm.resType);
formData.append('directoryId', this.uploadVideoForm.directoryId);
try {
// 使用 uploadVideo 方法发送请求
const response = await uploadMaterial(formData);
if (response && response.status === 200) {
this.$message.success('上传成功');
this.uploadVideoDialogVisible = false;
this.fetchMaterialsByDirectoryId(this.currentDirectory); // 刷新列表
// 清空表单
this.uploadVideoForm = {
file: null,
materialName: '',
tags: '',
director: null,
resType: null,
directoryId: null
};
this.fileList = [];
this.$refs.uploadVideo.clearFiles(); // 清空上传组件的文件列表
} else {
this.$message.error(response.msg || '上传失败');
}
} catch (error) {
this.$message.error('上传失败');
console.error('上传失败:', error);
}
} else {
console.log('error submit!!');
return false;
}
});
},
// 在你的 methods 中添加一个新的方法 showUploadVideoDialog
showUploadVideoDialog() {
this.uploadVideoDialogVisible = true;
},
handleDirectoryChange(value) {
this.uploadVideoForm.directoryId = value[value.length - 1];
},
} }
} };
</script> </script>
<style scoped> <style scoped>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment