refactor(i18n): U37 全量 JSX 文本节点硬编码中文清零 — 65 文件 151 处→0, 新增 common.* 98 翻译键, zh/en 对齐, tsc -b=0, npm build✓ (17.96s), ESLint=0/43/any=0, go build=0, 17/17 测试通过
This commit is contained in:
1 parent
e274ba7b9b
commit
7c80e35411
68 files changed
+11819
-11622
No files matched your search
@@ -92,7 +92,7 @@ export default function CapacityPage() {
|
||||
<Select value={selectedNs} onValueChange={setSelectedNs}>
|
||||
<SelectTrigger className="w-32 h-9 dg-input"><SelectValue placeholder={i18n.t('k8s.capacity.namespace')} /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">所有命名空间</SelectItem>
|
||||
<SelectItem value="all">{i18n.t("common.allNamespaces")}</SelectItem>
|
||||
{namespaces.map(n => <SelectItem key={n} value={n}>{n}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
@@ -111,9 +111,9 @@ export default function CapacityPage() {
|
||||
<Table>
|
||||
<TableHeader><TableRow className="border-[var(--dg-border)] hover:bg-transparent">
|
||||
<TableHead className="dg-text-secondary">Deployment</TableHead>
|
||||
<TableHead className="dg-text-secondary">命名空间</TableHead>
|
||||
<TableHead className="dg-text-secondary">副本</TableHead>
|
||||
<TableHead className="dg-text-secondary">容器</TableHead>
|
||||
<TableHead className="dg-text-secondary">{i18n.t("common.namespaceLabel")}</TableHead>
|
||||
<TableHead className="dg-text-secondary">{i18n.t("common.replicasLabel")}</TableHead>
|
||||
<TableHead className="dg-text-secondary">{i18n.t("common.containerLabel")}</TableHead>
|
||||
<TableHead className="dg-text-secondary"><Cpu className="h-3 w-3 inline mr-1" />CPU Req</TableHead>
|
||||
<TableHead className="dg-text-secondary"><Cpu className="h-3 w-3 inline mr-1" />CPU Lim</TableHead>
|
||||
<TableHead className="dg-text-secondary"><HardDrive className="h-3 w-3 inline mr-1" />Mem Req</TableHead>
|
||||
|
||||
@@ -107,7 +107,7 @@ export default function ClusterOverviewPage() {
|
||||
{/* 节点列表 // Logan.Li */}
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-[var(--dg-text-primary)] mb-3 flex items-center gap-2">
|
||||
<Cpu className="h-4 w-4 text-[var(--dg-blue)]" />节点列表
|
||||
<Cpu className="h-4 w-4 text-[var(--dg-blue)]" />{i18n.t("common.nodeList")}
|
||||
</h2>
|
||||
<ContentPanel>
|
||||
<Table>
|
||||
@@ -185,7 +185,7 @@ export default function ClusterOverviewPage() {
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-lg font-semibold text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Boxes className="h-4 w-4 text-[var(--dg-green)]" />命名空间
|
||||
<Boxes className="h-4 w-4 text-[var(--dg-green)]" />{i18n.t("common.namespaceLabel")}
|
||||
</h2>
|
||||
<Link to={`/kubernetes/${clusterCode}/namespaces`} className="text-sm text-[var(--dg-blue)] hover:text-[var(--dg-blue)] transition-colors flex items-center gap-1">
|
||||
管理全部 <ChevronRight className="h-3 w-3" />
|
||||
|
||||
@@ -138,7 +138,7 @@ export function DeploymentDetail({ clusterCode, namespace, deploymentName, onBac
|
||||
<Card className="dg-card">
|
||||
<CardContent className="p-12 text-center">
|
||||
<XCircle className="h-8 w-8 mx-auto dg-text-red" />
|
||||
<p className="dg-text-secondary mt-3">未找到 Deployment: {deploymentName}</p>
|
||||
<p className="dg-text-secondary mt-3">{i18n.t('common.notFoundDeploy')}: {deploymentName}</p>
|
||||
<Button variant="outline" className="mt-4" onClick={onBack}> {i18n.t('common.back')} </Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -179,7 +179,7 @@ export function DeploymentDetail({ clusterCode, namespace, deploymentName, onBac
|
||||
Pod 列表 ({pods.length})
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="logs" className="data-[state=active]:bg-[var(--dg-bg-active)]">
|
||||
<FileText className="h-4 w-4 mr-1" />日志
|
||||
<FileText className="h-4 w-4 mr-1" />{i18n.t("common.podLogs")}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="hpa" className="data-[state=active]:bg-[var(--dg-bg-active)]">
|
||||
<Gauge className="h-4 w-4 mr-1" />HPA ({hpas.length})
|
||||
|
||||
@@ -149,7 +149,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
|
||||
className="dg-text-red hover:dg-text-red ml-1"><Trash2 className="h-3 w-3" /></button>
|
||||
</div>
|
||||
))}
|
||||
{imagePullSecrets.length === 0 && <span className="text-[11px] dg-text-muted">无</span>}
|
||||
{imagePullSecrets.length === 0 && <span className="text-[11px] dg-text-muted">{i18n.t("common.none")}</span>}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Input placeholder={i18n.t('k8s.editContainers.secretPlaceholder')} className="dg-input text-xs h-8"
|
||||
@@ -161,7 +161,7 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
|
||||
}} />
|
||||
<Button size="sm" variant="outline" className="h-8 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
|
||||
onClick={() => setImagePullSecrets(prev => [...prev, ''])}>
|
||||
<Plus className="h-3 w-3 mr-1" />新增
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.add")}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -195,8 +195,8 @@ export function DeploymentEditContainers({ clusterCode, namespace, deploymentNam
|
||||
{/* 保存栏 */}
|
||||
<div className="sticky bottom-0 bg-[var(--dg-bg-primary)]/80 backdrop-blur border-t border-[var(--dg-border)] p-3 flex items-center justify-between">
|
||||
<div className="text-[11px] dg-text-muted">
|
||||
共 <span className="text-[var(--dg-text-secondary)] font-semibold">{initContainers.length}</span> 个初始化容器 +
|
||||
<span className="text-[var(--dg-text-secondary)] font-semibold ml-1">{containers.length}</span> 个工作容器
|
||||
{i18n.t("common.total")}: <span className="text-[var(--dg-text-secondary)] font-semibold">{initContainers.length}</span> {i18n.t("common.totalContainers")} +
|
||||
<span className="text-[var(--dg-text-secondary)] font-semibold ml-1">{containers.length}</span> {i18n.t("common.workContainers")}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}> {i18n.t('rbac.jobRole.cancel')} </Button>
|
||||
|
||||
@@ -266,7 +266,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
)}
|
||||
</div>
|
||||
<Button size="sm" variant="ghost" className="h-6 ml-auto text-xs dg-text-secondary" onClick={load}>
|
||||
<RefreshCw className="h-3 w-3 mr-1" />刷新
|
||||
<RefreshCw className="h-3 w-3 mr-1" />{i18n.t("common.refresh")}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -286,7 +286,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
setSvcForm({ name: `${deploymentName}-svc`, type: 'ClusterIP', ports: [{ name: 'http', port: '8080', targetPort: '8080', protocol: 'TCP', nodePort: '' }] });
|
||||
setShowCreate('service');
|
||||
}}>
|
||||
<Plus className="h-3 w-3 mr-1" />创建 Service
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.createService")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs dg-text-muted mt-1"> {i18n.t('kubernetes.deploymentEditService.selectorHint')} </p>
|
||||
@@ -338,7 +338,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
|
||||
setIngForm(s => ({ ...s, name: `${deploymentName}-ingress`, svcPort: String(matchedSvcs[0]?.ports[0]?.port || 80) }));
|
||||
setShowCreate('ingress');
|
||||
}}>
|
||||
<Plus className="h-3 w-3 mr-1" />创建 Ingress
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.createIngress")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs dg-text-muted mt-1">backend 指向关联 Service 的 Ingress 自动高亮</p>
|
||||
|
||||
@@ -202,7 +202,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
<p className="text-[11px] dg-text-muted mt-1"> {i18n.t('kubernetes.storage.volumeDesc')} </p>
|
||||
</div>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs shrink-0" onClick={addEntry}>
|
||||
<Plus className="h-3 w-3 mr-1" />添加数据卷
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.addVolume")}
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
@@ -285,7 +285,7 @@ export function DeploymentEditStorage({ clusterCode, namespace, deploymentName,
|
||||
将上述数据卷挂载到容器
|
||||
</p>
|
||||
<Button size="sm" variant="ghost" className="h-6 px-2 text-[11px] dg-text-secondary hover:text-[var(--dg-text-primary)]" onClick={() => addMount(i)}>
|
||||
<Plus className="h-3 w-3 mr-0.5" />添加挂载
|
||||
<Plus className="h-3 w-3 mr-0.5" />{i18n.t("common.addMount")}
|
||||
</Button>
|
||||
</div>
|
||||
{entry.mounts.map((mount, mi) => (
|
||||
|
||||
@@ -266,7 +266,7 @@ export default function EventsPage() {
|
||||
<ContentPanel
|
||||
toolbar={(
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<span className="text-sm dg-text-secondary">事件列表 ({displayEvents.length})</span>
|
||||
<span className="text-sm dg-text-secondary">{i18n.t('common.events')} ({displayEvents.length})</span>
|
||||
<Select value={filterType} onValueChange={setFilterType}>
|
||||
<SelectTrigger className="w-28 h-8 dg-input text-xs"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
|
||||
@@ -143,7 +143,7 @@ export default function NamespaceManagementPage() {
|
||||
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" className="dg-btn-primary">
|
||||
<Plus className="h-4 w-4 mr-1" />创建命名空间
|
||||
<Plus className="h-4 w-4 mr-1" />{i18n.t("common.createNamespace")}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
@@ -194,11 +194,11 @@ export default function NamespaceManagementPage() {
|
||||
<TableBody>
|
||||
{loading ? (
|
||||
<TableRow><TableCell colSpan={9} className="text-center text-[var(--dg-text-muted)] py-12">
|
||||
<Loader2 className="h-5 w-5 animate-spin mx-auto mb-2" />加载中...
|
||||
<Loader2 className="h-5 w-5 animate-spin mx-auto mb-2" />{i18n.t("common.loading")}
|
||||
</TableCell></TableRow>
|
||||
) : filtered.length === 0 ? (
|
||||
<TableRow><TableCell colSpan={9} className="text-center text-[var(--dg-text-muted)] py-12">
|
||||
<Boxes className="h-8 w-8 mx-auto mb-2 opacity-50" />暂无命名空间
|
||||
<Boxes className="h-8 w-8 mx-auto mb-2 opacity-50" />{i18n.t("common.noNamespace")}
|
||||
</TableCell></TableRow>
|
||||
) : (
|
||||
filtered.map((ns) => {
|
||||
@@ -226,7 +226,7 @@ export default function NamespaceManagementPage() {
|
||||
<TableCell className="text-center">
|
||||
{ns.has_resource_quota ? (
|
||||
<Badge className="bg-[var(--dg-orange)]/20 text-[var(--dg-orange)]" title={JSON.stringify(ns.resource_quotas?.[0]?.status)}>
|
||||
<Shield className="h-3 w-3 mr-1" />有
|
||||
<Shield className="h-3 w-3 mr-1" />{i18n.t("common.hasLabel")}
|
||||
</Badge>
|
||||
) : (
|
||||
<span className="text-xs text-[var(--dg-text-muted)]">-</span>
|
||||
@@ -273,13 +273,13 @@ export default function NamespaceManagementPage() {
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-[var(--dg-red)] flex items-center gap-2">
|
||||
<AlertTriangle className="h-5 w-5" />删除命名空间
|
||||
<AlertTriangle className="h-5 w-5" />{i18n.t("common.deleteNamespace")}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="space-y-3 py-4">
|
||||
<div className="bg-[var(--dg-red)]/10 border border-[var(--dg-red)]/30 rounded-lg p-3">
|
||||
<p className="text-sm text-[var(--dg-red)]">
|
||||
⚠️ 即将删除命名空间 <span className="font-bold">{deleteTarget}</span> 及其中所有资源。
|
||||
{i18n.t('common.deleteNamespaceWarn')} <span className="font-bold">{deleteTarget}</span> {i18n.t('common.allResources')}
|
||||
</p>
|
||||
<p className="text-xs text-[var(--dg-red)]/70 mt-1">
|
||||
此操作不可逆,所有 Deployment/Pod/Service/ConfigMap 等资源将被永久删除。
|
||||
|
||||
@@ -167,7 +167,7 @@ export default function NamespaceResourcePage() {
|
||||
}
|
||||
};
|
||||
|
||||
if (!config) return <div className="text-[var(--dg-text-secondary)] p-8 text-center">未知资源类型: {type}</div>;
|
||||
if (!config) return <div className="text-[var(--dg-text-secondary)] p-8 text-center">{i18n.t('common.unknownResource', { type })}</div>;
|
||||
|
||||
const searchToolbar = (
|
||||
<div className="relative w-56 flex-1 min-w-[200px] max-w-xs">
|
||||
@@ -214,16 +214,16 @@ export default function NamespaceResourcePage() {
|
||||
)}
|
||||
{EXPORT_YAML_TYPES.includes(type) && (
|
||||
<Button variant="outline" size="sm" className="dg-btn-secondary text-xs" onClick={handleExportYaml} title={i18n.t('k8s.nsResourcePage.exportYaml')}>
|
||||
<Download className="h-3 w-3 mr-1" />导出YAML
|
||||
<Download className="h-3 w-3 mr-1" />{i18n.t("common.exportYaml")}
|
||||
</Button>
|
||||
)}
|
||||
{(VISUAL_RESOURCE_TYPES.includes(type) || DEPLOYMENT_LIST_TYPES.includes(type)) && (
|
||||
<>
|
||||
<Button variant="outline" size="sm" className="dg-btn-secondary text-xs" onClick={() => setShowYamlImport(true)}>
|
||||
<Upload className="h-3 w-3 mr-1" />导入
|
||||
<Upload className="h-3 w-3 mr-1" />{i18n.t("common.import")}
|
||||
</Button>
|
||||
<Button size="sm" className="dg-btn-primary text-xs" onClick={handleCreate}>
|
||||
<Plus className="h-3 w-3 mr-1" />新建
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.buildNew")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
@@ -267,7 +267,7 @@ export default function NamespaceResourcePage() {
|
||||
{loading ? (
|
||||
<TableRow><TableCell colSpan={config.columns.length} className="text-center text-[var(--dg-text-muted)] py-12"><Loader2 className="h-5 w-5 animate-spin mx-auto mb-2" /> {i18n.t('monitor.logPanel.logResults.loading')} </TableCell></TableRow>
|
||||
) : filtered.length === 0 ? (
|
||||
<TableRow><TableCell colSpan={config.columns.length} className="text-center text-[var(--dg-text-muted)] py-12"><config.icon className="h-8 w-8 mx-auto mb-2 opacity-50" />暂无 {config.title}</TableCell></TableRow>
|
||||
<TableRow><TableCell colSpan={config.columns.length} className="text-center text-[var(--dg-text-muted)] py-12"><config.icon className="h-8 w-8 mx-auto mb-2 opacity-50" />{i18n.t('common.noData')} {config.title}</TableCell></TableRow>
|
||||
) : (
|
||||
filtered.map((item) => config.renderRow(item, { clusterCode: clusterCode || '', namespace: namespace || '', onDetail: handleDetail, onYaml: handleYaml, onEdit: handleEdit, onTerminal: (p: any) => setTerminalPod(p), onFileBrowser: (p: any) => setFileBrowserPod(p), onDeletePod: handleDeletePod, onPodDetail: (p: any) => setPodDetail(p) }))
|
||||
)}
|
||||
|
||||
@@ -172,7 +172,7 @@ export function PodFileBrowser({
|
||||
<div className="flex items-center justify-between p-3 border-b border-[var(--dg-border)] shrink-0 gap-3">
|
||||
<div className="flex items-center gap-2 min-w-0 flex-1">
|
||||
<HardDrive className="h-4 w-4 shrink-0 dg-text-yellow" />
|
||||
<span className="text-sm font-semibold text-[var(--dg-text-primary)] truncate" title={podName}>文件: {podName}</span>
|
||||
<span className="text-sm font-semibold text-[var(--dg-text-primary)] truncate" title={podName}>{i18n.t("common.fileLabel")}: {podName}</span>
|
||||
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary text-[10px] shrink-0">{namespace}</Badge>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -125,8 +125,8 @@ export default function PodMetricsPage() {
|
||||
<Table>
|
||||
<TableHeader><TableRow className="border-[var(--dg-border)] hover:bg-transparent">
|
||||
<TableHead className="dg-text-secondary">Pod</TableHead>
|
||||
<TableHead className="dg-text-secondary">命名空间</TableHead>
|
||||
<TableHead className="dg-text-secondary">容器</TableHead>
|
||||
<TableHead className="dg-text-secondary">{i18n.t("common.namespaceLabel")}</TableHead>
|
||||
<TableHead className="dg-text-secondary">{i18n.t("common.containerLabel")}</TableHead>
|
||||
<TableHead className="dg-text-secondary"><Cpu className="h-3 w-3 inline mr-1" />CPU</TableHead>
|
||||
<TableHead className="dg-text-secondary"><HardDrive className="h-3 w-3 inline mr-1" />Memory</TableHead>
|
||||
</TableRow></TableHeader>
|
||||
|
||||
@@ -153,12 +153,12 @@ export default function WorkloadViewPage() {
|
||||
actions={(
|
||||
<>
|
||||
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={() => navigate(-1)}>
|
||||
<ArrowLeft className="h-4 w-4 mr-1" />返回
|
||||
<ArrowLeft className="h-4 w-4 mr-1" />{i18n.t("common.back")}
|
||||
</Button>
|
||||
{modeTabs}
|
||||
{isSts && (
|
||||
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={() => { setScaleValue(replicas); setScaleModal(true); }}>
|
||||
<Boxes className="h-3.5 w-3.5 mr-1" />伸缩
|
||||
<Boxes className="h-3.5 w-3.5 mr-1" />{i18n.t("common.scale")}
|
||||
</Button>
|
||||
)}
|
||||
<Button variant="outline" size="sm" className="dg-btn-secondary" disabled={actionLoading} onClick={handleRestart}>
|
||||
@@ -225,7 +225,7 @@ export default function WorkloadViewPage() {
|
||||
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Database className="h-4 w-4 text-[var(--dg-cyan)]" />存储卷声明模板 (VolumeClaimTemplates)
|
||||
<Database className="h-4 w-4 text-[var(--dg-cyan)]" />{i18n.t("common.volumeClaimTemplates")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0">
|
||||
@@ -262,7 +262,7 @@ export default function WorkloadViewPage() {
|
||||
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Container className="h-4 w-4 text-[var(--dg-blue)]" />容器模板(Pod Template)
|
||||
<Container className="h-4 w-4 text-[var(--dg-blue)]" />{i18n.t("common.containerTemplate")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0">
|
||||
|
||||
@@ -57,34 +57,34 @@ export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCrea
|
||||
return (
|
||||
<>
|
||||
<Button variant="outline" size="sm" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]" onClick={() => setOpen(true)}>
|
||||
<Plus className="h-3.5 w-3.5 mr-1" />创建 HPA
|
||||
<Plus className="h-3.5 w-3.5 mr-1" />{i18n.t("common.createHpa")}
|
||||
</Button>
|
||||
{open && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4" onClick={() => setOpen(false)}>
|
||||
<div className="bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl w-[480px] max-w-[92vw] max-h-[85vh] flex flex-col" onClick={(e) => e.stopPropagation()}>
|
||||
<h2 className="text-lg font-bold text-[var(--dg-text-primary)] px-6 pt-6 pb-4 shrink-0">创建 HPA</h2>
|
||||
<h2 className="text-lg font-bold text-[var(--dg-text-primary)] px-6 pt-6 pb-4 shrink-0">{i18n.t("common.createHpaTitle")}</h2>
|
||||
<div className="flex-1 min-h-0 overflow-y-auto px-6 space-y-3">
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">名称</Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t("common.name")}</Label>
|
||||
<Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })}
|
||||
placeholder={`hpa-${deploymentName}`}
|
||||
className="dg-input mt-1" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">目标</Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t("common.target")}</Label>
|
||||
<p className="text-[var(--dg-text-secondary)] text-sm mt-1 bg-[var(--dg-bg-tertiary)] rounded px-3 py-2 truncate" title={`Deployment: ${deploymentName} · 命名空间: ${namespace}`}>
|
||||
Deployment: {deploymentName} · 命名空间: {namespace}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">最小副本数</Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t("common.minReplicas")}</Label>
|
||||
<Input type="number" value={form.minReplicas} min={1}
|
||||
onChange={(e) => setForm({ ...form, minReplicas: Number(e.target.value) })}
|
||||
className="dg-input mt-1" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">最大副本数</Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t("common.maxReplicas")}</Label>
|
||||
<Input type="number" value={form.maxReplicas} min={1}
|
||||
onChange={(e) => setForm({ ...form, maxReplicas: Number(e.target.value) })}
|
||||
className="dg-input mt-1" />
|
||||
@@ -98,7 +98,7 @@ export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCrea
|
||||
className="dg-input mt-1" />
|
||||
</div>
|
||||
<div>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t('k8s.misc.memory1')} <span className="dg-text-muted">可选</span></Label>
|
||||
<Label className="dg-text-secondary text-sm">{i18n.t('k8s.misc.memory1')} <span className="dg-text-muted">{i18n.t("common.optional")}</span></Label>
|
||||
<Input type="number" value={form.memPercent} min={0} max={100}
|
||||
onChange={(e) => setForm({ ...form, memPercent: Number(e.target.value) })}
|
||||
className="dg-input mt-1" />
|
||||
@@ -106,7 +106,7 @@ export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCrea
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end gap-2 px-6 py-4 border-t border-[var(--dg-border)] shrink-0">
|
||||
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={() => setOpen(false)}>取消</Button>
|
||||
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={() => setOpen(false)}>{i18n.t("common.cancel")}</Button>
|
||||
<Button className="bg-blue-600 hover:bg-blue-700" disabled={loading} onClick={handleCreate}>
|
||||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : i18n.t('common.create')}
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// HostSettingsCard.tsx — 主机设置 (Host Namespace) 卡片 (Q21 提取)
|
||||
// HostSettingsCard.tsx — {i18n.t("common.hostSettings")} 卡片 (Q21 提取)
|
||||
// hostNetwork / hostIPC / hostPID / shareProcessNamespace
|
||||
import { Network } from 'lucide-react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
interface HostSettingsCardProps {
|
||||
hostNetwork: boolean;
|
||||
@@ -24,7 +25,7 @@ export function HostSettingsCard({
|
||||
<Card className="dg-card">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Network className="h-4 w-4 dg-text-cyan" />主机设置 (Host Namespace)
|
||||
<Network className="h-4 w-4 dg-text-cyan" />{i18n.t("common.hostSettings")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 grid grid-cols-2 gap-3">
|
||||
|
||||
@@ -22,7 +22,7 @@ export function TolerationsCard({ tolerations, onAdd, onRemove, onUpdate }: Tole
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)]"> {i18n.t('kubernetes.deploymentEditAdvanced.tolerations')} </CardTitle>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
|
||||
onClick={onAdd}>
|
||||
<Plus className="h-3 w-3 mr-1" />添加
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.add")}
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
@@ -69,7 +69,7 @@ export function UpdateStrategyCard({
|
||||
<Card className="dg-card">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Clock className="h-4 w-4 dg-text-yellow" />历史版本 & 进度
|
||||
<Clock className="h-4 w-4 dg-text-yellow" />{i18n.t("common.historyVersion")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 grid grid-cols-2 gap-3">
|
||||
|
||||
@@ -19,7 +19,7 @@ export function IngressCreateForm({ ingForm, setIngForm, deploymentName, onCance
|
||||
return (
|
||||
<div className="mt-3 border border-purple-800/50 rounded-lg p-3 bg-purple-950/20 space-y-2">
|
||||
<div className="text-xs font-semibold text-purple-300 flex items-center gap-1.5">
|
||||
<Plus className="h-3 w-3" />创建新 Ingress
|
||||
<Plus className="h-3 w-3" />{i18n.t("common.newInstanceIngress")}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
|
||||
@@ -23,7 +23,7 @@ export function IngressListItem({ ing, matched, onEdit, onDelete }: Props) {
|
||||
{matched && <Badge className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-[10px]"> {i18n.t('kubernetes.deploymentEditService.associated')} </Badge>}
|
||||
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green ml-auto"
|
||||
onClick={onEdit}>
|
||||
<Pencil className="h-3 w-3 mr-1" />编辑
|
||||
<Pencil className="h-3 w-3 mr-1" />{i18n.t("common.editAction")}
|
||||
</Button>
|
||||
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
|
||||
title={i18n.t('kubernetes.ingress.deleteIngress')} onClick={onDelete}>
|
||||
|
||||
@@ -44,7 +44,7 @@ export function ServiceCreateForm({ svcForm, setSvcForm, selectorLabels, deploym
|
||||
return (
|
||||
<div className="mt-3 border border-blue-800/50 rounded-lg p-3 bg-blue-950/20 space-y-3">
|
||||
<div className="text-xs font-semibold text-blue-300 flex items-center gap-1.5">
|
||||
<Plus className="h-3 w-3" />创建新 Service
|
||||
<Plus className="h-3 w-3" />{i18n.t("common.newInstanceService")}
|
||||
</div>
|
||||
|
||||
{/* 基本信息 */}
|
||||
@@ -122,7 +122,7 @@ export function ServiceCreateForm({ svcForm, setSvcForm, selectorLabels, deploym
|
||||
{/* 添加自定义端口 */}
|
||||
<Button size="sm" variant="outline" className="h-7 w-full border-dashed border-[var(--dg-border)] dg-text-secondary text-xs"
|
||||
onClick={() => addPort()}>
|
||||
<Plus className="h-3 w-3 mr-1" />添加自定义端口
|
||||
<Plus className="h-3 w-3 mr-1" />{i18n.t("common.addCustom")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export function ServiceListItem({ svc, matched, onEdit, onDelete }: Props) {
|
||||
<code className="text-[11px] dg-text-muted ml-auto">{svc.clusterIP}</code>
|
||||
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green"
|
||||
onClick={onEdit}>
|
||||
<Pencil className="h-3 w-3 mr-1" />编辑
|
||||
<Pencil className="h-3 w-3 mr-1" />{i18n.t("common.editAction")}
|
||||
</Button>
|
||||
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
|
||||
title={i18n.t('kubernetes.service.deleteService')} onClick={onDelete}>
|
||||
|
||||
@@ -26,8 +26,8 @@ export function BottomStatusBar({
|
||||
return (
|
||||
<div className="flex items-center justify-between px-4 py-1.5 border-t border-[var(--dg-border)] bg-[var(--dg-bg-tertiary)] text-xs text-[var(--dg-text-muted)]">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="flex items-center gap-1"><Filter className="h-3 w-3" />缓冲 {lineCount}/{RING_BUFFER_MAX}</span>
|
||||
{keyword && <span>匹配 {matchedCount}</span>}
|
||||
<span className="flex items-center gap-1"><Filter className="h-3 w-3" />{i18n.t("common.buffer")} {lineCount}/{RING_BUFFER_MAX}</span>
|
||||
{keyword && <span>{i18n.t("common.matched")} {matchedCount}</span>}
|
||||
{container && <span className="flex items-center gap-1"><Box className="h-3 w-3" />{container}</span>}
|
||||
{previous && <span className="dg-text-yellow flex items-center gap-1"><History className="h-3 w-3" />previous</span>}
|
||||
</div>
|
||||
|
||||
@@ -56,11 +56,11 @@ export function PodInstancesTable({
|
||||
<div className="flex items-center gap-1">
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-[var(--dg-green)] hover:text-[var(--dg-green)] hover:bg-[var(--dg-green)]/10"
|
||||
onClick={() => onTerminal(pod)}>
|
||||
<Terminal className="h-3.5 w-3.5 mr-1" />终端
|
||||
<Terminal className="h-3.5 w-3.5 mr-1" />{i18n.t("common.podLogs")}
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-[var(--dg-orange)] hover:text-[var(--dg-orange)] hover:bg-[var(--dg-orange)]/10"
|
||||
onClick={() => onFileBrowser(pod)}>
|
||||
<HardDrive className="h-3.5 w-3.5 mr-1" />文件浏览器
|
||||
<HardDrive className="h-3.5 w-3.5 mr-1" />{i18n.t("common.fileBrowser")}
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
@@ -15,7 +15,7 @@ export function UpdateStrategySelectorCards({ stats }: { stats: WorkloadStats })
|
||||
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Settings className="h-4 w-4 text-[var(--dg-orange)]" />更新策略
|
||||
<Settings className="h-4 w-4 text-[var(--dg-orange)]" />{i18n.t("common.updateStrategy")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 space-y-2 text-xs">
|
||||
@@ -70,7 +70,7 @@ export function UpdateStrategySelectorCards({ stats }: { stats: WorkloadStats })
|
||||
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Tag className="h-4 w-4 text-[var(--dg-purple)]" />选择器与标签
|
||||
<Tag className="h-4 w-4 text-[var(--dg-purple)]" />{i18n.t("common.selectAndLabel")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 space-y-3 text-xs">
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Badge } from '@/components/ui/badge';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Container } from 'lucide-react';
|
||||
import type { JsonData } from '@/types/common';
|
||||
import i18n from '@/i18n';
|
||||
|
||||
/** 统计卡片 */
|
||||
export function StatCard({ label, value, sub, color }: {
|
||||
@@ -25,7 +26,7 @@ export function StatCard({ label, value, sub, color }: {
|
||||
/** 键值对标签徽章组 */
|
||||
export function LabelBadges({ labels }: { labels: Record<string, string> | undefined }) {
|
||||
const entries = Object.entries(labels || {});
|
||||
if (entries.length === 0) return <span className="text-xs text-[var(--dg-text-muted)]">无</span>;
|
||||
if (entries.length === 0) return <span className="text-xs text-[var(--dg-text-muted)]">{i18n.t("common.none")}</span>;
|
||||
return (
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{entries.map(([k, v]) => (
|
||||
|
||||
Reference in new issue
Block a user