├── static └── .gitkeep ├── src ├── mock │ ├── index.js │ ├── data │ │ └── user.js │ └── mock.js ├── api │ ├── index.js │ └── api.js ├── vuex │ ├── getters.js │ ├── actions.js │ └── store.js ├── assets │ ├── logo.png │ └── user.jpg ├── util │ └── js │ │ └── common.js ├── main.js ├── view │ ├── homePage │ │ └── homePage.vue │ ├── log │ │ └── log.vue │ ├── login.vue │ ├── data │ │ ├── dataGroup.vue │ │ └── dataDict.vue │ ├── anth │ │ ├── auth.vue │ │ └── menu.vue │ ├── home.vue │ └── user │ │ ├── user.vue │ │ └── role.vue ├── App.vue ├── components │ └── HelloWorld.vue └── router │ └── index.js ├── .eslintignore ├── test ├── unit │ ├── setup.js │ ├── .eslintrc │ ├── specs │ │ └── HelloWorld.spec.js │ └── jest.conf.js └── e2e │ ├── specs │ └── test.js │ ├── custom-assertions │ └── elementCount.js │ ├── nightwatch.conf.js │ └── runner.js ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── .editorconfig ├── .postcssrc.js ├── .gitignore ├── .babelrc ├── index.html ├── README.md ├── .eslintrc.js └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mock/index.js: -------------------------------------------------------------------------------- 1 | import mock from './mock'; 2 | 3 | export default mock; -------------------------------------------------------------------------------- /src/api/index.js: -------------------------------------------------------------------------------- 1 | import * as api from './api'; 2 | 3 | export default api; -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | /test/unit/coverage/ 6 | -------------------------------------------------------------------------------- /test/unit/setup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/vuex/getters.js: -------------------------------------------------------------------------------- 1 | //test 2 | export const getCount = state => { 3 | return state.count 4 | } -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangyuanjun008/wyj-vue-security/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/user.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangyuanjun008/wyj-vue-security/HEAD/src/assets/user.jpg -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "globals": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | //test 2 | export const increment = ({commit}) => { 3 | commit('INCREMENT') 4 | } 5 | export const decrement = ({commit}) => { 6 | commit('DECREMENT') 7 | } -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserslist" field in package.json 6 | "postcss-import": {}, 7 | "autoprefixer": {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | /test/e2e/reports/ 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false 5 | }], 6 | "stage-2" 7 | ], 8 | "plugins": ["transform-runtime"], 9 | "env": { 10 | "test": { 11 | "presets": ["env", "stage-2"], 12 | "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | wyj-vue-security 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .toEqual('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /src/util/js/common.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | export default{ 3 | hasPermission : function(permission){ 4 | if(this.isNullOrEmpty(window.perms)) { 5 | return false; 6 | } 7 | if (window.perms.indexOf(permission) > -1) { 8 | return true; 9 | } else { 10 | return false; 11 | } 12 | }, 13 | isNullOrEmpty : function (obj) { 14 | if ((typeof (obj) == "string" && obj == "") || obj == null || obj == undefined) { 15 | return true; 16 | } else { 17 | return false; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/vuex/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import * as actions from './actions' 4 | import * as getters from './getters' 5 | 6 | Vue.use(Vuex) 7 | 8 | // 应用初始状态 9 | const state = { 10 | count: 10 11 | } 12 | 13 | // 定义所需的 mutations 14 | const mutations = { 15 | INCREMENT(state) { 16 | state.count++ 17 | }, 18 | DECREMENT(state) { 19 | state.count-- 20 | } 21 | } 22 | 23 | // 创建 store 实例 24 | export default new Vuex.Store({ 25 | actions, 26 | getters, 27 | state, 28 | mutations 29 | }) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wyj-vue-security 2 | 3 | > 此项目是基于vue + element ui的前后端分离基础权限管理后台的前台,后端访问地址 https://github.com/wangyuanjun008/wyj-springboot-security.git 4 | 5 | ### 技术栈 6 | - "vue": "^2.5.2" 7 | - "vue-router": "^3.0.1" 8 | - "mockjs": "^1.0.1-beta3", 9 | - "axios": "^0.17.1", 10 | - "element-ui": "^2.0.5", 11 | 具体请参考 https://github.com/wangyuanjun008/wyj-vue-security/blob/master/package.json 12 | 13 | ### 说明 目前这个项目还在维护中,后面还会继续增加新功能!! 14 | 如果对您对此项目有兴趣,可以点 "Star" 支持一下 谢谢! ^_^ 15 | 16 | ### 项目运行 17 | - git clone https://github.com/wangyuanjun008/wyj-vue-security.git 18 | - cd wyj-vue-security 19 | - npm install 20 | - npm run dev -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://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/standard/standard/blob/master/docs/RULES-en.md 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 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import babelpolyfill from 'babel-polyfill' 4 | import Vue from 'vue' 5 | import App from './App' 6 | import router from './router' 7 | import ElementUI from 'element-ui' 8 | import Mock from './mock' 9 | import store from './vuex/store' 10 | //Mock.mockData(); 11 | import 'element-ui/lib/theme-chalk/index.css' 12 | import 'font-awesome/css/font-awesome.min.css' 13 | import 'ztree/css/zTreeStyle/zTreeStyle.css' 14 | import 'ztree' 15 | Vue.config.productionTip = false 16 | 17 | /* eslint-disable no-new */ 18 | Vue.use(ElementUI) 19 | new Vue({ 20 | //el: '#app', 21 | //template: '', 22 | router, 23 | store, 24 | //components: { App } 25 | render: h => h(App) 26 | }).$mount('#app') -------------------------------------------------------------------------------- /test/unit/jest.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '../../'), 5 | moduleFileExtensions: [ 6 | 'js', 7 | 'json', 8 | 'vue' 9 | ], 10 | moduleNameMapper: { 11 | '^@/(.*)$': '/src/$1' 12 | }, 13 | transform: { 14 | '^.+\\.js$': '/node_modules/babel-jest', 15 | '.*\\.(vue)$': '/node_modules/vue-jest' 16 | }, 17 | testPathIgnorePatterns: [ 18 | '/test/e2e' 19 | ], 20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'], 21 | setupFiles: ['/test/unit/setup'], 22 | mapCoverage: true, 23 | coverageDirectory: '/test/unit/coverage', 24 | collectCoverageFrom: [ 25 | 'src/**/*.{js,vue}', 26 | '!src/main.js', 27 | '!src/router/index.js', 28 | '!**/node_modules/**' 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/view/homePage/homePage.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 34 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // The assertion name is the filename. 3 | // Example usage: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // For more information on custom assertions see: 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | 10 | exports.assertion = function (selector, count) { 11 | this.message = 'Testing if element <' + selector + '> has count: ' + count 12 | this.expected = count 13 | this.pass = function (val) { 14 | return val === this.expected 15 | } 16 | this.value = function (res) { 17 | return res.value 18 | } 19 | this.command = function (cb) { 20 | var self = this 21 | return this.api.execute(function (selectorToCount) { 22 | return document.querySelectorAll(selectorToCount).length 23 | }, [selector], function (res) { 24 | cb.call(self, res) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/mock/data/user.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs'; 2 | 3 | const LoginUsers = [ 4 | { 5 | id: 1, 6 | username: 'admin', 7 | password: '123456', 8 | avatar: '../../assets/user.jpg', 9 | name: '管理员' 10 | } 11 | ]; 12 | 13 | const Users = []; 14 | 15 | for (let i = 0; i < 86; i++) { 16 | Users.push(Mock.mock({ 17 | id: Mock.Random.guid(), 18 | userName: Mock.Random.string( 5, 10 ), 19 | password: Mock.Random.integer( 100, 10000 ), 20 | name: Mock.Random.cname(), 21 | address: Mock.mock('@county(true)'), 22 | 'age|18-60': 1, 23 | phone: /^1[0-9]{10}$/, 24 | email: Mock.Random.email(), 25 | sex: Mock.Random.integer(1, 2) 26 | })); 27 | } 28 | 29 | const dataGroups = []; 30 | 31 | for (let i = 0; i < 86; i++) { 32 | dataGroups.push(Mock.mock({ 33 | id: Mock.Random.guid(), 34 | groupCode: Mock.Random.string( 5, 10 ), 35 | groupName: Mock.Random.string( 5, 10 ), 36 | remark: Mock.Random.string( 5, 10 ), 37 | status: Mock.Random.integer(1, 0), 38 | parentId: Mock.Random.guid() 39 | })); 40 | } 41 | 42 | export { LoginUsers, Users,dataGroups }; -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 16 | 17 | 60 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 35 | 51 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | 4 | const webpack = require('webpack') 5 | const DevServer = require('webpack-dev-server') 6 | 7 | const webpackConfig = require('../../build/webpack.prod.conf') 8 | const devConfigPromise = require('../../build/webpack.dev.conf') 9 | 10 | let server 11 | 12 | devConfigPromise.then(devConfig => { 13 | const devServerOptions = devConfig.devServer 14 | const compiler = webpack(webpackConfig) 15 | server = new DevServer(compiler, devServerOptions) 16 | const port = devServerOptions.port 17 | const host = devServerOptions.host 18 | return server.listen(port, host) 19 | }) 20 | .then(() => { 21 | // 2. run the nightwatch test suite against it 22 | // to run in additional browsers: 23 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 24 | // 2. add it to the --env flag below 25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 26 | // For more information on Nightwatch's config file, see 27 | // http://nightwatchjs.org/guide#settings-file 28 | let opts = process.argv.slice(2) 29 | if (opts.indexOf('--config') === -1) { 30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 31 | } 32 | if (opts.indexOf('--env') === -1) { 33 | opts = opts.concat(['--env', 'chrome']) 34 | } 35 | 36 | const spawn = require('cross-spawn') 37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 38 | 39 | runner.on('exit', function (code) { 40 | server.close() 41 | process.exit(code) 42 | }) 43 | 44 | runner.on('error', function (err) { 45 | server.close() 46 | throw err 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | 6 | export default new Router({ 7 | routes: [{ 8 | path: '/', 9 | component: resolve => require(['../view/login.vue'], resolve), 10 | hidden: true 11 | },{ 12 | path: '/homePage', 13 | name : '首页', 14 | component: resolve => require(['../view/home.vue'], resolve), 15 | leaf: true,//只有一个节点 16 | children: [{ 17 | path: '/homePage', 18 | component: resolve => require(['../view/homePage/homePage.vue'], resolve), 19 | name : '首页' 20 | } 21 | ] 22 | }, { 23 | path: '/user', 24 | component: resolve => require(['../view/home.vue'], resolve), 25 | name : '角色用户管理', 26 | children: [{ 27 | path: '/user', 28 | component: resolve => require(['../view/user/user.vue'], resolve), 29 | name : '用户管理' 30 | },{ 31 | path: '/role', 32 | component: resolve => require(['../view/user/role.vue'], resolve), 33 | name : '角色管理' 34 | } 35 | ] 36 | }, { 37 | path: '/auth', 38 | component: resolve => require(['../view/home.vue'], resolve), 39 | name : '权限资源管理', 40 | children: [{ 41 | path: '/menu', 42 | component: resolve => require(['../view/anth/menu.vue'], resolve), 43 | name : '菜单管理' 44 | },{ 45 | path: '/auth', 46 | component: resolve => require(['../view/anth/auth.vue'], resolve), 47 | name : '权限管理' 48 | } 49 | ] 50 | }, { 51 | path: '/data', 52 | component: resolve => require(['../view/home.vue'], resolve), 53 | name : '数据字典', 54 | children: [{ 55 | path: '/dataGroup', 56 | component: resolve => require(['../view/data/dataGroup.vue'], resolve), 57 | name : '数据分组' 58 | },{ 59 | path: '/dataDict', 60 | component: resolve => require(['../view/data/dataDict.vue'], resolve), 61 | name : '数据字典' 62 | },{ 63 | path: '/log', 64 | component: resolve => require(['../view/log/log.vue'], resolve), 65 | name : '日志记录' 66 | } 67 | ] 68 | }] 69 | }) 70 | -------------------------------------------------------------------------------- /src/view/log/log.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 81 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.2.4 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: { 14 | '/remote': { 15 | target: 'http://127.0.0.1:8081', 16 | changeOrigin: true, 17 | pathRewrite: { 18 | '^/remote': '/remote' 19 | } 20 | } 21 | }, 22 | 23 | // Various Dev Server settings 24 | host: 'localhost', // can be overwritten by process.env.HOST 25 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 26 | autoOpenBrowser: false, 27 | errorOverlay: true, 28 | notifyOnErrors: true, 29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 30 | 31 | // Use Eslint Loader? 32 | // If true, your code will be linted during bundling and 33 | // linting errors and warnings will be shown in the console. 34 | useEslint: true, 35 | // If true, eslint errors and warnings will also be shown in the error overlay 36 | // in the browser. 37 | showEslintErrorsInOverlay: false, 38 | 39 | /** 40 | * Source Maps 41 | */ 42 | 43 | // https://webpack.js.org/configuration/devtool/#development 44 | devtool: 'eval-source-map', 45 | 46 | // If you have problems debugging vue-files in devtools, 47 | // set this to false - it *may* help 48 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 49 | cacheBusting: true, 50 | 51 | // CSS Sourcemaps off by default because relative paths are "buggy" 52 | // with this option, according to the CSS-Loader README 53 | // (https://github.com/webpack/css-loader#sourcemaps) 54 | // In our experience, they generally work as expected, 55 | // just be aware of this issue when enabling this option. 56 | cssSourceMap: false, 57 | }, 58 | 59 | build: { 60 | // Template for index.html 61 | index: path.resolve(__dirname, '../dist/index.html'), 62 | 63 | // Paths 64 | assetsRoot: path.resolve(__dirname, '../dist'), 65 | assetsSubDirectory: 'static', 66 | assetsPublicPath: '/', 67 | 68 | /** 69 | * Source Maps 70 | */ 71 | 72 | productionSourceMap: true, 73 | // https://webpack.js.org/configuration/devtool/#production 74 | devtool: '#source-map', 75 | 76 | // Gzip off by default as many popular static hosts such as 77 | // Surge or Netlify already gzip all static assets for you. 78 | // Before setting to `true`, make sure to: 79 | // npm install --save-dev compression-webpack-plugin 80 | productionGzip: false, 81 | productionGzipExtensions: ['js', 'css'], 82 | 83 | // Run the build command with an extra argument to 84 | // View the bundle analyzer report after build finishes: 85 | // `npm run build --report` 86 | // Set to `true` or `false` to always turn it on or off 87 | bundleAnalyzerReport: process.env.npm_config_report 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/api/api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import qs from 'qs'; 3 | 4 | let base = ''; 5 | 6 | //登录 7 | export const requestLogin = params => { return axios.post(`/remote/login`, qs.stringify(params)).then(res => res.data); }; 8 | 9 | //用户管理 10 | export const getUserListPage = params => { return axios.post(`/remote/user/list`, qs.stringify(params)); }; 11 | 12 | export const removeUser = params => { return axios.post(`/remote/user/remove`, qs.stringify(params)); }; 13 | 14 | export const editUser = params => { return axios.get(`/remote/user/`+params); }; 15 | 16 | export const addUser = params => { return axios.post(`/remote/user/add`, qs.stringify(params)); }; 17 | 18 | //角色管理 19 | export const getRoleListPage = params => { return axios.post(`/remote/role/list`, qs.stringify(params)); }; 20 | 21 | export const addRole= params => { return axios.post(`/remote/role/add`, qs.stringify(params)); }; 22 | 23 | export const removeRole = params => { return axios.post(`/remote/role/remove`, qs.stringify(params)); }; 24 | 25 | //菜单管理 26 | export const getMenuListPage = params => { return axios.post(`/remote/menu/list`, qs.stringify(params)); }; 27 | 28 | export const addMenu = params => { return axios.post(`/remote/menu/add`, qs.stringify(params)); }; 29 | 30 | export const removeMenu = params => { return axios.post(`/remote/menu/remove`, qs.stringify(params)); }; 31 | 32 | //权限管理 33 | export const getAuthListPage = params => { return axios.post(`/remote/auth/list`, qs.stringify(params)); }; 34 | 35 | export const addAuth = params => { return axios.post(`/remote/auth/add`, qs.stringify(params)); }; 36 | 37 | export const removeAuth = params => { return axios.post(`/remote/auth/remove`, qs.stringify(params)); }; 38 | 39 | //数据分组 40 | export const getDataGroupListPage = params => { return axios.post(`/remote/dataGroup/list`, qs.stringify(params)); }; 41 | 42 | export const addDataGroup = params => { return axios.post(`/remote/dataGroup/add`, params); }; 43 | 44 | export const removeDataGroup = params => { return axios.post(`/remote/dataGroup/remove`, qs.stringify(params)); }; 45 | 46 | 47 | //数据字典 48 | export const getDataDictListPage = params => { return axios.post(`/remote/dataDict/list`, qs.stringify(params)); }; 49 | 50 | export const addDataDict = params => { return axios.post(`/remote/dataDict/add`, qs.stringify(params) ); }; 51 | 52 | export const removeDataDict = params => { return axios.post(`/remote/dataDict/remove`, qs.stringify(params)); }; 53 | 54 | //日志 55 | export const getLogPage = params => { return axios.post(`/remote/log/list`, qs.stringify(params)); }; 56 | 57 | export const removeLog = params => { return axios.post(`/remote/log/remove`, qs.stringify(params)); }; 58 | 59 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | //获取下拉框数据源 61 | export const getData = params => {return axios.get(`/remote/dataDict/getData`, { params }); }; 62 | 63 | export const getDataStore = url => { 64 | var dataStore; 65 | $.ajax({ 66 | dataType : 'json', 67 | type : 'get', 68 | url : url, 69 | async : false, 70 | success : function(data) { 71 | dataStore = data; 72 | } 73 | }); 74 | return dataStore; 75 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wyj-vue-security", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "wangyuanjun008 <1098345452@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "webpack-dev-server –hot –inline", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", 14 | "build": "node build/build.js" 15 | }, 16 | "dependencies": { 17 | "vue": "^2.5.2", 18 | "vue-router": "^3.0.1" 19 | }, 20 | "devDependencies": { 21 | "autoprefixer": "^7.1.2", 22 | "axios": "^0.17.1", 23 | "axios-mock-adapter": "^1.10.0", 24 | "babel-core": "^6.22.1", 25 | "babel-eslint": "^7.1.1", 26 | "babel-jest": "^21.0.2", 27 | "babel-loader": "^7.1.1", 28 | "babel-plugin-dynamic-import-node": "^1.2.0", 29 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 30 | "babel-plugin-transform-runtime": "^6.22.0", 31 | "babel-polyfill": "^6.26.0", 32 | "babel-preset-env": "^1.3.2", 33 | "babel-preset-stage-2": "^6.22.0", 34 | "babel-register": "^6.22.0", 35 | "chalk": "^2.0.1", 36 | "chromedriver": "^2.27.2", 37 | "copy-webpack-plugin": "^4.0.1", 38 | "cross-spawn": "^5.0.1", 39 | "css-loader": "^0.28.7", 40 | "element-ui": "^2.0.5", 41 | "eslint": "^3.19.0", 42 | "eslint-config-standard": "^10.2.1", 43 | "eslint-friendly-formatter": "^3.0.0", 44 | "eslint-loader": "^1.7.1", 45 | "eslint-plugin-html": "^3.0.0", 46 | "eslint-plugin-import": "^2.7.0", 47 | "eslint-plugin-node": "^5.2.0", 48 | "eslint-plugin-promise": "^3.4.0", 49 | "eslint-plugin-standard": "^3.0.1", 50 | "eventsource-polyfill": "^0.9.6", 51 | "extract-text-webpack-plugin": "^3.0.0", 52 | "file-loader": "^1.1.4", 53 | "font-awesome": "^4.7.0", 54 | "friendly-errors-webpack-plugin": "^1.6.1", 55 | "html-webpack-plugin": "^2.30.1", 56 | "jest": "^21.2.0", 57 | "jest-serializer-vue": "^0.3.0", 58 | "less": "^2.7.3", 59 | "less-loader": "^4.0.5", 60 | "mockjs": "^1.0.1-beta3", 61 | "nightwatch": "^0.9.12", 62 | "node-notifier": "^5.1.2", 63 | "node-sass": "^4.7.2", 64 | "optimize-css-assets-webpack-plugin": "^3.2.0", 65 | "ora": "^1.2.0", 66 | "portfinder": "^1.0.13", 67 | "postcss-import": "^11.0.0", 68 | "postcss-loader": "^2.0.8", 69 | "rimraf": "^2.6.0", 70 | "sass-loader": "^6.0.6", 71 | "selenium-server": "^3.0.1", 72 | "semver": "^5.3.0", 73 | "shelljs": "^0.7.6", 74 | "style-loader": "^0.19.0", 75 | "stylus-loader": "^3.0.1", 76 | "url-loader": "^0.5.8", 77 | "vue-jest": "^1.0.2", 78 | "vue-loader": "^13.3.0", 79 | "vue-style-loader": "^3.0.1", 80 | "vue-template-compiler": "^2.5.2", 81 | "vuex": "^3.0.1", 82 | "webpack": "^3.6.0", 83 | "webpack-bundle-analyzer": "^2.9.0", 84 | "webpack-dev-server": "^2.9.5", 85 | "webpack-merge": "^4.1.0", 86 | "ztree": "^3.5.24" 87 | }, 88 | "engines": { 89 | "node": ">= 4.0.0", 90 | "npm": ">= 3.0.0" 91 | }, 92 | "browserslist": [ 93 | "> 1%", 94 | "last 2 versions", 95 | "not ie <= 8" 96 | ] 97 | } 98 | -------------------------------------------------------------------------------- /src/view/login.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 77 | 78 | -------------------------------------------------------------------------------- /src/mock/mock.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import MockAdapter from 'axios-mock-adapter'; 3 | import { LoginUsers, Users,dataGroups } from './data/user'; 4 | let _Users = Users; 5 | let _dataGroups = dataGroups; 6 | 7 | 8 | export default { 9 | 10 | mockData() { 11 | let mock = new MockAdapter(axios); 12 | 13 | // mock success request 14 | mock.onGet('/success').reply(200, { 15 | msg: 'success' 16 | }); 17 | 18 | // mock error request 19 | mock.onGet('/error').reply(500, { 20 | msg: 'failure' 21 | }); 22 | 23 | //登录 24 | mock.onPost('/login').reply(config => { 25 | let {username, password} = JSON.parse(config.data); 26 | return new Promise((resolve, reject) => { 27 | let user = null; 28 | setTimeout(() => { 29 | let hasUser = LoginUsers.some(u => { 30 | if (u.username === username && u.password === password) { 31 | user = JSON.parse(JSON.stringify(u)); 32 | user.password = undefined; 33 | return true; 34 | } 35 | }); 36 | 37 | if (hasUser) { 38 | resolve([200, { code: 200, msg: '请求成功', user }]); 39 | } else { 40 | resolve([200, { code: 500, msg: '账号或密码错误' }]); 41 | } 42 | }, 1000); 43 | }); 44 | }); 45 | 46 | //获取用户列表 47 | mock.onGet('/user/list').reply(config => { 48 | let {name} = config.params; 49 | let mockUsers = _Users.filter(user => { 50 | if (name && user.name.indexOf(name) == -1) return false; 51 | return true; 52 | }); 53 | return new Promise((resolve, reject) => { 54 | setTimeout(() => { 55 | resolve([200, { 56 | users: mockUsers 57 | }]); 58 | }, 1000); 59 | }); 60 | }); 61 | 62 | //获取用户列表(分页) 63 | mock.onGet('/user/listpage').reply(config => { 64 | let {page, name} = config.params; 65 | let mockUsers = _Users.filter(user => { 66 | if (name && user.name.indexOf(name) == -1) return false; 67 | return true; 68 | }); 69 | let total = mockUsers.length; 70 | mockUsers = mockUsers.filter((u, index) => index < 20 * page && index >= 20 * (page - 1)); 71 | return new Promise((resolve, reject) => { 72 | setTimeout(() => { 73 | resolve([200, { 74 | total: total, 75 | users: mockUsers 76 | }]); 77 | }, 1000); 78 | }); 79 | }); 80 | 81 | //删除用户 82 | mock.onGet('/user/remove').reply(config => { 83 | let { id } = config.params; 84 | _Users = _Users.filter(u => u.id !== id); 85 | return new Promise((resolve, reject) => { 86 | setTimeout(() => { 87 | resolve([200, { 88 | code: 200, 89 | msg: '删除成功' 90 | }]); 91 | }, 500); 92 | }); 93 | }); 94 | 95 | //批量删除用户 96 | mock.onGet('/user/batchremove').reply(config => { 97 | let { ids } = config.params; 98 | ids = ids.split(','); 99 | _Users = _Users.filter(u => !ids.includes(u.id)); 100 | return new Promise((resolve, reject) => { 101 | setTimeout(() => { 102 | resolve([200, { 103 | code: 200, 104 | msg: '删除成功' 105 | }]); 106 | }, 500); 107 | }); 108 | }); 109 | 110 | //编辑用户 111 | mock.onGet('/user/edit').reply(config => { 112 | let { id, name, addr, age, birth, sex } = config.params; 113 | _Users.some(u => { 114 | if (u.id === id) { 115 | u.name = name; 116 | u.addr = addr; 117 | u.age = age; 118 | u.birth = birth; 119 | u.sex = sex; 120 | return true; 121 | } 122 | }); 123 | return new Promise((resolve, reject) => { 124 | setTimeout(() => { 125 | resolve([200, { 126 | code: 200, 127 | msg: '编辑成功' 128 | }]); 129 | }, 500); 130 | }); 131 | }); 132 | 133 | //新增用户 134 | mock.onGet('/user/add').reply(config => { 135 | let { name, addr, age, birth, sex } = config.params; 136 | _Users.push({ 137 | name: name, 138 | addr: addr, 139 | age: age, 140 | birth: birth, 141 | sex: sex 142 | }); 143 | return new Promise((resolve, reject) => { 144 | setTimeout(() => { 145 | resolve([200, { 146 | code: 200, 147 | msg: '新增成功' 148 | }]); 149 | }, 500); 150 | }); 151 | }); 152 | 153 | 154 | //获取用户列表 155 | mock.onGet('/dataGroup/list').reply(config => { 156 | let {groupCode} = config.params; 157 | let mockDataGroups = _dataGroups.filter(dataGroup => { 158 | if (groupCode && dataGroup.groupCode.indexOf(groupCode) == -1) return false; 159 | return true; 160 | }); 161 | return new Promise((resolve, reject) => { 162 | setTimeout(() => { 163 | resolve([200, { 164 | dataGroups: mockDataGroups 165 | }]); 166 | }, 1000); 167 | }); 168 | }); 169 | 170 | //获取用户列表(分页) 171 | mock.onGet('/dataGroup/listpage').reply(config => { 172 | let {page, groupCode} = config.params; 173 | let mockDataGroups = _dataGroups.filter(dataGroup => { 174 | if (groupCode && dataGroup.groupCode.indexOf(groupCode) == -1) return false; 175 | return true; 176 | }); 177 | let total = mockDataGroups.length; 178 | mockDataGroups = mockDataGroups.filter((u, index) => index < 20 * page && index >= 20 * (page - 1)); 179 | return new Promise((resolve, reject) => { 180 | setTimeout(() => { 181 | resolve([200, { 182 | total: total, 183 | dataGroups: mockDataGroups 184 | }]); 185 | }, 1000); 186 | }); 187 | }); 188 | 189 | } 190 | }; -------------------------------------------------------------------------------- /src/view/data/dataGroup.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 241 | -------------------------------------------------------------------------------- /src/view/anth/auth.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 274 | -------------------------------------------------------------------------------- /src/view/data/dataDict.vue: -------------------------------------------------------------------------------- 1 | 102 | 103 | 300 | -------------------------------------------------------------------------------- /src/view/home.vue: -------------------------------------------------------------------------------- 1 | 84 | 85 | 211 | 212 | 340 | -------------------------------------------------------------------------------- /src/view/user/user.vue: -------------------------------------------------------------------------------- 1 | 117 | 118 | 305 | -------------------------------------------------------------------------------- /src/view/anth/menu.vue: -------------------------------------------------------------------------------- 1 | 110 | 111 | 300 | -------------------------------------------------------------------------------- /src/view/user/role.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 321 | --------------------------------------------------------------------------------