├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── public ├── index.html └── logo.ico ├── src ├── App.vue ├── assets │ ├── 404_images │ │ ├── 404.png │ │ └── 404_cloud.png │ └── logo.ico ├── components │ ├── Dialog │ │ └── index.vue │ ├── Pagination │ │ └── index.vue │ ├── PowerWrapper │ │ └── index.vue │ ├── SvgIcon │ │ └── index.vue │ └── UploadImg │ │ ├── UploadImg.vue │ │ └── lib │ │ └── crypto1 │ │ ├── crypto │ │ ├── crypto-min.js │ │ └── crypto.js │ │ ├── hmac │ │ ├── hmac-min.js │ │ └── hmac.js │ │ └── sha1 │ │ ├── sha1-min.js │ │ └── sha1.js ├── icons │ ├── index.js │ └── svg │ │ ├── suger.svg │ │ └── yueliang.svg ├── main.js ├── permission.js ├── router │ ├── asyncRoutes.js │ └── index.js ├── services │ └── user.js ├── store.js ├── styles │ ├── base.less │ ├── element-ui.less │ ├── iconfont.less │ └── index.less ├── utils │ ├── auth.js │ ├── get-page-title.js │ ├── request.js │ └── utils.js └── views │ ├── Layout │ ├── SidebarItem │ │ └── index.vue │ ├── appMain │ │ └── index.vue │ └── index.vue │ ├── Login.vue │ ├── UserRelation │ └── UserRelation.vue │ ├── error-page │ └── 404.vue │ ├── navigatorOne │ ├── itemOne │ │ └── itemOne.vue │ ├── itemThree │ │ └── itemThree.vue │ └── itemTwo │ │ └── itemTwo.vue │ └── navigatorTwo │ ├── CommonInvite │ └── index.vue │ ├── itemFour │ └── itemFour.vue │ ├── itemOne │ └── itemOne.vue │ ├── itemThree │ └── itemThree.vue │ └── itemTwo │ └── itemTwo.vue └── vue.config.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | 'plugin:vue/essential', 9 | // '@vue/airbnb', 10 | ], 11 | rules: { 12 | 'no-console': 0, 13 | 'linebreak-style': 0, 14 | 'comma-dangle':0, 15 | "indent": 0, 16 | "semi":0, 17 | "space-infix-ops":0, 18 | "no-mixed-operators":0, 19 | "no-trailing-spaces":0, 20 | "no-multi-spaces":0, 21 | "no-else-return": 0 22 | }, 23 | // parserOptions: { 24 | // parser: 'babel-eslint', 25 | // } 26 | }; 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | package-lock.json 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### vue-element-admin-template 2 | 3 | #### 包含权限管理 4 | 5 | ##### 登录 用户名 admin 密码 123 6 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-element-admin-template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.19.0", 12 | "core-js": "^3.3.2", 13 | "element-ui": "^2.12.0", 14 | "js-base64": "^2.5.1", 15 | "js-cookie": "^2.2.1", 16 | "less": "^3.10.3", 17 | "moment": "^2.24.0", 18 | "nprogress": "^0.2.0", 19 | "qrcode.vue": "^1.7.0", 20 | "qs": "^6.9.1", 21 | "vue": "^2.6.10", 22 | "vue-router": "^3.1.3", 23 | "vuex": "^3.1.2" 24 | }, 25 | "devDependencies": { 26 | "@vue/cli-plugin-babel": "^4.0.0", 27 | "@vue/cli-plugin-eslint": "^4.0.0", 28 | "@vue/cli-service": "^4.0.0", 29 | "babel-eslint": "^10.0.3", 30 | "eslint": "^5.16.0", 31 | "eslint-plugin-vue": "^5.0.0", 32 | "less-loader": "^5.0.0", 33 | "svg-sprite-loader": "^5.0.0", 34 | "vue-template-compiler": "^2.6.10" 35 | }, 36 | "eslintConfig": { 37 | "root": true, 38 | "env": { 39 | "node": true 40 | }, 41 | "extends": [ 42 | "plugin:vue/essential", 43 | "eslint:recommended" 44 | ], 45 | "rules": {}, 46 | "parserOptions": { 47 | "parser": "babel-eslint" 48 | } 49 | }, 50 | "postcss": { 51 | "plugins": { 52 | "autoprefixer": {} 53 | } 54 | }, 55 | "browserslist": [ 56 | "> 1%", 57 | "last 2 versions" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-admin-start 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tang-yue/vue-element-admin-template/715eb4a8d163ee169714d3cd91f191f48039472c/public/logo.ico -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 31 | -------------------------------------------------------------------------------- /src/assets/404_images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tang-yue/vue-element-admin-template/715eb4a8d163ee169714d3cd91f191f48039472c/src/assets/404_images/404.png -------------------------------------------------------------------------------- /src/assets/404_images/404_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tang-yue/vue-element-admin-template/715eb4a8d163ee169714d3cd91f191f48039472c/src/assets/404_images/404_cloud.png -------------------------------------------------------------------------------- /src/assets/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tang-yue/vue-element-admin-template/715eb4a8d163ee169714d3cd91f191f48039472c/src/assets/logo.ico -------------------------------------------------------------------------------- /src/components/Dialog/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 62 | 63 | -------------------------------------------------------------------------------- /src/components/Pagination/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 81 | 82 | 91 | -------------------------------------------------------------------------------- /src/components/PowerWrapper/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 27 | 28 | 31 | -------------------------------------------------------------------------------- /src/components/SvgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 25 | 26 | 42 | -------------------------------------------------------------------------------- /src/components/UploadImg/UploadImg.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 81 | 82 | 85 | -------------------------------------------------------------------------------- /src/components/UploadImg/lib/crypto1/crypto/crypto-min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto-JS v1.1.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";window.Crypto={};var a=Crypto.util={rotl:function(d,c){return(d<>>(32-c))},rotr:function(d,c){return(d<<(32-c))|(d>>>c)},endian:function(d){if(d.constructor==Number){return a.rotl(d,8)&16711935|a.rotl(d,24)&4278255360}for(var c=0;c0;d--){c.push(Math.floor(Math.random()*256))}return c},stringToBytes:function(e){var c=[];for(var d=0;d>>5]|=f.charCodeAt(g)<<(24-d%32)}return e},bytesToWords:function(d){var f=[];for(var e=0,c=0;e>>5]|=d[e]<<(24-c%32)}return f},wordsToBytes:function(e){var d=[];for(var c=0;c>>5]>>>(24-c%32))&255)}return d},bytesToHex:function(c){var e=[];for(var d=0;d>>4).toString(16));e.push((c[d]&15).toString(16))}return e.join("")},hexToBytes:function(e){var d=[];for(var f=0;f>>2));f=(d[e]&3)<<4;break;case 1:c.push(b.charAt(f|(d[e]>>>4)));f=(d[e]&15)<<2;break;case 2:c.push(b.charAt(f|(d[e]>>>6)));c.push(b.charAt(d[e]&63));f=-1}}if(f!=undefined&&f!=-1){c.push(b.charAt(f))}while(c.length%4!=0){c.push("=")}return c.join("")},base64ToBytes:function(d){if(typeof atob=="function"){return a.stringToBytes(atob(d))}d=d.replace(/[^A-Z0-9+\/]/ig,"");var c=[];for(var e=0;e>>4));break;case 2:c.push(((b.indexOf(d.charAt(e-1))&15)<<4)|(b.indexOf(d.charAt(e))>>>2));break;case 3:c.push(((b.indexOf(d.charAt(e-1))&3)<<6)|(b.indexOf(d.charAt(e))));break}}return c}};Crypto.mode={}})(); -------------------------------------------------------------------------------- /src/components/UploadImg/lib/crypto1/crypto/crypto.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Crypto-JS v1.1.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){ 8 | 9 | var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 10 | 11 | // Global Crypto object 12 | window.Crypto = {}; 13 | 14 | // Crypto utilities 15 | var util = Crypto.util = { 16 | 17 | // Bit-wise rotate left 18 | rotl: function (n, b) { 19 | return (n << b) | (n >>> (32 - b)); 20 | }, 21 | 22 | // Bit-wise rotate right 23 | rotr: function (n, b) { 24 | return (n << (32 - b)) | (n >>> b); 25 | }, 26 | 27 | // Swap big-endian to little-endian and vice versa 28 | endian: function (n) { 29 | 30 | // If number given, swap endian 31 | if (n.constructor === Number) { 32 | return util.rotl(n, 8) & 0x00FF00FF | 33 | util.rotl(n, 24) & 0xFF00FF00; 34 | } 35 | 36 | // Else, assume array and swap all items 37 | for (var i = 0; i < n.length; i++) 38 | n[i] = util.endian(n[i]); 39 | return n; 40 | 41 | }, 42 | 43 | // Generate an array of any length of random bytes 44 | randomBytes: function (n) { 45 | for (var bytes = []; n > 0; n--) 46 | bytes.push(Math.floor(Math.random() * 256)); 47 | return bytes; 48 | }, 49 | 50 | // Convert a string to a byte array 51 | stringToBytes: function (str) { 52 | var bytes = []; 53 | for (var i = 0; i < str.length; i++) 54 | bytes.push(str.charCodeAt(i)); 55 | return bytes; 56 | }, 57 | 58 | // Convert a byte array to a string 59 | bytesToString: function (bytes) { 60 | var str = []; 61 | for (var i = 0; i < bytes.length; i++) 62 | str.push(String.fromCharCode(bytes[i])); 63 | return str.join(""); 64 | }, 65 | 66 | // Convert a string to big-endian 32-bit words 67 | stringToWords: function (str) { 68 | var words = []; 69 | for (var c = 0, b = 0; c < str.length; c++, b += 8) 70 | words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32); 71 | return words; 72 | }, 73 | 74 | // Convert a byte array to big-endian 32-bits words 75 | bytesToWords: function (bytes) { 76 | var words = []; 77 | for (var i = 0, b = 0; i < bytes.length; i++, b += 8) 78 | words[b >>> 5] |= bytes[i] << (24 - b % 32); 79 | return words; 80 | }, 81 | 82 | // Convert big-endian 32-bit words to a byte array 83 | wordsToBytes: function (words) { 84 | var bytes = []; 85 | for (var b = 0; b < words.length * 32; b += 8) 86 | bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); 87 | return bytes; 88 | }, 89 | 90 | // Convert a byte array to a hex string 91 | bytesToHex: function (bytes) { 92 | var hex = []; 93 | for (var i = 0; i < bytes.length; i++) { 94 | hex.push((bytes[i] >>> 4).toString(16)); 95 | hex.push((bytes[i] & 0xF).toString(16)); 96 | } 97 | return hex.join(""); 98 | }, 99 | 100 | // Convert a hex string to a byte array 101 | hexToBytes: function (hex) { 102 | var bytes = []; 103 | for (var c = 0; c < hex.length; c += 2) 104 | bytes.push(parseInt(hex.substr(c, 2), 16)); 105 | return bytes; 106 | }, 107 | 108 | // Convert a byte array to a base-64 string 109 | bytesToBase64: function (bytes) { 110 | 111 | // Use browser-native function if it exists 112 | if (typeof btoa === "function") return btoa(util.bytesToString(bytes)); 113 | 114 | var base64 = [], 115 | overflow; 116 | 117 | for (var i = 0; i < bytes.length; i++) { 118 | // eslint-disable-next-line 119 | switch (i % 3) { 120 | case 0: 121 | base64.push(base64map.charAt(bytes[i] >>> 2)); 122 | overflow = (bytes[i] & 0x3) << 4; 123 | break; 124 | case 1: 125 | base64.push(base64map.charAt(overflow | (bytes[i] >>> 4))); 126 | overflow = (bytes[i] & 0xF) << 2; 127 | break; 128 | case 2: 129 | base64.push(base64map.charAt(overflow | (bytes[i] >>> 6))); 130 | base64.push(base64map.charAt(bytes[i] & 0x3F)); 131 | overflow = -1; 132 | } 133 | } 134 | 135 | // Encode overflow bits, if there are any 136 | if (overflow !== undefined && overflow !== -1) 137 | base64.push(base64map.charAt(overflow)); 138 | 139 | // Add padding 140 | while (base64.length % 4 !== 0) base64.push("="); 141 | 142 | return base64.join(""); 143 | 144 | }, 145 | 146 | // Convert a base-64 string to a byte array 147 | base64ToBytes: function (base64) { 148 | 149 | // Use browser-native function if it exists 150 | if (typeof atob === "function") return util.stringToBytes(atob(base64)); 151 | 152 | // Remove non-base-64 characters 153 | base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); 154 | 155 | var bytes = []; 156 | 157 | for (var i = 0; i < base64.length; i++) { 158 | // eslint-disable-next-line 159 | switch(i%4) { 160 | case 1: 161 | bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) | 162 | (base64map.indexOf(base64.charAt(i)) >>> 4)); 163 | break; 164 | case 2: 165 | bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) | 166 | (base64map.indexOf(base64.charAt(i)) >>> 2)); 167 | break; 168 | case 3: 169 | bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) | 170 | (base64map.indexOf(base64.charAt(i)))); 171 | break; 172 | } 173 | } 174 | 175 | return bytes; 176 | 177 | } 178 | 179 | }; 180 | 181 | // Crypto mode namespace 182 | Crypto.mode = {}; 183 | 184 | })(); 185 | -------------------------------------------------------------------------------- /src/components/UploadImg/lib/crypto1/hmac/hmac-min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto-JS v1.1.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){var a=Crypto.util;Crypto.HMAC=function(g,h,f,d){f=f.length>g._blocksize*4?g(f,{asBytes:true}):a.stringToBytes(f);var c=f,j=f.slice(0);for(var e=0;e hasher._blocksize * 4 ? 16 | hasher(key, { asBytes: true }) : 17 | util.stringToBytes(key); 18 | 19 | // XOR keys with pad constants 20 | var okey = key, 21 | ikey = key.slice(0); 22 | for (var i = 0; i < hasher._blocksize * 4; i++) { 23 | okey[i] ^= 0x5C; 24 | ikey[i] ^= 0x36; 25 | } 26 | 27 | var hmacbytes = hasher(util.bytesToString(okey) + 28 | hasher(util.bytesToString(ikey) + message, { asString: true }), 29 | { asBytes: true }); 30 | return options && options.asBytes ? hmacbytes : 31 | options && options.asString ? util.bytesToString(hmacbytes) : 32 | util.bytesToHex(hmacbytes); 33 | 34 | }; 35 | 36 | })(); 37 | -------------------------------------------------------------------------------- /src/components/UploadImg/lib/crypto1/sha1/sha1-min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto-JS v1.1.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){var a=Crypto.util;var b=Crypto.SHA1=function(e,c){var d=a.wordsToBytes(b._sha1(e));return c&&c.asBytes?d:c&&c.asString?a.bytesToString(d):a.bytesToHex(d)};b._sha1=function(k){var u=a.stringToWords(k),v=k.length*8,o=[],q=1732584193,p=-271733879,h=-1732584194,g=271733878,f=-1009589776;u[v>>5]|=128<<(24-v%32);u[((v+64>>>9)<<4)+15]=v;for(var y=0;y>>31)}var r=((q<<5)|(q>>>27))+f+(o[x]>>>0)+(x<20?(p&h|~p&g)+1518500249:x<40?(p^h^g)+1859775393:x<60?(p&h|p&g|h&g)-1894007588:(p^h^g)-899497514);f=g;g=h;h=(p<<30)|(p>>>2);p=q;q=r}q+=D;p+=C;h+=B;g+=A;f+=z}return[q,p,h,g,f]};b._blocksize=16})(); -------------------------------------------------------------------------------- /src/components/UploadImg/lib/crypto1/sha1/sha1.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Crypto-JS v1.1.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){ 8 | 9 | // Shortcut 10 | var util = Crypto.util; 11 | 12 | // Public API 13 | var SHA1 = Crypto.SHA1 = function (message, options) { 14 | var digestbytes = util.wordsToBytes(SHA1._sha1(message)); 15 | return options && options.asBytes ? digestbytes : 16 | options && options.asString ? util.bytesToString(digestbytes) : 17 | util.bytesToHex(digestbytes); 18 | }; 19 | 20 | // The core 21 | SHA1._sha1 = function (message) { 22 | 23 | var m = util.stringToWords(message), 24 | l = message.length * 8, 25 | w = [], 26 | H0 = 1732584193, 27 | H1 = -271733879, 28 | H2 = -1732584194, 29 | H3 = 271733878, 30 | H4 = -1009589776; 31 | 32 | // Padding 33 | m[l >> 5] |= 0x80 << (24 - l % 32); 34 | m[((l + 64 >>> 9) << 4) + 15] = l; 35 | 36 | for (var i = 0; i < m.length; i += 16) { 37 | 38 | var a = H0, 39 | b = H1, 40 | c = H2, 41 | d = H3, 42 | e = H4; 43 | 44 | for (var j = 0; j < 80; j++) { 45 | 46 | if (j < 16) w[j] = m[i + j]; 47 | else { 48 | var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16]; 49 | w[j] = (n << 1) | (n >>> 31); 50 | } 51 | 52 | var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + ( 53 | j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 : 54 | j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 : 55 | j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 : 56 | (H1 ^ H2 ^ H3) - 899497514); 57 | 58 | H4 = H3; 59 | H3 = H2; 60 | H2 = (H1 << 30) | (H1 >>> 2); 61 | H1 = H0; 62 | H0 = t; 63 | 64 | } 65 | 66 | H0 += a; 67 | H1 += b; 68 | H2 += c; 69 | H3 += d; 70 | H4 += e; 71 | 72 | } 73 | 74 | return [H0, H1, H2, H3, H4]; 75 | 76 | }; 77 | 78 | // Package private blocksize 79 | SHA1._blocksize = 16; 80 | 81 | })(); 82 | -------------------------------------------------------------------------------- /src/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/SvgIcon' // svg component 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const req = require.context('../icons/svg', false, /\.svg$/) 8 | const requireAll = requireContext => requireContext.keys().map(requireContext) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /src/icons/svg/suger.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/yueliang.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui'; 3 | import 'element-ui/lib/theme-chalk/index.css'; 4 | import App from './App' 5 | import router from './router/index' 6 | import store from './store' 7 | import '@/styles/base.less' 8 | import '@/styles/element-ui.less' 9 | import '@/styles/iconfont.less' 10 | import '@/styles/index.less' // global css 11 | import './permission' 12 | import './icons/index' 13 | 14 | Vue.use(ElementUI); 15 | 16 | Vue.config.productionTip = false 17 | 18 | new Vue({ 19 | render: h => h(App), 20 | router, 21 | store 22 | }).$mount('#app') 23 | -------------------------------------------------------------------------------- /src/permission.js: -------------------------------------------------------------------------------- 1 | import router from '@/router' 2 | import store from './store' 3 | import { Message } from 'element-ui' 4 | import NProgress from 'nprogress' 5 | import 'nprogress/nprogress.css' 6 | import { getToken } from '@/utils/auth' 7 | import getPageTitle from '@/utils/get-page-title' 8 | import path from 'path' 9 | 10 | NProgress.configure({ showSpinner: false }) 11 | 12 | function getRoutePath(routes, _path) { 13 | var routerPath = '' 14 | routes.some((item) => { 15 | if (!item.hidden) { 16 | routerPath = _path ? path.resolve(_path, item.path) : item.path 17 | if (item.children) { 18 | routerPath = getRoutePath(item.children, routerPath) 19 | } 20 | return true 21 | } 22 | }) 23 | return routerPath 24 | } 25 | 26 | router.beforeEach(async (to, from, next) => { 27 | NProgress.start() 28 | document.title = to.meta.title ? getPageTitle(to.meta.title) : getPageTitle(to.name); 29 | const hasToken = getToken() 30 | if (hasToken) { 31 | if (to.path === '/login') { 32 | next({ path: '/' }) 33 | NProgress.done() 34 | } else { 35 | const hasRoles = store.state.roles && store.state.roles.length > 0 36 | if (hasRoles) { 37 | next() 38 | } else { 39 | try { 40 | store.dispatch('getInfo').then(roles => { 41 | // 根据roles 动态处理路由 42 | console.log('执行了吗?') 43 | store.dispatch('handleRoutes', { roles: roles }).then(() => { 44 | router.addRoutes(store.getters.addRouters) 45 | // 重定向到有权限的第一个菜单栏路由 46 | const authRouters = store.getters.addRouters 47 | if (to.path === '/') { 48 | const nextRoutePath = getRoutePath(authRouters) 49 | next({ path: nextRoutePath, replace: true }) 50 | } else { 51 | next({ ...to, replace: true }) 52 | } 53 | }) 54 | }) 55 | } catch (error) { 56 | await store.dispatch('resetToken') 57 | Message.error(error || 'Has Error') 58 | next(`/login?redirect=${to.path}`) 59 | NProgress.done() 60 | } 61 | } 62 | } 63 | } else { 64 | if (to.path === '/login') { 65 | next() 66 | } else { 67 | next({ path: `/login?redirect=${to.path}` }) 68 | NProgress.done() 69 | } 70 | } 71 | }) 72 | 73 | router.afterEach(() => { 74 | NProgress.done() 75 | }) 76 | -------------------------------------------------------------------------------- /src/router/asyncRoutes.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Layout from '@/views/Layout' 4 | import Login from '@/views/Login' 5 | // 共同拥有部分, 不需要任何的权限 6 | // 404 页面 7 | import errorPage from '@/views/error-page/404' 8 | 9 | import navigatorOneThree from '@/views/navigatorOne/itemThree/itemThree' 10 | import navigatorOneTwo from '@/views/navigatorOne/itemTwo/itemTwo' 11 | import navigatorOneOne from '@/views/navigatorOne/itemOne/itemOne' 12 | import Common from '@/views/navigatorTwo/CommonInvite' 13 | 14 | import navigatorTwoOne from '@/views/navigatorTwo/itemOne/itemOne' 15 | import navigatorTwoTwo from '@/views/navigatorTwo/itemTwo/itemTwo' 16 | import navigatorTwoThree from '@/views/navigatorTwo/itemThree/itemThree' 17 | import navigatorTwoFour from '@/views/navigatorTwo/itemFour/itemFour' 18 | 19 | export const asyncRoutes = [ 20 | { 21 | path: '/navigatorOne', 22 | name: 'one', 23 | component: Layout, 24 | redirect: '/navigatorOne/itemOne', 25 | meta: { 26 | icon: 'icon-suger', 27 | title: 'navigatorOne' 28 | }, 29 | children: [ 30 | { 31 | name: '1-itemOne', 32 | path: 'itemOne', 33 | component: navigatorOneOne, 34 | meta: { 35 | title: 'item one', 36 | // codes: ['item-one'] 37 | } 38 | }, 39 | { 40 | name: '1-itemTwo', 41 | path: 'itemTwo', 42 | component: navigatorOneTwo, 43 | meta: { 44 | title: 'item two', 45 | codes: ['item-two'] // 无权限 46 | } 47 | }, 48 | { 49 | name: '1-itemThree', 50 | path: 'itemThree', 51 | component: navigatorOneThree, 52 | meta: { 53 | title: 'itme three', 54 | codes: ['item-three'] // 无权限 55 | } 56 | } 57 | ] 58 | }, 59 | { 60 | path: '/navigatorTwo', 61 | name: 'two', 62 | component: Layout, 63 | redirect: '/navigatorTwo/itemOne', 64 | meta: { 65 | icon: 'icon-yueliang', 66 | title: 'navigatorTwo' 67 | }, 68 | // hidden: true, 69 | children: [ 70 | { 71 | path: 'itemOne', 72 | component: navigatorTwoOne, 73 | meta: { 74 | title: 'example', 75 | codes: ['item-one'] 76 | } 77 | }, 78 | { 79 | path: 'itemTwo', 80 | name: 'itemTwo', 81 | component: Common, 82 | meta: { 83 | title: 'item two', 84 | }, 85 | children: [ 86 | { 87 | path: 'table1', 88 | name: 'table1', 89 | component: navigatorTwoOne, 90 | meta: { 91 | title: 'table1' 92 | } 93 | }, 94 | { 95 | path: 'table2', 96 | name: 'table2', 97 | component: navigatorTwoTwo, 98 | meta: { 99 | title: 'table2', 100 | } 101 | }, 102 | { 103 | name: 'two/id', 104 | path: 'two/:id', 105 | component: navigatorTwoThree, 106 | hidden: true, 107 | meta: { 108 | activeMenu: '/navigatorTwo/itemTwo/table2' 109 | } 110 | }, 111 | ] 112 | }, 113 | { 114 | path: 'itemThree', 115 | component: navigatorTwoThree, 116 | meta: { 117 | title: 'item three', 118 | } 119 | }, 120 | { 121 | path: 'itemFour', 122 | component: navigatorTwoFour, 123 | meta: { 124 | title: 'item four', 125 | } 126 | }, 127 | ] 128 | }, 129 | { 130 | path: '*', 131 | name: '404', 132 | component: errorPage, 133 | hidden: true 134 | } 135 | ] 136 | 137 | 138 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Layout from '@/views/Layout' 4 | import Login from '@/views/Login' 5 | 6 | Vue.use(Router) 7 | 8 | export const fixedRoutes = [ 9 | { 10 | path: '/', 11 | name: 'home', 12 | component: Layout, 13 | hidden: true 14 | }, 15 | { 16 | path: '/login', 17 | name: 'Login', 18 | component: Login, 19 | hidden: true 20 | } 21 | ] 22 | 23 | const createRouter = () => new Router({ 24 | mode: 'history', 25 | base: '/vue-element-admin-template', 26 | scrollBehavior: () => ({ y: 0 }), 27 | routes: fixedRoutes 28 | }) 29 | 30 | const router = createRouter() 31 | 32 | export default router 33 | -------------------------------------------------------------------------------- /src/services/user.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request'; 2 | import { commonConfig } from '../utils/utils' 3 | 4 | 5 | export async function getInfo() { 6 | return request(`${commonConfig.apiUrl}/xxxxx`); 7 | } 8 | 9 | export async function login(params) { 10 | return request(`${commonConfig.apiUrl}/xxxx/xxx`, params); 11 | } 12 | 13 | export async function savePassword(params) { 14 | return request(`${commonConfig.apiUrl}/xxxx/xxxx`, params); 15 | } -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import { fixedRoutes } from '@/router' 4 | import { asyncRoutes } from '@/router/asyncRoutes' 5 | // import { getInfor } from '@/services/user' 6 | import { 7 | removeToken 8 | } from '@/utils/auth' 9 | 10 | Vue.use(Vuex) 11 | 12 | function hasPermission (roles, route) { 13 | if (route.meta && route.meta.codes) { 14 | return roles.some(role => route.meta.codes.includes(role)) 15 | } else { 16 | return true 17 | } 18 | } 19 | 20 | function filterAsyncRoutes(routes, roles) { 21 | const res = [] 22 | routes.forEach(route => { 23 | const tmp = { ...route } 24 | if (hasPermission(roles, tmp)) { 25 | if (tmp.children) { 26 | tmp.children = filterAsyncRoutes(tmp.children, roles) 27 | } 28 | res.push(tmp) 29 | } 30 | }) 31 | return res 32 | } 33 | 34 | const store = new Vuex.Store({ 35 | state: { 36 | roles: [], 37 | name: '', 38 | routes: fixedRoutes, 39 | uploadImages: {}, 40 | addRouters: [], 41 | user: { username: 'admin' } 42 | }, 43 | mutations: { 44 | SET_TOKEN: (state, token) => { 45 | state.token = token 46 | }, 47 | SET_USER: (state, user) => { 48 | state.user = user 49 | }, 50 | SET_ROLES: (state, roles) => { 51 | state.roles = roles 52 | }, 53 | SET_UPLOAD_IMG: (state, images) => { 54 | state.uploadImages = { ...state.uploadImages, ...images } 55 | }, 56 | REMOVE_UPLOAD_IMG: (state) => { 57 | state.uploadImages = {} 58 | }, 59 | SET_ROUTES: (state, routes) => { 60 | state.addRouters = routes 61 | state.routes = fixedRoutes.concat(routes) 62 | } 63 | }, 64 | // 下面这两个都是全局的 65 | actions: { 66 | getInfo ({ commit, state }) { 67 | return new Promise((resolve) => { 68 | // getInfor(state.token).then(response => { 69 | // if (response.data && response.data.errCode === 0) { 70 | // const result = response.data.data 71 | // const { permissionCodeList, userVo } = result 72 | // commit('SET_USER', userVo) 73 | const permissionCodeList = ['item-one'] 74 | commit('SET_ROLES', permissionCodeList) 75 | resolve(permissionCodeList) 76 | // } else { 77 | // removeToken() 78 | // window.location.href = window.location.origin + '/vue-element-admin/login' 79 | // } 80 | // }) 81 | }) 82 | }, 83 | handleRoutes ({ commit }, { roles }) { 84 | return new Promise((resolve) => { 85 | let accessedRoutes = [] 86 | accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) 87 | // 再次筛选最外层如果存在children, 但是children 为空数组,那么也要从里面剔除掉,(只遍历一遍) 88 | const new_accessedRoutes = [] 89 | accessedRoutes.map((item) => { 90 | if (item.children && item.children.length === 0) { 91 | // delete item.children 92 | } else { 93 | new_accessedRoutes.push(item) 94 | } 95 | }) 96 | commit('SET_ROUTES', new_accessedRoutes) 97 | resolve() 98 | }) 99 | }, 100 | resetToken ({ commit }) { 101 | return new Promise(resolve => { 102 | commit('SET_TOKEN', '') 103 | commit('SET_ROLES', []) 104 | removeToken() 105 | resolve() 106 | }) 107 | }, 108 | addUplaodImages ({ commit }, imgUrlObj) { 109 | return new Promise((resolve) => { 110 | commit('SET_UPLOAD_IMG', imgUrlObj) 111 | resolve() 112 | }) 113 | }, 114 | removeUploadImages ({ commit }) { 115 | return new Promise((resolve) => { 116 | commit('REMOVE_UPLOAD_IMG') 117 | resolve() 118 | }) 119 | } 120 | }, 121 | getters: { 122 | roles: state => state.roles, 123 | name: state => state.name, 124 | routesConfig: state => state.routes, 125 | uploadImages: state => state.uploadImages, 126 | addRouters: state => state.addRouters 127 | } 128 | }) 129 | 130 | export default store 131 | -------------------------------------------------------------------------------- /src/styles/base.less: -------------------------------------------------------------------------------- 1 | em, i, strong { 2 | font-weight: 400; 3 | } 4 | a { 5 | text-decoration: none; 6 | list-style: none; 7 | } 8 | h1, h2, h3, h4, h5, h6, p { 9 | margin: 0; 10 | padding: 0; 11 | } 12 | h3 { 13 | font-size: 18px; 14 | } -------------------------------------------------------------------------------- /src/styles/element-ui.less: -------------------------------------------------------------------------------- 1 | // cover some element-ui styles 2 | 3 | .el-button, .el-input__inner { 4 | height: 32px; 5 | line-height: 32px; 6 | } 7 | .el-input__inner { 8 | height: 32px; 9 | line-height: 32px; 10 | } 11 | .el-button { 12 | padding: 0 20px; 13 | } 14 | .el-button.is-round { 15 | padding: 0 20px; 16 | } 17 | 18 | .el-table td, .el-table th { 19 | text-align: center; 20 | } 21 | 22 | .el-table td, .el-table th { 23 | padding: 8px 0; 24 | } 25 | 26 | .el-form-item__label { 27 | line-height: 40px; 28 | } 29 | 30 | .el-submenu__icon-arrow { 31 | color: #909399 !important; 32 | } 33 | 34 | .el-menu-item i { 35 | color: #dee4eb; 36 | } 37 | .el-menu-item.is-active i { 38 | color: #409EFF; 39 | } -------------------------------------------------------------------------------- /src/styles/iconfont.less: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('//at.alicdn.com/t/font_1647403_aybihsndmv.eot?t=1582123640102'); /* IE9 */ 3 | src: url('//at.alicdn.com/t/font_1647403_aybihsndmv.eot?t=1582123640102#iefix') format('embedded-opentype'), /* IE6-IE8 */ 4 | url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPcAAsAAAAACEAAAAOPAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqEKINkATYCJAMMCwgABCAFhG0HOBssBxFVlNdkPw6cs+zMPfcvMBOlnMf5X3b/ndvdH5SyhZGCnle7EeBoGiCAoObWdGVMoyJUl+z51rP8j6Td+cU6j9MohZAgHH/cO/2roYHNZ1k5jLlsrEldFMeddwGNMc77ZAWIDWM3UR7EcyAA6rCGJygxObMQqhAA6wgAdba11EE1ZYGoKSaogqBcclSAlkEJqmw+uwVgKf89fYQ/qQIMShxga25zUiNi30S8OcJn5VlUUgTS8VwAtFMAB+AJQABUXeopBQ9jnuBQdzSiPlsZAgQ2VlCWAS5xdcor/eMxgJQBNJoixVXNTkqKeUDAmyNiUYvz9wHKPRJHAbyUKIYzlaCiqaXpaaSmpq+Gd45oLjgwd1BDa+H+2X2NpL4nwXDR2N3bUKgrVQ4dVdjwLVKw5qFHlmzz/aA2tzmqS1IxVyhKtB4/LmKzj4oXHDCnpFqj0xvq6ofuWWLdvpK5MwtOzZ5eeLYimFpUsnbDnl2GhYduWW4SkwqbrVJDsb5ZohVNmy1cp667wFyiOQWgL3xc89vii16zQ7MeFXCfxCM02zcPqp6WPfFLPJWpbtojY9/36MTEPvvzjOToPNORn0kWSVIedXRT3jPK7+jKoz+5dXZR/n7fi9dquX4x9VJ6fX0a1Q12a11vkkovFePpZ+sNUQei9ket77K2PhAZfixy/6+foU+i/x/dGh32RL9i7qRXdolxttfBOdPYSmfrA1EbotZH7e9aaNNQhO1ydpfrjjxbnTu9zNDecFnu1JrW3FPz5p/OvYeETBhtQS0AQL7LT/JgGSSuC7Avv/o93Fdrv1WjE/lbVUMAAJ4OdIxyabsCHkxFBNUX4SX4seMGWQaELgdWPluD2mYCcM02r80EdRgEZICAPn79fUaIYhdR1aUiMCqsgFPliAqKJyjREAjKVMWAOg9UpzUYwFmgqQFwx0sAoos3MNrOAqeLDyooX1BijD8o06UFqCvO4EoNztTuExyKgBrkE1rFEyF72AfFB6yvg3BJOWde0Pk2CFmcZpMVTujG2OFvdR4CATkeoRRew2FgMI47VCFuQjBFklAZSbHiMdpL4CAhQBpAegK0FDYhOjzY575/gGpXA8HVdHX4L5DjtZMDMsRIW6CVZmrVdS2zvZtajiAgeRVx2AhQii40wBgDmPJFHaQEMZoeEaNAIvWjtpp4ft34fEcA1IF7eYw4CbCH7rTwjWThdBQBAA==') format('woff2'), 5 | url('//at.alicdn.com/t/font_1647403_aybihsndmv.woff?t=1582123640102') format('woff'), 6 | url('//at.alicdn.com/t/font_1647403_aybihsndmv.ttf?t=1582123640102') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url('//at.alicdn.com/t/font_1647403_aybihsndmv.svg?t=1582123640102#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | .icon-58:before { 19 | content: "\e63b"; 20 | } 21 | 22 | .icon-dashboard:before { 23 | content: "\e6b6"; 24 | } 25 | -------------------------------------------------------------------------------- /src/styles/index.less: -------------------------------------------------------------------------------- 1 | @backgroundColorSty: #304156; 2 | 3 | .layout { 4 | position: relative; 5 | height: 100%; 6 | width: 100%; 7 | .menu { 8 | background-color: @backgroundColorSty; 9 | height: 100%; 10 | position: fixed; 11 | top: 0; 12 | bottom: 0; 13 | left: 0; 14 | z-index: 1001; 15 | .scrollbar-wrapper { 16 | overflow-x: hidden !important; 17 | } 18 | .scrollbar-wrapper { 19 | overflow-x: hidden !important; 20 | } 21 | .el-scrollbar__bar.is-vertical { 22 | right: 0px; 23 | } 24 | .el-scrollbar { 25 | height: 100%; 26 | } 27 | .activeWidth { 28 | width: 230px; 29 | transition: transform .28s; 30 | } 31 | .el-menu { 32 | height: 100%; 33 | .el-submenu__title { 34 | text-align: left; 35 | i { 36 | color: #dee4eb; 37 | } 38 | } 39 | .el-icon-arrow-right:before { 40 | content: '' !important; 41 | } 42 | .el-menu-item { 43 | text-align: left; 44 | } 45 | } 46 | } 47 | .main { 48 | line-height: 32px; 49 | position: relative; 50 | min-height: 100%; 51 | margin-left: 230px; 52 | transition: margin-left .28s; // 原来滑动效果是这样做出来的 53 | .header { 54 | height: 50px; 55 | width: 100%; 56 | box-shadow: 1px 2px 6px #ddd; 57 | background-color: #fff; 58 | .el-icon-s-fold, .el-icon-s-unfold { 59 | cursor: pointer; 60 | margin: 13px 10px; 61 | font-size: 25px; 62 | } 63 | .user { 64 | cursor: pointer; 65 | float: right; 66 | font-size: 18px; 67 | font-weight: bold; 68 | margin: 15px 25px; 69 | text-align: center; 70 | } 71 | } 72 | } 73 | } 74 | .hideSidebar { 75 | .main { 76 | margin-left: 54px; 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/utils/auth.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie'; 2 | 3 | export function getToken() { 4 | return Cookies.get('token') 5 | } 6 | export function removeUserId() { 7 | return Cookies.remove('userId') 8 | } 9 | export function removeId() { 10 | return Cookies.remove('staffId') 11 | } 12 | export function removeNickname() { 13 | return Cookies.remove('nickname') 14 | } 15 | export function removeToken() { 16 | return Cookies.remove('token') 17 | } 18 | export function setToken(token) { 19 | return Cookies.set('token', token) 20 | } 21 | export function getStaffId() { 22 | return Cookies.get('staffId') 23 | } 24 | export function getUserId() { 25 | return Cookies.get('userId') 26 | } 27 | export function getNickname() { 28 | return Cookies.get('nickname') 29 | } -------------------------------------------------------------------------------- /src/utils/get-page-title.js: -------------------------------------------------------------------------------- 1 | const title = 'vue-element-admin-template' 2 | 3 | export default function getPageTitle(pageTitle) { 4 | if(pageTitle) { 5 | return `${pageTitle} - ${title}` 6 | } 7 | return title; 8 | } -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import Cookie from 'js-cookie'; 3 | 4 | const instance = axios.create({ 5 | baseURL: '', 6 | timeout: 500000 7 | }); 8 | 9 | instance.interceptors.request.use((req) => { 10 | req.headers.authorization = Cookie.get('token'); 11 | return req; 12 | }, err => Promise.reject(err)); 13 | 14 | instance.interceptors.response.use( 15 | res => res, 16 | err => Promise.reject(err) 17 | ); 18 | 19 | export default function request(url, options) { 20 | const opt = options || {}; 21 | return new Promise((resolve, reject) => { 22 | instance({ 23 | url, 24 | method: opt.type || 'get', 25 | data: opt.params || {}, 26 | headers: { 27 | 'Content-Type': 'application/json', 28 | } 29 | }).then((res) => { 30 | if (res) { 31 | const h = res.headers; 32 | resolve({data: res.data, headers:h}) 33 | } 34 | return res; 35 | }) 36 | .catch((err) => { reject(err) }); 37 | }); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/utils/utils.js: -------------------------------------------------------------------------------- 1 | export const uploadOssConfig = { 2 | accessid: "", 3 | accesskey: "", 4 | host: "", 5 | policyText: { 6 | expiration: "2021-01-01T12:00:00.000Z", //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了 7 | conditions: [ 8 | ["content-length-range", 0, 1048576000] // 设置上传文件的大小限制 9 | ] 10 | }, 11 | uploadUrl: "" 12 | } 13 | 14 | export function judgePower(arr, str) { 15 | for (let i = 0; i < arr.length; i++) { 16 | if (arr[i] === str) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | function domainConfig() { 24 | if (window.location.origin.indexOf("online domain name") !== -1) { 25 | return "https://api.xxxx.com"; 26 | } 27 | return "https://api.testing.xxxx.com"; 28 | } 29 | 30 | export const commonConfig = { 31 | apiUrl: domainConfig(), 32 | }; -------------------------------------------------------------------------------- /src/views/Layout/SidebarItem/index.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 66 | 67 | 72 | -------------------------------------------------------------------------------- /src/views/Layout/appMain/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 50 | 51 | 62 | -------------------------------------------------------------------------------- /src/views/Layout/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 65 | 66 | 71 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 84 | 216 | 217 | 286 | -------------------------------------------------------------------------------- /src/views/UserRelation/UserRelation.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /src/views/error-page/404.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 146 | -------------------------------------------------------------------------------- /src/views/navigatorOne/itemOne/itemOne.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/views/navigatorOne/itemThree/itemThree.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /src/views/navigatorOne/itemTwo/itemTwo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /src/views/navigatorTwo/CommonInvite/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/views/navigatorTwo/itemFour/itemFour.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /src/views/navigatorTwo/itemOne/itemOne.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /src/views/navigatorTwo/itemThree/itemThree.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /src/views/navigatorTwo/itemTwo/itemTwo.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 20 | 21 | 29 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | 4 | function resolve(dir) { 5 | return path.join(__dirname, dir) 6 | } 7 | 8 | module.exports = { 9 | publicPath: '/vue-element-admin-template', 10 | outputDir: 'dist/vue-element-admin-template', 11 | devServer: { 12 | port: 10080, 13 | disableHostCheck: true, // solve Invilid host header problem 14 | hotOnly: true, // 热更新 15 | }, 16 | chainWebpack: config => { 17 | config.module 18 | .rule('svg') 19 | .exclude.add(resolve('src/icons')) 20 | .end() 21 | config.module 22 | .rule('icons') 23 | .test(/\.svg$/) 24 | .include.add(resolve('src/icons')) 25 | .end() 26 | .use('svg-sprite-loader') 27 | .loader('svg-sprite-loader') 28 | .options({ 29 | symbolId: 'icon-[name]' 30 | }) 31 | .end() 32 | } 33 | } --------------------------------------------------------------------------------