1.32
This commit is contained in:
parent
a19b4b8ec8
commit
e70f6c5d41
@ -35,7 +35,7 @@ import { PodRowSkeleton } from './PodRowSkeleton';
|
|||||||
import { YamlViewerDialog } from './YamlViewerDialog';
|
import { YamlViewerDialog } from './YamlViewerDialog';
|
||||||
import { restartK8sDeployment, scaleK8sDeployment, deleteK8sDeployment } from '../service';
|
import { restartK8sDeployment, scaleK8sDeployment, deleteK8sDeployment } from '../service';
|
||||||
import type { K8sDeploymentResponse, K8sPodResponse } from '../types';
|
import type { K8sDeploymentResponse, K8sPodResponse } from '../types';
|
||||||
import { getDeploymentHealth, HealthStatusLabels } from '../types';
|
import { getDeploymentHealth } from '../types';
|
||||||
import { getK8sPodsByDeployment } from '../service';
|
import { getK8sPodsByDeployment } from '../service';
|
||||||
import { useAutoRefresh } from '../hooks/useAutoRefresh';
|
import { useAutoRefresh } from '../hooks/useAutoRefresh';
|
||||||
import { formatCpuPair } from '../utils/resourceFormatter';
|
import { formatCpuPair } from '../utils/resourceFormatter';
|
||||||
@ -64,6 +64,7 @@ export const DeploymentRow: React.FC<DeploymentRowProps> = ({
|
|||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [pods, setPods] = useState<K8sPodResponse[]>([]);
|
const [pods, setPods] = useState<K8sPodResponse[]>([]);
|
||||||
const [initialLoading, setInitialLoading] = useState(true);
|
const [initialLoading, setInitialLoading] = useState(true);
|
||||||
|
const [restartDialogOpen, setRestartDialogOpen] = useState(false);
|
||||||
const [scaleDialogOpen, setScaleDialogOpen] = useState(false);
|
const [scaleDialogOpen, setScaleDialogOpen] = useState(false);
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
const [yamlDialogOpen, setYamlDialogOpen] = useState(false);
|
const [yamlDialogOpen, setYamlDialogOpen] = useState(false);
|
||||||
@ -130,6 +131,7 @@ export const DeploymentRow: React.FC<DeploymentRowProps> = ({
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
setRestartDialogOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -292,8 +294,7 @@ export const DeploymentRow: React.FC<DeploymentRowProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={handleRestart}
|
onClick={() => setRestartDialogOpen(true)}
|
||||||
disabled={loading}
|
|
||||||
className="h-8 w-8 p-0"
|
className="h-8 w-8 p-0"
|
||||||
>
|
>
|
||||||
<RotateCw className="h-4 w-4" />
|
<RotateCw className="h-4 w-4" />
|
||||||
@ -388,6 +389,28 @@ export const DeploymentRow: React.FC<DeploymentRowProps> = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 重启确认对话框 */}
|
||||||
|
<Dialog open={restartDialogOpen} onOpenChange={setRestartDialogOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>确认重启</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
确定要重启 Deployment <strong>{deployment.deploymentName}</strong> 吗?
|
||||||
|
这将触发滚动更新,Pod会逐个重启。
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => setRestartDialogOpen(false)}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleRestart} disabled={loading}>
|
||||||
|
{loading && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||||
|
确认重启
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
{/* 扩缩容对话框 */}
|
{/* 扩缩容对话框 */}
|
||||||
<Dialog open={scaleDialogOpen} onOpenChange={setScaleDialogOpen}>
|
<Dialog open={scaleDialogOpen} onOpenChange={setScaleDialogOpen}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
|||||||
129
frontend/src/pages/Resource/K8s/List/utils/resourceFormatter.ts
Normal file
129
frontend/src/pages/Resource/K8s/List/utils/resourceFormatter.ts
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* 解析CPU值为核数
|
||||||
|
* @param value CPU字符串,如 "500m" 或 "1" 或 "1.5"
|
||||||
|
* @returns 核数(浮点数)
|
||||||
|
*/
|
||||||
|
export function parseCpu(value: string): number {
|
||||||
|
if (!value) return 0;
|
||||||
|
|
||||||
|
const trimmed = value.trim();
|
||||||
|
|
||||||
|
// 处理毫核(如 "500m")
|
||||||
|
if (trimmed.endsWith('m')) {
|
||||||
|
const milliCores = parseFloat(trimmed.slice(0, -1));
|
||||||
|
return milliCores / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理纯数字(如 "1" 或 "1.5")
|
||||||
|
return parseFloat(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析内存值为字节数
|
||||||
|
* @param value 内存字符串,如 "512Mi" 或 "1Gi"
|
||||||
|
* @returns 字节数
|
||||||
|
*/
|
||||||
|
export function parseMemory(value: string): number {
|
||||||
|
if (!value) return 0;
|
||||||
|
|
||||||
|
const trimmed = value.trim();
|
||||||
|
const units: Record<string, number> = {
|
||||||
|
'Ki': 1024,
|
||||||
|
'Mi': 1024 * 1024,
|
||||||
|
'Gi': 1024 * 1024 * 1024,
|
||||||
|
'Ti': 1024 * 1024 * 1024 * 1024,
|
||||||
|
'K': 1000,
|
||||||
|
'M': 1000 * 1000,
|
||||||
|
'G': 1000 * 1000 * 1000,
|
||||||
|
'T': 1000 * 1000 * 1000 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [unit, multiplier] of Object.entries(units)) {
|
||||||
|
if (trimmed.endsWith(unit)) {
|
||||||
|
const value = parseFloat(trimmed.slice(0, -unit.length));
|
||||||
|
return value * multiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 纯数字,默认为字节
|
||||||
|
return parseFloat(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化CPU显示(智能统一单位)
|
||||||
|
* @param request CPU请求值
|
||||||
|
* @param limit CPU限制值
|
||||||
|
* @returns 格式化后的字符串,如 "0.5 / 1" 或 "500m / 800m"
|
||||||
|
*/
|
||||||
|
export function formatCpuPair(request?: string, limit?: string): string {
|
||||||
|
if (!request && !limit) return '- / -';
|
||||||
|
if (!request) return `- / ${limit}`;
|
||||||
|
if (!limit) return `${request} / -`;
|
||||||
|
|
||||||
|
const reqCores = parseCpu(request);
|
||||||
|
const limitCores = parseCpu(limit);
|
||||||
|
|
||||||
|
// 如果都小于1核,使用毫核显示
|
||||||
|
if (reqCores < 1 && limitCores < 1) {
|
||||||
|
const reqMilli = Math.round(reqCores * 1000);
|
||||||
|
const limitMilli = Math.round(limitCores * 1000);
|
||||||
|
return `${reqMilli}m / ${limitMilli}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则统一使用核数显示
|
||||||
|
const formatCore = (cores: number) => {
|
||||||
|
// 如果是整数,不显示小数点
|
||||||
|
if (cores === Math.floor(cores)) {
|
||||||
|
return cores.toString();
|
||||||
|
}
|
||||||
|
// 保留最多2位小数
|
||||||
|
return cores.toFixed(2).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
return `${formatCore(reqCores)} / ${formatCore(limitCores)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化内存显示(智能统一单位)
|
||||||
|
* @param request 内存请求值
|
||||||
|
* @param limit 内存限制值
|
||||||
|
* @returns 格式化后的字符串,如 "0.5Gi / 1Gi" 或 "512Mi / 1024Mi"
|
||||||
|
*/
|
||||||
|
export function formatMemoryPair(request?: string, limit?: string): string {
|
||||||
|
if (!request && !limit) return '- / -';
|
||||||
|
if (!request) return `- / ${limit}`;
|
||||||
|
if (!limit) return `${request} / -`;
|
||||||
|
|
||||||
|
const reqBytes = parseMemory(request);
|
||||||
|
const limitBytes = parseMemory(limit);
|
||||||
|
|
||||||
|
const units = [
|
||||||
|
{ name: 'Ti', value: 1024 * 1024 * 1024 * 1024 },
|
||||||
|
{ name: 'Gi', value: 1024 * 1024 * 1024 },
|
||||||
|
{ name: 'Mi', value: 1024 * 1024 },
|
||||||
|
{ name: 'Ki', value: 1024 },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 选择合适的单位(以较大值为准)
|
||||||
|
const maxBytes = Math.max(reqBytes, limitBytes);
|
||||||
|
let selectedUnit = units[units.length - 1]; // 默认Ki
|
||||||
|
|
||||||
|
for (const unit of units) {
|
||||||
|
if (maxBytes >= unit.value) {
|
||||||
|
selectedUnit = unit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatValue = (bytes: number) => {
|
||||||
|
const value = bytes / selectedUnit.value;
|
||||||
|
// 如果是整数,不显示小数点
|
||||||
|
if (value === Math.floor(value)) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
// 保留最多2位小数
|
||||||
|
return value.toFixed(2).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
return `${formatValue(reqBytes)}${selectedUnit.name} / ${formatValue(limitBytes)}${selectedUnit.name}`;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user