pyt
2025-04-10 d635b51ae0ffe922d7e56bbceb7229fe7a5fd8f2
src/layouts/components/HeaderNav.vue
@@ -2,45 +2,96 @@
  <div>
    <!-- 右侧用户登录图标 -->
    <div class="user-logininfo">
      <el-dropdown @command="clickmenu">
        <span class="el-dropdown-link right-userName">
          <div style="margin-left: 10px;">{{ userInfo.nickName }}</div>
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="outlogin">退出登录</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <div class="user-logininfo-icon">
        <!-- 折叠 -->
        <i @click="clickFold" class="el-icon-s-fold"></i>
        <!-- 标签列表 -->
        <div class="tag-list-container" @wheel.prevent="handleWheel">
          <div class="tag-list" v-for="tag in tagList" :key="tag.name">
            <div @click="goTag(tag)" :class="{ 'activeTag': tag.path === $route.path }">
              {{ tag.meta.title }}
            </div>
            <i @click="closeTag(tag)" v-if="tagList.length > 1" class="el-icon-close"></i>
          </div>
        </div>
      </div>
      <div class="user-info">
        <img src="@/assets/public/photo.png" />
        <div class="user-info-text">欢迎您,admin</div>
        <div class="user-info-line"></div>
        <div @click="outLogin" class="user-info-out">
          <img src="@/assets/public/logOut.png" />
          <div class="user-info-out-text">退出登录</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {
      userInfo: '',
      scrollTimer: null,
      scrollAmount: 0
    }
  },
  computed: {
    ...mapState(['tagList', 'isFold'])
  },
  mounted() {
    // 获取用户信息
    this.getUserInfo()
  },
  methods: {
    // 点击折叠按钮
    clickFold() {
      this.$store.commit('SET_ISFOLD', !this.isFold)
    },
    // 获取用户信息
    getUserInfo() {
      this.userInfo = JSON.parse(localStorage.getItem('userInfo'))
    },
    // 点击下拉菜单回调
    clickmenu(e) {
      if (e === 'outlogin') {
        this.outLogin()
      }
    },
    // 退出登录
    outLogin() {
      localStorage.clear()
      this.$router.replace({ path: "/" });
    },
    // 关闭标签
    closeTag(tag) {
      this.$store.commit('SET_TAGLIST', this.tagList.filter(item => item.path !== tag.path))
      // 判断是否是当前标签
      if (tag.path === this.$route.path) {
        // if (this.tagList.length > 1) {
        this.$router.push(this.tagList[this.tagList.length - 1].path)
        // } else {
        //   // this.$router.push('/welcome')
        // }
      }
    },
    // 跳转标签
    goTag(tag) {
      this.$router.push(tag.path)
    },
    handleWheel(e) {
      if (this.scrollTimer) {
        this.scrollAmount += e.deltaY;
        return;
      }
      const container = e.currentTarget;
      this.scrollAmount = e.deltaY;
      const scroll = () => {
        container.scrollLeft += this.scrollAmount * 1.2; // 增加滚动速度
        this.scrollAmount = 0;
        this.scrollTimer = null;
      };
      this.scrollTimer = setTimeout(scroll, 8); // 减少延迟时间
    }
  },
}
</script>
@@ -49,16 +100,138 @@
// 右侧用户头像
.user-logininfo {
  height: 100%;
  padding-right: 40px;
  cursor: pointer;
  padding-left: 32px;
  padding-right: 20px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  justify-content: space-between;
  overflow: hidden;
}
  .user-logininfo-icon {
    margin-right: 30px;
    flex: 1;
    display: flex;
    align-items: center;
    min-width: 0;
    overflow: hidden;
.right-userName {
  display: flex;
  align-items: center;
    i:first-child {
      margin-right: 21px;
    }
    i {
      cursor: pointer;
    }
    .tag-list-container {
      display: flex;
      align-items: center;
      overflow-x: auto;
      flex: 1;
      min-width: 0;
      scroll-behavior: auto; // 移除平滑滚动,提高性能
      -webkit-overflow-scrolling: touch;
      .tag-list {
        flex-shrink: 0;
        display: flex;
        align-items: center;
        cursor: pointer;
        font-weight: 400;
        font-size: 18px;
        color: rgba(0, 0, 0, .6);
        margin-right: 40px;
        div:hover {
          font-weight: bold;
          color: #049C9A;
        }
        i {
          margin-left: 10px;
          &:hover {
            color: #049C9A;
          }
        }
      }
      .activeTag {
        font-weight: bold;
        color: #049C9A;
      }
    }
  }
  .user-info {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    img {
      width: 26px;
      height: 26px;
      border-radius: 50%;
    }
    .user-info-text {
      margin-left: 16px;
      font-size: 14px;
      color: #303133;
      font-weight: 400;
    }
    .user-info-line {
      width: 1px;
      height: 12px;
      background-color: #979797;
      margin: 0 20px;
    }
    .user-info-out {
      display: flex;
      align-items: center;
      padding: 0 11px;
      border-radius: 12px;
      position: relative;
      background: transparent;
      cursor: pointer;
      &::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 12px;
        padding: 1px;
        background: linear-gradient(180deg, rgba(10, 203, 202, 1), rgba(4, 156, 154, 1));
        -webkit-mask:
          linear-gradient(#fff 0 0) content-box,
          linear-gradient(#fff 0 0);
        -webkit-mask-composite: xor;
        mask-composite: exclude;
      }
      .user-info-out-text {
        font-weight: 400;
        font-size: 14px;
        color: #049C9A;
        line-height: 21px;
        position: relative;
        z-index: 1;
      }
      img {
        width: 14px;
        height: 14px;
        margin-right: 7px;
        position: relative;
        z-index: 1;
      }
    }
  }
}
</style>