import { Button, Card, Checkbox, Form, Input, Modal, Badge } from "antd"; import { EditOutlined, DeleteOutlined, KeyOutlined, ReloadOutlined, ExperimentOutlined, ThunderboltOutlined, } from "@ant-design/icons"; import { useState } from "react"; interface WebhookEvent { id: string; name: string; description: string; category: string; } interface WebhookConfig { id: string; name: string; url: string; events: string[]; status: "active" | "inactive"; secret: string; retryCount: number; } const availableEvents: WebhookEvent[] = [ { id: "project_created", name: "项目创建", description: "新项目被创建时触发", category: "项目管理", }, { id: "project_updated", name: "项目更新", description: "项目信息被修改时触发", category: "项目管理", }, { id: "project_deleted", name: "项目删除", description: "项目被删除时触发", category: "项目管理", }, { id: "task_created", name: "任务创建", description: "新任务被创建时触发", category: "任务管理", }, { id: "task_updated", name: "任务更新", description: "任务状态或内容被更新时触发", category: "任务管理", }, { id: "task_completed", name: "任务完成", description: "任务被标记为完成时触发", category: "任务管理", }, { id: "annotation_created", name: "标注创建", description: "新标注被创建时触发", category: "标注管理", }, { id: "annotation_updated", name: "标注更新", description: "标注被修改时触发", category: "标注管理", }, { id: "annotation_deleted", name: "标注删除", description: "标注被删除时触发", category: "标注管理", }, { id: "model_trained", name: "模型训练完成", description: "模型训练任务完成时触发", category: "模型管理", }, { id: "prediction_created", name: "预测生成", description: "新预测结果生成时触发", category: "预测管理", }, ]; export default function WebhookConfig() { const [newWebhook, setNewWebhook] = useState({ name: "", url: "", events: [] as string[], secret: "", retryCount: 3, }); const [showWebhookDialog, setShowWebhookDialog] = useState(false); // Webhook State const [webhooks, setWebhooks] = useState([ { id: "1", name: "数据同步Webhook", url: "https://webhook.example.com/data-sync", events: ["task_created", "task_completed", "annotation_created"], status: "active", secret: "wh_secret_123456", retryCount: 3, }, { id: "2", name: "任务通知Webhook", url: "https://webhook.example.com/task-notify", events: ["task_started", "task_completed", "task_failed"], status: "inactive", secret: "wh_secret_789012", retryCount: 5, }, ]); const handleAddWebhook = () => { setNewWebhook({ name: "", url: "", events: [], secret: generateApiKey(), retryCount: 3, }); setShowWebhookDialog(true); }; const generateApiKey = () => { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = "sk-"; for (let i = 0; i < 48; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; }; return (

Webhook 配置

{webhooks.map((webhook) => (
{webhook.name}

{webhook.url}

事件: {webhook.events.map((event) => { const eventInfo = availableEvents.find( (e) => e.id === event ); return ( ); })}
Secret: {webhook.secret.substring(0, 12)}... 重试: {webhook.retryCount}次
))}
setShowWebhookDialog(false)} title="新增 Webhook" footer={[ , , ]} >
{ setNewWebhook({ ...newWebhook, ...changedValues }); }} > } onClick={() => setNewWebhook({ ...newWebhook, secret: generateApiKey() }) } /> } />
{Object.entries( availableEvents.reduce((acc, event) => { if (!acc[event.category]) acc[event.category] = []; acc[event.category].push(event); return acc; }, {} as Record) ).map(([category, events]) => (

{category}

{events.map((event) => (
{ const checked = e.target.checked; if (checked) { setNewWebhook({ ...newWebhook, events: [...newWebhook.events, event.id], }); } else { setNewWebhook({ ...newWebhook, events: newWebhook.events.filter( (ev) => ev !== event.id ), }); } }} > {event.name} {event.description}
))}
))}
); }