user-behavior-monitor 1.0.0 → 4.0.1

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.
@@ -96,6 +96,22 @@ return /******/ (function(modules) { // webpackBootstrap
96
96
  /************************************************************************/
97
97
  /******/ ({
98
98
 
99
+ /***/ "0c60":
100
+ /***/ (function(module, exports, __webpack_require__) {
101
+
102
+ // style-loader: Adds some css to the DOM by adding a <style> tag
103
+
104
+ // load the styles
105
+ var content = __webpack_require__("d167");
106
+ if(content.__esModule) content = content.default;
107
+ if(typeof content === 'string') content = [[module.i, content, '']];
108
+ if(content.locals) module.exports = content.locals;
109
+ // add the styles to the DOM
110
+ var add = __webpack_require__("499e").default
111
+ var update = add("9677a646", content, true, {"sourceMap":false,"shadowMode":false});
112
+
113
+ /***/ }),
114
+
99
115
  /***/ "2350":
100
116
  /***/ (function(module, exports) {
101
117
 
@@ -445,18 +461,7 @@ function applyToTag (styleElement, obj) {
445
461
 
446
462
  /***/ }),
447
463
 
448
- /***/ "533e":
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":
464
+ /***/ "d167":
460
465
  /***/ (function(module, exports, __webpack_require__) {
461
466
 
462
467
  exports = module.exports = __webpack_require__("2350")(false);
@@ -464,26 +469,21 @@ exports = module.exports = __webpack_require__("2350")(false);
464
469
 
465
470
 
466
471
  // module
467
- exports.push([module.i, ".user-behavior-monitor[data-v-06a138e4]{display:none}.behavior-warning-dialog[data-v-06a138e4] .el-dialog__body{text-align:center;font-size:16px;padding:30px 20px}.behavior-warning-dialog[data-v-06a138e4]{z-index:9999!important}", ""]);
472
+ exports.push([module.i, ".behavior-warning-dialog.el-dialog.el-dialog--center{text-align:left}", ""]);
468
473
 
469
474
  // exports
470
475
 
471
476
 
472
477
  /***/ }),
473
478
 
474
- /***/ "d1b1":
475
- /***/ (function(module, exports, __webpack_require__) {
479
+ /***/ "d1a8":
480
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
476
481
 
477
- // style-loader: Adds some css to the DOM by adding a <style> tag
482
+ "use strict";
483
+ /* 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_0335f60c_prod_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("0c60");
484
+ /* 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_0335f60c_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_0335f60c_prod_lang_css__WEBPACK_IMPORTED_MODULE_0__);
485
+ /* unused harmony reexport * */
478
486
 
479
- // load the styles
480
- var content = __webpack_require__("9cfc");
481
- if(content.__esModule) content = content.default;
482
- if(typeof content === 'string') content = [[module.i, content, '']];
483
- if(content.locals) module.exports = content.locals;
484
- // add the styles to the DOM
485
- var add = __webpack_require__("499e").default
486
- var update = add("2c53b590", 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":"7caff2c6-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=06a138e4&scoped=true
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","append-to-body":true,"modal-append-to-body":true,"close-on-click-modal":false,"close-on-press-escape":false},on:{"update:visible":function($event){_vm.showWarning=$event}}},[_c('span',[_vm._v(_vm._s(_vm.warningMessage))])]),_c('button',{staticStyle:{"position":"fixed","top":"10px","right":"10px","z-index":"10000"},on:{"click":_vm.testWarning}},[_vm._v("\n 测试警告\n ")])],1)}
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=0335f60c
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=06a138e4&scoped=true
520
+ // CONCATENATED MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=template&id=0335f60c
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
- type: String,
555
- required: true
556
- },
545
+ // websocketUrl: {
546
+ // type: String,
547
+ // required: true
548
+ // },
557
549
  // 倒计时时长(分钟)
558
550
  timeoutMinutes: {
559
551
  type: Number,
@@ -567,39 +559,123 @@ var staticRenderFns = []
567
559
  },
568
560
  data() {
569
561
  return {
570
- mouseMoveThrottled:false,
571
- websocket: null,
562
+ mouseMoveThrottled: false,
563
+ socket: null,
572
564
  countdownTimer: null,
573
565
  warningTimer: null,
574
566
  showWarning: false,
575
- warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,
567
+ // warningMinutes
568
+ warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在1分钟后自动退出`,
576
569
  lastActivityTime: null,
577
- isMonitoring: false
570
+ isMonitoring: false,
571
+ currentTimeoutMinutes: 10,
572
+ currentWarningMinutes: 1,
573
+ reconnectAttempts: 0,
574
+ maxReconnectAttempts: 3,
575
+ reconnectDelay: 3000,
576
+ isLocalDevelopment: this.checkIfLocalDevelopment()
578
577
  };
579
578
  },
580
579
  mounted() {
581
- console.log('开始开始! mounted');
582
- this.initMonitor();
580
+ // 检查当前路由是否包含/login,如果不包含则初始化监控
581
+ if (!this.isLoginRoute()) {
582
+ this.initMonitor();
583
+ }
583
584
  },
584
585
  beforeDestroy() {
585
- console.log('开始开始! beforeDestroy');
586
586
  this.destroyMonitor();
587
587
  },
588
+ watch: {
589
+ // 监听路由变化
590
+ '$route'(to, from) {
591
+ // 安全检查 from.href 是否存在
592
+ const isFromLogin = from.path.includes('/login') ||
593
+ (from.href && from.href.includes('/login'));
594
+
595
+ // 检查当前是否为登录路由
596
+ const isToLogin = this.isLoginRoute();
597
+
598
+ // 如果从登录页跳转到非登录页,且监控未启动,则初始化监控
599
+ if (isFromLogin && !isToLogin && !this.isMonitoring) {
600
+ this.initMonitor();
601
+ }
602
+ // 如果从非登录页跳转到登录页,且监控正在运行,则销毁监控
603
+ else if (!isFromLogin && isToLogin && this.isMonitoring) {
604
+ this.destroyMonitor();
605
+ }
606
+ }
607
+ },
588
608
  methods: {
589
- testWarning() {
590
- console.log('Testing warning display');
591
- this.showWarning = true;
609
+ // 检查当前路由是否为登录页面
610
+ isLoginRoute() {
611
+ // 优先检查 Vue Router 路由
612
+ if (this.$route && this.$route.path) {
613
+ if (this.$route.path.includes('/login')) {
614
+ return true;
615
+ }
616
+ }
617
+
618
+ // 检查浏览器地址栏作为后备
619
+ if (typeof window !== 'undefined') {
620
+ return window.location.pathname.includes('/login') ||
621
+ window.location.href.includes('/login');
622
+ }
623
+
624
+ return false;
625
+ },
626
+
627
+ // 检查是否为本地开发环境
628
+ checkIfLocalDevelopment() {
629
+ if (typeof window !== 'undefined') {
630
+ const hostname = window.location.hostname;
631
+ return hostname === 'localhost' ||
632
+ hostname === '127.0.0.1' ||
633
+ hostname === '0.0.0.0' ||
634
+ /^192\.168\./.test(hostname) || // 局域网IP
635
+ /^10\./.test(hostname) || // 局域网IP
636
+ /^172\.(1[6-9]|2[0-9]|3[01])\./.test(hostname); // 局域网IP
637
+ }
638
+ return false;
639
+ },
640
+
641
+ updateTimeoutSettings(timeoutMinutes, warningMinutes) {
642
+ if (timeoutMinutes !== undefined) {
643
+ this.currentTimeoutMinutes = timeoutMinutes;
644
+ localStorage.setItem('userBehavior_timeoutMinutes', timeoutMinutes.toString());
645
+ }
646
+
647
+ if (warningMinutes !== undefined) {
648
+ this.currentWarningMinutes = warningMinutes;
649
+ localStorage.setItem('userBehavior_warningMinutes', warningMinutes.toString());
650
+ }
651
+
652
+ // 更新警告消息
653
+ // ${this.currentWarningMinutes}
654
+ this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在1分钟后自动退出`;
655
+
656
+ // 重置计时器
657
+ this.resetTimer();
592
658
  },
593
659
  // 初始化监控
594
660
  initMonitor() {
595
- console.log('Initializing monitor');
661
+ // 再次检查确保不在登录页面
662
+ if (this.isLoginRoute()) {
663
+ // 如果在登录页面,确保清理所有监控资源
664
+ this.destroyMonitor();
665
+ return;
666
+ }
667
+
596
668
  if (this.isMonitoring) return;
597
669
 
598
670
  this.isMonitoring = true;
599
671
  this.lastActivityTime = Date.now();
672
+ this.reconnectAttempts = 0; // 重置重连尝试次数
673
+
674
+ // 初始化WebSocket连接
675
+ this.initWebSocket();
600
676
 
601
677
  // 启动倒计时
602
- this.startCountdown();
678
+ // this.startCountdown();
603
679
 
604
680
  // 绑定事件监听器
605
681
  this.bindEventListeners();
@@ -613,71 +689,263 @@ var staticRenderFns = []
613
689
  if (this.countdownTimer) clearInterval(this.countdownTimer);
614
690
  if (this.warningTimer) clearTimeout(this.warningTimer);
615
691
 
692
+ // 关闭WebSocket连接
693
+ if (this.socket) {
694
+ this.socket.close();
695
+ this.socket = null;
696
+ }
697
+
616
698
  // 解绑事件监听器
617
699
  this.unbindEventListeners();
618
700
  },
619
701
 
702
+ // 初始化WebSocket连接
703
+ initWebSocket() {
704
+ try {
705
+ // 使用传入的WebSocket URL
706
+ const websocketUrl = `wss://${location.host}/xy-api/auth-server/ws/user-activity`;
707
+
708
+ // 获取token(假设存储在localStorage中)
709
+ let token = '';
710
+ try {
711
+ const apiHeader = localStorage.getItem('api_header');
712
+ if (apiHeader) {
713
+ token = JSON.parse(apiHeader).Authorization || '';
714
+ }
715
+ } catch (e) {
716
+ token = localStorage.getItem('token') || '';
717
+ }
718
+
719
+ // 创建WebSocket连接
720
+ this.socket = new WebSocket(`${websocketUrl}?token=${encodeURIComponent(token)}`);
721
+
722
+ // 设置连接成功回调
723
+ this.socket.onopen = () => {
724
+ console.log('WebSocket连接已建立');
725
+ this.sendUserBehavior();
726
+ this.$emit('websocket-open');
727
+ // 连接成功时重置重连尝试次数
728
+ this.reconnectAttempts = 0;
729
+ };
730
+
731
+ // 设置接收消息回调
732
+ this.socket.onmessage = (event) => {
733
+ try {
734
+ const data = JSON.parse(event.data);
735
+ console.log('收到用户活动状态消息:', data);
736
+ this.handleActivityStatus(data);
737
+ this.$emit('websocket-message', data);
738
+ } catch (e) {
739
+ console.error('解析WebSocket消息失败:', e);
740
+ }
741
+ };
742
+
743
+ // 设置连接关闭回调
744
+ this.socket.onclose = (event) => {
745
+ console.log('WebSocket连接已断开:', event.reason);
746
+ this.$emit('websocket-close');
747
+
748
+ // 如果不是在登录页面且监控仍在运行,尝试重连
749
+ if (this.shouldAttemptReconnect()) {
750
+ this.attemptReconnect();
751
+ } else if (!this.isLoginRoute() && this.isMonitoring) {
752
+ // 如果不应该重连但仍在监控状态,根据环境决定是否跳转
753
+ if (!this.isLocalDevelopment) {
754
+ this.handleReconnectFailure();
755
+ }
756
+ }
757
+ };
758
+
759
+ // 设置连接错误回调
760
+ this.socket.onerror = (error) => {
761
+ console.error('WebSocket错误:', error);
762
+ this.$emit('websocket-error', error);
763
+
764
+ // 如果不是在登录页面且监控仍在运行,尝试重连
765
+ if (this.shouldAttemptReconnect()) {
766
+ this.attemptReconnect();
767
+ } else if (!this.isLoginRoute() && this.isMonitoring) {
768
+ // 如果不应该重连但仍在监控状态,根据环境决定是否跳转
769
+ if (!this.isLocalDevelopment) {
770
+ this.handleReconnectFailure();
771
+ }
772
+ }
773
+ };
774
+
775
+ } catch (error) {
776
+ console.error('WebSocket初始化失败:', error);
777
+ this.$emit('websocket-error', error);
778
+
779
+ // 初始化失败时也可以尝试重连(如果不是在登录页面)
780
+ if (this.shouldAttemptReconnect()) {
781
+ this.attemptReconnect();
782
+ } else if (!this.isLoginRoute() && this.isMonitoring) {
783
+ // 如果不应该重连但仍在监控状态,根据环境决定是否跳转
784
+ if (!this.isLocalDevelopment) {
785
+ this.handleReconnectFailure();
786
+ }
787
+ }
788
+ }
789
+ },
790
+
791
+ // 判断是否应该尝试重连
792
+ shouldAttemptReconnect() {
793
+ return this.isMonitoring &&
794
+ !this.isLoginRoute() &&
795
+ this.reconnectAttempts < this.maxReconnectAttempts;
796
+ },
797
+
798
+ // 添加重连方法
799
+ attemptReconnect() {
800
+ // 再次检查是否为登录页面
801
+ if (this.isLoginRoute()) {
802
+ console.log('当前在登录页面,取消重连');
803
+ return;
804
+ }
805
+
806
+ this.reconnectAttempts++;
807
+ console.log(`尝试第${this.reconnectAttempts}次重连...`);
808
+
809
+ // 如果是本地开发环境且重连次数已达到最大值,则不跳转登录页
810
+ if (this.isLocalDevelopment && this.reconnectAttempts >= this.maxReconnectAttempts) {
811
+ console.log('本地开发环境,重连失败但不跳转到登录页');
812
+ this.$emit('websocket-reconnect-failed');
813
+ return;
814
+ }
815
+
816
+ // 如果是线上环境且重连次数已达到最大值,则跳转到登录页
817
+ if (!this.isLocalDevelopment && this.reconnectAttempts >= this.maxReconnectAttempts) {
818
+ console.log('线上环境,重连失败,跳转到登录页');
819
+ this.handleReconnectFailure();
820
+ return;
821
+ }
822
+
823
+ setTimeout(() => {
824
+ this.initWebSocket();
825
+ }, this.reconnectDelay);
826
+ },
827
+
828
+ // 处理重连失败
829
+ handleReconnectFailure() {
830
+ // 清空缓存
831
+ localStorage.clear();
832
+ sessionStorage.clear();
833
+
834
+ // 跳转到登录页
835
+ window.location.href = '/login';
836
+
837
+ // 触发登出事件
838
+ this.$emit('logout');
839
+ },
840
+
841
+ // 处理活动状态信息
842
+ handleActivityStatus(data) {
843
+ if (data.type === 'ACTIVITY_STATUS' && data.data) {
844
+ const activityData = data.data;
845
+
846
+ // 更新超时和警告时间配置
847
+ this.currentTimeoutMinutes = activityData.timeoutMinutes || 10;
848
+ this.currentWarningMinutes = activityData.reminderMinutes || 1;
849
+
850
+ // 更新警告消息
851
+ this.warningMessage = `您已${this.currentTimeoutMinutes}分钟未操作,将在${this.currentWarningMinutes}分钟后自动退出`;
852
+ if(activityData.needReminder){
853
+ this.showWarningWarning(activityData.remainingMillis);
854
+ }
855
+ // remainingMillis
856
+
857
+
858
+ // 检查是否仍然活跃
859
+ //if (!activityData.isActive) {
860
+ //this.handleInactiveStatus();
861
+ //}
862
+ }
863
+ // 检查是否需要显示提醒
864
+ // let dataReminder=data.data;
865
+ // if (dataReminder&&dataReminder.needReminder) {
866
+ // this.showWarningWarning(dataReminder.remainingSeconds);
867
+ // }
868
+ },
869
+
870
+ // 处理非活跃状态
871
+ handleInactiveStatus() {
872
+ // 清空缓存
873
+ localStorage.clear();
874
+ sessionStorage.clear();
875
+
876
+ // 跳转到登录页
877
+ //this.$router.push('/login');
878
+
879
+ // 或者使用window.location
880
+ window.location.href = '/login';
881
+
882
+ // 触发登出事件
883
+ this.$emit('logout');
884
+ },
885
+
620
886
  // 发送用户行为数据到后端
621
887
  sendUserBehavior(data) {
622
- // 用于测试:在控制台输出用户行为信息
623
- console.log('用户行为监测:', data);
888
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
889
+ const message = {
890
+ "type": "HEARTBEAT",
891
+ "message": "心跳",
892
+ };
893
+ console.log('用户行为监测:', JSON.stringify(message));
894
+ this.socket.send(JSON.stringify(message));
895
+ }
624
896
  },
625
897
 
626
898
  // 绑定事件监听器
627
899
  bindEventListeners() {
628
- console.log('Binding event listeners');
629
- // 使用箭头函数或bind来保持this上下文
630
900
  // 鼠标事件
631
- document.addEventListener('click', this.handleUserActivity.bind(this), true);
632
- document.addEventListener('dblclick', this.handleUserActivity.bind(this), true);
633
- document.addEventListener('mousedown', this.handleUserActivity.bind(this), true);
634
- document.addEventListener('mouseup', this.handleUserActivity.bind(this), true);
635
- document.addEventListener('mousemove', this.handleMouseMove.bind(this), true);
636
- document.addEventListener('mouseover', this.handleUserActivity.bind(this), true);
637
- document.addEventListener('mouseout', this.handleUserActivity.bind(this), true);
901
+ document.addEventListener('click', this.handleUserActivity, true);
902
+ document.addEventListener('dblclick', this.handleUserActivity, true);
903
+ document.addEventListener('mousedown', this.handleUserActivity, true);
904
+ document.addEventListener('mouseup', this.handleUserActivity, true);
905
+ document.addEventListener('mousemove', this.handleMouseMove, true);
906
+ document.addEventListener('mouseover', this.handleUserActivity, true);
907
+ document.addEventListener('mouseout', this.handleUserActivity, true);
638
908
 
639
909
  // 键盘事件
640
- document.addEventListener('keydown', this.handleUserActivity.bind(this), true);
641
- document.addEventListener('keyup', this.handleUserActivity.bind(this), true);
910
+ document.addEventListener('keydown', this.handleUserActivity, true);
911
+ document.addEventListener('keyup', this.handleUserActivity, true);
642
912
 
643
913
  // 表单事件
644
- document.addEventListener('input', this.handleUserActivity.bind(this), true);
645
- document.addEventListener('change', this.handleUserActivity.bind(this), true);
646
- document.addEventListener('focus', this.handleUserActivity.bind(this), true);
647
- document.addEventListener('blur', this.handleUserActivity.bind(this), true);
914
+ document.addEventListener('input', this.handleUserActivity, true);
915
+ document.addEventListener('change', this.handleUserActivity, true);
916
+ document.addEventListener('focus', this.handleUserActivity, true);
917
+ document.addEventListener('blur', this.handleUserActivity, true);
648
918
 
649
919
  // 滚动事件(防抖处理)
650
- document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);
920
+ document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300), true);
651
921
 
652
922
  // 窗口事件
653
- window.addEventListener('resize', this.handleUserActivity.bind(this), true);
654
- window.addEventListener('beforeunload', this.handleBeforeUnload.bind(this));
923
+ window.addEventListener('resize', this.handleUserActivity, true);
924
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
655
925
  },
656
926
 
657
927
  // 解绑事件监听器
658
928
  unbindEventListeners() {
659
- console.log('Unbinding event listeners');
660
- // 解绑时也要使用相同的方式
661
- document.removeEventListener('click', this.handleUserActivity.bind(this), true);
662
- document.removeEventListener('dblclick', this.handleUserActivity.bind(this), true);
663
- document.removeEventListener('mousedown', this.handleUserActivity.bind(this), true);
664
- document.removeEventListener('mouseup', this.handleUserActivity.bind(this), true);
665
- document.removeEventListener('mousemove', this.handleMouseMove.bind(this), true);
666
- document.removeEventListener('mouseover', this.handleUserActivity.bind(this), true);
667
- document.removeEventListener('mouseout', this.handleUserActivity.bind(this), true);
668
-
669
- document.removeEventListener('keydown', this.handleUserActivity.bind(this), true);
670
- document.removeEventListener('keyup', this.handleUserActivity.bind(this), true);
671
-
672
- document.removeEventListener('input', this.handleUserActivity.bind(this), true);
673
- document.removeEventListener('change', this.handleUserActivity.bind(this), true);
674
- document.removeEventListener('focus', this.handleUserActivity.bind(this), true);
675
- document.removeEventListener('blur', this.handleUserActivity.bind(this), true);
676
-
677
- document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);
678
-
679
- window.removeEventListener('resize', this.handleUserActivity.bind(this), true);
680
- window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));
929
+ document.removeEventListener('click', this.handleUserActivity, true);
930
+ document.removeEventListener('dblclick', this.handleUserActivity, true);
931
+ document.removeEventListener('mousedown', this.handleUserActivity, true);
932
+ document.removeEventListener('mouseup', this.handleUserActivity, true);
933
+ document.removeEventListener('mousemove', this.handleMouseMove, true);
934
+ document.removeEventListener('mouseover', this.handleUserActivity, true);
935
+ document.removeEventListener('mouseout', this.handleUserActivity, true);
936
+
937
+ document.removeEventListener('keydown', this.handleUserActivity, true);
938
+ document.removeEventListener('keyup', this.handleUserActivity, true);
939
+
940
+ document.removeEventListener('input', this.handleUserActivity, true);
941
+ document.removeEventListener('change', this.handleUserActivity, true);
942
+ document.removeEventListener('focus', this.handleUserActivity, true);
943
+ document.removeEventListener('blur', this.handleUserActivity, true);
944
+
945
+ document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300), true);
946
+
947
+ window.removeEventListener('resize', this.handleUserActivity, true);
948
+ window.removeEventListener('beforeunload', this.handleBeforeUnload);
681
949
  },
