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:
attacker committed 2026-07-03 02:02:29 +08:00
1 parent ecec73989b
commit 72bfb0e12d
191 files changed
+5057 -7592

No files matched your search

+25 -27
View File
@@ -23,10 +23,8 @@ import { PageShell } from '@/components/layout/PageShell';
import { ContentPanel } from '@/components/layout/ContentPanel';
import { PageEmpty } from '@/components/layout/PageEmpty';
import type { JsonData } from '@/types/common';
import { useTranslation } from 'react-i18next';
export function ScriptManager() {
const { t } = useTranslation();
const _confirm = useConfirm();
const { hasAnyPermission, isAdmin } = usePermission();
const canWrite = isAdmin || hasAnyPermission(['auto:script', 'auto:cron', 'auto:ansible']);
@@ -53,7 +51,7 @@ export function ScriptManager() {
const items = (res as JsonData)?.list || [];
setScripts(items.map(mapScript));
} catch {
toast.error(t('task.scriptmanager.s0fa260'));
toast.error('获取脚本列表失败');
} finally {
setLoading(false);
}
@@ -114,7 +112,7 @@ export function ScriptManager() {
const handleSave = async () => {
if (!formData.name.trim() || !formData.content.trim()) {
toast.error(t('task.scriptmanager.s54c121'));
toast.error('请填写名称和脚本内容');
return;
}
const payload = {
@@ -128,49 +126,49 @@ export function ScriptManager() {
try {
if (editingId !== null) {
await scriptApi.updateScript(editingId, payload);
toast.success(t('task.scriptmanager.sdb91e3'));
toast.success('脚本更新成功');
} else {
await scriptApi.createScript(payload);
toast.success(t('task.scriptmanager.s4aac59'));
toast.success('脚本创建成功');
}
setEditorOpen(false);
fetchScripts();
} catch (e) {
toast.error(e instanceof Error ? e.message : (editingId !== null ? t('alert.updateFailed') : t('monitor.quickSetupFailed')));
toast.error(e instanceof Error ? e.message : (editingId !== null ? '更新失败' : '创建失败'));
}
};
const handleClone = async (sc: Script) => {
try {
await scriptApi.createScript({
name: t('task.scriptmanager.s624267', { sc.name: sc.name }),
name: `${sc.name} (副本)`,
code: genCode(),
description: sc.description,
type: sc.type,
content: sc.content,
timeout: sc.timeout,
});
toast.success(t('common.copySuccess'));
toast.success('复制成功');
fetchScripts();
} catch (e) {
toast.error(e instanceof Error ? e.message : t('common.copyFailed'));
toast.error(e instanceof Error ? e.message : '复制失败');
}
};
const handleDelete = async (sc: Script) => {
const ok = await _confirm({
title: t('automation.deleteScript'),
description: t('task.scriptmanager.sf18242', { sc.name: sc.name }),
confirmText: t('common.delete'),
title: '删除脚本',
description: `确定删除「${sc.name}」吗?此操作不可恢复。`,
confirmText: '删除',
variant: 'destructive',
});
if (!ok) return;
try {
await scriptApi.deleteScript(sc.id);
toast.success(t('common.deleteSuccess'));
toast.success('删除成功');
fetchScripts();
} catch (e) {
toast.error(e instanceof Error ? e.message : t('common.deleteFailed'));
toast.error(e instanceof Error ? e.message : '删除失败');
}
};
@@ -195,19 +193,19 @@ export function ScriptManager() {
const handleBatchDelete = async () => {
if (selectedIds.length === 0) return;
const ok = await _confirm({
title: t('task.scriptmanager.sd730a0'),
description: t('task.scriptmanager.sc53e36', { selectedIds.length: selectedIds.length }),
confirmText: t('common.batchDelete'),
title: '批量删除脚本',
description: `确定删除选中的 ${selectedIds.length} 个脚本吗?此操作不可恢复。`,
confirmText: '批量删除',
variant: 'destructive',
});
if (!ok) return;
try {
await scriptApi.batchDelete(selectedIds);
toast.success(t('task.scriptmanager.s01215a', { selectedIds.length: selectedIds.length }));
toast.success(`已删除 ${selectedIds.length} 个脚本`);
setSelectedIds([]);
fetchScripts();
} catch (e) {
toast.error(e instanceof Error ? e.message : t('cloud.batchDeleteFailed'));
toast.error(e instanceof Error ? e.message : '批量删除失败');
}
};
@@ -217,7 +215,7 @@ export function ScriptManager() {
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 dg-text-muted" />
<Input
placeholder=t('deploy.label.searchPlaceholder')
placeholder="搜索名称、描述..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 dg-input"
@@ -225,10 +223,10 @@ export function ScriptManager() {
</div>
<Select value={typeFilter} onValueChange={setTypeFilter}>
<SelectTrigger className="w-[140px] dg-input">
<SelectValue placeholder=t('common.type') />
<SelectValue placeholder="类型" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">{t('deploy.label.allType')}</SelectItem>
<SelectItem value="all">全部类型</SelectItem>
{scriptTypes.map(t => (
<SelectItem key={t.value} value={t.value}>{t.label}</SelectItem>
))}
@@ -242,8 +240,8 @@ export function ScriptManager() {
<>
<PageShell
variant="list"
title=t('menu.scripts')
subtitle=t('task.scriptmanager.sed1dec')
title="脚本库"
subtitle="脚本编辑与管理"
icon={<FileCode className="h-5 w-5" />}
toolbar={toolbar}
loading={loading}
@@ -296,8 +294,8 @@ export function ScriptManager() {
{filteredScripts.length === 0 ? (
<PageEmpty
title={scripts.length === 0 ? t('automation.noScript') : t('task.scriptmanager.s83533d')}
description={scripts.length === 0 ? t('task.scriptmanager.sc31b6b') : undefined}
title={scripts.length === 0 ? '暂无脚本' : '未匹配到符合条件的脚本'}
description={scripts.length === 0 ? '点击「新建脚本」创建第一个' : undefined}
action={scripts.length === 0 && canWrite ? (
<Button className="dg-btn-primary" onClick={openCreate}>
<Plus className="w-4 h-4 mr-2" />