Files
aiops/frontend/src/App.tsx
T
attacker d581441fa8 feat: Deployment详情页重构 — ACK风格Tab布局 + CI/CD Webhook + 信息面板
DeploymentView 完全重写:
- Tab布局: 容器组|访问方式(Service/Ingress)|事件|容器伸缩|历史版本
- 顶部信息面板: 状态/副本/节点/IP/创建时间 + Pod条件时间线
- 容器组Tab: 卡片式列表(日志/终端/文件按钮), 展开显示容器详情
- 访问方式Tab: 自动加载匹配的Service+Ingress(selector过滤)
- 事件Tab: 加载Deployment相关K8s Events
- 容器伸缩Tab: 内联伸缩UI(+/-按钮)
- 历史版本Tab: 回滚功能

DeploymentWorkload 精简:
- 删除下拉菜单(元数据/运行时/服务/应用路由/YAML预览/日志终端)
- 操作按钮改为直接按钮行: 编辑|调整镜像|重启|暂停/恢复|CI/CD|删除
- CI/CD改为Webhook模态(生成URL+curl示例, 自动填充Token)
- AIOpsAssistant UUID fallback支持HTTP环境
- Dockerfile chmod a+r 修复favicon.svg 403
2026-06-24 03:55:23 +00:00

207 lines
14 KiB
TypeScript

