1
admin
2026-01-05 c8361f1a9080a9e52d0ac772bd59697ad318cfe9
src/App.vue
@@ -3,12 +3,22 @@
    <div :class="`header-box`" v-if="hasHeader && title !== $t('hj248')">
      <mt-header :title="title">
        <mt-button icon="back" slot="left" @click="$router.go(-1)"></mt-button>
        <div v-if="!is_Show">
          <template v-if="iconRight == 'search'">
            <img slot="right" class="search-right" src="./assets/ico/fangdajing.png" alt />
          </template>
          <template v-else>
            <mt-button icon="more" slot="right"></mt-button>
        <div slot="right" class="header-right">
          <!-- 消息图标 - 始终显示(如果已登录) -->
          <div class="message-icon-wrapper" @click="goToMessage" v-if="isLoggedIn">
            <svg class="message-icon" viewBox="0 0 24 24" fill="currentColor">
              <path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"/>
            </svg>
            <span v-if="unreadCount > 0" class="message-badge">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>
          </div>
          <!-- 其他图标 -->
          <template v-if="!is_Show">
            <template v-if="iconRight == 'search'">
              <img class="search-right" src="./assets/ico/fangdajing.png" alt />
            </template>
            <template v-else-if="iconRight != 'message'">
              <mt-button icon="more"></mt-button>
            </template>
          </template>
        </div>
      </mt-header>
@@ -28,6 +38,7 @@
import elalert from "@/components/elalert.vue";
import foot from "@/components/foot.vue";
import loginPopup from "@/components/loginDialog.vue";
import * as api from "@/axios/api";
//引入css
import "@/assets/iconfont/iconfont.css";
import "@/assets/iconfont/iconfont.ttf";
@@ -61,6 +72,49 @@
    }
    // this.$store.state.className = window.localStorage.getItem('styleName')?window.localStorage.getItem('styleName'):'red'
  },
  data() {
    return {
      title: this.$t('hj224'),
      hasHeader: false,
      iconRight: "default",
      transitionName: '',
      is_Show: true,
      is_foot: true,
      unreadCount: 0,
      messageTimer: null,
      loginCheckTimer: null,
      lastToken: null,
    };
  },
  computed: {
    isLoggedIn() {
      // 实时检查登录状态
      return !!window.localStorage.getItem("USERTOKEN");
    }
  },
  mounted() {
    // 初始化时检查登录状态并获取消息数
    this.checkLoginAndLoadMessages();
    // 监听localStorage变化(用于跨标签页同步)
    window.addEventListener('storage', this.handleStorageChange);
    // 定期检查登录状态(处理同标签页内的登录/登出)
    this.loginCheckTimer = setInterval(() => {
      this.checkLoginAndLoadMessages();
    }, 1000);
  },
  beforeDestroy() {
    // 清除定时器
    if (this.messageTimer) {
      clearInterval(this.messageTimer);
    }
    if (this.loginCheckTimer) {
      clearInterval(this.loginCheckTimer);
    }
    // 移除事件监听
    window.removeEventListener('storage', this.handleStorageChange);
  },
  watch: {
    $route(to, from) {
      let title = to.meta.title || this.$t('hj224');
@@ -84,17 +138,10 @@
        console.log("slide-right");
        this.transitionName = "slide-right";
      }
      // 路由变化时,如果已登录则刷新未读消息数
      this.checkLoginAndLoadMessages();
    }
  },
  data() {
    return {
      title: this.$t('hj224'),
      hasHeader: false,
      iconRight: "default",
      transitionName: '',
      is_Show: true,
      is_foot: true,
    };
  },
  methods: {
    footColse() {
@@ -102,6 +149,73 @@
    },
    dialogClose() {
      this.$store.commit('dialogVisible', false);
    },
    // 跳转到消息页面
    goToMessage() {
      this.$router.push('/notify');
    },
    // 获取未读消息数
    async getUnreadCount() {
      try {
        console.log('开始获取未读消息数...');
        const data = await api.getUnreadCount();
        console.log('未读消息数API响应:', data);
        if (data && data.status === 0) {
          this.unreadCount = data.data || 0;
          console.log('未读消息数:', this.unreadCount);
        } else {
          console.warn('获取未读消息数失败:', data ? data.msg : '响应为空');
          this.unreadCount = 0;
        }
      } catch (error) {
        console.error('获取未读消息数异常:', error);
        this.unreadCount = 0;
      }
    },
    // 开始轮询未读消息数(每30秒)
    startMessagePolling() {
      // 如果已有定时器,先清除
      if (this.messageTimer) {
        clearInterval(this.messageTimer);
      }
      this.messageTimer = setInterval(() => {
        if (this.isLoggedIn) {
          this.getUnreadCount();
        }
      }, 30000);
    },
    // 检查登录状态并加载消息
    checkLoginAndLoadMessages() {
      const token = window.localStorage.getItem("USERTOKEN");
      const isLoggedIn = !!token;
      // 如果登录状态发生变化
      if (this.lastToken !== token) {
        this.lastToken = token;
        if (isLoggedIn) {
          console.log('检测到登录,开始加载消息');
          this.getUnreadCount();
          this.startMessagePolling();
        } else {
          console.log('检测到登出,清除消息');
          this.unreadCount = 0;
          if (this.messageTimer) {
            clearInterval(this.messageTimer);
            this.messageTimer = null;
          }
        }
      } else if (isLoggedIn && !this.messageTimer) {
        // 如果已登录但没有启动轮询,启动它
        this.getUnreadCount();
        this.startMessagePolling();
      }
    },
    // 处理localStorage变化事件
    handleStorageChange(e) {
      if (e.key === 'USERTOKEN') {
        this.checkLoginAndLoadMessages();
      }
    }
  }
};
@@ -257,7 +371,6 @@
      color: #000;
    }
    /deep/.mint-tab-container {}
    /deep/.mint-tab-item {
      background: #272733;
@@ -311,4 +424,51 @@
/deep/.icon-icon_A::before {
  font-size: 0.6rem !important;
}
.header-right {
  display: flex;
  align-items: center;
  gap: 0.2rem;
}
.message-icon-wrapper {
  position: relative;
  display: inline-block;
  margin-right: 0.2rem;
  cursor: pointer;
}
.message-icon {
  width: 0.48rem;
  height: 0.48rem;
  color: rgba(255, 255, 255, 0.8);
  cursor: pointer;
}
.message-badge {
  position: absolute;
  top: -0.1rem;
  right: -0.1rem;
  min-width: 0.32rem;
  height: 0.32rem;
  line-height: 0.32rem;
  padding: 0 0.08rem;
  background-color: #ff4444;
  color: #fff;
  border-radius: 0.16rem;
  font-size: 0.2rem;
  text-align: center;
  font-weight: bold;
  border: 0.02rem solid #fff;
}
#app.red-theme {
  .message-icon {
    color: #212121;
  }
  .message-badge {
    border-color: #fff;
  }
}
</style>