user-behavior-monitor 1.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 +106 -0
- package/dist/demo.html +8 -0
- package/dist/user-behavior-monitor.common.js +991 -0
- package/dist/user-behavior-monitor.common.js.map +1 -0
- package/dist/user-behavior-monitor.umd.js +1001 -0
- package/dist/user-behavior-monitor.umd.js.map +1 -0
- package/dist/user-behavior-monitor.umd.min.js +2 -0
- package/dist/user-behavior-monitor.umd.min.js.map +1 -0
- package/package.json +33 -0
- package/src/components/UserBehaviorMonitor.vue +343 -0
- package/src/components/UserBehaviorMonitor1.vue +394 -0
- package/src/index.js +17 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["webpack://user-behavior-monitor/webpack/universalModuleDefinition","webpack://user-behavior-monitor/webpack/bootstrap","webpack://user-behavior-monitor/./node_modules/css-loader/lib/css-base.js","webpack://user-behavior-monitor/./node_modules/vue-style-loader/lib/listToStyles.js","webpack://user-behavior-monitor/./node_modules/vue-style-loader/lib/addStylesClient.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?70b8","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?f529","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?c282","webpack://user-behavior-monitor/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?f2c6","webpack://user-behavior-monitor/src/components/UserBehaviorMonitor.vue","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?8778","webpack://user-behavior-monitor/./node_modules/vue-loader/lib/runtime/componentNormalizer.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue","webpack://user-behavior-monitor/./src/index.js","webpack://user-behavior-monitor/./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;QCVA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,mCAAmC,gBAAgB;AACnD,IAAI;AACJ;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA,YAAY,oBAAoB;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,oDAAoD,cAAc;;AAElE;AACA;;;;;;;;;;;;;;;;AC3EA;AACA;AACA;AACA;AACe;AACf;AACA;AACA,iBAAiB,iBAAiB;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,wBAAwB;AAC3D,KAAK;AACL;AACA;AACA;AACA;AACA;;;AC1BA;AACA;AACA;AACA;AACA;;AAEyC;;AAEzC;;AAEA;AACA;AACA;AACA;AACA,UAAU,iBAAiB;AAC3B;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEe;AACf;;AAEA;;AAEA,eAAe,YAAY;AAC3B;;AAEA;AACA;AACA,mBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,YAAY;AAC3B;AACA,KAAK;AACL;AACA;AACA,mBAAmB,sBAAsB;AACzC;AACA;AACA,uBAAuB,2BAA2B;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAiB,mBAAmB;AACpC;AACA;AACA;AACA;AACA,qBAAqB,2BAA2B;AAChD;AACA;AACA,YAAY,uBAAuB;AACnC;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,qBAAqB,uBAAuB;AAC5C;AACA;AACA,8BAA8B;AAC9B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,yDAAyD;AACzD;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AC7NA;AAAA;AAAA;;;;;;;;ACAA,2BAA2B,mBAAO,CAAC,MAA+C;AAClF;;;AAGA;AACA,cAAc,QAAS,2CAA2C,aAAa,4DAA4D,kBAAkB,eAAe,kBAAkB,0CAA0C,uBAAuB;;AAE/P;;;;;;;;ACPA;;AAEA;AACA,cAAc,mBAAO,CAAC,MAAsY;AAC5Z;AACA,4CAA4C,QAAS;AACrD;AACA;AACA,UAAU,mBAAO,CAAC,MAA6D;AAC/E,6CAA6C,qCAAqC,E;;;;;;;;;;;;;;;ACTlF;;AAEA;AACA,MAAM,KAAuC,EAAE,EAE5C;;AAEH;AACA;AACA,IAAI,qBAAuB;AAC3B;AACA;;AAEA;AACe,sDAAI;;;ACdnB,0BAA0B,aAAa,0BAA0B,wBAAwB,iBAAiB,0DAA0D,kBAAkB,OAAO,0OAA0O,KAAK,kCAAkC,yBAAyB,iEAAiE,aAAa,iEAAiE,KAAK,yBAAyB;AACppB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyBe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,CAAC,EAAC;;;ACnUyL,CAAgB,oIAAG,EAAC,C;;;;;ACA/M;;AAEA;AACA;AACA;;AAEe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AC/F6G;AACvC;AACL;AAC0C;;;AAG3G;AAC0F;AAC1F,gBAAgB,kBAAU;AAC1B,EAAE,qDAAM;AACR,EAAE,MAAM;AACR,EAAE,eAAe;AACjB;AACA;AACA;AACA;;AAEA;;AAEe,yE;;ACnBwD;;AAEvE;AACA,mBAAmB;AACnB,gBAAgB,mBAAmB,OAAO,mBAAmB;AAC7D;;AAEA;AACe,2DAAmB,EAAC;;AAEnC;AACA;AACA,EAAE,mBAAmB;AACrB;;AAEA;;;ACfwB;AACA;AACT,kFAAG;AACI","file":"user-behavior-monitor.umd.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"user-behavior-monitor\"] = factory();\n\telse\n\t\troot[\"user-behavior-monitor\"] = factory();\n})((typeof self !== 'undefined' ? self : this), function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fb15\");\n","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n","/**\n * Translates the list format produced by css-loader into something\n * easier to manipulate.\n */\nexport default function listToStyles (parentId, list) {\n var styles = []\n var newStyles = {}\n for (var i = 0; i < list.length; i++) {\n var item = list[i]\n var id = item[0]\n var css = item[1]\n var media = item[2]\n var sourceMap = item[3]\n var part = {\n id: parentId + ':' + i,\n css: css,\n media: media,\n sourceMap: sourceMap\n }\n if (!newStyles[id]) {\n styles.push(newStyles[id] = { id: id, parts: [part] })\n } else {\n newStyles[id].parts.push(part)\n }\n }\n return styles\n}\n","/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n Modified by Evan You @yyx990803\n*/\n\nimport listToStyles from './listToStyles'\n\nvar hasDocument = typeof document !== 'undefined'\n\nif (typeof DEBUG !== 'undefined' && DEBUG) {\n if (!hasDocument) {\n throw new Error(\n 'vue-style-loader cannot be used in a non-browser environment. ' +\n \"Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.\"\n ) }\n}\n\n/*\ntype StyleObject = {\n id: number;\n parts: Array<StyleObjectPart>\n}\n\ntype StyleObjectPart = {\n css: string;\n media: string;\n sourceMap: ?string\n}\n*/\n\nvar stylesInDom = {/*\n [id: number]: {\n id: number,\n refs: number,\n parts: Array<(obj?: StyleObjectPart) => void>\n }\n*/}\n\nvar head = hasDocument && (document.head || document.getElementsByTagName('head')[0])\nvar singletonElement = null\nvar singletonCounter = 0\nvar isProduction = false\nvar noop = function () {}\nvar options = null\nvar ssrIdKey = 'data-vue-ssr-id'\n\n// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n// tags it will allow on a page\nvar isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase())\n\nexport default function addStylesClient (parentId, list, _isProduction, _options) {\n isProduction = _isProduction\n\n options = _options || {}\n\n var styles = listToStyles(parentId, list)\n addStylesToDom(styles)\n\n return function update (newList) {\n var mayRemove = []\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n domStyle.refs--\n mayRemove.push(domStyle)\n }\n if (newList) {\n styles = listToStyles(parentId, newList)\n addStylesToDom(styles)\n } else {\n styles = []\n }\n for (var i = 0; i < mayRemove.length; i++) {\n var domStyle = mayRemove[i]\n if (domStyle.refs === 0) {\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j]()\n }\n delete stylesInDom[domStyle.id]\n }\n }\n }\n}\n\nfunction addStylesToDom (styles /* Array<StyleObject> */) {\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n if (domStyle) {\n domStyle.refs++\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j](item.parts[j])\n }\n for (; j < item.parts.length; j++) {\n domStyle.parts.push(addStyle(item.parts[j]))\n }\n if (domStyle.parts.length > item.parts.length) {\n domStyle.parts.length = item.parts.length\n }\n } else {\n var parts = []\n for (var j = 0; j < item.parts.length; j++) {\n parts.push(addStyle(item.parts[j]))\n }\n stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts }\n }\n }\n}\n\nfunction createStyleElement () {\n var styleElement = document.createElement('style')\n styleElement.type = 'text/css'\n head.appendChild(styleElement)\n return styleElement\n}\n\nfunction addStyle (obj /* StyleObjectPart */) {\n var update, remove\n var styleElement = document.querySelector('style[' + ssrIdKey + '~=\"' + obj.id + '\"]')\n\n if (styleElement) {\n if (isProduction) {\n // has SSR styles and in production mode.\n // simply do nothing.\n return noop\n } else {\n // has SSR styles but in dev mode.\n // for some reason Chrome can't handle source map in server-rendered\n // style tags - source maps in <style> only works if the style tag is\n // created and inserted dynamically. So we remove the server rendered\n // styles and inject new ones.\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n if (isOldIE) {\n // use singleton mode for IE9.\n var styleIndex = singletonCounter++\n styleElement = singletonElement || (singletonElement = createStyleElement())\n update = applyToSingletonTag.bind(null, styleElement, styleIndex, false)\n remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true)\n } else {\n // use multi-style-tag mode in all other cases\n styleElement = createStyleElement()\n update = applyToTag.bind(null, styleElement)\n remove = function () {\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n update(obj)\n\n return function updateStyle (newObj /* StyleObjectPart */) {\n if (newObj) {\n if (newObj.css === obj.css &&\n newObj.media === obj.media &&\n newObj.sourceMap === obj.sourceMap) {\n return\n }\n update(obj = newObj)\n } else {\n remove()\n }\n }\n}\n\nvar replaceText = (function () {\n var textStore = []\n\n return function (index, replacement) {\n textStore[index] = replacement\n return textStore.filter(Boolean).join('\\n')\n }\n})()\n\nfunction applyToSingletonTag (styleElement, index, remove, obj) {\n var css = remove ? '' : obj.css\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = replaceText(index, css)\n } else {\n var cssNode = document.createTextNode(css)\n var childNodes = styleElement.childNodes\n if (childNodes[index]) styleElement.removeChild(childNodes[index])\n if (childNodes.length) {\n styleElement.insertBefore(cssNode, childNodes[index])\n } else {\n styleElement.appendChild(cssNode)\n }\n }\n}\n\nfunction applyToTag (styleElement, obj) {\n var css = obj.css\n var media = obj.media\n var sourceMap = obj.sourceMap\n\n if (media) {\n styleElement.setAttribute('media', media)\n }\n if (options.ssrId) {\n styleElement.setAttribute(ssrIdKey, obj.id)\n }\n\n if (sourceMap) {\n // https://developer.chrome.com/devtools/docs/javascript-debugging\n // this makes source maps inside style tags work properly in Chrome\n css += '\\n/*# sourceURL=' + sourceMap.sources[0] + ' */'\n // http://stackoverflow.com/a/26603875\n css += '\\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'\n }\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild)\n }\n styleElement.appendChild(document.createTextNode(css))\n }\n}\n","export * from \"-!../../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\"","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \".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}\", \"\"]);\n\n// exports\n","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../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\");\nif(content.__esModule) content = content.default;\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar add = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\").default\nvar update = add(\"2c53b590\", content, true, {\"sourceMap\":false,\"shadowMode\":false});","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n require('current-script-polyfill')\n }\n\n var i\n if ((i = window.document.currentScript) && (i = i.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/))) {\n __webpack_public_path__ = i[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","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)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<template>\r\n <div ref=\"behaviorMonitor\" class=\"user-behavior-monitor\">\r\n <!-- 提示框 -->\r\n <el-dialog\r\n :visible.sync=\"showWarning\"\r\n :show-close=\"false\"\r\n :modal=\"true\"\r\n width=\"30%\"\r\n center\r\n custom-class=\"behavior-warning-dialog\"\r\n :append-to-body=\"true\"\r\n :modal-append-to-body=\"true\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n >\r\n <span>{{ warningMessage }}</span>\r\n </el-dialog>\r\n\r\n\r\n <button @click=\"testWarning\" style=\"position: fixed; top: 10px; right: 10px; z-index: 10000;\">\r\n 测试警告\r\n </button>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nexport default {\r\n name: 'UserBehaviorMonitor',\r\n props: {\r\n // WebSocket服务器地址\r\n websocketUrl: {\r\n type: String,\r\n required: true\r\n },\r\n // 倒计时时长(分钟)\r\n timeoutMinutes: {\r\n type: Number,\r\n default: 10\r\n },\r\n // 警告提前时间(分钟)\r\n warningMinutes: {\r\n type: Number,\r\n default: 1\r\n }\r\n },\r\n data() {\r\n return {\r\n mouseMoveThrottled:false,\r\n websocket: null,\r\n countdownTimer: null,\r\n warningTimer: null,\r\n showWarning: false,\r\n warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,\r\n lastActivityTime: null,\r\n isMonitoring: false\r\n };\r\n },\r\n mounted() {\r\n console.log('开始开始! mounted');\r\n this.initMonitor();\r\n },\r\n beforeDestroy() {\r\n console.log('开始开始! beforeDestroy');\r\n this.destroyMonitor();\r\n },\r\n methods: {\r\n testWarning() {\r\n console.log('Testing warning display');\r\n this.showWarning = true;\r\n },\r\n // 初始化监控\r\n initMonitor() {\r\n console.log('Initializing monitor');\r\n if (this.isMonitoring) return;\r\n \r\n this.isMonitoring = true;\r\n this.lastActivityTime = Date.now();\r\n \r\n // 启动倒计时\r\n this.startCountdown();\r\n \r\n // 绑定事件监听器\r\n this.bindEventListeners();\r\n },\r\n \r\n // 销毁监控\r\n destroyMonitor() {\r\n this.isMonitoring = false;\r\n \r\n // 清除定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n if (this.warningTimer) clearTimeout(this.warningTimer);\r\n \r\n // 解绑事件监听器\r\n this.unbindEventListeners();\r\n },\r\n \r\n // 发送用户行为数据到后端\r\n sendUserBehavior(data) {\r\n // 用于测试:在控制台输出用户行为信息\r\n console.log('用户行为监测:', data);\r\n },\r\n \r\n // 绑定事件监听器\r\n bindEventListeners() {\r\n console.log('Binding event listeners');\r\n // 使用箭头函数或bind来保持this上下文\r\n // 鼠标事件\r\n document.addEventListener('click', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('dblclick', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mousedown', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mouseup', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mousemove', this.handleMouseMove.bind(this), true);\r\n document.addEventListener('mouseover', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mouseout', this.handleUserActivity.bind(this), true);\r\n \r\n // 键盘事件\r\n document.addEventListener('keydown', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('keyup', this.handleUserActivity.bind(this), true);\r\n \r\n // 表单事件\r\n document.addEventListener('input', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('change', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('focus', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('blur', this.handleUserActivity.bind(this), true);\r\n \r\n // 滚动事件(防抖处理)\r\n document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);\r\n \r\n // 窗口事件\r\n window.addEventListener('resize', this.handleUserActivity.bind(this), true);\r\n window.addEventListener('beforeunload', this.handleBeforeUnload.bind(this));\r\n },\r\n \r\n // 解绑事件监听器\r\n unbindEventListeners() {\r\n console.log('Unbinding event listeners');\r\n // 解绑时也要使用相同的方式\r\n document.removeEventListener('click', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('dblclick', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mousedown', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mouseup', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mousemove', this.handleMouseMove.bind(this), true);\r\n document.removeEventListener('mouseover', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mouseout', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('keydown', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('keyup', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('input', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('change', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('focus', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('blur', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);\r\n \r\n window.removeEventListener('resize', this.handleUserActivity.bind(this), true);\r\n window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));\r\n },\r\n \r\n // 处理用户活动\r\n handleUserActivity(event) {\r\n // 过滤掉自动触发的事件\r\n if (this.isAutomaticEvent(event)) return;\r\n \r\n this.resetTimer();\r\n \r\n // 发送用户行为数据\r\n const behaviorData = {\r\n eventType: event.type,\r\n target: event.target.tagName,\r\n timestamp: Date.now(),\r\n url: window.location.href\r\n };\r\n \r\n // 添加特定事件的额外信息\r\n if (event.type === 'click') {\r\n behaviorData.clientX = event.clientX;\r\n behaviorData.clientY = event.clientY;\r\n } else if (event.type === 'keydown') {\r\n behaviorData.key = event.key;\r\n behaviorData.ctrlKey = event.ctrlKey;\r\n behaviorData.altKey = event.altKey;\r\n behaviorData.shiftKey = event.shiftKey;\r\n }\r\n \r\n this.sendUserBehavior(behaviorData);\r\n },\r\n handleMouseMove(event) {\r\n if (!this.mouseMoveThrottled) {\r\n this.handleUserActivity(event);\r\n this.mouseMoveThrottled = true;\r\n setTimeout(() => {\r\n this.mouseMoveThrottled = false;\r\n }, 500);\r\n }\r\n },\r\n \r\n // 处理鼠标移动(降低频率)\r\n // handleMouseMove: function() {\r\n // let isThrottled = false;\r\n // return (event) => {\r\n // if (!isThrottled) {\r\n // this.handleUserActivity(event);\r\n // isThrottled = true;\r\n // setTimeout(() => {\r\n // isThrottled = false;\r\n // }, 500);\r\n // }\r\n // };\r\n // }(),\r\n \r\n // 判断是否为自动触发事件\r\n isAutomaticEvent(event) {\r\n // 自动刷新等非用户主动触发的事件\r\n if (event.type === 'scroll' && !this.isUserScrolling) {\r\n return true;\r\n }\r\n return false;\r\n },\r\n \r\n // 防抖函数\r\n debounce(func, wait) {\r\n let timeout;\r\n return function executedFunction(...args) {\r\n const later = () => {\r\n clearTimeout(timeout);\r\n func.apply(this, args);\r\n };\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n };\r\n },\r\n \r\n // 重置计时器\r\n resetTimer() {\r\n console.log('Resetting timer');\r\n this.lastActivityTime = Date.now();\r\n this.showWarning = false;\r\n \r\n // 清除警告定时器\r\n if (this.warningTimer) {\r\n clearTimeout(this.warningTimer);\r\n this.warningTimer = null;\r\n }\r\n \r\n // 重新启动倒计时\r\n this.startCountdown();\r\n \r\n this.$emit('user-active');\r\n },\r\n \r\n // 启动倒计时\r\n startCountdown() {\r\n console.log('Starting countdown');\r\n // 清除现有定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n \r\n // 设置新的倒计时\r\n this.countdownTimer = setInterval(() => {\r\n const now = Date.now();\r\n const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 60);\r\n console.log('Elapsed minutes:', elapsedMinutes);\r\n \r\n // 检查是否需要显示警告\r\n if (elapsedMinutes >= (this.timeoutMinutes - this.warningMinutes) && !this.warningTimer) {\r\n console.log('Showing warning');\r\n this.showWarningWarning();\r\n }\r\n \r\n // 检查是否超时\r\n if (elapsedMinutes >= this.timeoutMinutes) {\r\n console.log('Handling timeout');\r\n this.handleTimeout();\r\n }\r\n }, 1000);\r\n },\r\n \r\n // 显示超时警告\r\n showWarningWarning() {\r\n console.log('Setting showWarning to true');\r\n this.showWarning = true;\r\n this.$emit('timeout-warning');\r\n \r\n // 设置超时处理\r\n this.warningTimer = setTimeout(() => {\r\n this.handleTimeout();\r\n }, this.warningMinutes * 60 * 1000);\r\n },\r\n \r\n // 处理超时\r\n handleTimeout() {\r\n console.log('Handling timeout');\r\n this.showWarning = false;\r\n this.$emit('timeout');\r\n \r\n // 执行登出逻辑\r\n this.logout();\r\n },\r\n \r\n // 登出操作\r\n logout() {\r\n // 用于测试:在控制台输出登出信息\r\n console.log('用户超时登出');\r\n \r\n this.$emit('logout');\r\n \r\n // 清除定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n if (this.warningTimer) clearTimeout(this.warningTimer);\r\n },\r\n \r\n // 处理页面卸载前的操作\r\n handleBeforeUnload(event) {\r\n // 用于测试:在控制台输出页面卸载信息\r\n console.log('页面即将卸载');\r\n },\r\n \r\n // 手动重置监控\r\n reset() {\r\n this.resetTimer();\r\n }\r\n }\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.user-behavior-monitor {\r\n display: none;\r\n}\r\n\r\n/* 使用深度选择器确保样式正确应用 */\r\n.behavior-warning-dialog ::v-deep .el-dialog__body {\r\n text-align: center;\r\n font-size: 16px;\r\n padding: 30px 20px;\r\n}\r\n\r\n/* 确保弹框在最上层 */\r\n.behavior-warning-dialog {\r\n z-index: 9999 !important;\r\n}\r\n</style>","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserBehaviorMonitor.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserBehaviorMonitor.vue?vue&type=script&lang=js\"","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent(\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier /* server only */,\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options =\n typeof scriptExports === 'function' ? scriptExports.options : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) {\n // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () {\n injectStyles.call(\n this,\n (options.functional ? this.parent : this).$root.$options.shadowRoot\n )\n }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functional component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection(h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing ? [].concat(existing, hook) : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","import { render, staticRenderFns } from \"./UserBehaviorMonitor.vue?vue&type=template&id=06a138e4&scoped=true\"\nimport script from \"./UserBehaviorMonitor.vue?vue&type=script&lang=js\"\nexport * from \"./UserBehaviorMonitor.vue?vue&type=script&lang=js\"\nimport style0 from \"./UserBehaviorMonitor.vue?vue&type=style&index=0&id=06a138e4&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"06a138e4\",\n null\n \n)\n\nexport default component.exports","import UserBehaviorMonitor from './components/UserBehaviorMonitor.vue';\r\n\r\n// 为使用 CDN 方式引入的用户提供组件注册方法\r\nUserBehaviorMonitor.install = function(Vue) {\r\n Vue.component(UserBehaviorMonitor.name, UserBehaviorMonitor);\r\n};\r\n\r\n// 导出组件\r\nexport default UserBehaviorMonitor;\r\n\r\n// 如果是直接引入文件,则自动注册组件\r\nif (typeof window !== 'undefined' && window.Vue) {\r\n UserBehaviorMonitor.install(window.Vue);\r\n}\r\n\r\n// 同时支持按需导入\r\nexport { UserBehaviorMonitor };","import './setPublicPath'\nimport mod from '~entry'\nexport default mod\nexport * from '~entry'\n"],"sourceRoot":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports["user-behavior-monitor"]=t():e["user-behavior-monitor"]=t()})("undefined"!==typeof self?self:this,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s="fb15")}({2350:function(e,t){function n(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"===typeof btoa){var r=i(o),s=o.sources.map((function(e){return"/*# sourceURL="+o.sourceRoot+e+" */"}));return[n].concat(s).concat([r]).join("\n")}return[n].join("\n")}function i(e){var t=btoa(unescape(encodeURIComponent(JSON.stringify(e)))),n="sourceMappingURL=data:application/json;charset=utf-8;base64,"+t;return"/*# "+n+" */"}e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var i=n(t,e);return t[2]?"@media "+t[2]+"{"+i+"}":i})).join("")},t.i=function(e,n){"string"===typeof e&&(e=[[null,e,""]]);for(var i={},o=0;o<this.length;o++){var r=this[o][0];"number"===typeof r&&(i[r]=!0)}for(o=0;o<e.length;o++){var s=e[o];"number"===typeof s[0]&&i[s[0]]||(n&&!s[2]?s[2]=n:n&&(s[2]="("+s[2]+") and ("+n+")"),t.push(s))}},t}},"499e":function(e,t,n){"use strict";function i(e,t){for(var n=[],i={},o=0;o<t.length;o++){var r=t[o],s=r[0],a=r[1],d=r[2],u=r[3],l={id:e+":"+o,css:a,media:d,sourceMap:u};i[s]?i[s].parts.push(l):n.push(i[s]={id:s,parts:[l]})}return n}n.r(t),n.d(t,"default",(function(){return m}));var o="undefined"!==typeof document;if("undefined"!==typeof DEBUG&&DEBUG&&!o)throw new Error("vue-style-loader cannot be used in a non-browser environment. Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.");var r={},s=o&&(document.head||document.getElementsByTagName("head")[0]),a=null,d=0,u=!1,l=function(){},c=null,h="data-vue-ssr-id",v="undefined"!==typeof navigator&&/msie [6-9]\b/.test(navigator.userAgent.toLowerCase());function m(e,t,n,o){u=n,c=o||{};var s=i(e,t);return f(s),function(t){for(var n=[],o=0;o<s.length;o++){var a=s[o],d=r[a.id];d.refs--,n.push(d)}t?(s=i(e,t),f(s)):s=[];for(o=0;o<n.length;o++){d=n[o];if(0===d.refs){for(var u=0;u<d.parts.length;u++)d.parts[u]();delete r[d.id]}}}}function f(e){for(var t=0;t<e.length;t++){var n=e[t],i=r[n.id];if(i){i.refs++;for(var o=0;o<i.parts.length;o++)i.parts[o](n.parts[o]);for(;o<n.parts.length;o++)i.parts.push(g(n.parts[o]));i.parts.length>n.parts.length&&(i.parts.length=n.parts.length)}else{var s=[];for(o=0;o<n.parts.length;o++)s.push(g(n.parts[o]));r[n.id]={id:n.id,refs:1,parts:s}}}}function p(){var e=document.createElement("style");return e.type="text/css",s.appendChild(e),e}function g(e){var t,n,i=document.querySelector("style["+h+'~="'+e.id+'"]');if(i){if(u)return l;i.parentNode.removeChild(i)}if(v){var o=d++;i=a||(a=p()),t=b.bind(null,i,o,!1),n=b.bind(null,i,o,!0)}else i=p(),t=w.bind(null,i),n=function(){i.parentNode.removeChild(i)};return t(e),function(i){if(i){if(i.css===e.css&&i.media===e.media&&i.sourceMap===e.sourceMap)return;t(e=i)}else n()}}var y=function(){var e=[];return function(t,n){return e[t]=n,e.filter(Boolean).join("\n")}}();function b(e,t,n,i){var o=n?"":i.css;if(e.styleSheet)e.styleSheet.cssText=y(t,o);else{var r=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function w(e,t){var n=t.css,i=t.media,o=t.sourceMap;if(i&&e.setAttribute("media",i),c.ssrId&&e.setAttribute(h,t.id),o&&(n+="\n/*# sourceURL="+o.sources[0]+" */",n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */"),e.styleSheet)e.styleSheet.cssText=n;else{while(e.firstChild)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}},"533e":function(e,t,n){"use strict";n("d1b1")},"9cfc":function(e,t,n){t=e.exports=n("2350")(!1),t.push([e.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}",""])},d1b1:function(e,t,n){var i=n("9cfc");i.__esModule&&(i=i.default),"string"===typeof i&&(i=[[e.i,i,""]]),i.locals&&(e.exports=i.locals);var o=n("499e").default;o("2c53b590",i,!0,{sourceMap:!1,shadowMode:!1})},fb15:function(e,t,n){"use strict";var i;(n.r(t),n.d(t,"UserBehaviorMonitor",(function(){return l})),"undefined"!==typeof window)&&((i=window.document.currentScript)&&(i=i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))&&(n.p=i[1]));var o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{ref:"behaviorMonitor",staticClass:"user-behavior-monitor"},[n("el-dialog",{attrs:{visible:e.showWarning,"show-close":!1,modal:!0,width:"30%",center:"","custom-class":"behavior-warning-dialog","append-to-body":!0,"modal-append-to-body":!0,"close-on-click-modal":!1,"close-on-press-escape":!1},on:{"update:visible":function(t){e.showWarning=t}}},[n("span",[e._v(e._s(e.warningMessage))])]),n("button",{staticStyle:{position:"fixed",top:"10px",right:"10px","z-index":"10000"},on:{click:e.testWarning}},[e._v("\n 测试警告\n ")])],1)},r=[],s={name:"UserBehaviorMonitor",props:{websocketUrl:{type:String,required:!0},timeoutMinutes:{type:Number,default:10},warningMinutes:{type:Number,default:1}},data(){return{mouseMoveThrottled:!1,websocket:null,countdownTimer:null,warningTimer:null,showWarning:!1,warningMessage:`您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,lastActivityTime:null,isMonitoring:!1}},mounted(){console.log("开始开始! mounted"),this.initMonitor()},beforeDestroy(){console.log("开始开始! beforeDestroy"),this.destroyMonitor()},methods:{testWarning(){console.log("Testing warning display"),this.showWarning=!0},initMonitor(){console.log("Initializing monitor"),this.isMonitoring||(this.isMonitoring=!0,this.lastActivityTime=Date.now(),this.startCountdown(),this.bindEventListeners())},destroyMonitor(){this.isMonitoring=!1,this.countdownTimer&&clearInterval(this.countdownTimer),this.warningTimer&&clearTimeout(this.warningTimer),this.unbindEventListeners()},sendUserBehavior(e){console.log("用户行为监测:",e)},bindEventListeners(){console.log("Binding event listeners"),document.addEventListener("click",this.handleUserActivity.bind(this),!0),document.addEventListener("dblclick",this.handleUserActivity.bind(this),!0),document.addEventListener("mousedown",this.handleUserActivity.bind(this),!0),document.addEventListener("mouseup",this.handleUserActivity.bind(this),!0),document.addEventListener("mousemove",this.handleMouseMove.bind(this),!0),document.addEventListener("mouseover",this.handleUserActivity.bind(this),!0),document.addEventListener("mouseout",this.handleUserActivity.bind(this),!0),document.addEventListener("keydown",this.handleUserActivity.bind(this),!0),document.addEventListener("keyup",this.handleUserActivity.bind(this),!0),document.addEventListener("input",this.handleUserActivity.bind(this),!0),document.addEventListener("change",this.handleUserActivity.bind(this),!0),document.addEventListener("focus",this.handleUserActivity.bind(this),!0),document.addEventListener("blur",this.handleUserActivity.bind(this),!0),document.addEventListener("scroll",this.debounce(this.handleUserActivity,300).bind(this),!0),window.addEventListener("resize",this.handleUserActivity.bind(this),!0),window.addEventListener("beforeunload",this.handleBeforeUnload.bind(this))},unbindEventListeners(){console.log("Unbinding event listeners"),document.removeEventListener("click",this.handleUserActivity.bind(this),!0),document.removeEventListener("dblclick",this.handleUserActivity.bind(this),!0),document.removeEventListener("mousedown",this.handleUserActivity.bind(this),!0),document.removeEventListener("mouseup",this.handleUserActivity.bind(this),!0),document.removeEventListener("mousemove",this.handleMouseMove.bind(this),!0),document.removeEventListener("mouseover",this.handleUserActivity.bind(this),!0),document.removeEventListener("mouseout",this.handleUserActivity.bind(this),!0),document.removeEventListener("keydown",this.handleUserActivity.bind(this),!0),document.removeEventListener("keyup",this.handleUserActivity.bind(this),!0),document.removeEventListener("input",this.handleUserActivity.bind(this),!0),document.removeEventListener("change",this.handleUserActivity.bind(this),!0),document.removeEventListener("focus",this.handleUserActivity.bind(this),!0),document.removeEventListener("blur",this.handleUserActivity.bind(this),!0),document.removeEventListener("scroll",this.debounce(this.handleUserActivity,300).bind(this),!0),window.removeEventListener("resize",this.handleUserActivity.bind(this),!0),window.removeEventListener("beforeunload",this.handleBeforeUnload.bind(this))},handleUserActivity(e){if(this.isAutomaticEvent(e))return;this.resetTimer();const t={eventType:e.type,target:e.target.tagName,timestamp:Date.now(),url:window.location.href};"click"===e.type?(t.clientX=e.clientX,t.clientY=e.clientY):"keydown"===e.type&&(t.key=e.key,t.ctrlKey=e.ctrlKey,t.altKey=e.altKey,t.shiftKey=e.shiftKey),this.sendUserBehavior(t)},handleMouseMove(e){this.mouseMoveThrottled||(this.handleUserActivity(e),this.mouseMoveThrottled=!0,setTimeout(()=>{this.mouseMoveThrottled=!1},500))},isAutomaticEvent(e){return"scroll"===e.type&&!this.isUserScrolling},debounce(e,t){let n;return function(...i){const o=()=>{clearTimeout(n),e.apply(this,i)};clearTimeout(n),n=setTimeout(o,t)}},resetTimer(){console.log("Resetting timer"),this.lastActivityTime=Date.now(),this.showWarning=!1,this.warningTimer&&(clearTimeout(this.warningTimer),this.warningTimer=null),this.startCountdown(),this.$emit("user-active")},startCountdown(){console.log("Starting countdown"),this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval(()=>{const e=Date.now(),t=(e-this.lastActivityTime)/6e4;console.log("Elapsed minutes:",t),t>=this.timeoutMinutes-this.warningMinutes&&!this.warningTimer&&(console.log("Showing warning"),this.showWarningWarning()),t>=this.timeoutMinutes&&(console.log("Handling timeout"),this.handleTimeout())},1e3)},showWarningWarning(){console.log("Setting showWarning to true"),this.showWarning=!0,this.$emit("timeout-warning"),this.warningTimer=setTimeout(()=>{this.handleTimeout()},60*this.warningMinutes*1e3)},handleTimeout(){console.log("Handling timeout"),this.showWarning=!1,this.$emit("timeout"),this.logout()},logout(){console.log("用户超时登出"),this.$emit("logout"),this.countdownTimer&&clearInterval(this.countdownTimer),this.warningTimer&&clearTimeout(this.warningTimer)},handleBeforeUnload(e){console.log("页面即将卸载")},reset(){this.resetTimer()}}},a=s;n("533e");function d(e,t,n,i,o,r,s,a){var d,u="function"===typeof e?e.options:e;if(t&&(u.render=t,u.staticRenderFns=n,u._compiled=!0),i&&(u.functional=!0),r&&(u._scopeId="data-v-"+r),s?(d=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"===typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),o&&o.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},u._ssrRegister=d):o&&(d=a?function(){o.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:o),d)if(u.functional){u._injectStyles=d;var l=u.render;u.render=function(e,t){return d.call(t),l(e,t)}}else{var c=u.beforeCreate;u.beforeCreate=c?[].concat(c,d):[d]}return{exports:e,options:u}}var u=d(a,o,r,!1,null,"06a138e4",null),l=u.exports;l.install=function(e){e.component(l.name,l)};var c=l;"undefined"!==typeof window&&window.Vue&&l.install(window.Vue);t["default"]=c}})}));
|
|
2
|
+
//# sourceMappingURL=user-behavior-monitor.umd.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["webpack://user-behavior-monitor/webpack/universalModuleDefinition","webpack://user-behavior-monitor/webpack/bootstrap","webpack://user-behavior-monitor/./node_modules/css-loader/lib/css-base.js","webpack://user-behavior-monitor/./node_modules/vue-style-loader/lib/listToStyles.js","webpack://user-behavior-monitor/./node_modules/vue-style-loader/lib/addStylesClient.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?70b8","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?f529","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?c282","webpack://user-behavior-monitor/./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?f2c6","webpack://user-behavior-monitor/src/components/UserBehaviorMonitor.vue","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue?8778","webpack://user-behavior-monitor/./node_modules/vue-loader/lib/runtime/componentNormalizer.js","webpack://user-behavior-monitor/./src/components/UserBehaviorMonitor.vue","webpack://user-behavior-monitor/./src/index.js","webpack://user-behavior-monitor/./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js"],"names":["root","factory","exports","module","define","amd","self","this","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","cssWithMappingToString","item","useSourceMap","content","cssMapping","btoa","sourceMapping","toComment","sourceURLs","sources","map","source","sourceRoot","concat","join","sourceMap","base64","unescape","encodeURIComponent","JSON","stringify","data","list","toString","mediaQuery","alreadyImportedModules","length","id","push","listToStyles","parentId","styles","newStyles","css","media","part","parts","hasDocument","document","DEBUG","Error","stylesInDom","head","getElementsByTagName","singletonElement","singletonCounter","isProduction","noop","options","ssrIdKey","isOldIE","navigator","test","userAgent","toLowerCase","addStylesClient","_isProduction","_options","addStylesToDom","newList","mayRemove","domStyle","refs","j","addStyle","createStyleElement","styleElement","createElement","type","appendChild","obj","update","remove","querySelector","parentNode","removeChild","styleIndex","applyToSingletonTag","applyToTag","newObj","replaceText","textStore","index","replacement","filter","Boolean","styleSheet","cssText","cssNode","createTextNode","childNodes","insertBefore","setAttribute","ssrId","firstChild","default","locals","add","window","currentScript","src","match","render","_vm","_h","$createElement","_c","_self","ref","staticClass","attrs","showWarning","on","$event","_v","_s","warningMessage","staticStyle","testWarning","staticRenderFns","props","websocketUrl","String","required","timeoutMinutes","Number","warningMinutes","mouseMoveThrottled","websocket","countdownTimer","warningTimer","lastActivityTime","isMonitoring","console","log","initMonitor","destroyMonitor","methods","Date","now","startCountdown","bindEventListeners","clearInterval","clearTimeout","unbindEventListeners","addEventListener","handleUserActivity","handleMouseMove","debounce","handleBeforeUnload","removeEventListener","event","isAutomaticEvent","resetTimer","behaviorData","eventType","target","tagName","timestamp","url","location","href","clientX","clientY","ctrlKey","altKey","shiftKey","sendUserBehavior","setTimeout","isUserScrolling","func","wait","timeout","args","later","apply","$emit","setInterval","elapsedMinutes","showWarningWarning","handleTimeout","logout","normalizeComponent","scriptExports","functionalTemplate","injectStyles","scopeId","moduleIdentifier","shadowMode","hook","_compiled","functional","_scopeId","context","$vnode","ssrContext","parent","__VUE_SSR_CONTEXT__","_registeredComponents","_ssrRegister","$root","$options","shadowRoot","_injectStyles","originalRender","h","existing","beforeCreate","component","UserBehaviorMonitor","install","Vue"],"mappings":"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","file":"user-behavior-monitor.umd.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"user-behavior-monitor\"] = factory();\n\telse\n\t\troot[\"user-behavior-monitor\"] = factory();\n})((typeof self !== 'undefined' ? self : this), function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"fb15\");\n","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n","/**\n * Translates the list format produced by css-loader into something\n * easier to manipulate.\n */\nexport default function listToStyles (parentId, list) {\n var styles = []\n var newStyles = {}\n for (var i = 0; i < list.length; i++) {\n var item = list[i]\n var id = item[0]\n var css = item[1]\n var media = item[2]\n var sourceMap = item[3]\n var part = {\n id: parentId + ':' + i,\n css: css,\n media: media,\n sourceMap: sourceMap\n }\n if (!newStyles[id]) {\n styles.push(newStyles[id] = { id: id, parts: [part] })\n } else {\n newStyles[id].parts.push(part)\n }\n }\n return styles\n}\n","/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n Modified by Evan You @yyx990803\n*/\n\nimport listToStyles from './listToStyles'\n\nvar hasDocument = typeof document !== 'undefined'\n\nif (typeof DEBUG !== 'undefined' && DEBUG) {\n if (!hasDocument) {\n throw new Error(\n 'vue-style-loader cannot be used in a non-browser environment. ' +\n \"Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.\"\n ) }\n}\n\n/*\ntype StyleObject = {\n id: number;\n parts: Array<StyleObjectPart>\n}\n\ntype StyleObjectPart = {\n css: string;\n media: string;\n sourceMap: ?string\n}\n*/\n\nvar stylesInDom = {/*\n [id: number]: {\n id: number,\n refs: number,\n parts: Array<(obj?: StyleObjectPart) => void>\n }\n*/}\n\nvar head = hasDocument && (document.head || document.getElementsByTagName('head')[0])\nvar singletonElement = null\nvar singletonCounter = 0\nvar isProduction = false\nvar noop = function () {}\nvar options = null\nvar ssrIdKey = 'data-vue-ssr-id'\n\n// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n// tags it will allow on a page\nvar isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase())\n\nexport default function addStylesClient (parentId, list, _isProduction, _options) {\n isProduction = _isProduction\n\n options = _options || {}\n\n var styles = listToStyles(parentId, list)\n addStylesToDom(styles)\n\n return function update (newList) {\n var mayRemove = []\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n domStyle.refs--\n mayRemove.push(domStyle)\n }\n if (newList) {\n styles = listToStyles(parentId, newList)\n addStylesToDom(styles)\n } else {\n styles = []\n }\n for (var i = 0; i < mayRemove.length; i++) {\n var domStyle = mayRemove[i]\n if (domStyle.refs === 0) {\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j]()\n }\n delete stylesInDom[domStyle.id]\n }\n }\n }\n}\n\nfunction addStylesToDom (styles /* Array<StyleObject> */) {\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n if (domStyle) {\n domStyle.refs++\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j](item.parts[j])\n }\n for (; j < item.parts.length; j++) {\n domStyle.parts.push(addStyle(item.parts[j]))\n }\n if (domStyle.parts.length > item.parts.length) {\n domStyle.parts.length = item.parts.length\n }\n } else {\n var parts = []\n for (var j = 0; j < item.parts.length; j++) {\n parts.push(addStyle(item.parts[j]))\n }\n stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts }\n }\n }\n}\n\nfunction createStyleElement () {\n var styleElement = document.createElement('style')\n styleElement.type = 'text/css'\n head.appendChild(styleElement)\n return styleElement\n}\n\nfunction addStyle (obj /* StyleObjectPart */) {\n var update, remove\n var styleElement = document.querySelector('style[' + ssrIdKey + '~=\"' + obj.id + '\"]')\n\n if (styleElement) {\n if (isProduction) {\n // has SSR styles and in production mode.\n // simply do nothing.\n return noop\n } else {\n // has SSR styles but in dev mode.\n // for some reason Chrome can't handle source map in server-rendered\n // style tags - source maps in <style> only works if the style tag is\n // created and inserted dynamically. So we remove the server rendered\n // styles and inject new ones.\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n if (isOldIE) {\n // use singleton mode for IE9.\n var styleIndex = singletonCounter++\n styleElement = singletonElement || (singletonElement = createStyleElement())\n update = applyToSingletonTag.bind(null, styleElement, styleIndex, false)\n remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true)\n } else {\n // use multi-style-tag mode in all other cases\n styleElement = createStyleElement()\n update = applyToTag.bind(null, styleElement)\n remove = function () {\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n update(obj)\n\n return function updateStyle (newObj /* StyleObjectPart */) {\n if (newObj) {\n if (newObj.css === obj.css &&\n newObj.media === obj.media &&\n newObj.sourceMap === obj.sourceMap) {\n return\n }\n update(obj = newObj)\n } else {\n remove()\n }\n }\n}\n\nvar replaceText = (function () {\n var textStore = []\n\n return function (index, replacement) {\n textStore[index] = replacement\n return textStore.filter(Boolean).join('\\n')\n }\n})()\n\nfunction applyToSingletonTag (styleElement, index, remove, obj) {\n var css = remove ? '' : obj.css\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = replaceText(index, css)\n } else {\n var cssNode = document.createTextNode(css)\n var childNodes = styleElement.childNodes\n if (childNodes[index]) styleElement.removeChild(childNodes[index])\n if (childNodes.length) {\n styleElement.insertBefore(cssNode, childNodes[index])\n } else {\n styleElement.appendChild(cssNode)\n }\n }\n}\n\nfunction applyToTag (styleElement, obj) {\n var css = obj.css\n var media = obj.media\n var sourceMap = obj.sourceMap\n\n if (media) {\n styleElement.setAttribute('media', media)\n }\n if (options.ssrId) {\n styleElement.setAttribute(ssrIdKey, obj.id)\n }\n\n if (sourceMap) {\n // https://developer.chrome.com/devtools/docs/javascript-debugging\n // this makes source maps inside style tags work properly in Chrome\n css += '\\n/*# sourceURL=' + sourceMap.sources[0] + ' */'\n // http://stackoverflow.com/a/26603875\n css += '\\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'\n }\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild)\n }\n styleElement.appendChild(document.createTextNode(css))\n }\n}\n","export * from \"-!../../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\"","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \".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}\", \"\"]);\n\n// exports\n","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../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\");\nif(content.__esModule) content = content.default;\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar add = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\").default\nvar update = add(\"2c53b590\", content, true, {\"sourceMap\":false,\"shadowMode\":false});","// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n require('current-script-polyfill')\n }\n\n var i\n if ((i = window.document.currentScript) && (i = i.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/))) {\n __webpack_public_path__ = i[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","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)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<template>\r\n <div ref=\"behaviorMonitor\" class=\"user-behavior-monitor\">\r\n <!-- 提示框 -->\r\n <el-dialog\r\n :visible.sync=\"showWarning\"\r\n :show-close=\"false\"\r\n :modal=\"true\"\r\n width=\"30%\"\r\n center\r\n custom-class=\"behavior-warning-dialog\"\r\n :append-to-body=\"true\"\r\n :modal-append-to-body=\"true\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n >\r\n <span>{{ warningMessage }}</span>\r\n </el-dialog>\r\n\r\n\r\n <button @click=\"testWarning\" style=\"position: fixed; top: 10px; right: 10px; z-index: 10000;\">\r\n 测试警告\r\n </button>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nexport default {\r\n name: 'UserBehaviorMonitor',\r\n props: {\r\n // WebSocket服务器地址\r\n websocketUrl: {\r\n type: String,\r\n required: true\r\n },\r\n // 倒计时时长(分钟)\r\n timeoutMinutes: {\r\n type: Number,\r\n default: 10\r\n },\r\n // 警告提前时间(分钟)\r\n warningMinutes: {\r\n type: Number,\r\n default: 1\r\n }\r\n },\r\n data() {\r\n return {\r\n mouseMoveThrottled:false,\r\n websocket: null,\r\n countdownTimer: null,\r\n warningTimer: null,\r\n showWarning: false,\r\n warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,\r\n lastActivityTime: null,\r\n isMonitoring: false\r\n };\r\n },\r\n mounted() {\r\n console.log('开始开始! mounted');\r\n this.initMonitor();\r\n },\r\n beforeDestroy() {\r\n console.log('开始开始! beforeDestroy');\r\n this.destroyMonitor();\r\n },\r\n methods: {\r\n testWarning() {\r\n console.log('Testing warning display');\r\n this.showWarning = true;\r\n },\r\n // 初始化监控\r\n initMonitor() {\r\n console.log('Initializing monitor');\r\n if (this.isMonitoring) return;\r\n \r\n this.isMonitoring = true;\r\n this.lastActivityTime = Date.now();\r\n \r\n // 启动倒计时\r\n this.startCountdown();\r\n \r\n // 绑定事件监听器\r\n this.bindEventListeners();\r\n },\r\n \r\n // 销毁监控\r\n destroyMonitor() {\r\n this.isMonitoring = false;\r\n \r\n // 清除定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n if (this.warningTimer) clearTimeout(this.warningTimer);\r\n \r\n // 解绑事件监听器\r\n this.unbindEventListeners();\r\n },\r\n \r\n // 发送用户行为数据到后端\r\n sendUserBehavior(data) {\r\n // 用于测试:在控制台输出用户行为信息\r\n console.log('用户行为监测:', data);\r\n },\r\n \r\n // 绑定事件监听器\r\n bindEventListeners() {\r\n console.log('Binding event listeners');\r\n // 使用箭头函数或bind来保持this上下文\r\n // 鼠标事件\r\n document.addEventListener('click', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('dblclick', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mousedown', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mouseup', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mousemove', this.handleMouseMove.bind(this), true);\r\n document.addEventListener('mouseover', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('mouseout', this.handleUserActivity.bind(this), true);\r\n \r\n // 键盘事件\r\n document.addEventListener('keydown', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('keyup', this.handleUserActivity.bind(this), true);\r\n \r\n // 表单事件\r\n document.addEventListener('input', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('change', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('focus', this.handleUserActivity.bind(this), true);\r\n document.addEventListener('blur', this.handleUserActivity.bind(this), true);\r\n \r\n // 滚动事件(防抖处理)\r\n document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);\r\n \r\n // 窗口事件\r\n window.addEventListener('resize', this.handleUserActivity.bind(this), true);\r\n window.addEventListener('beforeunload', this.handleBeforeUnload.bind(this));\r\n },\r\n \r\n // 解绑事件监听器\r\n unbindEventListeners() {\r\n console.log('Unbinding event listeners');\r\n // 解绑时也要使用相同的方式\r\n document.removeEventListener('click', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('dblclick', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mousedown', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mouseup', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mousemove', this.handleMouseMove.bind(this), true);\r\n document.removeEventListener('mouseover', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('mouseout', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('keydown', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('keyup', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('input', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('change', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('focus', this.handleUserActivity.bind(this), true);\r\n document.removeEventListener('blur', this.handleUserActivity.bind(this), true);\r\n \r\n document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);\r\n \r\n window.removeEventListener('resize', this.handleUserActivity.bind(this), true);\r\n window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));\r\n },\r\n \r\n // 处理用户活动\r\n handleUserActivity(event) {\r\n // 过滤掉自动触发的事件\r\n if (this.isAutomaticEvent(event)) return;\r\n \r\n this.resetTimer();\r\n \r\n // 发送用户行为数据\r\n const behaviorData = {\r\n eventType: event.type,\r\n target: event.target.tagName,\r\n timestamp: Date.now(),\r\n url: window.location.href\r\n };\r\n \r\n // 添加特定事件的额外信息\r\n if (event.type === 'click') {\r\n behaviorData.clientX = event.clientX;\r\n behaviorData.clientY = event.clientY;\r\n } else if (event.type === 'keydown') {\r\n behaviorData.key = event.key;\r\n behaviorData.ctrlKey = event.ctrlKey;\r\n behaviorData.altKey = event.altKey;\r\n behaviorData.shiftKey = event.shiftKey;\r\n }\r\n \r\n this.sendUserBehavior(behaviorData);\r\n },\r\n handleMouseMove(event) {\r\n if (!this.mouseMoveThrottled) {\r\n this.handleUserActivity(event);\r\n this.mouseMoveThrottled = true;\r\n setTimeout(() => {\r\n this.mouseMoveThrottled = false;\r\n }, 500);\r\n }\r\n },\r\n \r\n // 处理鼠标移动(降低频率)\r\n // handleMouseMove: function() {\r\n // let isThrottled = false;\r\n // return (event) => {\r\n // if (!isThrottled) {\r\n // this.handleUserActivity(event);\r\n // isThrottled = true;\r\n // setTimeout(() => {\r\n // isThrottled = false;\r\n // }, 500);\r\n // }\r\n // };\r\n // }(),\r\n \r\n // 判断是否为自动触发事件\r\n isAutomaticEvent(event) {\r\n // 自动刷新等非用户主动触发的事件\r\n if (event.type === 'scroll' && !this.isUserScrolling) {\r\n return true;\r\n }\r\n return false;\r\n },\r\n \r\n // 防抖函数\r\n debounce(func, wait) {\r\n let timeout;\r\n return function executedFunction(...args) {\r\n const later = () => {\r\n clearTimeout(timeout);\r\n func.apply(this, args);\r\n };\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n };\r\n },\r\n \r\n // 重置计时器\r\n resetTimer() {\r\n console.log('Resetting timer');\r\n this.lastActivityTime = Date.now();\r\n this.showWarning = false;\r\n \r\n // 清除警告定时器\r\n if (this.warningTimer) {\r\n clearTimeout(this.warningTimer);\r\n this.warningTimer = null;\r\n }\r\n \r\n // 重新启动倒计时\r\n this.startCountdown();\r\n \r\n this.$emit('user-active');\r\n },\r\n \r\n // 启动倒计时\r\n startCountdown() {\r\n console.log('Starting countdown');\r\n // 清除现有定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n \r\n // 设置新的倒计时\r\n this.countdownTimer = setInterval(() => {\r\n const now = Date.now();\r\n const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 60);\r\n console.log('Elapsed minutes:', elapsedMinutes);\r\n \r\n // 检查是否需要显示警告\r\n if (elapsedMinutes >= (this.timeoutMinutes - this.warningMinutes) && !this.warningTimer) {\r\n console.log('Showing warning');\r\n this.showWarningWarning();\r\n }\r\n \r\n // 检查是否超时\r\n if (elapsedMinutes >= this.timeoutMinutes) {\r\n console.log('Handling timeout');\r\n this.handleTimeout();\r\n }\r\n }, 1000);\r\n },\r\n \r\n // 显示超时警告\r\n showWarningWarning() {\r\n console.log('Setting showWarning to true');\r\n this.showWarning = true;\r\n this.$emit('timeout-warning');\r\n \r\n // 设置超时处理\r\n this.warningTimer = setTimeout(() => {\r\n this.handleTimeout();\r\n }, this.warningMinutes * 60 * 1000);\r\n },\r\n \r\n // 处理超时\r\n handleTimeout() {\r\n console.log('Handling timeout');\r\n this.showWarning = false;\r\n this.$emit('timeout');\r\n \r\n // 执行登出逻辑\r\n this.logout();\r\n },\r\n \r\n // 登出操作\r\n logout() {\r\n // 用于测试:在控制台输出登出信息\r\n console.log('用户超时登出');\r\n \r\n this.$emit('logout');\r\n \r\n // 清除定时器\r\n if (this.countdownTimer) clearInterval(this.countdownTimer);\r\n if (this.warningTimer) clearTimeout(this.warningTimer);\r\n },\r\n \r\n // 处理页面卸载前的操作\r\n handleBeforeUnload(event) {\r\n // 用于测试:在控制台输出页面卸载信息\r\n console.log('页面即将卸载');\r\n },\r\n \r\n // 手动重置监控\r\n reset() {\r\n this.resetTimer();\r\n }\r\n }\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.user-behavior-monitor {\r\n display: none;\r\n}\r\n\r\n/* 使用深度选择器确保样式正确应用 */\r\n.behavior-warning-dialog ::v-deep .el-dialog__body {\r\n text-align: center;\r\n font-size: 16px;\r\n padding: 30px 20px;\r\n}\r\n\r\n/* 确保弹框在最上层 */\r\n.behavior-warning-dialog {\r\n z-index: 9999 !important;\r\n}\r\n</style>","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserBehaviorMonitor.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserBehaviorMonitor.vue?vue&type=script&lang=js\"","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent(\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier /* server only */,\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options =\n typeof scriptExports === 'function' ? scriptExports.options : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) {\n // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () {\n injectStyles.call(\n this,\n (options.functional ? this.parent : this).$root.$options.shadowRoot\n )\n }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functional component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection(h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing ? [].concat(existing, hook) : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","import { render, staticRenderFns } from \"./UserBehaviorMonitor.vue?vue&type=template&id=06a138e4&scoped=true\"\nimport script from \"./UserBehaviorMonitor.vue?vue&type=script&lang=js\"\nexport * from \"./UserBehaviorMonitor.vue?vue&type=script&lang=js\"\nimport style0 from \"./UserBehaviorMonitor.vue?vue&type=style&index=0&id=06a138e4&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"06a138e4\",\n null\n \n)\n\nexport default component.exports","import UserBehaviorMonitor from './components/UserBehaviorMonitor.vue';\r\n\r\n// 为使用 CDN 方式引入的用户提供组件注册方法\r\nUserBehaviorMonitor.install = function(Vue) {\r\n Vue.component(UserBehaviorMonitor.name, UserBehaviorMonitor);\r\n};\r\n\r\n// 导出组件\r\nexport default UserBehaviorMonitor;\r\n\r\n// 如果是直接引入文件,则自动注册组件\r\nif (typeof window !== 'undefined' && window.Vue) {\r\n UserBehaviorMonitor.install(window.Vue);\r\n}\r\n\r\n// 同时支持按需导入\r\nexport { UserBehaviorMonitor };","import './setPublicPath'\nimport mod from '~entry'\nexport default mod\nexport * from '~entry'\n"],"sourceRoot":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "user-behavior-monitor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vue component for monitoring user behavior and auto-logout",
|
|
5
|
+
"main": "dist/user-behavior-monitor.umd.min.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/*",
|
|
8
|
+
"src/*"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "vue-cli-service build --target lib --name user-behavior-monitor src/index.js",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"element-ui": "^2.15.0"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"vue": "^2.5.2"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@vue/cli-service": "^3.12.1",
|
|
22
|
+
"vue": "^2.5.2",
|
|
23
|
+
"vue-template-compiler": "^2.5.2"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"vue",
|
|
27
|
+
"component",
|
|
28
|
+
"user-behavior",
|
|
29
|
+
"monitoring"
|
|
30
|
+
],
|
|
31
|
+
"author": "linmingchuang",
|
|
32
|
+
"license": "MIT"
|
|
33
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="behaviorMonitor" class="user-behavior-monitor">
|
|
3
|
+
<!-- 提示框 -->
|
|
4
|
+
<el-dialog
|
|
5
|
+
:visible.sync="showWarning"
|
|
6
|
+
:show-close="false"
|
|
7
|
+
:modal="true"
|
|
8
|
+
width="30%"
|
|
9
|
+
center
|
|
10
|
+
custom-class="behavior-warning-dialog"
|
|
11
|
+
:append-to-body="true"
|
|
12
|
+
:modal-append-to-body="true"
|
|
13
|
+
:close-on-click-modal="false"
|
|
14
|
+
:close-on-press-escape="false"
|
|
15
|
+
>
|
|
16
|
+
<span>{{ warningMessage }}</span>
|
|
17
|
+
</el-dialog>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
<button @click="testWarning" style="position: fixed; top: 10px; right: 10px; z-index: 10000;">
|
|
21
|
+
测试警告
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
export default {
|
|
28
|
+
name: 'UserBehaviorMonitor',
|
|
29
|
+
props: {
|
|
30
|
+
// WebSocket服务器地址
|
|
31
|
+
websocketUrl: {
|
|
32
|
+
type: String,
|
|
33
|
+
required: true
|
|
34
|
+
},
|
|
35
|
+
// 倒计时时长(分钟)
|
|
36
|
+
timeoutMinutes: {
|
|
37
|
+
type: Number,
|
|
38
|
+
default: 10
|
|
39
|
+
},
|
|
40
|
+
// 警告提前时间(分钟)
|
|
41
|
+
warningMinutes: {
|
|
42
|
+
type: Number,
|
|
43
|
+
default: 1
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
data() {
|
|
47
|
+
return {
|
|
48
|
+
mouseMoveThrottled:false,
|
|
49
|
+
websocket: null,
|
|
50
|
+
countdownTimer: null,
|
|
51
|
+
warningTimer: null,
|
|
52
|
+
showWarning: false,
|
|
53
|
+
warningMessage: `您已${this.timeoutMinutes}分钟未操作,将在${this.warningMinutes}分钟后自动退出`,
|
|
54
|
+
lastActivityTime: null,
|
|
55
|
+
isMonitoring: false
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
mounted() {
|
|
59
|
+
console.log('开始开始! mounted');
|
|
60
|
+
this.initMonitor();
|
|
61
|
+
},
|
|
62
|
+
beforeDestroy() {
|
|
63
|
+
console.log('开始开始! beforeDestroy');
|
|
64
|
+
this.destroyMonitor();
|
|
65
|
+
},
|
|
66
|
+
methods: {
|
|
67
|
+
testWarning() {
|
|
68
|
+
console.log('Testing warning display');
|
|
69
|
+
this.showWarning = true;
|
|
70
|
+
},
|
|
71
|
+
// 初始化监控
|
|
72
|
+
initMonitor() {
|
|
73
|
+
console.log('Initializing monitor');
|
|
74
|
+
if (this.isMonitoring) return;
|
|
75
|
+
|
|
76
|
+
this.isMonitoring = true;
|
|
77
|
+
this.lastActivityTime = Date.now();
|
|
78
|
+
|
|
79
|
+
// 启动倒计时
|
|
80
|
+
this.startCountdown();
|
|
81
|
+
|
|
82
|
+
// 绑定事件监听器
|
|
83
|
+
this.bindEventListeners();
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// 销毁监控
|
|
87
|
+
destroyMonitor() {
|
|
88
|
+
this.isMonitoring = false;
|
|
89
|
+
|
|
90
|
+
// 清除定时器
|
|
91
|
+
if (this.countdownTimer) clearInterval(this.countdownTimer);
|
|
92
|
+
if (this.warningTimer) clearTimeout(this.warningTimer);
|
|
93
|
+
|
|
94
|
+
// 解绑事件监听器
|
|
95
|
+
this.unbindEventListeners();
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// 发送用户行为数据到后端
|
|
99
|
+
sendUserBehavior(data) {
|
|
100
|
+
// 用于测试:在控制台输出用户行为信息
|
|
101
|
+
console.log('用户行为监测:', data);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
// 绑定事件监听器
|
|
105
|
+
bindEventListeners() {
|
|
106
|
+
console.log('Binding event listeners');
|
|
107
|
+
// 使用箭头函数或bind来保持this上下文
|
|
108
|
+
// 鼠标事件
|
|
109
|
+
document.addEventListener('click', this.handleUserActivity.bind(this), true);
|
|
110
|
+
document.addEventListener('dblclick', this.handleUserActivity.bind(this), true);
|
|
111
|
+
document.addEventListener('mousedown', this.handleUserActivity.bind(this), true);
|
|
112
|
+
document.addEventListener('mouseup', this.handleUserActivity.bind(this), true);
|
|
113
|
+
document.addEventListener('mousemove', this.handleMouseMove.bind(this), true);
|
|
114
|
+
document.addEventListener('mouseover', this.handleUserActivity.bind(this), true);
|
|
115
|
+
document.addEventListener('mouseout', this.handleUserActivity.bind(this), true);
|
|
116
|
+
|
|
117
|
+
// 键盘事件
|
|
118
|
+
document.addEventListener('keydown', this.handleUserActivity.bind(this), true);
|
|
119
|
+
document.addEventListener('keyup', this.handleUserActivity.bind(this), true);
|
|
120
|
+
|
|
121
|
+
// 表单事件
|
|
122
|
+
document.addEventListener('input', this.handleUserActivity.bind(this), true);
|
|
123
|
+
document.addEventListener('change', this.handleUserActivity.bind(this), true);
|
|
124
|
+
document.addEventListener('focus', this.handleUserActivity.bind(this), true);
|
|
125
|
+
document.addEventListener('blur', this.handleUserActivity.bind(this), true);
|
|
126
|
+
|
|
127
|
+
// 滚动事件(防抖处理)
|
|
128
|
+
document.addEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);
|
|
129
|
+
|
|
130
|
+
// 窗口事件
|
|
131
|
+
window.addEventListener('resize', this.handleUserActivity.bind(this), true);
|
|
132
|
+
window.addEventListener('beforeunload', this.handleBeforeUnload.bind(this));
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
// 解绑事件监听器
|
|
136
|
+
unbindEventListeners() {
|
|
137
|
+
console.log('Unbinding event listeners');
|
|
138
|
+
// 解绑时也要使用相同的方式
|
|
139
|
+
document.removeEventListener('click', this.handleUserActivity.bind(this), true);
|
|
140
|
+
document.removeEventListener('dblclick', this.handleUserActivity.bind(this), true);
|
|
141
|
+
document.removeEventListener('mousedown', this.handleUserActivity.bind(this), true);
|
|
142
|
+
document.removeEventListener('mouseup', this.handleUserActivity.bind(this), true);
|
|
143
|
+
document.removeEventListener('mousemove', this.handleMouseMove.bind(this), true);
|
|
144
|
+
document.removeEventListener('mouseover', this.handleUserActivity.bind(this), true);
|
|
145
|
+
document.removeEventListener('mouseout', this.handleUserActivity.bind(this), true);
|
|
146
|
+
|
|
147
|
+
document.removeEventListener('keydown', this.handleUserActivity.bind(this), true);
|
|
148
|
+
document.removeEventListener('keyup', this.handleUserActivity.bind(this), true);
|
|
149
|
+
|
|
150
|
+
document.removeEventListener('input', this.handleUserActivity.bind(this), true);
|
|
151
|
+
document.removeEventListener('change', this.handleUserActivity.bind(this), true);
|
|
152
|
+
document.removeEventListener('focus', this.handleUserActivity.bind(this), true);
|
|
153
|
+
document.removeEventListener('blur', this.handleUserActivity.bind(this), true);
|
|
154
|
+
|
|
155
|
+
document.removeEventListener('scroll', this.debounce(this.handleUserActivity, 300).bind(this), true);
|
|
156
|
+
|
|
157
|
+
window.removeEventListener('resize', this.handleUserActivity.bind(this), true);
|
|
158
|
+
window.removeEventListener('beforeunload', this.handleBeforeUnload.bind(this));
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// 处理用户活动
|
|
162
|
+
handleUserActivity(event) {
|
|
163
|
+
// 过滤掉自动触发的事件
|
|
164
|
+
if (this.isAutomaticEvent(event)) return;
|
|
165
|
+
|
|
166
|
+
this.resetTimer();
|
|
167
|
+
|
|
168
|
+
// 发送用户行为数据
|
|
169
|
+
const behaviorData = {
|
|
170
|
+
eventType: event.type,
|
|
171
|
+
target: event.target.tagName,
|
|
172
|
+
timestamp: Date.now(),
|
|
173
|
+
url: window.location.href
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// 添加特定事件的额外信息
|
|
177
|
+
if (event.type === 'click') {
|
|
178
|
+
behaviorData.clientX = event.clientX;
|
|
179
|
+
behaviorData.clientY = event.clientY;
|
|
180
|
+
} else if (event.type === 'keydown') {
|
|
181
|
+
behaviorData.key = event.key;
|
|
182
|
+
behaviorData.ctrlKey = event.ctrlKey;
|
|
183
|
+
behaviorData.altKey = event.altKey;
|
|
184
|
+
behaviorData.shiftKey = event.shiftKey;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.sendUserBehavior(behaviorData);
|
|
188
|
+
},
|
|
189
|
+
handleMouseMove(event) {
|
|
190
|
+
if (!this.mouseMoveThrottled) {
|
|
191
|
+
this.handleUserActivity(event);
|
|
192
|
+
this.mouseMoveThrottled = true;
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
this.mouseMoveThrottled = false;
|
|
195
|
+
}, 500);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
// 处理鼠标移动(降低频率)
|
|
200
|
+
// handleMouseMove: function() {
|
|
201
|
+
// let isThrottled = false;
|
|
202
|
+
// return (event) => {
|
|
203
|
+
// if (!isThrottled) {
|
|
204
|
+
// this.handleUserActivity(event);
|
|
205
|
+
// isThrottled = true;
|
|
206
|
+
// setTimeout(() => {
|
|
207
|
+
// isThrottled = false;
|
|
208
|
+
// }, 500);
|
|
209
|
+
// }
|
|
210
|
+
// };
|
|
211
|
+
// }(),
|
|
212
|
+
|
|
213
|
+
// 判断是否为自动触发事件
|
|
214
|
+
isAutomaticEvent(event) {
|
|
215
|
+
// 自动刷新等非用户主动触发的事件
|
|
216
|
+
if (event.type === 'scroll' && !this.isUserScrolling) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
// 防抖函数
|
|
223
|
+
debounce(func, wait) {
|
|
224
|
+
let timeout;
|
|
225
|
+
return function executedFunction(...args) {
|
|
226
|
+
const later = () => {
|
|
227
|
+
clearTimeout(timeout);
|
|
228
|
+
func.apply(this, args);
|
|
229
|
+
};
|
|
230
|
+
clearTimeout(timeout);
|
|
231
|
+
timeout = setTimeout(later, wait);
|
|
232
|
+
};
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
// 重置计时器
|
|
236
|
+
resetTimer() {
|
|
237
|
+
console.log('Resetting timer');
|
|
238
|
+
this.lastActivityTime = Date.now();
|
|
239
|
+
this.showWarning = false;
|
|
240
|
+
|
|
241
|
+
// 清除警告定时器
|
|
242
|
+
if (this.warningTimer) {
|
|
243
|
+
clearTimeout(this.warningTimer);
|
|
244
|
+
this.warningTimer = null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 重新启动倒计时
|
|
248
|
+
this.startCountdown();
|
|
249
|
+
|
|
250
|
+
this.$emit('user-active');
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
// 启动倒计时
|
|
254
|
+
startCountdown() {
|
|
255
|
+
console.log('Starting countdown');
|
|
256
|
+
// 清除现有定时器
|
|
257
|
+
if (this.countdownTimer) clearInterval(this.countdownTimer);
|
|
258
|
+
|
|
259
|
+
// 设置新的倒计时
|
|
260
|
+
this.countdownTimer = setInterval(() => {
|
|
261
|
+
const now = Date.now();
|
|
262
|
+
const elapsedMinutes = (now - this.lastActivityTime) / (1000 * 60);
|
|
263
|
+
console.log('Elapsed minutes:', elapsedMinutes);
|
|
264
|
+
|
|
265
|
+
// 检查是否需要显示警告
|
|
266
|
+
if (elapsedMinutes >= (this.timeoutMinutes - this.warningMinutes) && !this.warningTimer) {
|
|
267
|
+
console.log('Showing warning');
|
|
268
|
+
this.showWarningWarning();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 检查是否超时
|
|
272
|
+
if (elapsedMinutes >= this.timeoutMinutes) {
|
|
273
|
+
console.log('Handling timeout');
|
|
274
|
+
this.handleTimeout();
|
|
275
|
+
}
|
|
276
|
+
}, 1000);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
// 显示超时警告
|
|
280
|
+
showWarningWarning() {
|
|
281
|
+
console.log('Setting showWarning to true');
|
|
282
|
+
this.showWarning = true;
|
|
283
|
+
this.$emit('timeout-warning');
|
|
284
|
+
|
|
285
|
+
// 设置超时处理
|
|
286
|
+
this.warningTimer = setTimeout(() => {
|
|
287
|
+
this.handleTimeout();
|
|
288
|
+
}, this.warningMinutes * 60 * 1000);
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
// 处理超时
|
|
292
|
+
handleTimeout() {
|
|
293
|
+
console.log('Handling timeout');
|
|
294
|
+
this.showWarning = false;
|
|
295
|
+
this.$emit('timeout');
|
|
296
|
+
|
|
297
|
+
// 执行登出逻辑
|
|
298
|
+
this.logout();
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
// 登出操作
|
|
302
|
+
logout() {
|
|
303
|
+
// 用于测试:在控制台输出登出信息
|
|
304
|
+
console.log('用户超时登出');
|
|
305
|
+
|
|
306
|
+
this.$emit('logout');
|
|
307
|
+
|
|
308
|
+
// 清除定时器
|
|
309
|
+
if (this.countdownTimer) clearInterval(this.countdownTimer);
|
|
310
|
+
if (this.warningTimer) clearTimeout(this.warningTimer);
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
// 处理页面卸载前的操作
|
|
314
|
+
handleBeforeUnload(event) {
|
|
315
|
+
// 用于测试:在控制台输出页面卸载信息
|
|
316
|
+
console.log('页面即将卸载');
|
|
317
|
+
},
|
|
318
|
+
|
|
319
|
+
// 手动重置监控
|
|
320
|
+
reset() {
|
|
321
|
+
this.resetTimer();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
</script>
|
|
326
|
+
|
|
327
|
+
<style scoped>
|
|
328
|
+
.user-behavior-monitor {
|
|
329
|
+
display: none;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* 使用深度选择器确保样式正确应用 */
|
|
333
|
+
.behavior-warning-dialog ::v-deep .el-dialog__body {
|
|
334
|
+
text-align: center;
|
|
335
|
+
font-size: 16px;
|
|
336
|
+
padding: 30px 20px;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* 确保弹框在最上层 */
|
|
340
|
+
.behavior-warning-dialog {
|
|
341
|
+
z-index: 9999 !important;
|
|
342
|
+
}
|
|
343
|
+
</style>
|