<template> <div class="file-details"> <customHeader>文件共享中心</customHeader> <div class="content"> <div class="left-box"> <!-- 左侧树菜单 --> <fileSystem :selected="selected" :list="listArr" :draggable="true" @delete-node="onDeltet" @on-click="onClick" @change-name="onChangeName" @addNode="onAddNode" > <template #icon="{ item }"> <template v-if="item.isFolder"> <!-- <icon v-if="item.expanded" class="iconfont" iconName="icon-24gf-folderOpen" /> --> <SvgIcon v-if="item.expanded" size="18" name="file-open" /> <!-- <icon v-else class="iconfont" iconName="icon-bg-folder" /> --> <SvgIcon v-else size="18" name="file-close" /> </template> <treeIcon class="iconfont" :title="item.title" v-else /> </template> <template #operation="{ type }"> <!-- <i class="iconfont icon-add_file" v-if="type == 'addFolder'"></i> --> <i class="iconfont icon-xinzeng" v-if="type == 'addDocument'"></i> <i class="iconfont icon-bianji" v-if="type == 'Editable'"></i> <a-popconfirm v-if="type == 'deleteNode'" title="是否确认删除!" ok-text="确定" cancel-text="取消" @confirm="confirmDel"> <i class="iconfont icon-guanbi"></i> </a-popconfirm> </template> </fileSystem> </div> <div class="right-box"> <div class="search"> <a-input v-model:value="fileName" placeholder="请输入文件名称" /> <a-button type="primary" preIcon="ant-design:search-outlined" @click="onSearch">查询</a-button> <a-button type="primary" style="float: right; margin-right: 20px" @click="openModal(true)">文件上传</a-button> </div> <div class="list"> <!-- <div class="bd-t"></div> --> <NormalTable v-if="alive" :selfParam="selfParam" :searchParam="fileName" :nodeParam="nodeParam" :columns="columns" :list="getTree" :deleteById="deleteById" :downLoad="downLoad" designScope="file-detail" title="文件详情" /> <!-- <div class="bd-b"></div> --> </div> </div> </div> <!-- 上传谈弹窗 --> <a-modal v-model:visible="visible" centered :width="600" title="上传文件" @ok="handleOk" @cancel="handleCancel"> <a-form :model="formState" labelAlign="right" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }"> <a-form-item label="是否审批" :rules="[{ required: true, message: '请选择是否审批' }]"> <a-radio-group v-model:value="formState.isApprove" @change="changeRadio"> <a-radio :value="true">是</a-radio> <a-radio :value="false">否</a-radio> </a-radio-group> </a-form-item> <a-form-item label="文件类型"> <JDictSelectTag v-model:value="formState.fileType" placeholder="请选择文件类型" dictCode="file_type" style="width: 500px" /> </a-form-item> <a-form-item label="文件上传"> <a-upload :before-upload="beforeUpload" @remove="handleRemove" :multiple="false" :file-list="fileList"> <a-button type="primary" preIcon="ant-design:cloud-upload-outlined">选择文件</a-button> </a-upload> </a-form-item> </a-form> </a-modal> </div> </template> <script lang="ts" setup name="system-user"> import customHeader from '/@/views/vent/comment/components/customHeader.vue'; import { useRouter } from 'vue-router'; import { useMessage } from '/@/hooks/web/useMessage'; import fileSystem from './commen/fileSystem.vue'; import { SvgIcon } from '/@/components/Icon'; import treeIcon from './commen/Icon/treeIcon.vue'; import { ref, onMounted, reactive, nextTick, watch } from 'vue'; import NormalTable from '../comment/NormalTable.vue'; import { columns } from './fileDetail.data'; import { getTree, createFile, editMenu, delMenu, uploadApi, downLoad, deleteById } from './fileDetail.api'; import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue'; let selfParam = reactive({ //各矿参数 sysOrgCode: '', bpmStatus: null, flag: false, }); let router = useRouter(); //路由 const { createMessage } = useMessage(); let fileName = ref(''); let fileList = reactive<any[]>([]); //上传文件列表 // let uploadParam = reactive({}); //上传文件参数 let nodeParam = reactive({}); //点击树节点时传递的参数 let alive = ref(true); //点击树节点刷新表格数据 let visible = ref(false); //控制上传弹窗的显示 let formState = reactive({ //上传文件类型,是否审批 isApprove: null, fileType: '', }); //lxh 当前选中树节点 let selected = reactive<any>({ id: null, pid: null, title: '', isFolder: false, }); let flag = ref(''); //左侧菜单列表 let listArr = reactive<any[]>([]); //获取要删除的节点数据 let delNode = reactive({}); //上传文件 let openModal = (val) => { formState.isApprove = null; formState.fileType = ''; fileList.length = 0; visible.value = val; }; //文件审批状态切换 let changeRadio = (val) => { formState.isApprove = val.target.value; }; //开始上传 let handleOk = () => { if (formState.isApprove === null) { createMessage.warning('请选择文件审批状态!'); } else { const formData = new FormData(); formData.append('file', fileList[0]); formData.append('parentId', selected.id); formData.append('isApprove', formState.isApprove); formData.append('fileType', formState.fileType); uploadApi(formData).then((res) => { console.log(res, '上传返回'); alive.value = false; nextTick(() => { alive.value = true; visible.value = false; }); }); } }; //取消上传 let handleCancel = () => { visible.value = false; }; let list2trees = (data) => { // 删除 所有 children,以防止多次调用 data.forEach(function (item) { delete item.children; }); // 将数据存储为 以 id 为 KEY 的 map 索引数据列 let map = {}; data.forEach(function (item) { map[item.id] = item; }); var val = []; data.forEach(function (item) { item.isFolder = true; item.title = item.fileName; item.pid = item.parentId; // 以当前遍历项,的pid,去map对象中找到索引的id var parent = map[item.pid]; // 好绕啊,如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中 if (parent) { (parent.children || (parent.children = [])).push(item); } else { //如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中,作为顶级 val.push(item); } }); return val; }; //获取左侧菜单树数据 let getTreeList = async () => { listArr.length = 0; let data = await getTree({ parentId: '' }); let datas = data.records.filter((v) => v.fileType == null); let list = list2trees(datas); listArr.push(...list); console.log(listArr, '树节点数据'); selected.id = listArr[0].id; selected.pid = listArr[0].pid; selected.title = listArr[0].title; selected.isFolder = listArr[0].isFolder; }; //点击目录 const onClick = (node) => { selected = node; if (flag.value != node.title) { alive.value = false; nextTick(() => { alive.value = true; nodeParam = node; flag.value = node.title; }); } }; // // 拖拽结束 // const drop = (node) => { // console.log(node); // }; //添加文件 const onAddNode = async (node) => { let data = await createFile({ fileName: node.newName, type: 'FOL', parentId: node.id }); console.log(data, '新增文件返回'); getTreeList(); }; // 修改名字 const onChangeName = (node) => { editMenu({ id: node.id, fileName: node.newName, parentId: node.pid, }).then((res) => { getTreeList(); }); }; // 删除 let onDeltet = (node) => { delNode = { ...node }; }; //确定删除 let confirmDel = () => { if (delNode.pid == 'root') { createMessage.warning('根节点不能被删除!'); } else if (delNode.children) { createMessage.warning('该节点无法被删除,请先删除该节点下的子节点!'); } else { delMenu({ id: delNode.id }).then((res) => { console.log(res, '删除文件'); getTreeList(); }); } }; //取消删除 //查询列表 let onSearch = () => { alive.value = false; nextTick(() => { alive.value = true; }); }; //上传文件 let beforeUpload = (file) => { console.log(file, '选中文件'); fileList.length = 0; let index = file.name.indexOf('.'); let name = file.name.substring(index + 1); if (name == 'png' || name == 'jpg' || name == 'gif' || name == 'psd' || name == 'webp') { createMessage.warning('禁止上传图片类型的文件!'); } else { fileList.push(file); } }; // 文件移除 let handleRemove = (file) => { const index = fileList.indexOf(file); const newFileList = fileList.slice(); newFileList.splice(index, 1); fileList.length = 0; }; watch( () => router.currentRoute.value, (val) => { console.log('各矿传参', val); selfParam.bpmStatus = val.query.bpmStatus; selfParam.sysOrgCode = val.query.sysOrgCode; selfParam.flag = val.query.flag; }, { immediate: true } ); onMounted(() => { getTreeList(); }); </script> <style lang="less" scoped> @ventSpace: zxm; .file-details { width: calc(100% - 10px); height: calc(100% - 100px); padding: 15px; position: relative; margin-top: 100px; background: url(../../../../assets/images/files/homes/bd.png) no-repeat center; background-size: contain; &::after { display: block; content: ''; height: 200px; width: 100%; position: absolute; background-image: linear-gradient(#2eb2ff05, #2ea2ff00); border-top: 1px solid #2eb2ff20; top: 0px; left: 0px; } .content { width: 100%; height: calc(100% - 30px); display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start; position: relative; z-index: 999; .left-box { width: 15%; height: calc(100% - 20px); margin-bottom: 20px; padding: 20px; border: 1px solid #99e8ff66; background: #27546e1a; box-shadow: 0px 0px 20px 7px rgba(145, 233, 254, 0.7) inset; -moz-box-shadow: 0px 0px 20px 7px rgba(145, 233, 254, 0.7) inset; -webkit-box-shadow: 0px 0px 50px 1px rgb(149 235 255 / 5%) inset; // lxh .iconfont { color: #fff; font-size: 12px; margin-left: 5px; } } .right-box { width: 85%; height: calc(100% - 20px); padding: 0px 0px 0px 15px; box-sizing: border-box; .search { height: 34px; line-height: 34px; margin-bottom: 15px; } } .list { height: calc(100% - 49px); position: relative; .bd-t { height: 4px; width: 100%; position: absolute; top: 0px; background: url(../../../../assets/images/files/details/lb-b.png) no-repeat; background-size: 100% 100%; } .bd-b { height: 4px; width: 100%; position: absolute; bottom: 0px; background: url(../../../../assets/images/files/details/lb-b.png) no-repeat; background-size: 100% 100%; } } } .zxm-form { padding: 10px !important; } } ::v-deep .jeecg-svg-icon { margin-right: 5px; } ::v-deep .jeecg-basic-table-form-container { padding: 0px 0px; } ::v-deep .zxm-btn-primary { background-color: transparent; border: none; background: url(../../../../assets/images/files/details/btn.png) no-repeat !important; background-size: 100% 100% !important; } ::v-deep .zxm-tree-switcher { background: transparent; } ::v-deep .zxm-input { width: 220px; height: 28px; background: transparent; border: 1px solid #31bccc; color: #fff; margin: 0px 20px; border-radius: 5px; } ::v-deep .zxm-btn-group { margin-right: 25px; } ::v-deep .zxm-upload-list-item-name { color: #fff; } ::v-deep .zxm-upload-list-item:hover .zxm-upload-list-item-info { background-color: transparent; } :deep(.@{ventSpace}-table-cell-row-hover) { background: #264d8833 !important; } :deep(.@{ventSpace}-table-row-selected) { background: #268bc522 !important; } :deep(.@{ventSpace}-select-dropdown) { border: 1px solid #ececec66; background: #004362 !important; left: 0px !important; backdrop-filter: blur(50px); .@{ventSpace}-select-item { color: #fff !important; } .@{ventSpace}-select-item-option-selected, .@{ventSpace}-select-item-option-active { background-color: #00678b66 !important; } .@{ventSpace}-select-item:hover { background-color: #008fc366 !important; } } ::v-deep .zxm-form-item-control-input { width: 90%; } </style>