From 5ee62f267c6dec1ec34ded117313694616314dcd Mon Sep 17 00:00:00 2001 From: Yuxing Deng Date: Tue, 21 Jul 2026 16:52:35 +0800 Subject: [PATCH] feat(billing): on-card charge/pay badge slots for models & instance types Add the plugin-fed billing price-badge slots to the model cards and the gpu-instance-type / storage cards so the enterprise plugin can surface charge / pay indicators inline. --- .../components/instance-type-item.tsx | 5 ++ .../components/instance-type-list.tsx | 5 ++ src/pages/llmodels/components/model-item.tsx | 58 ++++++++++++++----- src/pages/llmodels/user-models.tsx | 5 ++ 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/pages/gpu-service/instances/components/instance-type-item.tsx b/src/pages/gpu-service/instances/components/instance-type-item.tsx index 41b4502a..f940716d 100644 --- a/src/pages/gpu-service/instances/components/instance-type-item.tsx +++ b/src/pages/gpu-service/instances/components/instance-type-item.tsx @@ -1,3 +1,4 @@ +import PluginExtraFields from '@/components/plugin-extra-fields'; import { AutoTooltip, IconFont, ThemeTag } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import { Flex, Tag } from 'antd'; @@ -271,6 +272,10 @@ const InstanceTypeItem: React.FC = ({ item }) => { {cpuManufacturer} )} + diff --git a/src/pages/gpu-service/instances/components/instance-type-list.tsx b/src/pages/gpu-service/instances/components/instance-type-list.tsx index 0c226c1b..8d22b673 100644 --- a/src/pages/gpu-service/instances/components/instance-type-list.tsx +++ b/src/pages/gpu-service/instances/components/instance-type-list.tsx @@ -1,3 +1,4 @@ +import PluginExtraFields from '@/components/plugin-extra-fields'; import { FileSkeletonRows } from '@/pages/llmodels/components/model-source/file-skeleton'; import { TemplateCard } from '@gpustack/core-ui'; import { Empty, Flex, Spin } from 'antd'; @@ -40,6 +41,10 @@ const InstanceTypeList: React.FC = ({ return ( + {dataList.map((item) => { const name = item.name; return ( diff --git a/src/pages/llmodels/components/model-item.tsx b/src/pages/llmodels/components/model-item.tsx index 09b8c33f..ff7b80a7 100644 --- a/src/pages/llmodels/components/model-item.tsx +++ b/src/pages/llmodels/components/model-item.tsx @@ -1,12 +1,13 @@ +import PluginExtraFields from '@/components/plugin-extra-fields'; import { IconFont, - StatusTag, + StatusDot, TagsWrapper, TemplateCard, ThemeTag } from '@gpustack/core-ui'; import { useIntl, useNavigate } from '@umijs/max'; -import { Button } from 'antd'; +import { Button, Tooltip } from 'antd'; import _ from 'lodash'; import React, { useMemo } from 'react'; import styled from 'styled-components'; @@ -192,6 +193,23 @@ const ModelItem: React.FC<{ return _.round(max_tokens / 1024); }, [model]); + // Ready is the normal state — show just the dot (no label); other states + // (Not Ready / Stopped) keep their label so the problem is legible. + const statusNode = ( + + ); + return ( )} - {model.name} + + {model.name} + {/* Status moved to a compact dot right after the name, freeing + the header's right side for the price summary. The dot keeps + the state message on hover (StatusDot has no built-in one). */} + + {model.state_message ? ( + + + {statusNode} + + + ) : ( + statusNode + )} + + + + + - } > diff --git a/src/pages/llmodels/user-models.tsx b/src/pages/llmodels/user-models.tsx index 1ceb6164..efec90a6 100644 --- a/src/pages/llmodels/user-models.tsx +++ b/src/pages/llmodels/user-models.tsx @@ -1,3 +1,4 @@ +import PluginExtraFields from '@/components/plugin-extra-fields'; import useTableFetch from '@/hooks/use-table-fetch'; import { SyncOutlined } from '@ant-design/icons'; import { @@ -268,6 +269,10 @@ const UserModels: React.FC = () => { } > +