Commit 18ed921e authored by jiyonggang's avatar jiyonggang

添加上传资源页面

parent b71750aa
......@@ -530,23 +530,45 @@ export function updateDirectory() {
})
}
export function getCount() {
export function getMaterialCount(params) {
return request({
url: 'http://localhost:8567/material/count',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/updateDirectory',
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({
url: 'http://localhost:8567/business/youtube/deleteDirectory',
url: 'http://localhost:8567/material/business/youtube/deleteDirectory',
// url: 'https://putinapi.zhangxindiet.com/business/youtube/deleteDirectory',
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 @@
<el-aside width="250px" class="aside">
<div class="directory-header">
<span>素材目录</span>
<el-button
type="text"
size="small"
@click="showNewDirDialog(null)"
>
<el-button type="text" size="small" @click="showNewDirDialog(null)">
<i class="el-icon-plus"></i> 新建目录
</el-button>
</div>
......@@ -49,28 +45,11 @@
<div class="current-path">
当前位置:{{ currentPath }}
</div>
<el-upload
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>
<el-button type="primary" @click="showUploadVideoDialog">上传视频</el-button>
</div>
<!-- 文件列表 -->
<el-table
v-loading="loading"
:data="materials"
style="width: 100%"
>
<el-table v-loading="loading" :data="materials" style="width: 100%">
<el-table-column label="预览" width="120">
<template slot-scope="scope">
<div class="preview-container">
......@@ -78,7 +57,7 @@
v-if="scope.row.resType === 1"
:src="scope.row.url"
class="preview-image"
>
/>
<video
v-else-if="scope.row.resType === 2"
:src="scope.row.url"
......@@ -95,11 +74,6 @@
{{ scope.row.resType === 1 ? '图片' : scope.row.resType === 2 ? '视频' : '' }}
</template>
</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">
<template slot-scope="scope">
{{ formatDate(scope.row.createdAt) }}
......@@ -108,25 +82,35 @@
<el-table-column prop="realName" label="创作者"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="showMoveDialog(scope.row)"
>移动</el-button>
<el-button
size="mini"
type="text"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button size="mini" type="text" @click="showMoveDialog(scope.row)">
移动
</el-button>
<el-button size="mini" type="text" @click="handlePreview(scope.row)">
预览
</el-button>
<el-button
size="mini"
type="text"
class="delete-btn"
@click="handleDelete(scope.row)"
>删除</el-button>
>
删除
</el-button>
</template>
</el-table-column>
</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-container>
......@@ -148,11 +132,7 @@
</el-dialog>
<!-- 移动文件弹窗 -->
<el-dialog
title="移动到"
:visible.sync="moveDialogVisible"
width="30%"
>
<el-dialog title="移动到" :visible.sync="moveDialogVisible" width="30%">
<el-tree
ref="moveTree"
:data="directories"
......@@ -175,28 +155,82 @@
>
<div class="preview-content">
<img
v-if="previewFile && previewFile.type === 'image'"
v-if="previewFile && previewFile.resType === 1"
:src="previewFile.url"
class="preview-image"
>
/>
<video
v-else-if="previewFile && previewFile.type === 'video'"
v-else-if="previewFile && previewFile.resType === 2"
:src="previewFile.url"
controls
class="preview-video"
></video>
>
</video>
</div>
</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>
</template>
<script>
import {
getMaterialDirectoriesTree,
getDirectoryById,
createDirectory,
updateDirectory,
deleteDirectory
deleteDirectory,
getDirectoryById,
getMaterialCount,
movematerial,
uploadMaterial
} from '@/api/report';
export default {
......@@ -241,94 +275,118 @@ export default {
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() {
this.fetchDirectories()
this.fetchDirectories();
},
methods: {
fetchDirectories(){
fetchDirectories() {
getMaterialDirectoriesTree().then(res => {
if (res.status === 200) {
this.directories= res.result.data
}else {
this.$message.error('获取目录失败')
this.directories = res.result.data;
} else {
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) {
this.currentDirectory = data.id
this.currentPath = this.getNodePath(data)
this.currentDirectory = data.id;
this.currentPath = this.getNodePath(data);
this.currentPage = 1; // 重置当前页码为 1
this.fetchMaterialsByDirectoryId(data.id);
},
fetchMaterialsByDirectoryId(directoryId) {
// 获取数据(包含总数和分页数据)
async fetchMaterialsByDirectoryId(directoryId) {
this.loading = true;
getDirectoryById({
directoryId: directoryId,
pageNum: 1,
pageSize: 10,
includeSubdirectories: true
})
.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;
try {
// 先获取总数
const countResponse = await getMaterialCount({
directoryId: directoryId,
includeSubdirectories: this.includeSubdirectories
});
},
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) {
const path = []
let currentNode = node
const path = [];
let currentNode = node;
while (currentNode) {
path.unshift(currentNode.name)
currentNode = currentNode.parent
path.unshift(currentNode.name);
currentNode = currentNode.parent;
}
return path.join(' / ')
return path.join(' / ');
},
// 显示新建目录弹窗
showNewDirDialog(parentId) {
this.parentId = parentId
this.newDirForm.name = ''
this.newDirForm.parentId = parentId
this.newDirDialogVisible = true
this.parentId = parentId;
this.newDirForm.name = '';
this.newDirForm.parentId = parentId;
this.newDirDialogVisible = true;
},
// 创建目录
......@@ -340,7 +398,12 @@ export default {
parentId: this.newDirForm.parentId
})
.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.newDirDialogVisible = false;
this.fetchDirectories();
......@@ -358,102 +421,101 @@ export default {
// 删除目录
handleDeleteDirectory(node, data) {
this.$confirm('确认删除该目录吗?其下的所有文件将被移动到根目录', '提示', {
this.$confirm('确认删除该目录吗?其下的所有文件将被删除', '提示', {
type: 'warning'
}).then(async () => {
try {
const response = await deleteDirectory(data.id);
if (response.code === 0) { // Assuming your API uses a code for success/failure
this.$message.success('删除成功');
await this.fetchDirectories(); // 重新获取目录树
// 如果删除的是当前选中的目录,清空文件列表
if (data.id === this.currentDirectory) {
this.materials = [];
this.currentDirectory = null;
this.currentPath = '根目录';
})
.then(async () => {
try {
const response = await deleteDirectory({id:data.id});
if (response.code === 0) {
this.$message.success('删除成功');
await this.fetchDirectories(); // 重新获取目录树
// 如果删除的是当前选中的目录,清空文件列表
if (data.id === this.currentDirectory) {
this.materials = [];
this.currentDirectory = null;
this.currentPath = '根目录';
}
} else {
this.$message.error(response.message || '删除失败');
}
} else {
this.$message.error(response.message || '删除失败');
} catch (error) {
this.$message.error('删除失败');
console.error('删除目录失败:', error);
}
} catch (error) {
this.$message.error('删除失败');
console.error('删除目录失败:', error);
}
}).catch(() => { });
})
.catch(() => {});
},
// 上传前验证
beforeUpload(file) {
const isImage = file.type.startsWith('image/')
const isVideo = file.type.startsWith('video/')
const isLt100M = file.size / 1024 / 1024 < 100
const isImage = file.type.startsWith('image/');
const isVideo = file.type.startsWith('video/');
const isLt100M = file.size / 1024 / 1024 < 100;
if (!isImage && !isVideo) {
this.$message.error('只能上传图片或视频文件!')
return false
this.$message.error('只能上传图片或视频文件!');
return false;
}
if (!isLt100M) {
this.$message.error('文件大小不能超过 100MB!')
return false
this.$message.error('文件大小不能超过 100MB!');
return false;
}
return true
return true;
},
// 处理上传成功
async handleUploadSuccess(response, file, fileList) {
// Assuming your upload API returns the uploaded file data on success
if (response.code === 0) { // Check for success code from your API
this.$message.success('上传成功')
await this.fetchMaterials(this.currentDirectory) // 重新获取文件列表
if (response.code === 0) {
this.$message.success('上传成功');
await this.fetchMaterials(this.currentDirectory); // 重新获取文件列表
} else {
this.$message.error(response.message || '上传失败')
this.$message.error(response.message || '上传失败');
}
},
// 处理上传失败
handleUploadError(err) {
this.$message.error('上传失败')
console.error('上传文件失败:', err)
this.$message.error('上传失败');
console.error('上传文件失败:', err);
},
// 显示移动文件弹窗
showMoveDialog(file) {
this.currentMoveFile = file
this.selectedMoveDirectory = null
this.moveDialogVisible = true
this.currentMoveFile = file;
this.selectedMoveDirectory = null;
this.moveDialogVisible = true;
},
// 处理移动目标目录选择
handleMoveNodeClick(data) {
this.selectedMoveDirectory = data.id
this.selectedMoveDirectory = data.id;
},
// 确认移动文件
async confirmMove() {
if (!this.selectedMoveDirectory) {
this.$message.warning('请选择目标目录')
return
this.$message.warning('请选择目标目录');
return;
}
try {
const response = await this.request({
url: '/api/materials/move',
method: 'post',
data: {
fileId: this.currentMoveFile.id,
targetDirectoryId: this.selectedMoveDirectory
}
const response = await movematerial({
materialId: this.currentMoveFile.id, // 素材的 ID
targetDirectoryId: this.selectedMoveDirectory // 目标目录的 ID
});
if (response.code === 0) {
this.$message.success('移动成功')
this.moveDialogVisible = false
await this.fetchMaterials(this.currentDirectory) // 重新获取当前目录的文件列表
// 移动成功
if (response && response.status === 200) {
this.$message.success("移动成功");
this.moveDialogVisible = false;
this.fetchMaterialsByDirectoryId(this.currentDirectory);
} else {
this.$message.error(response.message || '移动失败')
this.$message.error(response.msg || "移动失败");
}
} catch (error) {
this.$message.error('移动失败')
console.error('移动文件失败:', error)
this.$message.error('移动失败');
console.error('移动文件失败:', error);
}
},
......@@ -461,49 +523,108 @@ export default {
handleDelete(file) {
this.$confirm('确认删除该文件吗?', '提示', {
type: 'warning'
}).then(async () => {
try {
const response = await this.request({
url: '/api/materials/delete',
method: 'post',
params: { fileId: file.id }
});
if (response.code === 0) {
this.$message.success('删除成功')
await this.fetchMaterials(this.currentDirectory) // 重新获取文件列表
} else {
this.$message.error(response.message || '删除失败')
})
.then(async () => {
try {
const response = await this.request({
url: '/api/materials/delete',
method: 'post',
params: { fileId: file.id }
});
if (response.code === 0) {
this.$message.success('删除成功');
await this.fetchMaterials(this.currentDirectory); // 重新获取文件列表
} else {
this.$message.error(response.message || '删除失败');
}
} catch (error) {
this.$message.error('删除失败');
console.error('删除文件失败:', error);
}
} catch (error) {
this.$message.error('删除失败')
console.error('删除文件失败:', error)
}
}).catch(() => { })
})
.catch(() => {});
},
// 预览文件
handlePreview(file) {
this.previewFile = file
this.previewDialogVisible = true
this.previewFile = file;
this.previewDialogVisible = true;
},
// 工具方法 - 格式化文件大小
formatFileSize(size) {
if (size < 1024) {
return size + ' B'
return size + ' B';
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + ' KB'
return (size / 1024).toFixed(2) + ' KB';
} else {
return (size / 1024 / 1024).toFixed(2) + ' MB'
return (size / 1024 / 1024).toFixed(2) + ' MB';
}
},
// 工具方法 - 格式化日期
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>
<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