Files
PayrollManagementSystem/frontend/src/composables/useAppMenu.ts
T
liuwenxinandClaude Code 39a3fa7796 fix(dashboard): 修复普通用户落地页与待办角色过滤
- 新增 router/access.ts 统一准入与落地页(工作台→业务数据→回款),
  守卫/登录回跳/菜单/面包屑复用;普通用户不再被无限重定向
- 待办按角色映射在途审批节点(财务/领导/admin),admin 不代办但可查全部
- 预警排除已终止业务;WarningBlock.total 为全量命中数;回款趋势改日期范围
- 工作台加载请求序号防竞态;KPI 口径说明补经理分成/调整单
- 新增 role_home_flow e2e,更新 system_management 普通用户断言

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-20 09:45:03 +08:00

66 lines
2.0 KiB
TypeScript

import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { canAccessRoute, isMenuRecord } from '@/router/access'
import { useUserStore } from '@/store/user'
/** 菜单节点:从路由表派生,避免菜单标题与页面标题两处维护漂移。 */
export interface MenuNode {
path: string
title: string
order: number
group?: string
}
export interface MenuGroup {
name: string
items: MenuNode[]
}
/**
* 侧边菜单数据。
*
* 规则:
* - 取路由表中带 `meta.title` 且未被 `meta.menu === false` 排除的记录
* - `meta.requiresAdmin` 的项仅管理员可见(与路由守卫双保险,隐藏入口在前)
* - `meta.group` 相同的项聚合为一个子菜单;无 group 的为顶层菜单项
* - 按 `meta.order` 排序
*/
export function useAppMenu() {
const router = useRouter()
const userStore = useUserStore()
const userRoles = computed(() => userStore.roles)
const menuNodes = computed<MenuNode[]>(() =>
router
.getRoutes()
// 准入规则与路由守卫、落地页解析共用,避免三处漂移
.filter((record) => isMenuRecord(record) && canAccessRoute(record, userRoles.value))
.map((record) => ({
path: record.path,
title: record.meta.title ?? '',
order: record.meta.order ?? 99,
group: record.meta.group,
}))
.sort((a, b) => a.order - b.order),
)
/** 无分组的顶层菜单项 */
const topLevelMenus = computed(() => menuNodes.value.filter((node) => !node.group))
/** 分组菜单(按 group 名聚合,组内保持 order 顺序) */
const groupedMenus = computed<MenuGroup[]>(() => {
const groups = new Map<string, MenuNode[]>()
for (const node of menuNodes.value) {
if (!node.group) continue
const items = groups.get(node.group) ?? []
items.push(node)
groups.set(node.group, items)
}
return [...groups.entries()].map(([name, items]) => ({ name, items }))
})
return { topLevelMenus, groupedMenus }
}