08335 / hivui-platform-template
hivui平台项目模板
Newer
Older
hivui-platform-template / project / hivuiMain / views / layout / components / kyMenus / index.vue
<template>
  <div class="ky-menus-box" ref="kyMenus" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
    <div class="ky-menus-bg" :class="{ active: showAllSubMenus }" :style="{ height: backgroundHeight + 'px' }"></div>
    <ul class="ky-menus" :class="{ active: showAllSubMenus }">
      <template v-for="item in menus">
        <li class="ky-menus-item" v-if="item.isShow && !(item.children && item.children.length)" :icon="item.iconClass"
          @click="handleOpenFunc(item)" :key="item.resId">{{ item.name }}
        </li>
        <li class="ky-menus-item" v-if="item.isShow && item.children && item.children.length" :key="item.resId">
          <div class="title">
            <span class="txt">{{ item.name }}</span>
          </div>
          <div class="sub-menu" v-if="item.isShow && item.children && item.children.length">
            <ul v-show="showAllSubMenus">
              <template v-for="child in item.children">
                <li v-if="child.isShow && !(child.children && child.children.length)" @click="handleOpenFunc(child)"  :key="child.resId">
                  <div class="title">
                    <span class="txt">{{ child.name }}</span>
                  </div>
                </li>
                <nav-sub-menus :level="0" :menuitem="child" :parent="kyMenus"
                  v-if="child.isShow && child.children && child.children.length"  :key="child.resId" >
                </nav-sub-menus>
              </template>
            </ul>
          </div>
        </li>
      </template>
    </ul>
  </div>
</template>

<script>
import NavSubMenus from './menus.vue'
export default {
  inject: ['addTab'],
  provide() {
    let me = this;
    return {
      hideKyMenus() {
        me.hideKyMenus();
      },
      showAllFuncBox() {
      },
      hideAllFuncBox() {
      },
    }
  },

  props: {},
  components: { NavSubMenus },
  data() {
    return {
      showAllSubMenus: false,
      backgroundHeight: 0,
      isMenuDisabled: false // 添加禁用标志
    };
  },
  computed: {
    menus() {
      const menus = this.$store.getters.menus;
      return menus;
    }
  },
  watch: {},
  mounted() {
    console.log(this.menus);
  },
  methods: {
    async handleOpenFunc(item) {
      if (item.type == "link") {
        window.open(item.resUrl, item.name);
        return;
      } else if (item.type == "sso") {
        item.ssoUrl = await this.$store.dispatch("user/openSSOFuncPage", {
          serviceUrl: item.resUrl
        });
      }
      // this.addTab(item.resUrl,item.name,item.resId)//,item.resId
      this.addTab(item);//inject 提供的方法只能 传一个参数
      this.hideKyMenus();
    },
    handleMouseEnter(e) {
      // 如果菜单被禁用,则不处理鼠标事件
      if (this.isMenuDisabled) {
        return;
      }

      if (e) {
        const target = e.target || e.srcElement;
        if (target.closest && target.closest('.pl-menus-item')) {
          return;
        }
      }

      this.showAllSubMenus = true;
      this.$nextTick(() => {
        this.calculateMaxHeight();
      });
    },
    handleMouseLeave(e) {
      // 如果菜单被禁用,则不处理鼠标事件
      if (this.isMenuDisabled) {
        return;
      }
      if (e) {
        // 检查鼠标是否移向.pl-menus-item类元素
        const relatedTarget = e.relatedTarget || e.toElement;
        if (relatedTarget && relatedTarget.closest && relatedTarget.closest('.pl-menus-item')) {
          return;
        }
      }

      this.hideKyMenus();
    },
    hideKyMenus() {
      this.showAllSubMenus = false;
      this.backgroundHeight = 0;
      this.isMenuDisabled = true;

      // 延迟重置禁用标志,避免立即触发鼠标事件
      setTimeout(() => {
        this.isMenuDisabled = false;
      }, 100);
    },
    calculateMaxHeight() {
      // 获取所有显示的子菜单
      const subMenus = document.querySelectorAll('.ky-menus-item .sub-menu');
      let maxHeight = 0;

      subMenus.forEach(menu => {
        maxHeight = Math.max(maxHeight, menu.offsetHeight);
      });

      this.backgroundHeight = maxHeight + 20;
    }
  }
}
</script>

<style lang="less" scoped>
.ky-menus-box {

  ul,
  li {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .ky-menus-bg {
    position: absolute;
    top: 48px;
    left: 50%;
    transform: translateX(-50%) scaleY(0);
    width: 100%;
    z-index: -999;
    background: #0066cc;
    transition: all 0.5s;
    transform-origin: center top;

    &.active {
      transform: translateX(-50%) scaleY(1);
    }
  }

  .ky-menus {
    display: flex;
    padding-left: 10px;

    // &.active .ky-menus-item {
    //   opacity: 0.5;
    //   &:hover {
    //     opacity: 1;
    //   }
    // }

    .ky-menus-item {
      position: relative;
      line-height: 48px;
      padding-right: 30px;
      cursor: pointer;


    }

    .sub-menu {
      position: absolute;
      top: 48px;
      left: 0;
      line-height: 20px;
      // white-space: nowrap;

      ::v-deep .pl-menus-item {
        .title {
          position: relative;

          .txt {
            box-sizing: border-box;
            padding: 5px;
            padding-right: 20px;
            padding-left: 0;
            display: inline-block;
            width: 100%;
          }
        }
      }

      li {
        .title {
          padding: 5px;
          padding-left: 0;
        }
      }
    }
  }
}
</style>