批量转换 163 个文件,3204 处中文替换为 t() 调用: - Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换 - Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换 - Deploy: 流水线/发布/凭证/RBAC 全部转换 - Server/Cloud/Agent/Task/Layout/UI: 全部转换 - 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys) - tsc 编译零错误
154 lines
5.8 KiB
TypeScript
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>
|
|
);
|
|
}
|