682
950
 
683
951
  // 处理用户活动
@@ -708,7 +976,7 @@ var staticRenderFns = []
708
976
 
709
977
  this.sendUserBehavior(behaviorData);
710
978
  },
711
- handleMouseMove(event) {
979
+ handleMouseMove(event) {
712
980
  if (!this.mouseMoveThrottled) {
713
981
  this.handleUserActivity(event);
714
982
  this.mouseMoveThrottled = true;
@@ -718,20 +986,6 @@ var staticRenderFns = []
718
986
  }
719
987
  },
720
988
 
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
989
  // 判断是否为自动触发事件
736
990
  isAutomaticEvent(event) {
737
991
  // 自动刷新等非用户主动触发的事件
@@ -756,9 +1010,9 @@ var staticRenderFns = []
756
1010
 
757
1011
  // 重置计时器
758
1012
  resetTimer() {
759
- console.log('Resetting timer');
760
1013
  this.lastActivityTime = Date.now();
761
1014
  this.showWarning = false;
1015
+ this.reconnectAttempts = 0; // 重置重连尝试次数
762
1016
 
763
1017
  // 清除警告定时器
764
1018
  if (this.warningTimer) {
@@ -767,52 +1021,48 @@ var staticRenderFns = []
767
1021
  }
768
1022
 
769
1023
  // 重新启动倒计时
770
- this.startCountdown();
1024
+ // this.startCountdown();
771
1025
 
772
1026
  this.$emit('user-active');
773
1027
  },
774
1028
 
775
1029
  // 启动倒计时
776
1030
  startCountdown() {
777
- console.log('Starting countdown');
778
1031
  // 清除现有定时器
779
1032
  if (this.countdownTimer) clearInterval(this.countdownTimer);
780
1033
 
781
1034
  // 设置新的倒计时
782
1035
  this.countdownTimer = setInterval(() => {
783
1036
  const now = Date.now();
784
- const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 60);
785
- console.log('Elapsed minutes:', elapsedMinutes);
1037
+ const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 50);
786
1038
 
787
1039
  // 检查是否需要显示警告
788
- if (elapsedMinutes >= (this.timeoutMinutes - this.warningMinutes) && !this.warningTimer) {
789
- console.log('Showing warning');
1040
+ if (elapsedMinutes >= (this.currentTimeoutMinutes - this.currentWarningMinutes) && !this.warningTimer) {
790
1041
  this.showWarningWarning();
791
1042
  }
792
1043
 
793
1044
  // 检查是否超时
794
- if (elapsedMinutes >= this.timeoutMinutes) {
795
- console.log('Handling timeout');
1045
+ if (elapsedMinutes >= this.currentTimeoutMinutes) {
796
1046
  this.handleTimeout();
797
1047
  }
798
1048
  }, 1000);
799
1049
  },
800
1050
 
801
1051
  // 显示超时警告
802
- showWarningWarning() {
1052
+ showWarningWarning(timeoutMinutes) {
1053
+ let time=timeoutMinutes||50000;
803
1054
  console.log('Setting showWarning to true');
804
1055
  this.showWarning = true;
805
1056
  this.$emit('timeout-warning');
806
-
1057
+ if (this.warningTimer) clearTimeout(this.warningTimer);
807
1058
  // 设置超时处理
808
1059
  this.warningTimer = setTimeout(() => {
809
1060
  this.handleTimeout();
810
- }, this.warningMinutes * 60 * 1000);
1061
+ }, time);
811
1062
  },
812
1063
 
813
1064
  // 处理超时
814
1065
  handleTimeout() {
815
- console.log('Handling timeout');
816
1066
  this.showWarning = false;
817
1067
  this.$emit('timeout');
818
1068
 
@@ -822,9 +1072,24 @@ var staticRenderFns = []
822
1072
 
823
1073
  // 登出操作
824
1074
  logout() {
825
- // 用于测试:在控制台输出登出信息
826
- console.log('用户超时登出');
1075
+ localStorage.clear();
1076
+ sessionStorage.clear();
1077
+ location.reload();
1078
+ // 跳转到登录页
1079
+ //this.$router.push('/login');
827
1080
 
1081
+ // 或者使用window.location
1082
+ // window.location.href = '/login';
1083
+ // 发送登出消息到后端
1084
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
1085
+ const message = {
1086
+ type: 'logout',
1087
+ timestamp: Date.now()
1088
+ };
1089
+ this.socket.send(JSON.stringify(message));
1090
+ }
1091
+
1092
+ // 触发登出事件
828
1093
  this.$emit('logout');
829
1094
 
830
1095
  // 清除定时器
@@ -834,21 +1099,50 @@ var staticRenderFns = []
834
1099
 
835
1100
  // 处理页面卸载前的操作
836
1101
  handleBeforeUnload(event) {
837
- // 用于测试:在控制台输出页面卸载信息
838
- console.log('页面即将卸载');
1102
+ // 发送页面关闭消息
1103
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
1104
+ const message = {
1105
+ type: 'page_unload',
1106
+ timestamp: Date.now()
1107
+ };
1108
+ this.socket.send(JSON.stringify(message));
1109
+ }
839
1110
  },
840
1111
 
841
1112
  // 手动重置监控
842
1113
  reset() {
1114
+ // 检查当前路由,如果在登录页面则销毁监控
1115
+ if (this.isLoginRoute()) {
1116
+ this.destroyMonitor();
1117
+ return;
1118
+ }
1119
+
843
1120
  this.resetTimer();
1121
+ },
1122
+
1123
+ // 重新连接WebSocket
1124
+ reconnect() {
1125
+ // 检查当前路由,如果在登录页面则销毁监控
1126
+ if (this.isLoginRoute()) {
1127
+ this.destroyMonitor();
1128
+ return;
1129
+ }
1130
+
1131
+ // 重置重连尝试次数
1132
+ this.reconnectAttempts = 0;
1133
+
1134
+ if (this.socket) {
1135
+ this.socket.close();
1136
+ }
1137
+ this.initWebSocket();
844
1138
  }
845
1139
  }
