diff --git a/package.json b/package.json index 2413824..6a06c51 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "path-to-regexp": "2.4.0", "vue": "2.6.10", "vue-router": "3.0.6", - "vuex": "3.1.0" + "vuex": "3.1.0", + "webpack-dev-server": "^2.9.1" }, "devDependencies": { "@vue/cli-plugin-babel": "4.4.4", diff --git a/src/api/system/sysRole.js b/src/api/system/sysRole.js index b20984b..a0b0aec 100644 --- a/src/api/system/sysRole.js +++ b/src/api/system/sysRole.js @@ -1,48 +1,28 @@ +/* +角色管理相关的API请求函数 +*/ import request from '@/utils/request' -/** - * 角色管理相关的API请求函数 - * - * @type {string} - */ const api_name = '/admin/system/sysRole' export default { - /** - * 获取角色分页列表(带搜索) - * @param {*} page - * @param {*} limit - * @param {*} searchObj - * @returns - */ + /* + 获取角色分页列表(带搜索) + */ getPageList(page, limit, searchObj) { return request({ url: `${api_name}/${page}/${limit}`, method: 'get', - // 如果是普通对象参数写法,params:对象参数名 - // 如果是使用json格式传递,data:对象参数名 params: searchObj }) }, - - /** - * 角色删除 - * @param {*} id - * @returns - */ removeById(id) { return request({ url: `${api_name}/remove/${id}`, method: 'delete' }) }, - - /** - * 角色添加 - * @param {*} role - * @returns - */ save(role) { return request({ url: `${api_name}/save`, @@ -50,13 +30,6 @@ export default { data: role }) }, - - /** - * 回显要修改的id信息 - * - * @param id - * @returns {*} - */ getById(id) { return request({ url: `${api_name}/get/${id}`, @@ -64,11 +37,6 @@ export default { }) }, - /** 修改 - * - * @param role - * @returns {*} - */ updateById(role) { return request({ url: `${api_name}/update`, @@ -76,13 +44,6 @@ export default { data: role }) }, - - /** - * 批量删除 - * - * @param idList - * @returns {*} - */ batchRemove(idList) { return request({ url: `${api_name}/batchRemove`, @@ -90,29 +51,4 @@ export default { data: idList }) }, - /** - * 根据用户获取角色数据 - * - * @param adminId - * @returns {*} - */ - getRoles(adminId) { - return request({ - url: `${api_name}/toAssign/${adminId}`, - method: 'get' - }) - }, - /** - * 为用户分配角色 - * - * @param assginRoleVo - * @returns {*} - */ - assignRoles(assginRoleVo) { - return request({ - url: `${api_name}/doAssign`, - method: 'post', - data: assginRoleVo - }) - } } diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue index 61d677b..da39034 100644 --- a/src/layout/components/Sidebar/index.vue +++ b/src/layout/components/Sidebar/index.vue @@ -3,16 +3,16 @@ - + @@ -31,8 +31,7 @@ export default { 'sidebar' ]), routes() { - // return this.$router.options.routes - return this.$router.options.routes.concat(global.antRouter) + return this.$router.options.routes }, activeMenu() { const route = this.$route diff --git a/src/main.js b/src/main.js index 5aad0cc..01cba2f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,20 +1,19 @@ import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets + import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/en' // lang i18n + import '@/styles/index.scss' // global css + import App from './App' import store from './store' import router from './router' import '@/icons' // icon import '@/permission' // permission control -// 新增 -import hasBtnPermission from '@/utils/btn-permission' - -Vue.prototype.$hasBP = hasBtnPermission /** * If you don't want to use mock-server @@ -30,9 +29,9 @@ if (process.env.NODE_ENV === 'production') { } // set ElementUI lang to EN -// Vue.use(ElementUI, { locale }) +Vue.use(ElementUI, { locale }) // 如果想要中文版 element-ui,按如下方式声明 -Vue.use(ElementUI) +// Vue.use(ElementUI) Vue.config.productionTip = false diff --git a/src/permission.js b/src/permission.js index 32434bf..fa1ea19 100644 --- a/src/permission.js +++ b/src/permission.js @@ -1,23 +1,25 @@ import router from './router' import store from './store' -import { getToken } from '@/utils/auth' import { Message } from 'element-ui' -import NProgress from 'nprogress' // 水平进度条提示: 在跳转路由时使用 -import 'nprogress/nprogress.css' // 水平进度条样式 -import getPageTitle from '@/utils/get-page-title' // 获取应用头部标题的函数 -import Layout from '@/layout' -import ParentView from '@/components/ParentView' - -const _import = require('./router/_import_' + process.env.NODE_ENV) // 获取组件的方法 +import NProgress from 'nprogress' // progress bar +import 'nprogress/nprogress.css' // progress bar style +import { getToken } from '@/utils/auth' // get token from cookie +import getPageTitle from '@/utils/get-page-title' NProgress.configure({ showSpinner: false }) // NProgress Configuration + const whiteList = ['/login'] // no redirect whitelist + router.beforeEach(async(to, from, next) => { + // start progress bar NProgress.start() + // set page title document.title = getPageTitle(to.meta.title) + // determine whether the user has logged in const hasToken = getToken() + if (hasToken) { if (to.path === '/login') { // if is logged in, redirect to the home page @@ -30,25 +32,11 @@ router.beforeEach(async(to, from, next) => { } else { try { // get user info - await store.dispatch('user/getInfo')// 请求获取用户信息 - if (store.getters.menus.length < 1) { - global.antRouter = [] - next() - } - const menus = filterAsyncRouter(store.getters.menus)// 1.过滤路由 - console.log(menus) - router.addRoutes(menus) // 2.动态添加路由 - const lastRou = [{ path: '*', redirect: '/404', hidden: true }] - router.addRoutes(lastRou) - global.antRouter = menus // 3.将路由数据传递给全局变量,做侧边栏菜单渲染工作 - next({ - ...to, - replace: true - }) - // next() + await store.dispatch('user/getInfo') + + next() } catch (error) { // remove token and go to login page to re-login - console.log(error) await store.dispatch('user/resetToken') Message.error(error || 'Has Error') next(`/login?redirect=${to.path}`) @@ -56,7 +44,9 @@ router.beforeEach(async(to, from, next) => { } } } - } else { /* has no token*/ + } else { + /* has no token*/ + if (whiteList.indexOf(to.path) !== -1) { // in the free login whitelist, go directly next() @@ -68,32 +58,7 @@ router.beforeEach(async(to, from, next) => { } }) -router.afterEach(() => { // finish progress bar +router.afterEach(() => { + // finish progress bar NProgress.done() -}) // // 遍历后台传来的路由字符串,转换为组件对象 -function filterAsyncRouter(asyncRouterMap) { - const accessedRouters = asyncRouterMap.filter(route => { - if (route.component) { - if (route.component === 'Layout') { - route.component = Layout - } else if (route.component === 'ParentView') { - route.component = ParentView - } else { - try { - route.component = _import(route.component)// 导入组件 - } catch (error) { - // debugger - console.log(error) - route.component = _import('dashboard/index')// 导入组件 - } - } - } - if (route.children && route.children.length > 0) { - route.children = filterAsyncRouter(route.children) - } else { - delete route.children - } - return true - }) - return accessedRouters -} +}) diff --git a/src/router/index.js b/src/router/index.js index 3eb4a02..c06a850 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,10 +1,11 @@ import Vue from 'vue' import Router from 'vue-router' -/* Layout */ -import Layout from '@/layout' Vue.use(Router) +/* Layout */ +import Layout from '@/layout' + /** * Note: sub-menu only appear when route children.length >= 1 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html @@ -35,6 +36,13 @@ export const constantRoutes = [ component: () => import('@/views/login/index'), hidden: true }, + + { + path: '/404', + component: () => import('@/views/404'), + hidden: true + }, + { path: '/', component: Layout, @@ -45,7 +53,135 @@ export const constantRoutes = [ component: () => import('@/views/dashboard/index'), meta: { title: 'Dashboard', icon: 'dashboard' } }] - } + }, + + { + path: '/system', + component: Layout, + meta: { + title: '系统管理', + icon: 'el-icon-s-tools' + }, + alwaysShow: true, + children: [ + { + path: 'sysRole', + component: () => import('@/views/system/sysRole/list'), + meta: { + title: '角色管理', + icon: 'el-icon-s-help' + }, + } + ] + }, + + { + path: '/example', + component: Layout, + redirect: '/example/table', + name: 'Example', + meta: { title: 'Example', icon: 'el-icon-s-help' }, + children: [ + { + path: 'table', + name: 'Table', + component: () => import('@/views/table/index'), + meta: { title: 'Table', icon: 'table' } + }, + { + path: 'tree', + name: 'Tree', + component: () => import('@/views/tree/index'), + meta: { title: 'Tree', icon: 'tree' } + } + ] + }, + + { + path: '/form', + component: Layout, + children: [ + { + path: 'index', + name: 'Form', + component: () => import('@/views/form/index'), + meta: { title: 'Form', icon: 'form' } + } + ] + }, + + { + path: '/nested', + component: Layout, + redirect: '/nested/menu1', + name: 'Nested', + meta: { + title: 'Nested', + icon: 'nested' + }, + children: [ + { + path: 'menu1', + component: () => import('@/views/nested/menu1/index'), // Parent router-view + name: 'Menu1', + meta: { title: 'Menu1' }, + children: [ + { + path: 'menu1-1', + component: () => import('@/views/nested/menu1/menu1-1'), + name: 'Menu1-1', + meta: { title: 'Menu1-1' } + }, + { + path: 'menu1-2', + component: () => import('@/views/nested/menu1/menu1-2'), + name: 'Menu1-2', + meta: { title: 'Menu1-2' }, + children: [ + { + path: 'menu1-2-1', + component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'), + name: 'Menu1-2-1', + meta: { title: 'Menu1-2-1' } + }, + { + path: 'menu1-2-2', + component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'), + name: 'Menu1-2-2', + meta: { title: 'Menu1-2-2' } + } + ] + }, + { + path: 'menu1-3', + component: () => import('@/views/nested/menu1/menu1-3'), + name: 'Menu1-3', + meta: { title: 'Menu1-3' } + } + ] + }, + { + path: 'menu2', + component: () => import('@/views/nested/menu2/index'), + name: 'Menu2', + meta: { title: 'menu2' } + } + ] + }, + + { + path: 'external-link', + component: Layout, + children: [ + { + path: 'https://panjiachen.github.io/vue-element-admin-site/#/', + meta: { title: 'External Link', icon: 'link' } + } + ] + }, + + // 404 page must be placed at the end !!! + { path: '*', redirect: '/404', hidden: true } ] const createRouter = () => new Router({ diff --git a/src/store/getters.js b/src/store/getters.js index 1b69f16..5ab7b4c 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -3,9 +3,6 @@ const getters = { device: state => state.app.device, token: state => state.user.token, avatar: state => state.user.avatar, - name: state => state.user.name, - // 新增 - buttons: state => state.user.buttons, - menus: state => state.user.menus + name: state => state.user.name } export default getters diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 35737aa..2f6423f 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,15 +1,12 @@ -import { getInfo, login, logout } from '@/api/user' -import { getToken, removeToken, setToken } from '@/utils/auth' +import { login, logout, getInfo } from '@/api/user' +import { getToken, setToken, removeToken } from '@/utils/auth' import { resetRouter } from '@/router' const getDefaultState = () => { return { token: getToken(), name: '', - avatar: '', - - buttons: [], // 新增 - menus: '' // 新增 + avatar: '' } } @@ -27,14 +24,6 @@ const mutations = { }, SET_AVATAR: (state, avatar) => { state.avatar = avatar - }, - // 新增 - SET_BUTTONS: (state, buttons) => { - state.buttons = buttons - }, - // 新增 - SET_MENUS: (state, menus) => { - state.menus = menus } } @@ -57,7 +46,7 @@ const actions = { // get user info getInfo({ commit, state }) { return new Promise((resolve, reject) => { - getInfo().then(response => { + getInfo(state.token).then(response => { const { data } = response if (!data) { @@ -68,9 +57,6 @@ const actions = { commit('SET_NAME', name) commit('SET_AVATAR', avatar) - - commit('SET_BUTTONS', data.buttons) - commit('SET_MENUS', data.routers) resolve(data) }).catch(error => { reject(error) diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 72b01dc..1db2464 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -1,13 +1,6 @@ diff --git a/vue.config.js b/vue.config.js index e36b2c9..031ad3a 100644 --- a/vue.config.js +++ b/vue.config.js @@ -96,34 +96,34 @@ module.exports = { .plugin('ScriptExtHtmlWebpackPlugin') .after('html') .use('script-ext-html-webpack-plugin', [{ - // `runtime` must same as runtimeChunk name. default is `runtime` + // `runtime` must same as runtimeChunk name. default is `runtime` inline: /runtime\..*\.js$/ }]) .end() config .optimization.splitChunks({ - chunks: 'all', - cacheGroups: { - libs: { - name: 'chunk-libs', - test: /[\\/]node_modules[\\/]/, - priority: 10, - chunks: 'initial' // only package third parties that are initially dependent - }, - elementUI: { - name: 'chunk-elementUI', // split elementUI into a single package - priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app - test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm - }, - commons: { - name: 'chunk-commons', - test: resolve('src/components'), // can customize your rules - minChunks: 3, // minimum common number - priority: 5, - reuseExistingChunk: true + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // only package third parties that are initially dependent + }, + elementUI: { + name: 'chunk-elementUI', // split elementUI into a single package + priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app + test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm + }, + commons: { + name: 'chunk-commons', + test: resolve('src/components'), // can customize your rules + minChunks: 3, // minimum common number + priority: 5, + reuseExistingChunk: true + } } - } - }) + }) // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk config.optimization.runtimeChunk('single') }