user-behavior-monitor 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,8 @@
15
15
  </template>
16
16
 
17
17
  <script>
18
+ import { io } from "socket.io-client";
19
+
18
20
  export default {
19
21
  name: 'UserBehaviorMonitor',
20
22
  props: {
@@ -36,14 +38,16 @@ export default {
36
38
  },
37
39
  data() {
38
40
  return {
39
- mouseMoveThrottled:false,
40
- websocket: null,
41
+ mouseMoveThrottled: false,
42
+ socket: null,
41
43
  countdownTimer: null,
42
44
  warningTimer: null,
43
45
  showWarning: false,
44
46
  warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,
45
47
  lastActivityTime: null,
46
- isMonitoring: false
48
+ isMonitoring: false,
49
+ currentTimeoutMinutes: 10,
50
+ currentWarningMinutes: 1
47
51
  };
48
52
  },
49
53
  mounted() {
@@ -55,17 +59,17 @@ export default {
55
59
  methods: {
56
60
  updateTimeoutSettings(timeoutMinutes, warningMinutes) {
57
61
  if (timeoutMinutes !== undefined) {
58
- this.timeoutMinutes = timeoutMinutes;
62
+ this.currentTimeoutMinutes = timeoutMinutes;
59
63
  localStorage.setItem('userBehavior_timeoutMinutes', timeoutMinutes.toString());
60
64
  }
61
65
 
62
66
  if (warningMinutes !== undefined) {
63
- this.warningMinutes = warningMinutes;
67
+ this.currentWarningMinutes = warningMinutes;
64
68
  localStorage.setItem('userBehavior_warningMinutes', warningMinutes.toString());
65
69
  }
66
70
 
67
71
  // 更新警告消息
68
- this.warningMessage = `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`;
72
+ this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在${this.currentWarningMinutes}分钟后自动退出`;
69
73
 
70
74
  // 重置计时器
71
75
  this.resetTimer();
@@ -77,8 +81,8 @@ export default {
77
81
  this.isMonitoring = true;
78
82
  this.lastActivityTime = Date.now();
79
83
 
80
- // 初始化WebSocket连接
81
- this.initWebSocket();
84
+ // 初始化Socket.IO连接
85
+ this.initSocketIO();
82
86
 
83
87
  // 启动倒计时
84
88
  this.startCountdown();
@@ -95,56 +99,136 @@ export default {
95
99
  if (this.countdownTimer) clearInterval(this.countdownTimer);
96
100
  if (this.warningTimer) clearTimeout(this.warningTimer);
97
101
 
98
- // 关闭WebSocket连接
99
- if (this.websocket) {
100
- this.websocket.close();
101
- this.websocket = null;
102
+ // 关闭Socket.IO连接
103
+ if (this.socket) {
104
+ this.socket.disconnect();
105
+ this.socket = null;
102
106
  }
103
107
 
104
108
  // 解绑事件监听器
105
109
  this.unbindEventListeners();
106
110
  },
107
111
 
108
- // 初始化WebSocket连接
109
- initWebSocket() {
112
+ // 初始化Socket.IO连接
113
+ // 初始化Socket.IO连接
114
+ initSocketIO() {
110
115
  try {
111
- this.websocket = new WebSocket(this.websocketUrl);
116
+ // 使用正确的WebSocket URL和路径配置
117
+ const websocketUrl = 'http://100.150.0.4:30612';
118
+
119
+ // 从localStorage获取timeoutMinutes,如果没有默认为10
120
+ const storedTimeoutMinutes = localStorage.getItem('timeoutMinutes') || 10;
121
+
122
+ // 获取token(假设存储在localStorage中)
123
+ let token = '';
124
+ try {
125
+ const apiHeader = localStorage.getItem('api_header');
126
+ if (apiHeader) {
127
+ token = JSON.parse(apiHeader).Authorization || '';
128
+ }
129
+ } catch (e) {
130
+ token = localStorage.getItem('token') || '';
131
+ }
112
132
 
113
- this.websocket.onopen = () => {
114
- console.log('WebSocket连接已建立');
133
+ // 创建Socket.IO连接,添加自定义headers
134
+ this.socket = io(websocketUrl, {
135
+ transports: ['websocket'],
136
+ path: '/ws/user-activity', // 指定正确的路径
137
+ extraHeaders: {
138
+ 'Authorization': token
139
+ },
140
+ query: {
141
+ timeoutMinutes: storedTimeoutMinutes
142
+ },
143
+ reconnection: true,
144
+ reconnectionAttempts: 5,
145
+ reconnectionDelay: 1000,
146
+ timeout: 20000
147
+ });
148
+
149
+ this.socket.on('connect', () => {
150
+ console.log('Socket.IO连接已建立', this.socket.id);
115
151
  this.$emit('websocket-open');
116
- };
152
+ });
117
153
 
118
- this.websocket.onmessage = (event) => {
119
- console.log('收到WebSocket消息:', event.data);
120
- this.$emit('websocket-message', event.data);
121
- };
154
+ this.socket.on('disconnect', (reason) => {
155
+ console.log('Socket.IO连接已断开:', reason);
156
+ this.$emit('websocket-close');
157
+ });
122
158
 
123
- this.websocket.onerror = (error) => {
124
- console.error('WebSocket错误:', error);
159
+ // 处理后端返回的活动状态信息
160
+ this.socket.on('success', (data) => {
161
+ console.log('收到用户活动状态消息:', data);
162
+ this.handleActivityStatus(data);
163
+ this.$emit('websocket-message', data);
164
+ });
165
+
166
+ this.socket.on('connect_error', (error) => {
167
+ console.error('Socket.IO连接错误:', error);
125
168
  this.$emit('websocket-error', error);
126
- };
169
+ });
170
+
171
+ this.socket.on('error', (error) => {
172
+ console.error('Socket.IO错误:', error);
173
+ this.$emit('websocket-error', error);
174
+ });
127
175
 
128
- this.websocket.onclose = () => {
129
- console.log('WebSocket连接已关闭');
130
- this.$emit('websocket-close');
131
- };
132
176
  } catch (error) {
133
- console.error('WebSocket初始化失败:', error);
177
+ console.error('Socket.IO初始化失败:', error);
134
178
  this.$emit('websocket-error', error);
135
179
  }
136
180
  },
137
181
 
182
+ // 处理活动状态信息
183
+ handleActivityStatus(data) {
184
+ if (data.type === 'ACTIVITY_STATUS' && data.data) {
185
+ const activityData = data.data;
186
+
187
+ // 更新超时和警告时间配置
188
+ this.currentTimeoutMinutes = activityData.timeoutMinutes || 10;
189
+ this.currentWarningMinutes = activityData.reminderMinutes || 1;
190
+
191
+ // 更新警告消息
192
+ this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在${this.currentWarningMinutes}分钟后自动退出`;
193
+
194
+ // 检查是否需要显示提醒
195
+ if (activityData.needReminder) {
196
+ this.showWarningWarning();
197
+ }
198
+
199
+ // 检查是否仍然活跃
200
+ if (!activityData.isActive) {
201
+ this.handleInactiveStatus();
202
+ }
203
+ }
204
+ },
205
+
206
+ // 处理非活跃状态
207
+ handleInactiveStatus() {
208
+ // 清空缓存
209
+ localStorage.clear();
210
+ sessionStorage.clear();
211
+
212
+ // 跳转到登录页
213
+ this.$router.push('/login');
214
+
215
+ // 或者使用window.location
216
+ // window.location.href = '/login';
217
+
218
+ // 触发登出事件
219
+ this.$emit('logout');
220
+ },
221
+
138
222
  // 发送用户行为数据到后端
139
223
  sendUserBehavior(data) {
140
- if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
224
+ console.log('用户行为监测:')
225
+ if (this.socket && this.socket.connected) {
141
226
  const message = {
142
- type: 'user_behavior',
143
- timestamp: Date.now(),
144
- data: data
227
+ "type": "HEARTBEAT",
228
+ "message": "心跳"
145
229
  };
146
230
  console.log('用户行为监测:', JSON.stringify(message));
147
- this.websocket.send(JSON.stringify(message));
231
+ this.socket.emit('user_behavior', message);
148
232
  }
149
233
  },
150
234
 
@@ -239,20 +323,6 @@ export default {
239
323
  }
240
324
  },
241
325
 
242
- // 处理鼠标移动(降低频率)
243
- // handleMouseMove: function() {
244
- // let isThrottled = false;
245
- // return (event) => {
246
- // if (!isThrottled) {
247
- // this.handleUserActivity(event);
248
- // isThrottled = true;
249
- // setTimeout(() => {
250
- // isThrottled = false;
251
- // }, 500);
252
- // }
253
- // };
254
- // }(),
255
-
256
326
  // 判断是否为自动触发事件
257
327
  isAutomaticEvent(event) {
258
328
  // 自动刷新等非用户主动触发的事件
@@ -303,12 +373,12 @@ export default {
303
373
  const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 60);
304
374
 
305
375
  // 检查是否需要显示警告
306
- if (elapsedMinutes >= (this.timeoutMinutes - this.warningMinutes) && !this.warningTimer) {
376
+ if (elapsedMinutes >= (this.currentTimeoutMinutes - this.currentWarningMinutes) && !this.warningTimer) {
307
377
  this.showWarningWarning();
308
378
  }
309
379
 
310
380
  // 检查是否超时
311
- if (elapsedMinutes >= this.timeoutMinutes) {
381
+ if (elapsedMinutes >= this.currentTimeoutMinutes) {
312
382
  this.handleTimeout();
313
383
  }
314
384
  }, 1000);
@@ -322,7 +392,7 @@ export default {
322
392
  // 设置超时处理
323
393
  this.warningTimer = setTimeout(() => {
324
394
  this.handleTimeout();
325
- }, this.warningMinutes * 60 * 1000);
395
+ }, this.currentWarningMinutes * 60 * 1000);
326
396
  },
327
397
 
328
398
  // 处理超时
@@ -337,12 +407,12 @@ export default {
337
407
  // 登出操作
338
408
  logout() {
339
409
  // 发送登出消息到后端
340
- if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
410
+ if (this.socket && this.socket.connected) {
341
411
  const message = {
342
412
  type: 'logout',
343
413
  timestamp: Date.now()
344
414
  };
345
- this.websocket.send(JSON.stringify(message));
415
+ this.socket.emit('logout', message);
346
416
  }
347
417
 
348
418
  // 触发登出事件
@@ -356,12 +426,12 @@ export default {
356
426
  // 处理页面卸载前的操作
357
427
  handleBeforeUnload(event) {
358
428
  // 发送页面关闭消息
359
- if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
429
+ if (this.socket && this.socket.connected) {
360
430
  const message = {
361
431
  type: 'page_unload',
362
432
  timestamp: Date.now()
363
433
  };
364
- this.websocket.send(JSON.stringify(message));
434
+ this.socket.emit('page_unload', message);
365
435
  }
366
436
  },
367
437
 
@@ -370,12 +440,12 @@ export default {
370
440
  this.resetTimer();
371
441
  },
372
442
 
373
- // 重新连接WebSocket
443
+ // 重新连接Socket.IO
374
444
  reconnect() {
375
- if (this.websocket) {
376
- this.websocket.close();
445
+ if (this.socket) {
446
+ this.socket.disconnect();
377
447
  }
378
- this.initWebSocket();
448
+ this.initSocketIO();
379
449
  }
380
450
  }
381
451
  };