From fc76822bdfb161b2fb7af00b785a7c80fe90c1cb Mon Sep 17 00:00:00 2001 From: jialin Date: Mon, 12 Jan 2026 12:23:21 +0800 Subject: [PATCH] fix: catalog size --- src/components/card-wrapper/index.less | 7 - src/components/card-wrapper/index.tsx | 16 +- src/config/theme/dark.ts | 3 + src/config/theme/light.ts | 3 + src/pages/cluster-management/apis/index.ts | 7 + .../cluster-management/cluster-detail.tsx | 42 ++++- .../components/detail/cluster-basic.tsx | 167 ++++++++++++++++++ .../components/detail/cluster-system-load.tsx | 126 ++++++++++++- src/pages/cluster-management/config/types.ts | 1 + .../hooks/use-cluster-columns.tsx | 7 +- ...r-system-load.ts => use-cluster-detail.ts} | 48 ++++- .../llmodels/components/catalog-item.tsx | 20 ++- src/pages/llmodels/config/types.ts | 1 + 13 files changed, 413 insertions(+), 35 deletions(-) delete mode 100644 src/components/card-wrapper/index.less create mode 100644 src/pages/cluster-management/components/detail/cluster-basic.tsx rename src/pages/cluster-management/services/{use-cluster-system-load.ts => use-cluster-detail.ts} (60%) diff --git a/src/components/card-wrapper/index.less b/src/components/card-wrapper/index.less deleted file mode 100644 index 6376d7e8..00000000 --- a/src/components/card-wrapper/index.less +++ /dev/null @@ -1,7 +0,0 @@ -.cardWrapper { - border-radius: var(--border-radius-small); - background-color: var(--ant-color-bg-container); - box-shadow: none; - padding: 10px 16px; - border: 1px solid var(--ant-color-border); -} diff --git a/src/components/card-wrapper/index.tsx b/src/components/card-wrapper/index.tsx index 90c076b3..99d72401 100644 --- a/src/components/card-wrapper/index.tsx +++ b/src/components/card-wrapper/index.tsx @@ -1,12 +1,16 @@ -import styles from './index.less'; +import styled from 'styled-components'; + +const Wrapper = styled.div` + border-radius: var(--border-radius-small); + background-color: var(--ant-color-bg-container); + box-shadow: none; + padding: 10px 16px; + border: 1px solid var(--ant-color-border); +`; const CardWrapper = (props: any) => { const { children, style } = props; - return ( -
- {children} -
- ); + return {children}; }; export default CardWrapper; diff --git a/src/config/theme/dark.ts b/src/config/theme/dark.ts index 79d802aa..34e8120d 100644 --- a/src/config/theme/dark.ts +++ b/src/config/theme/dark.ts @@ -84,6 +84,9 @@ export default { trackHoverBg: '#646464', dotActiveBorderColor: 'rgba(255,255,255,0.25)', dotBorderColor: 'rgba(255,255,255,0.25)' + }, + Descriptions: { + itemPaddingBottom: 8 } }, token: { diff --git a/src/config/theme/light.ts b/src/config/theme/light.ts index ed2bedfd..dfd98922 100644 --- a/src/config/theme/light.ts +++ b/src/config/theme/light.ts @@ -83,6 +83,9 @@ export default { trackHoverBg: '#B4B4B4', dotActiveBorderColor: 'rgba(0,0,0,0.25)', dotBorderColor: 'rgba(0,0,0,0.25)' + }, + Descriptions: { + itemPaddingBottom: 8 } }, token: { diff --git a/src/pages/cluster-management/apis/index.ts b/src/pages/cluster-management/apis/index.ts index 29d1fee5..39317f9b 100644 --- a/src/pages/cluster-management/apis/index.ts +++ b/src/pages/cluster-management/apis/index.ts @@ -149,6 +149,13 @@ export async function queryClusterDetail( }); } +export async function queryClusterItem(params: { id: number }, options?: any) { + return request(`${CLUSTERS_API}/${params.id}`, { + method: 'GET', + cancelToken: options?.token + }); +} + export async function queryClusterToken(params: { id: number }) { return request(`${CLUSTERS_API}/${params.id}/${CLUSTER_TOKEN}`, { method: 'GET' diff --git a/src/pages/cluster-management/cluster-detail.tsx b/src/pages/cluster-management/cluster-detail.tsx index 6f17616f..07131235 100644 --- a/src/pages/cluster-management/cluster-detail.tsx +++ b/src/pages/cluster-management/cluster-detail.tsx @@ -1,7 +1,10 @@ +import IconFont from '@/components/icon-font'; import WorkerList from '@/pages/resources/components/workers'; import { useIntl, useNavigate, useSearchParams } from '@umijs/max'; +import { Tabs } from 'antd'; import { PageContainerInner } from '../_components/page-box'; import PageBreadcrumb from '../_components/page-breadcrumb'; +import ClusterBasic from './components/detail/cluster-basic'; import ClusterSystemLoad from './components/detail/cluster-system-load'; const ClusterDetailModal = () => { @@ -27,13 +30,40 @@ const ClusterDetailModal = () => { title: }} > + - , + children: ( + + ) + }, + { + key: 'deployments', + label: 'Deployments', + icon: , + children:
Deployments Content
+ }, + { + key: 'gpus', + label: 'GPUs', + icon: , + children:
GPUs Content
+ } + ]} /> ); diff --git a/src/pages/cluster-management/components/detail/cluster-basic.tsx b/src/pages/cluster-management/components/detail/cluster-basic.tsx new file mode 100644 index 00000000..f7f86e5e --- /dev/null +++ b/src/pages/cluster-management/components/detail/cluster-basic.tsx @@ -0,0 +1,167 @@ +import CardWrapper from '@/components/card-wrapper'; +import IconFont from '@/components/icon-font'; +import StatusTag from '@/components/status-tag'; +import { StarFilled } from '@ant-design/icons'; +import { useIntl } from '@umijs/max'; +import type { DescriptionsProps } from 'antd'; +import { Descriptions, Tooltip } from 'antd'; +import dayjs from 'dayjs'; +import React, { useEffect } from 'react'; +import styled from 'styled-components'; +import { + ClusterStatus, + ClusterStatusLabelMap, + ProviderLabelMap +} from '../../config'; +import providers from '../../config/providers'; +import { useClusterDetail } from '../../services/use-cluster-detail'; + +const Container = styled.div` + display: flex; + height: 184px; + .left { + padding: 24px 24px; + width: 160px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 20px; + .img { + width: 72px; + height: 72px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 8px; + background-color: var(--ant-blue-1); + .anticon { + font-size: 36px; + } + } + } + .right { + flex: 1; + padding-block: 24px; + padding-inline: 0 24px; + } +`; + +const Title = styled.div` + display: flex; + align-items: center; + gap: 8px; +`; + +const Resources = styled.div` + display: flex; + gap: 24px; + align-items: center; + line-height: 22px; + margin-top: 16px; + .item { + display: flex; + align-items: center; + gap: 8px; + .anticon { + color: var(--ant-color-text-quaternary); + font-size: 16px; + } + .value { + font-weight: 500; + } + .label { + color: var(--ant-color-text-secondary); + } + } +`; + +const ClusterBasic: React.FC<{ clusterId: number }> = ({ clusterId }) => { + const intl = useIntl(); + const { clusterDetail, fetchClusterDetail } = useClusterDetail(); + + const items: DescriptionsProps['items'] = [ + { + key: 'provider', + label: intl.formatMessage({ id: 'clusters.table.provider' }), + children: ProviderLabelMap[clusterDetail.provider || ''] + }, + { + key: 'created_at', + label: intl.formatMessage({ id: 'common.table.createTime' }), + children: dayjs(clusterDetail.created_at).format('YYYY-MM-DD HH:mm:ss') + } + ]; + + useEffect(() => { + if (clusterId) { + fetchClusterDetail({ id: clusterId }); + } + }, [clusterId]); + + return ( + + +
+
+ { + providers.find((item) => item.value === clusterDetail?.provider) + ?.icon + } +
+
+ +
+
+
+ + {clusterDetail.name} + {clusterDetail.is_default && ( + + + + )} + + } + layout="vertical" + items={items} + /> + +
+ + + {clusterDetail.ready_workers}/{clusterDetail.workers} + + Workers +
+
+ + {clusterDetail.models} + Deployments +
+
+ + {clusterDetail.gpus} + GPUs +
+
+
+
+
+ ); +}; + +export default ClusterBasic; diff --git a/src/pages/cluster-management/components/detail/cluster-system-load.tsx b/src/pages/cluster-management/components/detail/cluster-system-load.tsx index 472f5548..d42fc8cf 100644 --- a/src/pages/cluster-management/components/detail/cluster-system-load.tsx +++ b/src/pages/cluster-management/components/detail/cluster-system-load.tsx @@ -1,5 +1,36 @@ +import CardWrapper from '@/components/card-wrapper'; +import { Col, Progress, Row } from 'antd'; import React, { useEffect } from 'react'; -import { useClusterSystemLoad } from '../../services/use-cluster-system-load'; +import styled from 'styled-components'; +import { useClusterSystemLoad } from '../../services/use-cluster-detail'; + +const Container = styled.div` + display: flex; + flex-direction: column; + height: 86px; + gap: 16px; + .title { + font-size: 14px; + font-weight: 500; + color: var(--ant-color-text-secondary); + } + + .value-wrapper { + display: flex; + align-items: center; + justify-content: space-between; + .value { + display: flex; + flex: 1; + gap: 8px; + flex-direction: column; + align-items: flex-start; + justify-content: center; + font-size: 20px; + font-weight: 600; + } + } +`; const ClusterSystemLoad: React.FC<{ clusterId: number }> = ({ clusterId }) => { const { systemLoad, fetchClusterSystemLoad } = useClusterSystemLoad(); @@ -10,7 +41,98 @@ const ClusterSystemLoad: React.FC<{ clusterId: number }> = ({ clusterId }) => { } }, [clusterId]); - return
Cluster System Load Component
; + return ( + + + + +
GPU Utilization
+
+
+ 44% + +
+
+
+
+ + + + +
VRAM Utilization
+
+
44%
+
+ +
+
+
+
+ + + + +
CPU Utilization
+
+
+ 44% + +
+
+
+
+ + + + +
Memo Utilization
+
+
+ 44% +
+
+ +
+
+
+
+ +
+ ); }; export default ClusterSystemLoad; diff --git a/src/pages/cluster-management/config/types.ts b/src/pages/cluster-management/config/types.ts index 2d8acf15..da8def7a 100644 --- a/src/pages/cluster-management/config/types.ts +++ b/src/pages/cluster-management/config/types.ts @@ -57,6 +57,7 @@ export interface ClusterListItem { worker_config: Record; provider: ProviderType; credential_id: number; + created_at: string; zone: string; region: string; gpus: number; diff --git a/src/pages/cluster-management/hooks/use-cluster-columns.tsx b/src/pages/cluster-management/hooks/use-cluster-columns.tsx index b5d1b49e..bc5a8399 100644 --- a/src/pages/cluster-management/hooks/use-cluster-columns.tsx +++ b/src/pages/cluster-management/hooks/use-cluster-columns.tsx @@ -6,7 +6,7 @@ import StatusTag from '@/components/status-tag'; import { tableSorter } from '@/config/settings'; import { StarFilled } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { Tooltip, Typography } from 'antd'; +import { Tooltip } from 'antd'; import dayjs from 'dayjs'; import { useMemo } from 'react'; import { @@ -42,9 +42,10 @@ const useClusterColumns = ( render: (text: string, record: ClusterListItem) => ( <> - onCellClick?.(record, 'name')}> + {/* onCellClick?.(record, 'name')}> {record.name} - + */} + {record.name} {record.is_default && ( { + const axiosTokenRef = useRef(null); const [systemLoad, setSystemLoad] = useState<{ current: { cpu: number; @@ -22,7 +24,6 @@ export const useClusterSystemLoad = () => { }, history: {} }); - const axiosTokenRef = useRef(null); const { run: fetchClusterSystemLoad, @@ -71,3 +72,46 @@ export const useClusterSystemLoad = () => { fetchClusterSystemLoad }; }; + +export const useClusterDetail = () => { + const axiosTokenRef = useRef(null); + const [clusterDetail, setClusterDetail] = useState( + {} as ClusterListItem + ); + + const { + run: fetchClusterDetail, + loading, + cancel + } = useRequest( + async (params) => { + axiosTokenRef.current?.cancel(); + axiosTokenRef.current = createAxiosToken(); + return await queryClusterItem(params, { + token: axiosTokenRef.current.token + }); + }, + { + manual: true, + onSuccess: (response) => { + setClusterDetail(response); + }, + onError: () => { + setClusterDetail({} as ClusterListItem); + } + } + ); + + useEffect(() => { + return () => { + cancel(); + axiosTokenRef.current?.cancel(); + }; + }, []); + + return { + clusterDetail, + loading, + fetchClusterDetail + }; +}; diff --git a/src/pages/llmodels/components/catalog-item.tsx b/src/pages/llmodels/components/catalog-item.tsx index c0f9dcd8..fa215f97 100644 --- a/src/pages/llmodels/components/catalog-item.tsx +++ b/src/pages/llmodels/components/catalog-item.tsx @@ -129,15 +129,17 @@ const CatalogItem: React.FC = (props) => { ); })} - - {data.activated_size - ? `${data.size}B-A${data.activated_size}B` - : `${data.size}B`} - + {data.size > 0 && ( + + {data.activated_size + ? `${data.size}${data.size_unit}-A${data.activated_size}${data.size_unit}` + : `${data.size}${data.size_unit}`} + + )} diff --git a/src/pages/llmodels/config/types.ts b/src/pages/llmodels/config/types.ts index 0cdd8ce0..01566aa3 100644 --- a/src/pages/llmodels/config/types.ts +++ b/src/pages/llmodels/config/types.ts @@ -191,6 +191,7 @@ export interface CatalogItem { categories: string[]; capabilities: string[]; size: number; + size_unit: string; activated_size: number; licenses: string[]; release_date: string;