feat(alert-center): 添加飞书Webhook通知渠道 + 告警引擎实时通知

- 后端: NotifyChannel 模型新增 feishu 类型, FeishuWebhookConfig
- 后端: TestNotifyChannel 真实发送飞书测试消息(文本格式)
- 后端: 告警引擎触发/恢复时自动发送飞书通知(sendFeishuAlert/sendFeishuRecovery)
- 后端: AlertEngine 新增 tcp_time_wait/tcp_close_wait/service_process 指标检测
- 后端: NetworkStatModel 新增 TCPCloseWait 字段
- 后端: QuickSetupRules 一键创建6条告警规则(CPU/内存/磁盘/TIME_WAIT/CLOSE_WAIT/进程)
- 后端: 注册 /alerts/quick-setup 路由
- 前端: AlertChannelDialog 新增飞书类型选项
- 前端: helpers 新增 getChannelIcon/getChannelTypeLabel 支持 feishu/dingtalk/wechat
This commit is contained in:
attacker committed 2026-06-24 08:34:43 +00:00
1 parent 7bc5169e8f
commit 5333f6f04a
30 files changed
+2406 -1001

No files matched your search

@@ -85,7 +85,7 @@ export function PipelineManager() {
const [newCachePaths, setNewCachePaths] = useState('');
// Executor concurrency
const [newMaxExecutors, setNewMaxExecutors] = useState(1);
const [newMaxExecutors, setNewMaxExecutors] = useState(2);
// Reference data
const [repos, setRepos] = useState<any[]>([]);
@@ -288,33 +288,46 @@ export function PipelineManager() {
))}
</div>
{/* ══════════ 全流程可视化横幅 // Logan.Li ══════════ */}
<div className="flex items-center gap-1.5 px-4 py-2.5 rounded-lg bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)]">
<div className="flex items-center gap-1">
<GitBranch className="h-3.5 w-3.5 text-indigo-400" />
<span className="text-[11px] font-semibold text-indigo-400">Git 代码</span>
{/* ══════════ 全流程可视化横幅 — 双路径 ══════════ */}
<div className="flex items-stretch gap-3 px-4 py-3 rounded-lg bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)]">
{/* 路径 1: SSH 传统主机部署 */}
<div className="flex-1 space-y-1.5">
<div className="flex items-center gap-1.5">
<GitBranch className="h-3 w-3 text-indigo-400" />
<span className="text-[10px] font-semibold text-indigo-400">构建</span>
<ArrowRight className="h-2.5 w-2.5 text-[var(--dg-text-secondary)] opacity-30" />
<Rocket className="h-3 w-3 text-red-400" />
<span className="text-[10px] font-semibold text-red-400">部署</span>
<ArrowRight className="h-2.5 w-2.5 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1 px-2 py-0.5 rounded bg-blue-400/10 border border-blue-400/20">
<Server className="h-3 w-3 text-blue-400" />
<span className="text-[10px] font-medium text-blue-400">SSH 主机</span>
</div>
</div>
<p className="text-[9px] text-[var(--dg-text-secondary)] opacity-40 pl-1">传统主机 SCP 部署 · 无需镜像仓库</p>
</div>
<ArrowRight className="h-3 w-3 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1">
<Box className="h-3.5 w-3.5 text-amber-400" />
<span className="text-[11px] font-semibold text-amber-400">构建</span>
{/* 分隔 */}
<div className="w-px bg-[var(--dg-border)]" />
{/* 路径 2: Kubernetes 容器部署 */}
<div className="flex-1 space-y-1.5">
<div className="flex items-center gap-1.5">
<GitBranch className="h-3 w-3 text-indigo-400" />
<span className="text-[10px] font-semibold text-indigo-400">构建</span>
<ArrowRight className="h-2.5 w-2.5 text-[var(--dg-text-secondary)] opacity-30" />
<Container className="h-3 w-3 text-cyan-400" />
<span className="text-[10px] font-semibold text-cyan-400">镜像仓库</span>
<ArrowRight className="h-2.5 w-2.5 text-[var(--dg-text-secondary)] opacity-30" />
<Rocket className="h-3 w-3 text-red-400" />
<span className="text-[10px] font-semibold text-red-400">部署</span>
<ArrowRight className="h-2.5 w-2.5 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1 px-2 py-0.5 rounded bg-emerald-400/10 border border-emerald-400/20">
<Network className="h-3 w-3 text-emerald-400" />
<span className="text-[10px] font-medium text-emerald-400">Kubernetes</span>
</div>
</div>
<p className="text-[9px] text-[var(--dg-text-secondary)] opacity-40 pl-1">容器化部署 · 需镜像仓库推送</p>
</div>
<ArrowRight className="h-3 w-3 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1">
<Container className="h-3.5 w-3.5 text-cyan-400" />
<span className="text-[11px] font-semibold text-cyan-400">镜像仓库</span>
</div>
<ArrowRight className="h-3 w-3 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1">
<Rocket className="h-3.5 w-3.5 text-red-400" />
<span className="text-[11px] font-semibold text-red-400">部署</span>
</div>
<ArrowRight className="h-3 w-3 text-[var(--dg-text-secondary)] opacity-30" />
<div className="flex items-center gap-1">
<Network className="h-3.5 w-3.5 text-emerald-400" />
<span className="text-[11px] font-semibold text-emerald-400">K8s</span>
</div>
<span className="ml-auto text-[10px] text-[var(--dg-text-secondary)] opacity-40 tracking-wide">全流程可视化</span>
<span className="self-center ml-2 text-[10px] text-[var(--dg-text-secondary)] opacity-30 tracking-wide whitespace-nowrap">全流程可视化</span>
</div>
<div className="flex items-center gap-4">
@@ -401,7 +414,7 @@ export function PipelineManager() {
)}
<div className="flex items-center gap-3 mt-1.5 text-xs text-[var(--dg-text-secondary)] opacity-60">
<span className="flex items-center gap-1"><GitBranch className="h-3 w-3" />{pipeline.deploy_mode === 'tag' ? 'Tag发版' : pipeline.branch || 'main'}</span>
<span className="flex items-center gap-1">{(pipeline.deploy_target || 'ssh') === 'k8s' ? <><Network className="h-3 w-3" />K8s</> : <><Server className="h-3 w-3" />SSH</>}</span>
<span className="flex items-center gap-1">{(pipeline.deploy_target || 'ssh') === 'k8s' ? <><Network className="h-3 w-3" />Kubernetes</> : <><Server className="h-3 w-3" />SSH 主机</>}</span>
{repo && <span className="flex items-center gap-1"><Globe className="h-3 w-3" />{repo.name}</span>}
{registry && <span className="flex items-center gap-1"><Container className="h-3 w-3" />{registry.name}</span>}
{pipeline.last_run_at && <span><Clock className="h-3 w-3 inline mr-0.5" />{new Date(pipeline.last_run_at).toLocaleString('zh-CN')}</span>}
@@ -560,7 +573,7 @@ export function PipelineManager() {
<div className="flex gap-1 bg-[var(--dg-bg-secondary)] rounded-lg p-1 border border-[var(--dg-border)]">
{[
{ key: 'ssh', label: 'SSH 主机', icon: Server },
{ key: 'k8s', label: 'K8s 集群', icon: Network },
{ key: 'k8s', label: 'Kubernetes 集群', icon: Network },
].map(t => {
const active = newDeployTarget === t.key;
return (
@@ -819,7 +832,7 @@ export function PipelineManager() {
</SelectContent>
</Select>
</div>
<p className="text-[10px] text-[var(--dg-text-secondary)] opacity-50 mt-1">设为 1 则按顺序串行执行,超过 1 可并发构建</p>
<p className="text-[10px] text-[var(--dg-text-secondary)] opacity-50 mt-1">设为 1 则按顺序串行执行,默认 2 可并发构建</p>
</div>
</div>
<div className="flex justify-end gap-2 mt-4 pt-4 border-t border-[var(--dg-border)]">
@@ -889,7 +902,7 @@ function PipelineQueuePanel({ pipeline, clusterId: _cid }: { pipeline: any; clus
const running = queue?.running || 0;
const queued = queue?.queued || 0;
const queueIds: number[] = queue?.queue_ids || [];
const max = pipeline.max_executors || 1;
const max = pipeline.max_executors || 2;
const pendingRuns = queue?.pending_runs || [];
if (loading && !queue) return null;