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 {
      hideMenus() {
        me.hideMenus();
      },
    };
  },

  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.hideMenus();
    },
    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.hideMenus();
    },
    hideMenus() {
      // return;
      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;
    max-height: calc(100vh - 148px);

    &.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;
      font-size: 13px;
      max-height: calc(100vh - 148px);
      overflow: auto;

      ::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%;
            i {
              position: absolute;
              right: 8px;
              top: 50%;
              transform: translateY(-50%);
              font-size: 12px;
            }
          }
        }
      }

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