董国庆
2025-06-26 dae39dea7e2874ebe2f17438949255ce8331ecef
laboratory/src/layouts/components/HeaderNav.vue
@@ -2,22 +2,34 @@
  <div>
    <!-- 右侧用户登录图标 -->
    <div class="user-logininfo">
      <div class="user-logininfo-icon">
      <div class="logoIcon" v-if="logo">
        <div class="image">
          <img src="../../assets/logo.jpg" alt="" srcset="" />
        </div>
      </div>
      <div class="user-logininfo-icon" v-else>
        <!-- 折叠 -->
        <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 }">
            <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>
            <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-text">欢迎您,{{ userInfo.nickName }}</div>
        <div class="user-info-line"></div>
        <div @click="outLogin" class="user-info-out">
          <img src="@/assets/public/logOut.png" />
@@ -25,78 +37,126 @@
        </div>
      </div>
    </div>
    <el-dialog
      top="40vh"
      :visible.sync="show"
      :show-close="false"
      :append-to-body="true"
      :close-on-click-modal="false"
      width="433px"
    >
      <div class="top-con a-center" slot="title">
        <div class="left">
          <img
            src="@/assets/public/notice@2x.png"
            style="width: 24px; height: 24px; margin-right: 14px"
          />
          <div class="title">{{ "提示" }}</div>
        </div>
      </div>
      <div class="lh--32 fs--20">
        {{ "当前页面可能有未保存数据,确认关闭么" }}
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="show = false">取消</el-button>
        <el-button type='danger' @click="submitClose">{{ "确认" }}</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import { mapState } from 'vuex'
import { mapState } from "vuex";
export default {
  data() {
    return {
      userInfo: '',
      userInfo: "",
      scrollTimer: null,
      scrollAmount: 0
    }
      scrollAmount: 0,
      show: false,
      pendingCloseTag: null,
    };
  },
  props: {
    logo: {
      type: String,
      default: "",
    },
  },
  computed: {
    ...mapState(['tagList', 'isFold'])
    ...mapState(["tagList", "isFold"]),
  },
  mounted() {
    // 获取用户信息
    this.getUserInfo()
    this.getUserInfo();
  },
  methods: {
    // 点击折叠按钮
    clickFold() {
      this.$store.commit('SET_ISFOLD', !this.isFold)
      this.$store.commit("SET_ISFOLD", !this.isFold);
    },
    // 获取用户信息
    getUserInfo() {
      this.userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
      this.userInfo = JSON.parse(sessionStorage.getItem("userInfo"));
    },
    // 退出登录
    outLogin() {
      sessionStorage.clear()
      sessionStorage.clear();
      this.$router.replace({ path: "/" });
    },
    // 关闭标签
    closeTag(tag) {
      this.$store.commit('SET_TAGLIST', this.tagList.filter(item => item.path !== tag.path))
      if (tag.path && tag.path.includes('add')) {
        this.pendingCloseTag = tag;
        this.show = true;
        return;
      }
      this._doCloseTag(tag);
    },
    // 真正执行关闭标签的逻辑
    _doCloseTag(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')
        // }
        this.$router.push(this.tagList[this.tagList.length - 1].path);
      }
    },
    submitClose() {
      this.show = false;
      if (this.pendingCloseTag) {
        this._doCloseTag(this.pendingCloseTag);
        this.pendingCloseTag = null;
      }
    },
    // 跳转标签
    goTag(tag) {
        this.$router.push({
            path: tag.path,
            query: tag.query
        })
      this.$router.push({
        path: tag.path,
        query: tag.query,
      });
    },
    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>
<style lang="less" scoped>
@@ -109,6 +169,18 @@
  align-items: center;
  justify-content: space-between;
  overflow: hidden;
  .image {
    // margin-top: 40px;
    width: 70px;
    height: 70px;
    img {
      width: 100%;
      height: 100%;
      border-radius: 50%;
    }
  }
  .user-logininfo-icon {
    margin-right: 30px;
@@ -142,29 +214,28 @@
        cursor: pointer;
        font-weight: 400;
        font-size: 18px;
        color: rgba(0, 0, 0, .6);
        color: rgba(0, 0, 0, 0.6);
        margin-right: 40px;
        div:hover {
          font-weight: bold;
          color: #049C9A;
          color: #049c9a;
        }
        i {
          margin-left: 10px;
          &:hover {
            color: #049C9A;
            color: #049c9a;
          }
        }
      }
      .activeTag {
        font-weight: bold;
        color: #049C9A;
        color: #049c9a;
      }
    }
  }
  .user-info {
@@ -202,7 +273,7 @@
      cursor: pointer;
      &::before {
        content: '';
        content: "";
        position: absolute;
        top: 0;
        left: 0;
@@ -210,9 +281,12 @@
        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,
        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;
@@ -221,7 +295,7 @@
      .user-info-out-text {
        font-weight: 400;
        font-size: 14px;
        color: #049C9A;
        color: #049c9a;
        line-height: 21px;
        position: relative;
        z-index: 1;
@@ -237,4 +311,53 @@
    }
  }
}
.left {
    display: flex;
}
::v-deep .el-dialog {
    border-radius: 12px;
    .el-dialog__header {
        padding-top: 28px;
        padding-right: 27px;
        padding-left: 34px;
        padding-bottom: 11px;
    }
    .el-dialog__body {
        padding: unset;
        padding-left: 73px;
        padding-right: 20px;
    }
    .el-dialog__footer {
        padding-top: 18px;
        padding-right: 27px;
        padding-bottom: 29px;
    }
}
.bgcolor1 {
    background: rgba(22, 119, 255, 1);
}
.top-con {
    display: flex;
    justify-content: space-between;
    .title {
        font-family: PingFangSC, PingFang SC;
        font-weight: 600;
        font-size: 16px;
        color: rgba(0, 0, 0, 1);
        margin-bottom: 13px;
    }
}
.dialog-footer {
    display: flex;
    justify-content: end;
    gap: 10px;
}
</style>