区别于可编辑的表格,对于可编辑的表格,是每编辑一行,则调用接口保存数据;保存之后,再操作下一行数据。
直接增删表格项的话,是可以同时修改,之后在获取表格所有数据即可。
代码:
interface Props {
ruleItems: TagRuleItem[];
}
export interface TagRuleItem {
identi_path: string;
converter: string;
op: string;
expected: string;
index: number; // 需要手动添加 index, 作为每一项的唯一标识
}
function RuleTable(props: Props, ref: any) {
const { ruleItems } = props;
const [ruleList, setRuleList] = useState<TagRuleItem[]>(ruleItems);
const [converterOpts, setConverterOpts] = useState<OptionType[]>([]);
const [opOpts, setOpOpts] = useState<OptionType[]>([]);
// 检测数据是否完整
const checkValue = (arr: TagRuleItem[]) => {
return arr.some((item) => {
return Object.keys(item).some((key) => !item[key]);
});
};
// 对外提供数据
useImperativeHandle(ref, () => ({
getTableValue: () => {
if (checkValue(ruleList)) {
message.error('请检查表格项是否填写完整');
return null;
}
return ruleList;
},
}));
// 添加表格项
const addRuleItem = () => {
// 以最后一项的index为基准,+1,作为新增表格项的唯一index
const index = ruleList.length > 0 ? (ruleList[(ruleList?.length || 1) - 1]?.index || 0) + 1 : 0;
setRuleList([
...ruleList,
{
index, // 关键点
identi_path: '',
converter: '',
op: '',
expected: '',
},
]);
};
// 删除表格项
const removeRuleItem = (index: number) => {
const arrIndex = ruleList.findIndex((rule) => rule.index === index);
if (arrIndex === -1) {
return;
}
setRuleList([...ruleList.slice(0, arrIndex), ...ruleList.slice(arrIndex + 1)]);
};
// 监听表格项值的变化
const onChangedRuleItem = (key: string, value: string, index: number) => {
const ruleItem = ruleList.find((rule) => rule.index === index);
ruleItem[key] = value; // 关键点
setRuleList([...ruleList]); // 关键点,更新 ruleList 数据
};
const columns = [
{
title: '序号',
dataIndex: 'index',
render: (text: string, record: TagRuleItem, index: number) => {
return index + 1;
},
},
{
title: '路径',
dataIndex: 'identi_path',
render: (text: string, record: TagRuleItem) => {
return (
<Space>
<Input
disabled={!text}
value={text}
onChange={(e) => onChangedRuleItem('identi_path', e.target.value, record.index)}
/>
<SelectOutlined
style={{
color: '#1890ff',
}}
onClick={() => {}}
/>
</Space>
);
},
},
{
title: '转换函数',
dataIndex: 'converter',
render: (text: string, record: TagRuleItem) => {
return (
<Select
options={converterOpts}
value={text}
onChange={(value) => onChangedRuleItem('converter', value, record.index)}
/>
);
},
},
{
title: '操作符',
dataIndex: 'op',
render: (text: string, record: TagRuleItem) => {
return (
<Select options={opOpts} value={text} onChange={(value) => onChangedRuleItem('op', value, record.index)} />
);
},
},
{
title: '期待值',
dataIndex: 'expected',
render: (text: string, record: TagRuleItem) => {
return <Input value={text} onChange={(e) => onChangedRuleItem('expected', e.target.value, record.index)} />;
},
},
{
title: '操作',
dataIndex: 'action',
render: (text: any, record: TagRuleItem, index: number) => (
<Space>
<PlusCircleOutlined onClick={addRuleItem} />
{index > 0 && <MinusCircleOutlined onClick={() => removeRuleItem(record.index)} />}
</Space>
),
},
];
return (
<Table
sticky
scroll={{ x: '100%' }}
columns={columns}
rowKey={(record: any) => record.trace_id}
dataSource={ruleList}
pagination={false}
/>
);
}
export default forwardRef(RuleTable);
效果图: