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
6099f89
commit
1f20540a701c2694ad0ebc530f771567c1bee243
20278
authored
on 9 Aug 2023
Showing
2 changed files
project/hivuiMain/components/contextMenu/ContextMenuItem.vue
project/hivuiMain/components/contextMenu/index.vue
Ignore Space
Show notes
View
project/hivuiMain/components/contextMenu/ContextMenuItem.vue
<template> <li ref="contextMenu" @click="handleClick(item, $event)" :class="itemClass" :title="item[field]"> <div class="label" :class="(item.hoverBtn||item.chooseIcon)?'withHoverBtn':''"> <i class="iconfont" :class="item.iconClass" v-if="item.iconClass"></i> <span class="item-label" v-html="item.html||item[field]"></span> <span class="children-indicator iconfont icon-arrow-right trigger" v-if="item.children"></span> <div class="chooseIcon" v-if="item.chooseIcon" :title="item.chooseIcon.title"> <i :class="item.chooseIcon.iconClass"></i> </div> <div class="hoverBtn" v-if="item.hoverBtn" :title="item.hoverBtn.title" @click="hoverBtnHandleClick(item.hoverBtn,$event)"> <i :class="item.hoverBtn.iconClass"></i> </div> </div> <ul class="context-menu" v-if="item.children" :style="contextMenuStyle"> <context-menu-item v-for="(childItem, index) in item.children" :item="childItem" :field="field" :key="index"> </context-menu-item> </ul> </li> </template> <script> export default { name: 'context-menu-item', props: { item: { type: Object, }, field:{ type:String, default:'title' } }, inject:['getActiveKey','setActiveKey'], data(){ return { contextMenuStyle:"", } }, computed:{ itemClass() { let item =this.item; return { // 'item-active':(item.id!=null)&&this.activeKey==item.id, 'item-active':item.actived, 'item-disabled': this.isItemDisabled(item) }; }, activeKey(){ return this.getActiveKey(); }, }, watch:{ "item.children":{ handler:function(val,old){ setTimeout(()=>{ if(!this.$refs.contextMenu){ this.contextMenuStyle= ""; }else{ let _domRect=this.$refs.contextMenu.getBoundingClientRect(); this.contextMenuStyle= "max-height:calc(100vh - "+(_domRect.top+30)+"px)"; } },100); }, immediate: true, deep: true } }, methods: { handleClick(item, event) { // !item.children&&this.setActiveKey(item.id); if (typeof item.handler !== 'undefined') { if (!this.isItemDisabled(item)) { item.handler(event); } else { event.stopPropagation(); } }else{ } }, hoverBtnHandleClick(item,event){ event.stopPropagation(); if (typeof item.handler !== 'undefined') { item.handler(event); } }, isItemDisabled(item) { if (typeof item.disabled !== 'undefined') { return item.disabled; } return false; }, }, }; </script>
<template> <li @click="handleClick(item, $event)" :class="itemClass" :title="item[field]"> <div class="label"> <i class="iconfont" :class="item.iconClass" v-if="item.iconClass"></i> <span class="item-label" v-html="item.html||item[field]"></span> <span class="children-indicator iconfont icon-arrow-right trigger" v-if="item.children"></span> </div> <ul class="context-menu" v-if="item.children"> <context-menu-item v-for="(childItem, index) in item.children" :item="childItem" :field="field" :key="index"> </context-menu-item> </ul> </li> </template> <script> export default { name: 'context-menu-item', props: { item: { type: Object, }, field:{ type:String, default:'title' } }, inject:['getActiveKey','setActiveKey'], computed:{ itemClass() { let item =this.item; return { // 'item-active':(item.id!=null)&&this.activeKey==item.id, 'item-active':item.actived, 'item-disabled': this.isItemDisabled(item) }; }, activeKey(){ return this.getActiveKey(); } }, methods: { handleClick(item, event) { // !item.children&&this.setActiveKey(item.id); if (typeof item.handler !== 'undefined') { if (!this.isItemDisabled(item)) { item.handler(event); } else { event.stopPropagation(); } }else{ } }, isItemDisabled(item) { if (typeof item.disabled !== 'undefined') { return item.disabled; } return false; }, }, }; </script>
Ignore Space
Show notes
View
project/hivuiMain/components/contextMenu/index.vue
<template> <div class="context-menu context-menu-container" :class="openPosition" v-if="visible" :style="contextMenuPosition" v-click-outside="close" @click="close" @mouseenter="visble=true" @mouseleave="visible=false" ref="contextMenu" > <ul> <context-menu-item :field="field" v-for="(menuItem, index) in menuItems" :item="menuItem" :key="index"> </context-menu-item> </ul> </div> </template> <script> /* eslint-disable prefer-destructuring */ import ContextMenuItem from './ContextMenuItem.vue'; /** * A simple context menu component * * ```html * <ContextMenu :menu-items="[....]"/> * ``` */ export default { props: { menuItems: { type: Array, required: true, }, field:{ type:String, default:'title' } }, provide(){ let me=this; return { getActiveKey(){ return me.activeKey; }, setActiveKey(key){ me.activeKey = key; } } }, data() { return { visible: false, activeKey:'', contextMenuPosition: { top: 0, left: 0, }, openPosition: 'context-menu-open-right', }; }, methods: { close() { this.visible = false; }, /** * Accepts an Object with an `x, y` position or an instance of Event */ open(position) { this.visible = true; this.$nextTick(() => { let x = 0; let y = 0; if (typeof position !== 'undefined' && typeof position === 'object') { if (position instanceof Event) { const windowWidth = window.innerWidth; // const contextMenuWidth = this.$refs.contextMenu.getBoundingClientRect().width; //ie getBoundingClientRect null const contextMenuWidth = this.$refs.contextMenu.offsetWidth; let pageX = position.pageX; let pageY = position.pageY; // let elRect = position.currentTarget.getBoundingClientRect(); //ie getBoundingClientRect null let elRect = (position.currentTarget||position.target).getBoundingClientRect(); if( position.type != "contextmenu"){ pageX = elRect.left; pageY = elRect.top+elRect.height; if(pageX>=(windowWidth - contextMenuWidth*2)){ this.openPosition = 'context-menu-open-left'; x = windowWidth<(pageX+contextMenuWidth)?(windowWidth-contextMenuWidth):pageX; }else{ this.openPosition = 'context-menu-open-right'; x = pageX; } }else{ if (pageX >= (windowWidth - contextMenuWidth)) { this.openPosition = 'context-menu-open-left'; x = windowWidth - contextMenuWidth - 10; } else { this.openPosition = 'context-menu-open-right'; x = pageX; } } y = pageY; } else { x = position.x; y = position.y; } } this.contextMenuPosition = { left: `${x}px`, top: `${y}px`, }; }); }, }, components: { 'context-menu-item': ContextMenuItem, }, directives: { 'click-outside': { inserted: function (el) { document.body.appendChild(el) }, bind(el, binding, vnode) { el.clickOutsideEvent = (event) => { // here I check that click was outside the el and his childrens if (!(el === event.target || el.contains(event.target))) { // and if it did, call method provided in attribute value vnode.context[binding.expression](event); } }; document.body.addEventListener('click', el.clickOutsideEvent); }, unbind(el) { document.body.removeEventListener('click', el.clickOutsideEvent); }, } }, }; </script> <style lang="less"> @context-menu-border-radius: 0px; .context-menu-container { position: absolute; user-select: none; z-index: 100; } .context-menu { background: #fff; border-radius: @context-menu-border-radius; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); ul { margin: 0; padding: 0; list-style: none; :first-child { border-top-right-radius: @context-menu-border-radius; border-top-left-radius: @context-menu-border-radius; } :last-child { border-bottom-right-radius: @context-menu-border-radius; border-bottom-left-radius: @context-menu-border-radius; } li { position: relative; padding: 5px; display: block; line-height: 25px; cursor: pointer; .label { display: flex; white-space: nowrap; position: relative; .iconfont{ margin-right: 5px; } .item-label { margin-right: 10px; } .children-indicator{ margin-left:auto; } &.withHoverBtn{ padding-right:28px; .hoverBtn,.chooseIcon{ height:24px; line-height:24px; width:24px; position: absolute; top:0; bottom:0; right:0; margin:auto; display: none; &:hover{ color:#fc0; } i{ font-size: 20px; line-height:24px; font-weight: bold; } } .chooseIcon,&:hover .hoverBtn{ display: block; } .chooseIcon{ color:#fc0; } } } &.item-disabled { cursor: not-allowed; opacity: 0.3; } ul { display: none; } &.item-active{ background: #0066cc; >.label{ color:#fff; } } &:hover { background: #0066cc; >.label{ color:#fff; } > ul { position: absolute; // left: calc(100% + 2px); left:100%; top: 0; display: inline-block; min-width: 100px; overflow: auto; } } } } &.context-menu-open-left { ul { li { &:hover { > ul { left: auto; // right: calc(100% + 2px); right: 100%; } } } } } } </style>
<template> <div class="context-menu context-menu-container" :class="openPosition" v-if="visible" :style="contextMenuPosition" v-click-outside="close" @click="close" @mouseenter="visble=true" @mouseleave="visible=false" ref="contextMenu" > <ul> <context-menu-item :field="field" v-for="(menuItem, index) in menuItems" :item="menuItem" :key="index"> </context-menu-item> </ul> </div> </template> <script> /* eslint-disable prefer-destructuring */ import ContextMenuItem from './ContextMenuItem.vue'; /** * A simple context menu component * * ```html * <ContextMenu :menu-items="[....]"/> * ``` */ export default { props: { menuItems: { type: Array, required: true, }, field:{ type:String, default:'title' } }, provide(){ let me=this; return { getActiveKey(){ return me.activeKey; }, setActiveKey(key){ me.activeKey = key; } } }, data() { return { visible: false, activeKey:'', contextMenuPosition: { top: 0, left: 0, }, openPosition: 'context-menu-open-right', }; }, methods: { close() { this.visible = false; }, /** * Accepts an Object with an `x, y` position or an instance of Event */ open(position) { this.visible = true; this.$nextTick(() => { let x = 0; let y = 0; if (typeof position !== 'undefined' && typeof position === 'object') { if (position instanceof Event) { const windowWidth = window.innerWidth; // const contextMenuWidth = this.$refs.contextMenu.getBoundingClientRect().width; //ie getBoundingClientRect null const contextMenuWidth = this.$refs.contextMenu.offsetWidth; let pageX = position.pageX; let pageY = position.pageY; // let elRect = position.currentTarget.getBoundingClientRect(); //ie getBoundingClientRect null let elRect = (position.currentTarget||position.target).getBoundingClientRect(); if( position.type != "contextmenu"){ pageX = elRect.left; pageY = elRect.top+elRect.height; if(pageX>=(windowWidth - contextMenuWidth*2)){ this.openPosition = 'context-menu-open-left'; x = windowWidth<(pageX+contextMenuWidth)?(windowWidth-contextMenuWidth):pageX; }else{ this.openPosition = 'context-menu-open-right'; x = pageX; } }else{ if (pageX >= (windowWidth - contextMenuWidth)) { this.openPosition = 'context-menu-open-left'; x = windowWidth - contextMenuWidth - 10; } else { this.openPosition = 'context-menu-open-right'; x = pageX; } } y = pageY; } else { x = position.x; y = position.y; } } this.contextMenuPosition = { left: `${x}px`, top: `${y}px`, }; }); }, }, components: { 'context-menu-item': ContextMenuItem, }, directives: { 'click-outside': { inserted: function (el) { document.body.appendChild(el) }, bind(el, binding, vnode) { el.clickOutsideEvent = (event) => { // here I check that click was outside the el and his childrens if (!(el === event.target || el.contains(event.target))) { // and if it did, call method provided in attribute value vnode.context[binding.expression](event); } }; document.body.addEventListener('click', el.clickOutsideEvent); }, unbind(el) { document.body.removeEventListener('click', el.clickOutsideEvent); }, } }, }; </script> <style lang="less"> @context-menu-border-radius: 0px; .context-menu-container { position: absolute; user-select: none; z-index: 100; } .context-menu { background: #fff; border-radius: @context-menu-border-radius; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); ul { margin: 0; padding: 0; list-style: none; :first-child { border-top-right-radius: @context-menu-border-radius; border-top-left-radius: @context-menu-border-radius; } :last-child { border-bottom-right-radius: @context-menu-border-radius; border-bottom-left-radius: @context-menu-border-radius; } li { position: relative; padding: 5px; display: block; line-height: 25px; cursor: pointer; .label { display: flex; white-space: nowrap; .iconfont{ margin-right: 5px; } .item-label { margin-right: 10px; } .children-indicator{ margin-left:auto; } } &.item-disabled { cursor: not-allowed; opacity: 0.3; } ul { display: none; } &.item-active{ background: #0066cc; >.label{ color:#fff; } } &:hover { background: #0066cc; >.label{ color:#fff; } > ul { position: absolute; // left: calc(100% + 2px); left:100%; top: 0; display: inline-block; min-width: 100px; } } } } &.context-menu-open-left { ul { li { &:hover { > ul { left: auto; // right: calc(100% + 2px); right: 100%; } } } } } } </style>
Show line notes below