【避坑指“难”】实现ProTable可编辑的拖拽排序
DragSortTable排序采用的react-sortable-hoc,需要提供rowKey来确定数据的唯一值,否则不能正常工作。暂不支持request请求的数据进行排序,可将request请求的数据存起来通过dataSource传入。
⚠️:如果拖拽后列表没有重新排序,很大原因就是没有传入dataSource导致的。所以在request里请求到的数据还需要存入dataSource才行。
ProTable配置
<ProTable
rowKey="index"
columns={columns}
actionRef={actionRef}
form={form}
pagination={{
pageSize: 10,
}}
dataSource={dataSource}
search={true}
request={async (params) => {
const res = await getRuleList(p, {
...params,
orderByPriority: true,
current: 1,
pageSize: 10,
status: 3,
});
const list = res.data.list.map((item: any, index: number) => ({ ...item, index }));
setDataSource(list);
setDisableBtn(list[0].inPriorityAudit);
return {
data: list,
success: res?.success,
total: res?.data?.total,
};
}}
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow,
},
}}
toolBarRender={() => [
<Button
onClick={() => setIsEdit(true)}
type="primary"
disabled={disableBtn}
style={{ display: isEdit ? 'none' : 'block' }}
>
编 辑
</Button>,
<Button
onClick={() => setIsEdit(false)}
type="primary"
style={{ display: isEdit ? 'block' : 'none' }}
>
取消编辑
</Button>,
<Popconfirm
title="确认提交审核吗?"
onConfirm={confirmSubmit}
okText="确认"
cancelText="取消"
>
<Button type="primary" disabled={!isEdit}>
提交审核
</Button>
</Popconfirm>,
<Popconfirm
title="是否审核通过"
onConfirm={async () => {
await client<any>(`审核通过接口`, {
method: 'put',
params: {},
}).then((res) => {
if (res?.success)
notification.success({
message: '审核完成',
});
});
actionRef?.current?.reload();
}}
onCancel={async () => {
await client<any>(`审核失败接口`, {
method: 'put',
params: {},
}).then((res) => {
if (res?.success)
notification.success({
message: '审核完成',
});
});
actionRef?.current?.reload();
}}
okText="通过"
cancelText="拒绝"
>
<Button type="primary" disabled={!disableBtn}>
审 核
</Button>
</Popconfirm>,
]}
/>
拖拽功能
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow,
},
}}
const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
if (oldIndex !== newIndex) {
setIsDrag(true);
const newData = arrayMoveImmutable([...dataSource], oldIndex, newIndex).filter((el) => !!el);
const list = [...newData].map((item: any, index: number) => ({ ...item, index })) as any;
list.map((item: any) => {
obj = {
...obj,
ruleId: item.id,
newPriority: item.index + 1,
};
itemList.push(obj);
setDragList(itemList);
});
setDataSource(list);
}
};
const DraggableContainer = (props: any) => (
<SortContainer
useDragHandle
disableAutoscroll
helperClass="row-dragging"
onSortEnd={onSortEnd}
{...props}
/>
);
const DraggableBodyRow = (props: any) => {
const { className, style, ...restProps } = props;
const index = dataSource.findIndex((x) => x.index === restProps['data-row-key']);
return <SortableItem index={index} {...restProps} />;
}
至此,拖拽排序就可以实现啦。
通过编辑实现拖拽排序
1)InputNumber监听输入框变化
const columns = [
{
title: '规则优先级',
dataIndex: 'businessPriority',
hideInSearch: true,
align: 'center',
render: (text: any, record: any) => {
if (isEdit) {
return (
<div>
<InputNumber
defaultValue={isDrag ? record.index + 1 : record.businessPriority}
onChange={(value: any) => inputChange(value, record)}
/>
</div>
);
} else {
return record.businessPriority;
}
},
},
{
title: 'index',
dataIndex: 'index',
hideInSearch: true,
hideInTable: true,
},
] as any;
2)设置两个状态值,判断是编辑状态or拖拽状态
const [isEdit, setIsEdit] = useState(false);
const [isDrag, setIsDrag] = useState(false);
3)拿到整个Table编辑后的数据,存在itemList数组里
let itemList = [] as any;
let obj = {} as any;
const inputChange = (value: any, record: any) => {
let ruleId;
let newPriority;
if (value) {
obj = {
...obj,
ruleId: record.id,
newPriority: value,
};
for (let i = 0; i < itemList.length; i++) {
if (itemList[i].ruleId === obj.ruleId) {
itemList[i].newPriority = obj.newPriority;
return;
}
}
itemList.push(obj);
}
};
结合编辑功能的拖拽排序,如何过滤重复数据
上述步骤单独使用都是没有问题的,但如果我们拖拽结束后 -> 再编辑输入框
或者 编辑完输入框 -> 再拖拽调整排序
,最后传值的时候,数组里会出现重复的值,类似于如下结构:
[
{id: 1, newIndex: 2},
{id: 2, newIndex: 5},
{id: 1, newIndex: 3} //再一次修改了id为1的排序值
]
这样后端是无法知道id:1的数据的排序值到底是多少,所以我们需要在最后一次操作的时候,将老的排序值替换掉。
1)记录拖拽结束后的数组、编辑结束后的数组
拖拽数组
const [dragList, setDragList] = useState([]);
编辑数组
let itemList = [] as any;
2)提交数据之前先重新赋值
const confirmSubmit = async () => {
console.log('提交的dragList', dragList);
console.log('提交的itemList', itemList);
const result = handleListrepeat(dragList, itemList);
}
const handleListrepeat = (listdrag: any, listItem: any) => {
if (listdrag.length === 0) {
return listItem;
} else if (listItem.length === 0) {
return listdrag;
} else {
for (let i = 0; i < listdrag.length; i++) {
for (let k = 0; k < listItem.length; k++) {
if (listdrag[i].ruleId === listItem[k].ruleId) {
listdrag[i].newPriority = listItem[k].newPriority;
return listdrag;
}
}
}
}
};
最终就能正确的将新排序的数组传给后端啦!
转载自:https://juejin.cn/post/7058454510217199624