task-9(壳层/路由): 实现路由 meta 菜单 key 约定与 RouteMeta 类型增强

新增 src/types/vue-router.d.ts 模块增强(RouteMeta.title/menuKey),meta.ts 提供
metaMenuKey/命名校验,router 守卫改类型化访问去掉 as cast,AdminLayout 标题同步
去 cast;校验首批注册表 menuKey 合规。
This commit is contained in:
2026-09-05 12:20:14 +08:00
parent 02e0dc20b8
commit ab7255a55b
5 changed files with 118 additions and 2 deletions
@@ -15,7 +15,7 @@ const collapsed = ref(false)
const activePath = computed(() => route.path)
const menuEntries = computed(() => toSidebarEntries(session.menuTree))
const openedKeys = computed(() => groupKeysForActive(menuEntries.value, route.path))
const pageTitle = computed(() => pageTitleOf(route.meta.title as string | undefined))
const pageTitle = computed(() => pageTitleOf(route.meta.title))
const userVm = computed(() => topbarUserOf(session.user))
const logoUrl = joinAdminPath('assets', 'logo.jpg')
+1 -1
View File
@@ -29,7 +29,7 @@ router.beforeEach(async (to) => {
if (to.path === '/') {
return session.firstVisible || true
}
const menuKey = to.meta.menuKey as string | undefined
const menuKey = to.meta.menuKey
if (menuKey && !session.isSuperAdmin && !hasMenu(session.menuTree, menuKey)) {
// 无权限页面:回退到首个可见页面;一个都没有则回根路由空态。
return session.firstVisible || '/'
+34
View File
@@ -0,0 +1,34 @@
/** 路由 meta 菜单 key 约定(任务 9):menuKey 对应后端菜单节点 key,仅作页面级鉴权。 */
export const ADMIN_MENU_KEY_PATTERN = /^[a-z][a-z0-9_]*$/
/** 从 route.meta 读取菜单 key;缺省/非法类型回退空串(无菜单约束)。 */
export function metaMenuKey(meta: { menuKey?: unknown } | undefined): string {
const value = meta?.menuKey
return typeof value === 'string' ? value : ''
}
/** 菜单 key 是否合规(小写下划线命名)。 */
export function isValidMenuKey(key: string): boolean {
return ADMIN_MENU_KEY_PATTERN.test(key)
}
export interface MenuKeyCandidate {
path?: string
menuKey?: unknown
}
/** 校验一批页面注册的 menuKey:重复与命名格式问题返回可操作清单。 */
export function validateRouteMenuKeys(records: MenuKeyCandidate[]): string[] {
const issues: string[] = []
const seen = new Set<string>()
for (const record of records) {
const key = metaMenuKey(record)
if (!key) continue
if (seen.has(key)) issues.push(`菜单 key 重复: ${key}`)
seen.add(key)
if (!isValidMenuKey(key)) {
issues.push(`菜单 key 命名非法(须小写下划线): ${record.path || '(无路径)'} -> ${key}`)
}
}
return issues
}
+10
View File
@@ -0,0 +1,10 @@
import 'vue-router'
declare module 'vue-router' {
interface RouteMeta {
/** 页面标题,驱动顶栏与 document.title。 */
title?: string
/** 菜单 key(对应后端菜单节点 key);仅页面级鉴权使用。 */
menuKey?: string
}
}