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

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

@ -1,172 +1,26 @@
import React, { useState, useEffect } from 'react'; import React from 'react';
import { NodeEditorProps } from './index'; import { NodeEditorProps } from './index';
import { Input, Select, Typography, Table, Button } from '@arco-design/web-react'; import { Typography } from '@arco-design/web-react';
import { IconUnorderedList, IconDelete } from '@arco-design/web-react/icon'; import { IconUnorderedList } from '@arco-design/web-react/icon';
import ParamsTable from './ParamsTable';
const EndNodeEditor: React.FC<NodeEditorProps> = ({ const EndNodeEditor: React.FC<NodeEditorProps> = ({
node, node,
nodeData, nodeData,
updateNodeData 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 ( return (
<> <>
<Typography.Title heading={5}><IconUnorderedList style={{ marginRight: 5 }} /></Typography.Title> <Typography.Title heading={5}><IconUnorderedList style={{ marginRight: 5 }} /></Typography.Title>
<Table columns={columns} data={data} pagination={false} /> <ParamsTable
<Button initialData={nodeData.parameters.dataIns || []}
style={{ height: 45 }} onUpdateData={(data) => {
long updateNodeData('parameters', {
type="outline" ...nodeData.parameters,
onClick={addRow} dataIns: data
> });
+ }}
</Button> />
</> </>
); );
}; };

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

Loading…
Cancel
Save