189 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <section class="AiPartyTree">
 | |
|     <template v-if="!!search">
 | |
|       <div class="searchItem" v-for="item in searchList" :class="{current:item.id==selected.id}" :key="item.id" v-text="item.name"
 | |
|            @click="handleNodeClick(item)"/>
 | |
|       <div/>
 | |
|       <ai-empty v-if="!searchList.length">暂无搜索结果</ai-empty>
 | |
|     </template>
 | |
|     <el-tree ref="partyTree" lazy :load="loadOrgs" node-key="id" :props="props" v-show="!search"
 | |
|              :default-expanded-keys="defaultExpanded" v-on="$listeners" v-bind="$attrs" @node-click="handleNodeClick"/>
 | |
|   </section>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import request from "../../lib/js/request";
 | |
| import AiEmpty from "../basic/AiEmpty";
 | |
| 
 | |
| export default {
 | |
|   name: "AiPartyTree",
 | |
|   components: {AiEmpty},
 | |
|   props: {
 | |
|     instance: {default: () => request},
 | |
|     root: {default: ""},
 | |
|     defaultFirstOption: Boolean
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       props: {
 | |
|         label: 'name',
 | |
|         isLeaf: data => data.isLeaf == 1
 | |
|       },
 | |
|       defaultExpanded: [],
 | |
|       searchList: [],
 | |
|       selected: {}
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     search: v => v.$parent.searchText || ""
 | |
|   },
 | |
|   methods: {
 | |
|     loadOrgs(node, resolve) {
 | |
|       if (node.level == 0) {
 | |
|         this.getRoot(resolve)
 | |
|       } else if (node.level >= 1) {
 | |
|         this.getOrgsByParent(node.data?.id, resolve)
 | |
|       }
 | |
|     },
 | |
|     getOrgsByParent(id, resolve) {
 | |
|       this.instance.post("/app/partyOrganization/queryChildrenByParentId", null, {
 | |
|         params: {id}
 | |
|       }).then(res => {
 | |
|         if (res?.data) {
 | |
|           resolve(res.data.filter(e => e.id != id) || [])
 | |
|         } else {
 | |
|           resolve([])
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     handleNodeClick(data) {
 | |
|       this.selected = data
 | |
|       this.$emit('select', data)
 | |
|       this.$emit('node-click', data)
 | |
|     },
 | |
|     getRoot(resolve) {
 | |
|       this.root && this.instance.post("/app/partyOrganization/queryOrgById", null, {
 | |
|         params: {id: this.root}
 | |
|       }).then(res => {
 | |
|         if (res?.data) {
 | |
|           resolve && resolve([res.data])
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     handleSearch(name) {
 | |
|       !!name && this.instance.post("/app/partyOrganization/queryPartyOrganizationListByName", null, {
 | |
|         throttle: 500,
 | |
|         params: {size: 999, name}
 | |
|       }).then(res => {
 | |
|         if (res?.data) {
 | |
|           this.searchList = res.data
 | |
|         }
 | |
|       })
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     root: {
 | |
|       immediate: true,
 | |
|       handler(v) {
 | |
|         this.getRoot(res => {
 | |
|           this.$nextTick(() => {
 | |
|             const root = res?.[0]
 | |
|             this.$nextTick(() => {
 | |
|               this.defaultExpanded = [res?.[0].id]
 | |
|             })
 | |
|             if (root && this.defaultFirstOption) {
 | |
|               this.handleNodeClick(root)
 | |
|               this.defaultExpanded = [res?.[0].id]
 | |
|             }
 | |
|             if (v) {
 | |
|               this.defaultExpanded = [v]
 | |
|             }
 | |
|           })
 | |
|         })
 | |
|       }
 | |
|     },
 | |
|     search(v) {
 | |
|       v && this.$refs.partyTree?.setCurrentKey(null)
 | |
|       this.handleSearch(v)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .AiPartyTree {
 | |
|   .gap {
 | |
|     width: 100%;
 | |
|     height: 17px;
 | |
|   }
 | |
| 
 | |
|   .searchItem {
 | |
|     cursor: pointer;
 | |
|     line-height: 32px;
 | |
|     white-space: nowrap;
 | |
|     padding: 0 8px;
 | |
| 
 | |
|     &:hover {
 | |
|       background: #E8EFFF;
 | |
|       color: #222222;
 | |
|       border-radius: 2px;
 | |
|     }
 | |
| 
 | |
|     &.current {
 | |
|       background: $primaryColor;
 | |
|       color: #fff;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep( .el-tree ) {
 | |
|     background: transparent;
 | |
| 
 | |
|     .el-tree-node__expand-icon.is-leaf {
 | |
|       color: transparent !important;
 | |
|     }
 | |
| 
 | |
|     .el-tree-node__content {
 | |
|       display: inline-flex;
 | |
|       min-width: 100%;
 | |
|     }
 | |
| 
 | |
|     .el-tree-node__content > .el-tree-node__expand-icon {
 | |
|       padding: 4px;
 | |
|     }
 | |
| 
 | |
|     .el-tree-node__content {
 | |
|       height: 32px;
 | |
|     }
 | |
| 
 | |
|     .el-tree__empty-text {
 | |
|       color: #222;
 | |
|       font-size: 14px;
 | |
|     }
 | |
| 
 | |
|     .el-tree-node__children .el-tree-node__content {
 | |
|       height: 32px;
 | |
|     }
 | |
| 
 | |
|     .el-tree-node__content:hover {
 | |
|       background: #E8EFFF;
 | |
|       color: #222222;
 | |
|       border-radius: 2px;
 | |
|     }
 | |
| 
 | |
|     .is-current > .el-tree-node__content {
 | |
|       &:hover {
 | |
|         background: $primaryColor;
 | |
|         color: #fff;
 | |
|       }
 | |
| 
 | |
|       background: $primaryColor;
 | |
| 
 | |
|       span {
 | |
|         color: #fff;
 | |
|         font-weight: bold;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |