Files
aiops/frontend/src/components/monitor/alert-center/ContactDialog.tsx
T
attacker ecec73989b feat(i18n): 剩余模块全量国际化 — 51% 覆盖率 (231 文件接入 t())
批量转换 163 个文件,3204 处中文替换为 t() 调用:
- Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换
- Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换
- Deploy: 流水线/发布/凭证/RBAC 全部转换
- Server/Cloud/Agent/Task/Layout/UI: 全部转换
- 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys)
- tsc 编译零错误
2026-07-03 01:51:57 +08:00

154 lines
5.8 KiB
TypeScript

// 报警联系人创建/编辑对话框 — 渠道类型下拉 + webhook URL // Logan.Li
import React, { useState, useEffect } from 'react';
import {
Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, 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 { toast } from 'sonner';
import { alertApi } from '@/api';
import type { Contact } from './alert-center-helpers';
import { useTranslation } from 'react-i18next';
import i18n from '@/i18n';
const CHANNEL_OPTIONS = [
{ value: 'feishu', label: i18n.t('monitor.contactdialog.s7714e5'), placeholder: 'https://open.feishu.cn/open-apis/bot/v2/hook/...' },
{ value: 'dingtalk', label: i18n.t('monitor.contactDingtalk'), placeholder: 'https://oapi.dingtalk.com/robot/send?access_token=...' },
{ value: 'wechat', label: i18n.t('monitor.contactWechat'), placeholder: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...' },
{ value: 'webhook', label: i18n.t('monitor.contactdialog.s3ccb7a'), placeholder: 'https://your-webhook-url...' },
];
export function ContactDialog({
open,
onOpenChange,
editingContact,
onSaved,
}: {
open: boolean;
onOpenChange: (open: boolean) => void;
editingContact: Contact | null;
onSaved: () => void;
}) {
const { t } = useTranslation();
const [channelType, setChannelType] = useState('feishu');
const [form, setForm] = useState({ name: '', phone: '', email: '', webhook_url: '' });
const [saving, setSaving] = useState(false);
useEffect(() => {
if (open) {
if (editingContact) {
setChannelType(editingContact.channel_type || 'feishu');
setForm({
name: editingContact.name || '',
phone: editingContact.phone || '',
email: editingContact.email || '',
webhook_url: editingContact.webhook_url || '',
});
} else {
setChannelType('feishu');
setForm({ name: '', phone: '', email: '', webhook_url: '' });
}
}
}, [open, editingContact]);
const handleSave = async () => {
if (!form.name.trim() || !form.webhook_url.trim()) return;
setSaving(true);
try {
const payload = {
name: form.name.trim(),
phone: form.phone.trim() || undefined,
email: form.email.trim() || undefined,
channel_type: channelType,
webhook_url: form.webhook_url.trim(),
};
if (editingContact) {
await alertApi.updateContact(editingContact.id, payload);
toast.success(t('monitor.contactdialog.sa0fe38'));
} else {
await alertApi.createContact(payload);
toast.success(t('monitor.contactdialog.s50ee3f'));
}
onOpenChange(false);
onSaved();
} catch {
toast.error(t('common.saveFailed'));
} finally {
setSaving(false);
}
};
const selectedChannel = CHANNEL_OPTIONS.find(c => c.value === channelType);
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>{editingContact ? t('monitor.contactdialog.sbc3c27') : t('monitor.contactdialog.sc044d1')}</DialogTitle>
<DialogDescription>{t('monitor.contactdialog.s04b40a')}</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
<Label>{t('monitor.contactdialog.s7c46af')}</Label>
<Input
value={form.name}
onChange={(e) => setForm({ ...form, name: e.target.value })}
placeholder=t('monitor.contactdialog.s6b9850')
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="space-y-2">
<Label>{t('system.userPhone')}</Label>
<Input
value={form.phone}
onChange={(e) => setForm({ ...form, phone: e.target.value })}
placeholder="13800138000"
/>
</div>
<div className="space-y-2">
<Label>{t('system.userEmail')}</Label>
<Input
value={form.email}
onChange={(e) => setForm({ ...form, email: e.target.value })}
placeholder="zhangsan@example.com"
/>
</div>
</div>
<div className="space-y-2">
<Label>{t('monitor.contactdialog.sc84995')}</Label>
<Select value={channelType} onValueChange={setChannelType}>
<SelectTrigger>
<SelectValue placeholder=t('monitor.contactdialog.seb8768') />
</SelectTrigger>
<SelectContent>
{CHANNEL_OPTIONS.map(opt => (
<SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Webhook URL *</Label>
<Input
value={form.webhook_url}
onChange={(e) => setForm({ ...form, webhook_url: e.target.value })}
placeholder={selectedChannel?.placeholder || 'https://...'}
className="font-mono text-xs"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>{t('common.cancel')}</Button>
<Button onClick={handleSave} disabled={!form.name.trim() || !form.webhook_url.trim() || saving}>
{saving ? i18n.t('k8s.topology.saving') : editingContact ? i18n.t('cloud.saveChanges') : i18n.t('alert.addContact')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}