From 7e744d4a16c941b0d18a4985461eca8f0d533307 Mon Sep 17 00:00:00 2001 From: zhaowei Date: Fri, 15 Aug 2025 09:16:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=9A=84=E8=AE=A1=E7=AE=97=E8=B5=84=E6=BA=90hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterSelect/config.tsx | 2 +- .../src/components/ParameterSelect/index.tsx | 31 +++-- react-ui/src/hooks/useComputingResource.ts | 118 +++++++++++------- .../components/ActiveLearnBasic/index.tsx | 4 +- .../AutoML/components/AutoMLBasic/index.tsx | 4 +- .../DevelopmentEnvironment/List/index.tsx | 4 +- .../components/HyperParameterBasic/index.tsx | 4 +- .../ModelDeployment/ServiceInfo/index.tsx | 4 +- .../components/VersionBasicInfo/index.tsx | 4 +- .../components/VersionCompareModal/index.tsx | 4 +- react-ui/src/pages/Pipeline/Info/utils.tsx | 14 +-- .../components/PipelineNodeDrawer/index.tsx | 30 +++-- react-ui/src/state/jcdResource.ts | 24 +++- react-ui/src/state/systemResource.ts | 53 ++++++++ 14 files changed, 200 insertions(+), 100 deletions(-) create mode 100644 react-ui/src/state/systemResource.ts diff --git a/react-ui/src/components/ParameterSelect/config.tsx b/react-ui/src/components/ParameterSelect/config.tsx index 651d2f1b..59d984b0 100644 --- a/react-ui/src/components/ParameterSelect/config.tsx +++ b/react-ui/src/components/ParameterSelect/config.tsx @@ -1,9 +1,9 @@ -import { filterResourceStandard, resourceFieldNames } from '@/hooks/useComputingResource'; import { DatasetData, ModelData } from '@/pages/Dataset/config'; import { ServiceData } from '@/pages/ModelDeployment/types'; import { getDatasetList, getModelList } from '@/services/dataset/index.js'; import { getServiceListReq } from '@/services/modelDeployment'; import type { JCCResourceImage, JCCResourceStandard, JCCResourceType } from '@/state/jcdResource'; +import { filterResourceStandard, resourceFieldNames } from '@/state/systemResource'; import { type SelectProps } from 'antd'; export type SelectPropsConfig = { diff --git a/react-ui/src/components/ParameterSelect/index.tsx b/react-ui/src/components/ParameterSelect/index.tsx index 7bef834d..4beddf7f 100644 --- a/react-ui/src/components/ParameterSelect/index.tsx +++ b/react-ui/src/components/ParameterSelect/index.tsx @@ -4,8 +4,8 @@ * @Description: 参数下拉选择组件,支持资源规格、数据集、模型、服务 */ -import { useComputingResource } from '@/hooks/useComputingResource'; -import state from '@/state/jcdResource'; +import jccResourceState from '@/state/jcdResource'; +import systemResourceState, { getSystemResources } from '@/state/systemResource'; import { to } from '@/utils/promise'; import { useSnapshot } from '@umijs/max'; import { Select, type SelectProps } from 'antd'; @@ -20,6 +20,8 @@ export type ParameterSelectObject = { [key: string]: any; }; +type SelectOptions = SelectProps['options']; + const identityFunc = (value: any) => value; export interface ParameterSelectProps extends SelectProps { @@ -41,7 +43,7 @@ function ParameterSelect({ onChange, ...rest }: ParameterSelectProps) { - const [options, setOptions] = useState([]); + const [options, setOptions] = useState([]); const propsConfig = paramSelectConfig[dataType]; const { getLabel = identityFunc, @@ -56,18 +58,19 @@ function ParameterSelect({ // 数据集、模型、服务,对象转换成 json 字符串 const valueText = typeof selectValue === 'object' && selectValue !== null ? getValue(selectValue) : selectValue; - const [resourceStandardList] = useComputingResource(); - const snap = useSnapshot(state); - const { getResourceTypes } = snap; + const jccResourceSnap = useSnapshot(jccResourceState); + const { getResourceTypes } = jccResourceSnap; + const systemResourceSnap = useSnapshot(systemResourceState); - const objectOptions = - dataType === 'remote-resource-type' - ? snap.types + const objectOptions = useMemo(() => { + return dataType === 'remote-resource-type' + ? jccResourceSnap.types : dataType === 'remote-image' - ? snap.images + ? jccResourceSnap.images : dataType === 'remote-resource' - ? snap.resources + ? jccResourceSnap.resources : options; + }, [dataType, options, jccResourceSnap.types, jccResourceSnap.images, jccResourceSnap.resources]); // 将对象类型转换为 Select Options const converObjectToOptions = useCallback( @@ -105,12 +108,16 @@ function ParameterSelect({ } } else if (dataType === 'remote-resource-type') { getResourceTypes(); + } else if (dataType === 'resource') { + getSystemResources(); } }; getSelectOptions(); }, [getOptions, dataType, getResourceTypes]); - const selectOptions = dataType === 'resource' ? resourceStandardList : objectSelectOptions; + const selectOptions = ( + dataType === 'resource' ? systemResourceSnap.resources : objectSelectOptions + ) as SelectOptions; const handleChange = (text: string) => { // 数据集、模型、服务,转换成对象 diff --git a/react-ui/src/hooks/useComputingResource.ts b/react-ui/src/hooks/useComputingResource.ts index b2239247..9eb5aa62 100644 --- a/react-ui/src/hooks/useComputingResource.ts +++ b/react-ui/src/hooks/useComputingResource.ts @@ -4,66 +4,90 @@ * @Description: 资源规格 hook */ -import { getComputingResourceReq } from '@/services/pipeline'; -import { ComputingResource } from '@/types'; -import { to } from '@/utils/promise'; -import { type SelectProps } from 'antd'; -import { useCallback, useEffect, useState } from 'react'; +// import { getComputingResourceReq } from '@/services/pipeline'; +// import { ComputingResource } from '@/types'; +// import { to } from '@/utils/promise'; +// import { type SelectProps } from 'antd'; +// import { useCallback, useEffect, useState } from 'react'; -const computingResource: ComputingResource[] = []; +// const computingResource: ComputingResource[] = []; -/** 过滤资源规格 */ -export const filterResourceStandard: SelectProps['filterOption'] = ( - input: string, - option?: ComputingResource, -) => { - return ( - option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? false - ); -}; +// /** 过滤资源规格 */ +// export const filterResourceStandard: SelectProps['filterOption'] = ( +// input: string, +// option?: ComputingResource, +// ) => { +// return ( +// option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? false +// ); +// }; -/** 资源规格字段 */ -export const resourceFieldNames = { - label: 'description', - value: 'id', -}; +// /** 资源规格字段 */ +// export const resourceFieldNames = { +// label: 'description', +// value: 'id', +// }; -/** 获取资源规格 */ -export function useComputingResource() { - const [resourceStandardList, setResourceStandardList] = useState([]); +// /** 获取资源规格 */ +// export function useComputingResource() { +// const [resourceStandardList, setResourceStandardList] = useState([]); - useEffect(() => { - // 获取资源规格列表数据 - const getComputingResource = async () => { - const params = { - page: 0, - size: 1000, - resource_type: '', - }; - const [res] = await to(getComputingResourceReq(params)); - if (res && res.data && Array.isArray(res.data.content)) { - setResourceStandardList(res.data.content); - computingResource.splice(0, computingResource.length, ...res.data.content); - } - }; +// useEffect(() => { +// // 获取资源规格列表数据 +// const getComputingResource = async () => { +// const params = { +// page: 0, +// size: 1000, +// resource_type: '', +// }; +// const [res] = await to(getComputingResourceReq(params)); +// if (res && res.data && Array.isArray(res.data.content)) { +// setResourceStandardList(res.data.content); +// computingResource.splice(0, computingResource.length, ...res.data.content); +// } +// }; + +// if (computingResource.length > 0) { +// setResourceStandardList(computingResource); +// } else { +// getComputingResource(); +// } +// }, []); - if (computingResource.length > 0) { - setResourceStandardList(computingResource); - } else { - getComputingResource(); - } +// // 根据 standard 获取 description +// const getDescription = useCallback( +// (id?: string | number) => { +// if (!id) { +// return undefined; +// } +// return resourceStandardList.find((item) => Number(item.id) === Number(id))?.description; +// }, +// [resourceStandardList], +// ); + +// return [resourceStandardList, getDescription] as const; +// } + +import state, { getSystemResources } from '@/state/systemResource'; +import { useSnapshot } from '@umijs/max'; +import { useCallback, useEffect } from 'react'; + +export const useSystemResource = () => { + useEffect(() => { + getSystemResources(); }, []); - // 根据 standard 获取 description + const snap = useSnapshot(state); + /* 根据 standard 获取 description */ const getDescription = useCallback( (id?: string | number) => { if (!id) { return undefined; } - return resourceStandardList.find((item) => Number(item.id) === Number(id))?.description; + return snap.resources.find((item) => Number(item.id) === Number(id))?.description; }, - [resourceStandardList], + [snap.resources], ); - return [resourceStandardList, getDescription] as const; -} + return getDescription; +}; diff --git a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx index e0decf8b..82ad98d9 100644 --- a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx +++ b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx @@ -1,6 +1,6 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; import { AutoMLTaskType, autoMLTaskTypeOptions, ExperimentStatus } from '@/enums'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { classifierAlgorithms, FrameworkType, @@ -39,7 +39,7 @@ function BasicInfo({ instanceStatus, isInstance = false, }: BasicInfoProps) { - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { return []; diff --git a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx index 6f7870d8..faf83b56 100644 --- a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx +++ b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx @@ -6,7 +6,7 @@ import { autoMLEnsembleClassOptions, autoMLTaskTypeOptions, } from '@/enums'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { classificationAlgorithms, featureAlgorithms, @@ -76,7 +76,7 @@ function AutoMLBasic({ instanceStatus, isInstance = false, }: AutoMLBasicProps) { - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { return []; diff --git a/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx b/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx index 7339135d..5395d44e 100644 --- a/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx +++ b/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx @@ -8,7 +8,7 @@ import { CodeConfigData } from '@/components/CodeSelectorModal'; import KFIcon from '@/components/KFIcon'; import { DevEditorStatus } from '@/enums'; import { useCacheState } from '@/hooks/useCacheState'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { DatasetData, ModelData } from '@/pages/Dataset/config'; import { deleteEditorReq, @@ -66,7 +66,7 @@ function EditorList() { pageSize: 10, }, ); - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); // 获取编辑器列表 const getEditorList = useCallback(async () => { diff --git a/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx b/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx index 282a5667..ea5ad15b 100644 --- a/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx +++ b/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx @@ -1,6 +1,6 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; import { ExperimentStatus, hyperParameterOptimizedMode } from '@/enums'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import ExperimentRunBasic from '@/pages/AutoML/components/ExperimentRunBasic'; import { schedulerAlgorithms, @@ -41,7 +41,7 @@ function HyperParameterBasic({ instanceStatus, isInstance = false, }: HyperParameterBasicProps) { - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { diff --git a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx index 5d47ce71..fae1e3be 100644 --- a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx +++ b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx @@ -9,7 +9,7 @@ import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; import { ServiceRunStatus, serviceStatusOptions } from '@/enums'; import { useCacheState } from '@/hooks/useCacheState'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { ModelData } from '@/pages/Dataset/config'; import { deleteServiceVersionReq, @@ -89,7 +89,7 @@ function ServiceInfo() { format: formatDate, }, ]; - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); // 获取服务详情 const getServiceInfo = useCallback(async () => { diff --git a/react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx b/react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx index 2656b946..47d03d61 100644 --- a/react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx @@ -1,6 +1,6 @@ import BasicInfo, { type BasicInfoData } from '@/components/BasicInfo'; import { ServiceRunStatus } from '@/enums'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { ServiceVersionData } from '@/pages/ModelDeployment/types'; import { formatDate } from '@/utils/date'; import { formatMirror, formatModel } from '@/utils/format'; @@ -36,7 +36,7 @@ const formatEnvText = (env?: Record) => { }; function VersionBasicInfo({ info }: BasicInfoProps) { - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); const datas: BasicInfoData[] = [ { diff --git a/react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx b/react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx index ee92edb2..c31e4700 100644 --- a/react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx @@ -1,6 +1,6 @@ import KFModal from '@/components/KFModal'; import { ServiceRunStatus } from '@/enums'; -import { useComputingResource } from '@/hooks/useComputingResource'; +import { useSystemResource } from '@/hooks/useComputingResource'; import { type ServiceVersionData } from '@/pages/ModelDeployment/types'; import { getServiceVersionCompareReq } from '@/services/modelDeployment'; import { isEmpty } from '@/utils'; @@ -42,7 +42,7 @@ const formatEnvText = (env: Record) => { function VersionCompareModal({ version1, version2, ...rest }: VersionCompareModalProps) { const [compareData, setCompareData] = useState(undefined); - const getResourceDescription = useComputingResource()[1]; + const getResourceDescription = useSystemResource(); const fields: FiledType[] = useMemo( () => [ diff --git a/react-ui/src/pages/Pipeline/Info/utils.tsx b/react-ui/src/pages/Pipeline/Info/utils.tsx index eccad30c..2feb70c6 100644 --- a/react-ui/src/pages/Pipeline/Info/utils.tsx +++ b/react-ui/src/pages/Pipeline/Info/utils.tsx @@ -70,15 +70,6 @@ export function createMenuItems( } } -export function getInParameterComponent( - parameter: PipelineNodeModelParameter, -): React.ReactNode | null { - if (parameter.value) { - } - - return null; -} - // 判断是否允许输入 export function canInput(parameter: PipelineNodeModelParameter) { const { type, item_type } = parameter; @@ -87,6 +78,9 @@ export function canInput(parameter: PipelineNodeModelParameter) { (item_type === 'dataset' || item_type === 'model' || item_type === 'image' || - item_type === 'code') + item_type === 'code' || + item_type === 'remote-dataset' || + item_type === 'remote-model' || + item_type === 'remote-code') ); } diff --git a/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx b/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx index 68691d15..0ceee5d5 100644 --- a/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx +++ b/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx @@ -43,6 +43,17 @@ type PipelineNodeParameterProps = { onFormChange: (data: PipelineNodeModelSerialize) => void; }; +// 自定义的下拉组件类型 +const parameterSelectList = [ + 'dataset', + 'model', + 'service', + 'resource', + 'remote-resource-type', + 'remote-image', + 'remote-resource', +]; + const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParameterProps, ref) => { const [form] = Form.useForm(); const [stagingItem, setStagingItem] = useState( @@ -51,6 +62,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete const [open, setOpen] = useState(false); const [menuItems, setMenuItems] = useState([]); const snap = useSnapshot(state); + const { setCurrentType } = snap; const afterOpenChange = async () => { if (!open) { @@ -125,6 +137,12 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete // 参数下拉菜单 setMenuItems(createMenuItems(params, parentNodes)); + + // 云际组件,设置 store 当前资源类型 + if (model.id.startsWith('remote-task')) { + const resourceType = model.in_parameters['--resource_type'].value; + setCurrentType(resourceType); + } }, close: () => { onClose(); @@ -142,7 +160,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete } }, }), - [form, open], + [form, open, setCurrentType], ); // ref 类型选择 @@ -384,15 +402,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete )} {item.value.type === ComponentType.Select && - ([ - 'dataset', - 'model', - 'service', - 'resource', - 'remote-resource-type', - 'remote-image', - 'remote-resource', - ].includes(item.value.item_type) ? ( + (parameterSelectList.includes(item.value.item_type) ? ( void; getResourceTypes: () => void; getImages: (cardTypes: string[]) => void; getResources: (cardType: string) => void; @@ -89,6 +90,13 @@ const state = proxy({ images: [], resources: [], currentType: undefined, + jccLogin: async () => { + const [res] = await to(jccLoginReq()); + if (res && res.code === 200 && res.data) { + const { tokenHead, token } = res.data; + state.token = tokenHead + token; + } + }, getResourceTypes: async () => { const [loginRes] = await to(jccLoginReq()); if (loginRes && loginRes.code === 200 && loginRes.data) { @@ -116,11 +124,15 @@ const state = proxy({ state.resources = res.data.resource; } }, - setCurrentType: (cardType: string) => { - state.currentType = cardType; - if (cardType) { - state.getImages([cardType]); - state.getResources(cardType); + setCurrentType: (cardType: string | undefined | null) => { + if (state.currentType !== cardType) { + state.currentType = cardType; + state.images = []; + state.resources = []; + if (cardType) { + state.getImages([cardType]); + state.getResources(cardType); + } } }, }); diff --git a/react-ui/src/state/systemResource.ts b/react-ui/src/state/systemResource.ts new file mode 100644 index 00000000..0d7d6b15 --- /dev/null +++ b/react-ui/src/state/systemResource.ts @@ -0,0 +1,53 @@ +/* + * @Author: 赵伟 + * @Date: 2024-10-10 08:51:41 + * @Description: 资源规格 + */ + +import { getComputingResourceReq } from '@/services/pipeline'; +import { ComputingResource } from '@/types'; +import { to } from '@/utils/promise'; +import { proxy } from '@umijs/max'; +import { type SelectProps } from 'antd'; + +/** 过滤资源规格 */ +export const filterResourceStandard: SelectProps['filterOption'] = ( + input: string, + option?: ComputingResource, +) => { + return ( + option?.computing_resource?.toLocaleLowerCase()?.includes(input.toLocaleLowerCase()) ?? false + ); +}; + +/** 资源规格字段 */ +export const resourceFieldNames = { + label: 'description', + value: 'id', +}; + +export interface SystemResourceStore { + resources: ComputingResource[]; +} + +const state = proxy({ + resources: [], +}); + +/** 获取资源列表 */ +export const getSystemResources = async () => { + if (state.resources.length > 0) { + return; + } + const params = { + page: 0, + size: 1000, + resource_type: '', + }; + const [res] = await to(getComputingResourceReq(params)); + if (res && res.data && Array.isArray(res.data.content)) { + state.resources = res.data.content; + } +}; + +export default state;