├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── LICENSE ├── README.md ├── build ├── build.js ├── check-versions.js ├── dev-client.js ├── dev-server.js ├── mock-server.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── index.html ├── mock.js ├── package.json ├── src ├── App.vue ├── api.js ├── common │ ├── auth.js │ ├── axios.js │ └── utils.js ├── components │ ├── 404.vue │ ├── panel.vue │ ├── selectTree.vue │ ├── sideMenu.vue │ ├── subMenu.vue │ └── treeter.js ├── filters │ └── index.js ├── frame.vue ├── main.js ├── mock │ ├── common.js │ ├── global.js │ ├── mock.js │ └── user.js ├── pages │ ├── dashboard.vue │ ├── layout │ │ ├── footer.vue │ │ ├── header.vue │ │ └── index.js │ ├── login.vue │ ├── register.vue │ ├── resetPwd.vue │ └── sys │ │ ├── menu.vue │ │ ├── resource.vue │ │ ├── role.vue │ │ ├── user.vue │ │ └── userAdd.vue ├── router │ ├── index.js │ └── routes.js ├── services │ ├── default.js │ └── sys.js └── store │ ├── actions.js │ ├── index.js │ └── mutation-types.js └── static ├── data ├── cmenu.png ├── dash.png ├── dash2.png ├── data.json ├── login.png ├── menu.png ├── menu2.png ├── menu5.png ├── mobile.png ├── resource.png ├── role.png ├── role4.png ├── user.png └── user2.png ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf ├── fontawesome-webfont.woff └── fontawesome-webfont.woff2 └── img ├── 404_error.png └── user.png /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "stage-0" 5 | ], 6 | "plugins": [ 7 | "transform-runtime", 8 | "transform-vue-jsx" 9 | ], 10 | "comments": false, 11 | "env": { 12 | "test": { 13 | "presets": [ 14 | "es2015", 15 | "stage-0" 16 | ], 17 | "plugins": [ 18 | "istanbul" 19 | ] 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | * 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | *.log 5 | .idea/ 6 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | >友情链接:[**【react-admin】**](https://github.com/lanux/react-admin)持续更新 [演示地址](https://lanux.github.io/react-admin/) 2 | 3 | [演示地址](https://lanux.github.io/Vue-Admin/ "Vue-Admin") 4 | >账号密码任意 5 | 6 | ## Build Setup 7 | ``` bash 8 | npm install 9 | 10 | # 修改文件内容/build/webpack.base.conf.js,将element-ui和vuex-router-sync版本替换成install后node_modules目录中当前版本,注意不能用软链 11 | #      { 12 | #        test: /\.js$/, 13 | #        loader: 'babel-loader', 14 | #        //exclude: /(node_modules|bower_components)/, 15 | #        // 注意elementUI的源码使用ES6需要解析 16 | #        include: [ 17 | #          resolve('src'), 18 | #          resolve('test'), 19 | #          resolve('/node_modules/.1.4.8@element-ui/src'), 20 | #          resolve('/node_modules/.1.4.8@element-ui/packages'), 21 | #          resolve('/node_modules/.4.3.0@vuex-router-sync') 22 | # ] 23 | # }, 24 | 25 | 26 | # serve with hot reload at localhost:9000 27 | npm run dev 28 | npm run build 29 | 30 | npm run mock 31 | ``` 32 | 33 | 1. **启动mock服务** 34 | npm run mock 35 | 2. **启动dev server** 36 | npm run dev 37 | 38 | 39 | - #### 打包发布,修改根路径名 40 | 1. 修改 **[./Vue-Admin/config/index.js](https://github.com/lanux/Vue-Admin/blob/master/config/index.js)** 参数:build.assetsPublicPath 41 | ```javascript 42 | //eg. assetsPublicPath: '/Vue-Admin/' 43 | assetsPublicPath: 'Your path name'; 44 | ``` 45 | 2. 修改 **[./Vue-Admin/src/api.js](https://github.com/lanux/Vue-Admin/blob/master/src/api.js)** 46 | ```javascript 47 | // export const CONTEXT = './Vue-Admin'; 48 | export const CONTEXT = 'Your path name'; 49 | ``` 50 | 51 | 52 | ``` 53 | cnpm i json-server -D 54 | cnpm i json-server -S 55 | npm outdated:检查包是否已经过时,此命令会列出所有已经过时的包,可以及时进行包的更新 56 | npm update moduleName:更新node模块 57 | npm uninstall moudleName:卸载node模块 58 | 59 | ``` 60 | 61 | ## 页面截图 62 | 63 |

64 |

65 |

66 |

67 |

68 |

69 |

70 |

71 |

72 |

73 |

74 |

75 |

76 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // 实现浏览器端的EventSource,用于跟服务器双向通信 3 | // webpack热重载客户端跟dev-server上的热重载插件之间需要进行双向通信 4 | // 服务端webpack重新编译后,会向客户端推送信息,告诉客户端进行更新 5 | require('eventsource-polyfill') 6 | // webpack热重载客户端 7 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 8 | 9 | // 客户端收到更新动作,执行页面刷新 10 | hotClient.subscribe(function (event) { 11 | if (event.action === 'reload') { 12 | window.location.reload() 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = require('./webpack.dev.conf') 14 | 15 | // 监听http端口 16 | var port = process.env.PORT || config.dev.port 17 | // 是否要自动打开浏览器 18 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 19 | // Define HTTP proxies to your custom API backend 20 | // https://github.com/chimurai/http-proxy-middleware 21 | var proxyTable = config.dev.proxyTable 22 | 23 | var app = express() 24 | var compiler = webpack(webpackConfig) 25 | 26 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 27 | publicPath: webpackConfig.output.publicPath, 28 | quiet: true 29 | }) 30 | 31 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 32 | log: () => {} 33 | }) 34 | // force page reload when html-webpack-plugin template changes 35 | compiler.plugin('compilation', function (compilation) { 36 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 37 | hotMiddleware.publish({ action: 'reload' }) 38 | cb() 39 | }) 40 | }) 41 | 42 | // proxy api requests 43 | Object.keys(proxyTable).forEach(function (context) { 44 | var options = proxyTable[context] 45 | if (typeof options === 'string') { 46 | options = { target: options } 47 | } 48 | app.use(proxyMiddleware(options.filter || context, options)) 49 | }) 50 | 51 | // handle fallback for HTML5 history API 52 | app.use(require('connect-history-api-fallback')()) 53 | 54 | // serve webpack bundle output 55 | app.use(devMiddleware) 56 | 57 | // enable hot-reload and state-preserving 58 | // compilation error display 59 | app.use(hotMiddleware) 60 | 61 | // serve pure static assets 62 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 63 | app.use(staticPath, express.static('./static')) 64 | 65 | var uri = 'http://localhost:' + port 66 | 67 | devMiddleware.waitUntilValid(function () { 68 | console.log('> Listening at ' + uri + '\n') 69 | }) 70 | 71 | module.exports = app.listen(port, function (err) { 72 | if (err) { 73 | console.log(err) 74 | return 75 | } 76 | 77 | // when env is testing, don't need open it 78 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 79 | opn(uri) 80 | } 81 | }) 82 | -------------------------------------------------------------------------------- /build/mock-server.js: -------------------------------------------------------------------------------- 1 | const jsonServer = require('json-server') 2 | var path = require('path') 3 | const server = jsonServer.create() 4 | const router = jsonServer.router(path.join(__dirname, '../static/data/data.json')) 5 | const middlewares = jsonServer.defaults() 6 | 7 | const config = require("../src/mock/mock.js") 8 | 9 | function parseKey(key) { 10 | var method = 'get'; 11 | var path = key; 12 | 13 | if (key.indexOf(' ') > -1) { 14 | var splited = key.split(' '); 15 | method = splited[0].toLowerCase(); 16 | path = splited[1]; 17 | } 18 | 19 | return { method: method, path: path }; 20 | } 21 | 22 | // Set default middlewares (logger, static, cors and no-cache) 23 | server.use(middlewares) 24 | 25 | function createMockHandler(method, path, value) { 26 | return function mockHandler(...args) { 27 | const res = args[1]; 28 | if (typeof value === 'function') { 29 | value(...args); 30 | } else { 31 | res.json(value); 32 | } 33 | }; 34 | } 35 | 36 | Object.keys(config).forEach(function (key) { 37 | var keyParsed = parseKey(key); 38 | if(!server[keyParsed.method]){ 39 | console.error('method of ' + key + ' is not valid') 40 | } 41 | if(!(typeof config[key] === 'function' || typeof(config[key]) === 'object')){ 42 | console.error('mock value of ' + key + ' should be function or object or string, but got ' + typeof(config[key])) 43 | } 44 | server[keyParsed.method](keyParsed.path, createMockHandler(keyParsed.method, keyParsed.path, config[key])); 45 | }); 46 | 47 | // To handle POST, PUT and PATCH you need to use a body-parser 48 | // You can use the one used by JSON Server 49 | server.use(jsonServer.bodyParser) 50 | 51 | // Use default router 52 | server.use(router) 53 | 54 | server.listen(3000, () => { 55 | console.log('Mock Server is running') 56 | }) 57 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var config = require('../config/index') 4 | var vueLoaderConfig = require('./vue-loader.conf') 5 | 6 | function resolve (dir) { 7 | return path.join(__dirname, '..', dir) 8 | } 9 | 10 | module.exports = { 11 | entry: { 12 | app: './src/main.js', 13 | vendor: [ 'vue', 'vuex', 'vue-router', 'element-ui' ] //第三方库和框架 14 | }, 15 | output: { 16 | // path仅仅告诉Webpack结果存储在哪里,然而publicPath项则被许多Webpack的插件用于在生产模式下更新内嵌到css、html文件里的url值。 17 | path: config.build.assetsRoot, 18 | filename: '[name].js', 19 | publicPath: config.dev.assetsPublicPath 20 | }, 21 | resolve: { 22 | extensions: ['.js', '.vue', '.json'], 23 | alias: { 24 | '@': resolve('src'), 25 | } 26 | }, 27 | module: { 28 | rules: [ 29 | // { 30 | // test: /\.(js|vue)$/, 31 | // loader: 'eslint-loader', 32 | // enforce: "pre", 33 | // include: [resolve('src'), resolve('test')], 34 | // options: { 35 | // formatter: require('eslint-friendly-formatter') 36 | // } 37 | // }, 38 | { 39 | test: /\.vue$/, 40 | loader: 'vue-loader', 41 | options: vueLoaderConfig 42 | }, 43 | { 44 | test: /\.js$/, 45 | loader: 'babel-loader', 46 | //exclude: /(node_modules|bower_components)/, 47 | // 注意elementUI的源码使用ES6需要解析 48 | include: [ 49 | resolve('src'), 50 | resolve('test'), 51 | resolve('/node_modules/.1.4.8@element-ui/src'), 52 | resolve('/node_modules/.1.4.8@element-ui/packages'), 53 | resolve('/node_modules/.4.3.0@vuex-router-sync') 54 | ] 55 | }, 56 | { 57 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 58 | loader: 'url-loader', 59 | options: { 60 | limit: 5120, 61 | name: utils.assetsPath('img/[name].[ext]') 62 | } 63 | }, 64 | { 65 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 66 | loader: 'url-loader', 67 | options: { 68 | limit: 10240, 69 | name: utils.assetsPath('media/[name].[ext]') 70 | } 71 | }, 72 | { 73 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 74 | loader: 'url-loader', 75 | options: { 76 | limit: 1024, 77 | name: utils.assetsPath('fonts/[name].[ext]') 78 | } 79 | } 80 | ] 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | //devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env, 23 | __DEV__:true, 24 | }),new webpack.ProvidePlugin({ 25 | $: "jquery", 26 | jQuery: "jquery", 27 | "window.jQuery": "jquery" 28 | }), 29 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 30 | new webpack.HotModuleReplacementPlugin(), 31 | new webpack.NoEmitOnErrorsPlugin(), 32 | new webpack.optimize.CommonsChunkPlugin({ 33 | names: ['vendor', 'manifest'], 34 | }), 35 | // https://github.com/ampedandwired/html-webpack-plugin 36 | new HtmlWebpackPlugin({ 37 | filename: 'index.html', 38 | template: 'index.html', 39 | inject: true 40 | }), 41 | new FriendlyErrorsPlugin() 42 | ] 43 | }) 44 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var CopyWebpackPlugin = require('copy-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 10 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 11 | 12 | var env = config.build.env 13 | 14 | var webpackConfig = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ 17 | sourceMap: config.build.productionSourceMap, 18 | extract: true 19 | }) 20 | }, 21 | devtool: config.build.productionSourceMap ? '#source-map' : false, 22 | output: { 23 | path: config.build.assetsRoot, 24 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 25 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'), 26 | // path仅仅告诉Webpack结果存储在哪里,然而publicPath项则被许多Webpack的插件用于在生产模式下更新内嵌到css、html文件里的url值。 27 | publicPath: config.build.assetsPublicPath 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }),new webpack.ProvidePlugin({ 34 | $: "jquery", 35 | jQuery: "jquery", 36 | "window.jQuery": "jquery" 37 | }), 38 | // new webpack.optimize.UglifyJsPlugin({ 39 | // compress: { 40 | // warnings: false 41 | // }, 42 | // sourceMap: true 43 | // }), 44 | // extract css into its own file 45 | new ExtractTextPlugin({ 46 | filename: utils.assetsPath('css/[name].[hash:7].css') 47 | }), 48 | // Compress extracted CSS. We are using this plugin so that possible 49 | // duplicated CSS from different components can be deduped. 50 | new OptimizeCSSPlugin(), 51 | // generate dist index.html with correct asset hash for caching. 52 | // you can customize output by editing /index.html 53 | // see https://github.com/ampedandwired/html-webpack-plugin 54 | new HtmlWebpackPlugin({ 55 | filename: config.build.index, 56 | template: 'index.html', 57 | inject: true, 58 | minify: { 59 | removeComments: true, 60 | collapseWhitespace: true, 61 | removeAttributeQuotes: true 62 | // more options: 63 | // https://github.com/kangax/html-minifier#options-quick-reference 64 | }, 65 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 66 | chunksSortMode: 'dependency' 67 | }), 68 | // split vendor js into its own file 69 | new webpack.optimize.CommonsChunkPlugin({ 70 | name: 'vendor', 71 | minChunks: function (module, count) { 72 | // any required modules inside node_modules are extracted to vendor 73 | return ( 74 | module.resource && 75 | /\.js$/.test(module.resource) && 76 | module.resource.indexOf( 77 | path.join(__dirname, '../node_modules') 78 | ) === 0 79 | ) 80 | } 81 | }), 82 | // extract webpack runtime and module manifest to its own file in order to 83 | // prevent vendor hash from being updated whenever app bundle is updated 84 | new webpack.optimize.CommonsChunkPlugin({ 85 | name: 'manifest', 86 | chunks: ['vendor'] 87 | }), 88 | // copy custom static assets 89 | new CopyWebpackPlugin([ 90 | { 91 | from: path.resolve(__dirname, '../static'), 92 | to: config.build.assetsSubDirectory, 93 | ignore: ['.*'] 94 | } 95 | ]) 96 | ] 97 | }) 98 | 99 | if (config.build.productionGzip) { 100 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 101 | 102 | webpackConfig.plugins.push( 103 | new CompressionWebpackPlugin({ 104 | asset: '[path].gz[query]', 105 | algorithm: 'gzip', 106 | test: new RegExp( 107 | '\\.(' + 108 | config.build.productionGzipExtensions.join('|') + 109 | ')$' 110 | ), 111 | threshold: 10240, 112 | minRatio: 0.8 113 | }) 114 | ) 115 | } 116 | 117 | if (config.build.bundleAnalyzerReport) { 118 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 119 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 120 | } 121 | 122 | module.exports = webpackConfig 123 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | // assetsPublicPath: '/', 11 | assetsPublicPath: '/Vue-Admin/', 12 | productionSourceMap: true, 13 | // Gzip off by default as many popular static hosts such as 14 | // Surge or Netlify already gzip all static assets for you. 15 | // Before setting to `true`, make sure to: 16 | // npm install --save-dev compression-webpack-plugin 17 | productionGzip: false, 18 | productionGzipExtensions: ['js', 'css'], 19 | // Run the build command with an extra argument to 20 | // View the bundle analyzer report after build finishes: 21 | // `npm run build --report` 22 | // Set to `true` or `false` to always turn it on or off 23 | bundleAnalyzerReport: process.env.npm_config_report 24 | }, 25 | dev: { 26 | env: require('./dev.env'), 27 | port: 9000, 28 | autoOpenBrowser: false, 29 | assetsSubDirectory: 'static', 30 | assetsPublicPath: '/', 31 | proxyTable: { 32 | // http://localhost:9000/api/menuList => http://localhost:3000/menuList 33 | '/api': { 34 | target: 'http://127.0.0.1:3000', 35 | changeOrigin: true, 36 | pathRewrite: { 37 | '^/api' : '', // rewrite path 38 | }, 39 | } 40 | }, 41 | // CSS Sourcemaps off by default because relative paths are "buggy" 42 | // with this option, according to the CSS-Loader README 43 | // (https://github.com/webpack/css-loader#sourcemaps) 44 | // In our experience, they generally work as expected, 45 | // just be aware of this issue when enabling this option. 46 | cssSourceMap: false 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue-Admin-Demo 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /mock.js: -------------------------------------------------------------------------------- 1 | const mock = {} 2 | require('fs').readdirSync(require('path').join(`${__dirname}/src/mock`)).forEach((file) => { 3 | Object.assign(mock, require(`./src/mock/${file}`)) 4 | }) 5 | 6 | module.exports = mock 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-admin-demo", 3 | "version": "1.0.0", 4 | "description": "vue admin demo project", 5 | "author": "Lanux", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "lint": "eslint --ext .js,.vue src", 11 | "mock": "babel-node build/mock-server.js --presets es2015,stage-0", 12 | "mockdev": "npm run dev & npm run mock" 13 | }, 14 | "dependencies": { 15 | "animate.css": "3.5.2", 16 | "axios": "^0.16.2", 17 | "babel-polyfill": "^6.26.0", 18 | "echarts": "^3.5.1", 19 | "element-ui": "^1.4.8", 20 | "font-awesome": "^4.7.0", 21 | "vue": "^2.4.2", 22 | "vue-core-image-upload": "^2.3.9", 23 | "vue-fancybox": "^1.0.2", 24 | "vue-image-crop-upload": "^2.0.3", 25 | "vue-progressbar": "^0.7.3", 26 | "vue-router": "^2.7.0", 27 | "vuex": "^2.4.0", 28 | "vuex-router-sync": "^4.3.0" 29 | }, 30 | "devDependencies": { 31 | "autoprefixer": "^7.1.3", 32 | "babel-cli": "^6.26.0", 33 | "babel-core": "^6.26.0", 34 | "babel-eslint": "^7.1.1", 35 | "babel-helper-vue-jsx-merge-props": "^2.0.2", 36 | "babel-loader": "^7.1.2", 37 | "babel-plugin-component": "^0.10.0", 38 | "babel-plugin-syntax-jsx": "^6.18.0", 39 | "babel-plugin-transform-runtime": "^6.22.0", 40 | "babel-plugin-transform-vue-jsx": "^3.5.0", 41 | "babel-polyfill": "^6.26.0", 42 | "babel-preset-es2015": "^6.24.1", 43 | "babel-preset-latest": "^6.22.0", 44 | "babel-preset-stage-0": "^6.24.1", 45 | "babel-preset-stage-2": "^6.24.1", 46 | "babel-register": "^6.26.0", 47 | "chalk": "^1.1.3", 48 | "connect-history-api-fallback": "^1.3.0", 49 | "copy-webpack-plugin": "^4.0.1", 50 | "css-loader": "^0.28.7", 51 | "errorhandler": "^1.5.0", 52 | "eslint": "^4.6.1", 53 | "eslint-config-standard": "^10.2.1", 54 | "eslint-friendly-formatter": "^3.0.0", 55 | "eslint-loader": "^1.9.0", 56 | "eslint-plugin-html": "^3.2.1", 57 | "eslint-plugin-promise": "^3.4.0", 58 | "eslint-plugin-standard": "^3.0.1", 59 | "eventsource-polyfill": "^0.9.6", 60 | "express": "^4.15.4", 61 | "extract-text-webpack-plugin": "^3.0.0", 62 | "file-loader": "^0.11.2", 63 | "friendly-errors-webpack-plugin": "^1.1.3", 64 | "function-bind": "^1.1.1", 65 | "html-webpack-plugin": "^2.30.1", 66 | "http-proxy-middleware": "^0.17.3", 67 | "json-server": "^0.12.0", 68 | "mockjs": "^1.0.1-beta3", 69 | "opn": "^4.0.2", 70 | "optimize-css-assets-webpack-plugin": "^3.1.1", 71 | "ora": "^1.3.0", 72 | "postcss": "^6.0.10", 73 | "postcss-loader": "^2.0.6", 74 | "rimraf": "^2.6.0", 75 | "semver": "^5.4.1", 76 | "style-loader": "^0.18.2", 77 | "url-loader": "^0.5.9", 78 | "vue-loader": "^13.0.4", 79 | "vue-style-loader": "^3.0.1", 80 | "vue-template-compiler": "^2.4.2", 81 | "webpack": "^3.5.5", 82 | "webpack-bundle-analyzer": "^2.9.0", 83 | "webpack-dev-middleware": "^1.12.0", 84 | "webpack-hot-middleware": "^2.18.2", 85 | "webpack-merge": "^4.1.0" 86 | }, 87 | "engines": { 88 | "node": ">= 4.0.0", 89 | "npm": ">= 3.0.0" 90 | }, 91 | "browserslist": [ 92 | "> 1%", 93 | "last 2 versions", 94 | "not ie <= 8" 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 122 | 123 | 171 | -------------------------------------------------------------------------------- /src/api.js: -------------------------------------------------------------------------------- 1 | // export const CONTEXT = './api'; 2 | export const CONTEXT = './Vue-Admin'; 3 | 4 | export const LOGIN = CONTEXT + '/login'; 5 | export const LOGOUT = CONTEXT + '/logout'; 6 | export const CHANGE_PWD = CONTEXT + '/changePwd'; 7 | 8 | export const SYS_MENU_GET = CONTEXT + '/sys/menu/get'; 9 | export const SYS_MENU_UPDATE = CONTEXT + '/sys/menu/update'; 10 | export const SYS_MENU_DELETE = CONTEXT + '/sys/menu/delete'; 11 | export const SYS_MENU_ADD = CONTEXT + '/sys/menu/add'; 12 | export const SYS_MENU_PAGE = CONTEXT + '/sys/menu/page'; 13 | export const SYS_MENU_LIST = CONTEXT + '/sys/menu/list'; 14 | export const SYS_MENU_LIST2 = CONTEXT + '/sys/menu/list2'; 15 | 16 | export const SYS_ROLE_GET = CONTEXT + '/sys/role/get'; 17 | export const SYS_ROLE_UPDATE = CONTEXT + '/sys/role/update'; 18 | export const SYS_ROLE_DELETE = CONTEXT + '/sys/role/delete'; 19 | export const SYS_ROLE_ADD = CONTEXT + '/sys/role/add'; 20 | export const SYS_ROLE_PAGE = CONTEXT + '/sys/role/page'; 21 | export const SYS_ROLE_LIST = CONTEXT + '/sys/role/list'; 22 | export const SYS_ROLE_LIST2 = CONTEXT + '/sys/role/list2'; 23 | export const SYS_ROLE_RESOURCE = CONTEXT + '/sys/role/resources'; 24 | export const SYS_SET_ROLE_RESOURCE = CONTEXT + '/sys/role/setResources'; 25 | 26 | export const SYS_RESOURCE_GET = CONTEXT + '/sys/resource/get'; 27 | export const SYS_RESOURCE_UPDATE = CONTEXT + '/sys/resource/update'; 28 | export const SYS_RESOURCE_DELETE = CONTEXT + '/sys/resource/delete'; 29 | export const SYS_RESOURCE_ADD = CONTEXT + '/sys/resource/add'; 30 | export const SYS_RESOURCE_PAGE = CONTEXT + '/sys/resource/page'; 31 | export const SYS_RESOURCE_LIST = CONTEXT + '/sys/resource/list'; 32 | export const SYS_RESOURCE_LIST2 = CONTEXT + '/sys/resource/list2'; 33 | 34 | export const SYS_USER_GET = CONTEXT + '/sys/user/get'; 35 | export const SYS_USER_ADD = CONTEXT + '/sys/user/add'; 36 | export const SYS_USER_UPDATE = CONTEXT + '/sys/user/update'; 37 | export const SYS_USER_DELETE = CONTEXT + '/sys/user/delete'; 38 | export const SYS_USER_PAGE = CONTEXT + '/sys/user/page'; 39 | export const SYS_USER_ROLE = CONTEXT + '/sys/user/roleIds'; 40 | export const SYS_SET_USER_ROLE = CONTEXT + '/sys/user/setRoles'; 41 | 42 | export const MSG_TOP_TEN = CONTEXT + '/messageList'; 43 | export const TEST_DATA = CONTEXT + '/static/data/data.json'; 44 | 45 | -------------------------------------------------------------------------------- /src/common/auth.js: -------------------------------------------------------------------------------- 1 | export default { 2 | randomString:function(len,radix){ 3 | var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 4 | var chars = CHARS, uuid = [], i; 5 | radix = radix || chars.length; 6 | 7 | if (len) { 8 | // Compact form 9 | for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix]; 10 | } else { 11 | // rfc4122, version 4 form 12 | var r; 13 | 14 | // rfc4122 requires these characters 15 | uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; 16 | uuid[14] = '4'; 17 | 18 | // Fill in random data. At i==19 set the high bits of clock sequence as 19 | // per rfc4122, sec. 4.1.5 20 | for (i = 0; i < 36; i++) { 21 | if (!uuid[i]) { 22 | r = 0 | Math.random()*16; 23 | uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; 24 | } 25 | } 26 | } 27 | 28 | return uuid.join(''); 29 | }, 30 | getUid:function(){ 31 | var uid = window.localStorage.getItem('imp-uuid'); 32 | if (!uid) { 33 | uid = this.randomString(32); 34 | window.localStorage.setItem('imp-uuid',uid); 35 | } 36 | return uid; 37 | }, 38 | getSid:function(){ 39 | var sid = window.localStorage.getItem('imp-sid'); 40 | if(!!sid){ 41 | return sid; 42 | } 43 | return ''; 44 | }, 45 | login (token, callback) { 46 | window.localStorage.setItem('imp-sid',token); 47 | if (callback) callback(); 48 | }, 49 | 50 | getToken () { 51 | return window.localStorage.getItem('imp-sid'); 52 | }, 53 | 54 | logout (cb) { 55 | window.localStorage.removeItem('imp-sid'); 56 | if (cb) cb() 57 | }, 58 | 59 | loggedIn () { 60 | return !!window.localStorage.getItem('imp-sid'); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/common/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import qs from "qs"; 3 | import auth from "./auth"; 4 | import { getBaseUrl } from "../common/utils"; 5 | import { MessageBox } from "element-ui"; 6 | 7 | // axios 配置 8 | axios.defaults.timeout = 5000; 9 | //axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; 10 | //axios.defaults.baseURL = 'http://localhost:8008'; 11 | axios.defaults.baseURL = getBaseUrl(window.location.href); 12 | axios.defaults.headers.common[ 'authUid' ] = auth.getUid(); 13 | axios.defaults.headers.common[ 'authSid' ] = auth.getSid(); 14 | 15 | //POST传参序列化 16 | axios.interceptors.request.use((config) => { 17 | if (config.method === 'post') { 18 | config.data = qs.stringify(config.data); 19 | } 20 | return config; 21 | }, (error) => { 22 | return Promise.reject(error); 23 | }); 24 | 25 | //返回状态判断 26 | axios.interceptors.response.use( 27 | response => { 28 | if (response.data && response.data.code) { 29 | if (response.data.code === '2001') { 30 | auth.logout() 31 | } 32 | } 33 | return response; 34 | }, 35 | error => { 36 | if (error.response) { 37 | //全局ajax错误信息提示 38 | //MessageBox({type:"error",message:error.response.data,title:"温馨提示",}); 39 | } 40 | //return Promise.reject(error); 41 | }); 42 | 43 | export function fetch (url, config = { method: 'get' }) { 44 | return axios.request({ ...config, url }) 45 | // return new Promise((resolve, reject) => { 46 | // axios.request({ ...config, url }) 47 | // .then(response => { 48 | // resolve(response.data); 49 | // }, err => { 50 | // reject(err); 51 | // }) 52 | // .catch((error) => { 53 | // reject(error) 54 | // }) 55 | // }) 56 | } 57 | 58 | export default axios 59 | -------------------------------------------------------------------------------- /src/common/utils.js: -------------------------------------------------------------------------------- 1 | import pathToRegexp from "path-to-regexp"; 2 | 3 | export const getSessionKey = (key, defaultValue) => { 4 | const item = window.sessionStorage.getItem(key); 5 | if (item == undefined && defaultValue != undefined) { 6 | return defaultValue 7 | } 8 | return item; 9 | } 10 | 11 | export const getBaseUrl = (url) => { 12 | var reg = /^((\w+):\/\/([^\/:]*)(?::(\d+))?)(.*)/; 13 | reg.exec(url); 14 | return RegExp.$1; 15 | } 16 | 17 | export const keyMirror = (obj) => { 18 | let key 19 | let mirrored = {} 20 | if (obj && typeof obj === 'object') { 21 | for (key in obj) { 22 | if ({}.hasOwnProperty.call(obj, key)) { 23 | mirrored[ key ] = key 24 | } 25 | } 26 | } 27 | return mirrored 28 | } 29 | 30 | /** 31 | * 数组格式转树状结构 32 | * @param {array} array 33 | * @param {String} id 34 | * @param {String} pid 35 | * @param {String} children 36 | * @return {Array} 37 | */ 38 | export const arrayToTree = (array, id = 'id', pid = 'pid', children = 'children') => { 39 | let data = array.map(item => ({ ...item })) 40 | let result = [] 41 | let hash = {} 42 | data.forEach((item, index) => { 43 | hash[ data[ index ][ id ] ] = data[ index ] 44 | }) 45 | 46 | data.forEach((item) => { 47 | let hashVP = hash[ item[ pid ] ] 48 | if (hashVP) { 49 | !hashVP[ children ] && (hashVP[ children ] = []) 50 | hashVP[ children ].push(item) 51 | } else { 52 | result.push(item) 53 | } 54 | }) 55 | return result 56 | } 57 | 58 | export function getCurrentMenu (location, arrayMenu) { 59 | if (!!arrayMenu) { 60 | let current = [] 61 | for (let i = 0; i < arrayMenu.length; i++) { 62 | const e = arrayMenu[ i ]; 63 | const child = getCurrentMenu(location, e.children); 64 | if (!!child && child.length > 0) { 65 | child.push({ ...e, children: null }); 66 | return child; 67 | } 68 | if (e.href && pathToRegexp(e.href).exec(location)) { 69 | current.push({ ...e, children: null }); 70 | return current; 71 | } 72 | } 73 | return current; 74 | } 75 | return null; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/components/404.vue: -------------------------------------------------------------------------------- 1 | 13 | 17 | 58 | -------------------------------------------------------------------------------- /src/components/panel.vue: -------------------------------------------------------------------------------- 1 | 17 | 33 | 128 | -------------------------------------------------------------------------------- /src/components/selectTree.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 388 | -------------------------------------------------------------------------------- /src/components/sideMenu.vue: -------------------------------------------------------------------------------- 1 | 26 | 101 | 176 | -------------------------------------------------------------------------------- /src/components/subMenu.vue: -------------------------------------------------------------------------------- 1 | 11 | 25 | 30 | -------------------------------------------------------------------------------- /src/components/treeter.js: -------------------------------------------------------------------------------- 1 | const findFromTree = (treeArray, id, idPropName = "id", childrenPropName = "children") => { 2 | if (!treeArray || treeArray == null || treeArray.length <= 0)return null; 3 | for (var i = 0; i < treeArray.length; i++) { 4 | if (treeArray[i][idPropName] == id) { 5 | return treeArray[i]; 6 | } else { 7 | let result = findFromTree(treeArray[i][childrenPropName], id, idPropName, childrenPropName); 8 | if (result != null) { 9 | return result; 10 | } 11 | } 12 | } 13 | return null; 14 | } 15 | 16 | const appendTreeNode = (treeArray, item, idPropName = "id", parentPropName = "parentId", childrenPropName = "children") => { 17 | if (treeArray == null || treeArray.length <= 0)return; 18 | if (!item[parentPropName] || item[parentPropName] == null) { 19 | let i = treeArray.findIndex(p => p.sort > item.sort); 20 | if (i == -1) { 21 | i = treeArray.length; 22 | } 23 | treeArray.splice(i, 0, item); 24 | return; 25 | } 26 | for (var j = 0; j < treeArray.length; j++) { 27 | var value = treeArray[j]; 28 | if (item[parentPropName] == value[idPropName]) { 29 | if (value[childrenPropName] && value[childrenPropName].length > 0) { 30 | let i = value[childrenPropName].findIndex(p => p.sort > item.sort); 31 | if (i == -1) { 32 | i = value[childrenPropName].length; 33 | } 34 | value[childrenPropName].splice(i, 0, item); 35 | } else { 36 | value[childrenPropName] = []; 37 | value[childrenPropName].push(item); 38 | } 39 | } else { 40 | appendTreeNode(value[childrenPropName], item, idPropName, parentPropName, childrenPropName); 41 | } 42 | } 43 | } 44 | 45 | const deleteFromTree = (list, id, idPropName = "id", childrenPropName = "children") => { 46 | if (!list || list == null || list.length <= 0)return true; 47 | for (var i = 0; i < list.length; i++) { 48 | if (list[i][idPropName] == id) { 49 | list.splice(i, 1); 50 | return true; 51 | } else { 52 | let result = deleteFromTree(list[i][childrenPropName], id, idPropName, childrenPropName); 53 | if (result) { 54 | return result; 55 | } 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | const batchDeleteFromTree = (list, ids, idPropName = "id", childrenPropName = "children") => { 62 | if (!list || list == null || list.length <= 0)return; 63 | if (!ids || ids == null || ids.length <= 0)return; 64 | for (var i = 0; i < list.length; i++) { 65 | if (ids.findIndex(x => x == list[i][idPropName])>-1) { 66 | list.splice(i, 1); 67 | i--; 68 | continue; 69 | } else { 70 | batchDeleteFromTree(list[i][childrenPropName], ids, idPropName, childrenPropName); 71 | } 72 | } 73 | } 74 | 75 | const updateTreeNode = (list, item, idPropName = "id", childrenPropName = "children") => { 76 | if (!list || list == null || list.length <= 0) return false; 77 | for (var i = 0; i < list.length; i++) { 78 | if (list[i][idPropName] == item[idPropName]) { 79 | console.log(list[i][idPropName],item[idPropName]); 80 | list.splice(i, 1, item); 81 | return true; 82 | } else { 83 | let result = updateTreeNode(list[i][childrenPropName], item, idPropName, childrenPropName); 84 | if (result) { 85 | return result; 86 | } 87 | } 88 | } 89 | return false; 90 | } 91 | 92 | export default { 93 | methods: { 94 | findFromTree, 95 | appendTreeNode, 96 | deleteFromTree, 97 | updateTreeNode, 98 | batchDeleteFromTree 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /src/filters/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 去除首尾空格 3 | * @param {[string]} string [字符串] 4 | * @return {[string]} [返回处理后数据] 5 | */ 6 | const trim = (string) => { 7 | return string.toString().replace(); 8 | } 9 | 10 | const subString = (value, length = 10) => { 11 | if (value && value != null && value.length > length) { 12 | return value.substring(0, length) 13 | } 14 | return value; 15 | } 16 | 17 | 18 | export default { 19 | trim, subString 20 | } 21 | -------------------------------------------------------------------------------- /src/frame.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 37 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill' 2 | import Vue from "vue"; 3 | import frame from "./frame.vue"; 4 | import router from "./router"; 5 | import store from "./store"; 6 | import axios from "./common/axios"; 7 | import filters from "./filters"; 8 | import VueProgressBar from "vue-progressbar"; 9 | import Element from "element-ui"; 10 | import 'element-ui/lib/theme-default/index.css'; 11 | import ImpPanel from "./components/panel.vue"; 12 | 13 | Vue.prototype.$http = axios 14 | Vue.axios = axios 15 | Vue.http = axios; 16 | Vue.use(axios); 17 | 18 | Vue.use(Element); 19 | 20 | Vue.component(ImpPanel.name, ImpPanel); 21 | 22 | Vue.use(VueProgressBar, { 23 | color: '#eeeeee', 24 | failedColor: '#874b4b', 25 | thickness: '2px', 26 | transition: { 27 | speed: '0.2s', 28 | opacity: '0.6s' 29 | }, 30 | autoRevert: true, 31 | location: 'top', 32 | inverse: false 33 | }) 34 | 35 | 36 | Object.keys(filters).forEach(key => { 37 | Vue.filter(key, filters[key]) 38 | }) 39 | 40 | new Vue({ 41 | store, 42 | router, 43 | el: "#root", 44 | render: h => h(frame) 45 | }) 46 | -------------------------------------------------------------------------------- /src/mock/common.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs') 2 | 3 | let listData = Mock.mock({ 4 | 'data|10': [ 5 | { 6 | id: '@id', 7 | 'type|0-1': 1, 8 | 'code|101-110': 1, 9 | timeLine: '@datetime("yyyyMMddHH")', 10 | message: '@cparagraph(1, 3)', 11 | title: '@ctitle(8, 18)', 12 | createTime: '@datetime("T")', 13 | senderName: '@last', 14 | senderPic () { 15 | return Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', this.senderName.substr(0, 1)) 16 | }, 17 | }, 18 | ], 19 | }) 20 | 21 | const resourceList = [{"id":52,"parentId":null,"sort":0,"name":"登录","code":"/login","type":3,"usable":"1","remarks":"","children":[]}, 22 | {"id":68,"parentId":null,"sort":0,"name":"仪表盘","code":"/index","type":1,"usable":"1","remarks":"","children":[]}, 23 | {"id":69,"parentId":null,"sort":0,"name":"系统管理","code":"/sys","type":1,"usable":"1","remarks":"","children":[{"id":82,"parentId":69,"sort":0,"name":"资源管理","code":"/sys/resource","type":1,"usable":"1","remarks":"","children":[{"id":99,"parentId":82,"sort":0,"name":"/sys/resource/get","code":"/sys/resource/get","type":3,"usable":"1","remarks":"","children":[]}, 24 | {"id":100,"parentId":82,"sort":0,"name":"/sys/resource/update","code":"/sys/resource/update","type":3,"usable":"1","remarks":"","children":[]}, 25 | {"id":101,"parentId":82,"sort":0,"name":"/sys/resource/delete","code":"/sys/resource/delete","type":3,"usable":"1","remarks":"","children":[]}, 26 | {"id":102,"parentId":82,"sort":0,"name":"/sys/resource/add","code":"/sys/resource/add","type":3,"usable":"1","remarks":"","children":[]}, 27 | {"id":103,"parentId":82,"sort":0,"name":"/sys/resource/page","code":"/sys/resource/page","type":3,"usable":"1","remarks":"","children":[]}, 28 | {"id":104,"parentId":82,"sort":0,"name":"/sys/resource/list","code":"/sys/resource/list","type":3,"usable":"1","remarks":"","children":[]}, 29 | {"id":105,"parentId":82,"sort":0,"name":"/sys/resource/list2","code":"/sys/resource/list2","type":3,"usable":"1","remarks":"","children":[]}]}, 30 | {"id":70,"parentId":69,"sort":1,"name":"菜单管理","code":"/sys/menuList","type":1,"usable":"1","remarks":"","children":[{"id":83,"parentId":70,"sort":0,"name":"/sys/menu/get","code":"/sys/menu/get","type":3,"usable":"1","remarks":"","children":[]}, 31 | {"id":84,"parentId":70,"sort":0,"name":"/sys/menu/update","code":"/sys/menu/update","type":3,"usable":"1","remarks":"","children":[]}, 32 | {"id":85,"parentId":70,"sort":0,"name":"/sys/menu/delete","code":"/sys/menu/delete","type":3,"usable":"1","remarks":"","children":[]}, 33 | {"id":86,"parentId":70,"sort":0,"name":"/sys/menu/add","code":"/sys/menu/add","type":3,"usable":"1","remarks":"","children":[]}, 34 | {"id":87,"parentId":70,"sort":0,"name":"/sys/menu/page","code":"/sys/menu/page","type":3,"usable":"1","remarks":"","children":[]}, 35 | {"id":88,"parentId":70,"sort":0,"name":"/sys/menu/list","code":"/sys/menu/list","type":3,"usable":"1","remarks":"","children":[]}, 36 | {"id":89,"parentId":70,"sort":0,"name":"/sys/menu/list2","code":"/sys/menu/list2","type":3,"usable":"1","remarks":"","children":[]}]}, 37 | {"id":71,"parentId":69,"sort":3,"name":"角色管理","code":"/sys/roleList","type":1,"usable":"1","remarks":"","children":[{"id":90,"parentId":71,"sort":0,"name":"/sys/role/get","code":"/sys/role/get","type":3,"usable":"1","remarks":"","children":[]}, 38 | {"id":91,"parentId":71,"sort":0,"name":"/sys/role/update","code":"/sys/role/update","type":3,"usable":"1","remarks":"","children":[]}, 39 | {"id":92,"parentId":71,"sort":0,"name":"/sys/role/delete","code":"/sys/role/delete","type":3,"usable":"1","remarks":"","children":[]}, 40 | {"id":93,"parentId":71,"sort":0,"name":"/sys/role/add","code":"/sys/role/add","type":3,"usable":"1","remarks":"","children":[]}, 41 | {"id":94,"parentId":71,"sort":0,"name":"/sys/role/page","code":"/sys/role/page","type":3,"usable":"1","remarks":"","children":[]}, 42 | {"id":95,"parentId":71,"sort":0,"name":"/sys/role/list","code":"/sys/role/list","type":3,"usable":"1","remarks":"","children":[]}, 43 | {"id":96,"parentId":71,"sort":0,"name":"/sys/role/list2","code":"/sys/role/list2","type":3,"usable":"1","remarks":"","children":[]}, 44 | {"id":97,"parentId":71,"sort":0,"name":"/sys/role/resources","code":"/sys/role/resources","type":3,"usable":"1","remarks":"","children":[]}, 45 | {"id":98,"parentId":71,"sort":0,"name":"/sys/role/setResources","code":"/sys/role/setResources","type":3,"usable":"1","remarks":"","children":[]}]}, 46 | {"id":72,"parentId":69,"sort":6,"name":"用户管理","code":"/sys/userList","type":1,"usable":"1","remarks":"","children":[{"id":106,"parentId":72,"sort":0,"name":"/sys/user/get","code":"/sys/user/get","type":3,"usable":"1","remarks":"","children":[]}, 47 | {"id":107,"parentId":72,"sort":0,"name":"/sys/user/add","code":"/sys/user/add","type":3,"usable":"1","remarks":"","children":[]}, 48 | {"id":108,"parentId":72,"sort":0,"name":"/sys/user/update","code":"/sys/user/update","type":3,"usable":"1","remarks":"","children":[]}, 49 | {"id":109,"parentId":72,"sort":0,"name":"/sys/user/delete","code":"/sys/user/delete","type":3,"usable":"1","remarks":"","children":[]}, 50 | {"id":110,"parentId":72,"sort":0,"name":"/sys/user/page","code":"/sys/user/page","type":3,"usable":"1","remarks":"","children":[]}, 51 | {"id":111,"parentId":72,"sort":0,"name":"/sys/user/roleIds","code":"/sys/user/roleIds","type":3,"usable":"1","remarks":"","children":[]}, 52 | {"id":112,"parentId":72,"sort":0,"name":"/sys/user/setRoles","code":"/sys/user/setRoles","type":3,"usable":"1","remarks":"","children":[]}]}]}] 53 | 54 | const menuList = [ 55 | {"id":1,"parentId":null,"sort":0,"name":"仪表盘","href":"/index","icon":"fa fa-dashboard","children":[], 56 | "isShow":"1"}, 57 | {"id":31,"parentId":null,"sort":1,"name":"测试1","href":"/test/1","icon":"fa fa-upload","children": 58 | [ 59 | {"id":92,"parentId":31,"sort":0,"name":"测试1-1","href":"/test/1/1","icon":"fa fa-bank","children":[ 60 | {"id":912,"parentId":92,"sort":0,"name":"测试1-1-1","href":"/test/1/1/1","icon":"fa fa-bank","children":[],"isShow":"1"}, 61 | {"id":913,"parentId":92,"sort":0,"name":"测试1-1-2","href":"/test/1/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"} 62 | ],"isShow":"1"}, 63 | {"id":93,"parentId":31,"sort":0,"name":"测试1-2","href":"/test/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"} 64 | ] 65 | ,"isShow":"1"}, 66 | {"id":102,"parentId":null,"sort":3,"name":"测试2","href":"/test/2","icon":"fa fa-download","children": 67 | [ 68 | {"id":103,"parentId":102,"sort":0,"name":"测试2-1","href":"/test/2/1","icon":"fa fa-image","children":[],"isShow":"1"} 69 | ] 70 | ,"isShow":"1"}, 71 | {"id":6,"parentId":null,"sort":6,"name":"系统管理","href":"/sys","icon":"fa fa-cog","children": 72 | [ 73 | {"id":108,"parentId":6,"sort":0,"name":" 资源管理","href":"/sys/resource","icon":"fa fa-database","children":[],"isShow":"1"}, 74 | {"id":7,"parentId":6,"sort":1,"name":"菜单管理","href":"/sys/menuList","icon":"fa fa-navicon","children":[],"isShow":"1"}, 75 | {"id":8,"parentId":6,"sort":2,"name":"角色管理","href":"/sys/roleList","icon":"fa fa-universal-access","children":[],"isShow":"1"}, 76 | {"id":9,"parentId":6,"sort":3,"name":"用户管理","href":"/sys/userList","icon":"fa fa-user-plus","children":[],"isShow":"1"} 77 | ] 78 | ,"isShow":"1"}] 79 | 80 | const roleList = [ 81 | {"id":26,"delFlag":0,"parentId":null,"sort":0,"name":"超级管理员","enName":"super_manager","usable":"1","remarks":"","children":[]}, 82 | {"id":27,"delFlag":0,"parentId":null,"sort":1,"name":"客服主管","enName":"server_manager","usable":"1","remarks":"","children":[ 83 | {"id":28,"delFlag":0,"parentId":27,"sort":0,"name":"售后客服","enName":"server1","usable":"1","remarks":"","children":[]}, 84 | {"id":29,"delFlag":0,"parentId":27,"sort":1,"name":"售前客服","enName":"server2","usable":"1","remarks":"","children":[]} 85 | ]} 86 | ] 87 | 88 | let database = listData.data 89 | 90 | module.exports = { 91 | 'GET /messageList': function (req, res) { 92 | res.status(200).json(database) 93 | }, 94 | 'GET /sys/resource/list':function (req, res) { 95 | res.status(200).json(resourceList) 96 | }, 97 | 'GET /sys/menu/list':function (req, res) { 98 | res.status(200).json(menuList) 99 | }, 100 | 'GET /sys/role/list':function (req, res) { 101 | res.status(200).json(roleList) 102 | }, 103 | } 104 | -------------------------------------------------------------------------------- /src/mock/global.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | 'GET /menus': function (req, res) { 4 | res.status(200).json().end() 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/mock/mock.js: -------------------------------------------------------------------------------- 1 | const mock = {} 2 | require('fs').readdirSync(require('path').join(`${__dirname}`)).filter(p=>`${p}`!=='mock.js').forEach((file) => { 3 | Object.assign(mock, require(`./${file}`)) 4 | }) 5 | 6 | module.exports = mock 7 | -------------------------------------------------------------------------------- /src/mock/user.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs') 2 | import * as api from '../api.js' 3 | 4 | 5 | let usersListData = Mock.mock({ 6 | 'data|80-100': [ 7 | { 8 | id: '@id', 9 | name: '@cname', 10 | nickName: '@last', 11 | phone: /^1[34578]\d{9}$/, 12 | 'age|11-99': 1, 13 | address: '@county(true)', 14 | isMale: '@boolean', 15 | email: '@email', 16 | createTime: '@datetime', 17 | avatar () { 18 | return Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', this.nickName.substr(0, 1)) 19 | }, 20 | delFlag:0, 21 | status:1, 22 | userType:'1', 23 | no: '@id', 24 | remarks: '@cparagraph(1, 3)', 25 | }, 26 | ], 27 | }) 28 | 29 | 30 | const shuffle = function (input) { 31 | for (let i = input.length - 1; i >= 0; i--) { 32 | const randomIndex = Math.floor(Math.random() * (i + 1)) 33 | const itemAtIndex = input[randomIndex] 34 | input[randomIndex] = input[i] 35 | input[i] = itemAtIndex 36 | } 37 | return input 38 | } 39 | 40 | 41 | let database = usersListData.data 42 | 43 | 44 | module.exports = { 45 | userList: shuffle(database), 46 | 'GET /sys/user/page' : function (req, res) { 47 | const { query } = req 48 | let { pageSize, page } = query 49 | pageSize = pageSize || 10 50 | page = page || 1 51 | 52 | let newData = shuffle(database) 53 | 54 | res.status(200).json({ 55 | records: newData.slice((page - 1) * pageSize, page * pageSize), 56 | total: newData.length, 57 | }) 58 | }, 59 | 'POST /login': function (req, res) { 60 | let newData = shuffle(database)[0] 61 | res.status(200).json({ 62 | user:newData,sid:newData.id 63 | }) 64 | }, 65 | 'GET /sys/user/get' : function (req, res) { 66 | const { query } = req 67 | let { id } = query 68 | let newData = database.filter(p=>p.id===id)[0] 69 | res.status(200).json(newData) 70 | }, 71 | } 72 | -------------------------------------------------------------------------------- /src/pages/dashboard.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 193 | 194 | 202 | -------------------------------------------------------------------------------- /src/pages/layout/footer.vue: -------------------------------------------------------------------------------- 1 | 6 | 10 | 23 | -------------------------------------------------------------------------------- /src/pages/layout/header.vue: -------------------------------------------------------------------------------- 1 | 56 | 141 | 345 | -------------------------------------------------------------------------------- /src/pages/layout/index.js: -------------------------------------------------------------------------------- 1 | import footer from "footer.vue"; 2 | import header from "header.vue"; 3 | 4 | export { 5 | footer, 6 | header 7 | } 8 | -------------------------------------------------------------------------------- /src/pages/login.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 93 | 94 | 225 | -------------------------------------------------------------------------------- /src/pages/register.vue: -------------------------------------------------------------------------------- 1 | 30 | · 31 | 131 | 132 | 134 | -------------------------------------------------------------------------------- /src/pages/resetPwd.vue: -------------------------------------------------------------------------------- 1 | 19 | 45 | -------------------------------------------------------------------------------- /src/pages/sys/resource.vue: -------------------------------------------------------------------------------- 1 | 67 | 214 | 215 | 227 | -------------------------------------------------------------------------------- /src/pages/sys/role.vue: -------------------------------------------------------------------------------- 1 | 81 | 244 | 245 | 272 | -------------------------------------------------------------------------------- /src/pages/sys/user.vue: -------------------------------------------------------------------------------- 1 | 117 | 118 | 216 | 222 | -------------------------------------------------------------------------------- /src/pages/sys/userAdd.vue: -------------------------------------------------------------------------------- 1 | 44 | 110 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | import routeConfig from "./routes"; 4 | import {sync} from "vuex-router-sync"; 5 | import store from "../store"; 6 | import types from "../store/mutation-types"; 7 | import auth from "../common/auth"; 8 | 9 | //加载路由中间件 10 | Vue.use(VueRouter) 11 | 12 | //定义路由 13 | const router = new VueRouter({ 14 | routes: routeConfig, 15 | //mode: 'history' 16 | }) 17 | 18 | sync(store, router) 19 | 20 | const {state} = store 21 | 22 | router.beforeEach((route, redirect, next) => { 23 | if (state.device.isMobile && state.sidebar.opened) { 24 | store.commit(types.TOGGLE_SIDEBAR, false) 25 | } 26 | if (!auth.loggedIn() && route.path !== '/login') { 27 | next({ 28 | path: '/login', 29 | query: {redirect: route.fullPath} 30 | }) 31 | } else { 32 | next() 33 | } 34 | }) 35 | 36 | export default router 37 | -------------------------------------------------------------------------------- /src/router/routes.js: -------------------------------------------------------------------------------- 1 | import dashboard from "../pages/dashboard.vue"; 2 | import NotFoundView from "../components/404.vue"; 3 | import menuList from "../pages/sys/menu.vue"; 4 | import role from "../pages/sys/role.vue"; 5 | import resource from "../pages/sys/resource.vue"; 6 | import login from "../pages/login.vue"; 7 | import app from "../App.vue"; 8 | import sysUser from "../pages/sys/user.vue"; 9 | import userAdd from "../pages/sys/userAdd.vue"; 10 | import resetPwd from "../pages/resetPwd.vue"; 11 | // Routes 12 | const routes = [ 13 | {path: '/login', component: login}, 14 | { 15 | path: '/test', component: app, children: [ 16 | {path: '*', component: NotFoundView} 17 | ] 18 | }, 19 | { 20 | path: '', component: app, children: [ 21 | {path: '/resetPwd', component: resetPwd}, 22 | {path: '/index', component: dashboard}, 23 | {path: '/sys/menuList', component: menuList}, 24 | {path: '/sys/roleList', component: role}, 25 | {path: '/sys/userList', component: sysUser}, 26 | {path: '/sys/userAdd', component: userAdd}, 27 | {path: '/sys/resource', component: resource} 28 | ] 29 | }, 30 | {path: '*', component: NotFoundView} 31 | ] 32 | 33 | 34 | export default routes 35 | 36 | -------------------------------------------------------------------------------- /src/services/default.js: -------------------------------------------------------------------------------- 1 | export default { 2 | login:{"user":{"id":"310000198406275362","name":"叶洋","nickName":"Taylor","phone":"14309472560","age":74,"address":"浙江省 绍兴市 上虞市","isMale":false,"email":"w.pdmenv@rwfwadthss.tr","createTime":"1976-08-15 06:37:12","delFlag":0,"status":1,"userType":"1","no":"310000198406275362","remarks":"传方半织意意列业维领细斯样年场不次。样影此么论重示般会际开出二及西高。","avatar":"static/img/user.png"},"sid":"310000198406275362"}, 3 | msgList:[{"id":"310000201511210936","type":1,"code":102,"timeLine":"1975051514","message":"元派目想铁难而应才院色种离。义两作期复铁节被制等头设。此能论装受我电局代算素业用我。","title":"除口方增常处装公会深此面","createTime":"1192729032451","senderName":"Smith","senderPic":"http://dummyimage.com/100x100/d9f279/757575.png&text=S"},{"id":"460000201611256678","type":0,"code":108,"timeLine":"1972022907","message":"门可太长消题四义人素分天习。","title":"车主精论状第算整京联科出报","createTime":"1019549821001","senderName":"Anderson","senderPic":"http://dummyimage.com/100x100/e779f2/757575.png&text=A"},{"id":"21000019780808275X","type":1,"code":105,"timeLine":"1970031803","message":"指给西着林为计着布同细认产。","title":"正白要外高情总儿才必响","createTime":"503250769103","senderName":"Clark","senderPic":"http://dummyimage.com/100x100/79f2c4/757575.png&text=C"},{"id":"540000197505267710","type":1,"code":106,"timeLine":"2010020800","message":"变没装调标矿劳土类角九至由。特引南素都则次采特分义管装设青工率新。海者快决角定标门段越美流东厂体。","title":"马争有战采圆还使层极口队理任目器万干","createTime":"1282562311030","senderName":"Anderson","senderPic":"http://dummyimage.com/100x100/f2a179/757575.png&text=A"},{"id":"120000201607082136","type":0,"code":110,"timeLine":"1995042315","message":"议价进则族外代水白深白离系。质体们劳确作水今领议圆个中处每容江。","title":"看变易精最领得都","createTime":"557022187618","senderName":"Martinez","senderPic":"http://dummyimage.com/100x100/7d79f2/757575.png&text=M"},{"id":"310000199103172213","type":1,"code":107,"timeLine":"1993081322","message":"和油得离接装小都空看来响资。部算调法土图毛重知参时图改用化龙观地。","title":"史运美很且应部想器发此精","createTime":"331067892810","senderName":"Hernandez","senderPic":"http://dummyimage.com/100x100/97f279/757575.png&text=H"},{"id":"310000201408208918","type":0,"code":107,"timeLine":"1996071523","message":"影将度更调图界实交接外他度龙习。米战走加系区日委也总图日。","title":"高按我发史社就高水复周","createTime":"1115948146226","senderName":"Robinson","senderPic":"http://dummyimage.com/100x100/f279bb/757575.png&text=R"},{"id":"500000200504263440","type":0,"code":101,"timeLine":"1972032318","message":"都八在取音特业划克天造求照般。","title":"整家水山又知整新便分现物精划放干","createTime":"1241409165029","senderName":"Clark","senderPic":"http://dummyimage.com/100x100/79def2/757575.png&text=C"},{"id":"320000198908103896","type":1,"code":105,"timeLine":"2009010906","message":"当式名厂采物且计料三公切点应更民体。内反温干华点方上等或划消但名反到准。","title":"况别联东红后还由列级任法向","createTime":"138005376045","senderName":"Walker","senderPic":"http://dummyimage.com/100x100/f2e279/757575.png&text=W"},{"id":"330000199709134661","type":0,"code":102,"timeLine":"2007031214","message":"都种形一必采海想元的调次位府团系。社界个向但所历亲器它争计积相所为记。适心称备叫近理或种使水算党须今划文。","title":"酸约况实改火间子直后约质影反","createTime":"434811164417","senderName":"Thompson","senderPic":"http://dummyimage.com/100x100/bf79f2/757575.png&text=T"}], 4 | roleList:[{"id":26,"delFlag":0,"parentId":null,"sort":0,"name":"超级管理员","enName":"super_manager","usable":"1","remarks":"","children":[]},{"id":27,"delFlag":0,"parentId":null,"sort":1,"name":"客服主管","enName":"server_manager","usable":"1","remarks":"","children":[{"id":28,"delFlag":0,"parentId":27,"sort":0,"name":"售后客服","enName":"server1","usable":"1","remarks":"","children":[]},{"id":29,"delFlag":0,"parentId":27,"sort":1,"name":"售前客服","enName":"server2","usable":"1","remarks":"","children":[]}]}], 5 | userList:{records: [{"id":"340000198910193425","name":"曹明","nickName":"Hall","phone":"15692311412","age":88,"address":"湖南省 娄底市 双峰县","isMale":false,"email":"c.czieispd@cwp.gov.cn","createTime":"1978-05-22 08:53:07","delFlag":0,"status":1,"userType":"1","no":"340000198910193425","remarks":"近火就把政通增电加能开比没现过对办部。对率大元这证起速构感型众决王每状使。取力近标子组毛济料构论美业。","avatar":"http://dummyimage.com/100x100/79f28a/757575.png&text=H"},{"id":"350000201505204609","name":"田磊","nickName":"Young","phone":"15712309986","age":71,"address":"湖北省 随州市 随县","isMale":true,"email":"h.xmhalr@tswxut.ba","createTime":"2008-05-09 22:47:14","delFlag":0,"status":1,"userType":"1","no":"350000201505204609","remarks":"作又整只与关法期快口广信认东我比家。克用和科土江族住几起提因体将。","avatar":"http://dummyimage.com/100x100/79d1f2/757575.png&text=Y"},{"id":"630000198302122489","name":"顾霞","nickName":"Clark","phone":"14468417672","age":52,"address":"贵州省 黔东南苗族侗族自治州 岑巩县","isMale":true,"email":"h.bwzpy@lwlv.lt","createTime":"1978-09-18 16:05:12","delFlag":0,"status":1,"userType":"1","no":"630000198302122489","remarks":"共图务低义间需图加思较极用。理干该认值段或那门动位风义机产。带象商领党系千单证用水可保水今近细。","avatar":"http://dummyimage.com/100x100/8e79f2/757575.png&text=C"},{"id":"120000198201065745","name":"汤杰","nickName":"Brown","phone":"14817334423","age":38,"address":"天津 天津市 武清区","isMale":true,"email":"y.kxies@rrkf.do","createTime":"1970-09-25 13:39:05","delFlag":0,"status":1,"userType":"1","no":"120000198201065745","remarks":"维重常军规种可真入千组部方程红平水。按四很青水合道数以及铁集路上商。","avatar":"http://dummyimage.com/100x100/7986f2/757575.png&text=B"},{"id":"440000200412284520","name":"江涛","nickName":"Lee","phone":"14481283062","age":13,"address":"陕西省 渭南市 白水县","isMale":true,"email":"c.ukigvuno@kwfk.bt","createTime":"2008-08-13 02:57:58","delFlag":0,"status":1,"userType":"1","no":"440000200412284520","remarks":"济么形细难今上观难上设水民史。进又十西报成养时求并发者向。近火料新产回造统加正则教管到所别。","avatar":"http://dummyimage.com/100x100/79e6f2/757575.png&text=L"},{"id":"440000201502214088","name":"曾桂英","nickName":"Allen","phone":"15501677076","age":68,"address":"黑龙江省 齐齐哈尔市 梅里斯达斡尔族区","isMale":true,"email":"g.qaioxl@ffhpyfvnn.bn","createTime":"2000-05-24 08:08:42","delFlag":0,"status":1,"userType":"1","no":"440000201502214088","remarks":"口什采它六委市切门型部感前强子。真部最率体一程基入族外品。","avatar":"http://dummyimage.com/100x100/f2e979/757575.png&text=A"},{"id":"440000198106296849","name":"高霞","nickName":"Wilson","phone":"14488966580","age":82,"address":"新疆维吾尔自治区 昌吉回族自治州 奇台县","isMale":false,"email":"o.spamgt@nnbdwoaw.ad","createTime":"1977-01-26 04:18:22","delFlag":0,"status":1,"userType":"1","no":"440000198106296849","remarks":"以美理更管它存量种通不派车名然江。它已文道道百其百军达和知色。","avatar":"http://dummyimage.com/100x100/79e0f2/757575.png&text=W"},{"id":"640000200202182849","name":"顾平","nickName":"Rodriguez","phone":"14766033445","age":96,"address":"香港特别行政区 新界 离岛区","isMale":false,"email":"r.octrublxo@njk.kz","createTime":"1985-10-17 04:53:21","delFlag":0,"status":1,"userType":"1","no":"640000200202182849","remarks":"品持些示调般其需走你气切到热采工土。回响四立干百史号同特实子确又消已。","avatar":"http://dummyimage.com/100x100/8af279/757575.png&text=R"},{"id":"230000200802175187","name":"陈洋","nickName":"Garcia","phone":"15288638355","age":90,"address":"江西省 九江市 彭泽县","isMale":true,"email":"j.fumo@fcrx.dk","createTime":"2013-05-07 00:53:32","delFlag":0,"status":1,"userType":"1","no":"230000200802175187","remarks":"总其许他年矿率本根参变世。低南育体眼派万精长并车响料战。","avatar":"http://dummyimage.com/100x100/79f2cb/757575.png&text=G"},{"id":"610000200403119453","name":"范敏","nickName":"Brown","phone":"15178636234","age":80,"address":"海南省 三亚市 -","isMale":true,"email":"k.jbvimbagi@diwsihdqxx.dz","createTime":"1993-04-10 17:15:50","delFlag":0,"status":1,"userType":"1","no":"610000200403119453","remarks":"米界价区质需类边被自则按。江期合行色离接身准连工个称大说应目。称较号重生者素求几那开标算包属。","avatar":"http://dummyimage.com/100x100/79f2c2/757575.png&text=B"}],total:99}, 6 | menuList:[{"id":1,"parentId":null,"sort":0,"name":"仪表盘","href":"/index","icon":"fa fa-dashboard","children":[],"isShow":"1"},{"id":31,"parentId":null,"sort":1,"name":"测试1","href":"/test/1","icon":"fa fa-upload","children":[{"id":92,"parentId":31,"sort":0,"name":"测试1-1","href":"/test/1/1","icon":"fa fa-bank","children":[{"id":912,"parentId":92,"sort":0,"name":"测试1-1-1","href":"/test/1/1/1","icon":"fa fa-bank","children":[],"isShow":"1"},{"id":913,"parentId":92,"sort":0,"name":"测试1-1-2","href":"/test/1/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"}],"isShow":"1"},{"id":93,"parentId":31,"sort":0,"name":"测试1-2","href":"/test/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"}],"isShow":"1"},{"id":102,"parentId":null,"sort":3,"name":"测试2","href":"/test/2","icon":"fa fa-download","children":[{"id":103,"parentId":102,"sort":0,"name":"测试2-1","href":"/test/2/1","icon":"fa fa-image","children":[],"isShow":"1"}],"isShow":"1"},{"id":6,"parentId":null,"sort":6,"name":"系统管理","href":"/sys","icon":"fa fa-cog","children":[{"id":108,"parentId":6,"sort":0,"name":" 资源管理","href":"/sys/resource","icon":"fa fa-database","children":[],"isShow":"1"},{"id":7,"parentId":6,"sort":1,"name":"菜单管理","href":"/sys/menuList","icon":"fa fa-navicon","children":[],"isShow":"1"},{"id":8,"parentId":6,"sort":2,"name":"角色管理","href":"/sys/roleList","icon":"fa fa-universal-access","children":[],"isShow":"1"},{"id":9,"parentId":6,"sort":3,"name":"用户管理","href":"/sys/userList","icon":"fa fa-user-plus","children":[],"isShow":"1"}],"isShow":"1"}], 7 | resource:[{"id":52,"parentId":null,"sort":0,"name":"登录","code":"/login","type":3,"usable":"1","remarks":"","children":[]},{"id":68,"parentId":null,"sort":0,"name":"仪表盘","code":"/index","type":1,"usable":"1","remarks":"","children":[]},{"id":69,"parentId":null,"sort":0,"name":"系统管理","code":"/sys","type":1,"usable":"1","remarks":"","children":[{"id":82,"parentId":69,"sort":0,"name":"资源管理","code":"/sys/resource","type":1,"usable":"1","remarks":"","children":[{"id":99,"parentId":82,"sort":0,"name":"/sys/resource/get","code":"/sys/resource/get","type":3,"usable":"1","remarks":"","children":[]},{"id":100,"parentId":82,"sort":0,"name":"/sys/resource/update","code":"/sys/resource/update","type":3,"usable":"1","remarks":"","children":[]},{"id":101,"parentId":82,"sort":0,"name":"/sys/resource/delete","code":"/sys/resource/delete","type":3,"usable":"1","remarks":"","children":[]},{"id":102,"parentId":82,"sort":0,"name":"/sys/resource/add","code":"/sys/resource/add","type":3,"usable":"1","remarks":"","children":[]},{"id":103,"parentId":82,"sort":0,"name":"/sys/resource/page","code":"/sys/resource/page","type":3,"usable":"1","remarks":"","children":[]},{"id":104,"parentId":82,"sort":0,"name":"/sys/resource/list","code":"/sys/resource/list","type":3,"usable":"1","remarks":"","children":[]},{"id":105,"parentId":82,"sort":0,"name":"/sys/resource/list2","code":"/sys/resource/list2","type":3,"usable":"1","remarks":"","children":[]}]},{"id":70,"parentId":69,"sort":1,"name":"菜单管理","code":"/sys/menuList","type":1,"usable":"1","remarks":"","children":[{"id":83,"parentId":70,"sort":0,"name":"/sys/menu/get","code":"/sys/menu/get","type":3,"usable":"1","remarks":"","children":[]},{"id":84,"parentId":70,"sort":0,"name":"/sys/menu/update","code":"/sys/menu/update","type":3,"usable":"1","remarks":"","children":[]},{"id":85,"parentId":70,"sort":0,"name":"/sys/menu/delete","code":"/sys/menu/delete","type":3,"usable":"1","remarks":"","children":[]},{"id":86,"parentId":70,"sort":0,"name":"/sys/menu/add","code":"/sys/menu/add","type":3,"usable":"1","remarks":"","children":[]},{"id":87,"parentId":70,"sort":0,"name":"/sys/menu/page","code":"/sys/menu/page","type":3,"usable":"1","remarks":"","children":[]},{"id":88,"parentId":70,"sort":0,"name":"/sys/menu/list","code":"/sys/menu/list","type":3,"usable":"1","remarks":"","children":[]},{"id":89,"parentId":70,"sort":0,"name":"/sys/menu/list2","code":"/sys/menu/list2","type":3,"usable":"1","remarks":"","children":[]}]},{"id":71,"parentId":69,"sort":3,"name":"角色管理","code":"/sys/roleList","type":1,"usable":"1","remarks":"","children":[{"id":90,"parentId":71,"sort":0,"name":"/sys/role/get","code":"/sys/role/get","type":3,"usable":"1","remarks":"","children":[]},{"id":91,"parentId":71,"sort":0,"name":"/sys/role/update","code":"/sys/role/update","type":3,"usable":"1","remarks":"","children":[]},{"id":92,"parentId":71,"sort":0,"name":"/sys/role/delete","code":"/sys/role/delete","type":3,"usable":"1","remarks":"","children":[]},{"id":93,"parentId":71,"sort":0,"name":"/sys/role/add","code":"/sys/role/add","type":3,"usable":"1","remarks":"","children":[]},{"id":94,"parentId":71,"sort":0,"name":"/sys/role/page","code":"/sys/role/page","type":3,"usable":"1","remarks":"","children":[]},{"id":95,"parentId":71,"sort":0,"name":"/sys/role/list","code":"/sys/role/list","type":3,"usable":"1","remarks":"","children":[]},{"id":96,"parentId":71,"sort":0,"name":"/sys/role/list2","code":"/sys/role/list2","type":3,"usable":"1","remarks":"","children":[]},{"id":97,"parentId":71,"sort":0,"name":"/sys/role/resources","code":"/sys/role/resources","type":3,"usable":"1","remarks":"","children":[]},{"id":98,"parentId":71,"sort":0,"name":"/sys/role/setResources","code":"/sys/role/setResources","type":3,"usable":"1","remarks":"","children":[]}]},{"id":72,"parentId":69,"sort":6,"name":"用户管理","code":"/sys/userList","type":1,"usable":"1","remarks":"","children":[{"id":106,"parentId":72,"sort":0,"name":"/sys/user/get","code":"/sys/user/get","type":3,"usable":"1","remarks":"","children":[]},{"id":107,"parentId":72,"sort":0,"name":"/sys/user/add","code":"/sys/user/add","type":3,"usable":"1","remarks":"","children":[]},{"id":108,"parentId":72,"sort":0,"name":"/sys/user/update","code":"/sys/user/update","type":3,"usable":"1","remarks":"","children":[]},{"id":109,"parentId":72,"sort":0,"name":"/sys/user/delete","code":"/sys/user/delete","type":3,"usable":"1","remarks":"","children":[]},{"id":110,"parentId":72,"sort":0,"name":"/sys/user/page","code":"/sys/user/page","type":3,"usable":"1","remarks":"","children":[]},{"id":111,"parentId":72,"sort":0,"name":"/sys/user/roleIds","code":"/sys/user/roleIds","type":3,"usable":"1","remarks":"","children":[]},{"id":112,"parentId":72,"sort":0,"name":"/sys/user/setRoles","code":"/sys/user/setRoles","type":3,"usable":"1","remarks":"","children":[]}]}]}], 8 | } 9 | -------------------------------------------------------------------------------- /src/services/sys.js: -------------------------------------------------------------------------------- 1 | import axios from "../common/axios"; 2 | import * as api from "../api"; 3 | import defaultValue from "./default"; 4 | 5 | export function login (params) { 6 | return new Promise((resolve, reject) => { 7 | axios.post(api.LOGIN, { params }).then(response => { 8 | resolve(response.data); 9 | }, err => { 10 | resolve(defaultValue.login); 11 | }) 12 | .catch((error) => { 13 | resolve(defaultValue.login) 14 | }) 15 | }) 16 | } 17 | export function msgList (params) { 18 | return new Promise((resolve, reject) => { 19 | axios.post(api.MSG_TOP_TEN, { params }).then(response => { 20 | resolve(response.data); 21 | }, err => { 22 | resolve(defaultValue.msgList); 23 | }) 24 | .catch((error) => { 25 | resolve(defaultValue.msgList) 26 | }) 27 | }) 28 | } 29 | 30 | 31 | export function menuList (params) { 32 | return new Promise((resolve, reject) => { 33 | axios.get(api.SYS_MENU_LIST, { params }).then(response => { 34 | resolve(response.data); 35 | }, err => { 36 | resolve(defaultValue.menuList); 37 | }) 38 | .catch((error) => { 39 | resolve(defaultValue.menuList) 40 | }) 41 | }) 42 | } 43 | 44 | export function resourceList (params) { 45 | return new Promise((resolve, reject) => { 46 | axios.get(api.SYS_RESOURCE_LIST, { params }).then(response => { 47 | resolve(response.data); 48 | }, err => { 49 | resolve(defaultValue.resource); 50 | }) 51 | .catch((error) => { 52 | resolve(defaultValue.resource) 53 | }) 54 | }) 55 | } 56 | 57 | export function roleList (params) { 58 | return new Promise((resolve, reject) => { 59 | axios.get(api.SYS_MENU_LIST, { params }).then(response => { 60 | resolve(response.data); 61 | }, err => { 62 | resolve(defaultValue.roleList); 63 | }) 64 | .catch((error) => { 65 | resolve(defaultValue.roleList) 66 | }) 67 | }) 68 | } 69 | 70 | export function userList (params) { 71 | const userList = {total:defaultValue.userList.total,records:defaultValue.userList.records.reverse()} 72 | return new Promise((resolve, reject) => { 73 | axios.get(api.SYS_USER_PAGE, { params }).then(response => { 74 | resolve(response.data); 75 | }, err => { 76 | resolve(userList); 77 | }) 78 | .catch((error) => { 79 | resolve(userList) 80 | }) 81 | }) 82 | } 83 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './mutation-types' 2 | 3 | export const toggleSidebar = ({ commit }, opened) => commit(types.TOGGLE_SIDEBAR, opened) 4 | 5 | export const toggleDevice = ({ commit }, device) => commit(types.TOGGLE_DEVICE, device) 6 | 7 | export const expandMenu = ({ commit }, menuItem) => { 8 | if (menuItem) { 9 | menuItem.expanded = menuItem.expanded || false 10 | commit(types.EXPAND_MENU, menuItem) 11 | } 12 | } 13 | 14 | export const switchEffect = ({ commit }, effectItem) => { 15 | if (effectItem) { 16 | commit(types.SWITCH_EFFECT, effectItem) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | import types from "./mutation-types"; 4 | import defaultValue from "../services/default"; 5 | import * as api from "../api"; 6 | import { getCurrentMenu, getSessionKey } from '../common/utils' 7 | 8 | Vue.use(Vuex) 9 | 10 | const store = new Vuex.Store({ 11 | strict: true, // process.env.NODE_ENV !== 'production', 直接修改state 抛出异常 12 | 13 | getters: { 14 | loading: state => state.loading, 15 | menuList: state => state.menuList, 16 | sidebar: state => state.sidebar, 17 | userInfo:state => state.userInfo, 18 | device:state => state.device, 19 | currentMenus:state => state.currentMenus, 20 | }, 21 | state: { 22 | loading: false, 23 | menuList: {}, 24 | sidebar: { 25 | collapsed: getSessionKey('state.sidebar.collapsed','false')==='true', 26 | show: getSessionKey('state.sidebar.show','true')==='true', 27 | }, 28 | device: { 29 | isMobile: false 30 | }, 31 | userInfo:{name:'佚名'}, 32 | currentMenus:[], 33 | }, 34 | mutations: { 35 | //只能同步的函数 36 | [types.TOGGLE_DEVICE] (state, isMobile) { 37 | state.device.isMobile = isMobile 38 | }, 39 | [types.TOGGLE_LOADING] (state) { 40 | state.loading = !state.loading 41 | }, 42 | [types.LOAD_MENU] (state, menu) { 43 | state.menuList = menu; 44 | }, 45 | [types.LOAD_CURRENT_MENU] (state, menu) { 46 | state.currentMenus = menu; 47 | }, 48 | [types.SET_USER_INFO] (state, info) { 49 | state.userInfo = info; 50 | }, 51 | [types.TOGGLE_SIDEBAR] (state, collapsed) { 52 | if (collapsed == null) collapsed = !state.sidebar.collapsed; 53 | state.sidebar.collapsed = collapsed; 54 | window.sessionStorage.setItem("state.sidebar.collapsed",collapsed) 55 | }, 56 | [types.TOGGLE_SIDEBAR_SHOW] (state,show) { 57 | if (show == null) state.sidebar.show = !state.sidebar.show; 58 | else{ 59 | state.sidebar.show = show; 60 | } 61 | window.sessionStorage.setItem("state.sidebar.show",state.sidebar.show) 62 | }, 63 | }, actions: { 64 | //异步的函数 65 | toggleLoading: ({commit}) => commit(types.TOGGLE_LOADING), 66 | loadMenuList: ({commit}) => { 67 | Vue.axios.get(api.SYS_MENU_LIST).then(res => { 68 | commit(types.LOAD_MENU, res.data); 69 | }).catch(exp => commit(types.LOAD_MENU, defaultValue.menuList)); 70 | }, 71 | changeCurrentMenu: ({state,commit},{path,matched,fullPath}) => { 72 | const a = getCurrentMenu(fullPath,state.menuList); 73 | commit(types.LOAD_CURRENT_MENU, a.reverse()); 74 | } 75 | }, 76 | }) 77 | 78 | export default store 79 | -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | const types = { 2 | TOGGLE_LOADING: 'TOGGLE_LOADING', 3 | TOGGLE_SIDEBAR: 'TOGGLE_SIDEBAR', 4 | TOGGLE_SIDEBAR_SHOW: 'TOGGLE_SIDEBAR_SHOW', 5 | TOGGLE_DEVICE: "TOGGLE_DEVICE", 6 | EXPAND_MENU: 'EXPAND_MENU', 7 | SWITCH_EFFECT: 'SWITCH_EFFECT', 8 | LOAD_MENU: 'LOAD_MENU', 9 | LOAD_CURRENT_MENU: 'LOAD_CURRENT_MENU', 10 | SET_USER_INFO: 'SET_USER_INFO', 11 | } 12 | 13 | export default types 14 | -------------------------------------------------------------------------------- /static/data/cmenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/cmenu.png -------------------------------------------------------------------------------- /static/data/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/dash.png -------------------------------------------------------------------------------- /static/data/dash2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/dash2.png -------------------------------------------------------------------------------- /static/data/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceList":[{"id":52,"parentId":null,"sort":0,"name":"登录","code":"/login","type":3,"usable":"1","remarks":"","children":[]}, 3 | {"id":68,"parentId":null,"sort":0,"name":"仪表盘","code":"/index","type":1,"usable":"1","remarks":"","children":[]}, 4 | {"id":69,"parentId":null,"sort":0,"name":"系统管理","code":"/sys","type":1,"usable":"1","remarks":"","children":[{"id":82,"parentId":69,"sort":0,"name":"资源管理","code":"/sys/resource","type":1,"usable":"1","remarks":"","children":[{"id":99,"parentId":82,"sort":0,"name":"/sys/resource/get","code":"/sys/resource/get","type":3,"usable":"1","remarks":"","children":[]}, 5 | {"id":100,"parentId":82,"sort":0,"name":"/sys/resource/update","code":"/sys/resource/update","type":3,"usable":"1","remarks":"","children":[]}, 6 | {"id":101,"parentId":82,"sort":0,"name":"/sys/resource/delete","code":"/sys/resource/delete","type":3,"usable":"1","remarks":"","children":[]}, 7 | {"id":102,"parentId":82,"sort":0,"name":"/sys/resource/add","code":"/sys/resource/add","type":3,"usable":"1","remarks":"","children":[]}, 8 | {"id":103,"parentId":82,"sort":0,"name":"/sys/resource/page","code":"/sys/resource/page","type":3,"usable":"1","remarks":"","children":[]}, 9 | {"id":104,"parentId":82,"sort":0,"name":"/sys/resource/list","code":"/sys/resource/list","type":3,"usable":"1","remarks":"","children":[]}, 10 | {"id":105,"parentId":82,"sort":0,"name":"/sys/resource/list2","code":"/sys/resource/list2","type":3,"usable":"1","remarks":"","children":[]}]}, 11 | {"id":70,"parentId":69,"sort":1,"name":"菜单管理","code":"/sys/menuList","type":1,"usable":"1","remarks":"","children":[{"id":83,"parentId":70,"sort":0,"name":"/sys/menu/get","code":"/sys/menu/get","type":3,"usable":"1","remarks":"","children":[]}, 12 | {"id":84,"parentId":70,"sort":0,"name":"/sys/menu/update","code":"/sys/menu/update","type":3,"usable":"1","remarks":"","children":[]}, 13 | {"id":85,"parentId":70,"sort":0,"name":"/sys/menu/delete","code":"/sys/menu/delete","type":3,"usable":"1","remarks":"","children":[]}, 14 | {"id":86,"parentId":70,"sort":0,"name":"/sys/menu/add","code":"/sys/menu/add","type":3,"usable":"1","remarks":"","children":[]}, 15 | {"id":87,"parentId":70,"sort":0,"name":"/sys/menu/page","code":"/sys/menu/page","type":3,"usable":"1","remarks":"","children":[]}, 16 | {"id":88,"parentId":70,"sort":0,"name":"/sys/menu/list","code":"/sys/menu/list","type":3,"usable":"1","remarks":"","children":[]}, 17 | {"id":89,"parentId":70,"sort":0,"name":"/sys/menu/list2","code":"/sys/menu/list2","type":3,"usable":"1","remarks":"","children":[]}]}, 18 | {"id":71,"parentId":69,"sort":3,"name":"角色管理","code":"/sys/roleList","type":1,"usable":"1","remarks":"","children":[{"id":90,"parentId":71,"sort":0,"name":"/sys/role/get","code":"/sys/role/get","type":3,"usable":"1","remarks":"","children":[]}, 19 | {"id":91,"parentId":71,"sort":0,"name":"/sys/role/update","code":"/sys/role/update","type":3,"usable":"1","remarks":"","children":[]}, 20 | {"id":92,"parentId":71,"sort":0,"name":"/sys/role/delete","code":"/sys/role/delete","type":3,"usable":"1","remarks":"","children":[]}, 21 | {"id":93,"parentId":71,"sort":0,"name":"/sys/role/add","code":"/sys/role/add","type":3,"usable":"1","remarks":"","children":[]}, 22 | {"id":94,"parentId":71,"sort":0,"name":"/sys/role/page","code":"/sys/role/page","type":3,"usable":"1","remarks":"","children":[]}, 23 | {"id":95,"parentId":71,"sort":0,"name":"/sys/role/list","code":"/sys/role/list","type":3,"usable":"1","remarks":"","children":[]}, 24 | {"id":96,"parentId":71,"sort":0,"name":"/sys/role/list2","code":"/sys/role/list2","type":3,"usable":"1","remarks":"","children":[]}, 25 | {"id":97,"parentId":71,"sort":0,"name":"/sys/role/resources","code":"/sys/role/resources","type":3,"usable":"1","remarks":"","children":[]}, 26 | {"id":98,"parentId":71,"sort":0,"name":"/sys/role/setResources","code":"/sys/role/setResources","type":3,"usable":"1","remarks":"","children":[]}]}, 27 | {"id":72,"parentId":69,"sort":6,"name":"用户管理","code":"/sys/userList","type":1,"usable":"1","remarks":"","children":[{"id":106,"parentId":72,"sort":0,"name":"/sys/user/get","code":"/sys/user/get","type":3,"usable":"1","remarks":"","children":[]}, 28 | {"id":107,"parentId":72,"sort":0,"name":"/sys/user/add","code":"/sys/user/add","type":3,"usable":"1","remarks":"","children":[]}, 29 | {"id":108,"parentId":72,"sort":0,"name":"/sys/user/update","code":"/sys/user/update","type":3,"usable":"1","remarks":"","children":[]}, 30 | {"id":109,"parentId":72,"sort":0,"name":"/sys/user/delete","code":"/sys/user/delete","type":3,"usable":"1","remarks":"","children":[]}, 31 | {"id":110,"parentId":72,"sort":0,"name":"/sys/user/page","code":"/sys/user/page","type":3,"usable":"1","remarks":"","children":[]}, 32 | {"id":111,"parentId":72,"sort":0,"name":"/sys/user/roleIds","code":"/sys/user/roleIds","type":3,"usable":"1","remarks":"","children":[]}, 33 | {"id":112,"parentId":72,"sort":0,"name":"/sys/user/setRoles","code":"/sys/user/setRoles","type":3,"usable":"1","remarks":"","children":[]}]}]}], 34 | "menuList": [ 35 | {"id":1,"parentId":null,"sort":0,"name":"仪表盘","href":"/index","icon":"fa fa-dashboard","children":[], 36 | "isShow":"1"}, 37 | {"id":31,"parentId":null,"sort":1,"name":"测试1","href":"/test/1","icon":"fa fa-upload","children": 38 | [ 39 | {"id":92,"parentId":31,"sort":0,"name":"测试1-1","href":"/test/1/1","icon":"fa fa-bank","children":[ 40 | {"id":912,"parentId":92,"sort":0,"name":"测试1-1-1","href":"/test/1/1/1","icon":"fa fa-bank","children":[],"isShow":"1"}, 41 | {"id":913,"parentId":92,"sort":0,"name":"测试1-1-2","href":"/test/1/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"} 42 | ],"isShow":"1"}, 43 | {"id":93,"parentId":31,"sort":0,"name":"测试1-2","href":"/test/1/2","icon":"fa fa-area-chart","children":[],"isShow":"1"} 44 | ] 45 | ,"isShow":"1"}, 46 | {"id":102,"parentId":null,"sort":3,"name":"测试2","href":"/test/2","icon":"fa fa-download","children": 47 | [ 48 | {"id":103,"parentId":102,"sort":0,"name":"测试2-1","href":"/test/2/1","icon":"fa fa-image","children":[],"isShow":"1"} 49 | ] 50 | ,"isShow":"1"}, 51 | {"id":6,"parentId":null,"sort":6,"name":"系统管理","href":"/sys","icon":"fa fa-cog","children": 52 | [ 53 | {"id":108,"parentId":6,"sort":0,"name":" 资源管理","href":"/sys/resource","icon":"fa fa-database","children":[],"isShow":"1"}, 54 | {"id":7,"parentId":6,"sort":1,"name":"菜单管理","href":"/sys/menuList","icon":"fa fa-navicon","children":[],"isShow":"1"}, 55 | {"id":8,"parentId":6,"sort":2,"name":"角色管理","href":"/sys/roleList","icon":"fa fa-universal-access","children":[],"isShow":"1"}, 56 | {"id":9,"parentId":6,"sort":3,"name":"用户管理","href":"/sys/userList","icon":"fa fa-user-plus","children":[],"isShow":"1"} 57 | ] 58 | ,"isShow":"1"}], 59 | "roleList":[ 60 | {"id":26,"delFlag":0,"parentId":null,"sort":0,"name":"超级管理员","enName":"super_manager","usable":"1","remarks":"","children":[]}, 61 | {"id":27,"delFlag":0,"parentId":null,"sort":1,"name":"客服主管","enName":"server_manager","usable":"1","remarks":"","children":[ 62 | {"id":28,"delFlag":0,"parentId":27,"sort":0,"name":"售后客服","enName":"server1","usable":"1","remarks":"","children":[]}, 63 | {"id":29,"delFlag":0,"parentId":27,"sort":1,"name":"售前客服","enName":"server2","usable":"1","remarks":"","children":[]} 64 | ]} 65 | ], 66 | "userList":[ 67 | {"id":12,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":2,"token":null}, 68 | {"id":23,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":1,"token":null}, 69 | {"id":2333,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":null,"phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":1,"token":null}, 70 | {"id":345,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":2,"token":null}, 71 | {"id":45,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":null,"phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":0,"token":null}, 72 | {"id":56,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":null,"token":null}, 73 | {"id":67,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":null,"phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":null,"token":null}, 74 | {"id":78,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":null,"token":null}, 75 | {"id":87,"delFlag":"0","companyId":null,"officeId":null,"loginName":"lanux","password":null,"no":null,"name":"12345","email":"lanux@foxmail.com","phone":null,"mobile":null,"userType":null,"photo":null,"loginIp":null,"loginDate":null,"loginFlag":null,"remarks":null,"status":null,"token":null} 76 | ], 77 | "messageList":[ 78 | { 79 | "id": "640000201501165883", 80 | "type": 0, 81 | "code": 107, 82 | "timeLine": "2013031613", 83 | "message": "阶期查音音南这认式给自来走事。手进全线引其质行族导深些。", 84 | "title": "作几点内部重压示现或采候器日", 85 | "createTime": "426050337874", 86 | "senderName": "Hall", 87 | "senderPic": "http://dummyimage.com/100x100/f2799f/757575.png&text=H" 88 | }, 89 | { 90 | "id": "15000019760303327X", 91 | "type": 1, 92 | "code": 109, 93 | "timeLine": "1994030718", 94 | "message": "听飞叫例感给其团南织主作什。", 95 | "title": "府铁些以眼铁南单行办其被眼线", 96 | "createTime": "612808881585", 97 | "senderName": "Hall", 98 | "senderPic": "http://dummyimage.com/100x100/79c3f2/757575.png&text=H" 99 | }, 100 | { 101 | "id": "530000198607165793", 102 | "type": 1, 103 | "code": 106, 104 | "timeLine": "1990122503", 105 | "message": "于学认气感很效效引需说报党。调应各近思常市美许自毛完容矿日增。", 106 | "title": "整近律马造起米农员济解题自例识个", 107 | "createTime": "234654265042", 108 | "senderName": "Rodriguez", 109 | "senderPic": "http://dummyimage.com/100x100/e6f279/757575.png&text=R" 110 | }, 111 | { 112 | "id": "320000200905032842", 113 | "type": 1, 114 | "code": 103, 115 | "timeLine": "1980062104", 116 | "message": "除年命却积同部去断权议党低二易过。", 117 | "title": "消问料品把精是器话", 118 | "createTime": "1194108860623", 119 | "senderName": "Lewis", 120 | "senderPic": "http://dummyimage.com/100x100/da79f2/757575.png&text=L" 121 | }, 122 | { 123 | "id": "210000198109172937", 124 | "type": 1, 125 | "code": 104, 126 | "timeLine": "1993041210", 127 | "message": "具都主部确特次取圆派不儿日和难力。", 128 | "title": "导结计市色通证确高想", 129 | "createTime": "374284498307", 130 | "senderName": "Hernandez", 131 | "senderPic": "http://dummyimage.com/100x100/79f2b7/757575.png&text=H" 132 | }, 133 | { 134 | "id": "410000200402164212", 135 | "type": 1, 136 | "code": 108, 137 | "timeLine": "2015123015", 138 | "message": "青矿地级质还进眼件每产它整区土容斯消。", 139 | "title": "治龙工必近思空例东应", 140 | "createTime": "626036503938", 141 | "senderName": "Martinez", 142 | "senderPic": "http://dummyimage.com/100x100/f29479/757575.png&text=M" 143 | }, 144 | { 145 | "id": "620000198507210923", 146 | "type": 0, 147 | "code": 104, 148 | "timeLine": "1983120914", 149 | "message": "意动林设状军红关风家声会政复增低。上指置由步联其气养精直该才清。信果此二存日效产学者今打品江代面。", 150 | "title": "教月历统其等革法格油满精发光", 151 | "createTime": "778399865782", 152 | "senderName": "Rodriguez", 153 | "senderPic": "http://dummyimage.com/100x100/7981f2/757575.png&text=R" 154 | }, 155 | { 156 | "id": "330000198108089346", 157 | "type": 1, 158 | "code": 108, 159 | "timeLine": "1983032322", 160 | "message": "温象采色已必使战素并京名或们。报始民名料是究要系后体治给单消容且。", 161 | "title": "此个同但基广流看", 162 | "createTime": "396531147139", 163 | "senderName": "Robinson", 164 | "senderPic": "http://dummyimage.com/100x100/a4f279/757575.png&text=R" 165 | }, 166 | { 167 | "id": "82000019811016775X", 168 | "type": 0, 169 | "code": 105, 170 | "timeLine": "1970082304", 171 | "message": "你最志造越员因说转拉克要书实结心存。化研则济得象青便图造拉世格。", 172 | "title": "也作队思国月义听办研成", 173 | "createTime": "1429957209433", 174 | "senderName": "Anderson", 175 | "senderPic": "http://dummyimage.com/100x100/f279c8/757575.png&text=A" 176 | }, 177 | { 178 | "id": "710000198510122053", 179 | "type": 0, 180 | "code": 104, 181 | "timeLine": "2014052203", 182 | "message": "科三解角响观府你满在可之。权任合区员学它果接领速广断领按。", 183 | "title": "几它场新亲农也区技须究声完社情", 184 | "createTime": "1013282383046", 185 | "senderName": "Wilson", 186 | "senderPic": "http://dummyimage.com/100x100/79ebf2/757575.png&text=W" 187 | } 188 | ] 189 | } 190 | -------------------------------------------------------------------------------- /static/data/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/login.png -------------------------------------------------------------------------------- /static/data/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/menu.png -------------------------------------------------------------------------------- /static/data/menu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/menu2.png -------------------------------------------------------------------------------- /static/data/menu5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/menu5.png -------------------------------------------------------------------------------- /static/data/mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/mobile.png -------------------------------------------------------------------------------- /static/data/resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/resource.png -------------------------------------------------------------------------------- /static/data/role.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/role.png -------------------------------------------------------------------------------- /static/data/role4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/role4.png -------------------------------------------------------------------------------- /static/data/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/user.png -------------------------------------------------------------------------------- /static/data/user2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/data/user2.png -------------------------------------------------------------------------------- /static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /static/img/404_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/img/404_error.png -------------------------------------------------------------------------------- /static/img/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanux/Vue-Admin/6b18cb0533880d66173791e0c214e80a892539fb/static/img/user.png --------------------------------------------------------------------------------