mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-15 14:24:39 +00:00
perf: 修改路由守卫 (#1421)
* perf: 修改路由守卫 * perf: 路由守卫 * perf: 去掉 debug * perf: 修改img to * perf: 修改路由 Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
@@ -4,8 +4,7 @@ import NProgress from 'nprogress' // progress bar
|
||||
import 'nprogress/nprogress.css' // progress bar style
|
||||
import { startup } from '@/utils/startup'
|
||||
import store from '@/store'
|
||||
import { getPropView, getRouteViewRequirePerms, hasPermission } from '@/utils/jms'
|
||||
import Vue from 'vue'
|
||||
import { isSameView } from '@/utils/jms'
|
||||
|
||||
NProgress.configure({
|
||||
showSpinner: false
|
||||
@@ -16,7 +15,6 @@ router.beforeEach(async(to, from, next) => {
|
||||
NProgress.start()
|
||||
try {
|
||||
await startup({ to, from, next })
|
||||
await changeCurrentViewIfNeed({ to, from, next })
|
||||
next()
|
||||
} catch (e) {
|
||||
const msg = 'Start service error: ' + e
|
||||
@@ -25,9 +23,8 @@ router.beforeEach(async(to, from, next) => {
|
||||
})
|
||||
|
||||
function generateViewRoutesIfChange({ to, from }) {
|
||||
const fromView = from?.path.split('/')[1]
|
||||
const toView = to?.path.split('/')[1]
|
||||
if (fromView !== toView) {
|
||||
const sameView = isSameView(to, from)
|
||||
if (!sameView) {
|
||||
return store.dispatch('permission/generateViewRoutes', { to: to, from: from })
|
||||
}
|
||||
}
|
||||
@@ -41,25 +38,10 @@ function setPageTitle() {
|
||||
}
|
||||
}
|
||||
|
||||
function changeCurrentViewIfNeed({ to, from, next }) {
|
||||
if (to.path.slice(0, 5) === from.path.slice(0, 5)) {
|
||||
return
|
||||
}
|
||||
const viewRequirePerms = getRouteViewRequirePerms(to)
|
||||
const hasPerm = hasPermission(viewRequirePerms)
|
||||
Vue.$log.debug('Change current view if need: ', viewRequirePerms, hasPerm)
|
||||
if (hasPerm) {
|
||||
Vue.$log.debug('Has current view perm')
|
||||
return
|
||||
}
|
||||
const view = getPropView()
|
||||
next({ name: view })
|
||||
}
|
||||
|
||||
router.afterEach(async(to, from) => {
|
||||
router.afterEach(async(to, from, next) => {
|
||||
// finish progress bar
|
||||
await setPageTitle()
|
||||
NProgress.done()
|
||||
await generateViewRoutesIfChange({ to, from })
|
||||
NProgress.done()
|
||||
})
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import orgUtil from '@/utils/org'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
isCollapse: {
|
||||
@@ -63,23 +64,26 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
const actionObject = {
|
||||
const orgActions = {
|
||||
label: this.$t('xpack.Organization.OrganizationList'),
|
||||
options: [{
|
||||
id: 'create',
|
||||
icon: 'fa-plus',
|
||||
disabled: !this.$hasPerm('orgs.add_organization'),
|
||||
name: this.$t('xpack.Organization.OrganizationCreate')
|
||||
}, {
|
||||
id: 'list',
|
||||
icon: 'fa-list-ul',
|
||||
disabled: !this.$hasPerm('orgs.view_organization'),
|
||||
name: this.$t('xpack.Organization.OrganizationLists')
|
||||
}]
|
||||
options: [
|
||||
{
|
||||
id: 'create',
|
||||
icon: 'fa-plus',
|
||||
disabled: !this.$hasPerm('orgs.add_organization'),
|
||||
name: this.$t('xpack.Organization.OrganizationCreate')
|
||||
},
|
||||
{
|
||||
id: 'list',
|
||||
icon: 'fa-list-ul',
|
||||
disabled: !this.$hasPerm('orgs.view_organization'),
|
||||
name: this.$t('xpack.Organization.OrganizationLists')
|
||||
}
|
||||
]
|
||||
}
|
||||
const hasPerms = this.$hasPerm('orgs.view_organization') || this.$hasPerm('xpack.Organization.OrganizationCreate')
|
||||
const hasPerms = this.$hasPerm('orgs.view_organization | orgs.add_organization')
|
||||
this.orgOption = [
|
||||
(hasPerms && actionObject),
|
||||
(hasPerms && orgActions),
|
||||
{
|
||||
label: this.$t('xpack.Organization.AllOrganization'),
|
||||
options: this.orgs
|
||||
@@ -100,62 +104,70 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/styles/element-variables.scss';
|
||||
.org-select {
|
||||
padding: 0 10px 0 18px;
|
||||
line-height: 55px;
|
||||
background-color: #293846;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
//border-top: solid 1px rgb(47, 64, 80);
|
||||
::v-deep .el-input {
|
||||
input.el-input__inner {
|
||||
line-height: 55px;
|
||||
height: 55px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
@import '~@/styles/element-variables.scss';
|
||||
|
||||
.org-select {
|
||||
padding: 0 10px 0 18px;
|
||||
line-height: 55px;
|
||||
background-color: #293846;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
//border-top: solid 1px rgb(47, 64, 80);
|
||||
::v-deep .el-input {
|
||||
input.el-input__inner {
|
||||
line-height: 55px;
|
||||
height: 55px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.organization {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
background: #E0E0E0;
|
||||
border-radius: 19px;
|
||||
color: #606266;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
left: -16px;
|
||||
content: '';
|
||||
width: 1px;
|
||||
height: 25px;
|
||||
background-color: rgba(144, 147, 152, .5);
|
||||
}
|
||||
|
||||
.organization {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
background: #E0E0E0;
|
||||
border-radius: 19px;
|
||||
& > > > .el-input__prefix {
|
||||
left: 8px
|
||||
}
|
||||
|
||||
& > > > .el-input--prefix .el-input__inner {
|
||||
line-height: 35px !important;
|
||||
height: 35px !important;
|
||||
}
|
||||
|
||||
& > > > .fa-sitemap {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
& > > > .el-input__icon {
|
||||
color: #606266;
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
left: -16px;
|
||||
content: '';
|
||||
width: 1px;
|
||||
height: 25px;
|
||||
background-color: rgba(144,147,152,.5);
|
||||
}
|
||||
&>>> .el-input__prefix {
|
||||
left: 8px
|
||||
}
|
||||
&>>> .el-input--prefix .el-input__inner {
|
||||
line-height: 35px !important;
|
||||
height: 35px !important;
|
||||
}
|
||||
&>>> .fa-sitemap {
|
||||
padding-left: 4px;
|
||||
}
|
||||
&>>> .el-input__icon {
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
.option-group >>> .el-select-group__title {
|
||||
color: #909399 !important;
|
||||
padding-left: 15px;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.option-group > > > .el-select-group__title {
|
||||
color: #909399 !important;
|
||||
padding-left: 15px;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<img :src="logoSrc" class="sidebar-logo">
|
||||
<img :src="logoSrc" class="sidebar-logo" alt="logo">
|
||||
</router-link>
|
||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||
<img :src="logoTextSrc" class="sidebar-logo-text">
|
||||
<img :src="logoTextSrc" class="sidebar-logo-text" alt="logo">
|
||||
</router-link>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,6 @@ export default {
|
||||
'sidebar'
|
||||
]),
|
||||
activeMenu() {
|
||||
console.log('View routes: ', this.currentViewRoute)
|
||||
const route = this.$route
|
||||
const { meta, path } = route
|
||||
// if set path, the sidebar will highlight the path you set
|
||||
|
||||
@@ -49,6 +49,16 @@ export const constantRoutes = [
|
||||
meta: {
|
||||
icon: 'dashboard',
|
||||
title: i18n.t('route.Overview')
|
||||
},
|
||||
beforeEnter: (to, from, next) => {
|
||||
console.log('Enter home view')
|
||||
const preferView = getPermedPreferView()
|
||||
if (preferView) {
|
||||
console.log('Go to preferView: ', preferView)
|
||||
next(`/${preferView}/`)
|
||||
return false
|
||||
}
|
||||
next()
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -73,6 +83,7 @@ import workspaceViewRoutes from './workspace'
|
||||
import ticketsRoutes from './tickets'
|
||||
import settingsRoutes from './settings'
|
||||
import profileRoutes from './profile'
|
||||
import { getPermedPreferView } from '@/utils/jms'
|
||||
|
||||
/**
|
||||
* admin
|
||||
|
||||
@@ -182,6 +182,7 @@ const actions = {
|
||||
if (!matched) {
|
||||
Vue.$log.debug('Not match path, set default routes', path)
|
||||
commit('SET_VIEW_ROUTE', constantRoutes[0])
|
||||
resolve(constantRoutes[0])
|
||||
return
|
||||
}
|
||||
const viewName = matched[1]
|
||||
@@ -189,12 +190,14 @@ const actions = {
|
||||
for (const route of state.routes) {
|
||||
if (route.meta?.view === viewName) {
|
||||
viewRoute = route
|
||||
break
|
||||
}
|
||||
}
|
||||
if (viewRoute.meta?.showNavSwitcher) {
|
||||
localStorage.setItem('PreView', viewName)
|
||||
}
|
||||
commit('SET_VIEW_ROUTE', viewRoute)
|
||||
resolve(viewRoute)
|
||||
})
|
||||
},
|
||||
generateRoutes({ commit, dispatch, rootState }, { to, from }) {
|
||||
@@ -207,7 +210,6 @@ const actions = {
|
||||
Vue.$log.debug('All routes: ', routes)
|
||||
}
|
||||
commit('SET_ROUTES', { routes })
|
||||
dispatch('generateViewRoutes', { from, to })
|
||||
resolve(routes)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -89,13 +89,7 @@ export function getViewRequirePerms(view) {
|
||||
return viewRequirePermsMapper[view] || 'super'
|
||||
}
|
||||
|
||||
export function getPropView() {
|
||||
const preView = localStorage.getItem('PreView')
|
||||
const preViewRequirePerms = getViewRequirePerms(preView)
|
||||
const hasPerm = hasPermission(preViewRequirePerms)
|
||||
if (hasPerm) {
|
||||
return preView
|
||||
}
|
||||
export function getPermedPreferView() {
|
||||
for (const [view, perms] of Object.entries(viewRequirePermsMapper)) {
|
||||
const hasPerm = hasPermission(perms)
|
||||
Vue.$log.debug('Has view perm: ', view, hasPerm)
|
||||
@@ -103,7 +97,26 @@ export function getPropView() {
|
||||
return view
|
||||
}
|
||||
}
|
||||
return 'home'
|
||||
}
|
||||
|
||||
export function isSameView(to, from) {
|
||||
const fromView = from?.path.split('/')[1]
|
||||
const toView = to?.path.split('/')[1]
|
||||
return fromView === toView
|
||||
}
|
||||
|
||||
export function getPropView() {
|
||||
const preView = localStorage.getItem('PreView')
|
||||
const preViewRequirePerms = getViewRequirePerms(preView)
|
||||
const hasPerm = hasPermission(preViewRequirePerms)
|
||||
if (hasPerm) {
|
||||
return preView
|
||||
}
|
||||
const preferView = getPermedPreferView()
|
||||
if (preferView) {
|
||||
return preferView
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export function getApiUrlRequirePerms(url, action) {
|
||||
@@ -115,3 +128,9 @@ export function getRouteViewRequirePerms(route) {
|
||||
const viewName = route.path.split('/')[1]
|
||||
return getViewRequirePerms(viewName)
|
||||
}
|
||||
|
||||
export function hasRouteViewPerm(route) {
|
||||
const viewName = route.path.split('/')[1]
|
||||
const perms = getViewRequirePerms(viewName)
|
||||
return hasPermission(perms)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'nprogress/nprogress.css' // progress bar style
|
||||
import { getTokenFromCookie } from '@/utils/auth'
|
||||
import orgUtil from '@/utils/org'
|
||||
import { getCurrentOrg } from '@/api/orgs'
|
||||
import { getPropView, hasRouteViewPerm, isSameView } from '@/utils/jms'
|
||||
|
||||
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
|
||||
let initial = false
|
||||
@@ -84,8 +85,11 @@ export async function generatePageRoutes({ to, from, next }) {
|
||||
const accessRoutes = await store.dispatch('permission/generateRoutes', { to, from })
|
||||
|
||||
// dynamically add accessible routes
|
||||
Vue.$log.debug('All routes: ', accessRoutes)
|
||||
router.addRoutes(accessRoutes)
|
||||
|
||||
await store.dispatch('permission/generateViewRoutes', { to, from })
|
||||
|
||||
// hack method to ensure that addRoutes is complete
|
||||
// set the replace: true, so the navigation will not leave a history record
|
||||
// Vue.$log.debug('Next to: ', to)
|
||||
@@ -104,6 +108,21 @@ export async function checkUserFirstLogin({ to, from, next }) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function changeCurrentViewIfNeed({ to, from, next }) {
|
||||
if (!to.path || isSameView(to, from)) {
|
||||
return
|
||||
}
|
||||
const hasPerm = hasRouteViewPerm(to)
|
||||
Vue.$log.debug('Change current view if need: ', hasPerm)
|
||||
if (hasPerm) {
|
||||
Vue.$log.debug('Has current view perm')
|
||||
return
|
||||
}
|
||||
const view = getPropView()
|
||||
Vue.$log.debug('Get prop view and goto: ', view)
|
||||
next(`/${view}`)
|
||||
}
|
||||
|
||||
export async function startup({ to, from, next }) {
|
||||
if (initial) {
|
||||
return true
|
||||
@@ -116,6 +135,7 @@ export async function startup({ to, from, next }) {
|
||||
await checkLogin({ to, from, next })
|
||||
await changeCurrentOrgIfNeed({ to, from, next })
|
||||
await generatePageRoutes({ to, from, next })
|
||||
await changeCurrentViewIfNeed({ to, from, next })
|
||||
await checkUserFirstLogin({ to, from, next })
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user