1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| <template> <div v-loading="loading"> <div @contextmenu="onTreeWrapperContextmenu"> <el-card> <div class="tree-wrapper"> <el-tree ref="treeRef" :data="treeData" :props="treeProps" :highlight-current="true" node-key="id" draggable @node-contextmenu="onContextmenu" @node-drop="onDropSuccess" @node-click="onNodeClick" @node-drag-start="onNodeDragStart" :allow-drop="onAllowDrop" ></el-tree> </div> </el-card> </div> <el-dialog :visible.sync="renameData.visible" title="重命名" > <el-input v-model="renameData.value"></el-input> <div class="mt-5 flex justify-end"> <el-button @click="onCloseRenameDialog">取消</el-button> <el-button type="primary" @click="onConfirmRename" :loading="renameData.confirmLoading" >确定</el-button> </div> </el-dialog> <el-dialog :visible.sync="createData.visible" title="新增" > <el-input v-model="createData.value"></el-input> <div class="mt-5 flex justify-end"> <el-button @click="onCloseCreateDialog">取消</el-button> <el-button type="primary" @click="onConfirmCreate" :loading="createData.confirmLoading" >确定</el-button> </div> </el-dialog> </div></template><script lang="ts">import { IDataFolderCreate, IDataFolderItem, IDataFolderSortRequest, IDataFolderUpdate,} from '@/models/Data/DataFolder';import { Component, Vue, Ref, Prop, Watch,} from 'vue-property-decorator';import { Tree } from 'element-ui';import dataFolderService from '@/services/DataFolderServices';@Component({ components: { [Tree.name]: Tree, },}) export default class FolderTree extends Vue { @Ref() treeRef!: Tree @Prop() sourceType!: number @Watch('sourceType') onSourceTypeChange() { this.fetchList(); } loading = false renameData = { visible: false, value: '', confirmLoading: false, data: null as null | IDataFolderItem, } createData = { visible: false, value: '', confirmLoading: false, parentData: null as null | IDataFolderItem, } treeProps = { label: 'name', children: 'files', } treeData: IDataFolderItem[] = [] backupTreeData: IDataFolderItem[] = [] this.fetchList(); } async fetchList() { this.loading = true; try { const res = await dataFolderService.getList({ type: this.sourceType, }); this.treeData = res; this.$nextTick(() => { this.treeRef.setCurrentKey(this.treeData[0].id); this.onNodeClick(this.treeData[0]); }); } finally { this.loading = false; } } onAddMenu(parentItemData: IDataFolderItem) { this.createData.value = ''; this.createData.parentData = parentItemData; this.createData.visible = true; } async onDeleteMenu(data: IDataFolderItem) { await this.$confirm(`确定删除 “${data.name}” 文件夹`, { type: 'warning', }); this.loading = true; try { await dataFolderService.delete(data.id); this.treeRef.remove(data); } finally { this.loading = false; } } onContextmenu(event: Event, dataItem: IDataFolderItem, node: any) { console.log(node); (this as any).$contextmenu({ items: [ { label: '重命名', onClick: () => this.onOpenRenameDialog(dataItem), }, { label: '新增', disabled: node.level >= 5, onClick: () => this.onAddMenu(dataItem), }, { label: '删除', onClick: () => this.onDeleteMenu(dataItem), }, ], zIndex: 99, event, }); event.stopPropagation(); } onTreeWrapperContextmenu(event: Event) { (this as any).$contextmenu({ items: [ { label: '新增', onClick: () => this.onAddMenu({ id: 0, name: '根目录', files: [], up_id: 0, datas: [], }), }, ], zIndex: 99, event, }); event.preventDefault(); } onOpenRenameDialog(nodeData: IDataFolderItem) { this.renameData.value = nodeData.name; this.renameData.data = nodeData; this.renameData.visible = true; } onCloseRenameDialog() { this.renameData.visible = false; } async onConfirmRename() { this.renameData.confirmLoading = true; try { const submitData: IDataFolderUpdate = { ...this.renameData.data!, name: this.renameData.value, }; await dataFolderService.update(submitData); this.renameData.visible = false; this.renameData.data!.name = this.renameData.value; } finally { this.renameData.confirmLoading = false; } } onCloseCreateDialog() { this.createData.visible = false; } async onConfirmCreate() { this.createData.confirmLoading = true; try { const submitData: IDataFolderCreate = { name: this.createData.value, up_id: this.createData.parentData!.id, type: this.sourceType, }; const res = await dataFolderService.create(submitData); if (!res.files) { res.files = []; } this.createData.visible = false; if (!this.createData.parentData!.files) { this.createData.parentData!.files = []; } if (this.createData.parentData?.id === 0) { } finally { this.createData.confirmLoading = false; } } onNodeDragStart() { this.backupTreeData = [...this.treeData]; } async onDropSuccess(selfNode: Record<string, any>, afterNode: Record<string, any>) { const submitData: IDataFolderSortRequest = { from_id: selfNode.data.id, to_id: afterNode.data.id, }; this.loading = true; try { await dataFolderService.sort(submitData); } catch { this.loading = false; } } onAllowDrop(draggingNode: any, dropNode: any, type: string) { const dragData = draggingNode.data; const dropData = dropNode.data; const res = dragData.up_id === dropData.up_id && draggingNode.level === dropNode.level && type !== 'inner'; return res; } onNodeClick(data: IDataFolderItem) { this.$emit('active-change', data); } } </script><style lang="scss" scoped>.tree-wrapper { overflow-x: auto; overflow-y: auto; height: 500px; width: 300px; ::v-deep { .el-tree-node>.el-tree-node__children { overflow: visible; } } } </style>
|