用于实现多标签页机构ID同步功能

27 阅读3分钟

业务:当个浏览器中,切换了机构,多个标签页面同步切换机构ID

方法说明
startPolling启动Cookie监听
stopPolling停止Cookie监听
checkCookieChange检查Cookie变化
shouldRefreshPage根据流程图逻辑判断是否需要刷新页面
handleInstitutionChange处理机构变更
showNotification显示通知
setChangingInstitution标记当前标签页正在变更机构
addCallback添加变更回调函数
removeCallback移除回调函数
triggerCallbacks触发所有回调函数
destroy销毁实例
/**
 * Cookie同步工具
 * 用于实现多标签页机构ID同步功能
 */

import { getInstitutionId, getToken } from '@/utils/auth'

class CookieSync {
  constructor() {
    this.cookieName = process.env.VUE_APP_INS_COOKIE_KEY
    this.pollingInterval = null
    this.lastInstitutionId = null
    this.isChangingInstitution = false
    this.callbacks = []
  }

  /**
   * 启动Cookie监听
   */
  startPolling() {
    // 获取初始值
    this.lastInstitutionId = getInstitutionId()
    
    // 清除现有的轮询(如果有)
    if (this.pollingInterval) {
      clearInterval(this.pollingInterval)
    }

    // 每秒检查一次Cookie变化
    this.pollingInterval = setInterval(() => {
      this.checkCookieChange()
    }, 1000)

    console.log('Cookie同步监听已启动')
  }

  /**
   * 停止Cookie监听
   */
  stopPolling() {
    if (this.pollingInterval) {
      clearInterval(this.pollingInterval)
      this.pollingInterval = null
      console.log('Cookie同步监听已停止')
    }
  }

  /**
   * 检查Cookie变化
   */
  checkCookieChange() {
    // 如果当前标签页正在变更机构,跳过检查
    if (this.isChangingInstitution) {
      return
    }

    const currentInstitutionId = getInstitutionId()
    const token = getToken()
    const isLoggedIn = !!token // 判断是否登录
    
    // 根据流程图逻辑判断是否需要处理变化
    if (currentInstitutionId !== this.lastInstitutionId) {
      console.log('检测到机构ID变化:', this.lastInstitutionId, '->', currentInstitutionId)
      console.log('当前登录状态:', isLoggedIn)
      
      // 更新记录的值
      this.lastInstitutionId = currentInstitutionId
      
      // 触发回调函数
      this.triggerCallbacks(currentInstitutionId)
      
      // 根据流程图逻辑决定是否刷新页面
      if (this.shouldRefreshPage(isLoggedIn, currentInstitutionId)) {
        // 显示通知并刷新页面
        this.handleInstitutionChange(currentInstitutionId)
      } else {
        console.log('根据流程图逻辑,不触发页面刷新')
      }
    }
  }

  /**
   * 根据流程图逻辑判断是否需要刷新页面
   * @param {boolean} isLoggedIn - 是否登录
   * @param {string} institutionId - 机构ID
   * @returns {boolean} - 是否需要刷新页面
   */
  shouldRefreshPage(isLoggedIn, institutionId) {
    // 根据流程图逻辑:
    // 1. 如果未登录(登录状态为false),触发刷新
    if (!isLoggedIn) {
      console.log('用户未登录,触发页面刷新')
      return true
    }
    
    // 2. 如果已登录(登录状态为true)
    if (isLoggedIn) {
      // 2.1 机构ID为空,不触发刷新
      if (!institutionId || institutionId === '') {
        console.log('用户已登录但机构ID为空,不触发页面刷新')
        return false
      }
      
      // 2.2 机构ID不为空或为'0',触发刷新
      console.log('用户已登录且机构ID不为空,触发页面刷新')
      return true
    }
    
    return false
  }

  /**
   * 处理机构变更
   */
  handleInstitutionChange(id) {
    // 显示通知
    this.showNotification('机构已切换,页面即将刷新...')
    const pathname = window.location.pathname
    
    // 延迟跳转,让用户看到通知 
    setTimeout(() => {
      if (location.pathname.startsWith('业务页面')) {
        location.href = '跳转业务的页面';
      } else {
        location.reload();
      }
    }, 1500);
  }

  /**
   * 显示通知
   */
  showNotification(message) {
    // 创建通知元素
    const notification = document.createElement('div')
    notification.style.cssText = `
      position: fixed;
      top: 20px;
      right: 20px;
      background: #4caf50;
      color: white;
      padding: 15px 25px;
      border-radius: 8px;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
      z-index: 10000;
      font-size: 14px;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      transform: translateX(100%);
      transition: transform 0.3s ease;
    `
    notification.textContent = message
    
    // 添加到页面
    document.body.appendChild(notification)
    
    // 显示动画
    setTimeout(() => {
      notification.style.transform = 'translateX(0)'
    }, 100)
    
    // 3秒后移除
    setTimeout(() => {
      notification.style.transform = 'translateX(100%)'
      setTimeout(() => {
        if (notification.parentNode) {
          notification.parentNode.removeChild(notification)
        }
      }, 300)
    }, 3000)
  }

  /**
   * 标记当前标签页正在变更机构
   */
  setChangingInstitution(isChanging) {
    this.isChangingInstitution = isChanging
  }

  /**
   * 添加变更回调函数
   */
  addCallback(callback) {
    if (typeof callback === 'function') {
      this.callbacks.push(callback)
    }
  }

  /**
   * 移除回调函数
   */
  removeCallback(callback) {
    const index = this.callbacks.indexOf(callback)
    if (index > -1) {
      this.callbacks.splice(index, 1)
    }
  }

  /**
   * 触发所有回调函数
   */
  triggerCallbacks(newInstitutionId) {
    this.callbacks.forEach(callback => {
      try {
        callback(newInstitutionId)
      } catch (error) {
        console.error('Cookie同步回调函数执行失败:', error)
      }
    })
  }

  /**
   * 销毁实例
   */
  destroy() {
    this.stopPolling()
    this.callbacks = []
  }
}

// 创建单例实例
const cookieSync = new CookieSync()

export default cookieSync