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:
1 parent
5ca0e6d83a
commit
8d46e8f352
197 files changed
+5014
-815
No files matched your search
@@ -5,6 +5,12 @@ import {
|
||||
} from '../k8s-yaml-utils';
|
||||
import type { PodItem } from './types';
|
||||
|
||||
export interface PodStage {
|
||||
label: string;
|
||||
ts?: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
// Pod 条件时间线提取 // Logan.Li
|
||||
export function getPodTimeline(pod: PodItem) {
|
||||
const cond: Record<string, any>[] = (pod as Record<string, any>).conditions || (pod as Record<string, any>).pod_conditions || [];
|
||||
@@ -19,6 +25,17 @@ export function getPodTimeline(pod: PodItem) {
|
||||
};
|
||||
}
|
||||
|
||||
// 启动阶段列表(列表/详情共用) // Logan.Li
|
||||
export function getPodStages(pod: PodItem): PodStage[] {
|
||||
const tl = getPodTimeline(pod);
|
||||
return [
|
||||
{ label: '已调度', ts: tl.scheduled, color: STATUS_COLORS.blue },
|
||||
{ label: '已初始化', ts: tl.initialized, color: STATUS_COLORS.orange },
|
||||
{ label: '容器已就绪', ts: tl.containersReady, color: STATUS_COLORS.green },
|
||||
{ label: '容器组已就绪', ts: tl.ready, color: STATUS_COLORS.green },
|
||||
];
|
||||
}
|
||||
|
||||
// 信息面板单项 // Logan.Li
|
||||
export function InfoItem({ label, value }: { label: string; value: React.ReactNode }) {
|
||||
return (
|
||||
@@ -29,36 +46,99 @@ export function InfoItem({ label, value }: { label: string; value: React.ReactNo
|
||||
);
|
||||
}
|
||||
|
||||
// Pod 条件进度条 // Logan.Li
|
||||
export function PodConditionsRow({ pod }: { pod: PodItem }) {
|
||||
const tl = getPodTimeline(pod);
|
||||
const stages = [
|
||||
{ label: '已调度', ts: tl.scheduled, color: STATUS_COLORS.blue },
|
||||
{ label: '已初始化', ts: tl.initialized, color: STATUS_COLORS.orange },
|
||||
{ label: '容器已就绪', ts: tl.containersReady, color: STATUS_COLORS.green },
|
||||
{ label: '容器组已就绪', ts: tl.ready, color: STATUS_COLORS.green },
|
||||
];
|
||||
// 列表行紧凑就绪指示(无时间戳,避免视觉疲劳) // Logan.Li
|
||||
export function PodStatusCompact({ pod }: { pod: PodItem }) {
|
||||
const stages = getPodStages(pod);
|
||||
const done = stages.filter(s => s.ts).length;
|
||||
const allReady = done === stages.length;
|
||||
const pending = stages.find(s => !s.ts);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 overflow-x-auto">
|
||||
{stages.map((s, i) => {
|
||||
const prev = stages[i - 1];
|
||||
const dur = elapsedSeconds(prev?.ts, s.ts);
|
||||
return (
|
||||
<div className="flex items-center gap-2 min-w-[88px]">
|
||||
<div className="flex items-center gap-0.5" aria-label="启动进度">
|
||||
{stages.map((s, i) => (
|
||||
<Fragment key={s.label}>
|
||||
<div className="flex flex-col items-center min-w-[80px]">
|
||||
<div className="h-2 w-2 rounded-full" style={{ background: s.ts ? s.color : '#334155' }} />
|
||||
<span className="text-[10px] mt-1 font-medium" style={{ color: s.ts ? s.color : '#475569' }}>{s.label}</span>
|
||||
<span className="text-[9px] text-[var(--dg-text-muted)]">{s.ts ? formatK8sTime(s.ts) : '-'}</span>
|
||||
</div>
|
||||
<span
|
||||
className="inline-block h-1.5 w-1.5 rounded-full shrink-0"
|
||||
style={{ background: s.ts ? s.color : 'var(--dg-border)' }}
|
||||
title={`${s.label}${s.ts ? ` · ${formatK8sTime(s.ts)}` : ''}`}
|
||||
/>
|
||||
{i < stages.length - 1 && (
|
||||
<div className="flex flex-col items-center mx-0.5 min-w-[30px]">
|
||||
<div className="h-0.5 w-8 bg-[var(--dg-border)]" />
|
||||
<span className="text-[9px] text-[var(--dg-text-muted)] mt-0.5">{dur != null ? formatDuration(dur) : ''}</span>
|
||||
</div>
|
||||
<span
|
||||
className="inline-block h-px w-2 shrink-0"
|
||||
style={{ background: s.ts && stages[i + 1]?.ts ? s.color : 'var(--dg-border)' }}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</div>
|
||||
<span
|
||||
className="text-[11px] whitespace-nowrap"
|
||||
style={{ color: allReady ? STATUS_COLORS.green : 'var(--dg-text-muted)' }}
|
||||
>
|
||||
{allReady ? '就绪' : pending?.label || `${done}/${stages.length}`}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 详情区完整启动时间线(仅展开或概览面板使用) // Logan.Li
|
||||
export function PodConditionsRow({ pod }: { pod: PodItem }) {
|
||||
const stages = getPodStages(pod);
|
||||
const totalBoot = elapsedSeconds(stages[0]?.ts, stages[stages.length - 1]?.ts);
|
||||
|
||||
return (
|
||||
<div className="rounded-lg bg-[var(--dg-bg-tertiary)]/60 px-4 py-3">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs text-[var(--dg-text-muted)]">启动时间线</span>
|
||||
{totalBoot != null && (
|
||||
<span className="text-[11px] text-[var(--dg-text-muted)]">
|
||||
总耗时 <span className="font-mono text-[var(--dg-text-secondary)]">{formatDuration(totalBoot)}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-start gap-0 overflow-x-auto">
|
||||
{stages.map((s, i) => {
|
||||
const prev = stages[i - 1];
|
||||
const dur = elapsedSeconds(prev?.ts, s.ts);
|
||||
const active = !!s.ts;
|
||||
return (
|
||||
<Fragment key={s.label}>
|
||||
<div className="flex flex-col min-w-[108px]">
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[10px] font-semibold"
|
||||
style={{
|
||||
background: active ? `${s.color}22` : 'var(--dg-bg-secondary)',
|
||||
color: active ? s.color : 'var(--dg-text-muted)',
|
||||
border: `1px solid ${active ? `${s.color}55` : 'var(--dg-border)'}`,
|
||||
}}
|
||||
>
|
||||
{i + 1}
|
||||
</span>
|
||||
<span className="text-xs font-medium" style={{ color: active ? s.color : 'var(--dg-text-muted)' }}>
|
||||
{s.label}
|
||||
</span>
|
||||
</div>
|
||||
<span className="mt-1.5 pl-7 text-[11px] font-mono text-[var(--dg-text-muted)]">
|
||||
{s.ts ? formatK8sTime(s.ts) : '—'}
|
||||
</span>
|
||||
</div>
|
||||
{i < stages.length - 1 && (
|
||||
<div className="flex flex-col items-center justify-center px-1 pt-2.5 min-w-[48px]">
|
||||
<div
|
||||
className="h-px w-full"
|
||||
style={{ background: active && stages[i + 1]?.ts ? s.color : 'var(--dg-border)' }}
|
||||
/>
|
||||
<span className="mt-1 text-[10px] text-[var(--dg-text-muted)]">
|
||||
{dur != null ? formatDuration(dur) : ''}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user