| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- import { onMounted, onUnmounted } from 'vue'
- import { ElMessageBox } from 'element-plus'
- import { useRouter } from 'vue-router'
- import { useUserStore } from '@/store/modules/user'
- import { getAccessToken } from '@/utils/auth'
- import { throttle } from 'lodash-es'
- // --- 关键修改:将变量移到函数外部,变成全局共享变量 ---
- let timer: ReturnType<typeof setTimeout> | null = null
- const TIMEOUT = 30 * 60 * 1000 // 30分钟
- const events = ['click', 'mousedown', 'keydown', 'scroll', 'mousemove']
- export function useAutoLogout() {
- const userStore = useUserStore()
- const router = useRouter()
- // 处理登出逻辑
- const handleLogout = () => {
- // 防止重复触发,先清理
- removeListeners()
- userStore.loginOut()
- ElMessageBox.alert('长时间未操作,登录已超时,请重新登录!', '提示', {
- confirmButtonText: '确定',
- type: 'warning',
- showClose: false,
- callback: () => {
- router.push('/login')
- }
- })
- }
- // 节流的重置计时器
- const resetTimer = throttle(() => {
- // 这里引用的 timer 是文件顶部的全局变量
- if (timer) clearTimeout(timer)
- // 只有有 Token 时才开启倒计时
- if (getAccessToken()) {
- timer = setTimeout(handleLogout, TIMEOUT)
- }
- }, 1000)
- const addListeners = () => {
- // 每次添加前先移除,防止重复绑定导致事件堆积
- removeListeners()
- events.forEach((event) => {
- window.addEventListener(event, resetTimer)
- })
- resetTimer()
- }
- const removeListeners = () => {
- if (timer) {
- clearTimeout(timer)
- timer = null
- }
- events.forEach((event) => {
- window.removeEventListener(event, resetTimer)
- })
- }
- // 注意:如果你要在路由守卫中手动控制,
- // 建议去掉这里的生命周期钩子,或者只在 App.vue 中保留
- // 如果这里保留,会导致只要 import 并在组件 setup 中调用,就会自动开启监听
- onMounted(() => {
- // 如果你想完全由路由守卫控制,注释掉下面这行
- // addListeners()
- })
- onUnmounted(() => {
- // 组件卸载时销毁监听
- removeListeners()
- })
- return {
- addListeners,
- removeListeners
- }
- }
|