GitBucket
4.6.0
Toggle navigation
Sign in
Files
Branches
1
Tags
Issues
Pull Requests
Labels
Milestones
Wiki
08335
/
hivui-platform-template
hivui平台项目模板
Browse code
Merge branch 'master' of http://git.hieap.cn/gitbucket/git/08335/hivui-platform-template
master
commit
cfe48a5e4c424e8389fe675fa7d531ff34aae077
2 parents
1693a2a
+
554180a
hhb
authored
on 10 May
Showing
2 changed files
project/hivuiMain/views/layout/components/Header.vue
project/hivuiMain/views/layout/components/allFuncMenu/index.vue
Ignore Space
Show notes
View
project/hivuiMain/views/layout/components/Header.vue
<template> <div class="pl-header " :data-layout="layout"> <ul class="ltArea"> <li v-if="layout=='level'" class="logoStyle"> <div class="pl-logo"> <div v-if="hasTitle" @click="logoClickHanlder(logoOpt)"> <img :src="def_sy_logo_horizon" :width="logoWidth" v-if="!logoOpt.src"> <img :src="logoOpt.src" :width="logoOpt.width?(logoOpt.width+'px'):(!logoOpt.height?logoWidth:null)" :height="logoOpt.height&&(logoOpt.height+'px')" :title="logoOpt.title" v-if="logoOpt.src"> </div> <div v-else @click="logoClickHanlder(MlogoOpt)"> <img :src="def_sy_minLogo" v-if="!MlogoOpt.src"> <img :src="MlogoOpt.src" :width="MlogoOpt.width?(MlogoOpt.width+'px'):(!MlogoOpt.height?logoWidth:null)" :height="MlogoOpt.height&&(MlogoOpt.height+'px')" :title="MlogoOpt.title" v-if="MlogoOpt.src"> </div> </div> </li> <li v-else class="logoStyle"> <div class="pl-logo" @click="logoClickHanlder(logoOpt)"> <img :src="def_sy_logo" :width="logoWidth" v-if="!logoOpt.src"> <img :src="logoOpt.src" :width="logoOpt.width?(logoOpt.width+'px'):(!logoOpt.height?logoWidth:null)" :height="logoOpt.height&&(logoOpt.height+'px')" :title="logoOpt.title" v-if="logoOpt.src"> </div> </li> <li v-if="sysList.length"> <div class="sysTrigger" ref='dom-sysList' @mouseover="handleShowSysList" @mouseout="handleHideSysList"> <span>{{$t('hivuiMain_projectManage')}}</span> <i class="iconfont icon-change"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" @mouseenter="handleShowSysList" @mouseleave="handleHideSysList" :style="sysListStyle" v-add2Body> <li class="pl-menus-item" v-for="item,index in sysList" @click="handleChangeSys(item)"> <a class="title"><span class="txt">{{item.title}}</span></a> </li> </ul> </li> <li v-if="layout == 'level'&&!hideHistoryFuncList" > <div class="sysTrigger" ref="dom-latelyUse" :title='$t("hivuiMain_recentlyUsed")' @mouseenter="handleShowLatelyUse" @mouseleave="handleHideLatelyUse"> <i class="icon iconfont icon-time"></i> <span class="title">{{$t('hivuiMain_recentlyUsed')}}</span> <i class="icon iconfont icon-arrow-down"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" @mouseenter="handleShowLatelyUse" @mouseleave="handleHideLatelyUse" :style="latelyUseStyle" v-add2Body> <li class="pl-menus-item" v-for="item,index in navsLatelyUse" @click="handleOpenLatelyFunc(item)"> <a class="title"><span class="txt">{{item.name}}</span></a> </li> <li v-show="navsLatelyUse.length==0" class="pl-menus-tips"> {{$t('hivuiMain_nodata')}} </li> </ul> </li> <li v-if="layout == 'level'&&showAllFuncBtn" > <div class="sysTrigger"> <span ref="allFuncBtn" class="title" @mouseenter="allFuncTriggerOpen" @mouseleave="allFuncTriggerClose">{{$t('hivuiMain_allFunction')}}</span> <i class="icon iconfont icon-arrow-down"></i> <allFuncMenu ref="allFuncMenu" :triggerObj="allFuncBtnObj" v-add2Body></allFuncMenu> </div> </li> </ul> <ul class="rtArea"> <li> <div class="pl-search" ref="dom-searchBox" > <input ref="dom-seachTxt" class="pl-search-text" type="text" :placeholder="$t('hivuiMain_searchKey')" v-model.trim="searchWord" @keyup="handleSeachKeyUp" /> <i class="iconfont icon-search"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" :style="searchMenusStyle" v-add2Body> <li :class="['pl-menus-item',seldIndex==index?'pl-menus-itemSeld':'']" v-for="item,index in searchList" style="width:100%" @click="openFunc(item)"> <a class="title"><span class="txt" v-html="item.html||item.name"></span></a> </li> <li v-show="searchList.length==0&&searchWord.length>0" class="pl-menus-tips"> {{$t('hivuiMain_nodata')}} </li> </ul> </li> <li v-if="sysProjectManage"> <a :href="sysProjectManage.url" target='_blank' class="item" :title="sysProjectManage.name"> <i class="iconfont" :class="sysProjectManage.iconClass"></i> <span class="title">{{sysProjectManage.name}}</span> </a> </li> <template v-for="item in sysFuncMenus"> <li v-if="item.type!='split'"> <template v-if="item.type=='withNumTips'"> <div class="item" @click.prevent="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <span class="pl-head-tipsNum" :hidden="!(msgCount!=0)">{{msgCount}}</span> <!-- <span class="pl-head-tipsNum" :hidden="!(item.tipNum&&item.tipNum!=0)">{{item.tipNum}}</span> --> </div> </template> <template v-else> <template v-if="item.children&&item.children.length"> <div class="item" @mouseenter="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <i class="iconfont icon-arrow-down" v-if="item.children"></i> </div> </template> <template v-if="!item.children||item.children&&item.children.length==0"> <div class="item" @click.prevent="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <i class="iconfont icon-arrow-down" v-if="item.children"></i> </div> </template> </template> </li> <li v-if="item.type=='split'"><div class="line"></div></li> </template> <!-- <li> <div class="item"> <div class="tip"> <i class="iconfont icon-user"></i> </div> <span class="title">{{this.$store.getters.userId}}/{{this.$store.getters.userName}}</span> <i class="iconfont icon-arrow-down"></i> </div> </li> <li><div class="line"></div></li> --> <!-- 语言切换 --> <li v-if="langList"> <template v-if="langList.children&&langList.children.length"> <div class="item" @mouseenter="handleFuncMenus(langList,$event)"> <div class="tip"> <i class="iconfont" :class="langList.iconClass"></i> </div> <span class="title" v-html="langList.html||langList.name"></span> <i class="iconfont icon-arrow-down" v-if="langList.children"></i> </div> </template> </li> <li v-if="langList"><div class="line"></div></li> <!-- 用户信息 --> <li> <template v-if="sysUserInfo.children&&sysUserInfo.children.length"> <div class="item" @mouseenter="handleFuncMenus(sysUserInfo,$event)"> <div class="tip"> <i class="iconfont" :class="sysUserInfo.iconClass"></i> </div> <span class="title" v-html="sysUserInfo.html||sysUserInfo.name"></span> <i class="iconfont icon-arrow-down" v-if="sysUserInfo.children"></i> </div> </template> </li> <li><div class="line"></div></li> <li v-if="hasSetting"> <div class="item" :title="$t('hivuiMain_customWorkbench')"> <a href="#design" target='_blank'><i class="iconfont icon-set-fill"></i></a> </div> </li> <li> <div class="item" :title="$t('hivuiMain_logout')"> <a @click="handleLogout"><i class="iconfont icon-tuichu"></i></a> </div> </li> </ul> <vueContextMenu ref="cmp-funcMenu" :menu-items="menuItems" field="name"></vueContextMenu> <modifyPw></modifyPw> </div> </template> <script> import pinyin from 'js-pinyin';//ie 下有问题 编译不过 import vueContextMenu from "@main/components/contextMenu"; import modifyPw from "@main/views/layout/components/modifyPw"; import allFuncMenu from './allFuncMenu' import {changeBz} from "@main/api/user"; import { removeToken } from '@main/utils/auth' import { sortMapTurnArr } from '@main/utils/index' import def_sy_loading from "@main/assets/logo_max.png" import def_sy_minLogo from "@main/assets/logo_min.png" import def_sy_logo from "@main/assets/logo.png" import def_sy_logo_horizon from "@main/assets/logo_horizon.png" export default { components:{ vueContextMenu, modifyPw, allFuncMenu, }, inject:['addTab','showTab','hideTab'], props:{ hasTitle:{ type: Boolean, }, logoWidth:{ type: String, } }, data(){ return { menuItems:[], searchWord:"", searchList:[], seldIndex:0, menuShow:false, searchMenusStyle:{ display:'none', left:0, top:0, width:0, // maxHeight:'50%', // overflow:'auto' }, sysListStyle:{ display:'none', left:0, top:0, }, latelyUseStyle:{ display:'none', left:0, top:0, maxHeight:'50%', overflow:'auto' }, def_sy_minLogo:def_sy_minLogo, def_sy_logo:def_sy_logo, def_sy_logo_horizon:def_sy_logo_horizon, numTipTimer:null, showAllFuncBtn:window.customSysCofig.isShowAllFunc===false?false:true, hideHistoryFuncList:window.customSysCofig.hideHistoryFuncList||false, isShowAllFuncMenu:false, allFuncBtnObj:{}, msgCount:0 } }, computed:{ hasSetting(){ let cfg = this.$store.state.app.config||{}; if(cfg.hideSettingBtn){ return false; } let _arr=sortMapTurnArr(cfg.sysSetTabs); return _arr&&_arr.length; }, sysList(){ let cfg = this.$store.state.app.config||{}; return cfg.sysList||[]; }, sysUserInfo(){ let me=this; let cfg = this.$store.state.app.config||{}; function replaceData(str){ if(!str)return ['',false]; var _arr=str.match(/\${(\S*?)}/g); var nullNum=0; if(_arr&&_arr.length>0){ for(let i of _arr){ var _data=me.userInfo[i.match(/\${(\S*)}/)[1]]; if(typeof(_data)!="undefined"){ str=str.replace(i,_data); }else{ str=str.replace(i,me.$t('hivuiMain_header_null')); nullNum++; } } return [str,nullNum==_arr.length?false:true]; } return [str,true]; } //多岗信息文字模板format function orgBzTplFormat(str,item){ let fieldArr=str.match(/(?<=\${).*?(?=})/g); fieldArr.forEach((_i)=>{ if(typeof(item[_i])!="undefined"){ str=str.replaceAll("${"+_i+"}",item[_i]); } }); return str; } let _userInfo=cfg.userInfo; if(_userInfo){ _userInfo.name=replaceData(_userInfo.name)[0]; if(_userInfo.children&&_userInfo.children.length>0){ _userInfo.children=_userInfo.children.filter((item)=>{ let _rData=replaceData(item.name); item.name=_rData[0]; switch(item.type){ case "modifyUserInfo": item.handler=me.modifyUserInfo; break; case "modifyPw": item.handler=me.modifyPw; break; case "personalCenter": item.handler=me.personalCenter; break; case "orgBz": if(Array.isArray(me.bzList)&&me.bzList.length>1){ item.children=[]; for(let i of me.bzList){ let _pushData={ iconClass:'icon-user', name:cfg.orgBzTpl?orgBzTplFormat(cfg.orgBzTpl,i):`${i.fbzname}/${i.fbzid}`, handler:function(){ me.__changeOrgBz(`${i.fbzid}`); }, }; /*if(i.fbzid==me.userInfo.fbzid){ _pushData.chooseIcon={ title:me.$t("hivuiMain_header_bzchooseIcon_title"), iconClass:"el-icon-star-on", }; }else{ _pushData.hoverBtn={ title:me.$t("hivuiMain_header_bzhoverbtn_title"), iconClass:"iconfont icon-set", handler:function(){ console.log(123456789); } } }*/ item.children.push(_pushData); } } break; } if(_rData[1]){ return item; } }); } } return _userInfo||[]; }, sysProjectManage(){ let cfg = this.$store.state.app.config||{}; let item = cfg.sysProjectMange||{},flag=false; this.$store.state.app.powerList.forEach(p=>{ if(p.resUrl.indexOf(item.uri)>-1){ flag = true; return true; } }); if(flag){ return cfg.sysProjectMange; }else{ return null; } }, langList(){ let cfg = this.$store.state.app.config||{}; if(!cfg.showChangeLangBtn){ return; } let menus = cfg.langList||[]; return menus; }, sysFuncMenus(){ let cfg = this.$store.state.app.config||{}; let menus = sortMapTurnArr(cfg.sysFuncMenus)||[]; return menus; }, logoOpt(){ let cfg = this.$store.state.app.config||{}; return (this.layout=="level"&&cfg.sysLogoHorizon?cfg.sysLogoHorizon:cfg.sysLogo)||{}; }, MlogoOpt(){ let cfg = this.$store.state.app.config||{}; return cfg.MsysLogo||{}; }, layout(){ return window.localStorage.getItem('layout'); }, navsLatelyUse(){ return this.$store.getters.navsLatelyUse; }, token(){ return this.$store.getters.token; }, userInfo(){ return this.$store.state.user.userInfo; }, bzList(){ return this.$store.state.user.bzList; }, }, watch:{ searchWord(newVal,oldVal){ this.seldIndex=0; this.doSearch(newVal); } }, mounted(){ let me=this; document.addEventListener('click',me.hideSeachResult); me.$store.dispatch("app/getSysConfig"); me.sysFuncMenus.filter(item=>{ if(item.type=="withNumTips"&&item.numFunc){ function __intervalFunc(){ item.numFunc().then(res=>{ me.msgCount = res.num; // me.$set(item,"tipNum",res.num); //渲染报错?? if(res.num&&!item.hideNotific){ window.SysPage.notificationFunc(me.$t("hivuiMain_header_notification_title"),item.messageText(res),()=>{ me.handleFuncMenus(item); }); } }).catch(err=>{ clearInterval(me.numTipTimer); }); } clearInterval(me.numTipTimer); me.numTipTimer=setInterval(__intervalFunc,item.numIntervalTime||1000*30); __intervalFunc(); } }); me.allFuncBtnObj=(me.layout == 'level')&&me.showAllFuncBtn&&me.$refs.allFuncBtn.getBoundingClientRect(); }, beforeDestroy(){ document.removeEventListener('click',this.hideSeachResult) }, methods:{ openDesign(){ this.$refs['cmp-dd'].show(); }, doSearch(cnKey){ if(cnKey==""){ this.hideSeachResult(); return; } this.showSeachResult(); let list = [], records = this.$store.getters.menusList, hideMenuItemList = this.$store.getters.hideMenuItemList; let py = pinyin.getCamelChars(cnKey).toLocaleLowerCase(); console.log('records', records) //let py = Scp.String.getPinyin(cnKey).toLocaleLowerCase(); let re = new RegExp("^[a-zA-Z]+$"); for(let i=0,l=records.length;i<l;i++){ let item = records[i]; if(list.length>10){ break; } if(item.name && !(!item.isShow || hideMenuItemList.indexOf(item.parentId)!=-1)){ if(re.test(cnKey)){ let y = pinyin.getCamelChars(item.name).toLocaleLowerCase(); //let y = Scp.String.getPinyin(item.name).toLocaleLowerCase(); if(y.indexOf(py)>-1 && item.type!='dir'){ list.push(item); } }else{ if(item.name.indexOf(cnKey)>-1 && item.type!='dir' ){ list.push(item); continue; } } } } this.$set(this,'searchList',list); }, openFunc(item){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } // this.addTab(item.resUrl,item.name,item.resId) this.addTab(item);//inject 提供的方法只能 传一个参数 }, handleSearchBoxClick(){ this.doSearch(this.searchWord); this.$refs['dom-seachTxt'].focus(); }, handleSeachKeyUp(evt){ if(evt.keyCode==40){//ArrowDown if(this.seldIndex<this.searchList.length-1){ this.seldIndex++; }else{ this.seldIndex=0; } } if(evt.keyCode==38){//ArrowUp if(this.seldIndex==0){ this.seldIndex=this.searchList.length-1; }else{ this.seldIndex--; } } if(evt.keyCode==13){//enter let item = this.searchList[this.seldIndex]; if(item.type== "link"){ window.open(item.resUrl,item.name); return; } // this.addTab(item.resUrl,item.name,item.resId); this.addTab(item);//inject 提供的方法只能 传一个参数 this.searchWord = ""; this.seldIndex = 0; this.hideSeachResult(); } }, showSeachResult(){ this.searchMenusStyle.display ='block'; let s = this.$refs["dom-searchBox"]; let rect = s.getBoundingClientRect(); this.searchMenusStyle.left = rect.left+'px'; this.searchMenusStyle.top = rect.top + rect.height + 5 +'px'; this.searchMenusStyle.width = rect.width+'px'; this.searchMenusStyle.opacity = '1'; }, hideSeachResult(){ this.searchMenusStyle.display ='none'; }, handleChangeSys(item){ if(!item.url)return; if(item.target=="_blank"){ window.open(item.url) }else{ window.location.href=item.url; } }, handleShowSysList(){ this.sysListStyle.display ='block'; let s = this.$refs["dom-sysList"]; let rect = s.getBoundingClientRect(); this.sysListStyle.left = rect.left+'px'; this.sysListStyle.top = rect.top + rect.height +'px'; }, handleHideSysList(){ this.sysListStyle.display ='none'; }, handleFuncMenus(item,$event){ $event&&$event.stopPropagation(); if(item.type== "link"){ window.open(item.resUrl,item.name); return; } var _url=item.url; if(item.type== "widthToken"||item.type== "withToken"){ _url=item.url+"&access_token="+this.token; } if(item.url){ item.target=='tab'? this.addTab({ resUrl:_url, name:item.name, resId:item.id, openType:item.openType, }) : window.open(_url); return }else{ item.handler&&item.handler(); } if(item.children&&item.children.length){ this.menuItems = item.children; this.$refs['cmp-funcMenu'].open($event) } }, async handleLogout(){ await this.$store.dispatch("user/logout").then(()=>{ //removeToken(); window.sessionStorage.removeItem("bzid"); if(window.customSysCofig.logoutCallback){ window.customSysCofig.logoutCallback(); }else{ if(window.HIVUI_SETTING.isSingleLogin&&window.HIVUI_SETTING.singleLogoutUrl){ location=window.HIVUI_SETTING.singleLogoutUrl; }else{ location=window.HIVUI_SETTING.loginUrl; } } }); }, handleShowLatelyUse(){ this.$store.dispatch('app/getLatelyUse')//最近使用 let s = this.$refs["dom-latelyUse"]; let rect = s.getBoundingClientRect(); this.latelyUseStyle.display ='block'; this.latelyUseStyle.left = rect.left+'px'; this.latelyUseStyle.top = rect.top + rect.height +'px'; this.latelyUseStyle.opacity = '1'; }, handleHideLatelyUse(){ this.latelyUseStyle.display ='none'; }, handleOpenLatelyFunc(item){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } this.addTab({ resUrl:item.resUrl, name:item.name, openType:item.openType, });//inject 提供的方法只能 传一个参数 }, hideTitle(name){ this.$emit('hideTitle', name); }, //切岗 __changeOrgBz(bzid){ changeBz({ bzid:bzid }).then(res=>{ window.location.reload(); }); }, modifyPw(){ this.$store.dispatch("user/showPwDialog",true); }, // 个人中心 personalCenter(){ top.window.SysPage.newPage(this.$t("hivuiMain_app_personal_Center"), '#personalCenter'); }, modifyUserInfo(){ }, //全部功能弹窗 allFuncTrigger(){ let me=this; me.isShowAllFuncMenu=me.isShowAllFuncMenu?false:true; if(me.isShowAllFuncMenu){ me.$refs.allFuncMenu.showBox(); }else{ me.$refs.allFuncMenu.hideBox(); } }, allFuncTriggerOpen(){ let me=this; me.$refs.allFuncMenu.showBox(); }, allFuncTriggerClose(){ let me=this; me.$refs.allFuncMenu.hideBox(); }, logoClickHanlder(opt){ if(opt&&opt.clickHandler){ opt.clickHandler(); } }, } } </script> <style lang="less" scoped> .pl-header{ z-index: 99; } </style>
<template> <div class="pl-header " :data-layout="layout"> <ul class="ltArea"> <li v-if="layout=='level'" class="logoStyle"> <div class="pl-logo"> <div v-if="hasTitle" @click="logoClickHanlder(logoOpt)"> <img :src="def_sy_logo_horizon" :width="logoWidth" v-if="!logoOpt.src"> <img :src="logoOpt.src" :width="logoOpt.width?(logoOpt.width+'px'):(!logoOpt.height?logoWidth:null)" :height="logoOpt.height&&(logoOpt.height+'px')" :title="logoOpt.title" v-if="logoOpt.src"> </div> <div v-else @click="logoClickHanlder(MlogoOpt)"> <img :src="def_sy_minLogo" v-if="!MlogoOpt.src"> <img :src="MlogoOpt.src" :width="MlogoOpt.width?(MlogoOpt.width+'px'):(!MlogoOpt.height?logoWidth:null)" :height="MlogoOpt.height&&(MlogoOpt.height+'px')" :title="MlogoOpt.title" v-if="MlogoOpt.src"> </div> </div> </li> <li v-else class="logoStyle"> <div class="pl-logo" @click="logoClickHanlder(logoOpt)"> <img :src="def_sy_logo" :width="logoWidth" v-if="!logoOpt.src"> <img :src="logoOpt.src" :width="logoOpt.width?(logoOpt.width+'px'):(!logoOpt.height?logoWidth:null)" :height="logoOpt.height&&(logoOpt.height+'px')" :title="logoOpt.title" v-if="logoOpt.src"> </div> </li> <li v-if="sysList.length"> <div class="sysTrigger" ref='dom-sysList' @mouseover="handleShowSysList" @mouseout="handleHideSysList"> <span>{{$t('hivuiMain_projectManage')}}</span> <i class="iconfont icon-change"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" @mouseenter="handleShowSysList" @mouseleave="handleHideSysList" :style="sysListStyle" v-add2Body> <li class="pl-menus-item" v-for="item,index in sysList" @click="handleChangeSys(item)"> <a class="title"><span class="txt">{{item.title}}</span></a> </li> </ul> </li> <li v-if="layout == 'level'&&!hideHistoryFuncList" > <div class="sysTrigger" ref="dom-latelyUse" :title='$t("hivuiMain_recentlyUsed")' @mouseenter="handleShowLatelyUse" @mouseleave="handleHideLatelyUse"> <i class="icon iconfont icon-time"></i> <span class="title">{{$t('hivuiMain_recentlyUsed')}}</span> <i class="icon iconfont icon-arrow-down"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" @mouseenter="handleShowLatelyUse" @mouseleave="handleHideLatelyUse" :style="latelyUseStyle" v-add2Body> <li class="pl-menus-item" v-for="item,index in navsLatelyUse" @click="handleOpenLatelyFunc(item)"> <a class="title"><span class="txt">{{item.name}}</span></a> </li> <li v-show="navsLatelyUse.length==0" class="pl-menus-tips"> {{$t('hivuiMain_nodata')}} </li> </ul> </li> <li v-if="layout == 'level'&&showAllFuncBtn" > <div class="sysTrigger"> <span ref="allFuncBtn" class="title" @mouseenter="allFuncTriggerOpen" @mouseleave="allFuncTriggerClose">{{$t('hivuiMain_allFunction')}}</span> <i class="icon iconfont icon-arrow-down"></i> <allFuncMenu ref="allFuncMenu" :triggerObj="allFuncBtnObj" v-add2Body></allFuncMenu> </div> </li> </ul> <ul class="rtArea"> <li> <div class="pl-search" ref="dom-searchBox" > <input ref="dom-seachTxt" class="pl-search-text" type="text" :placeholder="$t('hivuiMain_searchKey')" v-model.trim="searchWord" @keyup="handleSeachKeyUp" /> <i class="iconfont icon-search"></i> </div> <ul class="pl-menus pl-menus-sub pl-menus-pop" :style="searchMenusStyle" v-add2Body> <li :class="['pl-menus-item',seldIndex==index?'pl-menus-itemSeld':'']" v-for="item,index in searchList" style="width:100%" @click="openFunc(item)"> <a class="title"><span class="txt" v-html="item.html||item.name"></span></a> </li> <li v-show="searchList.length==0&&searchWord.length>0" class="pl-menus-tips"> {{$t('hivuiMain_nodata')}} </li> </ul> </li> <li v-if="sysProjectManage"> <a :href="sysProjectManage.url" target='_blank' class="item" :title="sysProjectManage.name"> <i class="iconfont" :class="sysProjectManage.iconClass"></i> <span class="title">{{sysProjectManage.name}}</span> </a> </li> <template v-for="item in sysFuncMenus"> <li v-if="item.type!='split'"> <template v-if="item.type=='withNumTips'"> <div class="item" @click.prevent="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <span class="pl-head-tipsNum" :hidden="!(msgCount!=0)">{{msgCount}}</span> <!-- <span class="pl-head-tipsNum" :hidden="!(item.tipNum&&item.tipNum!=0)">{{item.tipNum}}</span> --> </div> </template> <template v-else> <template v-if="item.children&&item.children.length"> <div class="item" @mouseenter="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <i class="iconfont icon-arrow-down" v-if="item.children"></i> </div> </template> <template v-if="!item.children||item.children&&item.children.length==0"> <div class="item" @click.prevent="handleFuncMenus(item,$event)"> <div class="tip"> <i class="iconfont" :class="item.iconClass"></i> </div> <span class="title" v-html="item.html||item.name"></span> <i class="iconfont icon-arrow-down" v-if="item.children"></i> </div> </template> </template> </li> <li v-if="item.type=='split'"><div class="line"></div></li> </template> <!-- <li> <div class="item"> <div class="tip"> <i class="iconfont icon-user"></i> </div> <span class="title">{{this.$store.getters.userId}}/{{this.$store.getters.userName}}</span> <i class="iconfont icon-arrow-down"></i> </div> </li> <li><div class="line"></div></li> --> <!-- 语言切换 --> <li v-if="langList"> <template v-if="langList.children&&langList.children.length"> <div class="item" @mouseenter="handleFuncMenus(langList,$event)"> <div class="tip"> <i class="iconfont" :class="langList.iconClass"></i> </div> <span class="title" v-html="langList.html||langList.name"></span> <i class="iconfont icon-arrow-down" v-if="langList.children"></i> </div> </template> </li> <li v-if="langList"><div class="line"></div></li> <!-- 用户信息 --> <li> <template v-if="sysUserInfo.children&&sysUserInfo.children.length"> <div class="item" @mouseenter="handleFuncMenus(sysUserInfo,$event)"> <div class="tip"> <i class="iconfont" :class="sysUserInfo.iconClass"></i> </div> <span class="title" v-html="sysUserInfo.html||sysUserInfo.name"></span> <i class="iconfont icon-arrow-down" v-if="sysUserInfo.children"></i> </div> </template> </li> <li><div class="line"></div></li> <li v-if="hasSetting"> <div class="item" :title="$t('hivuiMain_customWorkbench')"> <a href="#design" target='_blank'><i class="iconfont icon-set-fill"></i></a> </div> </li> <li> <div class="item" :title="$t('hivuiMain_logout')"> <a @click="handleLogout"><i class="iconfont icon-tuichu"></i></a> </div> </li> </ul> <vueContextMenu ref="cmp-funcMenu" :menu-items="menuItems" field="name"></vueContextMenu> <modifyPw></modifyPw> </div> </template> <script> import pinyin from 'js-pinyin';//ie 下有问题 编译不过 import vueContextMenu from "@main/components/contextMenu"; import modifyPw from "@main/views/layout/components/modifyPw"; import allFuncMenu from './allFuncMenu' import {changeBz} from "@main/api/user"; import { removeToken } from '@main/utils/auth' import { sortMapTurnArr } from '@main/utils/index' import def_sy_loading from "@main/assets/logo_max.png" import def_sy_minLogo from "@main/assets/logo_min.png" import def_sy_logo from "@main/assets/logo.png" import def_sy_logo_horizon from "@main/assets/logo_horizon.png" export default { components:{ vueContextMenu, modifyPw, allFuncMenu, }, inject:['addTab','showTab','hideTab'], props:{ hasTitle:{ type: Boolean, }, logoWidth:{ type: String, } }, data(){ return { menuItems:[], searchWord:"", searchList:[], seldIndex:0, menuShow:false, searchMenusStyle:{ display:'none', left:0, top:0, width:0, // maxHeight:'50%', // overflow:'auto' }, sysListStyle:{ display:'none', left:0, top:0, }, latelyUseStyle:{ display:'none', left:0, top:0, maxHeight:'50%', overflow:'auto' }, def_sy_minLogo:def_sy_minLogo, def_sy_logo:def_sy_logo, def_sy_logo_horizon:def_sy_logo_horizon, numTipTimer:null, showAllFuncBtn:window.customSysCofig.isShowAllFunc===false?false:true, hideHistoryFuncList:window.customSysCofig.hideHistoryFuncList||false, isShowAllFuncMenu:false, allFuncBtnObj:{}, msgCount:0 } }, computed:{ hasSetting(){ let cfg = this.$store.state.app.config||{}; if(cfg.hideSettingBtn){ return false; } let _arr=sortMapTurnArr(cfg.sysSetTabs); return _arr&&_arr.length; }, sysList(){ let cfg = this.$store.state.app.config||{}; return cfg.sysList||[]; }, sysUserInfo(){ let me=this; let cfg = this.$store.state.app.config||{}; function replaceData(str){ if(!str)return ['',false]; var _arr=str.match(/\${(\S*?)}/g); var nullNum=0; if(_arr&&_arr.length>0){ for(let i of _arr){ var _data=me.userInfo[i.match(/\${(\S*)}/)[1]]; if(typeof(_data)!="undefined"){ str=str.replace(i,_data); }else{ str=str.replace(i,me.$t('hivuiMain_header_null')); nullNum++; } } return [str,nullNum==_arr.length?false:true]; } return [str,true]; } //多岗信息文字模板format function orgBzTplFormat(str,item){ let fieldArr=str.match(/(?<=\${).*?(?=})/g); fieldArr.forEach((_i)=>{ if(typeof(item[_i])!="undefined"){ str=str.replaceAll("${"+_i+"}",item[_i]); } }); return str; } let _userInfo=cfg.userInfo; if(_userInfo){ _userInfo.name=replaceData(_userInfo.name)[0]; if(_userInfo.children&&_userInfo.children.length>0){ _userInfo.children=_userInfo.children.filter((item)=>{ let _rData=replaceData(item.name); item.name=_rData[0]; switch(item.type){ case "modifyUserInfo": item.handler=me.modifyUserInfo; break; case "modifyPw": item.handler=me.modifyPw; break; case "personalCenter": item.handler=me.personalCenter; break; case "orgBz": if(Array.isArray(me.bzList)&&me.bzList.length>1){ item.children=[]; for(let i of me.bzList){ let _pushData={ iconClass:'icon-user', name:cfg.orgBzTpl?orgBzTplFormat(cfg.orgBzTpl,i):`${i.fbzname}/${i.fbzid}`, handler:function(){ me.__changeOrgBz(`${i.fbzid}`); }, }; /*if(i.fbzid==me.userInfo.fbzid){ _pushData.chooseIcon={ title:me.$t("hivuiMain_header_bzchooseIcon_title"), iconClass:"el-icon-star-on", }; }else{ _pushData.hoverBtn={ title:me.$t("hivuiMain_header_bzhoverbtn_title"), iconClass:"iconfont icon-set", handler:function(){ console.log(123456789); } } }*/ item.children.push(_pushData); } } break; } if(_rData[1]){ return item; } }); } } return _userInfo||[]; }, sysProjectManage(){ let cfg = this.$store.state.app.config||{}; let item = cfg.sysProjectMange||{},flag=false; this.$store.state.app.powerList.forEach(p=>{ if(p.resUrl.indexOf(item.uri)>-1){ flag = true; return true; } }); if(flag){ return cfg.sysProjectMange; }else{ return null; } }, langList(){ let cfg = this.$store.state.app.config||{}; if(!cfg.showChangeLangBtn){ return; } let menus = cfg.langList||[]; return menus; }, sysFuncMenus(){ let cfg = this.$store.state.app.config||{}; let menus = sortMapTurnArr(cfg.sysFuncMenus)||[]; return menus; }, logoOpt(){ let cfg = this.$store.state.app.config||{}; return (this.layout=="level"&&cfg.sysLogoHorizon?cfg.sysLogoHorizon:cfg.sysLogo)||{}; }, MlogoOpt(){ let cfg = this.$store.state.app.config||{}; return cfg.MsysLogo||{}; }, layout(){ return window.localStorage.getItem('layout'); }, navsLatelyUse(){ return this.$store.getters.navsLatelyUse; }, token(){ return this.$store.getters.token; }, userInfo(){ return this.$store.state.user.userInfo; }, bzList(){ return this.$store.state.user.bzList; }, }, watch:{ searchWord(newVal,oldVal){ this.seldIndex=0; this.doSearch(newVal); } }, mounted(){ let me=this; document.addEventListener('click',me.hideSeachResult); me.$store.dispatch("app/getSysConfig"); me.sysFuncMenus.filter(item=>{ if(item.type=="withNumTips"&&item.numFunc){ function __intervalFunc(){ item.numFunc().then(res=>{ me.msgCount = res.num; // me.$set(item,"tipNum",res.num); //渲染报错?? if(res.num&&!item.hideNotific){ window.SysPage.notificationFunc(me.$t("hivuiMain_header_notification_title"),item.messageText(res),()=>{ me.handleFuncMenus(item); }); } }).catch(err=>{ clearInterval(me.numTipTimer); }); } clearInterval(me.numTipTimer); me.numTipTimer=setInterval(__intervalFunc,item.numIntervalTime||1000*30); __intervalFunc(); } }); me.allFuncBtnObj=(me.layout == 'level')&&me.showAllFuncBtn&&me.$refs.allFuncBtn.getBoundingClientRect(); }, beforeDestroy(){ document.removeEventListener('click',this.hideSeachResult) }, methods:{ openDesign(){ this.$refs['cmp-dd'].show(); }, doSearch(cnKey){ if(cnKey==""){ this.hideSeachResult(); return; } this.showSeachResult(); let list = [], records = this.$store.getters.menusList, hideMenuItemList = this.$store.getters.hideMenuItemList; let py = pinyin.getCamelChars(cnKey).toLocaleLowerCase(); console.log('records', records) //let py = Scp.String.getPinyin(cnKey).toLocaleLowerCase(); let re = new RegExp("^[a-zA-Z]+$"); for(let i=0,l=records.length;i<l;i++){ let item = records[i]; if(list.length>10){ break; } if(item.name && hideMenuItemList.indexOf(item.parentId)==-1){ if(re.test(cnKey)){ let y = pinyin.getCamelChars(item.name).toLocaleLowerCase(); //let y = Scp.String.getPinyin(item.name).toLocaleLowerCase(); if(y.indexOf(py)>-1 && item.type!='dir'){ list.push(item); } }else{ if(item.name.indexOf(cnKey)>-1 && item.type!='dir' ){ list.push(item); continue; } } } } this.$set(this,'searchList',list); }, openFunc(item){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } // this.addTab(item.resUrl,item.name,item.resId) this.addTab(item);//inject 提供的方法只能 传一个参数 }, handleSearchBoxClick(){ this.doSearch(this.searchWord); this.$refs['dom-seachTxt'].focus(); }, handleSeachKeyUp(evt){ if(evt.keyCode==40){//ArrowDown if(this.seldIndex<this.searchList.length-1){ this.seldIndex++; }else{ this.seldIndex=0; } } if(evt.keyCode==38){//ArrowUp if(this.seldIndex==0){ this.seldIndex=this.searchList.length-1; }else{ this.seldIndex--; } } if(evt.keyCode==13){//enter let item = this.searchList[this.seldIndex]; if(item.type== "link"){ window.open(item.resUrl,item.name); return; } // this.addTab(item.resUrl,item.name,item.resId); this.addTab(item);//inject 提供的方法只能 传一个参数 this.searchWord = ""; this.seldIndex = 0; this.hideSeachResult(); } }, showSeachResult(){ this.searchMenusStyle.display ='block'; let s = this.$refs["dom-searchBox"]; let rect = s.getBoundingClientRect(); this.searchMenusStyle.left = rect.left+'px'; this.searchMenusStyle.top = rect.top + rect.height + 5 +'px'; this.searchMenusStyle.width = rect.width+'px'; this.searchMenusStyle.opacity = '1'; }, hideSeachResult(){ this.searchMenusStyle.display ='none'; }, handleChangeSys(item){ if(!item.url)return; if(item.target=="_blank"){ window.open(item.url) }else{ window.location.href=item.url; } }, handleShowSysList(){ this.sysListStyle.display ='block'; let s = this.$refs["dom-sysList"]; let rect = s.getBoundingClientRect(); this.sysListStyle.left = rect.left+'px'; this.sysListStyle.top = rect.top + rect.height +'px'; }, handleHideSysList(){ this.sysListStyle.display ='none'; }, handleFuncMenus(item,$event){ $event&&$event.stopPropagation(); if(item.type== "link"){ window.open(item.resUrl,item.name); return; } var _url=item.url; if(item.type== "widthToken"||item.type== "withToken"){ _url=item.url+"&access_token="+this.token; } if(item.url){ item.target=='tab'? this.addTab({ resUrl:_url, name:item.name, resId:item.id, openType:item.openType, }) : window.open(_url); return }else{ item.handler&&item.handler(); } if(item.children&&item.children.length){ this.menuItems = item.children; this.$refs['cmp-funcMenu'].open($event) } }, async handleLogout(){ await this.$store.dispatch("user/logout").then(()=>{ //removeToken(); window.sessionStorage.removeItem("bzid"); if(window.customSysCofig.logoutCallback){ window.customSysCofig.logoutCallback(); }else{ if(window.HIVUI_SETTING.isSingleLogin&&window.HIVUI_SETTING.singleLogoutUrl){ location=window.HIVUI_SETTING.singleLogoutUrl; }else{ location=window.HIVUI_SETTING.loginUrl; } } }); }, handleShowLatelyUse(){ this.$store.dispatch('app/getLatelyUse')//最近使用 let s = this.$refs["dom-latelyUse"]; let rect = s.getBoundingClientRect(); this.latelyUseStyle.display ='block'; this.latelyUseStyle.left = rect.left+'px'; this.latelyUseStyle.top = rect.top + rect.height +'px'; this.latelyUseStyle.opacity = '1'; }, handleHideLatelyUse(){ this.latelyUseStyle.display ='none'; }, handleOpenLatelyFunc(item){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } this.addTab({ resUrl:item.resUrl, name:item.name, openType:item.openType, });//inject 提供的方法只能 传一个参数 }, hideTitle(name){ this.$emit('hideTitle', name); }, //切岗 __changeOrgBz(bzid){ changeBz({ bzid:bzid }).then(res=>{ window.location.reload(); }); }, modifyPw(){ this.$store.dispatch("user/showPwDialog",true); }, // 个人中心 personalCenter(){ top.window.SysPage.newPage(this.$t("hivuiMain_app_personal_Center"), '#personalCenter'); }, modifyUserInfo(){ }, //全部功能弹窗 allFuncTrigger(){ let me=this; me.isShowAllFuncMenu=me.isShowAllFuncMenu?false:true; if(me.isShowAllFuncMenu){ me.$refs.allFuncMenu.showBox(); }else{ me.$refs.allFuncMenu.hideBox(); } }, allFuncTriggerOpen(){ let me=this; me.$refs.allFuncMenu.showBox(); }, allFuncTriggerClose(){ let me=this; me.$refs.allFuncMenu.hideBox(); }, logoClickHanlder(opt){ if(opt&&opt.clickHandler){ opt.clickHandler(); } }, } } </script> <style lang="less" scoped> .pl-header{ z-index: 99; } </style>
Ignore Space
Show notes
View
project/hivuiMain/views/layout/components/allFuncMenu/index.vue
<template> <div class="boxMain" ref="allFuncMenu" @mouseenter="showBox" @mouseleave="hideBox" :style="allFuncMenuStyle"> <div class="searchBox"> <input type="text" :placeholder="$t('hivuiMain_allfuncmenu_text')" v-model.trim="searchWord" @keyup="handleSeachKeyUp" /> <i class="iconfont icon-search"></i> </div> <div ref="listBox" class="listBox" :style="listBoxStyle"> <ul class="level1List" v-if="searchWord==''"> <template v-for=" (item1,index) in menus"> <li :key="'level1-'+index" :class="item1.type!='dir'&&!item1.children&&'funcBtn'" :title="item1.type!='dir'?item1.name:''" @click="funcClick(item1)" v-if="item1.isShow"> <itemIcon :item="item1"></itemIcon> <span>{{item1.name}}</span> <ul class="level2List" v-if="item1.children && item1.children.length"> <template v-for=" (item2,index) in item1.children"> <li :key="'level2-'+index" :class="item2.type!='dir'&&!item2.children&&'funcBtn'" :title="item2.type!='dir'?item2.name:''" @click="funcClick(item2)" v-if="item2.isShow"> <itemIcon :item="item2"></itemIcon> <span>{{item2.name}}</span> <!-- <i v-if="item2.type=='dir'" class="el-icon-caret-bottom"></i> --> <ul class="level3List" v-if="item2.children && item2.children.length"> <template v-for=" (item3,index) in item2.children"> <menus :class="'funcBtn level3Dir'" :key="'level3-'+index" :level="0" :parent="allFuncMenu" :menuitem="item3" v-if="item3.isShow&&item3.children&&item3.children.length"></menus> <li v-else-if="item3.isShow" :class="'funcBtn'" :key="'level3-'+index" :title="item3.type!='dir'?item3.name:''" @click="funcClick(item3)" > <itemIcon :item="item3"></itemIcon> <span>{{item3.name}}</span> </li> </template> </ul> </li> </template> </ul> </li> </template> <li v-show="menus.length==0"> {{$t("hivuiMain_nodata")}} </li> </ul> <!-- 搜索结果列表 --> <ul class="searchResultList" v-else> <li v-for=" (searchItem,index) in searchList" :key="'search-'+index" :data-index="index" :class="seldIndex==index&&'itemSeld'" :title="searchItem.name" @click="funcClick(searchItem)"> <itemIcon :item="searchItem"></itemIcon> <span>{{searchItem.name}}</span> </li> <li v-show="searchList.length==0"> {{$t("hivuiMain_nodata")}} </li> </ul> </div> </div> </template> <script> import pinyin from 'js-pinyin'; import itemIcon from './itemIcon'; import menus from './menus'; import cloneDeep from 'lodash/cloneDeep'; export default { inject:['addTab'], provide(){ let me=this; return { showAllFuncBox(){ me.showBox(); }, hideAllFuncBox(){ me.hideBox(); }, } }, props:{ triggerObj:{ type:Object, } }, components:{ itemIcon,menus }, data(){ return { searchWord:"", searchList:[], seldIndex:0, allFuncMenuStyle:"", listBoxStyle:"", loading:false, loadingTime:200, triggerTimer:null, }; }, computed:{ menus(){ //调整排序,功能页面排前面 function sort(list){ let dirList=list.filter(item=>{ return item.type=="dir"; }); let funcList=list.filter(item=>{ return item.type!="dir"; }); list=funcList.concat(dirList); for(let item of list){ if(item.type=='dir'){ if(item.children&&item.children.length>0){ item.children=sort(item.children); } } } return list; } return sort(cloneDeep(this.$store.getters.menus)); }, }, watch:{ searchWord(newVal,oldVal){ this.seldIndex=0; this.doSearch(newVal); } }, mounted(){ let me=this; }, methods:{ //获取搜索列表数据 doSearch(cnKey){ let me=this; let list = [], records = me.$store.getters.menusList, hideMenuItemList = me.$store.getters.hideMenuItemList; let py = pinyin.getCamelChars(cnKey).toLocaleLowerCase(); let re = new RegExp("^[a-zA-Z]+$"); for(let i=0,l=records.length;i<l;i++){ let item = records[i]; if(!(!item.isShow || hideMenuItemList.indexOf(item.parentId)!=-1)){ if(re.test(cnKey)){ let y = pinyin.getCamelChars(item.name).toLocaleLowerCase(); if(y.indexOf(py)>-1 && item.type!='dir'){ list.push(item); } }else{ if(item.name.indexOf(cnKey)>-1 && item.type!='dir'){ list.push(item); } } } } me.$set(me,'searchList',list); me.$nextTick(()=>{ me.countHeight(); me.$refs.listBox.scrollTo({ top:0, }); }); }, //搜索时方向键及回车事件 handleSeachKeyUp(evt){ let colNum=4; let me=this; if(evt.keyCode==37){//左方向 if(me.seldIndex==0){ me.seldIndex=me.searchList.length-1; }else{ me.seldIndex--; } me.scrollSearchList("up"); } if(evt.keyCode==38){//上方向 if(me.seldIndex-colNum<0){ let re1=me.searchList.length%colNum; let re2=(me.seldIndex+1)%colNum; let count=re2>re1 ? (colNum-re2+re1) : (re1-re2); me.seldIndex=((me.searchList.length-count>0) ? me.searchList.length-count : me.searchList.length) - 1; }else{ me.seldIndex-=colNum; } me.scrollSearchList("up"); } if(evt.keyCode==39){//右方向 if(me.seldIndex<me.searchList.length-1){ me.seldIndex++; }else{ me.seldIndex=0; } me.scrollSearchList("down"); } if(evt.keyCode==40){//下方向 if(me.seldIndex+colNum>me.searchList.length-1){ me.seldIndex=(me.seldIndex+colNum)%colNum; }else{ me.seldIndex+=colNum; } me.scrollSearchList("down"); } if(evt.keyCode==13){//回车 let item = me.searchList[me.seldIndex]; if(item.type== "link"){ window.open(item.resUrl,item.name); return; } me.addTab(item);//inject 提供的方法只能 传一个参数 me.searchWord = ""; me.seldIndex = 0; me.$refs.listBox.scrollTo({ top:0, }); me.hideBox(); } }, //滚动搜索菜单列表 scrollSearchList(type){ let me=this; let _scrollTop=0; let listDom=me.$refs.listBox; let listDomObj=listDom.getBoundingClientRect(); let currItemDom=listDom.querySelector("[data-index='"+me.seldIndex+"']"); let currItemDomObj=currItemDom.getBoundingClientRect(); //在可视范围内不滚动 if(currItemDomObj.top+currItemDomObj.height<(listDomObj.height+listDomObj.top) && currItemDomObj.top>listDomObj.top){ return; } if(type=="up"){ _scrollTop=currItemDomObj.top-listDomObj.top+listDom.scrollTop; }else if(type=="down"){ _scrollTop=currItemDomObj.top+currItemDomObj.height-listDomObj.top-listDomObj.height+listDom.scrollTop; } me.$refs.listBox.scrollTo({ top:_scrollTop, behavior:"smooth", }); }, //菜单功能项点击事件 funcClick(item){ if(item.type!="dir"&&item.resUrl){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } this.addTab(item);//inject 提供的方法只能 传一个参数 this.hideBox(); } }, //显隐共用样式(设置定位) commonFunc(){ let me=this; let btnOffset=me.triggerObj; let ww=window.outerWidth; let boxleft=btnOffset.left+me.$refs.allFuncMenu.offsetWidth; me.isShowAllFuncMenu=me.isShowAllFuncMenu?false:true; me.allFuncMenuStyle=`top:${btnOffset.top+btnOffset.height}px;`; if(boxleft>ww){ me.allFuncMenuStyle+=`right:10px;`; }else{ me.allFuncMenuStyle+=`left:${btnOffset.left}px;`; } }, //计算高度 countHeight(){ let me=this; let wh=window.outerHeight; let listContentH=me.$refs.listBox.children[0].scrollHeight+50; let boxheight=listContentH > (wh/2) ? wh/2 : listContentH; me.allFuncMenuStyle+=`opacity:1;z-index:99;height:${boxheight+2}px;`;//2:弹窗边框 me.listBoxStyle=`height:${boxheight-50}px;`;//50:搜索框高度 }, //显示弹窗 showBox(){ let me=this; me.commonFunc(); me.countHeight(); me.loading=true; clearTimeout(me.triggerTimer); me.triggerTimer=setTimeout(()=>{ me.loading=false; },me.loadingTime); }, //隐藏弹窗 hideBox(){ let me=this; me.commonFunc(); //me.loading=true; me.allFuncMenuStyle+=`z-index:99;`; setTimeout(()=>{ if(!me.loading){ me.allFuncMenuStyle=''; me.loading=false; } },me.loadingTime); }, } } </script> <style lang="less" scoped> .boxMain{ position:absolute; top:-9999px; z-index:-1; opacity: 0; transition-duration: 0.2s; transition-property: opacity,height; width: 800px; height:0; background-color: #fff; border:1px solid #ddd; box-shadow: 0 2px 10px 0 #ddd; padding:50px 0px 0; box-sizing: border-box; overflow: auto; *{ box-sizing: border-box; } ul,li{ padding: 0; margin:0; list-style: none; } ul{ display: flex; flex-wrap: wrap; width:100%; } li{ flex:0 0 100%; color:#333; span{ overflow: hidden; text-overflow: ellipsis; } } &.show{ z-index:99; opacity: 1; } li.funcBtn{ display: flex; align-items: center; flex:0 0 25%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right:20px; color:#888; &:hover>span{ color:#06c; cursor: pointer; } } .searchBox{ position: absolute; top:0; left:0; right:0; margin:auto; width: calc(100% - 60px); background-color: #fff; input{ border:none; border-bottom:1px solid #ddd; padding:0 10px 0 40px; line-height: 48px; width: 100%; outline: none; &::placeholder{ color:#ccc; } } i{ position: absolute; top:0; bottom:0; left:10px; margin:auto; width:20px; height:20px; line-height:20px; text-align: center; font-size: 20px; font-weight: bold; color:#ccc; } } .listBox{ overflow: auto; padding:0 30px; } .level1List{ margin-bottom:30px; padding: 10px; &>li{ line-height: 36px; font-size: 18px; font-weight: bold; } } .level2List{ padding: 10px; &>li{ line-height: 32px; font-size: 14px; font-weight: bold; &.funcBtn{ font-size: 13px; font-weight: normal; } } } .level3List{ padding:0px 0 10px; display:flex; flex-wrap: wrap; &>li{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 32px; font-size: 13px; &.funcBtn{ font-weight: normal; } } .level3Dir{ color:#333; } } .searchResultList{ width: 100%; display:flex; flex-wrap: wrap; padding-bottom:30px; li{ flex:0 0 25%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 32px; font-size: 14px; display: flex; align-items: center; cursor: pointer; &:hover{ color:#06c; } } .itemSeld{ color:#f00; } } } </style>
<template> <div class="boxMain" ref="allFuncMenu" @mouseenter="showBox" @mouseleave="hideBox" :style="allFuncMenuStyle"> <div class="searchBox"> <input type="text" :placeholder="$t('hivuiMain_allfuncmenu_text')" v-model.trim="searchWord" @keyup="handleSeachKeyUp" /> <i class="iconfont icon-search"></i> </div> <div ref="listBox" class="listBox" :style="listBoxStyle"> <ul class="level1List" v-if="searchWord==''"> <template v-for=" (item1,index) in menus"> <li :key="'level1-'+index" :class="item1.type!='dir'&&!item1.children&&'funcBtn'" :title="item1.type!='dir'?item1.name:''" @click="funcClick(item1)" v-if="item1.isShow"> <itemIcon :item="item1"></itemIcon> <span>{{item1.name}}</span> <ul class="level2List" v-if="item1.children && item1.children.length"> <template v-for=" (item2,index) in item1.children"> <li :key="'level2-'+index" :class="item2.type!='dir'&&!item2.children&&'funcBtn'" :title="item2.type!='dir'?item2.name:''" @click="funcClick(item2)" v-if="item2.isShow"> <itemIcon :item="item2"></itemIcon> <span>{{item2.name}}</span> <!-- <i v-if="item2.type=='dir'" class="el-icon-caret-bottom"></i> --> <ul class="level3List" v-if="item2.children && item2.children.length"> <template v-for=" (item3,index) in item2.children"> <menus :class="'funcBtn level3Dir'" :key="'level3-'+index" :level="0" :parent="allFuncMenu" :menuitem="item3" v-if="item3.isShow&&item3.children&&item3.children.length"></menus> <li v-else-if="item3.isShow" :class="'funcBtn'" :key="'level3-'+index" :title="item3.type!='dir'?item3.name:''" @click="funcClick(item3)" > <itemIcon :item="item3"></itemIcon> <span>{{item3.name}}</span> </li> </template> </ul> </li> </template> </ul> </li> </template> <li v-show="menus.length==0"> {{$t("hivuiMain_nodata")}} </li> </ul> <!-- 搜索结果列表 --> <ul class="searchResultList" v-else> <li v-for=" (searchItem,index) in searchList" :key="'search-'+index" :data-index="index" :class="seldIndex==index&&'itemSeld'" :title="searchItem.name" @click="funcClick(searchItem)"> <itemIcon :item="searchItem"></itemIcon> <span>{{searchItem.name}}</span> </li> <li v-show="searchList.length==0"> {{$t("hivuiMain_nodata")}} </li> </ul> </div> </div> </template> <script> import pinyin from 'js-pinyin'; import itemIcon from './itemIcon'; import menus from './menus'; import cloneDeep from 'lodash/cloneDeep'; export default { inject:['addTab'], provide(){ let me=this; return { showAllFuncBox(){ me.showBox(); }, hideAllFuncBox(){ me.hideBox(); }, } }, props:{ triggerObj:{ type:Object, } }, components:{ itemIcon,menus }, data(){ return { searchWord:"", searchList:[], seldIndex:0, allFuncMenuStyle:"", listBoxStyle:"", loading:false, loadingTime:200, triggerTimer:null, }; }, computed:{ menus(){ //调整排序,功能页面排前面 function sort(list){ let dirList=list.filter(item=>{ return item.type=="dir"; }); let funcList=list.filter(item=>{ return item.type!="dir"; }); list=funcList.concat(dirList); for(let item of list){ if(item.type=='dir'){ if(item.children&&item.children.length>0){ item.children=sort(item.children); } } } return list; } return sort(cloneDeep(this.$store.getters.menus)); }, }, watch:{ searchWord(newVal,oldVal){ this.seldIndex=0; this.doSearch(newVal); } }, mounted(){ let me=this; }, methods:{ //获取搜索列表数据 doSearch(cnKey){ let me=this; let list = [], records = me.$store.getters.menusList, hideMenuItemList = me.$store.getters.hideMenuItemList; let py = pinyin.getCamelChars(cnKey).toLocaleLowerCase(); let re = new RegExp("^[a-zA-Z]+$"); for(let i=0,l=records.length;i<l;i++){ let item = records[i]; if(hideMenuItemList.indexOf(item.parentId)==-1){ if(re.test(cnKey)){ let y = pinyin.getCamelChars(item.name).toLocaleLowerCase(); if(y.indexOf(py)>-1 && item.type!='dir'){ list.push(item); } }else{ if(item.name.indexOf(cnKey)>-1 && item.type!='dir'){ list.push(item); } } } } me.$set(me,'searchList',list); me.$nextTick(()=>{ me.countHeight(); me.$refs.listBox.scrollTo({ top:0, }); }); }, //搜索时方向键及回车事件 handleSeachKeyUp(evt){ let colNum=4; let me=this; if(evt.keyCode==37){//左方向 if(me.seldIndex==0){ me.seldIndex=me.searchList.length-1; }else{ me.seldIndex--; } me.scrollSearchList("up"); } if(evt.keyCode==38){//上方向 if(me.seldIndex-colNum<0){ let re1=me.searchList.length%colNum; let re2=(me.seldIndex+1)%colNum; let count=re2>re1 ? (colNum-re2+re1) : (re1-re2); me.seldIndex=((me.searchList.length-count>0) ? me.searchList.length-count : me.searchList.length) - 1; }else{ me.seldIndex-=colNum; } me.scrollSearchList("up"); } if(evt.keyCode==39){//右方向 if(me.seldIndex<me.searchList.length-1){ me.seldIndex++; }else{ me.seldIndex=0; } me.scrollSearchList("down"); } if(evt.keyCode==40){//下方向 if(me.seldIndex+colNum>me.searchList.length-1){ me.seldIndex=(me.seldIndex+colNum)%colNum; }else{ me.seldIndex+=colNum; } me.scrollSearchList("down"); } if(evt.keyCode==13){//回车 let item = me.searchList[me.seldIndex]; if(item.type== "link"){ window.open(item.resUrl,item.name); return; } me.addTab(item);//inject 提供的方法只能 传一个参数 me.searchWord = ""; me.seldIndex = 0; me.$refs.listBox.scrollTo({ top:0, }); me.hideBox(); } }, //滚动搜索菜单列表 scrollSearchList(type){ let me=this; let _scrollTop=0; let listDom=me.$refs.listBox; let listDomObj=listDom.getBoundingClientRect(); let currItemDom=listDom.querySelector("[data-index='"+me.seldIndex+"']"); let currItemDomObj=currItemDom.getBoundingClientRect(); //在可视范围内不滚动 if(currItemDomObj.top+currItemDomObj.height<(listDomObj.height+listDomObj.top) && currItemDomObj.top>listDomObj.top){ return; } if(type=="up"){ _scrollTop=currItemDomObj.top-listDomObj.top+listDom.scrollTop; }else if(type=="down"){ _scrollTop=currItemDomObj.top+currItemDomObj.height-listDomObj.top-listDomObj.height+listDom.scrollTop; } me.$refs.listBox.scrollTo({ top:_scrollTop, behavior:"smooth", }); }, //菜单功能项点击事件 funcClick(item){ if(item.type!="dir"&&item.resUrl){ if(item.type== "link"){ window.open(item.resUrl,item.name); return; } this.addTab(item);//inject 提供的方法只能 传一个参数 this.hideBox(); } }, //显隐共用样式(设置定位) commonFunc(){ let me=this; let btnOffset=me.triggerObj; let ww=window.outerWidth; let boxleft=btnOffset.left+me.$refs.allFuncMenu.offsetWidth; me.isShowAllFuncMenu=me.isShowAllFuncMenu?false:true; me.allFuncMenuStyle=`top:${btnOffset.top+btnOffset.height}px;`; if(boxleft>ww){ me.allFuncMenuStyle+=`right:10px;`; }else{ me.allFuncMenuStyle+=`left:${btnOffset.left}px;`; } }, //计算高度 countHeight(){ let me=this; let wh=window.outerHeight; let listContentH=me.$refs.listBox.children[0].scrollHeight+50; let boxheight=listContentH > (wh/2) ? wh/2 : listContentH; me.allFuncMenuStyle+=`opacity:1;z-index:99;height:${boxheight+2}px;`;//2:弹窗边框 me.listBoxStyle=`height:${boxheight-50}px;`;//50:搜索框高度 }, //显示弹窗 showBox(){ let me=this; me.commonFunc(); me.countHeight(); me.loading=true; clearTimeout(me.triggerTimer); me.triggerTimer=setTimeout(()=>{ me.loading=false; },me.loadingTime); }, //隐藏弹窗 hideBox(){ let me=this; me.commonFunc(); //me.loading=true; me.allFuncMenuStyle+=`z-index:99;`; setTimeout(()=>{ if(!me.loading){ me.allFuncMenuStyle=''; me.loading=false; } },me.loadingTime); }, } } </script> <style lang="less" scoped> .boxMain{ position:absolute; top:-9999px; z-index:-1; opacity: 0; transition-duration: 0.2s; transition-property: opacity,height; width: 800px; height:0; background-color: #fff; border:1px solid #ddd; box-shadow: 0 2px 10px 0 #ddd; padding:50px 0px 0; box-sizing: border-box; overflow: auto; *{ box-sizing: border-box; } ul,li{ padding: 0; margin:0; list-style: none; } ul{ display: flex; flex-wrap: wrap; width:100%; } li{ flex:0 0 100%; color:#333; span{ overflow: hidden; text-overflow: ellipsis; } } &.show{ z-index:99; opacity: 1; } li.funcBtn{ display: flex; align-items: center; flex:0 0 25%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right:20px; color:#888; &:hover>span{ color:#06c; cursor: pointer; } } .searchBox{ position: absolute; top:0; left:0; right:0; margin:auto; width: calc(100% - 60px); background-color: #fff; input{ border:none; border-bottom:1px solid #ddd; padding:0 10px 0 40px; line-height: 48px; width: 100%; outline: none; &::placeholder{ color:#ccc; } } i{ position: absolute; top:0; bottom:0; left:10px; margin:auto; width:20px; height:20px; line-height:20px; text-align: center; font-size: 20px; font-weight: bold; color:#ccc; } } .listBox{ overflow: auto; padding:0 30px; } .level1List{ margin-bottom:30px; padding: 10px; &>li{ line-height: 36px; font-size: 18px; font-weight: bold; } } .level2List{ padding: 10px; &>li{ line-height: 32px; font-size: 14px; font-weight: bold; &.funcBtn{ font-size: 13px; font-weight: normal; } } } .level3List{ padding:0px 0 10px; display:flex; flex-wrap: wrap; &>li{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 32px; font-size: 13px; &.funcBtn{ font-weight: normal; } } .level3Dir{ color:#333; } } .searchResultList{ width: 100%; display:flex; flex-wrap: wrap; padding-bottom:30px; li{ flex:0 0 25%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 32px; font-size: 14px; display: flex; align-items: center; cursor: pointer; &:hover{ color:#06c; } } .itemSeld{ color:#f00; } } } </style>
Show line notes below