From f02b972dc00aaabe705929b00bf463d7aecc4893 Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 14 Oct 2025 20:02:55 +0800 Subject: [PATCH] fix(styles): my models --- src/pages/llmodels/components/model-item.tsx | 186 +++++++++++------- .../llmodels/components/update-modal.tsx | 3 + src/pages/llmodels/config/button-actions.ts | 10 +- src/pages/llmodels/forms/backend.tsx | 8 +- 4 files changed, 129 insertions(+), 78 deletions(-) diff --git a/src/pages/llmodels/components/model-item.tsx b/src/pages/llmodels/components/model-item.tsx index 561f4065..a4b65331 100644 --- a/src/pages/llmodels/components/model-item.tsx +++ b/src/pages/llmodels/components/model-item.tsx @@ -2,20 +2,39 @@ import IconFont from '@/components/icon-font'; import StatusTag from '@/components/status-tag'; import ThemeTag from '@/components/tags-wrapper/theme-tag'; import Card from '@/components/templates/card'; +import { StatusMaps } from '@/config'; import { useIntl, useNavigate } from '@umijs/max'; import { Button } from 'antd'; -import dayjs from 'dayjs'; import _ from 'lodash'; -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { - InstanceStatusMapValue, - modelCategories, - modelCategoriesMap, - modelSourceMap -} from '../config'; +import { modelCategories, modelCategoriesMap, modelSourceMap } from '../config'; import { categoryToPathMap } from '../config/button-actions'; +const MyModelsStatusValueMap = { + Inactive: 'Inactive', + Starting: 'Starting', + Degrade: 'Degrade', + Active: 'Active' +}; + +const MyModelsStatusMap = { + [MyModelsStatusValueMap.Inactive]: StatusMaps.inactive, + [MyModelsStatusValueMap.Starting]: StatusMaps.transitioning, + [MyModelsStatusValueMap.Degrade]: StatusMaps.warning, + [MyModelsStatusValueMap.Active]: StatusMaps.success +}; + +const CardWrapper = styled.div` + &:hover { + .content { + .btn { + display: block; + } + } + } +`; + const ModelItemContent = styled.div` display: flex; flex-direction: column; @@ -24,7 +43,6 @@ const ModelItemContent = styled.div` cursor: default; .content { display: flex; - flex-direction: column; justify-content: space-between; flex: 1; } @@ -37,11 +55,7 @@ const ModelItemContent = styled.div` display: none; } } - &:hover { - .btn { - display: block; - } - } + .time { color: var(--ant-color-text-secondary); font-size: var(--font-size-small); @@ -51,7 +65,6 @@ const ModelItemContent = styled.div` display: flex; align-items: center; gap: 8px; - margin-bottom: 16px; .tag-item { margin-right: 0; display: flex; @@ -80,7 +93,7 @@ const Header = styled.div` display: flex; align-items: center; font-size: var(--font-size-middle); - font-weight: 600; + font-weight: 500; color: var(--ant-color-text); } `; @@ -119,59 +132,100 @@ const ModelItem: React.FC<{ navigate(`/playground/chat?model=${model.name}`); }; + // context length + const maxToken = useMemo(() => { + const meta = model.meta || {}; + const { max_model_len, n_ctx, n_slot, max_total_tokens } = meta || {}; + + let max_tokens: number = 0; + + if (n_ctx && n_slot) { + max_tokens = _.divide(n_ctx, n_slot); + } else if (max_model_len) { + max_tokens = max_model_len; + } else if (max_total_tokens) { + max_tokens = max_total_tokens; + } + + return max_tokens / 1024; + }, [model]); + + const status = useMemo(() => { + if (!model.replicas && !model.ready_replicas) { + return MyModelsStatusValueMap.Inactive; + } + if (model.replicas > 0 && !model.ready_replicas) { + return MyModelsStatusValueMap.Starting; + } + if (model.replicas > 1 && model.replicas !== model.ready_replicas) { + return MyModelsStatusValueMap.Degrade; + } + if (model.replicas === model.ready_replicas && model.replicas > 0) { + return MyModelsStatusValueMap.Active; + } + return MyModelsStatusValueMap.Inactive; + }, [model]); + return ( - onClick(model)} - clickable={false} - ghost - header={ -
- - - {model.name} - - -
- } - > - -
-
- - {_.find(modelCategories, { value: model.categories?.[0] }) - ?.label || model.categories?.[0]} - - - 128K context - -
-
- - {dayjs(model.created_at).format('YYYY-MM-DD HH:mm:ss')} + + onClick(model)} + clickable={false} + hoverable={true} + ghost + header={ +
+ + + {model.name} - + +
+ } + > + +
+
+
+ + {_.find(modelCategories, { value: model.categories?.[0] }) + ?.label || model.categories?.[0]} + + {maxToken > 0 && ( + + {maxToken}K context + + )} +
+ {[ + MyModelsStatusValueMap.Active, + MyModelsStatusValueMap.Degrade + ].includes(status) && ( + + )} +
-
- - + + + ); }; diff --git a/src/pages/llmodels/components/update-modal.tsx b/src/pages/llmodels/components/update-modal.tsx index 9dbe7a2d..31fe37ca 100644 --- a/src/pages/llmodels/components/update-modal.tsx +++ b/src/pages/llmodels/components/update-modal.tsx @@ -243,6 +243,9 @@ const UpdateModal: React.FC = (props) => { setTimeout(() => { setOriginalFormData(); initGPUSelector(); + formRef.current?.getBackendOptions?.({ + cluster_id: formData.cluster_id + }); }, 100); } if (!open) { diff --git a/src/pages/llmodels/config/button-actions.ts b/src/pages/llmodels/config/button-actions.ts index a3a3df62..26077fc8 100644 --- a/src/pages/llmodels/config/button-actions.ts +++ b/src/pages/llmodels/config/button-actions.ts @@ -61,11 +61,6 @@ export const ActionList: ActionItem[] = [ key: 'api', icon: icons.ApiOutlined }, - { - label: 'models.button.accessSettings', - key: 'accessControl', - icon: icons.Private - }, { label: 'common.button.stop', key: 'stop', @@ -76,6 +71,11 @@ export const ActionList: ActionItem[] = [ key: 'start', icon: icons.Play }, + { + label: 'models.button.accessSettings', + key: 'accessControl', + icon: icons.Private + }, { label: 'common.button.delete', key: 'delete', diff --git a/src/pages/llmodels/forms/backend.tsx b/src/pages/llmodels/forms/backend.tsx index 330e60c6..8b27a0dc 100644 --- a/src/pages/llmodels/forms/backend.tsx +++ b/src/pages/llmodels/forms/backend.tsx @@ -3,7 +3,6 @@ import AutoComplete from '@/components/seal-form/auto-complete'; import SealInput from '@/components/seal-form/seal-input'; import SealSelect from '@/components/seal-form/seal-select'; import TooltipList from '@/components/tooltip-list'; -import { PageAction } from '@/config'; import useAppUtils from '@/hooks/use-app-utils'; import { useIntl } from '@umijs/max'; import { Form, Typography } from 'antd'; @@ -11,8 +10,7 @@ import React, { useMemo } from 'react'; import { backendLabelMap, backendTipsList, - getBackendParamsTips, - modelSourceMap + getBackendParamsTips } from '../config'; import { backendOptionsMap } from '../config/backend-parameters'; import { useFormContext } from '../config/form-context'; @@ -68,10 +66,6 @@ const BackendFields: React.FC = () => { label={intl.formatMessage({ id: 'models.form.backend' })} description={} options={backendOptions} - disabled={ - action === PageAction.EDIT && - source !== modelSourceMap.local_path_value - } > {backendOptionsMap.custom !== backend && (