// 侧边栏菜单目录(唯一权威定义)。 // 布局(layouts/default.vue)按它渲染侧栏;账号管理(pages/accounts.vue)按它渲染「菜单权限」勾选; // 权限判定(stores/auth.ts hasAccess)与路由守卫(middleware/access.global.ts)按它取默认权限集。 // 新增页面 = 在此加一行 item,权限编辑器与守卫自动跟上。 export interface MenuItem { id: string // 权限键(存账号 access CSV) label: string to: string icon: string } export interface MenuGroup { label: string restricted?: boolean // true = 管理员默认不开放(仅超管/显式授权) items: MenuItem[] } export const MENU_GROUPS: MenuGroup[] = [ { label: '数据概览', items: [ { id: 'dashboard', label: '仪表盘', to: '/dashboard', icon: 'M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' }, ], }, { label: '生产管理', items: [ { id: 'provider', label: '方案商管理', to: '/provider', icon: 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z' }, { id: 'factory', label: '品牌商管理', to: '/factory', icon: 'M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4' }, { id: 'product', label: '产品管理', to: '/product', icon: 'M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4' }, { id: 'code', label: '公码管理', to: '/code', icon: 'M4 4h6v6H4V4zm10 0h6v6h-6V4zM4 14h6v6H4v-6zm10 2h2m-2 4h6m-4-4v4m4-8h2m-2 0v4' }, { id: 'device', label: '生产管理', to: '/device', icon: 'M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z' }, ], }, { label: '用户管理', items: [ { id: 'user', label: '用户查询', to: '/users', icon: 'M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z' }, ], }, { label: '服务配置', items: [ { id: 'globalconfig', label: '全局环境配置', to: '/globalconfig', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9' }, { id: 'appconfig', label: '应用环境配置', to: '/appconfig', icon: 'M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4' }, { id: 'meettemplate', label: '会议模板', to: '/meettemplates', icon: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' }, { id: 'svcconfig', label: '第三方服务配置', to: '/serviceconfig', icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z' }, { id: 'agents', label: 'Agent 配置', to: '/agents', icon: 'M12 3a2 2 0 012 2v1h3a2 2 0 012 2v3a2 2 0 01-2 2h-1v3a2 2 0 01-2 2H8a2 2 0 01-2-2v-3H5a2 2 0 01-2-2V8a2 2 0 012-2h3V5a2 2 0 012-2zM9 13h.01M15 13h.01' }, { id: 'meetingsvc', label: '会议记录服务', to: '/meetingsvc', icon: 'M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10' }, { id: 'calltranslate', label: '通话翻译配置', to: '/calltranslate', icon: 'M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129' }, ], }, { label: 'SaaS 管理', restricted: true, items: [ { id: 'apps', label: '应用中心', to: '/apps', icon: 'M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10' }, { id: 'environments', label: '环境节点', to: '/environments', icon: 'M5 3h14a2 2 0 012 2v4a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2zM5 13h14a2 2 0 012 2v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4a2 2 0 012-2zM7 7h.01M7 17h.01' }, { id: 'channels', label: '渠道分发', to: '/channels', icon: 'M12 3v12m0 0l-4-4m4 4l4-4M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2' }, ], }, { label: '系统管理', restricted: true, items: [ { id: 'systemconfig', label: '系统配置', to: '/systemconfig', icon: 'M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4' }, { id: 'statlog', label: '统计日志', to: '/statlog', icon: 'M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4' }, { id: 'admin', label: '后台账号', to: '/accounts', icon: 'M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z' }, ], }, ] // 全部菜单 id export const ALL_MENU_IDS: string[] = MENU_GROUPS.flatMap((g) => g.items.map((m) => m.id)) // 管理员默认权限集:除 restricted 分组(SaaS 管理 / 系统管理)以外的全部菜单。 export const DEFAULT_ADMIN_ACCESS: string[] = MENU_GROUPS .filter((g) => !g.restricted) .flatMap((g) => g.items.map((m) => m.id)) // 按路由路径反查菜单项(前缀匹配,取最长命中,供路由守卫用)。 export function menuItemByPath(path: string): MenuItem | null { let best: MenuItem | null = null for (const g of MENU_GROUPS) { for (const m of g.items) { if (path === m.to || path.startsWith(m.to + '/')) { if (!best || m.to.length > best.to.length) best = m } } } return best }