You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
10 KiB
337 lines
10 KiB
<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>
|