refactor(flowEditor): 抽离参数表格组件

- 从 EndNodeEditor 和 StartNodeEditor 中提取公共的参数表格逻辑
- 新增 ParamsTable 组件用于渲染参数表格
- 优化了参数表格的添加、编辑和删除功能- 统一了参数表格的样式和交互
master
钟良源 5 months ago
parent 9a4187a8c3
commit 2e5c6bc70b

@ -1,174 +1,28 @@
import React, { useState, useEffect } from 'react';
import React from 'react';
import { NodeEditorProps } from './index';
import { Input, Select, Typography, Table, Button } from '@arco-design/web-react';
import { IconUnorderedList, IconDelete } from '@arco-design/web-react/icon';
import { Typography } from '@arco-design/web-react';
import { IconUnorderedList } from '@arco-design/web-react/icon';
import ParamsTable from './ParamsTable';
const EndNodeEditor: React.FC<NodeEditorProps> = ({
node,
nodeData,
updateNodeData
}) => {
const [data, setData] = useState([]);
useEffect(() => {
// 为现有数据添加key属性如果不存在
const dataWithKeys = nodeData.parameters.dataIns?.map((item, index) => ({
...item,
key: item.key ?? index
})) || [];
setData(dataWithKeys);
}, [nodeData]);
const dataTypeOptions = [
{ label: '字符串', value: 'string' },
{ label: '数字', value: 'number' },
{ label: '布尔值', value: 'boolean' },
{ label: '数组', value: 'array' },
{ label: '对象', value: 'object' }
];
const arrayTypeOptions = [
{ label: '字符串数组', value: 'string' },
{ label: '数字数组', value: 'number' },
{ label: '布尔数组', value: 'boolean' }
];
const columns = [
{
title: '标识',
dataIndex: 'id',
render: (_, record) => (
<Input
value={record.id}
onChange={(value) => handleSave({ ...record, id: value })}
/>
)
},
{
title: '数据类型',
dataIndex: 'dataType',
render: (_, record) => (
<Select
autoWidth={{ minWidth: 200, maxWidth: 500 }}
options={dataTypeOptions}
value={record.dataType}
onChange={(value) => handleSave({ ...record, dataType: value })}
placeholder="请选择数据类型"
/>
)
},
{
title: '数组类型',
dataIndex: 'arrayType',
render: (_, record) => (
record.dataType === 'array' ? (
<Select
autoWidth={{ minWidth: 200, maxWidth: 500 }}
options={arrayTypeOptions}
value={record.arrayType}
onChange={(value) => handleSave({ ...record, arrayType: value })}
placeholder="请选择数组类型"
/>
) : (
<span></span>
)
)
},
{
title: '描述',
dataIndex: 'desc',
render: (_, record) => (
<Input
value={record.desc}
onChange={(value) => handleSave({ ...record, desc: value })}
/>
)
},
{
title: '默认值',
dataIndex: 'defaultValue',
render: (_, record) => (
<Input
value={record.defaultValue}
onChange={(value) => handleSave({ ...record, defaultValue: value })}
/>
)
},
{
title: '操作',
dataIndex: 'op',
render: (_, record) => (
<Button onClick={() => removeRow(record.key)} type="text" status="danger">
<IconDelete />
</Button>
)
}
];
const handleSave = (row) => {
const newData = [...data];
const index = newData.findIndex((item) => row.key === item.key);
if (index >= 0) {
newData.splice(index, 1, { ...newData[index], ...row });
}
else {
newData.push(row);
}
setData(newData);
// 更新节点数据
updateNodeData('parameters', {
...nodeData.parameters,
dataIns: newData
});
};
const removeRow = (key) => {
const newData = data.filter((item) => item.key !== key);
setData(newData);
// 更新节点数据
updateNodeData('parameters', {
...nodeData.parameters,
dataIns: newData
});
};
const addRow = () => {
const newKey = Date.now();
const newRow = {
key: newKey,
id: '',
dataType: '',
arrayType: '',
desc: '',
defaultValue: ''
};
const newData = [...data, newRow];
setData(newData);
// 更新节点数据
updateNodeData('parameters', {
...nodeData.parameters,
dataIns: newData
});
};
return (
<>
<Typography.Title heading={5}><IconUnorderedList style={{ marginRight: 5 }} /></Typography.Title>
<Table columns={columns} data={data} pagination={false} />
<Button
style={{ height: 45 }}
long
type="outline"
onClick={addRow}
>
+
</Button>
<ParamsTable
initialData={nodeData.parameters.dataIns || []}
onUpdateData={(data) => {
updateNodeData('parameters', {
...nodeData.parameters,
dataIns: data
});
}}
/>
</>
);
};
export default EndNodeEditor;
export default EndNodeEditor;

