useAutoLogout.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { onMounted, onUnmounted } from 'vue'
  2. import { ElMessageBox } from 'element-plus'
  3. import { useRouter } from 'vue-router'
  4. import { useUserStore } from '@/store/modules/user'
  5. import { getAccessToken } from '@/utils/auth'
  6. import { throttle } from 'lodash-es'
  7. // --- 关键修改:将变量移到函数外部,变成全局共享变量 ---
  8. let timer: ReturnType<typeof setTimeout> | null = null
  9. const TIMEOUT = 30 * 60 * 1000 // 30分钟
  10. const events = ['click', 'mousedown', 'keydown', 'scroll', 'mousemove']
  11. export function useAutoLogout() {
  12. const userStore = useUserStore()
  13. const router = useRouter()
  14. // 处理登出逻辑
  15. const handleLogout = () => {
  16. // 防止重复触发,先清理
  17. removeListeners()
  18. userStore.loginOut()
  19. ElMessageBox.alert('长时间未操作,登录已超时,请重新登录!', '提示', {
  20. confirmButtonText: '确定',
  21. type: 'warning',
  22. showClose: false,
  23. callback: () => {
  24. router.push('/login')
  25. }
  26. })
  27. }
  28. // 节流的重置计时器
  29. const resetTimer = throttle(() => {
  30. // 这里引用的 timer 是文件顶部的全局变量
  31. if (timer) clearTimeout(timer)
  32. // 只有有 Token 时才开启倒计时
  33. if (getAccessToken()) {
  34. timer = setTimeout(handleLogout, TIMEOUT)
  35. }
  36. }, 1000)
  37. const addListeners = () => {
  38. // 每次添加前先移除,防止重复绑定导致事件堆积
  39. removeListeners()
  40. events.forEach((event) => {
  41. window.addEventListener(event, resetTimer)
  42. })
  43. resetTimer()
  44. }
  45. const removeListeners = () => {
  46. if (timer) {
  47. clearTimeout(timer)
  48. timer = null
  49. }
  50. events.forEach((event) => {
  51. window.removeEventListener(event, resetTimer)
  52. })
  53. }
  54. // 注意:如果你要在路由守卫中手动控制,
  55. // 建议去掉这里的生命周期钩子,或者只在 App.vue 中保留
  56. // 如果这里保留,会导致只要 import 并在组件 setup 中调用,就会自动开启监听
  57. onMounted(() => {
  58. // 如果你想完全由路由守卫控制,注释掉下面这行
  59. // addListeners()
  60. })
  61. onUnmounted(() => {
  62. // 组件卸载时销毁监听
  63. removeListeners()
  64. })
  65. return {
  66. addListeners,
  67. removeListeners
  68. }
  69. }