import { Suspense, lazy } from 'react';
import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider } from '@/hooks/useTheme';
import { MainLayout } from '@/components/layout/MainLayout';
import { ConfirmProvider } from '@/components/ui/confirm-dialog';
import { Login } from '@/components/auth/Login';
import { ProtectedRoute } from '@/components/auth/ProtectedRoute';
import { PageTransition } from '@/components/layout/PageTransition';
import { ErrorBoundary } from '@/components/layout/ErrorBoundary';
// Lazy load page components for code splitting
const Dashboard = lazy(() => import('@/components/dashboard/Dashboard').then(m => ({ default: m.Dashboard })));
const ServerManager = lazy(() => import('@/components/server/ServerManager').then(m => ({ default: m.ServerManager })));
const CloudAccountManager = lazy(() => import('@/components/cloud/CloudAccountManager').then(m => ({ default: m.CloudAccountManager })));
const DomainManager = lazy(() => import('@/components/cloud/DomainManager').then(m => ({ default: m.DomainManager })));
const RegionManager = lazy(() => import('@/components/cloud/RegionManager').then(m => ({ default: m.RegionManager })));
const PlatformManager = lazy(() => import('@/components/cloud/PlatformManager').then(m => ({ default: m.PlatformManager })));
const CloudBilling = lazy(() => import('@/components/cloud/CloudBilling').then(m => ({ default: m.CloudBilling })));
const KubernetesClusters = lazy(() => import('@/components/kubernetes/KubernetesClusters').then(m => ({ default: m.KubernetesClusters })));
const ClusterOverviewPage = lazy(() => import('@/components/kubernetes/ClusterOverviewPage').then(m => ({ default: m.default })));
const NodeDetailPage = lazy(() => import('@/components/kubernetes/NodeDetailPage').then(m => ({ default: m.default })));
const NamespaceOverviewPage = lazy(() => import('@/components/kubernetes/NamespaceOverviewPage').then(m => ({ default: m.default })));
const NamespaceResourcePage = lazy(() => import('@/components/kubernetes/NamespaceResourcePage').then(m => ({ default: m.default })));
const DeploymentDetailPage = lazy(() => import('@/components/kubernetes/DeploymentDetailPage').then(m => ({ default: m.default })));
const WorkloadViewPage = lazy(() => import('@/components/kubernetes/WorkloadViewPage').then(m => ({ default: m.default })));
const TopologyView = lazy(() => import('@/components/kubernetes/TopologyView').then(m => ({ default: m.TopologyView })));
const KubernetesNodes = lazy(() => import('@/components/kubernetes/KubernetesNodes').then(m => ({ default: m.KubernetesNodes })));
const PodMetricsPage = lazy(() => import('@/components/kubernetes/PodMetricsPage').then(m => ({ default: m.default })));
const EventsPage = lazy(() => import('@/components/kubernetes/EventsPage').then(m => ({ default: m.default })));
const CapacityPage = lazy(() => import('@/components/kubernetes/CapacityPage').then(m => ({ default: m.default })));
const AlertManager = lazy(() => import('@/components/monitor/AlertManager').then(m => ({ default: m.AlertManager })));
const ApprovalFlowManager = lazy(() => import('@/components/approval/ApprovalFlow').then(m => ({ default: m.ApprovalFlowManager })));
const ScriptManager = lazy(() => import('@/components/automation/ScriptManager').then(m => ({ default: m.ScriptManager })));
const SystemManager = lazy(() => import('@/components/system/SystemManager').then(m => ({ default: m.SystemManager })));
const CredentialManager = lazy(() => import('@/components/deploy/CredentialManager').then(m => ({ default: m.default })));
const PipelineManager = lazy(() => import('@/components/deploy/PipelineManager').then(m => ({ default: m.PipelineManager })));
const DeployCredentials = lazy(() => import('@/components/deploy/DeployCredentials').then(m => ({ default: m.default })));
const PipelineEditor = lazy(() => import('@/components/deploy/PipelineEditor').then(m => ({ default: m.default })));
const PipelineRunDetail = lazy(() => import('@/components/deploy/PipelineRunDetail').then(m => ({ default: m.default })));
const DeployRBAC = lazy(() => import('@/components/deploy/DeployRBAC').then(m => ({ default: m.default })));
const UserGroupsManager = lazy(() => import('@/components/deploy/UserGroupsManager').then(m => ({ default: m.default })));
const CronJobManager = lazy(() => import('@/components/automation/CronJobManager').then(m => ({ default: m.CronJobManager })));
const AnsibleManager = lazy(() => import('@/components/automation/AnsibleManager').then(m => ({ default: m.default })));
const AnsibleWorkflow = lazy(() => import('@/components/automation/AnsibleWorkflow').then(m => ({ default: m.default })));
const AIOpsAssistant = lazy(() => import('@/components/aiops/AIOpsAssistant').then(m => ({ default: m.AIOpsAssistant })));
const AIAlertAnalyzer = lazy(() => import('@/components/aiops/AIAlertAnalyzer').then(m => ({ default: m.AIAlertAnalyzer })));
const AIPredictiveAnalytics = lazy(() => import('@/components/aiops/AIPredictiveAnalytics').then(m => ({ default: m.AIPredictiveAnalytics })));
const AlertCenter = lazy(() => import('@/components/monitor/alert-center/AlertCenter').then(m => ({ default: m.default })));
const TraceManager = lazy(() => import('@/components/monitor/trace/TraceManager').then(m => ({ default: m.default })));
const HostMonitor = lazy(() => import('@/pages/HostMonitor').then(m => ({ default: m.HostMonitor })));
const HostMonitorDashboard = lazy(() => import('@/components/monitor/dashboard/HostMonitorDashboard').then(m => ({ default: m.default })));
const GrafanaDashboard = lazy(() => import('@/components/monitor/dashboard/GrafanaDashboard').then(m => ({ default: m.default })));
const MonitorCenter = lazy(() => import('@/pages/MonitorCenter').then(m => ({ default: m.MonitorCenter })));
const MetricsExplorer = lazy(() => import('@/pages/MetricsExplorer').then(m => ({ default: m.MetricsExplorer })));
const DatasourcePage = lazy(() => import('@/components/monitor/datasource/DatasourcePage').then(m => ({ default: m.default })));
// Page loader fallback
function PageLoader() {
return (
<div className="flex flex-col items-center justify-center h-[calc(100vh-14rem)] gap-4">
<div className="relative">
<div className="h-10 w-10 border-3 border-[var(--dg-border)] border-t-[var(--dg-blue)] rounded-full animate-spin" />
<div className="absolute inset-0 h-10 w-10 border-3 border-transparent border-t-[var(--dg-blue)] rounded-full animate-spin opacity-30" style={{ animationDirection: 'reverse', animationDuration: '1s' }} />
</div>
<p className="text-sm text-[var(--dg-text-muted)]">加载中...</p>
</div>
);
}
// Lazy page wrapper with error boundary and transition
function LazyPage({ children }: { children: React.ReactNode }) {
const location = useLocation();
return (
<ErrorBoundary>
<PageTransition key={location.pathname}>
<Suspense fallback={<PageLoader />}>
{children}
</Suspense>
</PageTransition>
</ErrorBoundary>
);
}
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000,
retry: 1,
refetchOnWindowFocus: false,
},
},
});
function App() {
return (
<ThemeProvider>
<QueryClientProvider client={queryClient}>
<ConfirmProvider>
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/" element={
<ProtectedRoute>
<MainLayout />
</ProtectedRoute>
}>
<Route index element={<LazyPage><Dashboard /></LazyPage>} />
<Route path="servers" element={<LazyPage><ServerManager /></LazyPage>} />
<Route path="cloud-accounts" element={<LazyPage><CloudAccountManager /></LazyPage>} />
<Route path="domains" element={<LazyPage><DomainManager /></LazyPage>} />
<Route path="regions" element={<LazyPage><RegionManager /></LazyPage>} />
<Route path="platforms" element={<LazyPage><PlatformManager /></LazyPage>} />
<Route path="cloud-billing" element={<LazyPage><CloudBilling /></LazyPage>} />
{/* Kubernetes Routes */}
<Route path="kubernetes">
<Route index element={<LazyPage><KubernetesClusters /></LazyPage>} />
<Route path=":clusterCode">
<Route index element={<LazyPage><ClusterOverviewPage /></LazyPage>} />
<Route path="metrics/pods" element={<LazyPage><PodMetricsPage /></LazyPage>} />
<Route path="events" element={<LazyPage><EventsPage /></LazyPage>} />
<Route path="capacity" element={<LazyPage><CapacityPage /></LazyPage>} />
<Route path="nodes/:nodeName" element={<LazyPage><NodeDetailPage /></LazyPage>} />
<Route path="topology" element={<LazyPage><TopologyView /></LazyPage>} />
<Route path="namespace/:namespace">
<Route index element={<LazyPage><NamespaceOverviewPage /></LazyPage>} />
<Route path="workload">
<Route path=":mode/Deployment/:name" element={<LazyPage><DeploymentDetailPage /></LazyPage>} />
<Route path=":mode/StatefulSet/:name" element={<LazyPage><WorkloadViewPage /></LazyPage>} />
<Route path=":mode/DaemonSet/:name" element={<LazyPage><WorkloadViewPage /></LazyPage>} />
</Route>
<Route path="deployments" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="deployments/:name" element={<LazyPage><DeploymentDetailPage /></LazyPage>} />
<Route path="pods" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="services" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="ingresses" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="configmaps" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="secrets" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="hpas" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="cronjobs" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="pvcs" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="statefulsets" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="daemonsets" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
</Route>
</Route>
</Route>
{/* Quick Access Routes (redirect to first cluster) */}
<Route path="workloads" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="workloads/:type" element={<LazyPage><NamespaceResourcePage /></LazyPage>} />
<Route path="nodes" element={<LazyPage><KubernetesNodes /></LazyPage>} />
<Route path="topology" element={<LazyPage><TopologyView /></LazyPage>} />
{/* Deploy */}
<Route path="pipelines" element={<LazyPage><PipelineManager /></LazyPage>} />
<Route path="pipelines/:code" element={<LazyPage><PipelineEditor /></LazyPage>} />
<Route path="pipelines/:code/runs" element={<LazyPage><PipelineRunDetail /></LazyPage>} />
<Route path="pipelines/:code/edit" element={<LazyPage><PipelineEditor /></LazyPage>} />
<Route path="deploy/configureTools" element={<LazyPage><DeployCredentials /></LazyPage>} />
<Route path="deploy/groups" element={<LazyPage><UserGroupsManager /></LazyPage>} />
<Route path="deploy/rbac" element={<LazyPage><DeployRBAC /></LazyPage>} />
{/* Monitor */}
<Route path="metrics" element={<LazyPage><MetricsExplorer /></LazyPage>} />
<Route path="datasources" element={<LazyPage><DatasourcePage /></LazyPage>} />
<Route path="trace" element={<LazyPage><TraceManager /></LazyPage>} />
<Route path="dashboards" element={<LazyPage><GrafanaDashboard /></LazyPage>} />
<Route path="host-monitor" element={<LazyPage><HostMonitor /></LazyPage>} />
<Route path="alerts" element={<LazyPage><AlertManager /></LazyPage>} />
<Route path="alert-center" element={<LazyPage><AlertCenter /></LazyPage>} />
<Route path="monitor-center" element={<LazyPage><MonitorCenter /></LazyPage>} />
<Route path="logs" element={<LazyPage><AlertManager /></LazyPage>} />
{/* Automation */}
<Route path="approval" element={<LazyPage><ApprovalFlowManager /></LazyPage>} />
<Route path="cronjobs" element={<LazyPage><CronJobManager /></LazyPage>} />
<Route path="scripts" element={<LazyPage><ScriptManager /></LazyPage>} />
<Route path="ansible" element={<LazyPage><AnsibleWorkflow /></LazyPage>} />
<Route path="ansible/manage" element={<LazyPage><AnsibleManager /></LazyPage>} />
{/* AIOps */}
<Route path="ai-assistant" element={<LazyPage><AIOpsAssistant /></LazyPage>} />
<Route path="ai-alert-analyzer" element={<LazyPage><AIAlertAnalyzer /></LazyPage>} />
<Route path="ai-predictive" element={<LazyPage><AIPredictiveAnalytics /></LazyPage>} />
{/* System */}
<Route path="users" element={<LazyPage><SystemManager /></LazyPage>} />
<Route path="roles" element={<LazyPage><SystemManager /></LazyPage>} />
<Route path="logs-audit" element={<LazyPage><SystemManager /></LazyPage>} />
<Route path="terminal-audit" element={<LazyPage><SystemManager /></LazyPage>} />
<Route path="credentials" element={<LazyPage><CredentialManager /></LazyPage>} />
<Route path="settings" element={<LazyPage><SystemManager /></LazyPage>} />
{/* Fallback */}
<Route path="*" element={<Navigate to="/" replace />} />
</Route>
</Routes>
</BrowserRouter>
</ConfirmProvider>
</QueryClientProvider>
</ThemeProvider>
);
}
export default App;