249 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <section class="AiAddressBookMenu">
 | |
|     <div class="tabsPane">
 | |
|       <h2 v-for="tab in tabs" :key="tab.name" :class="{tabActive:current==tab.name}"
 | |
|           @click="handleTabClick(tab)">{{ tab.label }}</h2>
 | |
|     </div>
 | |
|     <div class="contentPane">
 | |
|       <el-input :placeholder="`请输入${currentTab.label}名称`"
 | |
|                 size="small" v-model="search" suffix-icon="iconfont iconSearch"
 | |
|                 @change="handleSearchChange"/>
 | |
|       <div v-if="isTagType" class="addressBook-left__tags">
 | |
|         <div @click="selected=item" v-for="(item, index) in tags" :key="index"
 | |
|              class="addressBook-left__tags--item"
 | |
|              :class="{'addressBook-left__tags--item-active':selected.id == item.id}">
 | |
|           <span>{{ item.tagname }}</span>
 | |
|         </div>
 | |
|       </div>
 | |
|       <div class="AiAddressBookMenu-wrapper" v-else>
 | |
|         <div class="AiAddressBookMenu-tree">
 | |
|           <el-tree
 | |
|             ref="tree"
 | |
|             node-key="id"
 | |
|             highlight-current
 | |
|             :filter-node-method="handleTreeFilter"
 | |
|             :props="defaultProps" :data="list"
 | |
|             :default-expanded-keys="treeRoot"
 | |
|             @current-change="v=>selected=v">
 | |
|             <div class="tree-container" slot-scope="{ data }">
 | |
|               <span>{{ data.name }}</span>
 | |
|             </div>
 | |
|           </el-tree>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|   </section>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| /**
 | |
|  * 通讯录选择器
 | |
|  */
 | |
