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
@中文描述:菜单显示隐藏判断
@升级登记:1 @同步后端:0 @同步数据库:0 @同步配置:0 @向下兼容:1
master
1 parent
060ba40
commit
c4c3c4bbfad2fb3411b295d7125e8171bdd8872e
20278
authored
on 8 May
Showing
1 changed file
project/hivuiMain/views/layout/components/allFuncMenu/index.vue
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(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==''"> <li v-for=" (item1,index) in menus" :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"> <li v-for=" (item2,index) in item1.children" :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> </ul> </li> <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