feat: 完善堡垒机与 Agent 智能运维能力
- 支持 Windows Agent 构建、安装脚本和统一上报协议 - 增强 RDP 剪贴板、虚拟盘和文件传输能力 - 新增 AIOps 上下文工具、告警 RCA trace 落库和回放接口 - 重构 docs 模块文档并补充终端、堡垒机、监控、AI Agent 设计
This commit is contained in:
1 parent
a9513c2056
commit
e0d652d211
169 files changed
+12192
-9116
No files matched your search
@@ -77,7 +77,7 @@ export default function CapacityPage() {
|
||||
return (
|
||||
<PageShell
|
||||
variant="list"
|
||||
title=i18n.t('k8s.capacity.resources')
|
||||
title={i18n.t('k8s.capacity.resources')}
|
||||
subtitle={clusterName ? `${clusterName} · Deployment 资源请求与限制` : i18n.t('k8s.capacity.resources1')}
|
||||
icon={<BarChart3 className="h-5 w-5" />}
|
||||
actions={(
|
||||
@@ -89,7 +89,7 @@ export default function CapacityPage() {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select value={selectedNs} onValueChange={setSelectedNs}>
|
||||
<SelectTrigger className="w-32 h-9 dg-input"><SelectValue placeholder=i18n.t('k8s.capacity.namespace') /></SelectTrigger>
|
||||
<SelectTrigger className="w-32 h-9 dg-input"><SelectValue placeholder={i18n.t('k8s.capacity.namespace')} /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">所有命名空间</SelectItem>
|
||||
{namespaces.map(n => <SelectItem key={n} value={n}>{n}</SelectItem>)}
|
||||
@@ -120,7 +120,7 @@ export default function CapacityPage() {
|
||||
</TableRow></TableHeader>
|
||||
<TableBody>
|
||||
{rows.length === 0 ? (
|
||||
<TableRow><TableCell colSpan={8} className="text-center dg-text-muted py-8i18n.t('k8s.capacity.s934752c9')animate-spin inline-block ml-2">⏳</span> : ''}</TableCell></TableRow>
|
||||
<TableRow><TableCell colSpan={8} className="text-center dg-text-muted py-8">{i18n.t('k8s.capacity.s934752c9')}</TableCell></TableRow>
|
||||
) : rows.map((r, i) => (
|
||||
<TableRow key={`${r.deployment}-${r.container}-${i}`} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-hover)]">
|
||||
<TableCell className="font-medium text-[var(--dg-text-primary)] text-sm">{r.deployment}</TableCell>
|
||||
|
||||
@@ -432,7 +432,7 @@ export function DeploymentEditAdvanced({ clusterCode, namespace, deploymentName,
|
||||
<option value="PreferNoSchedule">PreferNoSchedule</option>
|
||||
<option value="NoExecute">NoExecute</option>
|
||||
</select>
|
||||
<Input value={t.tolerationSeconds} placeholder=i18n.t('k8s.editAdvanced.s0c1fec65') disabled={t.effect !== 'NoExecute'}
|
||||
<Input value={t.tolerationSeconds} placeholder={i18n.t('k8s.editAdvanced.s0c1fec65')} disabled={t.effect !== 'NoExecute'}
|
||||
onChange={e => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, tolerationSeconds: e.target.value } : x))}
|
||||
className="h-7 dg-input text-xs font-mono" />
|
||||
<Button variant="ghost" size="icon" className="h-7 w-7 dg-text-red" onClick={() => setTolerations(prev => prev.filter((_, idx) => idx !== i))}>
|
||||
|
||||
@@ -190,7 +190,7 @@ export function KubectlTerminal({ open, onOpenChange, clusterId, clusterName }:
|
||||
{/* 终端容器 */}
|
||||
<div className="relative bg-[#0f172a]" style={{ height: fullscreen ? 'calc(100vh - 49px)' : '480px' }}>
|
||||
<div ref={containerRef} className="xterm-terminal-host h-full" />
|
||||
<TerminalLoadingOverlay show={!hasOutput && !error} label=i18n.t('k8s.kubectl.cluster') />
|
||||
<TerminalLoadingOverlay show={!hasOutput && !error} label={i18n.t('k8s.kubectl.cluster')} />
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -473,12 +473,16 @@ export default function NamespaceResourcePage() {
|
||||
);
|
||||
|
||||
const ResourceIcon = config.icon;
|
||||
const subtitleParts = [clusterCode, namespace].filter(Boolean);
|
||||
const pageSubtitle = subtitleParts.length > 0
|
||||
? `${subtitleParts.join(' / ')} · ${config.subtitle}`
|
||||
: config.subtitle;
|
||||
|
||||
return (
|
||||
<PageShell
|
||||
variant="list"
|
||||
title={config.title}
|
||||
subtitle={`${clusterCode || '-'} / ${namespace || '-'} · ${config.subtitle}`}
|
||||
subtitle={pageSubtitle}
|
||||
icon={<ResourceIcon className="h-5 w-5" />}
|
||||
actions={(
|
||||
<>
|
||||
|
||||
@@ -308,7 +308,7 @@ export function PodExecTerminal({
|
||||
<Select value={container} onValueChange={setContainer}>
|
||||
<SelectTrigger className="h-8 w-[150px] text-xs bg-[var(--dg-bg-hover)] border-[var(--dg-border)]">
|
||||
<Box className="h-3 w-3 mr-1 text-[var(--dg-text-muted)]" />
|
||||
<SelectValue placeholder=i18n.t('k8s.podExec.container') />
|
||||
<SelectValue placeholder={i18n.t('k8s.podExec.container')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>{containers.map((c) => <SelectItem key={c} value={c}>{c}</SelectItem>)}</SelectContent>
|
||||
</Select>
|
||||
@@ -320,13 +320,13 @@ export function PodExecTerminal({
|
||||
<SelectContent>{SHELLS.map(s => <SelectItem key={s.value} value={s.value}>{s.label}</SelectItem>)}</SelectContent>
|
||||
</Select>
|
||||
<Button variant="ghost" size="sm" className="h-8 px-2 text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)]"
|
||||
onClick={() => { connect(); toast({ title: i18n.t('k8s.podExec.reconnect1') }); }} title=i18n.t('k8s.podExec.reconnect2')>
|
||||
onClick={() => { connect(); toast({ title: i18n.t('k8s.podExec.reconnect1') }); }} title={i18n.t('k8s.podExec.reconnect2')}>
|
||||
<RotateCw className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
<button onClick={() => setFullscreen(!fullscreen)} className="p-1.5 rounded hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-secondary)]" title={fullscreen ? i18n.t('k8s.podExec.exitFullscreen') : i18n.t('k8s.podExec.fullscreen')}>
|
||||
{fullscreen ? <Minimize2 className="h-4 w-4" /> : <Maximize2 className="h-4 w-4" />}
|
||||
</button>
|
||||
<button onClick={() => onOpenChange(false)} className="p-1.5 rounded hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-secondary)]" title=i18n.t('k8s.podExec.close1')>
|
||||
<button onClick={() => onOpenChange(false)} className="p-1.5 rounded hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-secondary)]" title={i18n.t('k8s.podExec.close1')}>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -339,7 +339,7 @@ export function PodExecTerminal({
|
||||
className="xterm-terminal-host h-full cursor-text"
|
||||
onClick={handleTerminalClick}
|
||||
/>
|
||||
<TerminalLoadingOverlay show={connState === 'connecting' && !hasOutput} label=i18n.t('k8s.podExec.container1') />
|
||||
<TerminalLoadingOverlay show={connState === 'connecting' && !hasOutput} label={i18n.t('k8s.podExec.container1')} />
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -86,7 +86,7 @@ export default function PodMetricsPage() {
|
||||
return (
|
||||
<PageShell
|
||||
variant="list"
|
||||
title=i18n.t('k8s.podMetrics.resources2')
|
||||
title={i18n.t('k8s.podMetrics.resources2')}
|
||||
subtitle={clusterName ? `${clusterName} · 容器 CPU/内存实时指标` : i18n.t('k8s.podMetrics.container2')}
|
||||
icon={<Activity className="h-5 w-5" />}
|
||||
metrics={!loading ? (
|
||||
@@ -107,7 +107,7 @@ export default function PodMetricsPage() {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select value={selectedNs} onValueChange={setSelectedNs}>
|
||||
<SelectTrigger className="w-36 h-9 dg-input"><SelectValue placeholder=i18n.t('k8s.podMetrics.namespace') /></SelectTrigger>
|
||||
<SelectTrigger className="w-36 h-9 dg-input"><SelectValue placeholder={i18n.t('k8s.podMetrics.namespace')} /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">所有命名空间</SelectItem>
|
||||
{namespaces.map(n => <SelectItem key={n} value={n}>{n}</SelectItem>)}
|
||||
@@ -131,7 +131,7 @@ export default function PodMetricsPage() {
|
||||
</TableRow></TableHeader>
|
||||
<TableBody>
|
||||
{rows.length === 0 ? (
|
||||
<TableRow><TableCell colSpan={5} className="text-center dg-text-muted py-8i18n.t('k8s.podMetrics.s934752c9')animate-spin inline-block ml-2">⏳</span> : ''}</TableCell></TableRow>
|
||||
<TableRow><TableCell colSpan={5} className="text-center dg-text-muted py-8">{i18n.t('k8s.podMetrics.s934752c9')}</TableCell></TableRow>
|
||||
) : rows.map((r, i) => (
|
||||
<TableRow key={`${r.pod}-${r.container}-${i}`} className="border-[var(--dg-border)] hover:bg-[var(--dg-bg-hover)]">
|
||||
<TableCell className="font-medium text-[var(--dg-text-primary)] text-sm">{r.pod}</TableCell>
|
||||
|
||||
@@ -335,7 +335,7 @@ function ConfigMapEditor({ manifest, onSave, saving, isCreate }: { manifest: any
|
||||
<Textarea
|
||||
value={entry.value}
|
||||
onChange={e => update(i, 'value', e.target.value)}
|
||||
placeholder=i18n.t('k8s.resourceEditor.sfe7509e0')
|
||||
placeholder={i18n.t('k8s.resourceEditor.sfe7509e0')}
|
||||
rows={expandAll || entry.value.length > 300 ? 10 : (entry.value.length > 100 ? 6 : 3)}
|
||||
className="flex-[2] font-mono text-xs min-h-[70px] max-h-[420px] resize-y bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)] leading-relaxed"
|
||||
/>
|
||||
|
||||
@@ -98,7 +98,7 @@ export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCrea
|
||||
className="dg-input mt-1" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-smi18n.t('k8s.misc.memory1')dg-text-muted">可选</span></Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t('k8s.misc.memory1')} <span className="dg-text-muted">可选</span></Label>
|
||||
<Input type="number" value={form.memPercent} min={0} max={100}
|
||||
onChange={(e) => setForm({ ...form, memPercent: Number(e.target.value) })}
|
||||
className="dg-input mt-1" />
|
||||
|
||||
Reference in new issue
Block a user