├── static └── .gitkeep ├── .eslintignore ├── src ├── assets │ ├── css │ │ ├── index.scss │ │ ├── them.scss │ │ └── custom.scss │ └── img │ │ └── element-ui.svg ├── store │ ├── index.js │ ├── mutation-types.js │ └── modules │ │ └── common.js ├── page │ ├── 404.vue │ ├── menu1 │ │ ├── sub1.vue │ │ └── sub2.vue │ ├── login.vue │ ├── menu2 │ │ └── sub1.vue │ └── home.vue ├── api │ └── common.js ├── App.vue ├── components │ └── common │ │ └── pagination.vue ├── main.js ├── router │ └── index.js ├── utils │ └── utils.js └── config │ └── index.js ├── favicon.ico ├── config ├── prod.env.js ├── dev.env.js └── index.js ├── .editorconfig ├── .gitignore ├── .babelrc ├── .postcssrc.js ├── index.html ├── README.md ├── package.json └── .eslintrc.js /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | static 2 | config 3 | -------------------------------------------------------------------------------- /src/assets/css/index.scss: -------------------------------------------------------------------------------- 1 | @import "./custom.scss"; 2 | @import "./them.scss"; -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrKaKaluote/element-admin/HEAD/favicon.ico -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/css/them.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 定义基本的主题颜色 3 | * 4 | */ 5 | $baseColor: #409EFF; 6 | $borderColor: #717171; 7 | $globalColor: #545c64; 8 | $globalBgColor: #293038; -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import common from './modules/common'; 4 | 5 | Vue.use(Vuex); 6 | 7 | const store = new Vuex.Store({ 8 | modules: { 9 | common 10 | } 11 | }); 12 | 13 | export default store -------------------------------------------------------------------------------- /src/page/404.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | //user 2 | export const SET_USERNAME = 'SET_USERNAME' 3 | export const SET_PASSWORD = 'SET_PASSWORD' 4 | export const SET_TREEDTA = 'SET_TREEDTA' 5 | export const SET_TOKEN = 'SET_TOKEN' 6 | 7 | 8 | 9 | export const SET_TABDATA = 'SET_TABDATA' 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /src/api/common.js: -------------------------------------------------------------------------------- 1 | import {fetch, fetchapi, baseUrl} from 'config/index.js' 2 | /** 3 | * 会员登陆 4 | * @param params 5 | * @returns {*} 6 | */ 7 | export function loginUserNo(params) { 8 | return fetch(`${baseUrl}/api/declare/login?userName=${params.userName}&password=${params.password}`, params) 9 | } -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | my-project 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # element-admin 2 | > A simple project of admin 3 | 4 | ## Build Setup 5 | 6 | ``` bash 7 | # get code 8 | pull all code 9 | 10 | # install dependencies 11 | npm install or yarn or cnpm insall 12 | 13 | # start project 14 | npm run dev 15 | ``` 16 | 17 | ## 说明 18 | 本项目集成了axios、vue-router、vuex、v-charts,是一个完善的后台管理系统框架;其中包括数据交互配置、路有权限配置、状态管理配置都已经配置完善,并且还在处于不断优化的阶段。 19 | 需要快速搭建项目开发的,可以直接采用本框架,或者参考本项目搭建简化版本项目架构,初始登录密码任意输入,点击登录即可,需要者可放心使用。 20 | 权限配置写在home.vue文件里 -------------------------------------------------------------------------------- /src/assets/css/custom.scss: -------------------------------------------------------------------------------- 1 | @import "./them.scss"; 2 | body{ 3 | overflow: hidden !important; 4 | } 5 | .el-menu-vertical-demo{ 6 | background-color: $globalBgColor !important; 7 | width: 180px; 8 | } 9 | .el-menu-item, .el-submenu__title{ 10 | height: 42px; 11 | line-height: 42px; 12 | border-top: 1px solid $borderColor; 13 | } 14 | .el-submenu .el-menu-item{ 15 | height: 42px; 16 | line-height: 42px; 17 | background-color: $globalBgColor !important; 18 | text-align: center; 19 | } 20 | .el-menu-item.is-active { 21 | color: #ffffff; 22 | background-color: $baseColor !important; 23 | } 24 | .menu-expanded a { 25 | text-decoration: none; 26 | } 27 | .menu-expanded .router-link-exact-active{ 28 | text-decoration: none; 29 | } 30 | .content-container { 31 | padding: 0px !important; 32 | padding-top: 0 !important; 33 | } 34 | .el-breadcrumb__inner{ 35 | color: #fff !important; 36 | } 37 | .el-submenu .el-menu-item{ 38 | min-width: 180px; 39 | } -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 13 | 14 | 17 | 18 | 56 | -------------------------------------------------------------------------------- /src/components/common/pagination.vue: -------------------------------------------------------------------------------- 1 | 14 | 36 | 37 | -------------------------------------------------------------------------------- /src/store/modules/common.js: -------------------------------------------------------------------------------- 1 | import * as types from '../mutation-types.js' 2 | 3 | //全局状态 4 | const state = { 5 | username: '', 6 | password: '', 7 | tabData: [], 8 | treeData: [], 9 | token: '' 10 | } 11 | 12 | //getters 13 | const getters = { 14 | username: state => { 15 | return state.username 16 | }, 17 | password: state => { 18 | return state.password 19 | }, 20 | tabData: state => { 21 | return state.tabData 22 | }, 23 | treeData: state => { 24 | return state.treeData 25 | }, 26 | token: state => { 27 | return state.token 28 | }, 29 | } 30 | 31 | const mutations = { 32 | [types.SET_USERNAME] (state, username) { 33 | state.username = username 34 | }, 35 | [types.SET_PASSWORD] (state, password) { 36 | state.password = password 37 | }, 38 | [types.SET_TABDATA](state, tabData) { 39 | state.tabData = tabData 40 | }, 41 | [types.SET_TREEDTA](state, treeData) { 42 | state.treeData = treeData 43 | }, 44 | [types.SET_TOKEN](state, token) { 45 | state.token = token 46 | } 47 | } 48 | 49 | export default { 50 | state, 51 | mutations, 52 | getters 53 | } -------------------------------------------------------------------------------- /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 Vue from 'vue'; 4 | import store from './store'; 5 | import ElementUI from 'element-ui'; 6 | import 'element-ui/lib/theme-chalk/index.css'; 7 | import Router from 'vue-router'; 8 | import App from './App.vue'; 9 | import 'font-awesome/css/font-awesome.min.css'; 10 | import router from "./router"; 11 | import VCharts from 'v-charts' 12 | import Directives from 'g-directives' 13 | 14 | Vue.use(ElementUI); 15 | Vue.use(Router); 16 | Vue.use(VCharts); 17 | Vue.use(Directives); 18 | 19 | 20 | Vue.config.productionTip = false 21 | /** 22 | * 判断当前是否登录,未登录不能跳转路由 23 | * 防止未登录状态下直接输入路由跳转 24 | */ 25 | /* eslint-disable no-new */ 26 | router.beforeEach((to, from, next) => { 27 | if (to.path == '/login') { 28 | sessionStorage.removeItem('user'); 29 | } 30 | let user = JSON.parse(sessionStorage.getItem('user')); 31 | if (!user && to.path != '/login') { 32 | next({ 33 | path: '/login' 34 | }); 35 | } else { 36 | next(); 37 | } 38 | }); 39 | 40 | // 引入路由 41 | new Vue({ 42 | el: '#app', 43 | store, 44 | router, // 注入到根实例中 45 | render: h => h(App) 46 | }); 47 | -------------------------------------------------------------------------------- /src/page/menu1/sub1.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 44 | 45 | 47 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue" 2 | import VueRouter from "vue-router" 3 | 4 | // 引入组件 5 | 6 | import login from '../page/login.vue' 7 | import home from '../page/home.vue' 8 | import notFound from '../page/404.vue' 9 | import sub11 from '../page/menu1/sub1.vue' 10 | import sub12 from '../page/menu1/sub2.vue' 11 | import sub21 from '../page/menu2/sub1.vue' 12 | // 要告诉 vue 使用 vueRouter 13 | Vue.use(VueRouter); 14 | 15 | let routes = [ 16 | { 17 | path: "/", 18 | redirect: '/login', 19 | hidden: true 20 | }, 21 | { 22 | path: '/login', 23 | component: login, 24 | name: '', 25 | hidden: true 26 | }, 27 | { 28 | path: '/404', 29 | component: notFound, 30 | name: '', 31 | hidden: true 32 | }, 33 | { 34 | path: '/menu1', 35 | component: home, 36 | name: '菜單一', 37 | iconCls: 'el-icon-message', //图标样式class 38 | children: [ 39 | { 40 | path: 'sub1', 41 | component: sub11, 42 | name: '子菜單一' 43 | }, 44 | { 45 | path: 'sub2', 46 | component: sub12, 47 | name: '子菜單二' 48 | } 49 | ] 50 | }, 51 | { 52 | path: '/menu2', 53 | component: home, 54 | name: '菜單二', 55 | iconCls: 'el-icon-message', 56 | children: [ 57 | { 58 | path: 'sub1', 59 | component: sub21, 60 | name: '配置管理' 61 | } 62 | ] 63 | } 64 | ]; 65 | var router = new VueRouter({ 66 | routes 67 | }) 68 | export default router; -------------------------------------------------------------------------------- /src/assets/img/element-ui.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description:各工具类方法 3 | * @Autor: GaoSong 4 | * @Date: 2021-01-02 13:36:30 5 | * @LastEditors: GaoSong👉😜👈 6 | * @LastEditTime: 2021-01-10 17:42:23 7 | */ 8 | 9 | /** 10 | * @description: 判断是否是某种类型的数据 11 | * @param {*} null 12 | * @return {Object} _type 13 | * _typeof.isNumeric(num) 14 | */ 15 | export const _typeof = (() => { 16 | var _obj = { 17 | isNumeric: 'Number', 18 | isBoolean: 'Boolean', 19 | isString: 'String', 20 | isNull: 'Null', 21 | isUndefined: 'Undefined', 22 | isSymbol: 'Symbol', 23 | isPlainObject: 'Object', 24 | isArray: 'Array', 25 | isRegExp: 'RegExp', 26 | isDate: 'Date', 27 | isFunction: 'Function', 28 | isWindow: 'Window' 29 | } 30 | 31 | var _toString = _obj.toString 32 | 33 | var _type = {} 34 | for (var key in _obj) { 35 | // eslint-disable-next-line no-prototype-builtins 36 | if (!_obj.hasOwnProperty(key)) break 37 | _type[key] = (function() { 38 | var reg = new RegExp('^\\[object ' + _obj[key] + '\\]$') 39 | return function anonymous(val) { 40 | return reg.test(_toString.call(val)) 41 | } 42 | })() 43 | } 44 | return _type 45 | })() 46 | 47 | 48 | /** 节流函数 */ 49 | export function throttle(fun, wait, ...args) { 50 | let timer = null; let remainingTime = 0; let preTime = 0 51 | if (!wait) wait = 500 52 | return function proxy() { 53 | const nowTime = new Date() 54 | remainingTime = wait - (nowTime - preTime) 55 | if (remainingTime <= 0) { 56 | clearTimeout(timer) 57 | timer = null 58 | preTime = new Date() 59 | fun.call(this, ...arguments, ...args) 60 | } else if (!timer) { 61 | timer = setTimeout(() => { 62 | clearTimeout(timer) 63 | timer = null 64 | preTime = new Date() 65 | fun.call(this, ...arguments, ...args) 66 | }, remainingTime) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import Cookies from 'js-cookie' 3 | // 请求数据正常状态 4 | export const ERR_OK = 8200 5 | // 页面渲染延时 6 | export const TIME_QUERY = 500 7 | 8 | export const imageCDN = process.env.IMAGE_CDN 9 | export const baseUrl = '' 10 | export const baseImgUrl = process.env.BASE_URL 11 | 12 | // 请求超时时间 13 | axios.defaults.timeout = 5000 14 | 15 | // respone拦截器 16 | axios.interceptors.response.use( 17 | response => { 18 | /** 19 | * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页 20 | * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中 21 | */ 22 | let {data} = response 23 | console.log(data.message) 24 | if (data.message === 'token failure!') { 25 | localStorage.removeItem('token') 26 | localStorage.removeItem('UserName') 27 | localStorage.removeItem('Password') 28 | localStorage.removeItem('token') 29 | window.location.href = '#/' 30 | } else { 31 | return Promise.resolve(response) 32 | } 33 | // 50014:Token 过期了 50012:其他客户端登录了 50008:非法的token 34 | }, 35 | error => { 36 | console.log('err' + error)// for debug 37 | return Promise.reject(error) 38 | } 39 | ) 40 | 41 | export function fetch(requestUrl, params = '') { 42 | // const token = Cookies.get('token') === undefined ? '11111' : Cookies.get('token') 43 | const token = localStorage.getItem('token') === null ? '' : localStorage.getItem('token') 44 | return axios({ 45 | url: requestUrl, 46 | method: 'post', 47 | data: { 48 | 'body': params 49 | }, 50 | headers: { 51 | 'Content-Type': 'application/json;charset=UTF-8', 52 | 'Authorization': token 53 | } 54 | }) 55 | } 56 | 57 | export function fetchapi(requestUrl, params = '') { 58 | // const token = Cookies.get('token') === undefined ? '11111' : Cookies.get('token') 59 | const token = localStorage.getItem('token') === null ? '' : localStorage.getItem('token') 60 | return axios({ 61 | url: `${baseUrl}api/standardCheck`, 62 | method: 'post', 63 | data: { 64 | 'requestId': 'xxxxxx-xxxxxx-xxxxx-xxxxx', 65 | 'apiKey': 'highstore', 66 | 'uri': requestUrl, 67 | 'lang': 'zh-cn', 68 | 'timeZone': '+8:00', 69 | 'sign': ' xxxxxxxxxxxxxxxxxxxxxx', 70 | 'body': params 71 | }, 72 | headers: { 73 | 'Content-Type': 'application/json;charset=UTF-8', 74 | 'Authorization': token 75 | } 76 | }) 77 | } 78 | 79 | 80 | export function getCookies(params) { 81 | return Cookies.get(params) || '' 82 | } 83 | 84 | export function setCookies(memberNo, openid, token) { 85 | Cookies.set('memberNo', memberNo) 86 | Cookies.set('openid', openid) 87 | Cookies.set('token', token) 88 | } 89 | 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-project", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "gaosong ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.17.1", 14 | "echarts": "^4.2.0-rc.2", 15 | "element-ui": "^2.1.0", 16 | "font-awesome": "^4.7.0", 17 | "g-directives": "^1.0.0", 18 | "js-cookie": "^2.2.0", 19 | "v-charts": "^1.19.0", 20 | "vue": "^2.5.2", 21 | "vue-router": "^3.0.1", 22 | "vuex": "^3.0.1" 23 | }, 24 | "devDependencies": { 25 | "@vue/cli-plugin-eslint": "^3.3.0", 26 | "@vue/eslint-config-standard": "^4.0.0", 27 | "autoprefixer": "^7.1.2", 28 | "axios": "^0.17.1", 29 | "babel-core": "^6.22.1", 30 | "babel-eslint": "^10.1.0", 31 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 32 | "babel-loader": "^7.1.1", 33 | "babel-plugin-syntax-jsx": "^6.18.0", 34 | "babel-plugin-transform-runtime": "^6.22.0", 35 | "babel-plugin-transform-vue-jsx": "^3.5.0", 36 | "babel-preset-env": "^1.3.2", 37 | "babel-preset-stage-2": "^6.22.0", 38 | "chalk": "^2.0.1", 39 | "copy-webpack-plugin": "^4.0.1", 40 | "css-loader": "^0.28.0", 41 | "eslint": "^7.17.0", 42 | "eslint-friendly-formatter": "4.0.1", 43 | "eslint-loader": "2.0.0", 44 | "eslint-plugin-html": "^6.0.3", 45 | "eslint-plugin-import": "^2.20.2", 46 | "eslint-plugin-vue": "4.7.1", 47 | "extract-text-webpack-plugin": "^3.0.0", 48 | "file-loader": "^1.1.4", 49 | "friendly-errors-webpack-plugin": "^1.6.1", 50 | "html-webpack-plugin": "^2.30.1", 51 | "node-notifier": "^5.1.2", 52 | "node-sass": "^4.5.3", 53 | "optimize-css-assets-webpack-plugin": "^3.2.0", 54 | "ora": "^1.2.0", 55 | "portfinder": "^1.0.13", 56 | "postcss-import": "^11.0.0", 57 | "postcss-loader": "^2.0.8", 58 | "postcss-url": "^7.2.1", 59 | "rimraf": "^2.6.0", 60 | "sass-loader": "^6.0.6", 61 | "semver": "^5.3.0", 62 | "shelljs": "^0.7.6", 63 | "uglifyjs-webpack-plugin": "^1.1.1", 64 | "url-loader": "^0.5.8", 65 | "vue-loader": "^13.3.0", 66 | "vue-style-loader": "^3.0.1", 67 | "vue-template-compiler": "^2.5.2", 68 | "webpack": "^3.6.0", 69 | "webpack-bundle-analyzer": "^2.9.0", 70 | "webpack-dev-server": "^2.9.1", 71 | "webpack-merge": "^4.1.0" 72 | }, 73 | "engines": { 74 | "node": ">= 6.0.0", 75 | "npm": ">= 3.0.0" 76 | }, 77 | "browserslist": [ 78 | "> 1%", 79 | "last 2 versions", 80 | "not ie <= 8" 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Autor: GaoSong 4 | * @Date: 2021-01-02 12:29:38 5 | * @LastEditors: GaoSong👉😜👈 6 | * @LastEditTime: 2021-01-02 14:49:22 7 | */ 8 | 'use strict' 9 | // Template version: 1.3.1 10 | // see http://vuejs-templates.github.io/webpack for documentation. 11 | 12 | const path = require('path') 13 | 14 | function resolve(dir) { 15 | return path.join(__dirname, dir) 16 | } 17 | 18 | module.exports = { 19 | lintOnSave: true, 20 | chainWebpack: (config) => { 21 | config.resolve.alias 22 | .set('@', resolve('src')) 23 | }, 24 | dev: { 25 | // Paths 26 | assetsSubDirectory: 'static', 27 | assetsPublicPath: '/', 28 | proxyTable: { 29 | '/api/': { 30 | target: '', 31 | changeOrigin: true 32 | } 33 | }, 34 | 35 | // Various Dev Server settings 36 | host: 'localhost', // can be overwritten by process.env.HOST 37 | port: 8089, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 38 | autoOpenBrowser: true, 39 | errorOverlay: true, 40 | notifyOnErrors: true, 41 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 42 | 43 | /** 44 | * Source Maps 45 | */ 46 | 47 | // https://webpack.js.org/configuration/devtool/#development 48 | devtool: 'cheap-module-eval-source-map', 49 | 50 | // If you have problems debugging vue-files in devtools, 51 | // set this to false - it *may* help 52 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 53 | cacheBusting: true, 54 | 55 | cssSourceMap: true 56 | }, 57 | 58 | build: { 59 | // Template for index.html 60 | index: path.resolve(__dirname, '../dist/index.html'), 61 | 62 | // Paths 63 | assetsRoot: path.resolve(__dirname, '../dist'), 64 | assetsSubDirectory: 'static', 65 | assetsPublicPath: '/', 66 | 67 | /** 68 | * Source Maps 69 | */ 70 | 71 | productionSourceMap: true, 72 | // https://webpack.js.org/configuration/devtool/#production 73 | devtool: '#source-map', 74 | 75 | // Gzip off by default as many popular static hosts such as 76 | // Surge or Netlify already gzip all static assets for you. 77 | // Before setting to `true`, make sure to: 78 | // npm install --save-dev compression-webpack-plugin 79 | productionGzip: false, 80 | productionGzipExtensions: ['js', 'css'], 81 | 82 | // Run the build command with an extra argument to 83 | // View the bundle analyzer report after build finishes: 84 | // `npm run build --report` 85 | // Set to `true` or `false` to always turn it on or off 86 | bundleAnalyzerReport: process.env.npm_config_report 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/page/login.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 124 | 125 | 152 | -------------------------------------------------------------------------------- /src/page/menu2/sub1.vue: -------------------------------------------------------------------------------- 1 | 90 | 91 | 189 | 190 | 215 | -------------------------------------------------------------------------------- /src/page/menu1/sub2.vue: -------------------------------------------------------------------------------- 1 | 151 | 231 | 232 | 253 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 默认情况下,ESLint会在所有父级组件中寻找配置文件,一直到根目录。ESLint一旦发现配置文件中有 "root": true,它就会停止在父级目录中寻找。 3 | root: true, 4 | parserOptions: { 5 | // 对Babel解析器的包装使其与 ESLint 兼容。 6 | parser: 'babel-eslint', 7 | // 代码是 ECMAScript 模块 8 | sourceType: 'module' 9 | }, 10 | env: { 11 | // 预定义的全局变量,这里是浏览器环境 12 | browser: true, 13 | node: true, 14 | es6: true, 15 | }, 16 | // 扩展风格 17 | extends: ['plugin:vue/recommended', 'eslint:recommended'], 18 | // 规则的细节请到ESLint官方网站查看http://eslint.org/docs/rules/ 19 | rules: { 20 | "vue/max-attributes-per-line": [2, { 21 | "singleline": 10, 22 | "multiline": { 23 | "max": 1, 24 | "allowFirstLine": false 25 | } 26 | }], 27 | "no-import-assign" : 'off', 28 | "no-async-promise-executor": 'off', 29 | "no-dupe-else-if": 'off', 30 | "no-misleading-character-class": 'off', 31 | "no-async-promise-executor": 'off', 32 | "no-setter-return": 'off', 33 | "no-useless-catch": 'off', 34 | "vue/name-property-casing": ["error", "PascalCase"], 35 | // 定义对象的set存取器属性时,强制定义get 36 | 'accessor-pairs': 2, 37 | 'arrow-spacing': [2, { 38 | 'before': true, 39 | 'after': true 40 | }], 41 | // 禁止或强制在单行代码块中使用空格 42 | 'block-spacing': [2, 'always'], 43 | // 强制使用一致的缩进 第二个参数为 "tab" 时,会使用tab 44 | 'brace-style': [2, '1tbs', { 45 | 'allowSingleLine': true 46 | }], 47 | // 双峰驼命名格式 48 | 'camelcase': [0, { 49 | 'properties': 'always' 50 | }], 51 | // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号 52 | 'comma-dangle': [2, 'never'], 53 | // 控制逗号前后的空格 54 | 'comma-spacing': [2, { 55 | 'before': false, 56 | 'after': true 57 | }], 58 | // 控制逗号在行尾出现还是在行首出现 (默认行尾) 59 | 'comma-style': [2, 'last'], 60 | // 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示 61 | 'constructor-super': 2, 62 | // 强制所有控制语句使用一致的括号风格 63 | 'curly': [2, 'multi-line'], 64 | // 强制object.key 中 . 的位置,参数: 65 | // property,'.'号应与属性在同一行 66 | // object, '.' 号应与对象名在同一行 67 | 'dot-location': [2, 'property'], 68 | // 文件末尾强制换行 69 | 'eol-last': 2, 70 | // 使用 === 替代 == allow-null允许null和undefined== 71 | "eqeqeq": [2, "allow-null"], 72 | // 强制 generator 函数中 * 号周围使用一致的空格 73 | 'generator-star-spacing': [2, { 74 | 'before': true, 75 | 'after': true 76 | }], 77 | // 要求回调函数中有容错处理 78 | 'handle-callback-err': [2, '^(err|error)$'], 79 | 'indent': [2, 2, { 80 | 'SwitchCase': 1 81 | }], 82 | // 强制在 JSX 属性中一致地使用双引号或单引号 83 | 'jsx-quotes': [2, 'prefer-single'], 84 | // 强制在对象字面量的属性中键和值之间使用一致的间距 85 | 'key-spacing': [2, { 86 | 'beforeColon': false, 87 | 'afterColon': true 88 | }], 89 | // 强制在关键字前后使用一致的空格 90 | 'keyword-spacing': [2, { 91 | 'before': true, 92 | 'after': true 93 | }], 94 | // 要求构造函数首字母大写 95 | 'new-cap': [2, { 96 | 'newIsCap': true, 97 | 'capIsNew': false 98 | }], 99 | // 要求调用无参构造函数时有圆括号 100 | 'new-parens': 2, 101 | // 禁止在没有类型检查操作符的情况下与 null 进行比较 102 | 'no-eq-null': 0, 103 | // 禁止使用 Array 构造函数 104 | 'no-array-constructor': 2, 105 | // 禁用 arguments.caller 或 arguments.callee 106 | 'no-caller': 2, 107 | // 禁用 console 108 | 'no-console': 0, 109 | // 禁止修改类声明的变量 110 | 'no-class-assign': 2, 111 | // 禁止条件表达式中出现赋值操作符 112 | 'no-cond-assign': 2, 113 | // 禁止修改 const 声明的变量 114 | 'no-const-assign': 2, 115 | // 禁止在正则表达式中使用控制字符 :new RegExp("\x1f") 116 | 'no-control-regex': 0, 117 | // 禁止删除变量 118 | 'no-delete-var': 2, 119 | // 禁止 function 定义中出现重名参数 120 | 'no-dupe-args': 2, 121 | // 禁止类成员中出现重复的名称 122 | 'no-dupe-class-members': 2, 123 | // 禁止对象字面量中出现重复的 key 124 | 'no-dupe-keys': 2, 125 | // 禁止重复的 case 标签 126 | 'no-duplicate-case': 2, 127 | // 禁止在正则表达式中使用空字符集 (/^abc[]/) 128 | 'no-empty-character-class': 2, 129 | // 禁止使用空解构模式no-empty-pattern 130 | 'no-empty-pattern': 2, 131 | // 禁用 eval(),由于多处地方使用,暂不开启 132 | 'no-eval': 0, 133 | // 禁止对 catch 子句的参数重新赋值 134 | 'no-ex-assign': 2, 135 | // 禁止扩展原生类型 136 | 'no-extend-native': 2, 137 | // 禁止不必要的 .bind() 调用 138 | 'no-extra-bind': 2, 139 | // 禁止不必要的布尔转换 140 | 'no-extra-boolean-cast': 2, 141 | // 禁止不必要的括号 //(a * b) + c;//报错 142 | 'no-extra-parens': [2, 'functions'], 143 | // 禁止 case 语句落空 144 | 'no-fallthrough': 2, 145 | // 禁止数字字面量中使用前导和末尾小数点 146 | 'no-floating-decimal': 2, 147 | // 禁止对 function 声明重新赋值 148 | 'no-func-assign': 2, 149 | // 禁止使用类似 eval() 的方法 150 | 'no-implied-eval': 2, 151 | // 禁止在嵌套的块中出现 function 或 var 声明 152 | 'no-inner-declarations': [2, 'functions'], 153 | // 禁止 RegExp 构造函数中无效的正则表达式字符串 154 | 'no-invalid-regexp': 2, 155 | // 禁止在字符串和注释之外不规则的空白 156 | 'no-irregular-whitespace': 2, 157 | // 禁用 __iterator__ 属性 158 | 'no-iterator': 2, 159 | // 不允许标签与变量同名 160 | 'no-label-var': 2, 161 | // 禁用标签语句 162 | 'no-labels': [2, { 163 | 'allowLoop': false, 164 | 'allowSwitch': false 165 | }], 166 | // 禁用不必要的嵌套块 167 | 'no-lone-blocks': 2, 168 | // 不允许空格和 tab 混合缩进 169 | 'no-mixed-spaces-and-tabs': 2, 170 | // 禁止使用多个空格 171 | 'no-multi-spaces': 2, 172 | // 禁止使用多行字符串,在 JavaScript 中,可以在新行之前使用斜线创建多行字符串 173 | 'no-multi-str': 2, 174 | // 不允许多个空行 175 | 'no-multiple-empty-lines': [2, { 176 | 'max': 1 177 | }], 178 | // 禁止对原生对象赋值 179 | 'no-native-reassign': 2, 180 | // 禁止在 in 表达式中出现否定的左操作数 181 | 'no-negated-in-lhs': 2, 182 | // 禁止使用 Object 的构造函数 183 | 'no-new-object': 2, 184 | // 禁止调用 require 时使用 new 操作符 185 | 'no-new-require': 2, 186 | // 禁止 Symbol 的构造函数 187 | 'no-new-symbol': 2, 188 | // 禁止对 String,Number 和 Boolean 使用 new 操作符 189 | 'no-new-wrappers': 2, 190 | // 禁止把全局对象 (Math 和 JSON) 作为函数调用 错误:var math = Math(); 191 | 'no-obj-calls': 2, 192 | // 禁用八进制字面量 193 | 'no-octal': 2, 194 | // 禁止在字符串中使用八进制转义序列 195 | 'no-octal-escape': 2, 196 | // 禁止对 __dirname 和 __filename进行字符串连接 197 | 'no-path-concat': 2, 198 | // 禁用 __proto__ 属性 199 | 'no-proto': 2, 200 | // 禁止使用 var 多次声明同一变量 201 | 'no-redeclare': 2, 202 | // 禁止正则表达式字面量中出现多个空格 203 | 'no-regex-spaces': 2, 204 | // 禁用指定的通过 require 加载的模块 205 | 'no-return-assign': [2, 'except-parens'], 206 | // 禁止自我赋值 207 | 'no-self-assign': 2, 208 | // 禁止自身比较 209 | 'no-self-compare': 2, 210 | // 禁用逗号操作符 211 | 'no-sequences': 2, 212 | // 禁止覆盖受限制的标识符 213 | 'no-shadow-restricted-names': 2, 214 | // 禁止 function 标识符和括号之间出现空格 215 | 'no-spaced-func': 2, 216 | // 禁用稀疏数组 217 | 'no-sparse-arrays': 2, 218 | // 禁止在构造函数中,在调用 super() 之前使用 this 或 super 219 | 'no-this-before-super': 2, 220 | // 禁止抛出非异常字面量 221 | 'no-throw-literal': 0, 222 | // 禁用行尾空格 223 | 'no-trailing-spaces': 2, 224 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到 225 | 'no-undef': 2, 226 | // 禁止将变量初始化为 undefined 227 | 'no-undef-init': 2, 228 | // 禁止出现令人困惑的多行表达式 229 | 'no-unexpected-multiline': 2, 230 | // 禁用一成不变的循环条件 231 | 'no-unmodified-loop-condition': 2, 232 | // 禁止可以在有更简单的可替代的表达式时使用三元操作符 233 | 'no-unneeded-ternary': [2, { 234 | 'defaultAssignment': false 235 | }], 236 | // 禁止在return、throw、continue 和 break语句之后出现不可达代码 237 | 'no-unreachable': 2, 238 | 'no-unsafe-finally': 2, 239 | // 禁止出现未使用过的变量 240 | 'no-unused-vars': [2, { 241 | 'vars': 'all', 242 | 'args': 'none' 243 | }], 244 | // 禁止不必要的 .call() 和 .apply() 245 | 'no-useless-call': 2, 246 | // 禁止不必要的计算性能键对象的文字 247 | 'no-useless-computed-key': 2, 248 | 'no-useless-constructor': 2, 249 | // 禁用不必要的转义字符 250 | 'no-useless-escape': 0, 251 | // 禁止属性前有空白 252 | 'no-whitespace-before-property': 2, 253 | // 禁用 with 语句 254 | 'no-with': 2, 255 | // 强制函数中的变量要么一起声明要么分开声明 256 | 'one-var': [2, { 257 | 'initialized': 'never' 258 | }], 259 | // 强制操作符使用一致的换行符 260 | 'operator-linebreak': [2, 'after', { 261 | 'overrides': { 262 | '?': 'before', 263 | ':': 'before' 264 | } 265 | }], 266 | // 要求或禁止块内填充 267 | 'padded-blocks': [2, 'never'], 268 | // 强制使用一致的反勾号、双引号或单引号 269 | 'quotes': [2, 'single', { 270 | 'avoidEscape': true, 271 | 'allowTemplateLiterals': true 272 | }], 273 | // 要求或禁止使用分号而不是 ASI(这个才是控制行尾部分号的,) 274 | 'semi': [2, 'never'], 275 | // 强制分号之前和之后使用一致的空格 276 | 'semi-spacing': [2, { 277 | 'before': false, 278 | 'after': true 279 | }], 280 | // 强制在块之前使用一致的空格 281 | 'space-before-blocks': [2, 'always'], 282 | // 强制在 function的左括号之前使用一致的空格 283 | 'space-before-function-paren': [2, 'never'], 284 | // 强制在圆括号内使用一致的空格 285 | 'space-in-parens': [2, 'never'], 286 | // 要求操作符周围有空格 287 | 'space-infix-ops': 2, 288 | // 强制在一元操作符前后使用一致的空格 289 | 'space-unary-ops': [2, { 290 | 'words': true, 291 | 'nonwords': false 292 | }], 293 | // 强制在注释中 // 或 /* 使用一致的空格 294 | 'spaced-comment': [2, 'always', { 295 | 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] 296 | }], 297 | // 要求或禁止模板字符串中的嵌入表达式周围空格的使用 298 | 'template-curly-spacing': [2, 'never'], 299 | // 要求使用 isNaN() 检查 NaN 300 | 'use-isnan': 2, 301 | // typeof foo === "undefimed" 错误 302 | 'valid-typeof': 2, 303 | // 要求 IIFE 使用括号括起来 304 | 'wrap-iife': [2, 'any'], 305 | // 强制在 yield* 表达式中 * 周围使用空格 306 | 'yield-star-spacing': [2, 'both'], 307 | // 要求或禁止 “Yoda” 条件 308 | 'yoda': [2, 'never'], 309 | // 要求使用 const 声明那些声明后不再被修改的变量 310 | 'prefer-const': 2, 311 | // 是否允许debugger 312 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 313 | // 强制在花括号中使用一致的空格 314 | 'object-curly-spacing': [2, 'always', { 315 | objectsInObjects: false 316 | }], 317 | // 指定数组的元素之间要以空格隔开(, 后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格 318 | 'array-bracket-spacing': [2, 'never'] 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /src/page/home.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 173 | 174 | 316 | --------------------------------------------------------------------------------