交通管理局公文项目
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

4 months ago
2 months ago
4 months ago
3 months ago
4 months ago
2 months ago
4 months ago
3 months ago
4 months ago
2 months ago
4 months ago
2 months ago
4 months ago
2 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
3 months ago
2 months ago
3 months ago
4 months ago
2 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
  1. <template>
  2. <div class="container-left">
  3. <span class="right-top-line" />
  4. <span class="left-bottom-line" />
  5. <!--门类树状结构-->
  6. <div class="tree-scroll">
  7. <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">
  8. <span slot-scope="{ node, data }" class="custom-tree-node">
  9. <span v-if="data.isType === 1 " class="iconFolder">
  10. {{ data.label }}
  11. </span>
  12. <span v-else-if="data.isType === 2" class="iconFile">
  13. {{ data.label }}
  14. </span>
  15. <span v-else>{{ data.label }}</span>
  16. </span>
  17. </el-tree>
  18. </div>
  19. </div>
  20. </template>
  21. <script>
  22. import CRUD, { presenter, header } from '@crud/crud'
  23. import { miodLibraryCrud } from './mixins/index'
  24. import { mapGetters } from 'vuex'
  25. export default {
  26. name: 'MiodTree',
  27. components: { },
  28. cruds() {
  29. return [
  30. CRUD({
  31. title: '公文库', url: 'api/documentArchives/menu',
  32. crudMethod: { },
  33. optShow: {
  34. add: false,
  35. edit: false,
  36. del: false,
  37. download: true,
  38. group: false,
  39. reset: true
  40. }
  41. })
  42. ]
  43. },
  44. mixins: [presenter(), header(), miodLibraryCrud],
  45. data() {
  46. return {
  47. permission: {
  48. add: ['admin', 'prearchiveLibrary:add'],
  49. edit: ['admin', 'prearchiveLibrary:edit'],
  50. del: ['admin', 'prearchiveLibrary:del'],
  51. sort: ['admin', 'prearchiveLibrary:sort']
  52. },
  53. defaultProps: {
  54. children: 'children',
  55. label: 'cnName'
  56. },
  57. currentTreeVal: null,
  58. nodeToSelect: null
  59. }
  60. },
  61. computed: {
  62. ...mapGetters([
  63. 'user'
  64. ]),
  65. expandedKeys() {
  66. const keys = []
  67. const collectKeys = (nodes) => {
  68. nodes.forEach(node => {
  69. if (node.expanded) {
  70. keys.push(node.id)
  71. if (node.children) collectKeys(node.children)
  72. }
  73. })
  74. }
  75. collectKeys(this.crud.data)
  76. return keys
  77. }
  78. },
  79. created() {
  80. },
  81. methods: {
  82. refreshData() {
  83. // 保存当前选中节点信息用于刷新后重新选中
  84. if (this.currentTreeVal) {
  85. this.nodeToSelect = {
  86. ...this.currentTreeVal,
  87. timestamp: Date.now() // 添加时间戳确保数据新鲜
  88. }
  89. } else {
  90. this.nodeToSelect = null
  91. }
  92. this.crud.toQuery()
  93. },
  94. [CRUD.HOOK.beforeRefresh](crud) {
  95. this.crud.query.page = null
  96. this.crud.query.size = null
  97. this.crud.query.fondsId = this.user.fonds.id
  98. const ids = this.user.roles.map(item => { return item.id })
  99. this.crud.query.roleIds = ids.join(',')
  100. },
  101. [CRUD.HOOK.afterRefresh]() {
  102. // 将数据转换为适合树形结构的
  103. this.crud.data = this.crud.data.map(item => ({
  104. label: item.cnName,
  105. id: item.id,
  106. pid: item.pid,
  107. isType: item.isType,
  108. expanded: item.isType === 1,
  109. children: item.children?.map(child => ({
  110. label: child.cnName,
  111. id: child.id,
  112. pid: child.pid,
  113. isType: child.isType,
  114. expanded: child.isType === 2,
  115. children: child.docDepartments?.map(department => ({
  116. label: department.dictionaryName,
  117. id: department.dictionaryId,
  118. isType: 3,
  119. expanded: false,
  120. documentId: child.id,
  121. dictionaryId: department.dictionaryId,
  122. dictionaryCode: department.dictionaryCode,
  123. children: department.yearGroup
  124. .sort((a, b) => b - a) // 年份倒序排列
  125. .map(year => ({
  126. documentId: child.id,
  127. dictionaryName: department.dictionaryName,
  128. label: year,
  129. id: year + department.dictionaryName,
  130. isType: 4
  131. }))
  132. }))
  133. }))
  134. }))
  135. // 节点选择逻辑
  136. this.$nextTick(() => {
  137. let targetNode = null
  138. // 如果有需要选中的节点信息
  139. if (this.nodeToSelect) {
  140. switch (this.nodeToSelect.isType) {
  141. case 4: // 年份节点
  142. targetNode = this.findNodeByDocumentIdAndDictionaryName(
  143. this.crud.data,
  144. this.nodeToSelect.documentId,
  145. this.nodeToSelect.dictionaryName,
  146. this.nodeToSelect.id // 年份值
  147. )
  148. break
  149. case 3: // 部门节点
  150. targetNode = this.findNodeByDictionaryIdAndDocumentId(
  151. this.crud.data,
  152. this.nodeToSelect.dictionaryId,
  153. this.nodeToSelect.documentId
  154. )
  155. break
  156. case 2: // 文档节点
  157. targetNode = this.findNodeById(
  158. this.crud.data,
  159. this.nodeToSelect.id
  160. )
  161. break
  162. case 1: // 文件夹节点 - 找到第一个文档节点
  163. targetNode = this.findFirstIsType2Node(this.crud.data)
  164. break
  165. }
  166. }
  167. console.log('targetNode', targetNode)
  168. // 如果没有找到目标节点或者没有需要选中的节点,则选择第一个文档节点
  169. if (!targetNode) {
  170. targetNode = this.findFirstIsType2Node(this.crud.data)
  171. }
  172. // 如果找到了目标节点,则选中它
  173. if (targetNode) {
  174. this.$refs.tree.setCurrentKey(targetNode.id)
  175. this.handleNodeClick(targetNode, 'targetNode')
  176. if (targetNode.isType === 4) {
  177. this.$nextTick(() => {
  178. const parentNode = this.findParentNode(this.crud.data, targetNode)
  179. if (parentNode) {
  180. parentNode.expanded = true
  181. if (!this.expandedKeys.includes(parentNode.id)) {
  182. this.expandedKeys = [...this.expandedKeys, parentNode.id]
  183. }
  184. const treeNode = this.$refs.tree.getNode(parentNode.id)
  185. if (treeNode) {
  186. treeNode.expanded = true
  187. }
  188. }
  189. })
  190. }
  191. }
  192. // 重置节点选择信息
  193. this.nodeToSelect = null
  194. })
  195. },
  196. // 递归查找父节点
  197. findParentNode(nodes, targetNode) {
  198. for (const node of nodes) {
  199. if (node.children && node.children.some(child => child.id === targetNode.id)) {
  200. return node
  201. }
  202. const found = this.findParentNode(node.children || [], targetNode)
  203. if (found) return found
  204. }
  205. return null
  206. },
  207. // 查找函数
  208. findNodeById(nodes, id) {
  209. if (!nodes || nodes.length === 0) return null
  210. for (const node of nodes) {
  211. if (node.id === id) return node
  212. if (node.children && node.children.length > 0) {
  213. const found = this.findNodeById(node.children, id)
  214. if (found) return found
  215. }
  216. }
  217. return null
  218. },
  219. findNodeByDictionaryIdAndDocumentId(nodes, dictionaryId, documentId) {
  220. if (!nodes || nodes.length === 0) return null
  221. for (const node of nodes) {
  222. // 检查当前节点
  223. if (node.isType === 3 &&
  224. node.dictionaryId === dictionaryId &&
  225. node.documentId === documentId) {
  226. return node
  227. }
  228. // 递归检查子节点
  229. if (node.children && node.children.length > 0) {
  230. const found = this.findNodeByDictionaryIdAndDocumentId(
  231. node.children,
  232. dictionaryId,
  233. documentId
  234. )
  235. if (found) return found
  236. }
  237. }
  238. return null
  239. },
  240. findNodeByDocumentIdAndDictionaryName(nodes, documentId, dictionaryName, year) {
  241. if (!nodes || nodes.length === 0) return null
  242. for (const node of nodes) {
  243. // 检查当前节点是否是目标部门节点(isType=3)
  244. if (node.isType === 3 &&
  245. node.documentId === documentId &&
  246. node.label === dictionaryName) { // 使用 label 匹配部门名称(示例数据中为“中共中央”等)
  247. // 在部门子节点中查找年份节点(isType=4)
  248. if (node.children && node.children.length > 0) {
  249. return node.children.find(child => child.isType === 4 && child.id === year)
  250. }
  251. }
  252. // 递归检查子节点
  253. if (node.children && node.children.length > 0) {
  254. const found = this.findNodeByDocumentIdAndDictionaryName(
  255. node.children,
  256. documentId,
  257. dictionaryName,
  258. year
  259. )
  260. if (found) return found
  261. }
  262. }
  263. return null
  264. },
  265. findFirstIsType2Node(nodes) {
  266. if (!nodes || nodes.length === 0) return null
  267. for (const node of nodes) {
  268. if (node.isType === 2) {
  269. return node // 找到后返回节点对象
  270. }
  271. if (node.children && node.children.length > 0) {
  272. const found = this.findFirstIsType2Node(node.children)
  273. if (found) return found // 递归查找子节点
  274. }
  275. }
  276. return null // 未找到
  277. },
  278. // 选中门类后
  279. handleNodeClick(val, type) {
  280. if (val) {
  281. this.currentTreeVal = val
  282. this.$emit('nodeClick', val, type)
  283. }
  284. }
  285. }
  286. }
  287. </script>
  288. <style lang='scss' scoped>
  289. [data-theme=dark] .elect-cont-left .container-left {
  290. min-height: calc(100vh - 158px);
  291. }
  292. .tree-scroll{
  293. font-size: 14px;
  294. height: calc(100vh - 183px);
  295. overflow-y: scroll;
  296. }
  297. .el-card .el-tree, .container-left .el-tree{
  298. margin: 0 !important;
  299. }
  300. ::v-deep ::-webkit-scrollbar {
  301. width: 5px !important;
  302. height: 5px !important;
  303. }
  304. ::v-deep ::-webkit-scrollbar-thumb {
  305. background-color:rgba(0,0,0,.1) !important;
  306. }
  307. </style>