import React, { ForwardedRef, forwardRef, ReactNode, useCallback, useImperativeHandle, useMemo, useState } from 'react'; import { useMount } from '@fortissimo/hook'; import type { SizeType } from 'antd/lib/config-provider/SizeContext'; import type { DataListOptConfig, OptFormField } from '../index'; import { DataList } from '../index'; export type DataSimpleListProOptPosition = 'header' | 'row' | 'both'; export interface DataSimpleListProOptConfig extends DataListOptConfig { position?: DataSimpleListProOptPosition; } export interface DataSimpleListProOptParams< K extends string = string, T = any > { optKey: K; rowKey?: number; rowData?: T; } export type DataSimpleListProSearchConfig = Partial< Omit< OptFormField<{ data: T }>, | 'key' | 'name' | 'required' | 'labelCol' | 'labelTip' | 'editComponent' | 'showComponent' | 'editValuePropName' | 'showValuePropName' > >; export interface DataSimpleListProGetDataParams { pageNo?: number; pageSize?: number; searchData?: T; } export interface DataSimpleListProGetDataRes { total: number; data: T[]; } export interface DataSimpleListProProps { msgRender?: (value: T, index: number) => ReactNode; search?: DataSimpleListProSearchConfig; opts?: DataSimpleListProOptConfig[]; canExport?: boolean; canTotalExport?: boolean; resetPageNo?: boolean; hideSizeChanger?: boolean; autoHidePage?: boolean; size?: SizeType; emptyText?: string; onGetData?: ( params: DataSimpleListProGetDataParams ) => Promise>; onExportData?: (params: T) => Promise; onOpt?: (params: DataSimpleListProOptParams) => Promise | void; } export const DataSimpleListPro = forwardRef(function ( props: DataSimpleListProProps, ref: ForwardedRef ) { const [pageNo, setPageNo] = useState(1); const [pageSize, setPageSize] = useState(10); const [total, setTotal] = useState(0); const [data, setData] = useState([]); const [searchData, setSearchData] = useState(); const opts = useMemo(() => { const data: { header: DataListOptConfig[]; row: DataListOptConfig[]; } = { header: [], row: [] }; if (!props.opts) return data; props.opts.forEach((item) => { if (item.position === 'header' || item.position === 'both') { data.header.push(item); } if (item.position === 'row' || item.position === 'both') { data.row.push({ ...item, icon: undefined }); } }); return data; }, [props.opts]); const getData = useCallback( async (params: DataSimpleListProGetDataParams) => { if (!props.onGetData) return; const reqPageNo = params.pageNo || pageNo; const reqPageSize = params.pageSize || pageSize; const data: DataSimpleListProGetDataParams = { pageNo: reqPageNo, pageSize: reqPageSize, searchData: Reflect.has(params, 'searchData') ? params.searchData : searchData }; const res = await props.onGetData(data); const maxPageNo = Math.ceil(res.total / reqPageSize); if (maxPageNo > 0 && maxPageNo < reqPageNo) { await getData({ pageNo: maxPageNo }); setPageNo(maxPageNo); } else { setTotal(res.total); setData(res.data); } }, [pageNo, pageSize, searchData, props] ); const [exportLoading, setExportLoading] = useState(false); const [exportDisabled, setExportDisabled] = useState(!props.canTotalExport); const exportData = useCallback( async (params?: any) => { if (!props.onExportData) return; const data = params || searchData; setExportLoading(true); try { await props.onExportData(data); setExportLoading(false); } catch (e) { setExportLoading(false); } }, [searchData, props] ); const opt = useCallback( async (params: DataSimpleListProOptParams) => { props.onOpt && (await props.onOpt(params)); }, [props] ); useImperativeHandle(ref, () => ({ getData, opt })); useMount(async () => { await getData({ pageNo: 1 }); }); return ( <> { const data = formData.data; setSearchData(data); if (optKey === 'export') await exportData(data); else { if (optKey === 'reset' && !props.canTotalExport) { setExportDisabled(!data); } const resetPageNo = 1; setPageNo(resetPageNo); await getData({ pageNo: resetPageNo, searchData: data }); } }} headerOpts={opts.header} onHeaderOpt={async (optKey) => { await opt({ optKey }); }} /> { await opt({ optKey, rowKey, rowData }); }} render={props.msgRender} /> { let pageNoData = newPageNo; if (newPageSize !== pageSize && props.resetPageNo) pageNoData = 1; setPageNo(pageNoData); setPageSize(newPageSize); await getData({ pageNo: pageNoData, pageSize: newPageSize }); }} /> ); });