export class InactivityTimer { constructor(options = {}) { this.defaults = { timeout: 30000, // 默认30秒超时 warningTime: 5000, // 提前5秒警告 onTimeout: () => console.log('Timeout callback'), onWarning: () => console.log('Warning callback'), onReset: () => {}, onStart: () => {}, onStop: () => {} }; this.config = { ...this.defaults, ...options }; this.timer = null; this.timeLeft = this.config.timeout; this.isRunning = false; this.isPaused = false; this.warningTriggered = false; this.startTime = null; this.pageVisible = true; this.init(); } init() { document.addEventListener('visibilitychange', () => this.handleVisibilityChange()); this.setupActivityListeners(); } setupActivityListeners() { ['mousemove', 'keydown', 'click', 'scroll', 'touchstart'].forEach(event => { document.addEventListener(event, () => this.handleUserActivity()); }); } handleUserActivity() { if (this.isRunning && !this.isPaused) { this.resetTimer(); } } handleVisibilityChange() { this.pageVisible = document.visibilityState === 'visible'; if (this.pageVisible && this.isRunning && this.isPaused) { this.isPaused = false; this.startTime = Date.now() - (this.config.timeout - this.timeLeft); this.startTimer(); } else if (!this.pageVisible && this.isRunning && !this.isPaused) { this.isPaused = true; this.clearTimer(); } } start() { if (this.isRunning) return; this.isRunning = true; this.isPaused = false; this.warningTriggered = false; this.startTime = Date.now(); this.timeLeft = this.config.timeout; this.config.onStart(); this.startTimer(); } startTimer() { this.clearTimer(); this.timer = setInterval(() => { if (!this.isPaused) { const elapsed = Date.now() - this.startTime; this.timeLeft = this.config.timeout - elapsed; if (this.timeLeft <= 0) { this.clearTimer(); this.isRunning = false; this.timeLeft = 0; this.config.onTimeout(); } else if (this.timeLeft <= this.config.warningTime && !this.warningTriggered) { this.warningTriggered = true; this.config.onWarning(); } } }, 100); } resetTimer() { this.startTime = Date.now(); this.timeLeft = this.config.timeout; this.warningTriggered = false; this.config.onReset(); } reset() { if (!this.isRunning) return; this.resetTimer(); } stop() { if (!this.isRunning) return; this.clearTimer(); this.isRunning = false; this.isPaused = false; this.timeLeft = this.config.timeout; this.warningTriggered = false; this.config.onStop(); } clearTimer() { if (this.timer) { clearInterval(this.timer); this.timer = null; } } }