| export default {
 | |
|   name: "AiAddressBookMenu",
 | |
|   props: {
 | |
|     instance: Function,
 | |
|   },
 | |
|   computed: {
 | |
|     tabs() {
 | |
|       return [
 | |
|         {label: "组织架构", name: 0},
 | |
|         {label: "标签", name: 1}
 | |
|       ]
 | |
|     },
 | |
|     currentTab() {
 | |
|       return this.tabs.find(e => e.name == this.current) || {}
 | |
|     },
 | |
|     isTagType() {
 | |
|       return this.current == 1
 | |
|     },
 | |
|     defaultProps() {
 | |
|       return {
 | |
|         children: 'children',
 | |
|         label: 'name'
 | |
|       }
 | |
|     },
 | |
|     tags() {
 | |
|       return this.list?.filter(e => !this.search || e.tagname?.indexOf(this.search) > -1)
 | |
|     },
 | |
|     treeRoot() {
 | |
|       let root = this.list?.[0]
 | |
|       return root ? [root?.id] : []
 | |
|     }
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       current: 0,
 | |
|       search: "",
 | |
|       list: [],
 | |
|       origin: [],
 | |
|       selected: {}
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     selected(v) {
 | |
|       v && this.$emit('select', {...v, type: this.current})
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     handleTabClick(tab) {
 | |
|       this.current = tab.name
 | |
|       this.isTagType ? this.getTags() : this.getUnits()
 | |
|       this.$emit('tabClick')
 | |
|     },
 | |
|     handleTreeFilter(v, data) {
 | |
|       return data?.name?.indexOf(v) > -1
 | |
|     },
 | |
|     handleSearchChange(v) {
 | |
|       if (this.isTagType) {
 | |
|       } else {
 | |
|         this.$refs.tree?.filter(v)
 | |
|       }
 | |
|     },
 | |
|     handleTagClick(tag) {
 | |
|       this.$emit('tag', tag)
 | |
|       this.selected = tag
 | |
|     },
 | |
|     getUnits() {
 | |
|       this.instance.post(`/app/wxcp/wxdepartment/listAll`).then(res => {
 | |
|         if (res?.data) {
 | |
|           this.list = res.data?.filter(e => !e.parentid)
 | |
|           this.list.map(p => this.addChild(p, res.data, {parent: 'parentid'}))
 | |
| 
 | |
|           this.$nextTick(() => {
 | |
|             this.$refs.tree.setCurrentKey(res.data[0].id)
 | |
|             this.$emit('select', res.data[0])
 | |
|           })
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     getTags() {
 | |
|       this.instance.post(`/app/wxcp/wxtag/listAll`).then(res => {
 | |
|         if (res?.data) {
 | |
|           this.origin = JSON.parse(JSON.stringify(res.data))
 | |
|           this.list = res?.data
 | |
|         }
 | |
|       })
 | |
|     }
 | |
|   },
 | |
|   created() {
 | |
|     this.getUnits()
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .AiAddressBookMenu {
 | |
|   width: 100%;
 | |
|   height: 100%;
 | |
|   background: #FAFAFB;
 | |
|   .tabsPane {
 | |
|     display: flex;
 | |
|     align-items: center;
 | |
|     width: 100%;
 | |
|     height: 40px;
 | |
|     background: #ffffff;
 | |
| 
 | |
|     h2 {
 | |
|       flex: 1;
 | |
|       height: 100%;
 | |
|       line-height: 40px;
 | |
|       color: #222;
 | |
|       font-size: 14px;
 | |
|       text-align: center;
 | |
|       cursor: pointer;
 | |
|       border-bottom: 2px solid transparent;
 | |
| 
 | |
|       &.tabActive {
 | |
|         color: #2266FF;
 | |
|         border-bottom: 2px solid #2266FF;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .AiAddressBookMenu-wrapper {
 | |
|     height: calc(100% - 32px);
 | |
|     .AiAddressBookMenu-tree {
 | |
|       width: 100%;
 | |
|       height: 100%;
 | |
|       overflow: auto;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .contentPane {
 | |
|     height: calc(100% - 56px);
 | |
|     margin: 8px;
 | |
|     overflow: auto;
 | |
| 
 | |
|     .addressBook-left__tags--item {
 | |
|       cursor: pointer;
 | |
|       display: flex;
 | |
|       align-items: center;
 | |
|       justify-content: space-between;
 | |
|       height: 40px;
 | |
|       padding: 0 8px 0 16px;
 | |
|       color: #222222;
 | |
| 
 | |
|       &.addressBook-left__tags--item-active, &:hover {
 | |
|         background: #E8EFFF;
 | |
|         color: #2266FF;
 | |
| 
 | |
|         i, span {
 | |
|           color: #2266FF;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       span {
 | |
|         font-size: 14px;
 | |
|       }
 | |
| 
 | |
|       i {
 | |
|         cursor: pointer;
 | |
|         color: #8e9ebf;
 | |
|         font-size: 16px;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     span {
 | |
|       color: #222;
 | |
|       font-size: 14px;
 | |
|     }
 | |
| 
 | |
|     :deep( .el-tree ){
 | |
|       width: 100%;
 | |
|       margin-top: 4px;
 | |
|       background: transparent;
 | |
|       width: fit-content;
 | |
|       min-width: 100%;
 | |
| 
 | |
|       .el-tree-node__content {
 | |
|         display: inline-flex;
 | |
|         min-width: 100%;
 | |
|         height: 32px;
 | |
| 
 | |
|         &:hover {
 | |
|           background: #E8EFFF;
 | |
|           color: #222222;
 | |
|           border-radius: 2px;
 | |
|         }
 | |
|       }
 | |
| 
 | |
| 
 | |
|       .is-current > .el-tree-node__content {
 | |
|         background: #2266FF;
 | |
| 
 | |
|         &:hover {
 | |
|           background: #2266FF;
 | |
|           color: #fff;
 | |
|         }
 | |
| 
 | |
|         span {
 | |
|           color: #fff;
 | |
|           font-weight: bold;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |