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