20260921231313
This commit is contained in:
1 parent
ac710c1801
commit
583984c24f
81 files changed
+2523
-288
No files matched your search
@@ -20,7 +20,7 @@ const router = createRouter({
|
||||
})
|
||||
|
||||
// 登录守卫:未登录访问受保护页跳 /login?redirect=xxx;已登录访问 /login 跳 /dashboard
|
||||
// 权限守卫:路由配置 meta.moduleId 时校验访问权限,无权限跳 /dashboard
|
||||
// 权限守卫:路由配置 meta.moduleId 时校验访问权限,无权限跳 /403 缺省页
|
||||
router.beforeEach(async (to) => {
|
||||
NProgress.start()
|
||||
const authStore = useAuthStore()
|
||||
@@ -50,21 +50,21 @@ router.beforeEach(async (to) => {
|
||||
|
||||
const moduleId = to.meta.moduleId
|
||||
if (moduleId && !permissionStore.canAccess(moduleId)) {
|
||||
return '/dashboard'
|
||||
return '/403'
|
||||
}
|
||||
|
||||
// 菜单入口:路由命中 s_menu 里的页面菜单时,必须有该菜单的 menu.* 授权。
|
||||
// 侧栏已按授权裁剪(stores/menus),这里兜住「手输地址直接访问」。
|
||||
const menu = menuStore.findMenuByRoute(to.path)
|
||||
if (menu && !permissionStore.canEnterMenu(menu.b_id)) {
|
||||
return '/dashboard'
|
||||
return '/403'
|
||||
}
|
||||
|
||||
// 系统管理员专用页面(meta.adminOnly,当前为模块中心 /module/*):
|
||||
// 非 g3soft 一律拦回工作台。按路由标记而非路径前缀判断,避免「菜单上看不见、
|
||||
// 非 g3soft 一律拦到 403 页。按路由标记而非路径前缀判断,避免「菜单上看不见、
|
||||
// 手输地址却能进」的越权;侧栏入口同样仅对 g3soft 渲染(AppSidebar)。
|
||||
if (to.matched.some((r) => r.meta.adminOnly) && !permissionStore.isG3soft) {
|
||||
return '/dashboard'
|
||||
return '/403'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -22,8 +22,8 @@ import DefaultLayout from '@/layouts/DefaultLayout.vue'
|
||||
* 切勿给分组节点配「内部再放一个 router-view」的容器组件:那样页面会下沉一层,
|
||||
* 直接脱离 DefaultLayout 的 keep-alive,页面缓存失效。
|
||||
* 分组节点不配 redirect:分组只是归类,不该自带「默认落地页」语义 —— 直接访问 /base、/module
|
||||
* 这类裸前缀时交给表尾的 /:pathMatch(.*)* 兜到工作台,避免出现「菜单上没配、却能落在某个页面」
|
||||
* 的第二入口(业务入口一律由 s_menu + 路由地址维护)。
|
||||
* 这类裸前缀时交给表尾的 /:pathMatch(.*)* 渲染 404 缺省页,避免出现「菜单上没配、却能落在某个
|
||||
* 页面」的第二入口(业务入口一律由 s_menu + 路由地址维护)。
|
||||
* 子路由 path 写相对路径('module-management'),完整路径由父级拼接,
|
||||
* 调整分组前缀时只需改父节点一处。
|
||||
*/
|
||||
@@ -213,16 +213,45 @@ export const routes = [
|
||||
},
|
||||
],
|
||||
},
|
||||
// 缺省页(应用内展示:保留侧栏 / 顶栏 / 页签,用户可直接切走或用侧栏导航):
|
||||
// 403 由守卫跳转到达;500 供直接访问排查(渲染崩溃的兜底由 App 层
|
||||
// ErrorBoundary 全屏渲染,不经过本路由)。
|
||||
// componentName 不可省:布局的包装层按 name 缓存命名组件,无名页面会互相顶掉;
|
||||
// 不设 meta.title:AppTabs 按 title 收录页签,缺省页不该出现在页签栏。
|
||||
{
|
||||
path: '/403',
|
||||
name: 'fallback-403',
|
||||
component: () => import('@/views/fallback/Forbidden.vue'),
|
||||
meta: { componentName: 'Fallback403' },
|
||||
},
|
||||
{
|
||||
path: '/500',
|
||||
name: 'fallback-500',
|
||||
component: () => import('@/views/fallback/ServerError.vue'),
|
||||
meta: { componentName: 'Fallback500' },
|
||||
},
|
||||
],
|
||||
},
|
||||
// 404 兜住所有未知路径:独立布局(不挂 DefaultLayout)—— 未知路径与登录态无关,
|
||||
// 未登录也要能看到;保留原地址不重定向,用户能看到自己输错的是什么。
|
||||
// 不设 meta.title:AppTabs 按 title 收录页签,缺省页不该出现在页签栏。
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
redirect: '/dashboard',
|
||||
name: 'fallback-404',
|
||||
component: () => import('@/views/fallback/FallbackPage.vue'),
|
||||
props: { status: '404' },
|
||||
},
|
||||
]
|
||||
|
||||
/** 不作为菜单入口的路由:独立布局页(/login)与详情页(静态路径,无法靠动态段规则排除) */
|
||||
const EXCLUDED_PATHS = new Set(['/login', '/base/othercompany/detail', '/base/contact/detail'])
|
||||
/** 不作为菜单入口的路由:独立布局页(/login 与缺省页 /403 /500)与详情页(静态路径,
|
||||
* 无法靠动态段规则排除)。catch-all 缺省路由含动态段,已被 collectMenuRoutes 的规则滤除 */
|
||||
const EXCLUDED_PATHS = new Set([
|
||||
'/login',
|
||||
'/403',
|
||||
'/500',
|
||||
'/base/othercompany/detail',
|
||||
'/base/contact/detail',
|
||||
])
|
||||
|
||||
/**
|
||||
* 收集可作为菜单入口的页面路由(递归展开布局容器与分组节点)。
|
||||
|
||||
Reference in new issue
Block a user