846
1140
  });
847
1141
 
848
1142
  // CONCATENATED MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=script&lang=js
849
1143
  /* 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=06a138e4&prod&scoped=true&lang=css
851
- var UserBehaviorMonitorvue_type_style_index_0_id_06a138e4_prod_scoped_true_lang_css = __webpack_require__("533e");
1144
+ // EXTERNAL MODULE: ./src/components/UserBehaviorMonitor.vue?vue&type=style&index=0&id=0335f60c&prod&lang=css
1145
+ var UserBehaviorMonitorvue_type_style_index_0_id_0335f60c_prod_lang_css = __webpack_require__("d1a8");
852
1146
 
853
1147
  // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
854
1148
  /* globals __VUE_SSR_CONTEXT__ */
@@ -963,7 +1257,7 @@ var component = normalizeComponent(
963
1257
  staticRenderFns,
964
1258
  false,
965
1259
  null,
966
- "06a138e4",
1260
+ null,
967
1261
  null
968
1262
 
969
1263
  )
@@ -997,5 +1291,4 @@ if (typeof window !== 'undefined' && window.Vue) {
997
1291
  /***/ })
998
1292
 
999
1293
  /******/ });
1000
- });
1001
- //# sourceMappingURL=user-behavior-monitor.umd.js.map
1294
+ });