Browse Source

feat: 流水线组件调整

pull/273/head
zhaowei 6 months ago
parent
commit
c0781e31bb
7 changed files with 119 additions and 85 deletions
  1. +2
    -2
      react-ui/config/proxy.ts
  2. +38
    -37
      react-ui/src/components/ParameterSelect/config.tsx
  3. +69
    -33
      react-ui/src/components/ParameterSelect/index.tsx
  4. +1
    -1
      react-ui/src/components/ResourceSelectorModal/index.tsx
  5. +3
    -3
      react-ui/src/pages/Pipeline/Info/index.jsx
  6. +1
    -3
      react-ui/src/pages/Pipeline/Info/utils.tsx
  7. +5
    -6
      react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx

+ 2
- 2
react-ui/config/proxy.ts View File

@@ -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,


+ 38
- 37
react-ui/src/components/ParameterSelect/config.tsx View File

@@ -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,
}, },
}; };

+ 69
- 33
react-ui/src/components/ParameterSelect/index.tsx View File

@@ -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


+ 1
- 1
react-ui/src/components/ResourceSelectorModal/index.tsx View File

@@ -251,7 +251,7 @@ function ResourceSelectorModal({
} }
: { : {
activeTab: activeTab, activeTab: activeTab,
id,
id: Number(id),
name, name,
path: versionPath, path: versionPath,
version, version,


+ 3
- 3
react-ui/src/pages/Pipeline/Info/index.jsx View File

@@ -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
- 3
react-ui/src/pages/Pipeline/Info/utils.tsx View File

@@ -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,


+ 5
- 6
react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx View File

@@ -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,


Loading…
Cancel
Save