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.
- package/README.md +2 -29
- package/dist/user-behavior-monitor.common.js +311 -120
- package/dist/user-behavior-monitor.common.js.map +1 -1
- package/dist/user-behavior-monitor.umd.js +311 -120
- package/dist/user-behavior-monitor.umd.js.map +1 -1
- package/dist/user-behavior-monitor.umd.min.js +1 -1
- package/dist/user-behavior-monitor.umd.min.js.map +1 -1
- package/package.json +3 -2
- package/src/components/UserBehaviorMonitor.vue +293 -115
- package/src/components/{UserBehaviorMonitor1.vue → UserBehaviorMonitor2.vue} +130 -60
|
@@ -168,6 +168,17 @@ function toComment(sourceMap) {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
/***/ }),
|
|
172
|
+
|
|
173
|
+
/***/ "3505":
|
|
174
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
175
|
+
|
|
176
|
+
"use strict";
|
|
177
|
+
/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_4f34cec0_prod_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("f079");
|
|
178
|
+
/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_4f34cec0_prod_lang_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_4f34cec0_prod_lang_css__WEBPACK_IMPORTED_MODULE_0__);
|
|
179
|
+
/* unused harmony reexport * */
|
|
180
|
+
|
|
181
|
+
|
|
171
182
|
/***/ }),
|
|
172
183
|
|
|
173
184
|
/***/ "499e":
|
|
@@ -436,18 +447,7 @@ function applyToTag (styleElement, obj) {
|
|
|
436
447
|
|
|
437
448
|
/***/ }),
|
|
438
449
|
|
|
439
|
-
/***/ "
|
|
440
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
441
|
-
|
|
442
|
-
"use strict";
|
|
443
|
-
/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_06a138e4_prod_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("d1b1");
|
|
444
|
-
/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_06a138e4_prod_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_6_oneOf_1_0_node_modules_css_loader_index_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_UserBehaviorMonitor_vue_vue_type_style_index_0_id_06a138e4_prod_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__);
|
|
445
|
-
/* unused harmony reexport * */
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
/***/ }),
|
|
449
|
-
|
|
450
|
-
/***/ "9cfc":
|
|
450
|
+
/***/ "a042":
|
|
451
451
|
/***/ (function(module, exports, __webpack_require__) {
|
|
452
452
|
|
|
453
453
|
exports = module.exports = __webpack_require__("2350")(false);
|
|
@@ -455,26 +455,26 @@ exports = module.exports = __webpack_require__("2350")(false);
|
|
|
455
455
|
|
|
456
456
|
|
|
457
457
|
// module
|
|
458
|
-
exports.push([module.i, ".
|
|
458
|
+
exports.push([module.i, ".behavior-warning-dialog.el-dialog.el-dialog--center{text-align:left}", ""]);
|
|
459
459
|
|
|
460
460
|
// exports
|
|
461
461
|
|
|
462
462
|
|
|
463
463
|
/***/ }),
|
|
464
464
|
|
|
465
|
-
/***/ "
|
|
465
|
+
/***/ "f079":
|
|
466
466
|
/***/ (function(module, exports, __webpack_require__) {
|
|
467
467
|
|
|
468
468
|
// style-loader: Adds some css to the DOM by adding a <style> tag
|
|
469
469
|
|
|
470
470
|
// load the styles
|
|
471
|
-
var content = __webpack_require__("
|
|
471
|
+
var content = __webpack_require__("a042");
|
|
472
472
|
if(content.__esModule) content = content.default;
|
|
473
473
|
if(typeof content === 'string') content = [[module.i, content, '']];
|
|
474
474
|
if(content.locals) module.exports = content.locals;
|
|
475
475
|
// add the styles to the DOM
|
|
476
476
|
var add = __webpack_require__("499e").default
|
|
477
|
-
var update = add("
|
|
477
|
+
var update = add("1c569d63", content, true, {"sourceMap":false,"shadowMode":false});
|
|
478
478
|
|
|
479
479
|
/***/ }),
|
|
480
480
|
|
|
@@ -503,12 +503,12 @@ if (typeof window !== 'undefined') {
|
|
|
503
503
|
// Indicate to webpack that this file can be concatenated
|
|
504
504
|
/* harmony default export */ var setPublicPath = (null);
|
|
505
505
|
|
|
506
|
-
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"
|
|
507
|
-
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"behaviorMonitor",staticClass:"user-behavior-monitor"},[_c('el-dialog',{attrs:{"visible":_vm.showWarning,"show-close":false,"modal":true,"width":"30%","center":"","custom-class":"behavior-warning-dialog"
|
|
506
|
+
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"14550f6a-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/UserBehaviorMonitor.vue?vue&type=template&id=4f34cec0
|
|
507
|
+
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"behaviorMonitor",staticClass:"user-behavior-monitor"},[_c('el-dialog',{attrs:{"title":"提示","visible":_vm.showWarning,"show-close":false,"modal":true,"width":"30%","center":"","custom-class":"behavior-warning-dialog"},on:{"update:visible":function($event){_vm.showWarning=$event}}},[_c('span',[_vm._v(_vm._s(_vm.warningMessage))])])],1)}
|
|
508
508
|
var staticRenderFns = []
|
|
509
509
|
|
|
510
510
|
|
|
511
|
-
// CONCATENATED MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=template&id=
|
|
511
|
+
// CONCATENATED MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=template&id=4f34cec0
|
|
512
512
|
|
|
513
513
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/UserBehaviorMonitor.vue?vue&type=script&lang=js
|
|
514
514
|
//
|
|
@@ -528,23 +528,15 @@ var staticRenderFns = []
|
|
|
528
528
|
//
|
|
529
529
|
//
|
|
530
530
|
//
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
//
|
|
538
|
-
//
|
|
539
531
|
|
|
540
532
|
/* harmony default export */ var UserBehaviorMonitorvue_type_script_lang_js = ({
|
|
541
533
|
name: 'UserBehaviorMonitor',
|
|
542
534
|
props: {
|
|
543
535
|
// WebSocket服务器地址
|
|
544
|
-
websocketUrl: {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
},
|
|
536
|
+
// websocketUrl: {
|
|
537
|
+
// type: String,
|
|
538
|
+
// required: true
|
|
539
|
+
// },
|
|
548
540
|
// 倒计时时长(分钟)
|
|
549
541
|
timeoutMinutes: {
|
|
550
542
|
type: Number,
|
|
@@ -558,39 +550,104 @@ var staticRenderFns = []
|
|
|
558
550
|
},
|
|
559
551
|
data() {
|
|
560
552
|
return {
|
|
561
|
-
mouseMoveThrottled:false,
|
|
562
|
-
|
|
553
|
+
mouseMoveThrottled: false,
|
|
554
|
+
socket: null,
|
|
563
555
|
countdownTimer: null,
|
|
564
556
|
warningTimer: null,
|
|
565
557
|
showWarning: false,
|
|
566
|
-
|
|
558
|
+
// warningMinutes
|
|
559
|
+
warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在1分钟后自动退出`,
|
|
567
560
|
lastActivityTime: null,
|
|
568
|
-
isMonitoring: false
|
|
561
|
+
isMonitoring: false,
|
|
562
|
+
currentTimeoutMinutes: 10,
|
|
563
|
+
currentWarningMinutes: 1
|
|
569
564
|
};
|
|
570
565
|
},
|
|
571
566
|
mounted() {
|
|
572
|
-
|
|
573
|
-
this.
|
|
567
|
+
// 检查当前路由是否包含/login,如果不包含则初始化监控
|
|
568
|
+
if (!this.isLoginRoute()) {
|
|
569
|
+
this.initMonitor();
|
|
570
|
+
}
|
|
574
571
|
},
|
|
575
572
|
beforeDestroy() {
|
|
576
|
-
console.log('开始开始! beforeDestroy');
|
|
577
573
|
this.destroyMonitor();
|
|
578
574
|
},
|
|
575
|
+
watch: {
|
|
576
|
+
// 监听路由变化
|
|
577
|
+
'$route'(to, from) {
|
|
578
|
+
// 安全检查 from.href 是否存在
|
|
579
|
+
const isFromLogin = from.path.includes('/login') ||
|
|
580
|
+
(from.href && from.href.includes('/login'));
|
|
581
|
+
|
|
582
|
+
// 检查当前是否为登录路由
|
|
583
|
+
const isToLogin = this.isLoginRoute();
|
|
584
|
+
|
|
585
|
+
// 如果从登录页跳转到非登录页,且监控未启动,则初始化监控
|
|
586
|
+
if (isFromLogin && !isToLogin && !this.isMonitoring) {
|
|
587
|
+
this.initMonitor();
|
|
588
|
+
}
|
|
589
|
+
// 如果从非登录页跳转到登录页,且监控正在运行,则销毁监控
|
|
590
|
+
else if (!isFromLogin && isToLogin && this.isMonitoring) {
|
|
591
|
+
this.destroyMonitor();
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
},
|
|
579
595
|
methods: {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
596
|
+
// 检查当前路由是否为登录页面
|
|
597
|
+
isLoginRoute() {
|
|
598
|
+
// 优先检查 Vue Router 路由
|
|
599
|
+
if (this.$route && this.$route.path) {
|
|
600
|
+
if (this.$route.path.includes('/login')) {
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// 检查浏览器地址栏作为后备
|
|
606
|
+
if (typeof window !== 'undefined') {
|
|
607
|
+
return window.location.pathname.includes('/login') ||
|
|
608
|
+
window.location.href.includes('/login');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
return false;
|
|
612
|
+
},
|
|
613
|
+
|
|
614
|
+
updateTimeoutSettings(timeoutMinutes, warningMinutes) {
|
|
615
|
+
if (timeoutMinutes !== undefined) {
|
|
616
|
+
this.currentTimeoutMinutes = timeoutMinutes;
|
|
617
|
+
localStorage.setItem('userBehavior_timeoutMinutes', timeoutMinutes.toString());
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (warningMinutes !== undefined) {
|
|
621
|
+
this.currentWarningMinutes = warningMinutes;
|
|
622
|
+
localStorage.setItem('userBehavior_warningMinutes', warningMinutes.toString());
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// 更新警告消息
|
|
626
|
+
// ${this.currentWarningMinutes}
|
|
627
|
+
this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在1分钟后自动退出`;
|
|
628
|
+
|
|
629
|
+
// 重置计时器
|
|
630
|
+
this.resetTimer();
|
|
583
631
|
},
|
|
584
632
|
// 初始化监控
|
|
585
633
|
initMonitor() {
|
|
586
|
-
|
|
634
|
+
// 再次检查确保不在登录页面
|
|
635
|
+
if (this.isLoginRoute()) {
|
|
636
|
+
// 如果在登录页面,确保清理所有监控资源
|
|
637
|
+
this.destroyMonitor();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
587
641
|
if (this.isMonitoring) return;
|
|
588
642
|
|
|
589
643
|
this.isMonitoring = true;
|
|
590
644
|
this.lastActivityTime = Date.now();
|
|
591
645
|
|
|
646
|
+
// 初始化WebSocket连接
|
|
647
|
+
this.initWebSocket();
|
|
648
|
+
|
|
592
649
|
// 启动倒计时
|
|
593
|
-
this.startCountdown();
|
|
650
|
+
// this.startCountdown();
|
|
594
651
|
|
|
595
652
|
// 绑定事件监听器
|
|
596
653
|
this.bindEventListeners();
|
|
@@ -604,71 +661,183 @@ var staticRenderFns = []
|
|
|
604
661
|
if (this.countdownTimer) clearInterval(this.countdownTimer);
|
|
605
662
|
if (this.warningTimer) clearTimeout(this.warningTimer);
|
|
606
663
|
|
|
664
|
+
// 关闭WebSocket连接
|
|
665
|
+
if (this.socket) {
|
|
666
|
+
this.socket.close();
|
|
667
|
+
this.socket = null;
|
|
668
|
+
}
|
|
669
|
+
|
|
607
670
|
// 解绑事件监听器
|
|
608
671
|
this.unbindEventListeners();
|
|
609
672
|
},
|
|
610
673
|
|
|
674
|
+
// 初始化WebSocket连接
|
|
675
|
+
initWebSocket() {
|
|
676
|
+
try {
|
|
677
|
+
// 使用传入的WebSocket URL
|
|
678
|
+
const websocketUrl = `wss://${location.host}/xy-api/auth-server/ws/user-activity`;
|
|
679
|
+
|
|
680
|
+
// 获取token(假设存储在localStorage中)
|
|
681
|
+
let token = '';
|
|
682
|
+
try {
|
|
683
|
+
const apiHeader = localStorage.getItem('api_header');
|
|
684
|
+
if (apiHeader) {
|
|
685
|
+
token = JSON.parse(apiHeader).Authorization || '';
|
|
686
|
+
}
|
|
687
|
+
} catch (e) {
|
|
688
|
+
token = localStorage.getItem('token') || '';
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// 创建WebSocket连接
|
|
692
|
+
this.socket = new WebSocket(`${websocketUrl}?token=${encodeURIComponent(token)}`);
|
|
693
|
+
|
|
694
|
+
// 设置连接成功回调
|
|
695
|
+
this.socket.onopen = () => {
|
|
696
|
+
console.log('WebSocket连接已建立');
|
|
697
|
+
this.sendUserBehavior();
|
|
698
|
+
this.$emit('websocket-open');
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
// 设置接收消息回调
|
|
702
|
+
this.socket.onmessage = (event) => {
|
|
703
|
+
try {
|
|
704
|
+
const data = JSON.parse(event.data);
|
|
705
|
+
console.log('收到用户活动状态消息:', data);
|
|
706
|
+
this.handleActivityStatus(data);
|
|
707
|
+
this.$emit('websocket-message', data);
|
|
708
|
+
} catch (e) {
|
|
709
|
+
console.error('解析WebSocket消息失败:', e);
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// 设置连接关闭回调
|
|
714
|
+
this.socket.onclose = (event) => {
|
|
715
|
+
console.log('WebSocket连接已断开:', event.reason);
|
|
716
|
+
this.$emit('websocket-close');
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
// 设置连接错误回调
|
|
720
|
+
this.socket.onerror = (error) => {
|
|
721
|
+
console.error('WebSocket错误:', error);
|
|
722
|
+
this.$emit('websocket-error', error);
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
} catch (error) {
|
|
726
|
+
console.error('WebSocket初始化失败:', error);
|
|
727
|
+
this.$emit('websocket-error', error);
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
|
|
731
|
+
// 处理活动状态信息
|
|
732
|
+
handleActivityStatus(data) {
|
|
733
|
+
if (data.type === 'ACTIVITY_STATUS' && data.data) {
|
|
734
|
+
const activityData = data.data;
|
|
735
|
+
|
|
736
|
+
// 更新超时和警告时间配置
|
|
737
|
+
this.currentTimeoutMinutes = activityData.timeoutMinutes || 10;
|
|
738
|
+
this.currentWarningMinutes = activityData.reminderMinutes || 1;
|
|
739
|
+
|
|
740
|
+
// 更新警告消息
|
|
741
|
+
this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在${this.currentWarningMinutes}分钟后自动退出`;
|
|
742
|
+
if(activityData.needReminder){
|
|
743
|
+
this.showWarningWarning(activityData.remainingMillis);
|
|
744
|
+
}
|
|
745
|
+
// remainingMillis
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
// 检查是否仍然活跃
|
|
749
|
+
//if (!activityData.isActive) {
|
|
750
|
+
//this.handleInactiveStatus();
|
|
751
|
+
//}
|
|
752
|
+
}
|
|
753
|
+
// 检查是否需要显示提醒
|
|
754
|
+
// let dataReminder=data.data;
|
|
755
|
+
// if (dataReminder&&dataReminder.needReminder) {
|
|
756
|
+
// this.showWarningWarning(dataReminder.remainingSeconds);
|
|
757
|
+
// }
|
|
758
|
+
},
|
|
759
|
+
|
|
760
|
+
// 处理非活跃状态
|
|
761
|
+
handleInactiveStatus() {
|
|
762
|
+
// 清空缓存
|
|
763
|
+
localStorage.clear();
|
|
764
|
+
sessionStorage.clear();
|
|
765
|
+
|
|
766
|
+
// 跳转到登录页
|
|
767
|
+
//this.$router.push('/login');
|
|
768
|
+
|
|
769
|
+
// 或者使用window.location
|
|
770
|
+
window.location.href = '/login';
|
|
771
|
+
|
|
772
|
+
// 触发登出事件
|
|
773
|
+
this.$emit('logout');
|
|
774
|
+
},
|
|
775
|
+
|
|
611
776
|
// 发送用户行为数据到后端
|
|
612
777
|
sendUserBehavior(data) {
|
|
613
|
-
|
|
614
|
-
|
|
778
|
+
console.log('用户行为监测:')
|
|
779
|
+
if (this.warningTimer) clearTimeout(this.warningTimer);
|
|
780
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
781
|
+
const message = {
|
|
782
|
+
"type": "HEARTBEAT",
|
|
783
|
+
"message": "心跳",
|
|
784
|
+
};
|
|
785
|
+
console.log('用户行为监测:', JSON.stringify(message));
|
|
786
|
+
this.socket.send(JSON.stringify(message));
|
|
787
|
+
}
|
|
615
788
|
},
|
|
616
789
|
|
|
617
790
|
// 绑定事件监听器
|
|
618
791
|
bindEventListeners() {
|
|
619
|
-
console.log('Binding event listeners');
|
|
620
|
-
// 使用箭头函数或bind来保持this上下文
|
|
621
792
|
// 鼠标事件
|
|
622
|
-
document.addEventListener('click', this.handleUserActivity
|
|
623
|
-
document.addEventListener('dblclick', this.handleUserActivity
|
|
624
|
-
document.addEventListener('mousedown', this.handleUserActivity
|
|
625
|
-
document.addEventListener('mouseup', this.handleUserActivity
|
|
626
|
-
document.addEventListener('mousemove', this.handleMouseMove
|
|
627
|
-
document.addEventListener('mouseover', this.handleUserActivity
|
|
628
|
-
document.addEventListener('mouseout', this.handleUserActivity
|
|
793
|
+
document.addEventListener('click', this.handleUserActivity, true);
|
|
794
|
+
document.addEventListener('dblclick', this.handleUserActivity, true);
|
|
795
|
+
document.addEventListener('mousedown', this.handleUserActivity, true);
|
|
796
|
+
document.addEventListener('mouseup', this.handleUserActivity, true);
|
|
797
|
+
document.addEventListener('mousemove', this.handleMouseMove, true);
|
|
798
|
+
document.addEventListener('mouseover', this.handleUserActivity, true);
|
|
799
|
+
document.addEventListener('mouseout', this.handleUserActivity, true);
|
|
629
800
|
|
|
630
801
|
// 键盘事件
|
|
631
|
-
document.addEventListener('keydown', this.handleUserActivity
|
|
632
|
-
document.addEventListener('keyup', this.handleUserActivity
|
|
802
|
+
document.addEventListener('keydown', this.handleUserActivity, true);
|
|
803
|
+
document.addEventListener('keyup', this.handleUserActivity, true);
|
|
633
804
|
|
|
634
805
|
// 表单事件
|
|
635
|
-
document.addEventListener('input', this.handleUserActivity
|
|
636
|
-
document.addEventListener('change', this.handleUserActivity
|
|
637
|
-
document.addEventListener('focus', this.handleUserActivity
|
|
638
|
-
document.addEventListener('blur', this.handleUserActivity
|
|
806
|
+
document.addEventListener('input', this.handleUserActivity, true);
|
|
807
|
+
document.addEventListener('change', this.handleUserActivity, true);
|
|
808
|
+
document.addEventListener('focus', this.handleUserActivity, true);
|
|
809
|
+
document.addEventListener('blur', this.handleUserActivity, true);
|
|
639
810
|
|
|
640
811
|
// 滚动事件(防抖处理)
|
|
641
|
-
document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300)
|
|
812
|
+
document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300), true);
|
|
642
813
|
|
|
643
814
|
// 窗口事件
|
|
644
|
-
window.addEventListener('resize', this.handleUserActivity
|
|
645
|
-
window.addEventListener('beforeunload', this.handleBeforeUnload
|
|
815
|
+
window.addEventListener('resize', this.handleUserActivity, true);
|
|
816
|
+
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
646
817
|
},
|
|
647
818
|
|
|
648
819
|
// 解绑事件监听器
|
|
649
820
|
unbindEventListeners() {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
document.removeEventListener('
|
|
653
|
-
document.removeEventListener('
|
|
654
|
-
document.removeEventListener('
|
|
655
|
-
document.removeEventListener('
|
|
656
|
-
document.removeEventListener('
|
|
657
|
-
|
|
658
|
-
document.removeEventListener('
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
document.removeEventListener('
|
|
662
|
-
|
|
663
|
-
document.removeEventListener('
|
|
664
|
-
document.removeEventListener('
|
|
665
|
-
|
|
666
|
-
document.removeEventListener('
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
window.removeEventListener('resize', this.handleUserActivity.bind(this), true);
|
|
671
|
-
window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));
|
|
821
|
+
document.removeEventListener('click', this.handleUserActivity, true);
|
|
822
|
+
document.removeEventListener('dblclick', this.handleUserActivity, true);
|
|
823
|
+
document.removeEventListener('mousedown', this.handleUserActivity, true);
|
|
824
|
+
document.removeEventListener('mouseup', this.handleUserActivity, true);
|
|
825
|
+
document.removeEventListener('mousemove', this.handleMouseMove, true);
|
|
826
|
+
document.removeEventListener('mouseover', this.handleUserActivity, true);
|
|
827
|
+
document.removeEventListener('mouseout', this.handleUserActivity, true);
|
|
828
|
+
|
|
829
|
+
document.removeEventListener('keydown', this.handleUserActivity, true);
|
|
830
|
+
document.removeEventListener('keyup', this.handleUserActivity, true);
|
|
831
|
+
|
|
832
|
+
document.removeEventListener('input', this.handleUserActivity, true);
|
|
833
|
+
document.removeEventListener('change', this.handleUserActivity, true);
|
|
834
|
+
document.removeEventListener('focus', this.handleUserActivity, true);
|
|
835
|
+
document.removeEventListener('blur', this.handleUserActivity, true);
|
|
836
|
+
|
|
837
|
+
document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300), true);
|
|
838
|
+
|
|
839
|
+
window.removeEventListener('resize', this.handleUserActivity, true);
|
|
840
|
+
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
672
841
|
},
|
|
673
842
|
|
|
674
843
|
// 处理用户活动
|
|
@@ -699,7 +868,7 @@ var staticRenderFns = []
|
|
|
699
868
|
|
|
700
869
|
this.sendUserBehavior(behaviorData);
|
|
701
870
|
},
|
|
702
|
-
|
|
871
|
+
handleMouseMove(event) {
|
|
703
872
|
if (!this.mouseMoveThrottled) {
|
|
704
873
|
this.handleUserActivity(event);
|
|
705
874
|
this.mouseMoveThrottled = true;
|
|
@@ -709,20 +878,6 @@ var staticRenderFns = []
|
|
|
709
878
|
}
|
|
710
879
|
},
|
|
711
880
|
|
|
712
|
-
// 处理鼠标移动(降低频率)
|
|
713
|
-
// handleMouseMove: function() {
|
|
714
|
-
// let isThrottled = false;
|
|
715
|
-
// return (event) => {
|
|
716
|
-
// if (!isThrottled) {
|
|
717
|
-
// this.handleUserActivity(event);
|
|
718
|
-
// isThrottled = true;
|
|
719
|
-
// setTimeout(() => {
|
|
720
|
-
// isThrottled = false;
|
|
721
|
-
// }, 500);
|
|
722
|
-
// }
|
|
723
|
-
// };
|
|
724
|
-
// }(),
|
|
725
|
-
|
|
726
881
|
// 判断是否为自动触发事件
|
|
727
882
|
isAutomaticEvent(event) {
|
|
728
883
|
// 自动刷新等非用户主动触发的事件
|
|
@@ -747,7 +902,6 @@ var staticRenderFns = []
|
|
|
747
902
|
|
|
748
903
|
// 重置计时器
|
|
749
904
|
resetTimer() {
|
|
750
|
-
console.log('Resetting timer');
|
|
751
905
|
this.lastActivityTime = Date.now();
|
|
752
906
|
this.showWarning = false;
|
|
753
907
|
|
|
@@ -758,52 +912,48 @@ var staticRenderFns = []
|
|
|
758
912
|
}
|
|
759
913
|
|
|
760
914
|
// 重新启动倒计时
|
|
761
|
-
this.startCountdown();
|
|
915
|
+
// this.startCountdown();
|
|
762
916
|
|
|
763
917
|
this.$emit('user-active');
|
|
764
918
|
},
|
|
765
919
|
|
|
766
920
|
// 启动倒计时
|
|
767
921
|
startCountdown() {
|
|
768
|
-
console.log('Starting countdown');
|
|
769
922
|
// 清除现有定时器
|
|
770
923
|
if (this.countdownTimer) clearInterval(this.countdownTimer);
|
|
771
924
|
|
|
772
925
|
// 设置新的倒计时
|
|
773
926
|
this.countdownTimer = setInterval(() => {
|
|
774
927
|
const now = Date.now();
|
|
775
|
-
const elapsedMinutes = (now - this.lastActivityTime) / (1000 *
|
|
776
|
-
console.log('Elapsed minutes:', elapsedMinutes);
|
|
928
|
+
const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 50);
|
|
777
929
|
|
|
778
930
|
// 检查是否需要显示警告
|
|
779
|
-
if (elapsedMinutes >= (this.
|
|
780
|
-
console.log('Showing warning');
|
|
931
|
+
if (elapsedMinutes >= (this.currentTimeoutMinutes - this.currentWarningMinutes) && !this.warningTimer) {
|
|
781
932
|
this.showWarningWarning();
|
|
782
933
|
}
|
|
783
934
|
|
|
784
935
|
// 检查是否超时
|
|
785
|
-
if (elapsedMinutes >= this.
|
|
786
|
-
console.log('Handling timeout');
|
|
936
|
+
if (elapsedMinutes >= this.currentTimeoutMinutes) {
|
|
787
937
|
this.handleTimeout();
|
|
788
938
|
}
|
|
789
939
|
}, 1000);
|
|
790
940
|
},
|
|
791
941
|
|
|
792
942
|
// 显示超时警告
|
|
793
|
-
showWarningWarning() {
|
|
943
|
+
showWarningWarning(timeoutMinutes) {
|
|
944
|
+
let time=timeoutMinutes||50;
|
|
794
945
|
console.log('Setting showWarning to true');
|
|
795
946
|
this.showWarning = true;
|
|
796
947
|
this.$emit('timeout-warning');
|
|
797
|
-
|
|
948
|
+
if (this.warningTimer) clearTimeout(this.warningTimer);
|
|
798
949
|
// 设置超时处理
|
|
799
950
|
this.warningTimer = setTimeout(() => {
|
|
800
951
|
this.handleTimeout();
|
|
801
|
-
},
|
|
952
|
+
}, 1 * time * 1000);
|
|
802
953
|
},
|
|
803
954
|
|
|
804
955
|
// 处理超时
|
|
805
956
|
handleTimeout() {
|
|
806
|
-
console.log('Handling timeout');
|
|
807
957
|
this.showWarning = false;
|
|
808
958
|
this.$emit('timeout');
|
|
809
959
|
|
|
@@ -813,9 +963,24 @@ var staticRenderFns = []
|
|
|
813
963
|
|
|
814
964
|
// 登出操作
|
|
815
965
|
logout() {
|
|
816
|
-
|
|
817
|
-
|
|
966
|
+
localStorage.clear();
|
|
967
|
+
sessionStorage.clear();
|
|
968
|
+
location.reload();
|
|
969
|
+
// 跳转到登录页
|
|
970
|
+
//this.$router.push('/login');
|
|
818
971
|
|
|
972
|
+
// 或者使用window.location
|
|
973
|
+
// window.location.href = '/login';
|
|
974
|
+
// 发送登出消息到后端
|
|
975
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
976
|
+
const message = {
|
|
977
|
+
type: 'logout',
|
|
978
|
+
timestamp: Date.now()
|
|
979
|
+
};
|
|
980
|
+
this.socket.send(JSON.stringify(message));
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// 触发登出事件
|
|
819
984
|
this.$emit('logout');
|
|
820
985
|
|
|
821
986
|
// 清除定时器
|
|
@@ -825,21 +990,47 @@ var staticRenderFns = []
|
|
|
825
990
|
|
|
826
991
|
// 处理页面卸载前的操作
|
|
827
992
|
handleBeforeUnload(event) {
|
|
828
|
-
//
|
|
829
|
-
|
|
993
|
+
// 发送页面关闭消息
|
|
994
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
995
|
+
const message = {
|
|
996
|
+
type: 'page_unload',
|
|
997
|
+
timestamp: Date.now()
|
|
998
|
+
};
|
|
999
|
+
this.socket.send(JSON.stringify(message));
|
|
1000
|
+
}
|
|
830
1001
|
},
|
|
831
1002
|
|
|
832
1003
|
// 手动重置监控
|
|
833
1004
|
reset() {
|
|
1005
|
+
// 检查当前路由,如果在登录页面则销毁监控
|
|
1006
|
+
if (this.isLoginRoute()) {
|
|
1007
|
+
this.destroyMonitor();
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
834
1011
|
this.resetTimer();
|
|
1012
|
+
},
|
|
1013
|
+
|
|
1014
|
+
// 重新连接WebSocket
|
|
1015
|
+
reconnect() {
|
|
1016
|
+
// 检查当前路由,如果在登录页面则销毁监控
|
|
1017
|
+
if (this.isLoginRoute()) {
|
|
1018
|
+
this.destroyMonitor();
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
if (this.socket) {
|
|
1023
|
+
this.socket.close();
|
|
1024
|
+
}
|
|
1025
|
+
this.initWebSocket();
|
|
835
1026
|
}
|
|
836
1027
|
}
|
|
837
1028
|
});
|
|
838
1029
|
|
|
839
1030
|
// CONCATENATED MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=script&lang=js
|
|
840
1031
|
/* harmony default export */ var components_UserBehaviorMonitorvue_type_script_lang_js = (UserBehaviorMonitorvue_type_script_lang_js);
|
|
841
|
-
// EXTERNAL MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=style&index=0&id=
|
|
842
|
-
var
|
|
1032
|
+
// EXTERNAL MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=style&index=0&id=4f34cec0&prod&lang=css
|
|
1033
|
+
var UserBehaviorMonitorvue_type_style_index_0_id_4f34cec0_prod_lang_css = __webpack_require__("3505");
|
|
843
1034
|
|
|
844
1035
|
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
|
|
845
1036
|
/* globals __VUE_SSR_CONTEXT__ */
|
|
@@ -954,7 +1145,7 @@ var component = normalizeComponent(
|
|
|
954
1145
|
staticRenderFns,
|
|
955
1146
|
false,
|
|
956
1147
|
null,
|
|
957
|
-
|
|
1148
|
+
null,
|
|
958
1149
|
null
|
|
959
1150
|
|
|
960
1151
|
)
|