fix(i18n): 回退到稳定的 32% 覆盖率状态 (tsc + Vite 构建通过)
批量转换脚本引入的语法错误已回退,保留稳定的 i18n 转换: - 翻译词典: 22 namespaces, 3600+ keys - 已接入: 145+ 文件 (Dashboard/Login/K8s 主页面/Monitor/System/Deploy) - 语言切换器在 Header 中可用 (🇨🇳/🇺🇸) - tsc 零错误, Vite 构建成功
This commit is contained in:
1 parent
ecec73989b
commit
72bfb0e12d
191 files changed
+5057
-7592
No files matched your search
@@ -32,7 +32,6 @@ import { toast } from 'sonner';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { zabbixDatasourceApi } from '@/api';
|
||||
import type { JsonData } from '@/types/common';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface ZabbixDS {
|
||||
id: number;
|
||||
@@ -60,7 +59,6 @@ const defaultForm = {
|
||||
};
|
||||
|
||||
export default function ZabbixDatasourceManager() {
|
||||
const { t } = useTranslation();
|
||||
const _confirm = useConfirm();
|
||||
const [sources, setSources] = useState<ZabbixDS[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -80,7 +78,7 @@ export default function ZabbixDatasourceManager() {
|
||||
const res: JsonData = await zabbixDatasourceApi.list();
|
||||
setSources(res?.data || res || []);
|
||||
} catch {
|
||||
toast.error(t('monitor.zabbixdatasourcemanager.s45f817'));
|
||||
toast.error('获取数据源列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -117,51 +115,51 @@ export default function ZabbixDatasourceManager() {
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!form.name.trim()) { toast.error(t('monitor.zabbixdatasourcemanager.s138957')); return; }
|
||||
if (!form.url.trim()) { toast.error(t('monitor.zabbixdatasourcemanager.s2ba385')); return; }
|
||||
if (!form.username.trim()) { toast.error(t('login.usernameRequired')); return; }
|
||||
if (!form.password.trim()) { toast.error(t('login.passwordRequired')); return; }
|
||||
if (!form.name.trim()) { toast.error('请输入数据源名称'); return; }
|
||||
if (!form.url.trim()) { toast.error('请输入 Zabbix API URL'); return; }
|
||||
if (!form.username.trim()) { toast.error('请输入用户名'); return; }
|
||||
if (!form.password.trim()) { toast.error('请输入密码'); return; }
|
||||
|
||||
try {
|
||||
if (editingId) {
|
||||
await zabbixDatasourceApi.update(editingId, form);
|
||||
toast.success(t('monitor.zabbixdatasourcemanager.s8dfdd2'));
|
||||
toast.success('数据源已更新');
|
||||
} else {
|
||||
await zabbixDatasourceApi.create(form);
|
||||
toast.success(t('monitor.zabbixdatasourcemanager.sa6def0'));
|
||||
toast.success('数据源已创建');
|
||||
}
|
||||
setDialogOpen(false);
|
||||
fetchList();
|
||||
} catch (err) {
|
||||
toast.error(err?.message || t('common.operationFailed'));
|
||||
toast.error(err?.message || '操作失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async (ds: ZabbixDS) => {
|
||||
const ok = await _confirm({
|
||||
title: t('monitor.deleteDatasource'),
|
||||
description: t('monitor.zabbixdatasourcemanager.sa2b79a', { ds.name: ds.name }),
|
||||
title: '删除数据源',
|
||||
description: `确定删除「${ds.name}」?`,
|
||||
variant: 'destructive',
|
||||
});
|
||||
if (!ok) return;
|
||||
try {
|
||||
await zabbixDatasourceApi.delete(ds.id);
|
||||
toast.success(t('alert.deleted'));
|
||||
toast.success('已删除');
|
||||
fetchList();
|
||||
} catch { toast.error(t('common.deleteFailed')); }
|
||||
} catch { toast.error('删除失败'); }
|
||||
};
|
||||
|
||||
const handleSetDefault = async (ds: ZabbixDS) => {
|
||||
try {
|
||||
await zabbixDatasourceApi.setDefault(ds.id);
|
||||
toast.success(t('monitor.zabbixdatasourcemanager.sf0f959', { ds.name: ds.name }));
|
||||
toast.success(`已将「${ds.name}」设为默认`);
|
||||
fetchList();
|
||||
} catch { toast.error(t('monitor.zabbixdatasourcemanager.s9f9603')); }
|
||||
} catch { toast.error('设置失败'); }
|
||||
};
|
||||
|
||||
const handleTest = async () => {
|
||||
if (!form.url.trim() || !form.username.trim()) {
|
||||
toast.error(t('monitor.zabbixdatasourcemanager.s1d3562'));
|
||||
toast.error('请填写 URL 和用户名');
|
||||
return;
|
||||
}
|
||||
setTesting(true);
|
||||
@@ -175,7 +173,7 @@ export default function ZabbixDatasourceManager() {
|
||||
const data = res?.data || res;
|
||||
setTestResult(data);
|
||||
} catch (err) {
|
||||
setTestResult({ success: false, message: err?.message || t('monitor.zabbixdatasourcemanager.s9710d9') });
|
||||
setTestResult({ success: false, message: err?.message || '测试失败' });
|
||||
} finally {
|
||||
setTesting(false);
|
||||
}
|
||||
@@ -201,7 +199,7 @@ export default function ZabbixDatasourceManager() {
|
||||
/>
|
||||
Zabbix 数据源
|
||||
</h2>
|
||||
<p className="text-xs text-[var(--dg-text-muted)]">{t('monitor.zabbixdatasourcemanager.s79e929')}</p>
|
||||
<p className="text-xs text-[var(--dg-text-muted)]">配置 Zabbix API 连接,获取主机监控数据</p>
|
||||
</div>
|
||||
<Button onClick={openCreate} size="sm">
|
||||
<Plus className="w-4 h-4 mr-1" />添加
|
||||
@@ -212,7 +210,7 @@ export default function ZabbixDatasourceManager() {
|
||||
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
|
||||
<CardContent className="py-12 text-center text-[var(--dg-text-muted)]">
|
||||
<Database className="w-12 h-12 mx-auto mb-3 opacity-30" />
|
||||
<p className="text-sm">{t('monitor.zabbixdatasourcemanager.sc9c9bd')}</p>
|
||||
<p className="text-sm">暂无 Zabbix 数据源</p>
|
||||
<Button size="sm" className="mt-4" onClick={openCreate}>
|
||||
<Plus className="w-4 h-4 mr-1" />添加数据源
|
||||
</Button>
|
||||
@@ -228,15 +226,15 @@ export default function ZabbixDatasourceManager() {
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<div className={`w-2 h-2 rounded-full ${ds.status === 1 ? 'bg-emerald-400' : 'bg-[var(--dg-bg-active)]'}`} />
|
||||
<span className="font-medium text-[var(--dg-text-primary)]">{ds.name}</span>
|
||||
{ds.is_default && <Badge className="bg-amber-500/20 dg-text-yellow text-[10px]"><Star className="w-3 h-3 mr-0.5" />{t('approval.status.default')}</Badge>}
|
||||
{ds.is_default && <Badge className="bg-amber-500/20 dg-text-yellow text-[10px]"><Star className="w-3 h-3 mr-0.5" />默认</Badge>}
|
||||
{ds.status === 1
|
||||
? <Badge className="bg-emerald-500/20 dg-text-green text-[10px]">{t('common.enable')}</Badge>
|
||||
: <Badge className="bg-[var(--dg-bg-active)]/20 dg-text-secondary text-[10px]">{t('common.disable')}</Badge>}
|
||||
? <Badge className="bg-emerald-500/20 dg-text-green text-[10px]">启用</Badge>
|
||||
: <Badge className="bg-[var(--dg-bg-active)]/20 dg-text-secondary text-[10px]">禁用</Badge>}
|
||||
</div>
|
||||
<div className="text-xs text-[var(--dg-text-muted)] space-x-3">
|
||||
<code className="text-orange-300">{ds.url}</code>
|
||||
<span>用户: {ds.username}</span>
|
||||
{ds.direct_db && <Badge variant="outline" className="text-[10px]">{t('monitor.zabbixdatasourcemanager.s85260a')}</Badge>}
|
||||
{ds.direct_db && <Badge variant="outline" className="text-[10px]">直连DB</Badge>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -265,7 +263,7 @@ export default function ZabbixDatasourceManager() {
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Database className="h-5 w-5 dg-text-orange" />
|
||||
{editingId ? t('monitor.zabbixdatasourcemanager.sc1c87e') : t('monitor.zabbixdatasourcemanager.sa77d38')}
|
||||
{editingId ? '编辑 Zabbix 数据源' : '新建 Zabbix 数据源'}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
配置 Zabbix API 连接,用于主机监控与告警数据获取
|
||||
@@ -276,14 +274,14 @@ export default function ZabbixDatasourceManager() {
|
||||
{/* Name + Default */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">{t('deploy.form.nameStar')}</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" placeholder=t('monitor.zabbixdatasourcemanager.s9f1e6a')
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">名称 *</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" placeholder="如:生产 Zabbix"
|
||||
value={form.name} onChange={e => updateForm('name', e.target.value)} />
|
||||
</div>
|
||||
<div className="flex items-end pb-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch checked={form.is_default} onCheckedChange={v => updateForm('is_default', v)} />
|
||||
<Label className="text-xs cursor-pointer">{t('aiops.llmSetDefault')}</Label>
|
||||
<Label className="text-xs cursor-pointer">设为默认</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -307,15 +305,15 @@ export default function ZabbixDatasourceManager() {
|
||||
onClick={() => setShowAuth(!showAuth)}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Shield className="w-4 h-4" />
|
||||
<span>{t('monitor.zabbixdatasourcemanager.sb47858')}</span>
|
||||
<span>Zabbix API 认证</span>
|
||||
</div>
|
||||
{showAuth ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
|
||||
</button>
|
||||
{showAuth && (
|
||||
<div className="px-3 pb-3 space-y-3">
|
||||
<Input className="h-9 text-sm bg-[var(--dg-bg-primary)]" placeholder=t('monitor.zabbixdatasourcemanager.s04c3dd')
|
||||
<Input className="h-9 text-sm bg-[var(--dg-bg-primary)]" placeholder="用户名 *"
|
||||
value={form.username} onChange={e => updateForm('username', e.target.value)} />
|
||||
<Input className="h-9 text-sm bg-[var(--dg-bg-primary)]" type="password" placeholder=t('monitor.zabbixdatasourcemanager.s3140c0')
|
||||
<Input className="h-9 text-sm bg-[var(--dg-bg-primary)]" type="password" placeholder="密码 *"
|
||||
value={form.password} onChange={e => updateForm('password', e.target.value)} />
|
||||
</div>
|
||||
)}
|
||||
@@ -327,7 +325,7 @@ export default function ZabbixDatasourceManager() {
|
||||
onClick={() => setShowTrends(!showTrends)}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="w-4 h-4" />
|
||||
<span>{t('monitor.zabbixdatasourcemanager.s05ef18')}</span>
|
||||
<span>Trends 设置</span>
|
||||
</div>
|
||||
{showTrends ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
|
||||
</button>
|
||||
@@ -335,24 +333,24 @@ export default function ZabbixDatasourceManager() {
|
||||
<div className="px-3 pb-3 space-y-3">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">{t('monitor.zabbixdatasourcemanager.sebfa4e')}</Label>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">After (天)</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" type="number" min={0}
|
||||
value={form.trends_after} onChange={e => updateForm('trends_after', parseInt(e.target.value) || 0)} />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">{t('monitor.zabbixdatasourcemanager.s7fe44f')}</Label>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">Range (秒)</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" type="number" min={0}
|
||||
value={form.trends_range} onChange={e => updateForm('trends_range', parseInt(e.target.value) || 0)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">{t('monitor.zabbixdatasourcemanager.sbf9a86')}</Label>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">Cache TTL (秒)</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" type="number" min={0}
|
||||
value={form.trends_cache_ttl} onChange={e => updateForm('trends_cache_ttl', parseInt(e.target.value) || 3600)} />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">{t('monitor.zabbixdatasourcemanager.s21f982')}</Label>
|
||||
<Label className="text-xs text-[var(--dg-text-secondary)]">Timeout (秒)</Label>
|
||||
<Input className="mt-1 h-9 text-sm bg-[var(--dg-bg-primary)]" type="number" min={1}
|
||||
value={form.trends_timeout} onChange={e => updateForm('trends_timeout', parseInt(e.target.value) || 30)} />
|
||||
</div>
|
||||
@@ -367,7 +365,7 @@ export default function ZabbixDatasourceManager() {
|
||||
onClick={() => setShowOther(!showOther)}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Settings className="w-4 h-4" />
|
||||
<span>{t('monitor.zabbixdatasourcemanager.sdda36e')}</span>
|
||||
<span>其他设置</span>
|
||||
</div>
|
||||
{showOther ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
|
||||
</button>
|
||||
@@ -378,11 +376,11 @@ export default function ZabbixDatasourceManager() {
|
||||
<Switch checked={form.direct_db} onCheckedChange={v => updateForm('direct_db', v)} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs">{t('monitor.zabbixdatasourcemanager.s413ec7')}</Label>
|
||||
<Label className="text-xs">只读用户禁用确认</Label>
|
||||
<Switch checked={form.disable_acknowledges} onCheckedChange={v => updateForm('disable_acknowledges', v)} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs">{t('monitor.zabbixdatasourcemanager.s6d4d6f')}</Label>
|
||||
<Label className="text-xs">禁用数据对齐</Label>
|
||||
<Switch checked={form.disable_data_alignment} onCheckedChange={v => updateForm('disable_data_alignment', v)} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -406,8 +404,8 @@ export default function ZabbixDatasourceManager() {
|
||||
测试连接
|
||||
</Button>
|
||||
<div className="flex-1" />
|
||||
<Button variant="ghost" size="sm" onClick={() => setDialogOpen(false)}>{t('common.cancel')}</Button>
|
||||
<Button size="sm" onClick={handleSave}>{t('common.save')}</Button>
|
||||
<Button variant="ghost" size="sm" onClick={() => setDialogOpen(false)}>取消</Button>
|
||||
<Button size="sm" onClick={handleSave}>保存</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
Reference in new issue
Block a user