|
|
<template>
<div class="container-left"> <span class="right-top-line" /> <span class="left-bottom-line" /> <!--门类树状结构--> <div class="tree-scroll"> <el-tree ref="tree" v-loading="crud.loading" :data="crud.data" :props="defaultProps" node-key="id" :expand-on-click-node="false" highlight-current :default-expanded-keys="expandedKeys" @node-click="handleNodeClick"> <span slot-scope="{ node, data }" class="custom-tree-node"> <span v-if="data.isType === 1 " class="iconFolder"> {{ data.label }} </span> <span v-else-if="data.isType === 2" class="iconFile"> {{ data.label }} </span> <span v-else>{{ data.label }}</span> </span> </el-tree> </div> </div> </template>
<script> import CRUD, { presenter, header } from '@crud/crud' import { miodLibraryCrud } from './mixins/index' import { mapGetters } from 'vuex' export default { name: 'MiodTree', components: { }, cruds() { return [ CRUD({ title: '公文库', url: 'api/documentArchives/menu', crudMethod: { }, optShow: { add: false, edit: false, del: false, download: true, group: false, reset: true } }) ] }, mixins: [presenter(), header(), miodLibraryCrud], data() { return { permission: { add: ['admin', 'prearchiveLibrary:add'], edit: ['admin', 'prearchiveLibrary:edit'], del: ['admin', 'prearchiveLibrary:del'], sort: ['admin', 'prearchiveLibrary:sort'] }, defaultProps: { children: 'children', label: 'cnName' }, currentTreeVal: null, nodeToSelect: null } }, computed: { ...mapGetters([ 'user' ]), expandedKeys() { const keys = [] const collectKeys = (nodes) => { nodes.forEach(node => { if (node.expanded) { keys.push(node.id) if (node.children) collectKeys(node.children) } }) } collectKeys(this.crud.data) return keys } }, created() { }, methods: { refreshData() { // 保存当前选中节点信息用于刷新后重新选中
if (this.currentTreeVal) { this.nodeToSelect = { ...this.currentTreeVal, timestamp: Date.now() // 添加时间戳确保数据新鲜
} } else { this.nodeToSelect = null }
this.crud.toQuery() }, [CRUD.HOOK.beforeRefresh](crud) { this.crud.query.page = null this.crud.query.size = null this.crud.query.fondsId = this.user.fonds.id const ids = this.user.roles.map(item => { return item.id }) this.crud.query.roleIds = ids.join(',') }, [CRUD.HOOK.afterRefresh]() { // 将数据转换为适合树形结构的
this.crud.data = this.crud.data.map(item => ({ label: item.cnName, id: item.id, pid: item.pid, isType: item.isType, expanded: item.isType === 1, children: item.children?.map(child => ({ label: child.cnName, id: child.id, pid: child.pid, isType: child.isType, expanded: child.isType === 2, children: child.docDepartments?.map(department => ({ label: department.dictionaryName, id: department.dictionaryId, isType: 3, expanded: false, documentId: child.id, dictionaryId: department.dictionaryId, dictionaryCode: department.dictionaryCode, children: department.yearGroup .sort((a, b) => b - a) // 年份倒序排列
.map(year => ({ documentId: child.id, dictionaryName: department.dictionaryName, label: year, id: year + department.dictionaryName, isType: 4 })) })) })) })) // 节点选择逻辑
this.$nextTick(() => { let targetNode = null
// 如果有需要选中的节点信息
if (this.nodeToSelect) { switch (this.nodeToSelect.isType) { case 4: // 年份节点
targetNode = this.findNodeByDocumentIdAndDictionaryName( this.crud.data, this.nodeToSelect.documentId, this.nodeToSelect.dictionaryName, this.nodeToSelect.id // 年份值
) break
case 3: // 部门节点
targetNode = this.findNodeByDictionaryIdAndDocumentId( this.crud.data, this.nodeToSelect.dictionaryId, this.nodeToSelect.documentId ) break
case 2: // 文档节点
targetNode = this.findNodeById( this.crud.data, this.nodeToSelect.id ) break
case 1: // 文件夹节点 - 找到第一个文档节点
targetNode = this.findFirstIsType2Node(this.crud.data) break } } console.log('targetNode', targetNode)
// 如果没有找到目标节点或者没有需要选中的节点,则选择第一个文档节点
if (!targetNode) { targetNode = this.findFirstIsType2Node(this.crud.data) }
// 如果找到了目标节点,则选中它
if (targetNode) { this.$refs.tree.setCurrentKey(targetNode.id) this.handleNodeClick(targetNode, 'targetNode')
if (targetNode.isType === 4) { this.$nextTick(() => { const parentNode = this.findParentNode(this.crud.data, targetNode) if (parentNode) { parentNode.expanded = true
if (!this.expandedKeys.includes(parentNode.id)) { this.expandedKeys = [...this.expandedKeys, parentNode.id] }
const treeNode = this.$refs.tree.getNode(parentNode.id) if (treeNode) { treeNode.expanded = true } } }) } } // 重置节点选择信息
this.nodeToSelect = null }) }, // 递归查找父节点
findParentNode(nodes, targetNode) { for (const node of nodes) { if (node.children && node.children.some(child => child.id === targetNode.id)) { return node } const found = this.findParentNode(node.children || [], targetNode) if (found) return found } return null }, // 查找函数
findNodeById(nodes, id) { if (!nodes || nodes.length === 0) return null
for (const node of nodes) { if (node.id === id) return node
if (node.children && node.children.length > 0) { const found = this.findNodeById(node.children, id) if (found) return found } }
return null },
findNodeByDictionaryIdAndDocumentId(nodes, dictionaryId, documentId) { if (!nodes || nodes.length === 0) return null
for (const node of nodes) { // 检查当前节点
if (node.isType === 3 && node.dictionaryId === dictionaryId && node.documentId === documentId) { return node }
// 递归检查子节点
if (node.children && node.children.length > 0) { const found = this.findNodeByDictionaryIdAndDocumentId( node.children, dictionaryId, documentId ) if (found) return found } }
return null },
findNodeByDocumentIdAndDictionaryName(nodes, documentId, dictionaryName, year) { if (!nodes || nodes.length === 0) return null
for (const node of nodes) { // 检查当前节点是否是目标部门节点(isType=3)
if (node.isType === 3 && node.documentId === documentId && node.label === dictionaryName) { // 使用 label 匹配部门名称(示例数据中为“中共中央”等)
// 在部门子节点中查找年份节点(isType=4)
if (node.children && node.children.length > 0) { return node.children.find(child => child.isType === 4 && child.id === year) } }
// 递归检查子节点
if (node.children && node.children.length > 0) { const found = this.findNodeByDocumentIdAndDictionaryName( node.children, documentId, dictionaryName, year ) if (found) return found } }
return null }, findFirstIsType2Node(nodes) { if (!nodes || nodes.length === 0) return null
for (const node of nodes) { if (node.isType === 2) { return node // 找到后返回节点对象
}
if (node.children && node.children.length > 0) { const found = this.findFirstIsType2Node(node.children) if (found) return found // 递归查找子节点
} }
return null // 未找到
}, // 选中门类后
handleNodeClick(val, type) { if (val) { this.currentTreeVal = val this.$emit('nodeClick', val, type) } } } } </script>
<style lang='scss' scoped> [data-theme=dark] .elect-cont-left .container-left { min-height: calc(100vh - 158px); } .tree-scroll{ font-size: 14px; height: calc(100vh - 183px); overflow-y: scroll;
} .el-card .el-tree, .container-left .el-tree{ margin: 0 !important; }
::v-deep ::-webkit-scrollbar { width: 5px !important; height: 5px !important; }
::v-deep ::-webkit-scrollbar-thumb { background-color:rgba(0,0,0,.1) !important; } </style>
|