目录结构
import React, { useEffect, useState } from 'react';
import { Button, Card, Table } from 'antd';
import SearchForm from './SearchForm';
const UseTable = (props) => {
const {
request,
tableProps,
onClickNewBtn,
showNewBtn,
disableNewBtn,
search,
} = props;
const [loading, setLoading] = useState(true);
const [current, setCurrent] = useState(1);
const [size, setSize] = useState(10);
const [total, setTotal] = useState(0);
const getData = (values) => {
request(current, size, values)
.then((res) => {
setTotal(res?.total);
setLoading(false);
})
.catch(() => {
setLoading(false);
});
};
const paginationProps = {
showQuickJumper: true,
showSizeChanger: true,
total,
onShowSizeChange: (page, pageSize) => {
setCurrent(page);
setSize(pageSize);
},
showTotal: (totals) => `共${totals}条记录`,
onChange: (page, pageSize) => {
setCurrent(page);
setSize(pageSize);
},
};
useEffect(() => {
getData();
}, [current, size]);
return (
<Card>
{search && <SearchForm getData={getData} columns={tableProps?.columns} />}
{showNewBtn && (
<Button
type="primary"
onClick={showNewBtn && onClickNewBtn}
disabled={disableNewBtn}
>
新增
</Button>
)}
<Table
rowKey={(record) => record.id}
loading={loading}
{/* 通过新申明将默认项覆盖 */}
pagination={{ ...paginationProps, ...tableProps?.paginationProps }}
style={{ marginTop: 20 }}
{/* 放最后方便对上面的props覆盖 */}
{...tableProps}
/>
</Card>
);
};
UseTable.defaultProps = {
showNewBtn: true,
disableNewBtn: false,
search: true,
};
export default UseTable;
import React, { useState } from 'react';
import { Button, Col, Form, Input, Row, Icon } from 'antd';
const FormItem = Form.Item;
const SearchForm = (props) => {
const [paramExpand, setParamExpand] = useState();
const { form, getData, columns } = props;
const { getFieldDecorator } = form;
const formItemLayout = {
labelCol: { span: 7 },
wrapperCol: { span: 15 },
};
const setExpand = (expand) => {
setParamExpand(expand);
};
const handleSearch = (e) => {
if (e) e.preventDefault();
form.validateFields({ force: true }, (err, values) => {
getData(values);
});
};
const handleFormReset = () => {
form.resetFields();
handleSearch();
};
const renderFormItem = () => {
return (
<>
{columns?.map((item) => {
const { hideSearch = true } = item;
if (item?.renderSearchItem) {
return (
<Col md={8} sm={24} key={item?.dataIndex}>
<FormItem label={item?.searchTitle || item?.title}>
{getFieldDecorator(item?.searchIndex || item?.dataIndex)(
item?.renderSearchItem(),
)}
</FormItem>
</Col>
);
}
return (
hideSearch && (
<Col md={8} sm={24} key={item?.dataIndex}>
<FormItem label={item?.searchTitle || item?.title}>
{getFieldDecorator(item?.searchIndex || item?.dataIndex)(
<Input placeholder="请输入" />,
)}
</FormItem>
</Col>
)
);
})}
</>
);
};
return (
<Form {...formItemLayout} onSubmit={handleSearch}>
<Row gutter={24}>
{/* 展开前默认取两项,展开后显示全部。通过children进行dom渲染 */}
{paramExpand ? (
renderFormItem()?.props?.children.map((item) => item)
) : (
<>
{renderFormItem()
?.props?.children?.slice(0, 2)
?.map((item) => item)}
<Col
className={styles.submitButtons}
md={8}
sm={24}
style={{ lineHeight: '40px' }}
>
<span>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button
style={{ marginLeft: 8, marginRight: 8 }}
onClick={handleFormReset}
>
重置
</Button>
<a
style={{ fontSize: 12 }}
onClick={() => {
setExpand(!paramExpand);
}}
>
{paramExpand ? (
<Icon type="up" style={{ marginRight: '4px' }} />
) : (
<Icon type="down" style={{ marginRight: '4px' }} />
)}
{paramExpand ? '收起' : '展开'}
</a>
</span>
</Col>
</>
)}
</Row>
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
{paramExpand && (
<Col
className={styles.submitButtons}
style={{ float: 'right' }}
md={6}
sm={24}
>
<span>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button
style={{ marginLeft: 8, marginRight: 8 }}
onClick={handleFormReset}
>
重置
</Button>
<a
style={{ fontSize: 12 }}
onClick={() => {
setExpand(!paramExpand);
}}
>
{paramExpand ? (
<Icon type="up" style={{ marginRight: '4px' }} />
) : (
<Icon type="down" style={{ marginRight: '4px' }} />
)}
{paramExpand ? '收起' : '展开'}
</a>
</span>
</Col>
)}
</Row>
</Form>
);
};
export default Form.create()(SearchForm);
组件的使用
import React, { useState } from 'react';
import { Select } from 'antd';
import UseTable from '@/components/UseTable';
const { Option } = Select;
const Demo = (props) => {
const [dataSource, setDataSource] = useState([]);
const columns = [
{
title: 'id',
dataIndex: 'id',
searchIndex: '自定义字段',
searchTitle: '自定义头',
renderSearchItem: () => {
return (
<Select>
<Option value="1">s</Option>
<Option value="2">2</Option>
</Select>
);
},
},
{
title: '用户id',
dataIndex: 'userId',
},
{
title: '公司名称',
dataIndex: 'tenantChineseName',
hideSearch: false,
},
{
title: '用户名',
dataIndex: 'userName',
},
];
return (
<UseTable
request={async (current, size, values) => {
const res = await api({
pageSize: size,
pageNum: current,
...values,
});
if (res?.recode === '000000') {
setDataSource(res?.data?.records);
return Promise.resolve({ total: res?.data?.total });
}
return Promise.reject();
}}
tableProps={{
columns,
bordered: true,
dataSource,
paginationProps: { pageSizeOptions: ['2', '10'] },
}}
onClickNewBtn={() => {
props.history.push({
pathname: '/test',
});
}}
/>
);
};
export default Demo;
个人博客-记录各种前端问题