sailei1 / blog

1 stars 0 forks source link

antd mini proTable #116

Closed sailei1 closed 2 years ago

sailei1 commented 2 years ago
import React, { useState, useEffect, useRef } from 'react';
import 'antd/dist/antd.css';
import {
  Table,
  Space,
  Popover,
  Tooltip,
  Tree,
  Form,
  Row,
  Col,
  Button,
  Divider,
  Input,
  Pagination,
  TreeNode,
} from 'antd';
import useATRH from 'use-antd-resizable-header';
import 'use-antd-resizable-header/dist/style.css';
import { SettingOutlined } from '@ant-design/icons';

const ResizableTable = (props) => {
  const {
    columns = [],
    request,
    headerTitle = 'title',
    pagination = {
      showSizeChanger: true,
      // showTotal:true,
    },
  } = props;
  const { components, resizableColumns, tableWidth } = useATRH({ columns, minConstraints: 50 });
  const [columnsMap, setColumnsMap] = useState({});
  const [showColumns, setShowColumns] = useState([]);
  const selectKey = useRef([]);

  const [allColumns, setAllColumns] = useState([]);
  const [form] = Form.useForm();
  const [dataSource, setDataSource] = useState([]);
  const [total, setTotal] = useState(0);
  const [current, setCurrent] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const onFinish = (values) => {
    const obj = { ...values };
    if (pagination !== false) {
      obj.current = current;
      obj.pageSize = pageSize;
    }
    request &&
      request(obj)
        .then((res) => {
          setDataSource(res.data);
          setTotal(res.total);
        })
        .catch((rej) => {
          console.log(rej);
        });
  };
  const changePage = (val1, val2) => {
    setCurrent(val1);
    setPageSize(val2);
    form.submit();
  };
  // 获取formitem
  const getFields = () => {
    const arr = [];
    for (let i = 0; i < columns.length; i += 1) {
      if (!columns[i].hideInSearch || columns[i].hideInSearch !== true) {
        arr.push(
          <Col span={8} key={i}>
            <Form.Item name={columns[i].key || columns[i].dataIndex} label={columns[i].title}>
              {columns[i].renderFormItem ? columns[i].renderFormItem() : <Input></Input>}
            </Form.Item>
          </Col>,
        );
      }
    }
    return arr;
  };

  useEffect(() => {
    let cols = [];
    resizableColumns.map((item) => {
      item.key = item.title;
      if (item.hideInTable) {
        return;
      }
      if (columnsMap[item.key]?.show) {
        if (columnsMap[item.key]?.order > -1) {
          cols[`${columnsMap[item.key].order}`] = item;
        } else {
          cols.push(item);
        }
      }
    });
    setShowColumns(cols);
  }, [resizableColumns, columnsMap]);
  useEffect(() => {
    let treeDataConfig = [];
    const map = {};
    resizableColumns.map((item) => {
      item.key = item.title;
      map[item.title] = { show: true };
      treeDataConfig.push(item.title);
    });
    selectKey.current = treeDataConfig;
    setColumnsMap(map);
    setShowColumns(resizableColumns);
    setAllColumns(resizableColumns);
    form.submit();
  }, []);

  const move = (dragKey, dropKey, dropPosition) => {
    const newColumns = [...allColumns];
    const newMap = { ...columnsMap };
    const findIndex = newColumns.findIndex((item) => {
      return item.key == dragKey;
    });
    const targetIndex = newColumns.findIndex((item) => {
      return item.key == dropKey;
    });
    const isDownWord = dropPosition > findIndex;
    if (findIndex < 0) {
      return;
    }
    const targetItem = newColumns[findIndex];
    newColumns.splice(findIndex, 1);
    if (dropPosition === 0) {
      newColumns.unshift(targetItem);
    } else {
      newColumns.splice(isDownWord ? targetIndex : targetIndex + 1, 0, targetItem);
    }
    // // 重新生成排序数组
    newColumns.forEach((item, order) => {
      newMap[item.key] = { ...(newMap[item.key] || {}), order };
    });
    // // 更新数组
    setColumnsMap(newMap);
    setAllColumns(newColumns);
  };

  const content = () => {
    return (
      <>
        <Tree
          checkable
          blockNode
          treeData={allColumns}
          checkedKeys={selectKey.current}
          draggable={true}
          onDrop={(info) => {
            const dropKey = info.node.key;
            const dragKey = info.dragNode.key;
            const { dropPosition, dropToGap } = info;
            const position = dropPosition === -1 || !dropToGap ? dropPosition + 1 : dropPosition;
            move(dragKey, dropKey, position);
          }}
          onCheck={(select, e) => {
            if (select.length > 0) {
              const columnKey = e.node.key;
              const tempConfig = columnsMap[columnKey] || {};
              const newSetting = { ...tempConfig };
              if (e.checked) {
                newSetting.show = true;
              } else {
                newSetting.show = false;
              }
              selectKey.current = select;
              const map = {
                ...columnsMap,
                [columnKey]: newSetting,
              };
              setColumnsMap(map);
            }
          }}
        />
      </>
    );
  };

  return (
    <>
      <Form
        form={form}
        name="advanced_search"
        className="ant-advanced-search-form"
        onFinish={onFinish}
        labelCol={{ style: { width: '120px' } }}
      >
        <Row gutter={24} className="search-item">
          {getFields()}
        </Row>
        <Row>
          <Col span={24} style={{ textAlign: 'right' }}>
            <Button
              key="searchText"
              type="primary"
              onClick={() => {
                form.submit();
              }}
              style={{ marginRight: '10px' }}
            >
              查询
            </Button>
            <Button
              key="resetText"
              onClick={() => {
                form.resetFields();
              }}
            >
              重置
            </Button>
          </Col>
        </Row>
      </Form>
      <Divider style={{ margin: '10px 0' }} />
      <Row style={{ padding: '16px' }}>
        <Col span={4} style={{ textAlign: 'left' }}>
          {headerTitle}
        </Col>
        <Col span={20}>
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <Popover
              arrowPointAtCenter
              title="列设置"
              trigger="click"
              placement="bottomRight"
              content={content}
            >
              <Tooltip placement="topLeft" title="列设置" arrowPointAtCenter>
                <SettingOutlined style={{ margin: '0, 16px' }} />
              </Tooltip>
            </Popover>
          </div>
        </Col>
      </Row>

      <Table
        {...props}
        columns={showColumns}
        dataSource={dataSource}
        bordered
        size="middle"
        components={components}
        scroll={{ x: tableWidth }}
        pagination={
          pagination === false
            ? false
            : {
                ...pagination,
                onChange: changePage,
                onShowSizeChange: changePage,
                pageSize,
                current,
                total,
              }
        }
      />
    </>
  );
};

export default ResizableTable;