ForcePilot/web/src/components/external-systems/layout/navigation.js
Kris d38f325577 feat: 完成外部系统模块多维度优化迭代
本次提交包含以下核心改进:
1.  统一组件命名规范:为所有列表页组件添加defineOptions配置组件名
2.  重构侧边导航系统:支持折叠态、路由name跳转、自动激活匹配
3.  新增通用基础组件:ErrorRetryAlert错误重试提示、PermissionButton权限按钮
4.  优化列表页错误处理:替换全局错误提示为统一ErrorRetryAlert组件
5.  增强仪表盘能力:添加自动重试机制、traceId展示、多维度指标统计
6.  完善页面容器功能:支持详情页标签、面包屑优化、权限控制
7.  新增系统健康状态监控:集成健康检查API,展示系统健康状态
8.  优化页面交互:加载态、空态、错误态统一视觉语言
2026-07-11 05:44:45 +08:00

118 lines
4.0 KiB
JavaScript
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.

/**
* 外部系统集成框架 - 三级导航配置
*
* 单一数据源,供 GroupNav 侧边栏与 PageContainer 面包屑共享。
* 结构对齐原型图 §1.5.1 菜单层级树:
* 一级「外部系统集成」→ 二级「业务域分组」→ 三级「功能页面」
*
* 数据源对齐说明(与 channels 模块一致):
* module.routeName 引用 router/index.js 中的路由 name改路由 path 不影响导航,
* 改路由 name 时此处需同步更新(否则 RouterLink 会报错)。
* 详情页通过路由 meta.parentModule 显式声明归属,不依赖 path 前缀匹配。
* module.icon 为侧边栏模块级图标,对齐 channels 模块的视觉语言。
*
* 注:抽屉/弹窗类组件不作为独立路由,由宿主页面按需挂载,故不在导航配置中登记。
*/
import {
Server,
Activity,
ShieldCheck,
Settings,
Database,
Wrench,
Package,
FileInput,
FileText,
HeartPulse,
Gauge,
ScrollText,
KeyRound,
AlertTriangle,
KeyVault,
ShieldAlert,
FlaskConical,
Webhook,
Bell,
Plug,
BookUser,
Sparkles,
Trash2
} from 'lucide-vue-next'
export const ES_NAVIGATION = [
{
key: 'asset-management',
label: '资产管理',
icon: Server,
modules: [
{ label: '系统管理', routeName: 'EsSystems', icon: Database },
{ label: '工具管理', routeName: 'EsTools', icon: Wrench },
{ label: '环境管理', routeName: 'EsEnvironments', icon: Package },
{ label: '适配器资产', routeName: 'EsAssets', icon: FileInput },
{ label: '导入导出', routeName: 'EsImportExport', icon: FileText }
]
},
{
key: 'runtime-monitoring',
label: '运行监控',
icon: Activity,
modules: [
{ label: '执行记录', routeName: 'EsExecutions', icon: Activity },
{ label: '健康检查', routeName: 'EsHealthChecks', icon: HeartPulse },
{ label: '指标查询', routeName: 'EsMetrics', icon: Gauge },
{ label: '审计日志', routeName: 'EsAuditLogs', icon: ScrollText },
{ label: 'Token 管理', routeName: 'EsTokens', icon: KeyRound }
]
},
{
key: 'governance-control',
label: '治理管控',
icon: ShieldCheck,
modules: [
{ label: '配额管理', routeName: 'EsQuotas', icon: Gauge },
{ label: '告警事件', routeName: 'EsAlerts', icon: AlertTriangle },
{ label: '密钥轮换', routeName: 'EsKeyRotations', icon: KeyVault },
{ label: '访问规则', routeName: 'EsAccessRules', icon: ShieldAlert },
{ label: '测试用例', routeName: 'EsTestCases', icon: FlaskConical }
]
},
{
key: 'integration-config',
label: '集成配置',
icon: Settings,
modules: [
{ label: 'Webhook 订阅', routeName: 'EsWebhookSubscriptions', icon: Webhook },
{ label: 'Webhook 事件', routeName: 'EsWebhookEvents', icon: Webhook },
{ label: '厂商集成目录', routeName: 'EsVendorIntegrations', icon: BookUser },
{ label: '集成生成器', routeName: 'EsIntegrationGenerator', icon: Sparkles },
{ label: '通知渠道', routeName: 'EsNotificationChannels', icon: Bell },
{ label: '认证插件', routeName: 'EsAuthPlugins', icon: ShieldCheck },
{ label: '适配器元数据', routeName: 'EsAdapterMetadata', icon: Plug },
{ label: '回收站', routeName: 'EsRecycleBin', icon: Trash2 }
]
}
]
/**
* 根据当前路由查找所属分组与模块
*
* 匹配规则(与 channels 模块一致):
* - 优先读 route.meta.parentModule详情页显式声明父模块避免 path 前缀匹配的脆弱性)
* - 否则用 route.name 精确匹配
*
* @param {import('vue-router').RouteLocationNormalized} route - 当前路由对象
* @returns {{ group: object, module: object } | null}
*/
export function findActiveModule(route) {
const targetName = route?.meta?.parentModule || route?.name
if (!targetName) return null
for (const group of ES_NAVIGATION) {
for (const module of group.modules) {
if (module.routeName === targetName) {
return { group, module }
}
}
}
return null
}