|
@@ -0,0 +1,366 @@
|
|
|
+<template>
|
|
|
+ <div class="page-doc">
|
|
|
+ <div class="header">
|
|
|
+ <home-header @login="emits('login')" />
|
|
|
+ </div>
|
|
|
+ <div class="my-doc-container">
|
|
|
+ <TitleHeader :items="menuList" />
|
|
|
+ <FileDetail
|
|
|
+ v-if="clickFileDetail && clickFileDetail.sign == 'file'"
|
|
|
+ :fileDetail="clickFileDetail"
|
|
|
+ :changeFile="showFileDetail"
|
|
|
+ />
|
|
|
+ <div class="page-content" v-else>
|
|
|
+ <div class="content-top">
|
|
|
+ <div class="left">
|
|
|
+ <a-button
|
|
|
+ type="primary"
|
|
|
+ :icon="h(CloudUploadOutlined)"
|
|
|
+ @click="uploadFiles(state.selectedRowKeys)"
|
|
|
+ style="height: 36px"
|
|
|
+ >导入</a-button
|
|
|
+ >
|
|
|
+ <a-button
|
|
|
+ :icon="h(FolderAddOutlined)"
|
|
|
+ style="margin-left: 15px; height: 36px"
|
|
|
+ @click="openNewFolderModel = true"
|
|
|
+ v-if="!clickFileDetail"
|
|
|
+ >新建文件夹</a-button
|
|
|
+ >
|
|
|
+ <a-button
|
|
|
+ :icon="h(DownloadOutlined)"
|
|
|
+ @click="downloadFiles(state.selectedRowKeys)"
|
|
|
+ style="margin-left: 15px; height: 36px"
|
|
|
+ >下载</a-button
|
|
|
+ >
|
|
|
+ <a-button
|
|
|
+ v-if="clickFileDetail"
|
|
|
+ :icon="h(DeliveredProcedureOutlined)"
|
|
|
+ @click="moveFiles(state.selectedRowKeys)"
|
|
|
+ style="margin-left: 15px; height: 36px"
|
|
|
+ >移动</a-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="right">
|
|
|
+ <a-input
|
|
|
+ v-model:value="searchValue"
|
|
|
+ placeholder="搜索文档"
|
|
|
+ style="width: 280px; height: 40px"
|
|
|
+ @pressEnter="getDataSource({ searchKey: searchValue })"
|
|
|
+ >
|
|
|
+ <template #suffix>
|
|
|
+ <SearchOutlined
|
|
|
+ @click="getDataSource({ searchKey: searchValue })"
|
|
|
+ style=""
|
|
|
+ class="search-icon"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </a-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content-table">
|
|
|
+ <a-table
|
|
|
+ :rowSelection="{
|
|
|
+ selectedRowKeys: state.selectedRowKeys,
|
|
|
+ onChange: onSelectChange,
|
|
|
+ }"
|
|
|
+ :columns="columns"
|
|
|
+ :dataSource="dataSource"
|
|
|
+ :pagination="false"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record }">
|
|
|
+ <template v-if="column.key === 'fileName'">
|
|
|
+ <div
|
|
|
+ v-if="record.sign == 'dir'"
|
|
|
+ class="name-box"
|
|
|
+ @click="jumpToFile(record)"
|
|
|
+ >
|
|
|
+ <MyIcon :icon="iconTypeName.dir" size="18" />
|
|
|
+ <span>{{ record.fileName }}</span>
|
|
|
+ </div>
|
|
|
+ <div v-else class="name-box" @click="showFileDetail(record)">
|
|
|
+ <MyIcon :icon="iconTypeName[record.fileType]" size="18" />
|
|
|
+ <span>{{ record.fileName }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-if="column.key === 'createTime'">
|
|
|
+ <div>
|
|
|
+ {{ dayjs(record.createTime).format("YYYY-MM-DD HH:mm:ss") }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="column.key === 'action'">
|
|
|
+ <a-button
|
|
|
+ type="text"
|
|
|
+ :icon="h(DownloadOutlined)"
|
|
|
+ style="margin-right: 15px"
|
|
|
+ @click="
|
|
|
+ record.sign !== 'dir'
|
|
|
+ ? downloadFile(record)
|
|
|
+ : downloadFiles([record.id])
|
|
|
+ "
|
|
|
+ >下载</a-button
|
|
|
+ >
|
|
|
+ <a-dropdown>
|
|
|
+ <a class="ant-dropdown-link" @click.prevent>
|
|
|
+ <span style="font-size: 18px; font-wight: 600">···</span>
|
|
|
+ <DownOutlined />
|
|
|
+ </a>
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu>
|
|
|
+ <a-menu-item v-if="record.sign !== 'dir'">
|
|
|
+ <a-button
|
|
|
+ type="link"
|
|
|
+ :icon="h(DeliveredProcedureOutlined)"
|
|
|
+ style="color: #000"
|
|
|
+ @click="moveFiles([record.id])"
|
|
|
+ >移动</a-button
|
|
|
+ >
|
|
|
+ </a-menu-item>
|
|
|
+ <a-menu-item>
|
|
|
+ <a-button
|
|
|
+ type="link"
|
|
|
+ :icon="h(VerticalAlignTopOutlined)"
|
|
|
+ style="color: #000"
|
|
|
+ @click="topFile(record.id)"
|
|
|
+ >置顶</a-button
|
|
|
+ >
|
|
|
+ </a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ </a-dropdown>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <a-modal v-model:open="openNewFolderModel" title="新建分组" @ok="newFolder">
|
|
|
+ <a-input
|
|
|
+ style="margin-top: 15px; margin-bottom: 10px"
|
|
|
+ v-model:value="folderName"
|
|
|
+ placeholder="请输入分组名称"
|
|
|
+ />
|
|
|
+ </a-modal>
|
|
|
+ <MoveFileModel
|
|
|
+ :open="moveFileModel"
|
|
|
+ :ids="moveFileIds"
|
|
|
+ :closeModel="closeMoveFileModel"
|
|
|
+ />
|
|
|
+ <FileUpload ref="userUploadFileRef" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+/**
|
|
|
+ * @description 我的文档
|
|
|
+ */
|
|
|
+import { h, ref, reactive, onMounted } from "vue";
|
|
|
+import {
|
|
|
+ CloudUploadOutlined,
|
|
|
+ SearchOutlined,
|
|
|
+ DownloadOutlined,
|
|
|
+ FolderAddOutlined,
|
|
|
+ VerticalAlignTopOutlined,
|
|
|
+ DeliveredProcedureOutlined,
|
|
|
+} from "@ant-design/icons-vue";
|
|
|
+import HomeHeader from '@/views/home/components/HomeHeader.vue';
|
|
|
+import { message } from "ant-design-vue";
|
|
|
+import MyIcon from "@/components/myIcon/index.vue";
|
|
|
+import {
|
|
|
+ topDocs,
|
|
|
+ getDocList,
|
|
|
+ deleteDocs,
|
|
|
+ downloadDocs,
|
|
|
+ madeNewFolder,
|
|
|
+ isRepeatFolder
|
|
|
+} from "./http";
|
|
|
+import { columns, iconTypeName } from "./config";
|
|
|
+import MoveFileModel from "./MoveFiles.vue";
|
|
|
+import FileUpload from "./FileUpload.vue";
|
|
|
+import FileDetail from "./FileDetail.vue";
|
|
|
+import TitleHeader from "./TitleHeader.vue";
|
|
|
+import dayjs from "dayjs";
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getDataSource();
|
|
|
+});
|
|
|
+const menuList = ref<{
|
|
|
+ name: string,
|
|
|
+ id: string,
|
|
|
+ checked: boolean
|
|
|
+}[]>([
|
|
|
+ {
|
|
|
+ name: "我的收藏",
|
|
|
+ id: '',
|
|
|
+ checked: true
|
|
|
+ }
|
|
|
+])
|
|
|
+// 切换目录
|
|
|
+const changeMenu = (fileName: any = null) => {
|
|
|
+ // 切换目录时重置搜索内容和选中的文件
|
|
|
+ searchValue.value = "";
|
|
|
+ state.selectedRowKeys = [];
|
|
|
+
|
|
|
+ if (!fileName) {
|
|
|
+ // 清空选择打开的文件夹
|
|
|
+ clickFileDetail.value = null;
|
|
|
+ // 刷新列表
|
|
|
+ getDataSource();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ menuList.value.forEach((item) => {
|
|
|
+ item['checked'] = false;
|
|
|
+ })
|
|
|
+ menuList.value.push({
|
|
|
+ name: fileName,
|
|
|
+ id: '',
|
|
|
+ checked: true,
|
|
|
+ })
|
|
|
+};
|
|
|
+
|
|
|
+// 获取数据
|
|
|
+const searchValue = ref("");
|
|
|
+const dataSource = ref<any[]>([]);
|
|
|
+const getDataSource = (params = {}) => {
|
|
|
+ // 重置选中的文件
|
|
|
+ state.selectedRowKeys = [];
|
|
|
+ // 获取文档列表
|
|
|
+ getDocList(params).then((res) => {
|
|
|
+ if (res.success) {
|
|
|
+ dataSource.value = res.data.map((item: any) => ({
|
|
|
+ key: item.id,
|
|
|
+ ...item,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const state = reactive<{
|
|
|
+ selectedRowKeys: any[];
|
|
|
+ loading: boolean;
|
|
|
+}>({
|
|
|
+ selectedRowKeys: [], // Check here to configure the default column
|
|
|
+ loading: false,
|
|
|
+});
|
|
|
+
|
|
|
+const onSelectChange = (selectedRowKeys: any[]) => {
|
|
|
+ state.selectedRowKeys = selectedRowKeys;
|
|
|
+};
|
|
|
+
|
|
|
+// 点击进入文件夹
|
|
|
+const clickFileDetail = ref<null | any>(null);
|
|
|
+const jumpToFile = (data: any) => {
|
|
|
+ clickFileDetail.value = data;
|
|
|
+ // 触发目录切换的回调
|
|
|
+ changeMenu(data.fileName);
|
|
|
+ getDataSource({
|
|
|
+ id: data.id,
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 新建文件夹
|
|
|
+const openNewFolderModel = ref(false);
|
|
|
+const folderName = ref("");
|
|
|
+const newFolder = async () => {
|
|
|
+ const res = await isRepeatFolder(folderName.value);
|
|
|
+ if (!res.success) {
|
|
|
+ message.info("文件夹名称重复,请重新输入!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const res2 = await madeNewFolder(folderName.value);
|
|
|
+ if (res2.success) {
|
|
|
+ message.success("文件夹新建成功!");
|
|
|
+ folderName.value = "";
|
|
|
+ // 刷新列表
|
|
|
+ getDataSource();
|
|
|
+ openNewFolderModel.value = false;
|
|
|
+ } else {
|
|
|
+ message.error("新建文件夹失败,请稍后重试!");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 下载(单文件下载)
|
|
|
+const downloadFile = async (data: any) => {
|
|
|
+ if (!data.fileStorepath) {
|
|
|
+ message.error("下载失败,未找到文件下载地址!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ const blob = await response.blob();
|
|
|
+ const url = window.URL.createObjectURL(blob);
|
|
|
+ const a = document.createElement("a");
|
|
|
+ a.href = url;
|
|
|
+ a.download = data.fileName ?? "download.pdf"; // 强制下载并指定文件名
|
|
|
+ document.body.appendChild(a);
|
|
|
+ a.click();
|
|
|
+ document.body.removeChild(a);
|
|
|
+ // 释放 Blob URL
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
+};
|
|
|
+//文件导入
|
|
|
+// 上传文档
|
|
|
+const userUploadFileRef = ref<any>(null);
|
|
|
+const uploadFiles = () => userUploadFileRef.value.showModal();
|
|
|
+// 多文件打包下载
|
|
|
+const downloadFiles = async (ids: any[] = []) => {
|
|
|
+ message.success("正在为你下载文件,请稍等 ...");
|
|
|
+ try {
|
|
|
+ await downloadDocs(ids);
|
|
|
+ } catch {
|
|
|
+ message.error("下载失败,请稍后重试!");
|
|
|
+ }
|
|
|
+};
|
|
|
+// 移动:最外层文件禁止多选移动,文件夹类型禁止移动
|
|
|
+const moveFileModel = ref(false);
|
|
|
+const moveFileIds = ref<any[]>([]);
|
|
|
+const moveFiles = (ids: any[] = []) => {
|
|
|
+ moveFileIds.value = ids;
|
|
|
+ moveFileModel.value = true;
|
|
|
+};
|
|
|
+const closeMoveFileModel = () => {
|
|
|
+ moveFileModel.value = false;
|
|
|
+ moveFileIds.value = [];
|
|
|
+ refreshList();
|
|
|
+};
|
|
|
+// 列表刷新
|
|
|
+const refreshList = () => {
|
|
|
+ if (clickFileDetail.value) {
|
|
|
+ // 关闭弹窗后刷新列表
|
|
|
+ getDataSource({
|
|
|
+ id: clickFileDetail.value.id,
|
|
|
+ });
|
|
|
+ // 刷新目录
|
|
|
+ changeMenu(clickFileDetail.value.fileName);
|
|
|
+ } else {
|
|
|
+ // 关闭弹窗后刷新列表
|
|
|
+ getDataSource();
|
|
|
+ // 刷新目录
|
|
|
+ changeMenu();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 置顶
|
|
|
+const topFile = async (id: string) => {
|
|
|
+ const res = await topDocs(id);
|
|
|
+ if (res.success) {
|
|
|
+ message.success("置顶成功!");
|
|
|
+ // 刷新列表
|
|
|
+ refreshList();
|
|
|
+ } else {
|
|
|
+ message.error("置顶失败,请稍后重试!");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 跳到文件详情页面
|
|
|
+const showFileDetail = (data: any) => {
|
|
|
+ console.log("跳到文件详情页面", data);
|
|
|
+ clickFileDetail.value = {
|
|
|
+ ...data,
|
|
|
+ id: data.fileId,
|
|
|
+ };
|
|
|
+ // 触发目录切换的回调
|
|
|
+ changeMenu(data.fileName);
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style scoped lang="scss">
|
|
|
+@import "./index.scss";
|
|
|
+</style>
|