Files
ReelShortWeb/src/permission.ts
T

117 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Author: fruit.com.cn
import router, { resetRouter } from './router'
import { useAppStoreWithOut } from '@/store/modules/app'
import type { RouteRecordRaw } from 'vue-router'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { NO_REDIRECT_WHITE_LIST } from '@/constants'
import { useUserStoreWithOut } from '@/store/modules/user'
import { getAdminRoleApi, getProfileApi } from '@/api/login'
import { landingPath } from '@/utils/landing'
import { supplementLocalAdminRoutes } from '@/router/localRoutes'
const { start, done } = useNProgress()
const { loadStart, loadDone } = usePageLoading()
router.beforeEach(async (to, from, next) => {
start()
loadStart()
const permissionStore = usePermissionStoreWithOut()
const appStore = useAppStoreWithOut()
const userStore = useUserStoreWithOut()
if (userStore.getUserInfo) {
if (to.path === '/login') {
next({ path: '/' })
} else {
if (permissionStore.getIsAddRouters) {
// 已加过路由:只有还是同一个账号才能直接放行。
// 换账号时(例如超管退出后创作者登录)必须重建,否则侧边栏/路由会残留上一个账号的
const username = userStore.getUserInfo?.username || ''
if (permissionStore.getRoutersOwner === username) {
next()
return
}
// 摘掉上一个账号动态加进去的路由,避免两套菜单并存
resetRouter()
permissionStore.setIsAddRouters(false)
}
const username = userStore.getUserInfo?.username || ''
const ownerChanged = permissionStore.getRoutersOwner !== username
// 开发者可根据实际情况进行修改
const roleRouters = userStore.getRoleRouters || []
// 是否使用动态路由
if (appStore.getDynamicRouter) {
if (appStore.serverDynamicRouter) {
// 每次进入应用都重新拉菜单与权限:后台改了菜单或角色权限,刷新即可生效,不必重新登录
let routers = (userStore.getRoleRouters || []) as AppCustomRouteRecordRaw[]
try {
const [profileRes, menuRes] = await Promise.all([
getProfileApi(),
getAdminRoleApi({ roleName: username })
])
if (profileRes?.data) {
userStore.setUserInfo({ ...userStore.getUserInfo, ...profileRes.data })
}
if (menuRes?.data?.length) {
routers = menuRes.data
userStore.setRoleRouters(routers)
} else if (ownerChanged) {
// 换账号后菜单拉不到就别沿用上一个账号的缓存,宁可先给空菜单
routers = []
}
} catch {
// 拉取失败时退回上次缓存的菜单,不阻塞进入
}
const permissions = Array.isArray(userStore.getUserInfo?.permissions)
? userStore.getUserInfo.permissions
: []
routers = supplementLocalAdminRoutes(routers, permissions)
await permissionStore.generateRoutes('server', routers)
} else {
await permissionStore.generateRoutes('frontEnd', roleRouters as string[])
}
} else {
await permissionStore.generateRoutes('static')
}
permissionStore.getAddRouters.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
})
permissionStore.setRoutersOwner(username)
// 根路径按"这个账号能进的第一个菜单"落地:路由表里写死的 redirect 是 /dashboard/index,
// 创作者没有运营后台权限,访问 '/' 会直接掉 404
if (to.path === '/') {
permissionStore.setIsAddRouters(true)
next({ path: landingPath(), replace: true })
return
}
const redirectPath = from.query.redirect || to.path
const redirect = decodeURIComponent(redirectPath as string)
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
permissionStore.setIsAddRouters(true)
next(nextData)
}
} else {
if (NO_REDIRECT_WHITE_LIST.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
}
}
})
router.afterEach((to) => {
useTitle(to?.meta?.title as string)
done() // 结束Progress
loadDone()
})