packages/table-render/src/core/index.tsx (205 lines of code) (raw):
import React, { useEffect, useRef, useImperativeHandle } from 'react';
import { useForm } from 'form-render';
import { useUpdateEffect } from 'ahooks';
import { useTableStore } from './store';
import { _get, isFunction, isArray } from '../utils';
import { TableRenderProps } from '../types';
import ErrorBoundary from './ErrorBoundary';
import SearchView from './SearchView';
import ToolbarView from './ToolbarView';
import TableView from './TableView';
import './index.less';
type ISearchParams = {
current?: number;
tab?: number | string;
pageSize?: number;
sorter?: any;
};
const RenderCore: React.FC<TableRenderProps & { tableRef: any }> = props => {
const {
search: searchProps,
debug, className,
style,
title,
toolbarRender,
toolbarAction,
tableRef,
request: api,
size,
tableWrapper,
autoRequest = true,
columns,
onTabChange,
...tableProps
} = props;
const { hidden: hiddenSearch } = searchProps || { hidden: true };
const form = useForm();
const rootRef = useRef<HTMLDivElement>(null);
const inited = useTableStore((state) => state.inited);
const currentTab = useTableStore((state) => state.tab);
const tableSize = useTableStore((state) => state.tableSize);
const pagination = useTableStore((state) => state.pagination);
const setState = useTableStore((state) => state.setState);
const getState = useTableStore((state) => state.getState);
const setColumns = useTableStore((state) => state.setColumns);
useEffect(() => {
const initState = {
tableSize: size,
inited: true,
pagination
};
if (typeof tableProps?.pagination === 'object') {
if (tableProps?.pagination?.current) {
initState.pagination.current = tableProps.pagination.current;
}
if (tableProps?.pagination?.pageSize) {
initState.pagination.pageSize = tableProps.pagination.pageSize;
}
}
setState(initState);
}, []);
useEffect(() => {
if (columns) {
setColumns(columns);
}
}, [columns]);
useEffect(() => {
if (inited && hiddenSearch && autoRequest) {
refresh();
}
}, [inited]);
useUpdateEffect(() => {
refresh();
}, [currentTab])
useImperativeHandle(tableRef, () => ({
doSearch,
refresh,
changeTab,
form,
getState: () => ({
...getState(),
search: form.getValues(true)
}),
setState,
}));
const fullScreen = () => {
return Promise.resolve(rootRef.current?.requestFullscreen());
};
const doSearch = (params: ISearchParams, customSearch?: Record<string, any>) => {
const { current, pageSize, tab, sorter, ...extraSearch } = params || {};
const _pageNum = current || 1;
const _pageSize = pageSize || 10;
let _tab: any = currentTab;
if (['string', 'number'].indexOf(typeof tab) > -1) {
_tab = tab;
}
const _pagination = { current: _pageNum, pageSize: _pageSize };
const getTableData = (_api: any) => {
setState({ loading: true });
let _params = {
...form.getValues(true),
...customSearch,
...extraSearch,
..._pagination,
};
Promise.resolve(_api(_params, sorter, { tab: _tab }))
.then(res => {
// TODO:这里校验res是否规范
const { rows, data, total, pageSize, ...extraData } = res;
setState({
loading: false,
dataSource: data || rows,
...extraData,
pagination: {
..._pagination,
total,
pageSize: pageSize || _pageSize,
},
});
searchProps?.afterSearch?.({ data, total, pageSize, ...extraData });
})
.catch(err => {
setState({ loading: false });
});
};
if (isFunction(api)) {
getTableData(api);
return;
}
if (isArray(api)) {
const _api = _get(api, `[${_tab}].api`);
if (isFunction(_api)) {
getTableData(_api);
return;
}
}
console.warn('api 不是函数,检查 <Search /> 的 props');
};
const refresh = (params?: { tab?: string | number; stay?: boolean }, moreSearch?: any) => {
const _stay = (params && params.stay) || false;
const _tab = params && params.tab;
const _search = moreSearch || {};
doSearch(
{
...params,
current: _stay ? pagination.current : 1,
tab: _tab,
pageSize: pagination.pageSize,
},
_search
);
};
const changeTab = (tab: string | number) => {
if (['string', 'number'].indexOf(typeof tab) > -1) {
setState({ tab });
// refresh({ tab });
} else {
console.error('changeTab的入参必须是number或string');
}
};
const tableNode = (
<div
ref={rootRef}
className={`tr-table-wrapper ${className}`}
style={style}
>
<ToolbarView
request={api}
doSearch={doSearch}
refresh={refresh}
fullScreen={fullScreen}
title={title}
tableSize={tableSize}
currentTab={currentTab}
onTabChange={onTabChange}
toolbarAction={toolbarAction}
toolbarRender={toolbarRender}
setState={setState}
getState={getState}
/>
<TableView
{...tableProps}
doSearch={doSearch}
/>
</div>
);
const renderTable = () => {
if (isFunction(tableWrapper)) {
return tableWrapper(tableNode);
}
return tableNode;
};
return (
<div>
<SearchView
{...searchProps}
form={form}
refresh={refresh}
getState={getState}
hidden={hiddenSearch}
/>
<ErrorBoundary>
{renderTable()}
</ErrorBoundary>
</div>
);
}
export default RenderCore;