feat(m11): add idle timeout auto-logout with warning dialog

This commit is contained in:
2026-05-25 01:32:51 +08:00
parent 33773928c3
commit c2118b16aa
@@ -62,11 +62,17 @@
</div>
</div>
</div>
<el-dialog v-model="showIdleWarning" title="登录即将超时" width="400px" :close-on-click-modal="false" :show-close="false">
<p>您已长时间未操作登录将在 1 分钟后超时</p>
<template #footer>
<el-button type="primary" @click="resetIdleTimer">我还活跃</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { computed } from "vue";
import { computed, ref, onMounted, onUnmounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useAuthStore } from "../stores/auth";
import { ElMessage } from "element-plus";
@@ -75,6 +81,48 @@ const route = useRoute();
const router = useRouter();
const auth = useAuthStore();
const IDLE_TIMEOUT_MS = 30 * 60 * 1000
const WARNING_BEFORE_MS = 60 * 1000
let idleTimer = null
let warningTimer = null
const showIdleWarning = ref(false)
function resetIdleTimer() {
if (idleTimer) clearTimeout(idleTimer)
if (warningTimer) clearTimeout(warningTimer)
showIdleWarning.value = false
warningTimer = setTimeout(() => {
showIdleWarning.value = true
}, IDLE_TIMEOUT_MS - WARNING_BEFORE_MS)
idleTimer = setTimeout(() => {
showIdleWarning.value = false
ElMessage.warning('登录已超时,请重新登录')
auth.logout()
router.push({ name: 'login' })
}, IDLE_TIMEOUT_MS)
}
function onUserActivity() {
resetIdleTimer()
}
onMounted(() => {
window.addEventListener('mousemove', onUserActivity)
window.addEventListener('keydown', onUserActivity)
window.addEventListener('click', onUserActivity)
resetIdleTimer()
})
onUnmounted(() => {
window.removeEventListener('mousemove', onUserActivity)
window.removeEventListener('keydown', onUserActivity)
window.removeEventListener('click', onUserActivity)
if (idleTimer) clearTimeout(idleTimer)
if (warningTimer) clearTimeout(warningTimer)
})
const menuItems = [
{ path: "/", icon: "📊", label: "首页", roles: ["SYS_ADMIN","DEVELOPER","OPS"] },
{ path: "/customers", icon: "👥", label: "客户管理", roles: ["SYS_ADMIN","DEVELOPER"] },