Files
cma-management/frontend/src/permission.ts
T

184 lines
9.6 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.
/**
* 角色权限配置 — 管理会计OS
* 4角色: ceo(总经理), finance(财务), business(业务), it(IT运维)
*/
// 各角色可访问的路由列表
export const ROLE_ROUTES: Record<string, string[]> = {
ceo: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/notifications', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis', '/okr-templates', '/mpm-calculator'],
finance: ['/my-dashboard', '/dashboard', '/kpis', '/maps', '/maps-review', '/maps/canvas', '/maps/review', '/alerts', '/data', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/reports', '/alignment', '/dupont-analysis', '/okr-templates', '/mpm-calculator'],
business: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/deviations', '/budget', '/action-plans', '/knowledge', '/guide', '/customer', '/reports', '/alignment', '/mpm-calculator'],
it: ['/my-dashboard', '/dashboard', '/kpis', '/alerts', '/data', '/org', '/users', '/permissions', '/budget', '/deviations', '/cost', '/predict', '/action-plans', '/knowledge', '/guide', '/customer', '/learning-dashboard', '/okr-templates'],
}
// 可操作的CRUD权限
export const ROLE_ACTIONS: Record<string, string[]> = {
ceo: ['read'],
finance: ['read', 'write', 'import', 'export'],
business: ['read', 'write'],
it: ['read', 'write', 'delete', 'admin'],
}
// 菜单项定义(带角色限制)
export interface MenuItem {
path: string
label: string
icon: string
roles: string[]
group?: string // 分组标识,仅首位项标记
}
export const MENU_ITEMS: MenuItem[] = [
{ path: '/my-dashboard', label: '我的工作台', icon: 'Monitor', roles: ['ceo', 'finance', 'business', 'it'], group: '🔵 P 规划与目标' },
{ path: '/maps', label: '战略地图', icon: 'DataBoard', roles: ['ceo', 'finance'], group: '🔵 P 规划与目标' },
{ path: '/budget', label: '预算管理', icon: 'Coin', roles: ['ceo', 'finance', 'business', 'it'], group: '🔵 P 规划与目标' },
{ path: '/alignment', label: '战略执行看板', icon: 'Opportunity', roles: ['ceo', 'finance', 'business', 'it'], group: '🔵 P 规划与目标' },
// ══════════════════════════════════════════════════════════════
// GROUP 2: 执行与控制(Do
// ══════════════════════════════════════════════════════════════
{ path: '/real-options', label: '实物期权计算器', icon: 'TrendCharts', roles: ['ceo', 'finance'], group: '🔵 P 规划与目标' },
{ path: '/cost', label: '成本分析', icon: 'Money', roles: ['ceo', 'finance', 'it'], group: '🟢 D 执行与控制' },
{ path: '/deviations', label: '差异分析', icon: 'DataAnalysis', roles: ['ceo', 'finance', 'business', 'it'], group: '🟢 D 执行与控制' },
{ path: '/dashboard', label: '经营看板', icon: 'DataBoard', roles: ['ceo', 'finance', 'business', 'it'], group: '🟡 C 监控与评价' },
{ path: '/reports', label: '管理报表', icon: 'DataAnalysis', roles: ['ceo', 'finance', 'business'], group: '🟡 C 监控与评价' },
{ path: '/dupont-analysis', label: '杜邦分析', icon: 'TrendCharts', roles: ['ceo', 'finance', 'it'], group: '🟡 C 监控与评价' },
{ path: '/customer', label: '客户维度', icon: 'User', roles: ['ceo', 'finance', 'business', 'it'], group: '🟡 C 监控与评价' },
{ path: '/learning-dashboard', label: '学习成长看板', icon: 'Reading', roles: ['ceo', 'finance', 'it'], group: '🟡 C 监控与评价' },
{ path: '/alerts', label: '预警中心', icon: 'WarningFilled', roles: ['ceo', 'finance', 'business', 'it'], group: '🟡 C 监控与评价' },
{ path: '/action-plans', label: '改善行动', icon: 'Edit', roles: ['ceo', 'finance', 'business', 'it'], group: '🔴 A 复盘与改进' },
// ══════════════════════════════════════════════════════════════
// GROUP 3: 监控与评价(Check
// ══════════════════════════════════════════════════════════════
{ path: '/data-quality', label: '数据质量', icon: 'WarningFilled', roles: ['ceo', 'finance', 'it'], group: '🔴 A 复盘与改进' },
// ══════════════════════════════════════════════════════════════
// GROUP 4: 复盘与改进(Act
// ══════════════════════════════════════════════════════════════
{ path: '/maps-review', label: '战略回顾会', icon: 'TrendCharts', roles: ['ceo', 'finance'], group: '🔴 A 复盘与改进' },
{ path: '/predict', label: '预测模拟', icon: 'DataLine', roles: ['ceo', 'finance', 'it'], group: '🔴 A 复盘与改进' },
{ path: '/mpm-calculator', label: 'MPM计算器', icon: 'Money', roles: ['ceo', 'finance', 'business'], group: '🔴 A 复盘与改进' },
// ══════════════════════════════════════════════════════════════
// GROUP 5: 系统与支持(Infra
// ══════════════════════════════════════════════════════════════
{ path: '/kpis', label: 'KPI字典', icon: 'Document', roles: ['ceo', 'finance', 'business', 'it'], group: '基础数据与知识' },
{ path: '/data', label: '数据管理', icon: 'Connection', roles: ['ceo', 'finance', 'it'], group: '基础数据与知识' },
// ── 规划与目标 ──
{ path: '/knowledge', label: 'CMA知识库', icon: 'Document', roles: ['ceo', 'finance', 'business', 'it'], group: '基础数据与知识' },
{ path: '/okr-templates', label: 'OKR模板库', icon: 'Collection', roles: ['ceo', 'finance', 'it'], group: '基础数据与知识' },
{ path: '/org', label: '组织管理', icon: 'Collection', roles: ['ceo', 'it'], group: '系统管理' },
{ path: '/users', label: '用户管理', icon: 'User', roles: ['ceo', 'it'], group: '系统管理' },
{ path: '/notifications', label: '通知配置', icon: 'Bell', roles: ['ceo', 'it'], group: '系统管理' },
{ path: '/permissions', label: '系统设置', icon: 'Setting', roles: ['ceo', 'it'], group: '系统管理' },
]
// 角色名称映射
export const ROLE_LABELS: Record<string, string> = {
ceo: '总经理',
finance: '财务部',
business: '业务部',
it: 'IT部',
}
/**
* 检查用户是否有权访问某路由
*/
export function hasRouteAccess(role: string, path: string): boolean {
const allowed = ROLE_ROUTES[role]
if (!allowed) return false
// 精确匹配或前缀匹配(如 /kpis/123 匹配 /kpis
return allowed.some(r => path === r || path.startsWith(r + '/'))
}
/**
* 检查用户是否有指定操作权限
*/
export function hasAction(role: string, action: string): boolean {
const actions = ROLE_ACTIONS[role]
return actions ? actions.includes(action) : false
}
]
// 角色名称映射
export const ROLE_LABELS: Record<string, string> = {
ceo: '总经理',
finance: '财务部',
business: '业务部',
it: 'IT部',
}
/**
* 检查用户是否有权访问某路由
*/
export function hasRouteAccess(role: string, path: string): boolean {
const allowed = ROLE_ROUTES[role]
if (!allowed) return false
// 精确匹配或前缀匹配(如 /kpis/123 匹配 /kpis
return allowed.some(r => path === r || path.startsWith(r + '/'))
}
/**
* 检查用户是否有指定操作权限
*/
export function hasAction(role: string, action: string): boolean {
const actions = ROLE_ACTIONS[role]
return actions ? actions.includes(action) : false
}
]
// 角色名称映射
export const ROLE_LABELS: Record<string, string> = {
ceo: '总经理',
finance: '财务部',
business: '业务部',
it: 'IT部',
}
/**
* 检查用户是否有权访问某路由
*/
export function hasRouteAccess(role: string, path: string): boolean {
const allowed = ROLE_ROUTES[role]
if (!allowed) return false
// 精确匹配或前缀匹配(如 /kpis/123 匹配 /kpis
return allowed.some(r => path === r || path.startsWith(r + '/'))
}
/**
* 检查用户是否有指定操作权限
*/
export function hasAction(role: string, action: string): boolean {
const actions = ROLE_ACTIONS[role]
return actions ? actions.includes(action) : false
}
]
// 角色名称映射
export const ROLE_LABELS: Record<string, string> = {
ceo: '总经理',
finance: '财务部',
business: '业务部',
it: 'IT部',
}
/**
* 检查用户是否有权访问某路由
*/
export function hasRouteAccess(role: string, path: string): boolean {
const allowed = ROLE_ROUTES[role]
if (!allowed) return false
// 精确匹配或前缀匹配(如 /kpis/123 匹配 /kpis
return allowed.some(r => path === r || path.startsWith(r + '/'))
}
/**
* 检查用户是否有指定操作权限
*/
export function hasAction(role: string, action: string): boolean {
const actions = ROLE_ACTIONS[role]
return actions ? actions.includes(action) : false
}