Reorganize navigation and module structure based on new requirements. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
167 lines
6.1 KiB
TypeScript
167 lines
6.1 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
|
import { Checkbox } from "@/components/ui/checkbox"
|
|
|
|
interface CreateAlertRuleDialogProps {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}
|
|
|
|
export function CreateAlertRuleDialog({ open, onOpenChange }: CreateAlertRuleDialogProps) {
|
|
const [formData, setFormData] = useState({
|
|
name: "",
|
|
metric: "",
|
|
operator: "gt",
|
|
threshold: "",
|
|
duration: "5",
|
|
severity: "warning",
|
|
channels: [] as string[],
|
|
})
|
|
|
|
const toggleChannel = (channel: string) => {
|
|
setFormData({
|
|
...formData,
|
|
channels: formData.channels.includes(channel)
|
|
? formData.channels.filter((c) => c !== channel)
|
|
: [...formData.channels, channel],
|
|
})
|
|
}
|
|
|
|
const handleSubmit = () => {
|
|
console.log("创建告警规则:", formData)
|
|
onOpenChange(false)
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-[500px]">
|
|
<DialogHeader>
|
|
<DialogTitle>新建告警规则</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="space-y-4 py-4">
|
|
<div className="space-y-2">
|
|
<Label>规则名称</Label>
|
|
<Input
|
|
placeholder="输入规则名称"
|
|
value={formData.name}
|
|
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>监控指标</Label>
|
|
<Select value={formData.metric} onValueChange={(value) => setFormData({ ...formData, metric: value })}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="选择监控指标" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="cpu">CPU使用率</SelectItem>
|
|
<SelectItem value="memory">内存使用率</SelectItem>
|
|
<SelectItem value="disk">磁盘使用率</SelectItem>
|
|
<SelectItem value="api_latency">API延迟(P99)</SelectItem>
|
|
<SelectItem value="api_error_rate">API错误率</SelectItem>
|
|
<SelectItem value="qps">QPS</SelectItem>
|
|
<SelectItem value="service_status">服务状态</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>条件</Label>
|
|
<Select
|
|
value={formData.operator}
|
|
onValueChange={(value) => setFormData({ ...formData, operator: value })}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="gt">大于</SelectItem>
|
|
<SelectItem value="lt">小于</SelectItem>
|
|
<SelectItem value="eq">等于</SelectItem>
|
|
<SelectItem value="gte">大于等于</SelectItem>
|
|
<SelectItem value="lte">小于等于</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>阈值</Label>
|
|
<Input
|
|
placeholder="80"
|
|
value={formData.threshold}
|
|
onChange={(e) => setFormData({ ...formData, threshold: e.target.value })}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>持续时间(分钟)</Label>
|
|
<Input
|
|
type="number"
|
|
value={formData.duration}
|
|
onChange={(e) => setFormData({ ...formData, duration: e.target.value })}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>严重程度</Label>
|
|
<RadioGroup
|
|
value={formData.severity}
|
|
onValueChange={(value) => setFormData({ ...formData, severity: value })}
|
|
className="flex gap-4"
|
|
>
|
|
<div className="flex items-center space-x-2">
|
|
<RadioGroupItem value="info" id="info" />
|
|
<Label htmlFor="info" className="text-blue-600">
|
|
信息
|
|
</Label>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<RadioGroupItem value="warning" id="warning" />
|
|
<Label htmlFor="warning" className="text-amber-600">
|
|
警告
|
|
</Label>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<RadioGroupItem value="critical" id="critical" />
|
|
<Label htmlFor="critical" className="text-red-600">
|
|
严重
|
|
</Label>
|
|
</div>
|
|
</RadioGroup>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>通知渠道</Label>
|
|
<div className="flex flex-wrap gap-4">
|
|
{["邮件", "短信", "企业微信", "钉钉", "Webhook"].map((channel) => (
|
|
<div key={channel} className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id={channel}
|
|
checked={formData.channels.includes(channel)}
|
|
onCheckedChange={() => toggleChannel(channel)}
|
|
/>
|
|
<Label htmlFor={channel}>{channel}</Label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
取消
|
|
</Button>
|
|
<Button onClick={handleSubmit}>创建规则</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|