From d95fd8dc907fa4f9ade0fe0cf2357a27e05e3fcd Mon Sep 17 00:00:00 2001 From: jialin Date: Sun, 31 May 2026 22:20:00 +0800 Subject: [PATCH] fix: instance type format in list --- .../gpu-service/instances/forms/index.tsx | 10 ++- .../instances/forms/instance-type.tsx | 4 +- .../instances/hooks/use-instances-columns.tsx | 77 +++++++++++++++---- src/pages/gpu-service/utils.ts | 8 ++ 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/pages/gpu-service/instances/forms/index.tsx b/src/pages/gpu-service/instances/forms/index.tsx index ae91edf0..bba5ab89 100644 --- a/src/pages/gpu-service/instances/forms/index.tsx +++ b/src/pages/gpu-service/instances/forms/index.tsx @@ -1,6 +1,10 @@ import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; -import { ceilMilliToCore, parseQuantityToGi } from '@/pages/gpu-service/utils'; +import { + ceilMilliToCore, + parseJsonSafe, + parseQuantityToGi +} from '@/pages/gpu-service/utils'; import { PlusOutlined } from '@ant-design/icons'; import { CheckboxField, @@ -321,7 +325,7 @@ const GPUServiceInstanceForm: React.FC = forwardRef( resources: { ...currentData?.spec?.resources, ...buildResourcesData( - JSON.parse(currentData?.description || '{}'), + parseJsonSafe(currentData?.description || '{}', {}), { count: _.toNumber(currentData?.spec?.resources?.accelerator) || 0 @@ -341,7 +345,7 @@ const GPUServiceInstanceForm: React.FC = forwardRef( } try { return ( - JSON.parse(currentData?.description || '{}')?.spec + parseJsonSafe(currentData?.description || '{}', {})?.spec ?.unitResourcesParsed ?? undefined ); } catch { diff --git a/src/pages/gpu-service/instances/forms/instance-type.tsx b/src/pages/gpu-service/instances/forms/instance-type.tsx index 4a2d4e82..18ceb0c5 100644 --- a/src/pages/gpu-service/instances/forms/instance-type.tsx +++ b/src/pages/gpu-service/instances/forms/instance-type.tsx @@ -8,6 +8,7 @@ import _ from 'lodash'; import { useMemo } from 'react'; import styled from 'styled-components'; import { BasicResourceMax } from '../../templates/forms/basic'; +import { parseJsonSafe } from '../../utils'; import InstanceTypeItem from '../components/instance-type-item'; import { getAcceleratorMax } from '../config'; import { @@ -112,7 +113,8 @@ const InstanceTypeFormItem: React.FC = ({ }; const renderInstanceType = () => { - const description = JSON.parse(currentData?.description || '{}').spec || {}; + const description = + parseJsonSafe(currentData?.description || '{}', {}).spec || {}; return ( { - if (!cpu) return '-'; - return /m$/.test(cpu) ? (ceilMilliToCore(cpu) ?? cpu) : cpu; +const buildResourcesData = ( + instanceType: { + spec: InstanceTypeSpec; + }, + options: { + count: number; + } +) => { + const unitResourcesParsed = instanceType?.spec?.unitResourcesParsed; + const acceleratable = instanceType?.spec?.acceleratable; + const { count = 0 } = options; + + if (acceleratable) { + return { + accelerator: _.toString(count), + cpu: unitResourcesParsed?.cpu?.cores + ? count * unitResourcesParsed?.cpu?.cores + : undefined, + ram: unitResourcesParsed?.ram?.value + ? count * unitResourcesParsed?.ram?.value + : undefined + }; + } + return {}; }; -const formatMemoryGB = (value?: string | null): string => { - if (!value) return '-'; - if (/Gi$/.test(value)) return value.replace('Gi', 'GB'); - const gi = parseQuantityToGi(value); - return gi != null ? `${gi}GB` : value; +const formatResources = ( + instanceTypeSpec: { spec: InstanceTypeSpec }, + record: ListItem +) => { + const resources = buildResourcesData(instanceTypeSpec, { + count: _.toNumber(record.spec?.resources?.accelerator) || 0 + }); + + if (!record.spec?.resources?.accelerator) { + return { + cpu: record.spec?.resources?.cpu + ? `${record.spec?.resources?.cpu}C` + : '-', + ram: record.spec?.resources?.ram + ? `${record.spec?.resources?.ram}`.replace('Gi', 'GB') + : '-', + localStorage: record.spec?.resources?.localStorage + ? `${record.spec?.resources?.localStorage}`.replace('Gi', 'GB') + : '-' + }; + } + + return { + cpu: resources.cpu ? `${resources.cpu}C` : '-', + ram: resources.ram ? `${resources.ram}GB` : '-', + localStorage: record.spec?.resources?.localStorage + ? `${record.spec?.resources?.localStorage}`.replace('Gi', 'GB') + : undefined + }; }; type ConnectEntry = @@ -96,7 +141,11 @@ const useInstancesColumns = ({ const access = useAccess(); const renderInstanceType = (record: ListItem) => { - const description = JSON.parse(record?.description || '{}').spec || {}; + const description = + parseJsonSafe(record?.description || '{}', {}).spec || {}; + + const resources = formatResources({ spec: description }, record); + return ( - {formatCpu(record.spec.resources?.cpu)}C + {resources.cpu} {intl.formatMessage({ id: 'gpuservice.instance.ram' })}:{' '} - {formatMemoryGB(record.spec.resources?.ram)} + {resources.ram} {intl.formatMessage({ id: 'gpuservice.instance.disk' })}:{' '} - {formatMemoryGB(record.spec.resources?.localStorage)} + {resources.localStorage} diff --git a/src/pages/gpu-service/utils.ts b/src/pages/gpu-service/utils.ts index d96e3dfc..6ef161b8 100644 --- a/src/pages/gpu-service/utils.ts +++ b/src/pages/gpu-service/utils.ts @@ -106,3 +106,11 @@ export const ceilMilliToCore = ( num: parsed.base / outFactor }; }; + +export const parseJsonSafe = (value: string, fallback: T): T => { + try { + return JSON.parse(value) as T; + } catch { + return fallback; + } +};