├── .babelrc ├── .gitattributes ├── .gitignore ├── README.md ├── build └── quasar.js ├── cooking.conf.js ├── dist-0.3.0 ├── 0.1c4d4bb.js ├── 1.19a6aa8.js ├── MaterialIcons-Regular.012cf6a.woff ├── alert.531144d.mp3 ├── app.ce7030f.js ├── index.html └── manifest.7ce5866.js ├── dist-0.5.0 ├── 0.5611f24.js ├── 1.4855d68.js ├── MaterialIcons-Regular.012cf6a.woff ├── alert.531144d.mp3 ├── app.25bdeac.js ├── error.60b36c7.mp3 ├── fatal.36a9dd6.mp3 ├── index.html ├── manifest.0f3c3b5.js └── warn.f629ee5.mp3 ├── dist-0.6.0 ├── 0.6f1376d.js ├── 1.f89ee1c.js ├── MaterialIcons-Regular.012cf6a.woff ├── alert.531144d.mp3 ├── app.13fc557.js ├── error.60b36c7.mp3 ├── fatal.36a9dd6.mp3 ├── index.html ├── manifest.ed4e4aa.js └── warn.f629ee5.mp3 ├── dist-0.7.0 ├── 0.9199fd1.js ├── 1.0598766.js ├── MaterialIcons-Regular.012cf6a.woff ├── alert.531144d.mp3 ├── app.0bec6dc.js ├── app.6829ae9.css ├── echarts.deeae58.js ├── error.60b36c7.mp3 ├── fatal.36a9dd6.mp3 ├── index.html ├── manifest.1ef3136.js ├── mock.ace2ecd.js ├── quasar.3765f68.js ├── quasar.913c589.css ├── vue.4c2b1b0.js └── warn.f629ee5.mp3 ├── dist ├── 0.73fed4a.js ├── 1.99eb6e9.js ├── 2.dffdcc4.js ├── MaterialIcons-Regular.012cf6a.woff ├── alert.b8116c7.mp3 ├── app.5421bda.js ├── app.eea114c.css ├── echarts.ef8e2bb.js ├── error.29e5668.mp3 ├── fatal.8a322db.mp3 ├── index.html ├── manifest.359d8b1.js ├── mock.1689539.js ├── quasar.66a770c.js ├── quasar.913c589.css ├── vue.cda0fbf.js └── warn.8de28bd.mp3 ├── mock ├── index.js ├── modules │ ├── event.js │ ├── random.js │ └── string.js └── service │ ├── datas │ ├── business.js │ ├── database.js │ ├── exception.js │ ├── index.js │ └── system.js │ ├── index.js │ ├── request │ ├── axios.js │ ├── index.js │ ├── socket.js │ └── util.js │ └── respond │ ├── axios.js │ ├── index.js │ └── socket.js ├── package.json ├── quasar.conf.js └── src ├── assets ├── _raw │ ├── alert.mp3 │ ├── error.mp3 │ ├── fatal.mp3 │ └── warn.mp3 ├── alert.mp3 ├── error.mp3 ├── fatal.mp3 ├── favicon.png └── warn.mp3 ├── components ├── echarts.vue ├── q-item-group.vue └── q-item-ratio.vue ├── config └── echarts.js ├── filters ├── formatByte.js └── formatDate.js ├── frames ├── app.vue ├── login.vue └── main.vue ├── index.html ├── main.js ├── pages ├── business.vue ├── dashboard.vue ├── database.vue ├── database │ ├── detail.vue │ └── list.vue ├── exception.vue ├── form.vue ├── server │ ├── detail.vue │ └── list.vue └── system.vue ├── quasar.js ├── quasar.styl ├── router └── index.js └── service ├── config.js ├── index.js ├── request ├── axios.js ├── index.js └── socket.js └── urls └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["es2015", { "modules": false }], "stage-2"], 3 | "comments": false, 4 | "plugins": [ 5 | ["transform-runtime", { "polyfill": false, "regenerator": false }] 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | # Custom 50 | *.log 51 | .git 52 | .svn 53 | .idea 54 | .cache 55 | node_modules 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Server Monitor 9 | 10 | 11 | ## Demo 12 | 13 | 14 | 15 | 16 | ## Initialization 17 | > Npm link Dependencies: `vue`, `vue-router`, `quasar`, `echarts` 18 | 19 | ```shell 20 | npm run init 21 | ``` 22 | 23 | ## Development 24 | > Run Local Server: http://localhost:8101 25 | 26 | ```shell 27 | npm run dev 28 | ``` 29 | 30 | ## Production 31 | > Build `src` to `dist` 32 | 33 | ``` 34 | npm run dist 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /build/quasar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Quasar Statment 4 | * ============================================================================= 5 | * 6 | * @for quasar-framework@0.15.6~0.15.10 7 | * 8 | * @author dondevi 9 | * @create 2018-03-23 10 | */ 11 | 12 | const fs = require("fs"); 13 | const path = require("path"); 14 | 15 | const quasarConfig = require("../quasar.conf.js")(); 16 | const quasarSymlink = path.resolve(__dirname, "../node_modules/quasar-framework"); 17 | const quasarDir = fs.realpathSync(quasarSymlink); 18 | 19 | 20 | // Generate Quasar Import 21 | function generateQuasarImport (type, theme = "mat", isStylus) { 22 | const folders = {}; 23 | return quasarConfig.framework[type].map(name => { 24 | const dirname = path.join(quasarDir, `src/${type}`); 25 | const filename = ("directives" === type ? toKebabCase(name) : name) + ".js"; 26 | const filepath = findFileSync(dirname, filename); 27 | if (!filepath) { 28 | console.log(`Quasar: [Warn] ${type} Not Found:`, name); 29 | return ""; 30 | } 31 | const moduleName = filepath.split(/node_modules[\/\\]/)[1].replace(/\\/g, "/"); 32 | const folderName = moduleName.replace(`/${filename}`, ""); 33 | if (!isStylus) { 34 | return `import ${name} from "${moduleName}";`; 35 | } 36 | if (!folders[folderName]) { 37 | folders[folderName] = true; 38 | return `@import "../node_modules/${folderName}/*.${theme}.styl";`; 39 | } 40 | return ""; 41 | }).filter(statment => statment).join("\n"); 42 | } 43 | 44 | 45 | // Generate file to /src 46 | function generateQuasarFile (theme = "mat") { 47 | console.log("Quasar:", "Generating..."); 48 | const quasarFilepath = path.resolve(__dirname, "../src/quasar.js"); 49 | const quasarComment = `\ 50 | // Generated automatically by build/quasar.js 51 | // ${new Date().toString()} 52 | // Don't Edit please! 53 | `; 54 | const quasarStylus = `${quasarComment} 55 | @import "../node_modules/quasar-framework/src/css/core.variables.styl"; 56 | @import "../node_modules/quasar-framework/src/css/variables.${theme}.styl"; 57 | @import "../node_modules/quasar-framework/src/css/normalize.styl"; 58 | // @import "../node_modules/quasar-framework/src/components/*/*.${theme}.styl"; 59 | ${generateQuasarImport("components", theme, true)} 60 | @import "../node_modules/quasar-framework/src/css/core/*.styl"; 61 | // @import "../node_modules/quasar-framework/src/ie-compat/ie.${theme}.styl"; 62 | `; 63 | const quasarStatment = `${quasarComment} 64 | // import "quasar-extras/roboto-font"; 65 | import "quasar-extras/material-icons"; 66 | 67 | // import "quasar-framework/dist/umd/quasar.${theme}.css"; 68 | import "./quasar.styl"; 69 | 70 | import install from "quasar-framework/src/install.js"; 71 | import icons from "quasar-framework/src/icons.js"; 72 | 73 | ${generateQuasarImport("components", theme)} 74 | ${generateQuasarImport("directives", theme)} 75 | 76 | export const Quasar = { install, icons }; 77 | export const QuasarComponents = { ${quasarConfig.framework.components.join(", ")} }; 78 | export const QuasarDirectives = { ${quasarConfig.framework.directives.join(", ")} }; 79 | `; 80 | fs.writeFileSync(quasarFilepath.replace(/js$/, "styl"), quasarStylus); 81 | fs.writeFileSync(quasarFilepath, quasarStatment); 82 | console.log("Quasar:", "Success to generate /src/quasar.js", "\n"); 83 | return quasarFilepath; 84 | } 85 | 86 | 87 | module.exports = generateQuasarFile; 88 | 89 | 90 | 91 | 92 | 93 | /** 94 | * Get file's path by name from directory 95 | * @param {String} dirname - directory path 96 | * @param {String} filename - file name 97 | * @return {String} - file path 98 | */ 99 | function findFileSync (dirname, filename) { 100 | if (!fs.existsSync(dirname)) { 101 | return console.log("[Warn] Directory Not Exist:", dirname); 102 | } 103 | const files = fs.readdirSync(dirname); 104 | const targetpath = path.join(dirname, filename); 105 | for (let i = 0, file; file = files[i]; i++) { 106 | let filepath = path.join(dirname, file); 107 | let filestat = fs.lstatSync(filepath); 108 | if (filestat.isDirectory()) { 109 | filepath = findFileSync(filepath, filename); 110 | if (filepath) { return filepath; } 111 | } else if (filepath === targetpath) { 112 | return filepath; 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * Format CamelCase to kebab-case 119 | * @param {String} string 120 | * @return {String} 121 | */ 122 | function toKebabCase (string) { 123 | return string.replace(/[A-Z]/g, (match, index) => { 124 | return (index ? "-" : "") + match.toLowerCase(); 125 | }); 126 | } 127 | -------------------------------------------------------------------------------- /cooking.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Cooking Config 4 | * ============================================================================= 5 | * 6 | * @see http://cookingjs.github.io/zh-cn/configuration.html 7 | * @see https://webpack.js.org/configuration/ 8 | * @permission Engineer 9 | * 10 | * @author dondevi 11 | * @create 2018-02-02 12 | * 13 | * @todo 2018-03-29 dondevi 14 | * 1.Split stylus code 15 | * 16 | * @update 2018-03-13 dondevi 17 | * @update 2018-03-21 dondevi 18 | * 1.Add: Babel for Quasar ! 19 | * @update 2018-03-22 dondevi 20 | * 1.Update: Chunk config ! 21 | * @update 2018-03-23 dondevi 22 | * 1.Add: build/quasar.js ! 23 | * @update 2018-04-02 dondevi 24 | * 1.Add: devServer.compress: true 25 | */ 26 | 27 | const fs = require("fs"); 28 | const path = require("path"); 29 | const cooking = require("cooking"); 30 | const webpack = require("webpack"); 31 | const isDev = "development" === process.env.NODE_ENV; 32 | 33 | 34 | let cookingConfig = { 35 | entry: { 36 | app: "src/main.js", 37 | mock: "mock/index.js", 38 | }, 39 | chunk: [ 40 | { name: "vue", chunks: ["app"], 41 | minChunks: module => /node_modules[\/\\]vue/.test(module.context), 42 | }, 43 | { name: "quasar", chunks: ["app"], 44 | minChunks: module => /node_modules[\/\\]quasar/.test(module.context), 45 | }, 46 | { name: "echarts", chunks: ["app"], 47 | minChunks: module => /node_modules[\/\\]echarts/.test(module.context), 48 | }, 49 | { name: "manifest", minChunks: Infinity }, 50 | ], 51 | template: { 52 | "index.html": { 53 | template: "src/index.html", chunksSortMode: "manual", 54 | chunks: ["manifest", "vue", "quasar", "echarts", "mock", "app"], 55 | }, 56 | }, 57 | 58 | dist: "dist", 59 | publicPath: "./", 60 | assetsPath: "./", 61 | 62 | hash: true, 63 | clean: true, 64 | postcss: [], 65 | /** 66 | * For stylus, you need to add below to {user_home}/.cooking/package.json: 67 | * devDependencies: { 68 | * "stylus": "^0.54.5", 69 | * "stylus-loader": "^3.0.1", 70 | * ... 71 | * } 72 | */ 73 | extends: ["vue2", "stylus", "autoprefixer"], 74 | minimize: true, 75 | // sourceMap: "cheap-module-eval-source-map", 76 | sourceMap: isDev ? "source-map" : false, 77 | extractCSS: true, 78 | 79 | alias: { 80 | "src": path.resolve(__dirname, "src"), 81 | "mock": path.resolve(__dirname, "mock"), 82 | "config": path.resolve(__dirname, "src/config"), 83 | "router": path.resolve(__dirname, "src/router"), 84 | "service": path.resolve(__dirname, "src/service"), 85 | "pages": path.resolve(__dirname, "src/pages"), 86 | "frames": path.resolve(__dirname, "src/frames"), 87 | "assets": path.resolve(__dirname, "src/assets"), 88 | "filters": path.resolve(__dirname, "src/filters"), 89 | "modules": path.resolve(__dirname, "src/modules"), 90 | "components": path.resolve(__dirname, "src/components"), 91 | }, 92 | 93 | devServer: { 94 | port: 8101, 95 | hostname: "0.0.0.0", 96 | publicPath: "/", 97 | contentBase: "dist", 98 | clean: false, 99 | compress: true, 100 | extractCSS: false, 101 | proxy: { 102 | "/monitorcenter-as-server/monitor/websocket/**": { 103 | changeOrigin: true, 104 | target: "ws://192.168.0.157:8900", // Development 105 | // target: "ws://crj.xfbm100.com", // Production 106 | ws: true, 107 | }, 108 | }, 109 | }, 110 | }; 111 | 112 | cooking.set(cookingConfig); 113 | 114 | cooking.add("loader.html", { 115 | test: /\.html$/, loader: "html-loader", 116 | options: { attrs: ["img:src", "link:href"] }, 117 | }); 118 | cooking.add("loader.mp3", { 119 | test: /\.mp3$/, loader: "url-loader", 120 | options: { limit: 1000, name: "[name].[hash:7].[ext]" }, 121 | }); 122 | 123 | 124 | // Config For Quasar 125 | const quasarTheme = "mat" || "ios"; 126 | const quasarFilepath = require("./build/quasar.js")(quasarTheme); 127 | 128 | cooking.add("resolve.alias[quasar-framework-custom]", quasarFilepath); 129 | cooking.add("resolve.extensions", [".js", ".vue", `.${quasarTheme}.js`, `.${quasarTheme}.vue`]); 130 | cooking.add("plugin.DefineQuasar", new webpack.DefinePlugin({ "__THEME__": JSON.stringify(quasarTheme) })); 131 | 132 | // Babel for Quasar 133 | !isDev && cooking.add("loader.js", { 134 | test: /\.(jsx?|babel|es6)$/, 135 | include: [ 136 | path.resolve(__dirname, "src"), 137 | path.resolve(__dirname, "mock"), 138 | // path.resolve(__dirname, "node_modules/quasar-framework"), // Problem with "npm link" 139 | fs.realpathSync("node_modules/quasar-framework"), 140 | ], 141 | use: { 142 | loader: "babel-loader", 143 | /** 144 | * If not set this, ".babelrc" will be searched on resovle path, 145 | * and faied in "node_modules/quasar-framework". 146 | * @see http://babeljs.io/docs/usage/babelrc/#lookup-behavior 147 | */ 148 | options: { 149 | babelrc: false, 150 | extends: path.resolve(__dirname, ".babelrc"), 151 | }, 152 | }, 153 | }); 154 | 155 | 156 | 157 | let webpackConfig = cooking.resolve(); 158 | 159 | module.exports = webpackConfig; 160 | -------------------------------------------------------------------------------- /dist-0.3.0/0.1c4d4bb.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([0],{102:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=a(121),s=a.n(r),i=a(110),n=a(28),o=n(s.a,i.a,!1,null,null,null);e.default=o.exports},104:function(t,e,a){function r(t){for(var e=0;ea.parts.length&&(r.parts.length=a.parts.length)}else{for(var n=[],s=0;s"+t[0].axisValueLabel+"
"+t[0].value[1]+"%"},trigger:"axis",padding:[5,12],axisPointer:{lineStyle:{color:"rgba(255,255,255,0.3)"}}},grid:{left:0,top:0,right:0,bottom:0},xAxis:{type:"time",show:!1},yAxis:{type:"value",show:!1,max:100},series:{type:"line",showSymbol:!1,itemStyle:{color:"rgba(255,255,255,0.5)"},areaStyle:{}}};return{state:{},pieces:[{min:0,max:50,color:"green-5"},{min:50,max:80,color:"orange-5"},{min:80,max:100,color:"red-5"}],cpuData:r(),ramData:r(),vRamData:r(),diskData:r(),cpuOption:(0,i.default)({},t),ramOption:(0,i.default)({},t),vRamOption:(0,i.default)({},t),diskOption:(0,i.default)({},t)}},computed:{checkTime:function(){return new Date(this.state.checkTime||0).format("YYYY-MM-DD hh:mm:ss")},cpuRatio:function(){return~~this.state.cpuRatio},ramRatio:function(){return~~(this.state.usedPhysicalMemorySize/this.state.totalPhysicalMemorySize*100)},vRamRatio:function(){return~~(this.state.jvmUseingMemory/this.state.jvmMaxMemory*100)},diskRatio:function(){return~~(this.state.usedDiskSize/this.state.totalDiskSize*100)},cpuColor:function(){return this.getPieceColor(this.cpuRatio)},ramColor:function(){return this.getPieceColor(this.ramRatio)},vRamColor:function(){return this.getPieceColor(this.vRamRatio)},diskColor:function(){return this.getPieceColor(this.diskRatio)}},mounted:function(){this.socket=this.refreshData()},destroyed:function(){this.socket.close()},methods:{getPieceColor:function(t){var e=this.pieces,a=!0,r=!1,s=void 0;try{for(var i,n=e[Symbol.iterator]();!(a=(i=n.next()).done);a=!0){var o=i.value;if(t>o.min&&t<=o.max)return o.color}}catch(t){r=!0,s=t}finally{try{!a&&n.return&&n.return()}finally{if(r)throw s}}return"blue-3"},getStorageSize:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;return 1073741824<=t?(t/1073741824).toFixed(1)+" TB":1048576<=t?(t/1048576).toFixed(1)+" GB":1024<=t?(t/1024).toFixed(1)+" MB":t+" KB"},refreshData:function(){var t=this;return(0,n.getResourceState)(null,function(e){t.state=e.data,t.cpuData.shift(),t.cpuData.push({name:t.checkTime,value:[t.checkTime,t.cpuRatio]}),t.$refs.cpu.mergeOptions({series:[{data:t.cpuData}]}),t.ramData.shift(),t.ramData.push({name:t.checkTime,value:[t.checkTime,t.ramRatio]}),t.$refs.ram.mergeOptions({series:[{data:t.ramData}]}),t.vRamData.shift(),t.vRamData.push({name:t.checkTime,value:[t.checkTime,t.vRamRatio]}),t.$refs.vRam.mergeOptions({series:[{data:t.vRamData}]}),t.diskData.shift(),t.diskData.push({name:t.checkTime,value:[t.checkTime,t.diskRatio]}),t.$refs.disk.mergeOptions({series:[{data:t.diskData}]})})}}}},123:function(t,e,a){e=t.exports=a(9)(),e.push([t.i,".echarts[data-v-08a16120]{width:auto;height:100px}.q-card-separator+.q-card-main[data-v-08a16120]{background-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}",""])},124:function(t,e,a){e=t.exports=a(9)(),e.push([t.i,".q-card[data-v-176642f9]{text-align:center}.q-card-main[data-v-176642f9]{font-size:16px;text-indent:-5px}",""])},125:function(t,e,a){e=t.exports=a(9)(),e.push([t.i,"dd[data-v-402baba6],dt[data-v-402baba6]{padding:5px 10px}pre[data-v-402baba6]{font-family:inherit;white-space:pre-wrap;word-wrap:break-word}",""])},127:function(t,e,a){t.exports=a.p+"alert.531144d.mp3"}}); -------------------------------------------------------------------------------- /dist-0.3.0/1.19a6aa8.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],{103:function(e,t,r){"use strict";function n(e){r(118)}Object.defineProperty(t,"__esModule",{value:!0});var a=r(114),o=r(28),s=n,i=o(null,a.a,!1,s,null,null);t.default=i.exports},104:function(e,t,r){function n(e){for(var t=0;tr.parts.length&&(n.parts.length=r.parts.length)}else{for(var s=[],a=0;a 2 | 3 | 4 | 5 | 6 | 7 | Server Monitor 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /dist-0.3.0/manifest.7ce5866.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var a,i,f,l=0,s=[];l 2 | 3 | 4 | 5 | 6 | 7 | Server Monitor 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /dist-0.5.0/manifest.0f3c3b5.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];l 2 | 3 | 4 | 5 | 6 | 7 | Server Monitor 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /dist-0.6.0/manifest.ed4e4aa.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];l1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1024;if(!+e)return e;var r=["KB","MB","GB","TB","PB","EB","ZB","YB"],o=Math.floor(Math.log(e)/Math.log(n));return(e/Math.pow(n,o)).toFixed(t)+" "+r[o]}Object.defineProperty(t,"__esModule",{value:!0}),t.default=r},245:function(e,t,n){"use strict";function r(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"YYYY-MM-DD hh:mm:ss",n=new Date(e),r={"(Y+)":n.getFullYear(),"(M+)":n.getMonth()+1,"(D+)":n.getDate(),"(h+)":n.getHours(),"(m+)":n.getMinutes(),"(s+)":n.getSeconds(),"(q+)":Math.floor((n.getMonth()+3)/3),"(ms)":n.getMilliseconds()};return Object.keys(r).reduce(function(e,n){if(!new RegExp(n).test(t))return e;var o=RegExp.$1,i=r[n].toString(),a=i.length;1===a&&(i="0"+i,a=o.length);var u=i.substr(-a,a);return e.replace(o,u)},t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=r},246:function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.QuasarDirectives=t.QuasarComponents=t.Quasar=void 0,n(379),n(278);var o=n(229),i=r(o),a=n(65),u=r(a),s=n(197),c=r(s),l=n(199),f=r(l),d=n(200),p=r(d),h=n(201),m=r(h),v=n(202),g=r(v),y=n(203),b=r(y),T=n(63),w=r(T),M=n(208),_=r(M),Q=n(209),O=r(Q),C=n(210),L=r(C),j=n(211),I=r(j),x=n(212),E=r(x),B=n(204),R=r(B),S=n(205),k=r(S),U=n(213),P=r(U),D=n(214),A=r(D),F=n(215),Y=r(F),$=n(216),N=r($),z=n(206),G=r(z),H=n(207),J=r(H),q=n(220),K=r(q),Z=n(221),V=r(Z),W=n(225),X=r(W),ee=n(223),te=r(ee),ne=n(224),re=r(ne),oe=n(226),ie=r(oe);t.Quasar={install:i.default,icons:u.default},t.QuasarComponents={QBtn:c.default,QCard:f.default,QCardMain:p.default,QCardSeparator:m.default,QCardTitle:g.default,QChip:b.default,QIcon:w.default,QItem:_.default,QItemMain:O.default,QItemSeparator:L.default,QItemSide:I.default,QItemTile:E.default,QLayout:R.default,QLayoutHeader:k.default,QList:P.default,QListHeader:A.default,QModal:Y.default,QModalLayout:N.default,QPage:G.default,QPageContainer:J.default,QPopover:K.default,QProgress:V.default,QTooltip:X.default,QToolbar:te.default,QToolbarTitle:re.default},t.QuasarDirectives={BackToTop:ie.default}},247:function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(122),i=r(o),a=n(380),u=r(a);i.default.use(u.default);var s=function(){return n.e(1).then(n.bind(null,385))},c=function(){return n.e(0).then(n.bind(null,386))},l=[{path:"/",component:s,meta:{title:"Server Monitor"},children:[{path:"/",component:c,meta:{title:"Dashboard"}}]}],f=new u.default({routes:l});t.default=f},278:function(e,t){},279:function(e,t){},280:function(e,t){},282:function(e,t){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(e){if(l===setTimeout)return setTimeout(e,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(e,0);try{return l(e,0)}catch(t){try{return l.call(null,e,0)}catch(t){return l.call(this,e,0)}}}function i(e){if(f===clearTimeout)return clearTimeout(e);if((f===r||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function a(){m&&p&&(m=!1,p.length?h=p.concat(h):v=-1,h.length&&u())}function u(){if(!m){var e=o(a);m=!0;for(var t=h.length;t;){for(p=h,h=[];++v1)for(var n=1;n=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(283),t.setImmediate=setImmediate,t.clearImmediate=clearImmediate},34:function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},382:function(e,t,n){e.exports=n(124)},384:function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t=0&&y.splice(t,1)}function a(e){var t=document.createElement("style");return t.type="text/css",o(e,t),t}function u(e){var t=document.createElement("link");return t.rel="stylesheet",o(e,t),t}function s(e,t){var n,r,o;if(t.singleton){var s=g++;n=v||(v=a(t)),r=c.bind(null,n,s,!1),o=c.bind(null,n,s,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=u(t),r=f.bind(null,n),o=function(){i(n),n.href&&URL.revokeObjectURL(n.href)}):(n=a(t),r=l.bind(null,n),o=function(){i(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}function c(e,t,n,r){var o=n?"":r.css;if(e.styleSheet)e.styleSheet.cssText=b(t,o);else{var i=document.createTextNode(o),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(i,a[t]):e.appendChild(i)}}function l(e,t){var n=t.css,r=t.media;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function f(e,t){var n=t.css,r=t.sourceMap;r&&(n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var o=new Blob([n],{type:"text/css"}),i=e.href;e.href=URL.createObjectURL(o),i&&URL.revokeObjectURL(i)}var d={},p=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}},h=p(function(){return/msie [6-9]\b/.test(self.navigator.userAgent.toLowerCase())}),m=p(function(){return document.head||document.getElementsByTagName("head")[0]}),v=null,g=0,y=[];e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");t=t||{},void 0===t.singleton&&(t.singleton=h()),void 0===t.insertAt&&(t.insertAt="bottom");var o=r(e);return n(o,t),function(e){for(var i=[],a=0;a Server Monitor
-------------------------------------------------------------------------------- /dist-0.7.0/manifest.1ef3136.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];ln.min&&e<=n.max)return n.color}}catch(e){a=!0,o=e}finally{try{!r&&s.return&&s.return()}finally{if(a)throw o}}},onPopoverShow:function(){this.$refs.chart.startAnimation(),this.needRenderChart&&(this.resizeChart(),this.renderChart())},onPopoverHide:function(){this.$refs.chart.stopAnimation()},renderChart:function(){this.$refs.chart.setOption({dataset:{source:this.records}})},resizeChart:function(){var e=this.$el.offsetWidth;this.$refs.chart.resize({width:e,slinet:!0})}}}},415:function(e,t,r){t=e.exports=r(407)(),t.push([e.i,".echarts[data-v-0a4faac4]{height:100px}.q-item-side[data-v-0a4faac4]{min-width:0}.q-card-separator+.q-card-main[data-v-0a4faac4]{background-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.q-popover[data-v-0a4faac4]{background:none;-webkit-animation:none;animation:none}.q-popover .q-card[data-v-0a4faac4]{margin:0}",""])},416:function(e,t,r){var a=r(415);"string"==typeof a&&(a=[[e.i,a,""]]),a.locals&&(e.exports=a.locals);r(406)("10a29d03",a,!0)},418:function(e,t,r){"use strict";var a=r(427),o=r(419),i=r(1),s=i(a.a,o.a,!1,null,null,null);t.a=s.exports},419:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return e.current?r("q-list",{staticClass:"bg-dark",attrs:{"no-border":"",dark:""}},[r("q-list-header",[e._v(" "+e._s(e.current.sourceName)+"\n "),r("span",{staticClass:"float-right on-right"},[e._v("\n "+e._s(e._f("formatDate")(e.current.status.checkTime))+"\n ")])]),e._v(" "),r("q-item-ratio",{attrs:{label:"CPU",icon:"select_all",encode:{x:"checkTime",y:"cpuRatio"},records:e.current.records,ratio:e.current.status.cpuRatio}}),e._v(" "),r("q-item-ratio",{attrs:{label:"物理内存",icon:"memory",encode:{x:"checkTime",y:"memRatio"},records:e.current.records,ratio:e.current.status.memRatio,total:e.current.status.totalPhysicalMemorySize,used:e.current.status.usedPhysicalMemorySize,free:e.current.status.freePhysicalMemorySize}}),e._v(" "),r("q-item-ratio",{attrs:{label:"物理磁盘",icon:"hd",encode:{x:"checkTime",y:"diskRatio"},records:e.current.records,ratio:e.current.status.diskRatio,total:e.current.status.totalDiskSize,used:e.current.status.usedDiskSize,free:e.current.status.freeDiskSize}}),e._v(" "),r("q-item-ratio",{attrs:{label:"JVM 内存",icon:"developer_board",encode:{x:"checkTime",y:"jvmMemRatio"},records:e.current.records,ratio:e.current.status.jvmMemRatio,total:e.current.status.jvmMaxMemory,used:e.current.status.jvmUsingMemory,free:e.current.status.jvmFreeMemory}}),e._v(" "),r("q-item-separator"),e._v(" "),r("q-item-group",{attrs:{label:"线程数",icon:"subject",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"线程数",name:"totalThread"}]}}),e._v(" "),r("q-item-group",{attrs:{label:"Ping 值",icon:"slow_motion_video",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"内部服务",name:"innerServerPing",unit:"ms"},{label:"远程服务",name:"remoteServerPing",unit:"ms"}]}}),e._v(" "),r("q-item-group",{attrs:{label:"网络连接",icon:"language",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"连接数",name:"netEstablished"},{label:"关闭数",name:"netCloseWait"},{label:"等待数",name:"netTimeWait"}]}})],1):e._e()},o=[],i={render:a,staticRenderFns:o};t.a=i},421:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("section",[r("q-list",{staticClass:"bg-dark q-mb-md",attrs:{"no-border":"",dark:"",link:""}},[r("q-list-header",[e._v(" 服务器 ")]),e._v(" "),e._l(e.servers,function(t){return r("q-item",{key:t.sourceName,nativeOn:{click:function(r){e.switchDatabase(r,t)}}},[r("q-tooltip",[e._v(e._s(t.sourceIP))]),e._v(" "),r("q-item-side",{attrs:{icon:"lens",color:t.color}}),e._v(" "),r("q-item-main",[r("q-item-tile",{attrs:{label:""}},[e._v(" "+e._s(t.sourceName)+" ")])],1)],1)})],2),e._v(" "),r("q-popover",{ref:"popover",attrs:{"anchor-click":!1,anchor:"bottom right",self:"bottom left","max-height":"90vh",fit:""}},[r("com-server-detail",{attrs:{current:e.current}})],1)],1)},o=[],i={render:a,staticRenderFns:o};t.a=i},427:function(e,t,r){"use strict";var a=r(412),o=r(133);t.a={components:{QItemRatio:a.a,QItemGroup:o.a},props:{current:Object}}},428:function(e,t,r){"use strict";function a(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:60,a=e.length;e[a]=t,a>r?e.shift():e.__ob__.dep.notify()}var o=r(132),i=r(418);t.a={components:{comServerDetail:i.a},data:function(){return{current:null,servers:{},pieces:[{min:-1/0,max:0,color:"blue-3"},{min:0,max:70,color:"green-5"},{min:70,max:90,color:"orange-5"},{min:90,max:100,color:"red-5"}]}},mounted:function(){this.socket=this.refreshData()},destroyed:function(){this.socket.close()},methods:{getPieceColor:function(e){var t=this.pieces,r=!0,a=!1,o=void 0;try{for(var i,s=t[Symbol.iterator]();!(r=(i=s.next()).done);r=!0){var n=i.value;if(e===n.value||e>n.min&&e<=n.max)return n.color}}catch(e){a=!0,o=e}finally{try{!r&&s.return&&s.return()}finally{if(a)throw o}}},refreshData:function(){var e=this;return o.a.socket.getSystemInfo(null,function(t){var r=t.sourceID,o=t.sourceName,i=t.sourceIP,s=e.servers[r];s||(s={status:{},records:[]},e.$set(e.servers,r,s),Object.assign(s,{sourceID:r,sourceName:o,sourceIP:i}));var n=t.usedPhysicalMemorySize,c=t.totalPhysicalMemorySize,l=t.usedDiskSize,u=t.totalDiskSize,m=t.jvmUsingMemory,d=t.jvmMaxMemory;t.memRatio=~~(n/c*100),t.diskRatio=~~(l/u*100),t.jvmMemRatio=~~(m/d*100),s.status=Object.assign({},t);var h=t.cpuRatio,v=t.memRatio,f=t.diskRatio,p=t.jvmMemRatio,_=Math.max(h,v,f,p);s.color=e.getPieceColor(_),a(s.records,t,60)})},switchDatabase:function(e,t){this.current=t,this.$refs.popover.anchorEl=e.currentTarget||e.srcElement,this.$refs.popover.toggle()}}}},430:function(e,t,r){t=e.exports=r(407)(),t.push([e.i,".q-popover[data-v-63057a10]{background:none}",""])},433:function(e,t,r){var a=r(430);"string"==typeof a&&(a=[[e.i,a,""]]),a.locals&&(e.exports=a.locals);r(406)("a1ded0ca",a,!0)}}); -------------------------------------------------------------------------------- /dist/1.99eb6e9.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],{408:function(e,t,a){"use strict";function r(e){a(432)}Object.defineProperty(t,"__esModule",{value:!0});var n=a(425),s=a(420),o=a(1),i=r,l=o(n.a,s.a,!1,i,"data-v-577a0a14",null);t.default=l.exports},412:function(e,t,a){"use strict";function r(e){a(416)}var n=a(414),s=a(413),o=a(1),i=r,l=o(n.a,s.a,!1,i,"data-v-0a4faac4",null);t.a=l.exports},413:function(e,t,a){"use strict";var r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("q-item",{staticClass:"cursor-pointer",class:{"q-pl-none q-pr-none":e.isTile},attrs:{highlight:""}},[e.icon&&!e.isTile?a("q-item-side",{attrs:{icon:e.icon}}):e._e(),e._v(" "),a("q-item-main",[a("q-item-tile",{attrs:{label:!e.isTile,sublabel:e.isTile}},[e._v(" "+e._s(e.label)+"\n "),a("span",{staticClass:"float-right"},[e._v(e._s(e.ratio)+" %")])]),e._v(" "),a("q-item-tile",{attrs:{sublabel:""}},[a("q-progress",{staticClass:"round-borders inset-shadow",staticStyle:{height:"10px"},attrs:{percentage:+e.ratio,color:e.color}})],1)],1),e._v(" "),e._t("default"),e._v(" "),a("q-popover",{ref:"popover",attrs:{anchor:"bottom right",self:"bottom left",fit:""},on:{"~show":function(t){e.resizeChart(t)},show:e.onPopoverShow,hide:e.onPopoverHide}},[a("q-card",{attrs:{color:e.color}},[a("q-card-title",[e._v(" "+e._s(e.label)+"\n "),a("big",{attrs:{slot:"right"},slot:"right"},[e._v(e._s(e.ratio)+" %")])],1),e._v(" "),a("q-card-main",[a("chart",{ref:"chart",attrs:{option:e.option,theme:"light","auto-resize":""}})],1),e._v(" "),a("q-card-separator"),e._v(" "),e.total?a("q-card-main",{nativeOn:{click:function(t){e.$refs.popover.hide(t)}}},[e._v("\n 最大:"+e._s(e._f("formatByte")(e.total))+" "),a("br"),e._v("\n 已用:"+e._s(e._f("formatByte")(e.used))+" "),a("br"),e._v("\n 剩余:"+e._s(e._f("formatByte")(e.free))+" "),a("br")]):e._e()],1)],1)],2)},n=[],s={render:r,staticRenderFns:n};t.a=s},414:function(e,t,a){"use strict";var r=a(134);t.a={props:{"is-tile":Boolean,label:String,icon:String,encode:Object,ratio:[Number,String],total:[Number,String],used:[Number,String],free:[Number,String],records:Array},data:function(){return{pieces:[{min:-1/0,max:0,color:"blue-3"},{min:0,max:70,color:"green-5"},{min:70,max:90,color:"orange-5"},{min:90,max:100,color:"red-5"}],option:a.i(r.a)({yAxis:{max:100},series:{encode:this.encode}})}},computed:{color:function(){return this.getPieceColor(this.ratio)}},watch:{records:function(){this.$refs.popover.showing?(this.needRenderChart=!1,this.renderChart()):this.needRenderChart=!0}},mounted:function(){this.onPopoverHide()},methods:{getPieceColor:function(e){var t=this.pieces,a=!0,r=!1,n=void 0;try{for(var s,o=t[Symbol.iterator]();!(a=(s=o.next()).done);a=!0){var i=s.value;if(e===i.value||e>i.min&&e<=i.max)return i.color}}catch(e){r=!0,n=e}finally{try{!a&&o.return&&o.return()}finally{if(r)throw n}}},onPopoverShow:function(){this.$refs.chart.startAnimation(),this.needRenderChart&&(this.resizeChart(),this.renderChart())},onPopoverHide:function(){this.$refs.chart.stopAnimation()},renderChart:function(){this.$refs.chart.setOption({dataset:{source:this.records}})},resizeChart:function(){var e=this.$el.offsetWidth;this.$refs.chart.resize({width:e,slinet:!0})}}}},415:function(e,t,a){t=e.exports=a(407)(),t.push([e.i,".echarts[data-v-0a4faac4]{height:100px}.q-item-side[data-v-0a4faac4]{min-width:0}.q-card-separator+.q-card-main[data-v-0a4faac4]{background-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.q-popover[data-v-0a4faac4]{background:none;-webkit-animation:none;animation:none}.q-popover .q-card[data-v-0a4faac4]{margin:0}",""])},416:function(e,t,a){var r=a(415);"string"==typeof r&&(r=[[e.i,r,""]]),r.locals&&(e.exports=r.locals);a(406)("10a29d03",r,!0)},417:function(e,t,a){"use strict";var r=a(424),n=a(422),s=a(1),o=s(r.a,n.a,!1,null,null,null);t.a=o.exports},420:function(e,t,a){"use strict";var r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("section",[a("q-list",{staticClass:"bg-dark q-mb-md",attrs:{"no-border":"",dark:"",link:""}},[a("q-list-header",[e._v(" 数据库 ")]),e._v(" "),e._l(e.databases,function(t){return a("q-item",{key:t.dataBaseName,nativeOn:{click:function(a){e.switchDatabase(a,t)}}},[a("q-tooltip",[e._v(e._s(t.dataBaseIP))]),e._v(" "),a("q-item-side",{attrs:{icon:"storage",color:t.color}}),e._v(" "),a("q-item-main",[a("q-item-tile",{attrs:{label:""}},[e._v(" "+e._s(t.dataBaseName)+" ")])],1)],1)})],2),e._v(" "),a("q-popover",{ref:"popover",attrs:{"anchor-click":!1,anchor:"bottom right",self:"bottom left","max-height":"90vh",fit:""}},[a("com-database-detail",{attrs:{current:e.current}})],1)],1)},n=[],s={render:r,staticRenderFns:n};t.a=s},422:function(e,t,a){"use strict";var r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return e.current?a("q-list",{staticClass:"bg-dark",attrs:{"no-border":"",dark:""}},[a("q-list-header",[e._v(" "+e._s(e.current.dataBaseName)+"\n "),a("span",{staticClass:"float-right on-left"},[e._v("\n "+e._s(e._f("formatDate")(e.current.status.checkTime))+"\n ")])]),e._v(" "),a("q-item-group",{attrs:{label:"连接数",icon:"language",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"最大",name:"max_connections"},{label:"可用",name:"max_used_connections"}]}}),e._v(" "),a("q-item-group",{attrs:{label:"总流量",icon:"opacity",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"总流量",name:"traffic_all",type:"byte"},{label:"接收",name:"bytes_received",type:"byte"},{label:"发送",name:"bytes_sent",type:"byte"},{label:"每秒",name:"traffic_perSecond",type:"byte",unit:"/s"}]}}),e._v(" "),a("q-item-separator"),e._v(" "),a("q-item-group",{attrs:{label:"键缓冲",icon:"timelapse",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"使用率",name:"key_used_ratio",unit:"%",ratio:{used:"key_used",free:"key_free",total:"key_total"}},{label:"平均命中率",name:"key_avg_hit_ratio",unit:"%"},{label:"写命中率",name:"key_write_hit_ratio",unit:"%"},{label:"读命中率",name:"key_read_hit_ratio",unit:"%"},{label:"效率",name:"key_efficiency",unit:"%"}]}}),e._v(" "),a("q-item-separator"),e._v(" "),a("q-item-group",{attrs:{label:"查询缓存",icon:"filter_tilt_shift",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"使用率",name:"qcache_used_ratio",unit:"%"},{label:"命中率(查询比)",name:"qcache_hit_select_ratio",unit:"%"},{label:"命中率(插入比)",name:"qcache_hits_inserts_ratio",unit:"%"},{label:"碎片率",name:"qcache_frag_ratio",unit:"%"}]}}),e._v(" "),a("q-item-group",{attrs:{label:"线程缓存",icon:"line_style",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"使用率",name:"thread_cache_used_ratio",unit:"%"},{label:"命中率",name:"thread_cache_hit_ratio",unit:"%"},{label:"连接数",name:"thread_connections"}]}}),e._v(" "),a("q-item-group",{attrs:{label:"表缓存",icon:"rounded_corner",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"使用率",name:"table_cache_used_ratio",unit:"%"},{label:"命中率",name:"table_cache_hit_ratio",unit:"%"},{label:"表创建速度",name:"opened_tables"}]}}),e._v(" "),a("q-item-separator"),e._v(" "),a("q-item-group",{attrs:{label:"临时表创建",icon:"flip_to_front",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"内存临时表数量",name:"created_tmp_tables"},{label:"磁盘临时表数量",name:"created_tmp_disk_tables"},{label:"磁盘临时表占比",name:"created_tmp_tables_on_disk_ratio",unit:"%"},{label:"磁盘临时文件数量",name:"created_tmp_files"}]}}),e._v(" "),a("q-item-group",{attrs:{label:"MySQL 查询",icon:"search",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"Insert 语句",name:"inserted"},{label:"Update 语句",name:"updated"},{label:"Delete 语句",name:"deleted"},{label:"Select 语句",name:"selected"},{label:"Select 查询状态",name:"selects_perSecond",unit:"kb/s"}]}}),e._v(" "),a("q-item-group",{attrs:{label:"排序操作",icon:"sort",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"总次数",name:"sort_times"}]}}),e._v(" "),a("q-item-separator"),e._v(" "),a("q-item-group",{attrs:{label:"InnoDB 缓冲池",icon:"pool",status:e.current.status,records:e.current.records,"x-field":{name:"checkTime"},"y-field":[{label:"使用率",name:"innodb_buffer_pool_pages_usage",unit:"%"},{label:"读命中率",name:"innodb_buffer_pool_pages_read_hit_ratio",unit:"%"},{label:"读次数(磁盘)",name:"innodb_buffer_pool_reads"},{label:"读次数(内存-随机)",name:"innodb_buffer_pool_read_ahead_rnd"},{label:"读次数(内存-顺序)",name:"innodb_buffer_pool_read_ahead_seq"},{label:"刷新次数",name:"innodb_buffer_pool_pages_flushed"},{label:"读请求次数",name:"innodb_buffer_pool_read_requests"},{label:"写请求次数",name:"innodb_buffer_pool_write_requests"},{label:"数据读操作耗时",name:"innodb_pool_reads_perSecond",unit:"KB/s"},{label:"数据写操作耗时",name:"innodb_pool_reads_perSecond",unit:"KB/s"},{label:"已完成的 Insert 语句",name:"innodb_rows_inserted"},{label:"已完成的 Update 语句",name:"innodb_rows_updated"},{label:"已完成的 Delete 语句",name:"innodb_rows_deleted"}]}})],1):e._e()},n=[],s={render:r,staticRenderFns:n};t.a=s},424:function(e,t,a){"use strict";var r=a(412),n=a(133);t.a={components:{QItemRatio:r.a,QItemGroup:n.a},props:{current:Object}}},425:function(e,t,a){"use strict";function r(e,t){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:60,r=e.length;e[r]=t,r>a?e.shift():e.__ob__.dep.notify()}var n=a(132),s=a(417);t.a={components:{comDatabaseDetail:s.a},data:function(){return{current:null,databases:{}}},mounted:function(){this.socket=this.refreshData()},destroyed:function(){this.socket.close()},methods:{refreshData:function(){var e=this;return n.a.socket.getDatabaseInfo(null,function(t){var a=t.sourceID,n=t.dataBaseName,s=t.dataBaseIP,o=e.databases[a];o||(o={status:{},records:[]},e.$set(e.databases,a,o),Object.assign(o,{sourceID:a,dataBaseName:n,dataBaseIP:s}));var i=t.key_used,l=t.key_free;t.key_total=i+l,o.status=Object.assign({},t),r(o.records,t,60)})},switchDatabase:function(e,t){this.current=t,this.$refs.popover.anchorEl=e.currentTarget||e.srcElement,this.$refs.popover.toggle()}}}},429:function(e,t,a){t=e.exports=a(407)(),t.push([e.i,".q-popover[data-v-577a0a14]{background:none}",""])},432:function(e,t,a){var r=a(429);"string"==typeof r&&(r=[[e.i,r,""]]),r.locals&&(e.exports=r.locals);a(406)("47001534",r,!0)}}); -------------------------------------------------------------------------------- /dist/2.dffdcc4.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([2],{409:function(t,e,i){"use strict";function a(t){i(434)}Object.defineProperty(e,"__esModule",{value:!0});var o=i(426),n=i(423),l=i(1),s=a,r=l(o.a,n.a,!1,s,"data-v-f4534d5c",null);e.default=r.exports},423:function(t,e,i){"use strict";var a=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("q-list",{staticClass:"bg-dark",attrs:{dark:"","no-border":""}},[i("q-list-header",[t._v(" 异常信息\n "),t.exceptions.length?i("q-chip",{attrs:{color:"red",pointing:"left"}},[t._v("\n "+t._s(t.exceptions.length)+"\n ")]):t._e(),t._v(" "),i("q-btn",{staticClass:"float-right on-left",attrs:{round:""},nativeOn:{click:function(e){t.toggleAudio(e)}}},[i("q-icon",{attrs:{name:t.audio.muted?"volume_off":"volume_up"}})],1)],1),t._v(" "),i("q-item",[i("q-item-main",[i("chart",{ref:"chart",attrs:{option:t.option,theme:"light","auto-resize":""}})],1)],1),t._v(" "),i("q-item-separator"),t._v(" "),t._l(t.exceptions,function(e,a){return i("q-item",{key:a,attrs:{link:""},nativeOn:{click:function(i){t.openModal(e)}}},[i("q-item-side",{attrs:{icon:t.getIcon(e.level),color:t.getColor(e.level)}}),t._v(" "),i("q-item-main",[i("q-item-tile",{staticClass:"ellipsis",attrs:{label:"",color:["negative"][e.level]}},[t._v("\n "+t._s(e.sourceName)+"\n "),i("time",{staticClass:"float-right"},[t._v(t._s(t._f("formatDate")(e.checkTime)))])]),t._v(" "),i("q-item-tile",{staticClass:"ellipsis",attrs:{sublabel:"",color:["negative"][e.level]}},[t._v("\n "+t._s(e.message)+"\n ")])],1)],1)}),t._v(" "),i("q-modal",{ref:"modal-detail",attrs:{"content-css":{minWidth:"80vw",minHeight:"80vh"}}},[t.exception?i("q-modal-layout",[i("q-toolbar",{class:"bg-"+t.getColor(t.exception.level),attrs:{slot:"header"},slot:"header"},[i("q-btn",{attrs:{flat:""},nativeOn:{click:function(e){t.closeModal(e)}}},[i("q-icon",{attrs:{name:"keyboard_arrow_left"}})],1),t._v(" "),i("q-toolbar-title",[t._v("\n 【"+t._s(t.getLabel(t.exception.level))+"】\n "+t._s(t.exception.sourceName)+" "+t._s(t.exception.sourceIP)+"\n "),i("span",{staticClass:"float-right"},[t._v(t._s(t._f("formatDate")(t.exception.checkTime)))])])],1),t._v(" "),i("dl",{staticClass:"layout-padding"},[i("dt",{staticClass:"bg-light"},[t._v("异常信息")]),t._v(" "),i("dd",[i("pre",[t._v(t._s(t.exception.message))])]),t._v(" "),i("dt",{staticClass:"bg-light"},[t._v("用户信息")]),t._v(" "),i("br"),t._v(" "),i("dd",[i("label",[t._v("用户ID:")]),t._v(t._s(t.exception.userId))]),t._v(" "),i("dd",[i("label",[t._v("设备UUID:")]),t._v(t._s(t.exception.uuid))]),t._v(" "),i("dd",[i("label",[t._v("设备型号:")]),t._v(t._s(t.exception.device))]),t._v(" "),i("dd",[i("label",[t._v("客户端IP:")]),t._v(t._s(t.exception.clientIP))]),t._v(" "),i("dd",[i("label",[t._v("客户端版本号:")]),t._v(t._s(t.exception.clientVersion))]),t._v(" "),i("br"),t._v(" "),t.exception.stackTrace?[i("dt",{staticClass:"bg-light"},[t._v("异常堆栈")]),t._v(" "),i("dd",[i("pre",[t._v(t._s(t.exception.stackTrace))])])]:t._e()],2)],1):t._e()],1)],2)},o=[],n={render:a,staticRenderFns:o};e.a=n},426:function(t,e,i){"use strict";var a=i(132);e.a={data:function(){return{audio:{muted:!1,list:{0:{src:i(437),dom:null},1:{src:i(436),dom:null},2:{src:i(438),dom:null},3:{src:i(435),dom:null}}},option:{tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},grid:{top:5,right:0,bottom:0,left:0,containLabel:!0},xAxis:{type:"category",data:["FATAL","ERROR","WARN","INFO"],axisTick:{alignWithLabel:!0},nameTextStyle:{color:"rgba(255,255,255,0.4)"},axisLine:{lineStyle:{color:"rgba(255,255,255,0.4)"}}},yAxis:{type:"value",splitLine:{show:!1},nameTextStyle:{color:"rgba(255,255,255,0.4)"},axisLine:{lineStyle:{color:"rgba(255,255,255,0.4)"}}},series:{type:"bar",data:[{value:0,itemStyle:{color:"rgba(219,40,40,0.7)"}},{value:0,itemStyle:{color:"rgba(244,67,54,0.7)"}},{value:0,itemStyle:{color:"rgba(242,192,55,0.7)"}},{value:0,itemStyle:{color:"rgba(49,204,236,0.7)"}}]}},exception:null,exceptions:[]}},mounted:function(){this.socket=this.refreshData()},destroyed:function(){this.socket.close()},methods:{getLabel:function(t){return["FATAL","ERROR","WARN","INFO"][t]},getIcon:function(t){return["cancel","error","warning","info"][t]},getColor:function(t){return["negative","red","warning","info"][t]},toggleAudio:function(){var t=!this.audio.muted;this.audio.muted=t,Object.values(this.audio.list).forEach(function(e){e.dom&&!e.dom.paused&&(e.dom.muted=t)})},playSound:function(t){var e=this,i=this.audio.list[t];i.dom?(i.dom.muted=this.audio.muted,i.dom.play()):(i.dom=new Audio(i.src),i.dom.oncanplay=function(i){return e.playSound(t)})},openModal:function(t){this.exception=t,this.$refs["modal-detail"].show()},closeModal:function(){this.$refs["modal-detail"].hide()},refreshData:function(){var t=this;return a.a.socket.getException(null,function(e){var i=e.level;t.exceptions.unshift(e),t.playSound(i),t.option.series.data[i].value+=1,t.$refs.chart.setOption({series:{data:t.option.series.data}})})}}}},431:function(t,e,i){e=t.exports=i(407)(),e.push([t.i,"dd[data-v-f4534d5c],dt[data-v-f4534d5c]{padding:5px 10px}dd>label[data-v-f4534d5c]{display:inline-block;min-width:120px}pre[data-v-f4534d5c]{font-family:inherit;white-space:pre-wrap;word-wrap:break-word}.q-chip[data-v-f4534d5c]{z-index:1}",""])},434:function(t,e,i){var a=i(431);"string"==typeof a&&(a=[[t.i,a,""]]),a.locals&&(t.exports=a.locals);i(406)("4de1950b",a,!0)},435:function(t,e,i){t.exports=i.p+"alert.b8116c7.mp3"},436:function(t,e,i){t.exports=i.p+"error.29e5668.mp3"},437:function(t,e,i){t.exports=i.p+"fatal.8a322db.mp3"},438:function(t,e,i){t.exports=i.p+"warn.8de28bd.mp3"}}); -------------------------------------------------------------------------------- /dist/MaterialIcons-Regular.012cf6a.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/dist/MaterialIcons-Regular.012cf6a.woff -------------------------------------------------------------------------------- /dist/alert.b8116c7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/dist/alert.b8116c7.mp3 -------------------------------------------------------------------------------- /dist/error.29e5668.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/dist/error.29e5668.mp3 -------------------------------------------------------------------------------- /dist/fatal.8a322db.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/dist/fatal.8a322db.mp3 -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | Server Monitor
-------------------------------------------------------------------------------- /dist/manifest.359d8b1.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var a,i,f,l=0,s=[];l { 14 | object[method] = target[method].bind(target); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /mock/modules/random.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Genarate Random value series for chart 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-08 8 | * 9 | * @todo 2018-03-30 dondevi 10 | * 1.Fix: Memory leak 11 | * 12 | * @update 2018-03-14 dondevi 13 | * 1.Update: randomValue() - next() 14 | */ 15 | 16 | /** 17 | * Get random value from initial setting 18 | * @param {Number} value - Current value 19 | * @param {Number} minValue - Min limit 20 | * @param {Number} maxValue - Max limit 21 | * @param {Number} minOffset - Min limit of random offet from current value 22 | * @param {Number} maxOffset - Max limit of random offet from current value 23 | * @return {Object} - Random value & Next Function 24 | */ 25 | export function randomValue (value, minValue, maxValue, minOffset, maxOffset) { 26 | const now = () => value; 27 | const next = () => { 28 | value = value + randomInt(minOffset, maxOffset); 29 | value = Math.max(value, minValue); 30 | value = Math.min(value, maxValue); 31 | value = Math.round(value); 32 | return value; 33 | }; 34 | return { now, next }; 35 | } 36 | 37 | /** 38 | * Get random integer in range 39 | * @param {Number} min - Min limit 40 | * @param {Number} max - Max limit 41 | * @return {Number} int - Random integer 42 | */ 43 | export function randomInt (min, max) { 44 | return Math.floor(Math.random() * (max - min + 1) + min); 45 | } 46 | -------------------------------------------------------------------------------- /mock/modules/string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 反序列化 Search Params 3 | * @param {String} search - 序列化字符串 4 | * @return {Object} - 反序列化对象 5 | */ 6 | export function unserialize (search) { 7 | return search.split("&").reduce((acc, cur) => { 8 | const item = cur.split("="); 9 | acc[item[0]] = item[1]; 10 | return acc; 11 | }, {}); 12 | } 13 | -------------------------------------------------------------------------------- /mock/service/datas/business.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-02-06 4 | */ 5 | 6 | export const getStatistics = (param, socket) => { 7 | socket._delay = 60000; 8 | return { 9 | // 检查时间 10 | "checkTime": Date.now(), 11 | // 开始时间 12 | "startTime": Date.now() - 60000, 13 | // 结束时间 14 | "endTime": Date.now(), 15 | // 当前递交量 16 | "currentSubmit": 10, 17 | // 当前合格量 18 | "currentQualified": 5, 19 | // 当前不合格量 20 | "currentUnqualified": 2, 21 | // 总递交量 22 | "totalSubmit": 100, 23 | // 总合格量 24 | "totalQualified": 50, 25 | // 总不合格量 26 | "totalUnqualified": 20, 27 | // 机审平均操作耗时 28 | "machinePerSeconds": 100, 29 | // 机审操作最长耗时 30 | "machineMaxConsume": 300, 31 | // 机审操作最短耗时 32 | "machineMinConsume": 10, 33 | // 人审平均操作耗时 34 | "humenPerSeconds": 700, 35 | // 人审操作最长耗时 36 | "humenMaxConsume": 2000, 37 | // 人审操作最短耗时 38 | "humenMinConsume": 100, 39 | // 终审平均操作耗时 40 | "finalPerSeconds": 300, 41 | // 终审操作最长耗时 42 | "finalMaxConsume": 1000, 43 | // 终审操作最短耗时 44 | "finalMinConsume": 100, 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /mock/service/datas/database.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://github.com/dbsid/db2_slob/blob/master/misc/mystat.pl 3 | * 4 | * @author dondevi 5 | * @create 2018-03-07 6 | * 7 | * @update 2018-03-13 dondevi 8 | * @update 2018-03-16 dondevi 9 | */ 10 | 11 | import { randomValue, randomInt } from "mock/modules/random.js"; 12 | 13 | const databases = [ 14 | { name: "Database-1", ip: "192.168.111.102", id: "1" }, 15 | { name: "Database-2", ip: "192.168.111.103", id: "2" }, 16 | { name: "Database-3", ip: "192.168.111.104", id: "3" }, 17 | { name: "Database-4", ip: "192.168.111.105", id: "4" }, 18 | ]; 19 | 20 | 21 | const database = randomValue(0, 0, 3, -1, 1); 22 | const key_used_ratio = randomValue(0, 5, 100, -10, 10); 23 | const key_free_ratio = randomValue(100, 5, 100, -10, 10); 24 | const key_used = randomValue(0, 1048576, 8388608, -1024, 1024); 25 | const key_free = randomValue(8388608, 1048576, 8388608, -1024, 1024); 26 | const key_write_hit_ratio = randomValue(92, 5, 100, -10, 10); 27 | const key_read_hit_ratio = randomValue(99, 5, 100, -10, 10); 28 | const key_avg_hit_ratio = randomValue(95.5, 5, 100, -10, 10); 29 | const key_efficiency = randomValue(0.54, 0, 1, -0.1, 0.1); 30 | const qcache_frag_ratio = randomValue(100, 5, 100, -10, 10); 31 | const qcache_used_ratio = randomValue(1.6403198, 0, 100, -10, 10); 32 | const qcache_hit_select_ratio = randomValue(0, 5, 100, -10, 10); 33 | const qcache_hits_inserts_ratio = randomValue(0, 5, 100, -10, 10); 34 | const thread_connections = randomValue(82, 5, 100, -10, 10); 35 | const thread_cache_hit_ratio = randomValue(99, 5, 100, -10, 10); 36 | const thread_cache_used_ratio = randomValue(44, 5, 100, -10, 10); 37 | const table_cache_hit_ratio = randomValue(0, 5, 100, -10, 10); 38 | const table_cache_used_ratio = randomValue(0, 5, 100, -10, 10); 39 | const inserted = randomValue(49949, 1000, 99999, -500, 500); 40 | const updated = randomValue(0, 5, 100, -50, 50); 41 | const deleted = randomValue(3900, 100, 9999, -50, 50); 42 | const selected = randomValue(13636994, 100000, 99999999, -5000, 5000); 43 | const selects_perSecond = randomValue(13694, 1000, 999999, -500, 500); 44 | const sort_times = randomValue(25707, 500, 99999, -250, 250); 45 | const innodb_buffer_pool_pages_usage = randomValue(12.5, 5, 100, -10, 10); 46 | const innodb_buffer_pool_pages_read_hit_ratio = randomValue(0.0057600364, 0, 1, -0.01, 0.01); 47 | const max_connections = randomValue(1518769, 10000, 9999999, -1000, 1000); 48 | const max_used_connections = randomValue(1001, 1000, 99999, -100, 100); 49 | const traffic_all = randomValue(4652522, 1073741824, 1099511627776, -1048576, 1048576); 50 | const bytes_received = randomValue(15134017854, 1073741824, 1099511627776, -1048576, 1048576); 51 | const bytes_sent = randomValue(32528630802, 1073741824, 1099511627776, -1048576, 1048576); 52 | const traffic_perSecond = randomValue(100, 10, 1000, -10, 10); 53 | const opened_tables = randomValue(397013, 5000, 999999, -1000, 1000); 54 | const created_tmp_tables = randomValue(1772451, 100, 99999, -10, 10); 55 | const created_tmp_disk_tables = randomValue(46483, 100, 99999, -10, 10); 56 | const created_tmp_files = randomValue(242, 10, 1000, -10, 10); 57 | const created_tmp_tables_on_disk_ratio = randomValue(97, 5, 100, -10, 10); 58 | const innodb_buffer_pool_reads = randomValue(10105, 1000, 99999, -100, 100); 59 | const innodb_buffer_pool_read_ahead_rnd = randomValue(0, 5, 100, -10, 10); 60 | const innodb_buffer_pool_read_ahead_seq = randomValue(0, 5, 100, -10, 10); 61 | const innodb_buffer_pool_read_requests = randomValue(175432910, 100000, 999999999, -1000, 1000); 62 | const innodb_buffer_pool_pages_flushed = randomValue(149982, 1000, 999999, -100, 100); 63 | const innodb_buffer_pool_write_requests = randomValue(768770, 1000, 999999, -100, 100); 64 | const innodb_rows_inserted = randomValue(37351, 1000, 99999, -100, 100); 65 | const innodb_rows_updated = randomValue(29396, 1000, 99999, -100, 100); 66 | const innodb_rows_deleted = randomValue(14774, 1000, 99999, -100, 100); 67 | const innodb_pool_reads_perSecond = randomValue(100, 10, 1000, -10, 10); 68 | const innodb_pool_writes_perSecond = randomValue(100, 10, 1000, -10, 10); 69 | 70 | export const getDatabaseInfo = (param, socket) => { 71 | socket._delay = 5000; 72 | return { 73 | // 检查时间 74 | "checkTime": Date.now(), 75 | // 数据库名称 76 | "dataBaseName": databases[database.next()].name, 77 | // 数据库 IP 78 | "dataBaseIP": databases[database.now()].ip, 79 | // 数据库 ID 80 | "sourceID": databases[database.now()].id, 81 | // 效率 82 | "key_efficiency": key_efficiency.next(), 83 | // 键缓冲空间用过的最大使用率 (%) 84 | "key_used_ratio": key_used_ratio.next(), 85 | // 键缓冲空间空闲率 (%) 86 | "key_free_ratio": key_free_ratio.next(), 87 | // 键缓冲已用空间 88 | "key_used": key_used.next(), 89 | // 键缓冲空闲空间 90 | "key_free": key_free.next(), 91 | // 键缓冲写命中率 (%) 92 | "key_write_hit_ratio": key_write_hit_ratio.next(), 93 | // 键缓冲读命中率 (%) 94 | "key_read_hit_ratio": key_read_hit_ratio.next(), 95 | // 键缓冲读写平均命中率 (%) 96 | "key_avg_hit_ratio": key_avg_hit_ratio.next(), 97 | // 查询缓存空间碎片率 (%) 98 | "qcache_frag_ratio": qcache_frag_ratio.next(), 99 | // 查询缓存空间利用率 (%) 100 | "qcache_used_ratio": qcache_used_ratio.next(), 101 | // 查询缓存命中率 (%):查询比 102 | "qcache_hit_select_ratio": qcache_hit_select_ratio.next(), 103 | // 查询缓存命中率 (%):插入比 104 | "qcache_hits_inserts_ratio": qcache_hits_inserts_ratio.next(), 105 | // 线程缓存命中率 (%) 106 | "thread_cache_hit_ratio": thread_cache_hit_ratio.next(), 107 | // 线程缓存使用率 (%) 108 | "thread_cache_used_ratio": thread_cache_used_ratio.next(), 109 | // 当前线程连接数 110 | "thread_connections": thread_connections.next(), 111 | // 表缓存命中率 (%) 112 | "table_cache_hit_ratio": table_cache_hit_ratio.next(), 113 | // 表缓存使用率 (%) 114 | "table_cache_used_ratio": table_cache_used_ratio.next(), 115 | // 目前传入服务器并被执行的所有insert语句 116 | "inserted": inserted.next(), 117 | // 目前传入服务器并被执行的所有update语句 118 | "updated": updated.next(), 119 | // 目前传入服务器并被执行的所有delete语句 120 | "deleted": deleted.next(), 121 | // 目前传入服务器并被执行的所有select语句 122 | "selected": selected.next(), 123 | // selects 每秒的查询状态 (kb/s) 124 | "selects_perSecond": selects_perSecond.next(), 125 | // 所有排序操作总次数 126 | "sort_times": sort_times.next(), 127 | // 缓冲池利用率 128 | "innodb_buffer_pool_pages_usage": innodb_buffer_pool_pages_usage.next(), 129 | // 缓冲池命中率 (%) 130 | "innodb_buffer_pool_pages_read_hit_ratio": innodb_buffer_pool_pages_read_hit_ratio.next(), 131 | // 最大连接数 132 | "max_connections": max_connections.next(), 133 | // 可用连接数 134 | "max_used_connections": max_used_connections.next(), 135 | // 当前数据库总流速 (kb) 136 | "traffic_all": traffic_all.next(), 137 | // 每秒流量 (kb/s) 138 | "traffic_perSecond": traffic_perSecond.next(), 139 | // 当前数据库接收速率 (kb) 140 | "bytes_received": bytes_received.next(), 141 | // 当前数据库发送速率 (kb) 142 | "bytes_sent": bytes_sent.next(), 143 | // 表创建速度 144 | "opened_tables": opened_tables.next(), 145 | // 创建内存临时表的数量 146 | "created_tmp_tables": created_tmp_tables.next(), 147 | // 创建磁盘临时表的数量 148 | "created_tmp_disk_tables": created_tmp_disk_tables.next(), 149 | // 创建磁盘临时文件的数量 150 | "created_tmp_files": created_tmp_files.next(), 151 | // 创建磁盘临时表占临时表的比例 152 | "created_tmp_tables_on_disk_ratio": created_tmp_tables_on_disk_ratio.next(), 153 | // 从磁盘中读取次数 154 | "innodb_buffer_pool_reads": innodb_buffer_pool_reads.next(), 155 | // 从内存中随机读取次数 156 | "innodb_buffer_pool_read_ahead_rnd": innodb_buffer_pool_read_ahead_rnd.next(), 157 | // 从内存中顺序读取次数 158 | "innodb_buffer_pool_read_ahead_seq": innodb_buffer_pool_read_ahead_seq.next(), 159 | // 读取请求次数 160 | "innodb_buffer_pool_read_requests": innodb_buffer_pool_read_requests.next(), 161 | // 刷新次数 162 | "innodb_buffer_pool_pages_flushed": innodb_buffer_pool_pages_flushed.next(), 163 | // 写请求数量 164 | "innodb_buffer_pool_write_requests": innodb_buffer_pool_write_requests.next(), 165 | // 已经完成的insert语句数量 166 | "innodb_rows_inserted": innodb_rows_inserted.next(), 167 | // 已经完成的update语句数量 168 | "innodb_rows_updated": innodb_rows_updated.next(), 169 | // 已经完成的delete语句数量 170 | "innodb_rows_deleted": innodb_rows_deleted.next(), 171 | // 数据读操作耗时 (kb/s) 172 | "innodb_pool_reads_perSecond": innodb_pool_reads_perSecond.next(), 173 | // 数据写操作耗时 (kb/s) 174 | "innodb_pool_writes_perSecond": innodb_pool_writes_perSecond.next(), 175 | }; 176 | } 177 | -------------------------------------------------------------------------------- /mock/service/datas/exception.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-02-05 4 | * 5 | * @update 2018-03-12 dondevi 6 | */ 7 | 8 | import { randomValue, randomInt } from "mock/modules/random.js"; 9 | 10 | const servers = [ 11 | { name: "Server-1", ip: "192.168.112.101", id: "1" }, 12 | { name: "Server-2", ip: "192.168.112.102", id: "2" }, 13 | { name: "Server-3", ip: "192.168.112.103", id: "3" }, 14 | ]; 15 | 16 | const clients = [ 17 | { userId: "13123456789", uuid: "f64f2940-fae4-11e7", device: "Android 7", clientIP: "192.168.0.1", clientVersion: "1.0.0" }, 18 | { userId: "13223456789", uuid: "29e42f64-64e4-fae7", device: "iPhone 7", clientIP: "192.168.0.2", clientVersion: "1.0.1" }, 19 | { userId: "13323456789", uuid: "ff40faaf-f61f-4111", device: "Android 8", clientIP: "192.168.0.3", clientVersion: "1.0.2" }, 20 | { userId: "13423456789", uuid: "940f2940-11e4-e7e7", device: "Android 5", clientIP: "192.168.0.4", clientVersion: "1.0.3" }, 21 | ]; 22 | 23 | const server = randomValue(0, 0, 2, -1, 1); 24 | const client = randomValue(0, 0, 2, -1, 1); 25 | const level = randomValue(2, 0, 3, -1, 1); 26 | 27 | export const getException = (param, socket) => { 28 | socket._delay = 3600000; 29 | return { 30 | // 检查时间 31 | "checkTime": Date.now(), 32 | // 消息类型 33 | "type": "", 34 | // 异常等级 { 0: "FATAL", 1: "ERROR", 2: "WARN", 3: "INFO" } 35 | "level": level.next(), 36 | // 异常消息 37 | "message": "public abstract boolean com.manage.service.account.IAdminManageService.updateAdminPassword(long,java.lang.String,java.lang.String)", 38 | // 异常堆栈 39 | "stackTrace": "com.exception.XingfuException: Account_AdminAccountId_NotExist\n\tat com.manage.error.AccountServiceError.error(AccountServiceError.java:135)\n\tat com.manage.service.account.impl.AdminManageService.checkAdminAcount(AdminManageService.java:123)\n\tat com.manage.service.account.impl.AdminManageService.updateAdminPassword(AdminManageService.java:56)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.lang.reflect.Method.invoke(Method.java:606)\n\tat org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)\n\tat org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:59)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)\n\tat org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)\n\tat org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)\n\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)\n\tat org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)\n\tat org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n\tat com.sun.proxy.$Proxy42.updateAdminPassword(Unknown Source)\n\tat com.manage.rest.maintain.account.AdminManageController.updateAdminPassword(AdminManageController.java:208)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.lang.reflect.Method.invoke(Method.java:606)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:650)\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:731)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)\n\tat org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)\n\tat org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)\n\tat org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)\n\tat org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)\n\tat org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)\n\tat org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)\n\tat org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)\n\tat org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)\n\tat org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)\n\tat org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:745)\n", 40 | // 用户 ID 41 | "userId": clients[client.next()].userId, 42 | // 设备 UUID 43 | "uuid": clients[client.now()].uuid, 44 | // 设备型号 45 | "device": clients[client.now()].device, 46 | // 客户端 IP 47 | "clientIP": clients[client.now()].clientIP, 48 | // 客户端版本号 49 | "clientVersion": clients[client.now()].clientVersion, 50 | // 来源服务 ID 51 | "sourceID": servers[server.now()].id, 52 | // 来源服务名称 53 | "sourceName": servers[server.next()].name, 54 | // 来源服务 IP 55 | "sourceIP": servers[server.now()].ip, 56 | // 是否需要告警 57 | "isWarning": true, 58 | }; 59 | }; 60 | -------------------------------------------------------------------------------- /mock/service/datas/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock Datas 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-05 8 | */ 9 | 10 | import * as DATA_system from "mock/service/datas/system.js"; 11 | import * as DATA_business from "mock/service/datas/business.js"; 12 | import * as DATA_database from "mock/service/datas/database.js"; 13 | import * as DATA_exception from "mock/service/datas/exception.js"; 14 | 15 | export default { 16 | axios: {}, 17 | socket: { 18 | ...DATA_system, 19 | ...DATA_business, 20 | ...DATA_database, 21 | ...DATA_exception, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /mock/service/datas/system.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-02-05 4 | * 5 | * @update 2018-03-08 dondevi 6 | * 1.Update: data structure 7 | * 2.Update: randomValue() to curry function 8 | */ 9 | 10 | import { randomValue, randomInt } from "mock/modules/random.js"; 11 | 12 | const servers = [ 13 | { name: "Server-1", ip: "192.168.112.101", id: "1" }, 14 | { name: "Server-2", ip: "192.168.112.102", id: "2" }, 15 | { name: "Server-3", ip: "192.168.112.103", id: "3" }, 16 | ]; 17 | 18 | // Fixed value 19 | const jvmMaxMemory = 2739712; 20 | const totalPhysicalMemorySize = 12328484; 21 | const totalDiskSize = 41153856; 22 | 23 | // Computed value 24 | const server = randomValue(0, 0, 2, -1, 1); 25 | const cpuRatio = randomValue(randomInt(10, 80), 5, 90, -20, 20); 26 | const jvmUsingMemory = randomValue(548864, 102400, jvmMaxMemory - 512000, -51200, 51200); 27 | const usedPhysicalMemorySize = randomValue(12108668, 102400, totalPhysicalMemorySize - 512000, -102400, 102400); 28 | const usedDiskSize = randomValue(31323264, 102400, totalDiskSize - 512000, -256000, 256000); 29 | const totalThread = randomValue(118, 20, Infinity, -20, 20); 30 | const innerServerPing = randomValue(100, 20, Infinity, -20, 20); 31 | const remoteServerPing = randomValue(100, 20, Infinity, -20, 20); 32 | const netEstablished = randomValue(100, 20, Infinity, -20, 20); 33 | const netCloseWait = randomValue(100, 20, Infinity, -20, 20); 34 | const netTimeWait = randomValue(100, 20, Infinity, -20, 20); 35 | 36 | export const getSystemInfo = (param, socket) => { 37 | socket._delay = 5000; 38 | return { 39 | // 检查时间 40 | "checkTime": Date.now(), 41 | // 服务器名称 42 | "sourceName": servers[server.next()].name, 43 | // 服务器 IP 44 | "sourceIP": servers[server.now()].ip, 45 | // 服务器 ID 46 | "sourceID": servers[server.now()].id, 47 | // jvm最大可使用内存(kb) 48 | "jvmMaxMemory": jvmMaxMemory, 49 | // jvm目前占用的内存(kb) 50 | "jvmUsingMemory": jvmUsingMemory.next(), 51 | // jvm剩余可使用内存(kb) 52 | "jvmFreeMemory": jvmMaxMemory - jvmUsingMemory.now(), 53 | // cpu使用率 54 | "cpuRatio": cpuRatio.next(), 55 | // 总物理内存(kb) 56 | "totalPhysicalMemorySize": totalPhysicalMemorySize, 57 | // 已使用的物理内存(kb) 58 | "usedPhysicalMemorySize": usedPhysicalMemorySize.next(), 59 | // 剩余物理内存(kb) 60 | "freePhysicalMemorySize": totalPhysicalMemorySize - usedPhysicalMemorySize.now(), 61 | // 总物理磁盘(kb) 62 | "totalDiskSize": totalDiskSize, 63 | // 已使用的物理磁盘(kb) 64 | "usedDiskSize": usedDiskSize.next(), 65 | // 剩余物理磁盘(kb) 66 | "freeDiskSize": totalDiskSize - usedDiskSize.now(), 67 | // 线程总数 68 | "totalThread": totalThread.next(), 69 | // 内部服务ping值 70 | "innerServerPing": innerServerPing.next(), 71 | // 远程服务ping值 72 | "remoteServerPing": remoteServerPing.next(), 73 | // 网络连接数 74 | "netEstablished": netEstablished.next(), 75 | // 网络连接关闭数 76 | "netCloseWait": netCloseWait.next(), 77 | // 网络连接等待数 78 | "netTimeWait": netTimeWait.next(), 79 | }; 80 | }; 81 | -------------------------------------------------------------------------------- /mock/service/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock Service 4 | * ============================================================================= 5 | * @useage 6 | * import mockService form "mock/service"; 7 | * mockService.{type}.{key}(...); 8 | * @example 9 | * mockService.axios.getInfo(...); 10 | * ============================================================================= 11 | * 12 | * @author dondevi 13 | * @create 2017-09-28 14 | * 15 | * @update 2018-03-30 dondevi 16 | * 1.Update: `module.exports` to `export` ! 17 | * 18 | */ 19 | 20 | import URLS from "service/urls"; 21 | import REQUEST from "service/request"; 22 | import ADAPTER from "mock/service/request"; 23 | 24 | export default factoryMockService(); 25 | 26 | 27 | /** 28 | * 覆盖 service 接口 29 | * @useage Add "?mock" in URL 30 | */ 31 | export function injectMockService () { 32 | // let { axiosDefaults } = require("service/request/axios.js"); 33 | let { socketDefaults } = require("service/request/socket.js"); 34 | // axiosDefaults.adapter = ADAPTER.axios; 35 | socketDefaults.adapter = ADAPTER.socket; 36 | } 37 | 38 | 39 | /** 40 | * 生成 Mock Service 41 | */ 42 | function factoryMockService () { 43 | const mockService = {}; 44 | for (let type in URLS) { 45 | mockService[type] = mockService[type] || {}; 46 | for (let key in URLS[type]) { 47 | mockService[type][key] = (param, handler, config = {}) => { 48 | config.adapter = ADAPTER[type]; 49 | return REQUEST[type](URLS[type][key], param, handler, config); 50 | }; 51 | } 52 | } 53 | return mockService; 54 | } 55 | -------------------------------------------------------------------------------- /mock/service/request/axios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock Request 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2017-11-29 8 | * 9 | * @update 2018-02-09 dondevi 10 | * 1.Move: getMockData() to "/mock/service/util.js" 11 | */ 12 | 13 | import { getResponse } from "mock/service/respond/axios.js"; 14 | 15 | /** 16 | * Axios 假数据适配器 17 | * @param {Object} config - Axios 配置 18 | * @return {Promise} 19 | */ 20 | export default function axiosAdapter (config) { 21 | return new Promise((resolve, reject) => { 22 | const url = config.url.replace(config.baseURL, ""); 23 | const request = transformRequest(config.data, config.headers); 24 | const response = getResponse(url, request); 25 | const axiosResponse = { ...response, config }; 26 | settle(resolve, reject, axiosResponse); 27 | }); 28 | } 29 | 30 | /** 31 | * Transform request param 32 | * @param {*} request - 提交参数 33 | */ 34 | function transformRequest (request, headers) { 35 | // if (/x-www-form-urlencoded/.test(headers["Content-Type"])) { 36 | // return { param: unserialize(request) } 37 | // } 38 | // if (/application\/json/.test(headers["Content-Type"])) { 39 | return JSON.parse(request); 40 | // } 41 | } 42 | 43 | /** 44 | * Process Promise via HTTP status 45 | * @see https://github.com/mzabriskie/axios/blob/master/lib/core/settle.js 46 | * @param {Function} resolve - Promise resolve 47 | * @param {Function} reject - Promise reject 48 | * @param {object} response - Axios response 49 | */ 50 | function settle (resolve, reject, response) { 51 | const { url, validateStatus } = response.config; 52 | const { status } = response; 53 | if (!status || !validateStatus || validateStatus(status)) { 54 | return resolve(response); 55 | } 56 | const error = new Error(`Request failed: ${url} [${status}]`); 57 | error.config = response.config; 58 | error.response = response; // For process logic in catch() 59 | reject(error); 60 | }; 61 | -------------------------------------------------------------------------------- /mock/service/request/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-02-11 4 | */ 5 | 6 | // import axiosAdapter from "mock/service/request/axios.js"; 7 | import socketAdapter from "mock/service/request/socket.js"; 8 | 9 | export default { 10 | // axios: axiosAdapter, 11 | socket: socketAdapter, 12 | }; 13 | -------------------------------------------------------------------------------- /mock/service/request/socket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock WebSocket 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-09 8 | * 9 | * @update 2018-03-08 dondevi 10 | * 1.Rebuild: with class MockSocket 11 | */ 12 | 13 | import { inheritEventTarget } from "mock/modules/event.js"; 14 | import { openSocket, getResponse } from "mock/service/respond/socket.js"; 15 | 16 | /** 17 | * WebSocket mock adapter 18 | * @param {String} url - Socket address 19 | * @return {Object} 20 | */ 21 | export default function socketAdapter (url) { 22 | return new MockSocket(url); 23 | }; 24 | 25 | /** 26 | * Class MockSocket 27 | * @param {String} url 28 | */ 29 | function MockSocket (url) { 30 | this.url = url; 31 | this.readyState = 0; 32 | this.onopen = null; 33 | this.onmessage = null; 34 | this.onerror = null; 35 | this.onclose = null; 36 | this._timer = -1; 37 | this._delay = 50000; 38 | inheritEventTarget(this); 39 | window.setTimeout(() => openSocket(this)); 40 | } 41 | 42 | /** 43 | * @see https://medium.com/@tverwaes/setting-up-prototypes-in-v8-ec9c9491dfe2 44 | */ 45 | const mockSocketProto = MockSocket.prototype; 46 | mockSocketProto.CONNECTING = MockSocket.CONNECTING = 0; 47 | mockSocketProto.OPEN = MockSocket.OPEN = 1; 48 | mockSocketProto.CLOSING = MockSocket.CLOSING = 2; 49 | mockSocketProto.CLOSED = MockSocket.CLOSED = 3; 50 | 51 | mockSocketProto._trigger = function (type, props) { 52 | let event = new Event(type); 53 | Object.assign(event, props); 54 | this[`on${type}`] && this[`on${type}`](props); 55 | this.dispatchEvent(event); 56 | } 57 | 58 | mockSocketProto.send = function (data) { 59 | if (data) { 60 | let response = getResponse(this.url, data, this); 61 | this._trigger("message", { data: response }); 62 | } 63 | }; 64 | 65 | mockSocketProto.close = function (code, reason) { 66 | this.readyState = this.CLOSED; 67 | this._trigger("close", { code, reason }); 68 | window.clearTimeout(this._timer); 69 | }; 70 | -------------------------------------------------------------------------------- /mock/service/request/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-02-09 4 | */ 5 | 6 | /** 7 | * URL 匹配 DATA 8 | * @param {Object} URLS - 接口地址集合 9 | * @param {Object} DATAS - 假数据集合 10 | * @return {Object} 11 | */ 12 | export function mapMockData (URLS, DATAS) { 13 | let MOCKS = {}; 14 | for (let type in URLS) { 15 | MOCKS[type] = MOCKS[type] || {}; 16 | for (let key in URLS[type]) { 17 | let url = URLS[type][key]; 18 | let data = DATAS[type][key]; 19 | MOCKS[type][url] = data; 20 | } 21 | } 22 | return MOCKS; 23 | } 24 | 25 | /** 26 | * 通过 URL 获取假数据 27 | * @param {Object} MOCKS - 假数据集合 28 | * @param {String} url - 提交地址 29 | * @param {*} param - 提交参数 30 | * @return {*} 31 | */ 32 | export function getMockData (MOCKS, url, param, option) { 33 | var match = MOCKS[url]; 34 | if ("function" === typeof match) { 35 | match = match(param, option); 36 | } 37 | return match; 38 | } 39 | -------------------------------------------------------------------------------- /mock/service/respond/axios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock Response for Axios 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-08 8 | */ 9 | 10 | import { axios as RESPONSES } from "mock/service/respond"; 11 | 12 | /** 13 | * Get response form mock data or function 14 | * @param {String} url - Request address 15 | * @param {Object} request - Request param 16 | * @return {Object} 17 | */ 18 | export function getResponse (url, request) { 19 | let status = 200; 20 | let data = null; 21 | try { 22 | if (!(url in RESPONSES)) { throw { status: 404 }; } 23 | let response = RESPONSES[url]; 24 | if ("function" === typeof response) { 25 | response = response(request); 26 | } 27 | data = { error: false, data: response }; 28 | } catch (exception) { 29 | status = exception.status || 500; 30 | switch (status) { 31 | case 401: exception = `${url} 401 (Unauthorized)`; break; 32 | case 403: exception = `${url} 403 (Forbidden)`; break; 33 | case 404: exception = `${url} 404 (Not Found)`; break; 34 | case 200: exception = exception.exception; break; 35 | } 36 | console.error(exception); 37 | data = { error: true, exception }; 38 | exception = null; 39 | } 40 | data.requestNo = request.requestNo; 41 | return { status, data }; 42 | } 43 | -------------------------------------------------------------------------------- /mock/service/respond/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dondevi 3 | * @create 2018-03-08 4 | */ 5 | 6 | import URLS from "service/urls"; 7 | import DATAS from "mock/service/datas"; 8 | 9 | // export const axios = mapResponses(URLS.axios, DATAS.axios); 10 | export const socket = mapResponses(URLS.socket, DATAS.socket); 11 | 12 | /** 13 | * Get responses mapping data 14 | * @param {Object} urls 15 | * @param {Object} datas 16 | * @return {Object} 17 | */ 18 | export function mapResponses (urls, datas) { 19 | let result = {}; 20 | for (let key in urls) { 21 | let url = urls[key]; 22 | let data = datas[key]; 23 | result[url] = data; 24 | } 25 | return result; 26 | } 27 | -------------------------------------------------------------------------------- /mock/service/respond/socket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Mock Response for Websocket 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-08 8 | * 9 | * @update 2018-03-09 dondevi 10 | * 1.Add: openSocket(), pushMessage() 11 | */ 12 | 13 | import { socket as RESPONSES } from "mock/service/respond"; 14 | 15 | /** 16 | * Mock socket server 17 | * @param {Object} socket 18 | */ 19 | export function openSocket (socket) { 20 | socket.readyState = socket.OPEN; 21 | socket._trigger("open"); 22 | pushMessage(socket); 23 | } 24 | 25 | /** 26 | * Push message 27 | * @param {Object} socket 28 | */ 29 | function pushMessage (socket) { 30 | let response = getResponse(socket.url, null, socket); 31 | socket._trigger("message", { data: response }); 32 | if (socket._delay) { 33 | socket._timer = window.setTimeout(() => pushMessage(socket), socket._delay); 34 | } 35 | } 36 | 37 | /** 38 | * Get response form mock data or function 39 | * @param {String} url - Socket address 40 | * @param {Object} data - Socket message 41 | * @param {Object} socket - Socket object 42 | * @return {Object} 43 | */ 44 | export function getResponse (url, data, socket) { 45 | let response = RESPONSES[url]; 46 | try { 47 | if (!(url in RESPONSES)) { throw { status: 404 }; } 48 | if ("function" === typeof response) { 49 | response = response(data, socket); 50 | } 51 | } catch (exception) { 52 | status = exception.status || 500; 53 | switch (status) { 54 | case 401: exception = `${url} 401 (Unauthorized)`; break; 55 | case 403: exception = `${url} 403 (Forbidden)`; break; 56 | case 404: exception = `${url} 404 (Not Found)`; break; 57 | case 200: exception = exception.exception; break; 58 | } 59 | console.error(exception); 60 | socket.close(1011, exception); 61 | exception = null; 62 | } 63 | return JSON.stringify(response); 64 | }; 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server-monitor", 3 | "author": "dondevi", 4 | "version": "0.7.5", 5 | "private": true, 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/dondevi/server-monitor-ui/" 9 | }, 10 | "demo": "https://dondevi.github.io/server-monitor-ui/dist/index.html?mock", 11 | "scripts": { 12 | "init": "npm link vue & npm link vue-router & npm link quasar-framework@0.15.6 & npm link quasar-extras", 13 | "dev": "cooking watch -p", 14 | "dist": "cooking build -p" 15 | }, 16 | "engines": { 17 | "node": ">= 8.9.0", 18 | "npm": ">= 5.6.0" 19 | }, 20 | "dependencies": { 21 | "vue": "^2.5", 22 | "vue-router": "^3.0", 23 | "echarts": "^4.0.4", 24 | "quasar-framework": "0.15.6", 25 | "quasar-extras": "~1.0.2" 26 | }, 27 | "devDependencies": { 28 | "cooking-cli": "^1.5.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /quasar.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Quasar Config 4 | * ============================================================================= 5 | * 6 | * @see http://quasar-framework.org/guide/app-quasar.conf.js.html 7 | * @permission Engineer 8 | * 9 | * @author dondevi 10 | * @create 2018-03-21 11 | */ 12 | 13 | module.exports = function (ctx) { 14 | return { 15 | framework: { 16 | components: [ 17 | "QBtn", 18 | "QCard", 19 | "QCardMain", 20 | "QCardSeparator", 21 | "QCardTitle", 22 | "QChip", 23 | "QIcon", 24 | "QItem", 25 | "QItemMain", 26 | "QItemSeparator", 27 | "QItemSide", 28 | "QItemTile", 29 | "QLayout", 30 | "QLayoutHeader", 31 | "QList", 32 | "QListHeader", 33 | "QModal", 34 | "QModalLayout", 35 | "QPage", 36 | "QPageContainer", 37 | "QPopover", 38 | "QProgress", 39 | "QTooltip", 40 | "QToolbar", 41 | "QToolbarTitle", 42 | ], 43 | directives: [ 44 | "BackToTop", 45 | ], 46 | plugins: [], 47 | }, 48 | extras: [], 49 | css: [], 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /src/assets/_raw/alert.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/_raw/alert.mp3 -------------------------------------------------------------------------------- /src/assets/_raw/error.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/_raw/error.mp3 -------------------------------------------------------------------------------- /src/assets/_raw/fatal.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/_raw/fatal.mp3 -------------------------------------------------------------------------------- /src/assets/_raw/warn.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/_raw/warn.mp3 -------------------------------------------------------------------------------- /src/assets/alert.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/alert.mp3 -------------------------------------------------------------------------------- /src/assets/error.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/error.mp3 -------------------------------------------------------------------------------- /src/assets/fatal.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/fatal.mp3 -------------------------------------------------------------------------------- /src/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/favicon.png -------------------------------------------------------------------------------- /src/assets/warn.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/assets/warn.mp3 -------------------------------------------------------------------------------- /src/components/echarts.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | 19 | 70 | 71 | 77 | -------------------------------------------------------------------------------- /src/components/q-item-group.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 62 | 63 | 150 | 151 | 169 | -------------------------------------------------------------------------------- /src/components/q-item-ratio.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 58 | 59 | 137 | 138 | 157 | -------------------------------------------------------------------------------- /src/config/echarts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Echarts common options 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-16 8 | * 9 | * @todo 2018-03-29 dondevi 10 | * 1.Tooltip formatter show seconds and labels 11 | */ 12 | 13 | /** 14 | * Get line chart option 15 | * @param {Object} option 16 | * @return {Object} 17 | */ 18 | export function getLineChartOption (option) { 19 | const tooltipOption = { 20 | trigger: "axis", padding: [5, 12], confine: true, 21 | axisPointer: { 22 | lineStyle: { color: "rgba(255,255,255,0.3)" }, 23 | }, 24 | // formatter: params => 25 | // `${params[0].axisValueLabel}` + 26 | // `
${params[0].value}%`, 27 | }; 28 | const seriesOption = { 29 | type: "line", showSymbol: false, areaStyle: {}, 30 | itemStyle: { color: "rgba(255,255,255,0.5)" }, 31 | }; 32 | const chartOption = { 33 | tooltip: tooltipOption, 34 | grid: { top: 5, right: 0, bottom: 0, left: 0 }, 35 | xAxis: { type: "time", show: false }, 36 | yAxis: { type: "value", show: false }, 37 | }; 38 | mergeOption(chartOption, option) 39 | mergeSeriesOption(chartOption, seriesOption); 40 | return chartOption; 41 | } 42 | 43 | /** 44 | * Merge options 45 | * @param {Object} target 46 | * @param {Object} option 47 | * @param {Object} 48 | */ 49 | function mergeOption (target, option) { 50 | for (let key in option) { 51 | if (!option.hasOwnProperty(key)) { continue; } 52 | let value = option[key]; 53 | if ("[object Object]" === Object.prototype.toString.call(value)) { 54 | if (!target.hasOwnProperty(key)) { 55 | target[key] = {}; 56 | } 57 | mergeOption(target[key], value); 58 | } else { 59 | target[key] = value; 60 | } 61 | } 62 | return target; 63 | } 64 | 65 | /** 66 | * Merge series option 67 | * @param {Object} option 68 | */ 69 | function mergeSeriesOption (option, seriesOption) { 70 | let { series } = option; 71 | if (Array.isArray(series)) { 72 | series.forEach(seriesItem => { 73 | Object.assign(seriesItem, seriesOption); 74 | }); 75 | } else if (series) { 76 | Object.assign(series, seriesOption); 77 | } else { 78 | option.series = seriesOption; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/filters/formatByte.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Format Byte 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-08 8 | */ 9 | 10 | export default function formatByte (value, digits = 1, radix = 1024) { 11 | if (!+value) { return value; } 12 | const units = [/*"B", */"KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; 13 | let exponent = Math.floor(Math.log(value) / Math.log(radix)); 14 | let result = value / Math.pow(radix, exponent); 15 | return result.toFixed(digits).concat(" ", units[exponent]); 16 | }; 17 | -------------------------------------------------------------------------------- /src/filters/formatDate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Format Date 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-03-08 8 | */ 9 | 10 | export default function formatDate (value, format = "YYYY-MM-DD hh:mm:ss") { 11 | if (!value) { return ""; } 12 | 13 | const date = new Date(value); 14 | const values = { 15 | "(Y+)": date.getFullYear(), // Year 16 | "(M+)": date.getMonth() + 1, // Month 17 | "(D+)": date.getDate(), // Day 18 | "(h+)": date.getHours(), // Hour 19 | "(m+)": date.getMinutes(), // Minute 20 | "(s+)": date.getSeconds(), // Second 21 | "(q+)": Math.floor((date.getMonth() + 3) / 3), // Quarter 22 | "(ms)": date.getMilliseconds() // Millisecond 23 | }; 24 | 25 | return Object.keys(values).reduce((result, key) => { 26 | if (!new RegExp(key).test(format)) { 27 | return result; 28 | } 29 | let match = RegExp.$1; 30 | let value = values[key].toString(); 31 | let length = value.length; 32 | if (1 === length) { 33 | value = "0" + value; 34 | length = match.length; 35 | } 36 | let target = value.substr(-length, length); 37 | return result.replace(match, target); 38 | }, format); 39 | }; 40 | -------------------------------------------------------------------------------- /src/frames/app.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /src/frames/login.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondevi/server-monitor-ui/2bf0585c280f64ce75bff1bd4735e9c1272de503/src/frames/login.vue -------------------------------------------------------------------------------- /src/frames/main.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 64 | 65 | 73 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Server Monitor 8 | 9 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Main Entry 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-02 8 | */ 9 | 10 | /** 11 | * Vue 12 | */ 13 | import Vue from "vue"; 14 | // Vue.config.silent = true; 15 | // Vue.config.performance = true; 16 | // Vue.config.errorHandler = (err, vm, info) => {}; 17 | // Vue.config.warnHandler = (err, vm, info) => {}; 18 | 19 | /** 20 | * Quasar Framework 21 | * @see http://quasar-framework.org/components/ 22 | */ 23 | import { Quasar, QuasarDirectives, QuasarComponents } from "quasar-framework-custom"; 24 | Vue.use(Quasar, { directives: QuasarDirectives, components: QuasarComponents }); 25 | 26 | /** 27 | * Echarts 28 | * @see https://github.com/ecomfe/vue-echarts/blob/master/README.zh_CN.md 29 | * @see https://ecomfe.github.io/echarts-doc/public/cn/api.html 30 | */ 31 | // import ECharts from "vue-echarts/dist/vue-echarts.js"; 32 | // Vue.component("chart", ECharts); 33 | 34 | /** 35 | * Filters 36 | */ 37 | import formatDate from "filters/formatDate.js"; 38 | import formatByte from "filters/formatByte.js"; 39 | Vue.filter("formatDate", formatDate); 40 | Vue.filter("formatByte", formatByte); 41 | 42 | /** 43 | * Components 44 | */ 45 | import ECharts from "components/echarts.vue"; 46 | Vue.component("chart", ECharts); 47 | 48 | /** 49 | * Router & APP 50 | */ 51 | import router from "router/index.js"; 52 | // import session from "router/session.js"; 53 | import app from "frames/app.vue"; 54 | new Vue({ router, render: h => h(app) }).$mount("#app"); 55 | -------------------------------------------------------------------------------- /src/pages/business.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 112 | 113 | 139 | -------------------------------------------------------------------------------- /src/pages/dashboard.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 30 | 31 | 40 | 41 | 46 | -------------------------------------------------------------------------------- /src/pages/database.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 215 | 216 | 244 | 245 | 253 | -------------------------------------------------------------------------------- /src/pages/database/detail.vue: -------------------------------------------------------------------------------- 1 | 12 | 142 | 143 | 153 | -------------------------------------------------------------------------------- /src/pages/database/list.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 41 | 42 | 103 | 104 | 109 | -------------------------------------------------------------------------------- /src/pages/exception.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 87 | 88 | 175 | 176 | 193 | -------------------------------------------------------------------------------- /src/pages/form.vue: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /src/pages/server/detail.vue: -------------------------------------------------------------------------------- 1 | 12 | 73 | 74 | 84 | -------------------------------------------------------------------------------- /src/pages/server/list.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 42 | 43 | 129 | 130 | 135 | -------------------------------------------------------------------------------- /src/pages/system.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 131 | 132 | 133 | 134 | 223 | 224 | 225 | 226 | 244 | -------------------------------------------------------------------------------- /src/quasar.js: -------------------------------------------------------------------------------- 1 | // Generated automatically by build/quasar.js 2 | // Wed Apr 04 2018 17:52:44 GMT+0800 (中国标准时间) 3 | // Don't Edit please! 4 | 5 | // import "quasar-extras/roboto-font"; 6 | import "quasar-extras/material-icons"; 7 | 8 | // import "quasar-framework/dist/umd/quasar.mat.css"; 9 | import "./quasar.styl"; 10 | 11 | import install from "quasar-framework/src/install.js"; 12 | import icons from "quasar-framework/src/icons.js"; 13 | 14 | import QBtn from "quasar-framework/src/components/btn/QBtn.js"; 15 | import QCard from "quasar-framework/src/components/card/QCard.js"; 16 | import QCardMain from "quasar-framework/src/components/card/QCardMain.js"; 17 | import QCardSeparator from "quasar-framework/src/components/card/QCardSeparator.js"; 18 | import QCardTitle from "quasar-framework/src/components/card/QCardTitle.js"; 19 | import QChip from "quasar-framework/src/components/chip/QChip.js"; 20 | import QIcon from "quasar-framework/src/components/icon/QIcon.js"; 21 | import QItem from "quasar-framework/src/components/list/QItem.js"; 22 | import QItemMain from "quasar-framework/src/components/list/QItemMain.js"; 23 | import QItemSeparator from "quasar-framework/src/components/list/QItemSeparator.js"; 24 | import QItemSide from "quasar-framework/src/components/list/QItemSide.js"; 25 | import QItemTile from "quasar-framework/src/components/list/QItemTile.js"; 26 | import QLayout from "quasar-framework/src/components/layout/QLayout.js"; 27 | import QLayoutHeader from "quasar-framework/src/components/layout/QLayoutHeader.js"; 28 | import QList from "quasar-framework/src/components/list/QList.js"; 29 | import QListHeader from "quasar-framework/src/components/list/QListHeader.js"; 30 | import QModal from "quasar-framework/src/components/modal/QModal.js"; 31 | import QModalLayout from "quasar-framework/src/components/modal/QModalLayout.js"; 32 | import QPage from "quasar-framework/src/components/layout/QPage.js"; 33 | import QPageContainer from "quasar-framework/src/components/layout/QPageContainer.js"; 34 | import QPopover from "quasar-framework/src/components/popover/QPopover.js"; 35 | import QProgress from "quasar-framework/src/components/progress/QProgress.js"; 36 | import QTooltip from "quasar-framework/src/components/tooltip/QTooltip.js"; 37 | import QToolbar from "quasar-framework/src/components/toolbar/QToolbar.js"; 38 | import QToolbarTitle from "quasar-framework/src/components/toolbar/QToolbarTitle.js"; 39 | import BackToTop from "quasar-framework/src/directives/back-to-top.js"; 40 | 41 | export const Quasar = { install, icons }; 42 | export const QuasarComponents = { QBtn, QCard, QCardMain, QCardSeparator, QCardTitle, QChip, QIcon, QItem, QItemMain, QItemSeparator, QItemSide, QItemTile, QLayout, QLayoutHeader, QList, QListHeader, QModal, QModalLayout, QPage, QPageContainer, QPopover, QProgress, QTooltip, QToolbar, QToolbarTitle }; 43 | export const QuasarDirectives = { BackToTop }; 44 | -------------------------------------------------------------------------------- /src/quasar.styl: -------------------------------------------------------------------------------- 1 | // Generated automatically by build/quasar.js 2 | // Wed Apr 04 2018 17:52:44 GMT+0800 (中国标准时间) 3 | // Don't Edit please! 4 | 5 | @import "../node_modules/quasar-framework/src/css/core.variables.styl"; 6 | @import "../node_modules/quasar-framework/src/css/variables.mat.styl"; 7 | @import "../node_modules/quasar-framework/src/css/normalize.styl"; 8 | // @import "../node_modules/quasar-framework/src/components/*/*.mat.styl"; 9 | @import "../node_modules/quasar-framework/src/components/btn/*.mat.styl"; 10 | @import "../node_modules/quasar-framework/src/components/card/*.mat.styl"; 11 | @import "../node_modules/quasar-framework/src/components/chip/*.mat.styl"; 12 | @import "../node_modules/quasar-framework/src/components/icon/*.mat.styl"; 13 | @import "../node_modules/quasar-framework/src/components/list/*.mat.styl"; 14 | @import "../node_modules/quasar-framework/src/components/layout/*.mat.styl"; 15 | @import "../node_modules/quasar-framework/src/components/modal/*.mat.styl"; 16 | @import "../node_modules/quasar-framework/src/components/popover/*.mat.styl"; 17 | @import "../node_modules/quasar-framework/src/components/progress/*.mat.styl"; 18 | @import "../node_modules/quasar-framework/src/components/tooltip/*.mat.styl"; 19 | @import "../node_modules/quasar-framework/src/components/toolbar/*.mat.styl"; 20 | @import "../node_modules/quasar-framework/src/css/core/*.styl"; 21 | // @import "../node_modules/quasar-framework/src/ie-compat/ie.mat.styl"; 22 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Router 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-02 8 | * 9 | * @update 2018-03-06 dondevi 10 | * 1.Rename: "layous/" to "frames/" 11 | */ 12 | 13 | import Vue from "vue"; 14 | import VueRouter from "vue-router"; 15 | 16 | Vue.use(VueRouter); 17 | 18 | 19 | import main from "frames/main"; 20 | 21 | // const dashboard = () => import("pages/dashboard"); 22 | import dashboard from "pages/dashboard"; 23 | 24 | 25 | const routes = [ 26 | { path: "/", component: main, meta: { title: "Server Monitor" }, children: [ 27 | { path: "/", component: dashboard, meta: { title: "Dashboard" } }, 28 | ] }, 29 | ]; 30 | 31 | 32 | const router = new VueRouter({ routes }); 33 | 34 | export default router; 35 | -------------------------------------------------------------------------------- /src/service/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Service Config 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-09 8 | */ 9 | 10 | const { host, pathname } = window.location; 11 | 12 | /** 13 | * 环境判断 14 | * @type {Boolean} 15 | */ 16 | // const isLocal = /localhost|192\.168\./.test(host); 17 | 18 | /** 19 | * 基本地址 20 | * @type {String} 21 | */ 22 | export const BASEURL = `//${host}`; 23 | export const BASEURL_WS = `ws://${host}`; 24 | -------------------------------------------------------------------------------- /src/service/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Service 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-05 8 | * 9 | * @update 2018-02-09 dondevi 10 | */ 11 | 12 | import URLS from "service/urls/index.js"; 13 | import REQUEST from "service/request/index.js"; 14 | 15 | export default factoryService(); 16 | 17 | /** 18 | * 生成 service 19 | * @return {Object} 20 | */ 21 | function factoryService () { 22 | const service = {}; 23 | for (let type in URLS) { 24 | service[type] = service[type] || {}; 25 | for (let key in URLS[type]) { 26 | service[type][key] = REQUEST[type].bind(undefined, URLS[type][key]); 27 | } 28 | } 29 | return service; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/service/request/axios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Common Request 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-05 8 | * 9 | */ 10 | 11 | import axios from "axios"; 12 | 13 | import { BASEURL } from "service/config.js"; 14 | 15 | /** 16 | * Axios 实例 17 | */ 18 | export const axiosInstance = axios.create(); 19 | export const axiosDefaults = axiosInstance.defaults; // 暴露给 Mock 20 | 21 | /** 22 | * Axios 默认配置 23 | * @see https://www.npmjs.com/package/axios#request-config 24 | * @see https://github.com/mzabriskie/axios/blob/master/lib/defaults.js 25 | * @type {Object} 26 | */ 27 | axiosDefaults.baseURL = BASEURL; 28 | axiosDefaults.transformRequest = [transformRequest].concat(axios.defaults.transformRequest); 29 | 30 | 31 | /** 32 | * 通用请求函数 33 | * @param {String} url - 请求地址(相对路径) 34 | * @param {*} data - 请求参数 35 | * @param {Object} config - Axios 配置 36 | * @return {Promise} 37 | */ 38 | export default function axiosRequest (url, data, config) { 39 | config = Object.assign({ method: "post", url, data }, config); 40 | return axiosInstance(config).then(processResponse).catch(processError); 41 | }; 42 | 43 | /** 44 | * 转换提交参数 45 | * @param {*} request - 提交参数 46 | */ 47 | function transformRequest (request) { 48 | return { 49 | requestNo: Date.now(), 50 | param: request, 51 | }; 52 | } 53 | 54 | /** 55 | * 处理 Axios 响应数据 56 | * @param {Object} response - 响应对象 57 | */ 58 | function processResponse (response) { 59 | const { data } = response; 60 | if (data.error) { 61 | return Promise.reject({ response }); 62 | } 63 | return data; 64 | } 65 | 66 | /** 67 | * 处理 Axios 错误数据 68 | * @param {Object} error - 错误对象 69 | */ 70 | import { Toast, Alert } from "quasar-framework-js"; 71 | function processError (error) { 72 | const { status, data } = error.response; 73 | // 业务错误 74 | if (200 === status) { 75 | const { message } = data.exception; 76 | Toast.create({ html: message, timeout: 5000 }); 77 | return Promise.reject(message); 78 | // 网络错误 79 | } else if (!/401|403/.test(status)) { 80 | Alert.create({ 81 | icon: "error", 82 | html: `请求失败:${status}
${error.config.url}`, 83 | duration: 0, 84 | }); 85 | } 86 | return Promise.reject(error); // 避免后续 then 的执行 87 | } 88 | -------------------------------------------------------------------------------- /src/service/request/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Common Request 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-09 8 | */ 9 | 10 | // import axiosRequest from "service/request/axios.js"; 11 | import socketRequest from "service/request/socket.js"; 12 | 13 | export default { 14 | // axios: axiosRequest, 15 | socket: socketRequest, 16 | }; 17 | -------------------------------------------------------------------------------- /src/service/request/socket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Common WebSocket 4 | * ============================================================================= 5 | * 6 | * @author dondevi 7 | * @create 2018-02-09 8 | * 9 | * @update 2018-02-11 dondevi 10 | * 11 | */ 12 | 13 | import { BASEURL_WS } from "service/config.js"; 14 | 15 | export const socketDefaults = {}; 16 | 17 | /** 18 | * WebSocket Request 19 | * @param {String} url 20 | * @param {*} param 21 | * @param {Function} handler - Message Handler with json 22 | * @param {Object} option 23 | * @param {String} option.url 24 | * @param {*} option.param 25 | * @param {Function} option.onmessage - Message Handler with event 26 | * @param {Function} option.onopen 27 | * @param {Function} option.onerror 28 | * @param {Function} option.onclose 29 | * @return {Object} socket - WebSocket instance 30 | */ 31 | export default function socketRequest (url, param, handler, option) { 32 | if ("[object Object]" === Object.prototype.toString.call(url)) { 33 | url = option.url; 34 | param = option.param; 35 | option = url; 36 | } 37 | option = Object.assign({ 38 | onopen: param && (event => { 39 | option.socket.send(param); 40 | }), 41 | onmessage: event => { 42 | handler(JSON.parse(event.data)); 43 | }, 44 | }, socketDefaults, option); 45 | if (option.adapter) { 46 | option.socket = option.adapter(url); 47 | } else { 48 | option.socket = new WebSocket(BASEURL_WS + url); 49 | } 50 | let socket = option.socket; 51 | // Keep alive 52 | const timer = window.setInterval(() => socket.send(""), 30000); 53 | option.onopen && socket.addEventListener("open", option.onopen); 54 | option.onmessage && socket.addEventListener("message", option.onmessage); 55 | option.onerror && socket.addEventListener("error", option.onerror); 56 | option.onclose && socket.addEventListener("close", event => { 57 | window.clearInterval(timer); 58 | option.onclose(event); 59 | }); 60 | return socket; 61 | } 62 | -------------------------------------------------------------------------------- /src/service/urls/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Service URLs 4 | * ============================================================================= 5 | * 6 | * comment regex: (^\/\/.*)|(\s+\/\/.*)|((\/\*)(.|\n)+?(\*\/)) 7 | * 8 | * @author dondevi 9 | * @create 2018-02-05 10 | * 11 | * @update 2018-02-09 dondevi 12 | */ 13 | 14 | const path = "/monitorcenter-as-server/monitor/websocket/"; 15 | 16 | export default { 17 | axios: { 18 | }, 19 | socket: { 20 | getSystemInfo: path + "systeminfostatistics", 21 | getException: path + "exceptioninfostatistics", 22 | getStatistics: path + "credinfostatistics", 23 | getDatabaseInfo: path + "databaseinfosatistics", 24 | }, 25 | }; 26 | --------------------------------------------------------------------------------