slproj-web/src/components/crud/usePageTable.ts

116 lines
3.0 KiB
TypeScript

import { ListProps, TableProps } from 'antd';
import { useState, useRef, useEffect } from 'react';
import { PageResult, SearchOption } from '../../service/def';
type TableState<T> = {
data: T[];
total: number;
loading: boolean;
pageSize: number;
pageNumber: number;
search: { [key: string]: string };
sort?: [string, 'asc' | 'desc'];
}
export type PageTableContext<T> = {
tableProps: TableProps<T>,
listProps?: ListProps<T>,
search: (params?: SearchOption) => void,
refresh: () => void
}
function usePageTable<T>(
service: (params?: SearchOption) => Promise<PageResult<T>>,
options: SearchOption = {}
): PageTableContext<T> {
// 写在一起避免异步之后多次setState导致多次重绘
const [state, setState] = useState<TableState<T>>(() => ({
data: [],
total: 0,
loading: false,
pageSize: options.pageSize ?? 10,
pageNumber: options.pageNumber ?? 1,
sort: options.sort,
search: options.search || {},
}));
const abort = useRef(false);
useEffect(() => {
abort.current = false;
search();
return () => { abort.current = true; }
}, []);
const search = (opt: SearchOption = {}) => {
setState(s => ({ ...s, loading: true }));
const pageParams = {
pageNumber: opt?.pageNumber ?? state.pageNumber,
pageSize: opt?.pageSize ?? state.pageSize,
sort: opt?.sort ?? state.sort,
search: opt?.search ?? state.search,
};
service(pageParams).then((data) => {
if (!abort.current) {
setState({
...pageParams,
data: data.list,
total: data.totalRow,
loading: false,
})
}
});
}
const handleTableChange = (pagination: any, filters: any, sort: any) => {
search({ pageNumber: pagination.current, pageSize: pagination.pageSize, sort });
}
let listProps = undefined;
if (false) {
const handleListChange = (page: number, pageSize: number) => {
search({ pageNumber: page, pageSize: pageSize });
}
listProps = {
dataSource: state.data,
loading: state.loading,
pagination: {
showTotal: (totalRow: any) => `${totalRow}`,
showSizeChanger: true,
showQuickJumper: true,
pageSize: state.pageSize,
current: state.pageNumber,
total: state.total,
pageSizeOptions: ['10', '20', '50', '100'],
onChange: handleListChange
}
}
}
return {
tableProps: {
size: 'small',
bordered: true,
dataSource: state.data,
pagination: {
showTotal: (totalRow: any) => `${totalRow}`,
showSizeChanger: true,
showQuickJumper: true,
pageSize: state.pageSize,
current: state.pageNumber,
total: state.total,
pageSizeOptions: ['10', '20', '50', '100'],
hideOnSinglePage: true,
},
loading: state.loading,
onChange: handleTableChange,
},
listProps,
search: (params?: SearchOption) => search({ ...params, pageNumber: 1 }),
refresh: search,
}
}
export default usePageTable