动态路由
This commit is contained in:
parent
ff40c9afa0
commit
a665afac52
|
@ -9,7 +9,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { domTitle, setDocumentTitle } from '@/utils/domUtil'
|
import { domTitle, setDocumentTitle } from '@/utils/domUtil'
|
||||||
import { i18nRender } from '@/locales'
|
import { i18nRender } from '@/locales'
|
||||||
import { mapActions } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
|
@ -23,12 +22,6 @@ export default {
|
||||||
title && (setDocumentTitle(`${i18nRender(title)} - ${domTitle}`))
|
title && (setDocumentTitle(`${i18nRender(title)} - ${domTitle}`))
|
||||||
return this.$i18n.getLocaleMessage(this.$store.getters.lang).antLocale
|
return this.$i18n.getLocaleMessage(this.$store.getters.lang).antLocale
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['InitAccessToken'])
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.InitAccessToken()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,80 +1,40 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
const userApi = {
|
const userApi = {
|
||||||
Login: '/auth/login',
|
login: '/login',
|
||||||
Logout: '/auth/logout',
|
logout: '/logout',
|
||||||
ForgePassword: '/auth/forge-password',
|
getLoginUser: '/getLoginUser'
|
||||||
Register: '/auth/register',
|
|
||||||
twoStepCode: '/auth/2step-code',
|
|
||||||
SendSms: '/account/sms',
|
|
||||||
SendSmsErr: '/account/sms_err',
|
|
||||||
// get my info
|
|
||||||
UserInfo: '/user/info',
|
|
||||||
UserMenu: '/user/nav'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* login func
|
|
||||||
* parameter: {
|
|
||||||
* username: '',
|
|
||||||
* password: '',
|
|
||||||
* remember_me: true,
|
|
||||||
* captcha: '12345'
|
|
||||||
* }
|
|
||||||
* @param parameter
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
export function login (parameter) {
|
export function login (parameter) {
|
||||||
return request({
|
return request({
|
||||||
url: userApi.Login,
|
url: userApi.login,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: parameter
|
data: parameter
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSmsCaptcha (parameter) {
|
export function getLoginUser () {
|
||||||
return request({
|
return request({
|
||||||
url: userApi.SendSms,
|
url: userApi.getLoginUser,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: parameter
|
data: parameter
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInfo () {
|
|
||||||
return request({
|
|
||||||
url: userApi.UserInfo,
|
|
||||||
method: 'get',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json;charset=UTF-8'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCurrentUserNav () {
|
|
||||||
return request({
|
|
||||||
url: userApi.UserMenu,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logout () {
|
export function logout () {
|
||||||
return request({
|
return request({
|
||||||
url: userApi.Logout,
|
url: userApi.logout,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json;charset=UTF-8'
|
'Content-Type': 'application/json;charset=UTF-8'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function getSmsCaptcha (parameter) {
|
||||||
/**
|
return axios({
|
||||||
* get user 2step code open?
|
url: '/getSmsCaptcha',
|
||||||
* @param parameter {*}
|
method: 'get',
|
||||||
*/
|
params: parameter
|
||||||
export function get2step (parameter) {
|
|
||||||
return request({
|
|
||||||
url: userApi.twoStepCode,
|
|
||||||
method: 'post',
|
|
||||||
data: parameter
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,10 @@
|
||||||
* storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)
|
* storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
navTheme: 'dark', // theme for nav menu
|
navTheme: 'light', // theme for nav menu
|
||||||
primaryColor: '#1890ff', // primary color of ant design
|
primaryColor: '#1890ff', // primary color of ant design
|
||||||
layout: 'topmenu', // nav menu position: `sidemenu` or `topmenu`
|
layout: 'sidemenu', // nav menu position: `sidemenu` or `topmenu`
|
||||||
contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu
|
contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu
|
||||||
fixedHeader: false, // sticky header
|
fixedHeader: false, // sticky header
|
||||||
fixSiderbar: false, // sticky siderbar
|
fixSiderbar: false, // sticky siderbar
|
||||||
|
@ -23,7 +22,7 @@ export default {
|
||||||
menu: {
|
menu: {
|
||||||
locale: true
|
locale: true
|
||||||
},
|
},
|
||||||
title: '系统后台',
|
title: '安全培训平台',
|
||||||
pwa: false,
|
pwa: false,
|
||||||
iconfontUrl: '',
|
iconfontUrl: '',
|
||||||
production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true'
|
production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true'
|
||||||
|
|
|
@ -11,11 +11,9 @@
|
||||||
:i18nRender="i18nRender"
|
:i18nRender="i18nRender"
|
||||||
v-bind="settings"
|
v-bind="settings"
|
||||||
>
|
>
|
||||||
<!-- <setting-drawer :settings="settings" @change="handleSettingChange" /> -->
|
|
||||||
<template v-slot:rightContentRender>
|
<template v-slot:rightContentRender>
|
||||||
<right-content :top-menu="settings.layout === 'topmenu'" :is-mobile="isMobile" :theme="settings.theme" />
|
<right-content :top-menu="settings.layout === 'topmenu'" :is-mobile="isMobile" :theme="settings.theme" />
|
||||||
</template>
|
</template>
|
||||||
<!-- <multi-tab></multi-tab> -->
|
|
||||||
<template v-slot:footerRender>
|
<template v-slot:footerRender>
|
||||||
<global-footer />
|
<global-footer />
|
||||||
</template>
|
</template>
|
||||||
|
@ -24,25 +22,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { updateTheme } from '@ant-design-vue/pro-layout'
|
|
||||||
import { i18nRender } from '@/locales'
|
import { i18nRender } from '@/locales'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import { SIDEBAR_TYPE, TOGGLE_MOBILE_TYPE } from '@/store/mutation-types'
|
import { SIDEBAR_TYPE, TOGGLE_MOBILE_TYPE } from '@/store/mutation-types'
|
||||||
import { asyncRouterMap } from '@/config/router.config.js'
|
|
||||||
|
|
||||||
import defaultSettings from '@/config/defaultSettings'
|
import defaultSettings from '@/config/defaultSettings'
|
||||||
import RightContent from '@/components/GlobalHeader/RightContent'
|
import RightContent from '@/components/GlobalHeader/RightContent'
|
||||||
import GlobalFooter from '@/components/GlobalFooter'
|
import GlobalFooter from '@/components/GlobalFooter'
|
||||||
import MultiTab from '@/components/MultiTab'
|
|
||||||
import LogoSvg from '../assets/logo.svg?inline'
|
import LogoSvg from '../assets/logo.svg?inline'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BasicLayout',
|
name: 'BasicLayout',
|
||||||
components: {
|
components: {
|
||||||
// SettingDrawer,
|
|
||||||
RightContent,
|
RightContent,
|
||||||
GlobalFooter,
|
GlobalFooter
|
||||||
MultiTab
|
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -63,13 +56,11 @@ export default {
|
||||||
fixedHeader: defaultSettings.fixedHeader,
|
fixedHeader: defaultSettings.fixedHeader,
|
||||||
fixSiderbar: defaultSettings.fixSiderbar,
|
fixSiderbar: defaultSettings.fixSiderbar,
|
||||||
colorWeak: defaultSettings.colorWeak,
|
colorWeak: defaultSettings.colorWeak,
|
||||||
|
|
||||||
hideHintAlert: false,
|
hideHintAlert: false,
|
||||||
hideCopyButton: false
|
hideCopyButton: false
|
||||||
},
|
},
|
||||||
// 媒体查询
|
// 媒体查询
|
||||||
query: {},
|
query: {},
|
||||||
|
|
||||||
// 是否手机模式
|
// 是否手机模式
|
||||||
isMobile: false
|
isMobile: false
|
||||||
}
|
}
|
||||||
|
@ -81,16 +72,15 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
// const routes = this.mainMenu.find(item => item.path === '/')
|
const routes = this.mainMenu.find(item => item.path === '/')
|
||||||
// this.menus = (routes && routes.children) || []
|
this.menus = (routes && routes.children) || []
|
||||||
this.menus = asyncRouterMap.find((item) => item.path === '/').children
|
// 处理侧栏收起状态
|
||||||
// 处理侧栏收起状态
|
this.$watch('collapsed', () => {
|
||||||
this.$watch('collapsed', () => {
|
this.$store.commit(SIDEBAR_TYPE, this.collapsed)
|
||||||
this.$store.commit(SIDEBAR_TYPE, this.collapsed)
|
})
|
||||||
})
|
this.$watch('isMobile', () => {
|
||||||
this.$watch('isMobile', () => {
|
this.$store.commit(TOGGLE_MOBILE_TYPE, this.isMobile)
|
||||||
this.$store.commit(TOGGLE_MOBILE_TYPE, this.isMobile)
|
})
|
||||||
})
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
const userAgent = navigator.userAgent
|
const userAgent = navigator.userAgent
|
||||||
|
@ -102,12 +92,6 @@ export default {
|
||||||
}, 16)
|
}, 16)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// first update color
|
|
||||||
// TIPS: THEME COLOR HANDLER!! PLEASE CHECK THAT!!
|
|
||||||
if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') {
|
|
||||||
updateTheme(this.settings.primaryColor)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
i18nRender,
|
i18nRender,
|
||||||
|
@ -127,23 +111,6 @@ export default {
|
||||||
handleCollapse (val) {
|
handleCollapse (val) {
|
||||||
this.collapsed = val
|
this.collapsed = val
|
||||||
},
|
},
|
||||||
handleSettingChange ({ type, value }) {
|
|
||||||
console.log('type', type, value)
|
|
||||||
type && (this.settings[type] = value)
|
|
||||||
switch (type) {
|
|
||||||
case 'contentWidth':
|
|
||||||
this.settings[type] = value === 'Fixed'
|
|
||||||
break
|
|
||||||
case 'layout':
|
|
||||||
if (value === 'sidemenu') {
|
|
||||||
this.settings.contentWidth = false
|
|
||||||
} else {
|
|
||||||
this.settings.fixSiderbar = false
|
|
||||||
this.settings.contentWidth = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
logoRender () {
|
logoRender () {
|
||||||
return <LogoSvg />
|
return <LogoSvg />
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const loginRoutePath = '/user/login'
|
||||||
const defaultRoutePath = '/dashboard/workplace'
|
const defaultRoutePath = '/dashboard/workplace'
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
console.log("判断路由")
|
debugger
|
||||||
NProgress.start() // start progress bar
|
NProgress.start() // start progress bar
|
||||||
to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`))
|
to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`))
|
||||||
/* has token */
|
/* has token */
|
||||||
|
@ -24,16 +24,30 @@ router.beforeEach((to, from, next) => {
|
||||||
next({ path: defaultRoutePath })
|
next({ path: defaultRoutePath })
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else {
|
} else {
|
||||||
// check login user.roles is null
|
|
||||||
if (store.getters.roles.length === 0) {
|
if (store.getters.roles.length === 0) {
|
||||||
// request login userInfo
|
console.log('逻辑开始1 => src/permission.js')
|
||||||
store
|
store
|
||||||
.dispatch('GetInfo')
|
.dispatch('GetInfo')
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const roles = res.result && res.result.role
|
console.log('流程3-获取个人信息返回 => src/permission.js ')
|
||||||
|
if (res.menus.length < 1) {
|
||||||
|
Modal.error({
|
||||||
|
title: '提示:',
|
||||||
|
content: '无菜单权限,请联系管理员',
|
||||||
|
okText: '确定',
|
||||||
|
onOk: () => {
|
||||||
|
store.dispatch('Logout').then(() => {
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const antDesignMenus = res.menus
|
||||||
// generate dynamic router
|
// generate dynamic router
|
||||||
store.dispatch('GenerateRoutes', { roles }).then(() => {
|
console.log('流程4-从后端获取权限开始')
|
||||||
// 根据roles权限生成可访问的路由表
|
store.dispatch('GenerateRoutes', { antDesignMenus }).then(() => {
|
||||||
|
// 根据菜单权限生成可访问的路由表
|
||||||
// 动态添加可访问路由表
|
// 动态添加可访问路由表
|
||||||
router.addRoutes(store.getters.addRouters)
|
router.addRoutes(store.getters.addRouters)
|
||||||
// 请求带有 redirect 重定向时,登录自动重定向到该地址
|
// 请求带有 redirect 重定向时,登录自动重定向到该地址
|
||||||
|
@ -48,11 +62,6 @@ router.beforeEach((to, from, next) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
notification.error({
|
|
||||||
message: '错误',
|
|
||||||
description: '请求用户信息失败,请重试'
|
|
||||||
})
|
|
||||||
// 失败时,获取用户信息失败时,调用登出,来清空历史保留信息
|
|
||||||
store.dispatch('Logout').then(() => {
|
store.dispatch('Logout').then(() => {
|
||||||
next({ path: loginRoutePath, query: { redirect: to.fullPath } })
|
next({ path: loginRoutePath, query: { redirect: to.fullPath } })
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import * as loginService from '@/api/login'
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import { BasicLayout, BlankLayout, PageView, RouteView } from '@/layouts'
|
import { BasicLayout, BlankLayout, PageView, RouteView } from '@/layouts'
|
||||||
|
|
||||||
|
@ -16,39 +15,6 @@ const constantRouterComponents = {
|
||||||
|
|
||||||
// 你需要动态引入的页面组件
|
// 你需要动态引入的页面组件
|
||||||
'Workplace': () => import('@/views/dashboard/Workplace'),
|
'Workplace': () => import('@/views/dashboard/Workplace'),
|
||||||
// form
|
|
||||||
'BasicForm': () => import('@/views/form/basicForm/Index'),
|
|
||||||
'StepForm': () => import('@/views/form/stepForm/StepForm'),
|
|
||||||
'AdvanceForm': () => import('@/views/form/advancedForm/AdvancedForm'),
|
|
||||||
|
|
||||||
// list
|
|
||||||
'TableList': () => import('@/views/list/TableList'),
|
|
||||||
'StandardList': () => import('@/views/list/StandardList'),
|
|
||||||
'CardList': () => import('@/views/list/CardList'),
|
|
||||||
'SearchLayout': () => import('@/views/list/search/SearchLayout'),
|
|
||||||
'SearchArticles': () => import('@/views/list/search/Article'),
|
|
||||||
'SearchProjects': () => import('@/views/list/search/Projects'),
|
|
||||||
'SearchApplications': () => import('@/views/list/search/Applications'),
|
|
||||||
'ProfileBasic': () => import('@/views/profile/basic/Index'),
|
|
||||||
'ProfileAdvanced': () => import('@/views/profile/advanced/Advanced'),
|
|
||||||
|
|
||||||
// result
|
|
||||||
'ResultSuccess': () => import(/* webpackChunkName: "result" */ '@/views/result/Success'),
|
|
||||||
'ResultFail': () => import(/* webpackChunkName: "result" */ '@/views/result/Error'),
|
|
||||||
|
|
||||||
// exception
|
|
||||||
'Exception403': () => import(/* webpackChunkName: "fail" */ '@/views/exception/403'),
|
|
||||||
'Exception404': () => import(/* webpackChunkName: "fail" */ '@/views/exception/404'),
|
|
||||||
'Exception500': () => import(/* webpackChunkName: "fail" */ '@/views/exception/500'),
|
|
||||||
|
|
||||||
// account
|
|
||||||
'AccountCenter': () => import('@/views/account/center/Index'),
|
|
||||||
'AccountSettings': () => import('@/views/account/settings/Index'),
|
|
||||||
'BaseSettings': () => import('@/views/account/settings/BaseSetting'),
|
|
||||||
'SecuritySettings': () => import('@/views/account/settings/Security'),
|
|
||||||
'CustomSettings': () => import('@/views/account/settings/Custom'),
|
|
||||||
'BindingSettings': () => import('@/views/account/settings/Binding'),
|
|
||||||
'NotificationSettings': () => import('@/views/account/settings/Notification')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 前端未找到页面路由(固定不用改)
|
// 前端未找到页面路由(固定不用改)
|
||||||
|
@ -58,14 +24,10 @@ const notFoundRouter = {
|
||||||
|
|
||||||
// 根级菜单
|
// 根级菜单
|
||||||
const rootRouter = {
|
const rootRouter = {
|
||||||
key: '',
|
path: '/',
|
||||||
name: 'index',
|
name: 'index',
|
||||||
path: '',
|
|
||||||
component: 'BasicLayout',
|
component: 'BasicLayout',
|
||||||
redirect: '/dashboard',
|
meta: { title: '首页' },
|
||||||
meta: {
|
|
||||||
title: '首页'
|
|
||||||
},
|
|
||||||
children: []
|
children: []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,24 +36,26 @@ const rootRouter = {
|
||||||
* @param token
|
* @param token
|
||||||
* @returns {Promise<Router>}
|
* @returns {Promise<Router>}
|
||||||
*/
|
*/
|
||||||
export const generatorDynamicRouter = (token) => {
|
export const generatorDynamicRouter = (data) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
loginService.getCurrentUserNav(token).then(res => {
|
console.log('流程5-后端返回的权限菜单:generatorDynamicRouter')
|
||||||
const { result } = res
|
console.log(data)
|
||||||
const menuNav = []
|
const resNav = data.antDesignMenus
|
||||||
const childrenNav = []
|
const menuNav = []
|
||||||
// 后端数据, 根级树数组, 根级 PID
|
const childrenNav = []
|
||||||
listToTree(result, childrenNav, 0)
|
// 后端数据, 根级树数组, 根级 PID
|
||||||
rootRouter.children = childrenNav
|
listToTree(resNav, childrenNav, 0)
|
||||||
menuNav.push(rootRouter)
|
rootRouter.children = childrenNav
|
||||||
// console.log('menuNav', menuNav)
|
if (childrenNav.length > 0) {
|
||||||
const routers = generator(menuNav)
|
rootRouter.redirect = childrenNav[0].path
|
||||||
routers.push(notFoundRouter)
|
}
|
||||||
// console.log('routers', routers)
|
menuNav.push(rootRouter)
|
||||||
resolve(routers)
|
const routers = generator(menuNav)
|
||||||
}).catch(err => {
|
routers.push(notFoundRouter)
|
||||||
reject(err)
|
resolve(routers)
|
||||||
})
|
}).catch(err => {
|
||||||
|
// reject('加载菜单失败')
|
||||||
|
return Promise.reject(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
import { constantRouterMap, asyncRouterMap } from '@/config/router.config'
|
import { constantRouterMap } from '@/config/router.config'
|
||||||
|
|
||||||
// hack router push callback
|
// hack router push callback
|
||||||
const originalPush = Router.prototype.push
|
const originalPush = Router.prototype.push
|
||||||
Router.prototype.push = function push(location, onResolve, onReject) {
|
Router.prototype.push = function push (location, onResolve, onReject) {
|
||||||
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
|
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
|
||||||
return originalPush.call(this, location).catch(err => err)
|
return originalPush.call(this, location).catch(err => err)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ Router.prototype.push = function push(location, onResolve, onReject) {
|
||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
export default new Router({
|
export default new Router({
|
||||||
mode: 'hash', // history
|
mode: 'history',
|
||||||
// base: process.env.BASE_URL,
|
base: process.env.VUE_APP_PUBLIC_PATH,
|
||||||
scrollBehavior: () => ({ y: 0 }),
|
routes: constantRouterMap
|
||||||
routes: constantRouterMap.concat(asyncRouterMap)
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,11 +18,14 @@ const permission = {
|
||||||
actions: {
|
actions: {
|
||||||
GenerateRoutes ({ commit }, data) {
|
GenerateRoutes ({ commit }, data) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const { token } = data
|
console.log('动态生成路由:GenerateRoutes async-router 111')
|
||||||
generatorDynamicRouter(token).then(routers => {
|
generatorDynamicRouter(data).then(routers => {
|
||||||
commit('SET_ROUTERS', routers)
|
commit('SET_ROUTERS', routers)
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
}).catch(err => {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
reject(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,16 @@ import { asyncRouterMap, constantRouterMap } from '@/config/router.config'
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function hasPermission (permission, route) {
|
function hasPermission (permission, route) {
|
||||||
if (route.meta && route.meta.permission) {
|
// if (route.meta && route.meta.permission) {
|
||||||
let flag = false
|
// let flag = false
|
||||||
for (let i = 0, len = permission.length; i < len; i++) {
|
// for (let i = 0, len = permission.length; i < len; i++) {
|
||||||
flag = route.meta.permission.includes(permission[i])
|
// flag = route.meta.permission.includes(permission[i])
|
||||||
if (flag) {
|
// if (flag) {
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +64,10 @@ const permission = {
|
||||||
actions: {
|
actions: {
|
||||||
GenerateRoutes ({ commit }, data) {
|
GenerateRoutes ({ commit }, data) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
console.log('src/store/下的permission.js')
|
||||||
const { roles } = data
|
const { roles } = data
|
||||||
const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
|
const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
|
||||||
|
console.log('动态获取到的菜单列表:'+JSON.stringify(accessedRouters))
|
||||||
commit('SET_ROUTERS', accessedRouters)
|
commit('SET_ROUTERS', accessedRouters)
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import storage from 'store'
|
import storage from 'store'
|
||||||
import { userLogin, getInfo } from '@/api/security/user'
|
import { login, getLoginUser, logout } from '@/api/login'
|
||||||
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||||
import { welcome } from '@/utils/util'
|
import { welcome } from '@/utils/util'
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ const user = {
|
||||||
welcome: '',
|
welcome: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
roles: [],
|
roles: [],
|
||||||
|
buttons: [], // 按钮权限
|
||||||
info: {}
|
info: {}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -29,6 +30,9 @@ const user = {
|
||||||
},
|
},
|
||||||
SET_INFO: (state, info) => {
|
SET_INFO: (state, info) => {
|
||||||
state.info = info
|
state.info = info
|
||||||
|
},
|
||||||
|
SET_BUTTONS: (state, buttons) => {
|
||||||
|
state.buttons = buttons
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -36,7 +40,7 @@ const user = {
|
||||||
// 登录
|
// 登录
|
||||||
Login ({ commit }, userInfo) {
|
Login ({ commit }, userInfo) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
userLogin(userInfo).then(response => {
|
login(userInfo).then(response => {
|
||||||
storage.set(ACCESS_TOKEN, response.token, 24 * 60 * 60 * 1000)
|
storage.set(ACCESS_TOKEN, response.token, 24 * 60 * 60 * 1000)
|
||||||
commit('SET_TOKEN', response.token)
|
commit('SET_TOKEN', response.token)
|
||||||
resolve()
|
resolve()
|
||||||
|
@ -49,39 +53,41 @@ const user = {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
GetInfo ({ commit }) {
|
GetInfo ({ commit }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getInfo().then(response => {
|
getLoginUser().then(response => {
|
||||||
const result = response.result
|
if (response.code === 200) {
|
||||||
if (result.role && result.role.permissions.length > 0) {
|
const data = response.data
|
||||||
const role = result.role
|
console.log('流程2-获取到个人信息 => user.js')
|
||||||
role.permissions = result.role.permissions
|
console.log(data)
|
||||||
role.permissions.map(per => {
|
commit('SET_ROLES', 1)
|
||||||
if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
|
commit('SET_BUTTONS', data.permissions)
|
||||||
const action = per.actionEntitySet.map(action => { return action.action })
|
commit('SET_INFO', data)
|
||||||
per.actionList = action
|
commit('SET_NAME', { name: data.userName, welcome: welcome() })
|
||||||
}
|
if (data.avatar != null) {
|
||||||
})
|
commit('SET_AVATAR', process.env.VUE_APP_API_BASE_URL + '/sysFileInfo/preview?id=' + data.avatar)
|
||||||
role.permissionList = role.permissions.map(permission => { return permission.permissionId })
|
}
|
||||||
commit('SET_ROLES', result.role)
|
resolve(data)
|
||||||
commit('SET_INFO', result)
|
|
||||||
} else {
|
} else {
|
||||||
reject(new Error('getInfo: roles must be a non-null array !'))
|
// eslint-disable-next-line no-undef
|
||||||
|
reject(new Error(data.message))
|
||||||
}
|
}
|
||||||
commit('SET_NAME', { name: result.name, welcome: welcome() })
|
|
||||||
commit('SET_AVATAR', result.avatar)
|
|
||||||
resolve(response)
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 登出
|
// 登出
|
||||||
Logout ({ commit, state }) {
|
Logout ({ commit, state }) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
commit('SET_TOKEN', '')
|
logout(state.token).then(() => {
|
||||||
commit('SET_ROLES', [])
|
resolve()
|
||||||
storage.remove(ACCESS_TOKEN)
|
}).catch(() => {
|
||||||
resolve()
|
resolve()
|
||||||
|
}).finally(() => {
|
||||||
|
commit('SET_TOKEN', '')
|
||||||
|
commit('SET_ROLES', [])
|
||||||
|
commit('SET_BUTTONS', [])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-operator">
|
<div class="table-operator">
|
||||||
<a-button type="primary" icon="plus" @click="$refs.menuForm.add()">新增菜单</a-button>
|
<a-button type="primary" icon="plus" @click="$refs.menuForm.add()">新增菜单</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<s-table
|
<s-table
|
||||||
ref="table"
|
ref="table"
|
||||||
:rowKey="(record) => record.id"
|
:rowKey="(record) => record.id"
|
||||||
|
@ -110,7 +110,8 @@ export default {
|
||||||
],
|
],
|
||||||
loadData: parameter => {
|
loadData: parameter => {
|
||||||
return menuList(Object.assign(parameter, this.queryParam)).then((res) => {
|
return menuList(Object.assign(parameter, this.queryParam)).then((res) => {
|
||||||
return res.data
|
const menuList = listToTree(res.data, [], rootParentId)
|
||||||
|
return menuList
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,8 +134,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleDel (record) {
|
handleDel (record) {
|
||||||
menuDel({id: record.id, deleteReason: ""}).then((res) => {
|
menuDel({ id: record.id, deleteReason: '' }).then((res) => {
|
||||||
if (res.code == 200) {
|
if (res.code === 200) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
this.$refs.table.refresh()
|
this.$refs.table.refresh()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,33 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<a-form id="formLogin" class="user-layout-login" ref="formLogin" :form="form" @submit="handleSubmit">
|
<a-form-model ref="ruleForm" class="user-layout-login" :model="form" :rules="rules" @submit.prevent="handleSubmit">
|
||||||
<a-alert v-if="isLoginError" type="error" showIcon style="margin-bottom: 24px;" message="账户或密码错误(18729260811/a123456789 )" />
|
<a-form-model-item>
|
||||||
<a-form-item>
|
<a-input size="large" v-model="form.username" placeholder="请输入用户名">
|
||||||
<a-input size="large" type="text" placeholder="账户: 18729260811" v-decorator="[
|
<a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)" />
|
||||||
'mobile',
|
|
||||||
{rules: [{ required: true, message: '请输入帐户名或邮箱地址' }], validateTrigger: 'change'}
|
|
||||||
]">
|
|
||||||
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }" />
|
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-model-item>
|
||||||
|
<a-form-model-item>
|
||||||
<a-form-item>
|
<a-input-password size="large" v-model="form.password" placeholder="请输入密码">
|
||||||
<a-input-password size="large" placeholder="密码: a123456789" v-decorator="[
|
<a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
|
||||||
'password',
|
|
||||||
{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}
|
|
||||||
]">
|
|
||||||
<a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }" />
|
|
||||||
</a-input-password>
|
</a-input-password>
|
||||||
</a-form-item>
|
</a-form-model-item>
|
||||||
<a-form-item>
|
<a-form-model-item>
|
||||||
<a-checkbox v-decorator="['rememberMe', { valuePropName: 'checked' }]">自动登录</a-checkbox>
|
<a-button block type="primary" size="large" html-type="submit" :loading="loading">登录</a-button>
|
||||||
<router-link :to="{ name: 'recover', params: { user: 'aaa'} }" class="forge-password" style="float: right;">忘记密码</router-link>
|
</a-form-model-item>
|
||||||
</a-form-item>
|
</a-form-model>
|
||||||
|
|
||||||
<a-form-item style="margin-top:24px">
|
|
||||||
<a-button size="large" type="primary" htmlType="submit" class="login-button" :loading="state.loginBtn" :disabled="state.loginBtn">确定</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -36,53 +23,42 @@ import { mapActions } from 'vuex'
|
||||||
import { timeFix } from '@/utils/util'
|
import { timeFix } from '@/utils/util'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
loginBtn: false,
|
form: {
|
||||||
loginType: 0,
|
username: 'admin',
|
||||||
isLoginError: false,
|
password: 'daobang123'
|
||||||
form: this.$form.createForm(this),
|
},
|
||||||
state: {
|
rules: {
|
||||||
time: 60,
|
username: [{ required: true, message: '请输入用户名' }],
|
||||||
loginBtn: false,
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||||
loginType: 0
|
},
|
||||||
}
|
loading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['Login', 'Logout']),
|
...mapActions(['Login', 'Logout']),
|
||||||
handleSubmit(e) {
|
handleSubmit () {
|
||||||
e.preventDefault()
|
if (this.loading) {
|
||||||
const {
|
return false
|
||||||
form: { validateFields },
|
}
|
||||||
state,
|
this.loading = false
|
||||||
Login
|
this.$refs.ruleForm.validate(valid => {
|
||||||
} = this
|
const { form } = this
|
||||||
|
if (valid) {
|
||||||
state.loginBtn = true
|
this.Login(form).then(() => {
|
||||||
|
this.loginSuccess()
|
||||||
const validateFieldsKey = ['mobile', 'password']
|
}, () => {
|
||||||
|
this.requestFailed()
|
||||||
validateFields(validateFieldsKey, { force: true }, (err, values) => {
|
})
|
||||||
if (!err) {
|
|
||||||
const loginParams = { ...values }
|
|
||||||
delete loginParams.username
|
|
||||||
loginParams[!state.loginType ? 'email' : 'username'] = values.username
|
|
||||||
loginParams.password = values.password
|
|
||||||
Login(loginParams)
|
|
||||||
.then((res) => this.loginSuccess(res))
|
|
||||||
.catch(err => this.requestFailed(err))
|
|
||||||
.finally(() => {
|
|
||||||
state.loginBtn = false
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
this.loading = false
|
||||||
state.loginBtn = false
|
return false
|
||||||
}, 600)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
loginSuccess(res) {
|
loginSuccess (res) {
|
||||||
|
this.loading = false
|
||||||
this.$router.push({ path: '/' })
|
this.$router.push({ path: '/' })
|
||||||
// 延迟 1 秒显示欢迎信息
|
// 延迟 1 秒显示欢迎信息
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -91,33 +67,13 @@ export default {
|
||||||
description: `${timeFix()},欢迎回来`
|
description: `${timeFix()},欢迎回来`
|
||||||
})
|
})
|
||||||
}, 1000)
|
}, 1000)
|
||||||
this.isLoginError = false
|
|
||||||
},
|
},
|
||||||
requestFailed() {
|
requestFailed () {
|
||||||
this.isLoginError = true
|
this.loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.user-layout-login {
|
|
||||||
label {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.getCaptcha {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
.forge-password {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
button.login-button {
|
|
||||||
padding: 0 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
height: 40px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue