likes
comments
collection
share

【避坑指“难”】实现ProTable可编辑的拖拽排序

作者站长头像
站长
· 阅读数 77

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>,
      ]}
    />

【避坑指“难”】实现ProTable可编辑的拖拽排序

拖拽功能

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
评论
请登录