index.vue 6.51 KB
<script lang="ts" setup name="Header">
import Logo from "../Logo/index.vue";
import Tools from "../Tools/index.vue";
import useSettingsStore from "@/store/modules/settings";
import useMenuStore from "@/store/modules/menu";

const emits = defineEmits([
  "clickMsgSetting"
]);

const props = defineProps({
  noFinishCnt: {
    type: Number,
    default: 0,
  }
})

const settingsStore = useSettingsStore();
const menuStore = useMenuStore();
const { switchTo } = useMenu();
const navRef = ref();
const enableSubMenuCollapseButton = computed(() => {
  return (
    settingsStore.mode === "mobile" ||
    (["side", "head", "single"].includes(
      settingsStore.settings.menu.menuMode
    ) &&
      settingsStore.settings.menu.enableSubMenuCollapseButton)
  );
});
// 顶部模式鼠标滚动
function handlerMouserScroll(event: WheelEvent) {
  navRef.value.scrollBy({
    left: (event.deltaY || event.detail) > 0 ? 50 : -50,
  });
}

const handleShowMessage = () => {
  emits('clickMsgSetting');
}

</script>
<template>
  <transition name="header">
    <header v-if="
      settingsStore.mode === 'pc' &&
      settingsStore.settings.menu.menuMode === 'head'
    ">
      <div class="header-container">
        <Logo />
        <div v-if="enableSubMenuCollapseButton" class="sidebar-collapse" :class="{
          'is-collapse': settingsStore.settings.menu.subMenuCollapse,
        }" @click="settingsStore.toggleSidebarCollapse()" v-preReClick>
          <el-icon v-if="settingsStore.settings.menu.subMenuCollapse">
            <svg-icon name="toolbar-expend" />
          </el-icon>
          <el-icon v-else>
            <svg-icon name="toolbar-collapse" />
          </el-icon>
        </div>
        <div class="main">
          <!-- 顶部模式 -->
          <div ref="navRef" class="nav" @wheel.prevent="handlerMouserScroll">
            <template v-for="(item, index) in menuStore.allMenus" :key="index">
              <div v-if="item.children && item.children.length !== 0" class="item-container"
                :class="{ active: index === menuStore.actived }">
                <div class="item" @click="switchTo(index)" v-preReClick>
                  <el-icon v-if="item.meta?.icon">
                    <svg-icon :name="item.meta.icon" />
                  </el-icon>
                  <span v-if="item.meta?.title">{{ item.meta.title }}</span>
                </div>
              </div>
            </template>
          </div>
        </div>
        <div class="message-setting" @click=handleShowMessage>
          <span v-show="noFinishCnt > 0" class="msg-cnt">{{ noFinishCnt > 99 ? '99+' : noFinishCnt }}</span>
          <el-icon class="message-notify">
            <svg-icon name="message" />
          </el-icon>
        </div>
        <Tools />
      </div>
    </header>
  </transition>
</template>
<style lang="scss" scoped>
header {
  position: fixed;
  z-index: 1000;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  height: var(--g-header-height);
  color: var(--g-header-color);
  background-image: url("@/assets/images/header_bg_icon.png");
  background-repeat: no-repeat;
  background-size: 456px 48px;
  background-position: 0;
  background-color: #63b6bd;
  transition: background-color 0.3s, var(--el-transition-color);

  // position: relative;
  .header-container {
    width: var(--g-header-width);
    height: 100%;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: relative;
  }

  .sidebar-collapse {
    position: absolute;
    left: calc(var(--g-sub-sidebar-width) + 10px);
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    cursor: pointer;

    :deep(.el-icon) {
      color: #fff;
    }
  }

  .main {
    // width: calc(var(--g-header-width) - var(--g-sub-sidebar-width) - 48px);
    height: 100%;
    padding: 0 24px;
    flex: 1;
  }

  @media screen and (max-width: var(--g-header-width)) {
    .header-container {
      width: 100%;
    }
  }

  :deep(.title) {
    position: relative;
    width: var(--g-sub-sidebar-width);
    height: inherit;
    padding-left: 18px;
    padding-right: 0;
    background-color: inherit;

    .logo {
      width: auto;
      height: 30px;
    }

    span {
      font-size: 24px;
      letter-spacing: 1px;
      color: var(--g-header-color);
    }
  }

  .nav {
    display: flex;
    width: 100%;
    height: 100%;
    padding: 0 20px;
    align-items: center;
    overflow-x: auto;
    mask-image: linear-gradient(to right,
        transparent,
        #000 20px,
        #000 calc(100% - 20px),
        transparent);
    // firefox隐藏滚动条
    scrollbar-width: none;

    // chrome隐藏滚动条
    &::-webkit-scrollbar {
      display: none;
    }

    .item-container {
      position: relative;
      display: flex;
      width: initial;
      height: inherit;

      .item {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        min-width: 80px;
        padding: 0px 10px;
        height: 100%;
        cursor: pointer;
        color: var(--g-header-menu-color);
        background-color: transparent;

        // transition: background-color 0.3s, var(--el-transition-color);
        &:hover {
          color: var(--g-header-menu-hover-color);
          background-color: var(--g-header-menu-hover-bg);
        }

        .el-icon {
          font-size: 24px;
          vertical-align: middle;
        }

        span {
          text-align: center;
          vertical-align: middle;
          word-break: break-all;
          @include text-overflow(1, false);
        }
      }

      &.active .item {
        color: var(--g-header-menu-active-color);
        background-color: var(--g-header-menu-active-bg);
      }
    }
  }

  :deep(.tools) {
    padding: 0 18px;

    .buttons .item .el-icon {
      color: var(--g-header-color);
    }

    .user-container {
      font-size: 16px;
      color: var(--g-header-color);
      outline: none !important;
    }
  }
}

// 头部动画
.header-enter-active,
.header-leave-active {
  transition: transform 0.3s;
}

.header-enter-from,
.header-leave-to {
  transform: translateY(calc(var(--g-header-height) * -1));
}

.message-setting {
  position: relative;
  display: flex;
  margin-right: 5px;
  cursor: pointer;

  .msg-cnt {
    z-index: 3;
    background-color: #e63e33;
    padding: 2px 5px;
    color: #fff;
    border-radius: 40%;
    position: absolute;
    left: 9px;
    top: -10px;
    font-size: 12px;
  }
}

.message-notify.el-icon {
  width: 18px;
  height: 18px;

  svg {
    width: 18px;
    height: 18px;
  }
}

</style>