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