feat: 新增日志中心、功能优化与代码重构

- 新增 log_datasource.go / log_proxy.go / user_api_token.go 后端控制器
- 新增 log_datasource.go model
- 新增 monitor/log-center.ts API 模块
- 新增 LogCenter 前端组件及页面
- 重构 deployment 相关组件 (HPDA/UpdateImageModal/bundle-yaml 等)
- 新增 ResetPasswordDialog / code-snippet-block / copy-button 等 UI 组件
- 重构多个 k8s 相关组件 (TopologyView/ResourceVisualEditor/PodFileBrowser 等)
- 更新多个 API 和工具函数 (auth.ts/monitor/index.ts/request.ts 等)
- 更新静态资源 (index.html + 新 JS/CSS bundle)
- 删除废弃静态资源文件
This commit is contained in:
Logan committed 2026-06-26 23:18:05 +08:00
1 parent 5ca0e6d83a
commit 8d46e8f352
197 files changed
+5014 -815

No files matched your search

@@ -3,7 +3,7 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Cloud, XCircle } from 'lucide-react';
import { Cloud, XCircle, RefreshCw } from 'lucide-react';
import { kubernetesApi } from '@/api';
import {
AreaChart,
@@ -15,8 +15,9 @@ import {
ResponsiveContainer,
} from 'recharts';
// 资源使用趋势数据 — 从节点 metrics 实时计算(不再用硬编码 mock) // Logan.Li
// 由于当前无 time-series 存储,用当前快照展示一个合理的汇总值
// 资源使用趋势数据
// 由于当前无持久化时序存储,这里基于当前节点 metrics 构造一个简短的模拟趋势(最近几分钟变化)
// 真正历史数据需要后端记录指标快照后才能实现 // Logan.Li
export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; onClose: () => void }) {
const [nodes, setNodes] = useState<any[]>([]);
@@ -50,6 +51,21 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; on
};
}, [nodes]);
// 构造趋势数据(多点),避免单点导致“光点”效果 // Logan.Li
const trendData = useMemo(() => {
const cpu = Math.max(0, Math.min(100, Number(clusterMetrics.cpuPct.toFixed(1))));
const mem = Math.max(0, Math.min(100, Number(clusterMetrics.memPct.toFixed(1))));
// 模拟最近 5 个时间点的趋势(基于当前值轻微回溯)
return [
{ time: '10m前', cpu: Math.max(0, cpu * 0.72), memory: Math.max(0, mem * 0.78) },
{ time: '7m前', cpu: Math.max(0, cpu * 0.82), memory: Math.max(0, mem * 0.85) },
{ time: '4m前', cpu: Math.max(0, cpu * 0.90), memory: Math.max(0, mem * 0.93) },
{ time: '2m前', cpu: Math.max(0, cpu * 0.96), memory: Math.max(0, mem * 0.97) },
{ time: '现在', cpu, memory: mem },
];
}, [clusterMetrics]);
const loadClusterDetail = async (clusterId: string) => {
try {
// 后端 ListNodes/ListPods/etc 返回 data 直接为数组(非 {list,total})
@@ -132,49 +148,63 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; on
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<Card className="bg-slate-800/50 border-slate-700">
<CardHeader className="pb-2">
<CardTitle className="text-sm text-slate-400">资源使用趋势</CardTitle>
<div className="flex items-center justify-between w-full">
<CardTitle className="text-sm text-slate-400">资源使用趋势(模拟最近变化)</CardTitle>
<Button
variant="ghost"
size="sm"
className="h-6 w-6 p-0 text-slate-400 hover:text-slate-200"
onClick={() => cluster?.id && loadClusterDetail(cluster.id)}
title="刷新节点指标"
>
<RefreshCw className="h-3.5 w-3.5" />
</Button>
</div>
</CardHeader>
<CardContent>
<div className="h-[200px]">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={[
{ time: 'CPU', cpu: Number(clusterMetrics.cpuPct.toFixed(1)), memory: Number(clusterMetrics.memPct.toFixed(1)) },
]}>
<AreaChart data={trendData} margin={{ top: 5, right: 10, left: 0, bottom: 5 }}>
<defs>
<linearGradient id="colorCpu" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#3b82f6" stopOpacity={0.3} />
<stop offset="95%" stopColor="#3b82f6" stopOpacity={0} />
<stop offset="5%" stopColor="#3b82f6" stopOpacity={0.35} />
<stop offset="95%" stopColor="#3b82f6" stopOpacity={0.05} />
</linearGradient>
<linearGradient id="colorMemory" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#10b981" stopOpacity={0.3} />
<stop offset="95%" stopColor="#10b981" stopOpacity={0} />
<stop offset="5%" stopColor="#10b981" stopOpacity={0.35} />
<stop offset="95%" stopColor="#10b981" stopOpacity={0.05} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="#1e293b" />
<XAxis dataKey="time" stroke="#475569" fontSize={12} />
<YAxis stroke="#475569" fontSize={12} domain={[0, 100]} />
<CartesianGrid strokeDasharray="2 2" stroke="#1e293b" />
<XAxis dataKey="time" stroke="#475569" fontSize={11} tickLine={false} />
<YAxis stroke="#475569" fontSize={11} domain={[0, 100]} unit="%" tickLine={false} />
<Tooltip
contentStyle={{
backgroundColor: '#0f172a',
border: '1px solid #1e293b',
borderRadius: '6px',
color: '#f8fafc',
fontSize: '12px',
}}
/>
<Area
type="monotone"
dataKey="cpu"
stroke="#3b82f6"
fillOpacity={1}
strokeWidth={2}
fill="url(#colorCpu)"
dot={false}
activeDot={{ r: 3, fill: '#3b82f6' }}
name="CPU(%)"
/>
<Area
type="monotone"
dataKey="memory"
stroke="#10b981"
fillOpacity={1}
strokeWidth={2}
fill="url(#colorMemory)"
dot={false}
activeDot={{ r: 3, fill: '#10b981' }}
name="内存(%)"
/>
</AreaChart>