Files
fad_oa/ruoyi-ui/src/components/FileManager/index.vue

179 lines
4.1 KiB
Vue
Raw Normal View History

2026-04-13 17:04:38 +08:00
<!-- FileManager.vue -->
<template>
<div class="file-manager">
<FileManagerHeader
:config="headerConfig"
:search-text.sync="searchText"
:filter-type.sync="filterType"
:view-mode.sync="viewMode"
@new-file="$emit('new-file')"
/>
<FileList
:files="currentFiles"
:view-mode="viewMode"
:selected-files="selectedFiles"
@select="handleSelect"
@preview="handlePreview"
@download="handleDownload"
@delete="$emit('delete', $event)"
/>
<FileManagerPager
v-if="pagerConfig.enable"
:page-num.sync="pager.pageNum"
:page-size.sync="pager.pageSize"
:total="totalFiles"
/>
<el-dialog
:visible.sync="previwFileVisible"
title="文件预览"
@close="previewFileVisible = false"
>
<FilePreviewer :fileUrl="previewFileUrl"></FilePreviewer>
</el-dialog>
</div>
</template>
<script>
import FileManagerHeader from "./components/header/index.vue";
import FileList from "./components/list/index.vue";
import FileManagerPager from "./components/pager/index.vue";
import FilePreviewer from "./components/previewer/index.vue";
export default {
components: {
FileManagerHeader,
FileList,
FileManagerPager,
FilePreviewer,
},
props: {
files: Array,
pagerConfig: {
default: () => ({
enable: true,
// 分页实现方式:前端实现 / 后端实现
type: "front",
}),
type: Object,
},
headerConfig: {
default: () => ({
search: false,
filter: false,
view: true,
// 搜索实现方式
searchType: "front",
}),
type: Object,
},
},
data() {
return {
searchText: "",
filterType: "all",
viewMode: "grid",
selectedFiles: [],
previwFileVisible: false,
previewFileUrl: "",
pager: {
pageNum: 1,
pageSize: 20,
},
};
},
computed: {
totalFiles() {
return this.filteredFiles.length;
},
filteredFiles() {
return this.pipe([this.searchTextPipe], this.files);
},
currentFiles() {
return this.pagerPipe(this.filteredFiles);
},
},
watch: {
pager: {
handler(newVal) {
this.$emit("pagerChange", newVal);
},
deep: true,
},
searchText(newVal) {
this.$emit("searchChange", newVal);
},
filterType(newVal) {
this.$emit("filterChange", newVal);
},
viewMode(newVal) {
this.$emit("viewChange", newVal);
},
},
methods: {
// 搜索管道,文件一次经过文件名(搜索文本)过滤、文件类型过滤和分页过滤
// 管道组装函数
pipe(pipes, files) {
return pipes.reduce((prev, curr) => curr(prev), files);
},
searchTextPipe(files) {
if (this.searchText === "") {
return files;
}
console.log(files, this.searchText);
return files.filter((file) => {
return file.name.includes(this.searchText);
});
},
pagerPipe(files) {
if (!this.pagerConfig.enable) {
return files;
}
if (this.pagerConfig.type === "front") {
const start = (this.pager.pageNum - 1) * this.pager.pageSize;
const end = start + this.pager.pageSize;
return files.slice(start, end);
}
return files;
},
handleSelect(files) {
this.selectedFiles = files;
},
handlePreview(files) {
if (files.length === 0) {
this.$message.warning("请选择进行预览");
return;
}
if (files.length > 1) {
this.$message.warning("一次只能预览一个文件");
return;
}
if (this.previwFileVisible) {
this.previwFileVisible = false;
return;
}
console.log(files, "文件预览");
this.previwFileVisible = true;
this.previewFileUrl = files[0].url;
},
handleDownload(files) {
const a = document.createElement("a");
a.href = files[0].url;
a.download = files[0].name;
a.click();
a.remove();
console.log(files, "文件下载");
},
},
};
</script>
<style scoped>
.file-manager {
position: relative;
padding: 20px;
}
</style>