| @@ -22,8 +22,8 @@ export default { | |||||
| // 要代理的地址 | // 要代理的地址 | ||||
| // target: 'http://172.20.32.197:31213', // 开发环境 | // target: 'http://172.20.32.197:31213', // 开发环境 | ||||
| // target: 'http://172.20.32.235:31213', // 测试环境 | // target: 'http://172.20.32.235:31213', // 测试环境 | ||||
| target: 'http://172.20.32.44:8082', | |||||
| // target: 'http://172.20.32.150:8082', | |||||
| // target: 'http://172.20.32.44:8082', | |||||
| target: 'http://172.20.32.164:8082', | |||||
| // 配置了这个可以从 http 代理到 https | // 配置了这个可以从 http 代理到 https | ||||
| // 依赖 origin 的功能可能需要这个,比如 cookie | // 依赖 origin 的功能可能需要这个,比如 cookie | ||||
| changeOrigin: true, | changeOrigin: true, | ||||
| @@ -1,26 +1,18 @@ | |||||
| import { filterResourceStandard, resourceFieldNames } from '@/hooks/useComputingResource'; | import { filterResourceStandard, resourceFieldNames } from '@/hooks/useComputingResource'; | ||||
| import { DatasetData, ModelData } from '@/pages/Dataset/config'; | |||||
| import { ServiceData } from '@/pages/ModelDeployment/types'; | import { ServiceData } from '@/pages/ModelDeployment/types'; | ||||
| import { getDatasetList, getModelList } from '@/services/dataset/index.js'; | import { getDatasetList, getModelList } from '@/services/dataset/index.js'; | ||||
| import { getServiceListReq } from '@/services/modelDeployment'; | import { getServiceListReq } from '@/services/modelDeployment'; | ||||
| import { type SelectProps } from 'antd'; | import { type SelectProps } from 'antd'; | ||||
| import { pick } from 'lodash'; | |||||
| // id 从 number 转换为 string | |||||
| const convertId = (item: any) => ({ | |||||
| ...item, | |||||
| id: JSON.stringify({ | |||||
| id: `${item.id}`, | |||||
| name: item.name, | |||||
| identifier: item.identifier, | |||||
| owner: item.owner, | |||||
| }), | |||||
| }); | |||||
| export type SelectPropsConfig = { | export type SelectPropsConfig = { | ||||
| getOptions: () => Promise<any>; // 获取下拉数据 | |||||
| getOptions?: () => Promise<any>; // 获取下拉数据 | |||||
| fieldNames?: SelectProps['fieldNames']; // 下拉数据字段 | fieldNames?: SelectProps['fieldNames']; // 下拉数据字段 | ||||
| optionFilterProp?: SelectProps['optionFilterProp']; // 过滤字段名 | optionFilterProp?: SelectProps['optionFilterProp']; // 过滤字段名 | ||||
| filterOption?: SelectProps['filterOption']; // 过滤函数 | filterOption?: SelectProps['filterOption']; // 过滤函数 | ||||
| getValue: (value: any) => string | number; | |||||
| getLabel: (value: any) => string; | |||||
| isObjectValue: boolean; // value 是对象 | |||||
| }; | }; | ||||
| export const paramSelectConfig: Record<string, SelectPropsConfig> = { | export const paramSelectConfig: Record<string, SelectPropsConfig> = { | ||||
| @@ -31,13 +23,16 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||||
| size: 1000, | size: 1000, | ||||
| is_public: false, | is_public: false, | ||||
| }); | }); | ||||
| return res?.data?.content?.map(convertId) ?? []; | |||||
| return res?.data?.content ?? []; | |||||
| }, | |||||
| optionFilterProp: 'label', | |||||
| getValue: (value: DatasetData) => { | |||||
| return value.id; | |||||
| }, | }, | ||||
| fieldNames: { | |||||
| label: 'name', | |||||
| value: 'id', | |||||
| getLabel: (value: DatasetData) => { | |||||
| return value.name; | |||||
| }, | }, | ||||
| optionFilterProp: 'name', | |||||
| isObjectValue: true, | |||||
| }, | }, | ||||
| model: { | model: { | ||||
| getOptions: async () => { | getOptions: async () => { | ||||
| @@ -46,13 +41,16 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||||
| size: 1000, | size: 1000, | ||||
| is_public: false, | is_public: false, | ||||
| }); | }); | ||||
| return res?.data?.content?.map(convertId) ?? []; | |||||
| return res?.data?.content ?? []; | |||||
| }, | }, | ||||
| fieldNames: { | |||||
| label: 'name', | |||||
| value: 'id', | |||||
| optionFilterProp: 'label', | |||||
| getValue: (value: ModelData) => { | |||||
| return value.id; | |||||
| }, | |||||
| getLabel: (value: ModelData) => { | |||||
| return value.name; | |||||
| }, | }, | ||||
| optionFilterProp: 'name', | |||||
| isObjectValue: true, | |||||
| }, | }, | ||||
| service: { | service: { | ||||
| getOptions: async () => { | getOptions: async () => { | ||||
| @@ -60,25 +58,28 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||||
| page: 0, | page: 0, | ||||
| size: 1000, | size: 1000, | ||||
| }); | }); | ||||
| return ( | |||||
| res?.data?.content?.map((item: ServiceData) => ({ | |||||
| label: item.service_name, | |||||
| value: JSON.stringify(pick(item, ['id', 'service_name'])), | |||||
| })) ?? [] | |||||
| ); | |||||
| }, | |||||
| fieldNames: { | |||||
| label: 'label', | |||||
| value: 'value', | |||||
| return res?.data?.content ?? []; | |||||
| }, | }, | ||||
| optionFilterProp: 'label', | optionFilterProp: 'label', | ||||
| getValue: (value: ServiceData) => { | |||||
| return value.id; | |||||
| }, | |||||
| getLabel: (value: ServiceData) => { | |||||
| return value.service_name; | |||||
| }, | |||||
| isObjectValue: true, | |||||
| }, | }, | ||||
| resource: { | resource: { | ||||
| getOptions: async () => { | |||||
| // 不需要这个函数 | |||||
| return []; | |||||
| }, | |||||
| fieldNames: resourceFieldNames, | fieldNames: resourceFieldNames, | ||||
| filterOption: filterResourceStandard as SelectProps['filterOption'], | filterOption: filterResourceStandard as SelectProps['filterOption'], | ||||
| // 不会用到 | |||||
| getValue: () => { | |||||
| return ''; | |||||
| }, | |||||
| // 不会用的 | |||||
| getLabel: () => { | |||||
| return ''; | |||||
| }, | |||||
| isObjectValue: false, | |||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -7,7 +7,7 @@ | |||||
| import { useComputingResource } from '@/hooks/useComputingResource'; | import { useComputingResource } from '@/hooks/useComputingResource'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { Select, type SelectProps } from 'antd'; | import { Select, type SelectProps } from 'antd'; | ||||
| import { useEffect, useState } from 'react'; | |||||
| import { useEffect, useMemo, useState } from 'react'; | |||||
| import FormInfo from '../FormInfo'; | import FormInfo from '../FormInfo'; | ||||
| import { paramSelectConfig } from './config'; | import { paramSelectConfig } from './config'; | ||||
| @@ -36,69 +36,105 @@ function ParameterSelect({ | |||||
| dataType, | dataType, | ||||
| display = false, | display = false, | ||||
| value, | value, | ||||
| isPipeline = false, | |||||
| // isPipeline = false, | |||||
| onChange, | onChange, | ||||
| ...rest | ...rest | ||||
| }: ParameterSelectProps) { | }: ParameterSelectProps) { | ||||
| const [options, setOptions] = useState<SelectProps['options']>([]); | const [options, setOptions] = useState<SelectProps['options']>([]); | ||||
| const propsConfig = paramSelectConfig[dataType]; | const propsConfig = paramSelectConfig[dataType]; | ||||
| const valueText = typeof value === 'object' && value !== null ? value.value : value; | |||||
| const { | |||||
| getLabel, | |||||
| getValue, | |||||
| getOptions, | |||||
| filterOption, | |||||
| fieldNames, | |||||
| optionFilterProp, | |||||
| isObjectValue, | |||||
| } = propsConfig; | |||||
| const selectValue = typeof value === 'object' && value !== null ? value.value : value; | |||||
| // 数据集、模型、服务,对象转换成 json 字符串 | |||||
| const valueText = | |||||
| typeof selectValue === 'object' && selectValue !== null ? getValue(selectValue) : selectValue; | |||||
| const [resourceStandardList] = useComputingResource(); | const [resourceStandardList] = useComputingResource(); | ||||
| const computingResource = isPipeline | |||||
| ? resourceStandardList.map((v) => ({ | |||||
| ...v, | |||||
| id: String(v.id), | |||||
| })) | |||||
| : resourceStandardList; | |||||
| // const computingResource = isPipeline | |||||
| // ? resourceStandardList.map((v) => ({ | |||||
| // ...v, | |||||
| // id: String(v.id), | |||||
| // })) | |||||
| // : resourceStandardList; | |||||
| const objectOptions = useMemo(() => { | |||||
| return options?.map((v) => ({ | |||||
| label: getLabel(v), | |||||
| value: getValue(v), | |||||
| })); | |||||
| }, [getLabel, getValue, options]); | |||||
| const valueMap = useMemo(() => { | |||||
| const map = new Map<string | number, any>(); | |||||
| options?.forEach((v) => { | |||||
| map.set(getValue(v), v); | |||||
| }); | |||||
| return map; | |||||
| }, [options, getValue]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取下拉数据 | // 获取下拉数据 | ||||
| const getSelectOptions = async () => { | const getSelectOptions = async () => { | ||||
| if (!propsConfig) { | |||||
| return; | |||||
| } | |||||
| const getOptions = propsConfig.getOptions; | |||||
| const [res] = await to(getOptions()); | |||||
| if (res) { | |||||
| setOptions(res); | |||||
| if (getOptions) { | |||||
| const [res] = await to(getOptions()); | |||||
| if (res) { | |||||
| setOptions(res); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| getSelectOptions(); | getSelectOptions(); | ||||
| }, [propsConfig]); | |||||
| }, [getOptions]); | |||||
| const selectOptions = dataType === 'resource' ? computingResource : options; | |||||
| const selectOptions = dataType === 'resource' ? resourceStandardList : objectOptions; | |||||
| const handleChange = (text: string) => { | const handleChange = (text: string) => { | ||||
| if (typeof value === 'object' && value !== null) { | |||||
| onChange?.({ | |||||
| ...value, | |||||
| value: text, | |||||
| }); | |||||
| // 数据集、模型、服务,转换成对象 | |||||
| if (isObjectValue) { | |||||
| // 设置为 null 是因为 antv g6 的 bug | |||||
| // 如果值为 undefined 时, graph.changeData(data) 会保留前面的值 | |||||
| const selectValue = text ? valueMap.get(text) : null; | |||||
| if (typeof value === 'object' && value !== null) { | |||||
| onChange?.({ | |||||
| ...value, | |||||
| value: selectValue, | |||||
| }); | |||||
| } else { | |||||
| onChange?.(selectValue); | |||||
| } | |||||
| } else { | } else { | ||||
| onChange?.(text); | |||||
| if (typeof value === 'object' && value !== null) { | |||||
| onChange?.({ | |||||
| ...value, | |||||
| value: text, | |||||
| }); | |||||
| } else { | |||||
| onChange?.(text); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| // 只用于展示,FormInfo 组件带有 Tooltip | // 只用于展示,FormInfo 组件带有 Tooltip | ||||
| if (display) { | if (display) { | ||||
| return ( | return ( | ||||
| <FormInfo | |||||
| select | |||||
| value={valueText} | |||||
| options={selectOptions} | |||||
| fieldNames={propsConfig?.fieldNames} | |||||
| ></FormInfo> | |||||
| <FormInfo select value={valueText} options={selectOptions} fieldNames={fieldNames}></FormInfo> | |||||
| ); | ); | ||||
| } | } | ||||
| return ( | return ( | ||||
| <Select | <Select | ||||
| {...rest} | {...rest} | ||||
| filterOption={propsConfig?.filterOption} | |||||
| options={selectOptions} | options={selectOptions} | ||||
| fieldNames={propsConfig?.fieldNames} | |||||
| optionFilterProp={propsConfig?.optionFilterProp} | |||||
| fieldNames={fieldNames} | |||||
| optionFilterProp={optionFilterProp} | |||||
| filterOption={filterOption} | |||||
| value={valueText} | value={valueText} | ||||
| onChange={handleChange} | onChange={handleChange} | ||||
| showSearch | showSearch | ||||
| @@ -251,7 +251,7 @@ function ResourceSelectorModal({ | |||||
| } | } | ||||
| : { | : { | ||||
| activeTab: activeTab, | activeTab: activeTab, | ||||
| id, | |||||
| id: Number(id), | |||||
| name, | name, | ||||
| path: versionPath, | path: versionPath, | ||||
| version, | version, | ||||
| @@ -3,7 +3,7 @@ import { useStateRef } from '@/hooks/useStateRef'; | |||||
| import { useVisible } from '@/hooks/useVisible'; | import { useVisible } from '@/hooks/useVisible'; | ||||
| import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; | import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; | ||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { fittingString, parseJsonText, s8 } from '@/utils'; | |||||
| import { fittingString, s8 } from '@/utils'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import G6 from '@antv/g6'; | import G6 from '@antv/g6'; | ||||
| import { useNavigate, useParams } from '@umijs/max'; | import { useNavigate, useParams } from '@umijs/max'; | ||||
| @@ -120,8 +120,8 @@ const EditPipeline = () => { | |||||
| const params = { | const params = { | ||||
| ...locationParams, | ...locationParams, | ||||
| name: workflowInfo?.name, | name: workflowInfo?.name, | ||||
| dag: JSON.stringify(data), | |||||
| global_param: JSON.stringify(globalParamRes.global_param), | |||||
| dag: data, | |||||
| global_param: globalParamRes.global_param, | |||||
| }; | }; | ||||
| saveWorkflow(params).then((ret) => { | saveWorkflow(params).then((ret) => { | ||||
| message.success('保存成功'); | message.success('保存成功'); | ||||
| @@ -1,5 +1,4 @@ | |||||
| import { PipelineGlobalParam, PipelineNodeModelParameter } from '@/types'; | import { PipelineGlobalParam, PipelineNodeModelParameter } from '@/types'; | ||||
| import { parseJsonText } from '@/utils'; | |||||
| import { Graph, INode } from '@antv/g6'; | import { Graph, INode } from '@antv/g6'; | ||||
| import { type MenuProps } from 'antd'; | import { type MenuProps } from 'antd'; | ||||
| @@ -42,8 +41,7 @@ export function createMenuItems( | |||||
| ): MenuProps['items'] { | ): MenuProps['items'] { | ||||
| const nodes: MenuProps['items'] = parentNodes.map((item) => { | const nodes: MenuProps['items'] = parentNodes.map((item) => { | ||||
| const model = item.getModel(); | const model = item.getModel(); | ||||
| const out_parameters = model.out_parameters as string | undefined | null; | |||||
| const out_parametersObj = parseJsonText(out_parameters); | |||||
| const out_parametersObj = model.out_parameters as Record<string, PipelineNodeModelParameter>; | |||||
| const outParametersList = Object.keys(out_parametersObj ?? {}); | const outParametersList = Object.keys(out_parametersObj ?? {}); | ||||
| return { | return { | ||||
| key: model.id as string, | key: model.id as string, | ||||
| @@ -23,6 +23,7 @@ import { INode } from '@antv/g6'; | |||||
| import { Button, Drawer, Flex, Form, Input, MenuProps } from 'antd'; | import { Button, Drawer, Flex, Form, Input, MenuProps } from 'antd'; | ||||
| import { RuleObject } from 'antd/es/form'; | import { RuleObject } from 'antd/es/form'; | ||||
| import { NamePath } from 'antd/es/form/interface'; | import { NamePath } from 'antd/es/form/interface'; | ||||
| import { omit } from 'lodash'; | |||||
| import { forwardRef, useImperativeHandle, useState } from 'react'; | import { forwardRef, useImperativeHandle, useState } from 'react'; | ||||
| import PropsLabel from '../PropsLabel'; | import PropsLabel from '../PropsLabel'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -75,8 +76,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| console.log('getFieldsValue', fields); | console.log('getFieldsValue', fields); | ||||
| const res = { | const res = { | ||||
| ...stagingItem, | |||||
| ...fields, | |||||
| ...omit(stagingItem, ['control_strategy', 'task_info', 'in_parameters', 'out_parameters']), | |||||
| task_info: task_info, | task_info: task_info, | ||||
| control_strategy: control_strategy, | control_strategy: control_strategy, | ||||
| in_parameters: in_parameters, | in_parameters: in_parameters, | ||||
| @@ -371,7 +371,6 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| ) : null)} | ) : null)} | ||||
| {item.value.type === ComponentType.Map && ( | {item.value.type === ComponentType.Map && ( | ||||
| <Form.Item name={[parentName, item.key]} rules={getFormRules(item)} noStyle> | <Form.Item name={[parentName, item.key]} rules={getFormRules(item)} noStyle> | ||||
| {' '} | |||||
| <Form.List name={[parentName, item.key, 'value']}> | <Form.List name={[parentName, item.key, 'value']}> | ||||
| {(fields, { add, remove }) => ( | {(fields, { add, remove }) => ( | ||||
| <> | <> | ||||
| @@ -385,7 +384,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| <Form.Item | <Form.Item | ||||
| {...restField} | {...restField} | ||||
| name={[name, 'name']} | name={[name, 'name']} | ||||
| style={{ flex: 1 }} | |||||
| style={{ flex: 1, minWidth: 0 }} | |||||
| dependencies={fields.map((_, i) => [ | dependencies={fields.map((_, i) => [ | ||||
| parentName, | parentName, | ||||
| item.key, | item.key, | ||||
| @@ -429,7 +428,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| <Form.Item | <Form.Item | ||||
| {...restField} | {...restField} | ||||
| name={[name, 'value']} | name={[name, 'value']} | ||||
| style={{ flex: 1 }} | |||||
| style={{ flex: 1, minWidth: 0 }} | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| validator: requiredValidator, | validator: requiredValidator, | ||||
| @@ -447,7 +446,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| title="" | title="" | ||||
| onClick={(value) => { | onClick={(value) => { | ||||
| handleParameterClick( | handleParameterClick( | ||||
| [parentName, item.key, 'list', name, 'value'], | |||||
| [parentName, item.key, 'value', name, 'value'], | |||||
| { | { | ||||
| ...item.value, | ...item.value, | ||||
| value, | value, | ||||