Reorganize modules, add AI Agent smart interaction, include prompt settings, enhance data output with subscriptions, and separate system monitoring. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
347 lines
14 KiB
TypeScript
347 lines
14 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Badge } from "@/components/ui/badge"
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||
import { Input } from "@/components/ui/input"
|
||
import { Label } from "@/components/ui/label"
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||
import { Switch } from "@/components/ui/switch"
|
||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||
import {
|
||
Bell, Plus, Settings, CheckCircle2, AlertTriangle,
|
||
XCircle, Clock, Eye, Trash2, BellOff
|
||
} from "lucide-react"
|
||
|
||
const alerts = [
|
||
{
|
||
id: "1",
|
||
title: "磁盘使用率超过70%",
|
||
description: "服务器磁盘使用率达到72%,建议清理或扩容",
|
||
severity: "warning",
|
||
source: "系统监控",
|
||
time: "2024-01-15 14:30:00",
|
||
status: "active",
|
||
},
|
||
{
|
||
id: "2",
|
||
title: "AI推理服务延迟升高",
|
||
description: "AI推理服务平均延迟达到230ms,超过预设阈值200ms",
|
||
severity: "warning",
|
||
source: "AI Agent",
|
||
time: "2024-01-15 13:45:00",
|
||
status: "active",
|
||
},
|
||
{
|
||
id: "3",
|
||
title: "数据同步任务失败",
|
||
description: "用户行为数据同步任务执行失败,已自动重试",
|
||
severity: "error",
|
||
source: "数据接入",
|
||
time: "2024-01-15 10:20:00",
|
||
status: "resolved",
|
||
},
|
||
]
|
||
|
||
const alertRules = [
|
||
{ id: "1", name: "CPU使用率告警", condition: "CPU > 80%", severity: "critical", enabled: true },
|
||
{ id: "2", name: "内存使用率告警", condition: "内存 > 85%", severity: "critical", enabled: true },
|
||
{ id: "3", name: "磁盘使用率告警", condition: "磁盘 > 70%", severity: "warning", enabled: true },
|
||
{ id: "4", name: "API延迟告警", condition: "延迟 > 500ms", severity: "warning", enabled: true },
|
||
{ id: "5", name: "任务失败告警", condition: "失败次数 > 3", severity: "error", enabled: false },
|
||
]
|
||
|
||
export default function AlertsPage() {
|
||
const [activeTab, setActiveTab] = useState("active")
|
||
const [showCreateDialog, setShowCreateDialog] = useState(false)
|
||
|
||
const getSeverityBadge = (severity: string) => {
|
||
switch (severity) {
|
||
case "critical":
|
||
return <Badge className="bg-red-100 text-red-700">严重</Badge>
|
||
case "error":
|
||
return <Badge className="bg-red-100 text-red-700">错误</Badge>
|
||
case "warning":
|
||
return <Badge className="bg-yellow-100 text-yellow-700">警告</Badge>
|
||
case "info":
|
||
return <Badge className="bg-blue-100 text-blue-700">信息</Badge>
|
||
default:
|
||
return <Badge variant="secondary">未知</Badge>
|
||
}
|
||
}
|
||
|
||
const getSeverityIcon = (severity: string) => {
|
||
switch (severity) {
|
||
case "critical":
|
||
case "error":
|
||
return <XCircle className="h-5 w-5 text-red-500" />
|
||
case "warning":
|
||
return <AlertTriangle className="h-5 w-5 text-yellow-500" />
|
||
default:
|
||
return <Bell className="h-5 w-5 text-blue-500" />
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* 页面标题 */}
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<h1 className="text-2xl font-bold text-foreground">告警中心</h1>
|
||
<p className="text-muted-foreground">查看和管理系统告警</p>
|
||
</div>
|
||
<Button onClick={() => setShowCreateDialog(true)}>
|
||
<Plus className="mr-2 h-4 w-4" />
|
||
新建告警规则
|
||
</Button>
|
||
</div>
|
||
|
||
{/* 统计卡片 */}
|
||
<div className="grid gap-4 md:grid-cols-4">
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">活跃告警</p>
|
||
<p className="text-2xl font-bold text-yellow-600">2</p>
|
||
</div>
|
||
<AlertTriangle className="h-8 w-8 text-yellow-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">今日告警</p>
|
||
<p className="text-2xl font-bold">5</p>
|
||
</div>
|
||
<Bell className="h-8 w-8 text-blue-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">已解决</p>
|
||
<p className="text-2xl font-bold text-green-600">3</p>
|
||
</div>
|
||
<CheckCircle2 className="h-8 w-8 text-green-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">告警规则</p>
|
||
<p className="text-2xl font-bold">5</p>
|
||
</div>
|
||
<Settings className="h-8 w-8 text-purple-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
{/* 主内容区 */}
|
||
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
||
<TabsList>
|
||
<TabsTrigger value="active">
|
||
活跃告警
|
||
<Badge className="ml-2 bg-yellow-100 text-yellow-700">2</Badge>
|
||
</TabsTrigger>
|
||
<TabsTrigger value="history">历史告警</TabsTrigger>
|
||
<TabsTrigger value="rules">告警规则</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="active" className="space-y-4">
|
||
{alerts.filter(a => a.status === "active").map((alert) => (
|
||
<Card key={alert.id}>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-start justify-between">
|
||
<div className="flex items-start gap-4">
|
||
{getSeverityIcon(alert.severity)}
|
||
<div>
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<h3 className="font-semibold">{alert.title}</h3>
|
||
{getSeverityBadge(alert.severity)}
|
||
</div>
|
||
<p className="text-sm text-muted-foreground mb-2">{alert.description}</p>
|
||
<div className="flex items-center gap-4 text-xs text-muted-foreground">
|
||
<span>来源: {alert.source}</span>
|
||
<span>时间: {alert.time}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<Button variant="outline" size="sm">
|
||
<Eye className="h-4 w-4 mr-1" />
|
||
详情
|
||
</Button>
|
||
<Button size="sm">
|
||
<CheckCircle2 className="h-4 w-4 mr-1" />
|
||
确认
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</TabsContent>
|
||
|
||
<TabsContent value="history" className="space-y-4">
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>告警标题</TableHead>
|
||
<TableHead>严重程度</TableHead>
|
||
<TableHead>来源</TableHead>
|
||
<TableHead>时间</TableHead>
|
||
<TableHead>状态</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{alerts.map((alert) => (
|
||
<TableRow key={alert.id}>
|
||
<TableCell className="font-medium">{alert.title}</TableCell>
|
||
<TableCell>{getSeverityBadge(alert.severity)}</TableCell>
|
||
<TableCell>{alert.source}</TableCell>
|
||
<TableCell>{alert.time}</TableCell>
|
||
<TableCell>
|
||
{alert.status === "resolved" ? (
|
||
<Badge className="bg-green-100 text-green-700">已解决</Badge>
|
||
) : (
|
||
<Badge className="bg-yellow-100 text-yellow-700">活跃</Badge>
|
||
)}
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="rules" className="space-y-4">
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>规则名称</TableHead>
|
||
<TableHead>触发条件</TableHead>
|
||
<TableHead>严重程度</TableHead>
|
||
<TableHead>状态</TableHead>
|
||
<TableHead className="text-right">操作</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{alertRules.map((rule) => (
|
||
<TableRow key={rule.id}>
|
||
<TableCell className="font-medium">{rule.name}</TableCell>
|
||
<TableCell>
|
||
<code className="text-sm bg-muted px-2 py-1 rounded">{rule.condition}</code>
|
||
</TableCell>
|
||
<TableCell>{getSeverityBadge(rule.severity)}</TableCell>
|
||
<TableCell>
|
||
<Switch checked={rule.enabled} />
|
||
</TableCell>
|
||
<TableCell className="text-right">
|
||
<div className="flex items-center justify-end gap-1">
|
||
<Button variant="ghost" size="sm">
|
||
<Settings className="h-4 w-4" />
|
||
</Button>
|
||
<Button variant="ghost" size="sm" className="text-red-600">
|
||
<Trash2 className="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
</Tabs>
|
||
|
||
{/* 创建告警规则弹窗 */}
|
||
<Dialog open={showCreateDialog} onOpenChange={setShowCreateDialog}>
|
||
<DialogContent>
|
||
<DialogHeader>
|
||
<DialogTitle>新建告警规则</DialogTitle>
|
||
<DialogDescription>配置系统告警触发条件和通知方式</DialogDescription>
|
||
</DialogHeader>
|
||
<div className="space-y-4">
|
||
<div className="space-y-2">
|
||
<Label>规则名称</Label>
|
||
<Input placeholder="输入规则名称" />
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label>监控指标</Label>
|
||
<Select>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="选择指标" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="cpu">CPU使用率</SelectItem>
|
||
<SelectItem value="memory">内存使用率</SelectItem>
|
||
<SelectItem value="disk">磁盘使用率</SelectItem>
|
||
<SelectItem value="latency">API延迟</SelectItem>
|
||
<SelectItem value="error_rate">错误率</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>阈值</Label>
|
||
<Input placeholder="输入阈值" type="number" />
|
||
</div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>严重程度</Label>
|
||
<Select>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="选择严重程度" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="critical">严重</SelectItem>
|
||
<SelectItem value="warning">警告</SelectItem>
|
||
<SelectItem value="info">信息</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>通知方式</Label>
|
||
<div className="grid grid-cols-3 gap-2">
|
||
<label className="flex items-center gap-2 p-3 border rounded-lg cursor-pointer hover:bg-muted">
|
||
<input type="checkbox" defaultChecked />
|
||
<span>站内通知</span>
|
||
</label>
|
||
<label className="flex items-center gap-2 p-3 border rounded-lg cursor-pointer hover:bg-muted">
|
||
<input type="checkbox" />
|
||
<span>邮件</span>
|
||
</label>
|
||
<label className="flex items-center gap-2 p-3 border rounded-lg cursor-pointer hover:bg-muted">
|
||
<input type="checkbox" />
|
||
<span>短信</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setShowCreateDialog(false)}>取消</Button>
|
||
<Button>创建规则</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</div>
|
||
)
|
||
}
|