import AutoTooltip from '@/components/auto-tooltip'; import SealInput from '@/components/seal-form/seal-input'; import SealSelect from '@/components/seal-form/seal-select'; import { modelNameReg, PageAction } from '@/config'; import { OPENAI_COMPATIBLE } from '@/config/settings'; import useAppUtils from '@/hooks/use-app-utils'; import { ClusterStatusLabelMap, ClusterStatusValueMap } from '@/pages/cluster-management/config'; import { useIntl } from '@umijs/max'; import { Form } from 'antd'; import { useMemo } from 'react'; import styled from 'styled-components'; import { sourceOptions } from '../config'; import { useFormContext } from '../config/form-context'; import { FormData } from '../config/types'; import BackendForm from './backend'; import CatalogFrom from './catalog'; import CustomBackend from './custom-backend'; import LocalPathSource from './local-path-source'; import ModeField from './mode-field'; import OnlineSource from './online-source'; const ClusterOption = styled.span` display: flex; padding: 8px 0; width: 100%; flex-direction: column; border-bottom: 1px solid var(--ant-color-split); gap: 4px; .label { display: flex; align-items: center; gap: 8px; flex: 1; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .dot { display: flex; width: 6px; height: 6px; background-color: var(--ant-color-warning); border-radius: 50%; &.ready { background-color: var(--ant-color-success); } } .item { width: max-content; display: flex; align-items: center; padding: 2px 0px; border-radius: 4px; font-weight: 400; gap: 8px; } .s-dot { width: 4px; height: 4px; margin: 0 4px; background-color: var(--ant-color-text-quaternary); border-radius: 50%; } `; interface BasicFormProps { fields?: string[]; sourceDisable?: boolean; sourceList?: Global.BaseOption[]; clusterList: Global.BaseOption< number, { provider: string; state: string; is_default: boolean; workers: number; ready_workers: number; gpus: number; } >[]; handleClusterChange: (value: number) => void; onSourceChange?: (value: string) => void; } const BasicForm: React.FC = (props) => { const { fields = [], sourceList, clusterList, sourceDisable, handleClusterChange, onSourceChange } = props; const intl = useIntl(); const form = Form.useFormInstance(); const { getRuleMessage } = useAppUtils(); const { onValuesChange, action } = useFormContext(); const handleOnSourceChange = (val: string) => { onSourceChange?.(val); }; const handleNameBlur = (e: React.FocusEvent) => { if (action === PageAction.EDIT) { const value = e.target.value; onValuesChange?.({ name: value }, form.getFieldsValue()); } }; const clusterOptions = useMemo(() => { return clusterList?.map((item) => { return { label: item.state === ClusterStatusValueMap.Ready ? item.label : `${item.label} [${ClusterStatusLabelMap[item.state as string]}]`, value: item.value, workers: item.workers, ready_workers: item.ready_workers, gpus: item.gpus }; }); }, [clusterList]); const clusterOptionRender = (option: any) => { const { data } = option; return ( {data.label} 0 ? 'ready' : ''}`}> 0 ? 'ready' : ''}`} > {intl.formatMessage({ id: 'resources.nodes' })}: {data.ready_workers}/{data.workers} GPUs: {data.gpus} ); }; return ( <> data-field="name" name="name" rules={[ { required: true, message: getRuleMessage('input', 'common.table.name') }, { pattern: modelNameReg, message: intl.formatMessage({ id: 'models.form.rules.name' }) } ]} > {fields.includes('source') && ( name="source" rules={[ { required: true, message: getRuleMessage('select', 'models.form.source') } ]} > { } )} name="cluster_id" rules={[ { required: true, message: getRuleMessage('select', 'clusters.title') } ]} > { } name="replicas" rules={[ { required: true, message: getRuleMessage('input', 'models.form.replicas') } ]} > name="description"> ); }; export default BasicForm;