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