@ -0,0 +1,171 @@
import React, { useState, useEffect } from 'react';
import { Input, Select, Table, Button } from '@arco-design/web-react';
import { IconDelete } from '@arco-design/web-react/icon';
interface TableDataItem {
key: number | string;
id: string;
dataType: string;
arrayType: string;
desc: string;
defaultValue: string;
[key: string]: any; // 允许其他自定义字段
}
interface EndNodeTableProps {
initialData: TableDataItem[];
onUpdateData: (data: TableDataItem[]) => void;
}
const EndNodeTable: React.FC<EndNodeTableProps> = ({
initialData,
onUpdateData
}) => {
const [data, setData] = useState<TableDataItem[]>([]);
useEffect(() => {
// 为现有数据添加key属性如果不存在
const dataWithKeys = initialData?.map((item, index) => ({
...item,
key: item.key ?? index
})) || [];
setData(dataWithKeys);
}, [initialData]);
const dataTypeOptions = [
{ label: '字符串', value: 'string' },
{ label: '数字', value: 'number' },
{ label: '布尔值', value: 'boolean' },
{ label: '数组', value: 'array' },
{ label: '对象', value: 'object' }
];
const arrayTypeOptions = [
{ label: '字符串数组', value: 'string' },
{ label: '数字数组', value: 'number' },
{ label: '布尔数组', value: 'boolean' }
];
const columns = [
{
title: '标识',
dataIndex: 'id',
render: (_: any, record: TableDataItem) => (
<Input
value={record.id}
onChange={(value) => handleSave({ ...record, id: value })}
/>
)
},
{
title: '数据类型',
dataIndex: 'dataType',
render: (_: any, record: TableDataItem) => (
<Select
autoWidth={{ minWidth: 200, maxWidth: 500 }}
options={dataTypeOptions}
value={record.dataType}
onChange={(value) => handleSave({ ...record, dataType: value })}
placeholder="请选择数据类型"
/>
)
},
{
title: '数组类型',
dataIndex: 'arrayType',
render: (_: any, record: TableDataItem) => (
record.dataType === 'array' ? (
<Select
autoWidth={{ minWidth: 200, maxWidth: 500 }}
options={arrayTypeOptions}
value={record.arrayType}
onChange={(value) => handleSave({ ...record, arrayType: value })}
placeholder="请选择数组类型"
/>
) : (
<span></span>
)
)
},
{
title: '描述',
dataIndex: 'desc',
render: (_: any, record: TableDataItem) => (
<Input
value={record.desc}
onChange={(value) => handleSave({ ...record, desc: value })}
/>
)
},
{
title: '默认值',
dataIndex: 'defaultValue',
render: (_: any, record: TableDataItem) => (
<Input
value={record.defaultValue}
onChange={(value) => handleSave({ ...record, defaultValue: value })}
/>
)
},
{
title: '操作',
dataIndex: 'op',
render: (_: any, record: TableDataItem) => (
<Button onClick={() => removeRow(record.key)} type="text" status="danger">
<IconDelete />
</Button>
)
}
];
const handleSave = (row: TableDataItem) => {
const newData = [...data];
const index = newData.findIndex((item) => row.key === item.key);
if (index >= 0) {
newData.splice(index, 1, { ...newData[index], ...row });
}
else {
newData.push(row);
}
setData(newData);
onUpdateData(newData);
};
const removeRow = (key: number | string) => {
const newData = data.filter((item) => item.key !== key);
setData(newData);
onUpdateData(newData);
};
const addRow = () => {
const newKey = Date.now();
const newRow = {
key: newKey,
id: '',
dataType: '',
arrayType: '',
desc: '',
defaultValue: ''
};
const newData = [...data, newRow];
setData(newData);
onUpdateData(newData);
};
return (
<>
<Table columns={columns} data={data} pagination={false} />
<Button
style={{ height: 45 }}
long
type="outline"
onClick={addRow}
>
+
</Button>
</>
);
};
export default EndNodeTable;

@ -1,27 +1,28 @@
import React from 'react';
import { NodeEditorProps } from './index';
import { Form, Input } from '@arco-design/web-react';
import { Typography } from '@arco-design/web-react';
import { IconUnorderedList } from '@arco-design/web-react/icon';
import ParamsTable from './ParamsTable';
const StartNodeEditor: React.FC<NodeEditorProps> = ({
node,
nodeData,
updateNodeData
}) => {
node,
nodeData,
updateNodeData
}) => {
return (
<Form layout="vertical">
<Form.Item label="节点标题">
<Input
value={nodeData.title || ''}
onChange={(value) => updateNodeData('title', value)}
/>
</Form.Item>
<Form.Item label="描述">
<Input.TextArea
value={nodeData.description || ''}
onChange={(value) => updateNodeData('description', value)}
/>
</Form.Item>
</Form>
<>
<Typography.Title heading={5}><IconUnorderedList style={{ marginRight: 5 }} /></Typography.Title>
<ParamsTable
initialData={nodeData.parameters.dataOuts || []}
onUpdateData={(data) => {
updateNodeData('parameters', {
...nodeData.parameters,
dataOuts: data
});
}}
/>
</>
);
};

Loading…
Cancel
Save