feat: 工具配置增强、站点拨测与日志中心多项改进

- 工具配置:新增卸载 API/UI、Go 工具链、流水线构建自动安装依赖
- 修复 ListTools VerifyTool 递归栈溢出导致获取工具配置失败
- Node.js Alpine 安装改用 unofficial-builds musl 预编译包与 index.json 解析 LTS
- 站点拨测:详情页路由、告警自动恢复、并发拨测与默认可观测频率
- 日志中心:RBAC、查询构建器、ES/Loki 增强与审计 request/response 展示
- 发布配置:构建节点、流水线远程执行、Deploy RBAC 导航拆分
This commit is contained in:
Logan committed 2026-07-02 07:47:33 +08:00
1 parent cde7bbe540
commit 7e1c8f583c
84 files changed
+7729 -1507

No files matched your search

@@ -0,0 +1,88 @@
import { useState, useEffect } from 'react';
import { X, Trash2, Play, Bookmark, Clock } from 'lucide-react';
import type { SavedQuery } from './types-v3';
import { savedQueryStorage } from './types-v3';
import { ENGINE_META } from './types-v3';
interface Props {
visible: boolean;
onClose: () => void;
onSelect: (item: SavedQuery) => void;
}
// 已保存查询面板(localStorage)// Logan.Li
export function SavedQueriesPanel({ visible, onClose, onSelect }: Props) {
const [items, setItems] = useState<SavedQuery[]>([]);
useEffect(() => {
if (visible) setItems(savedQueryStorage.getAll());
}, [visible]);
if (!visible) return null;
return (
<>
<div className="fixed inset-0 z-40" style={{ background: 'rgba(0,0,0,0.3)' }} onClick={onClose} />
<div
className="fixed right-0 top-0 h-full z-50 border-l flex flex-col"
style={{ width: '380px', background: 'var(--dg-bg-secondary)', borderColor: 'var(--dg-border)' }}
>
<div className="flex items-center justify-between px-4 py-3 border-b" style={{ borderColor: 'var(--dg-border)' }}>
<div className="flex items-center gap-2">
<Bookmark className="h-4 w-4" style={{ color: 'var(--dg-blue)' }} />
<span className="text-sm font-medium" style={{ color: 'var(--dg-text-primary)' }}>已保存查询</span>
<span className="text-[10px] px-1.5 py-0.5 rounded" style={{ background: 'var(--dg-bg-tertiary)', color: 'var(--dg-text-muted)' }}>
{items.length}
</span>
</div>
<button onClick={onClose} className="h-7 w-7 flex items-center justify-center" style={{ color: 'var(--dg-text-muted)' }}>
<X className="h-4 w-4" />
</button>
</div>
<div className="flex-1 overflow-y-auto p-3 space-y-2">
{items.length === 0 ? (
<p className="text-xs text-center py-8" style={{ color: 'var(--dg-text-muted)' }}>暂无保存的查询</p>
) : items.map((item) => (
<div
key={item.id}
className="p-3 rounded-lg border group"
style={{ background: 'var(--dg-bg-tertiary)', borderColor: 'var(--dg-border)' }}
>
<div className="flex items-start justify-between gap-2">
<div className="min-w-0 flex-1">
<p className="text-sm font-medium truncate" style={{ color: 'var(--dg-text-primary)' }}>{item.name}</p>
<p className="text-[10px] mt-0.5" style={{ color: ENGINE_META[item.engine]?.color || 'var(--dg-text-muted)' }}>
{ENGINE_META[item.engine]?.name} · {item.timeRangeLabel}
</p>
<p className="text-[11px] font-mono mt-1 truncate" style={{ color: 'var(--dg-text-secondary)' }}>{item.query}</p>
<p className="text-[10px] mt-1 flex items-center gap-1" style={{ color: 'var(--dg-text-muted)' }}>
<Clock className="h-3 w-3" />
{new Date(item.createdAt).toLocaleString()}
</p>
</div>
<div className="flex flex-col gap-1 opacity-80 group-hover:opacity-100">
<button
onClick={() => { onSelect(item); onClose(); }}
className="h-7 w-7 flex items-center justify-center rounded border"
style={{ borderColor: 'var(--dg-border)', color: '#22c55e' }}
title="应用"
>
<Play className="h-3.5 w-3.5" />
</button>
<button
onClick={() => { savedQueryStorage.remove(item.id); setItems(savedQueryStorage.getAll()); }}
className="h-7 w-7 flex items-center justify-center rounded border"
style={{ borderColor: 'var(--dg-border)', color: 'var(--dg-text-muted)' }}
title="删除"
>
<Trash2 className="h-3.5 w-3.5" />
</button>
</div>
</div>
</div>
))}
</div>
</div>
</>
);
}