diff --git a/src/hooks/business/use-table.ts b/src/hooks/business/use-table.ts index e0624aa4..7417fd7c 100644 --- a/src/hooks/business/use-table.ts +++ b/src/hooks/business/use-table.ts @@ -1,10 +1,42 @@ import { ref, reactive } from 'vue'; import type { Ref } from 'vue'; import type { DataTableBaseColumn, DataTableSelectionColumn, DataTableExpandColumn, PaginationProps } from 'naive-ui'; -import type { MaybeComputedRef } from '@vueuse/core'; import type { TableColumnGroup, InternalRowData } from 'naive-ui/es/data-table/src/interface'; import { useLoadingEmpty } from '../common'; +/** + * 表格分页参数 + */ +type PaginationParams = Pick; + +/** + * 表格请求接口的参数 + */ +type ApiParams = Record & PaginationParams; + +/** + * 表格请求接口的结果 + * @description 这里用属性list来表示后端接口返回的表格数据 + */ +type ApiData> = Record & { list: TableData[] }; + +/** + * 表格接口的请求函数 + */ +type ApiFn> = ( + params: Params +) => Promise>>; + +/** + * 表格接口请求后转换后的数据 + */ +type TransformedTableData> = { + data: TableData[]; + pageNum: number; + pageSize: number; + total: number; +}; + /** * 表格的列 */ @@ -15,60 +47,45 @@ type DataTableColumn = | DataTableExpandColumn; /** - * 表格分页参数 + * 表格数据转换器 + * @description 将不同接口的表格数据转换成统一的类型 */ -type TablePaginationParams = Pick; +type Transformer> = ( + apiData: ApiData +) => TransformedTableData; -/** - * 表格接口的请求参数 - */ -type TableApiParams = Record & TablePaginationParams; - -/** - * 表格接口的请求数据 - */ -type TableApiData = { - data: T[]; - pageNum: number; - pageSize: number; - total: number; +type TableParams, Params = ApiParams> = { + apiFn: ApiFn; + apiParams: Params; + transformer: Transformer; + columns: DataTableColumn[]; + pagination?: PaginationProps; }; -/** - * 表格接口的请求函数 - */ -type TableApiFn

= ( - params: P -) => Promise>>; - -export function useNaiveTable( - apiFn: TableApiFn, - apiParams: P, - columns: MaybeComputedRef[]> +export function useTable, Params extends ApiParams>( + params: TableParams, + immediate = true ) { const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty(); + const data: Ref = ref([]); - const tableData: Ref = ref([]); - - async function getTableData(paginationParams?: TablePaginationParams) { - startLoading(); - - const params = { ...apiParams, ...paginationParams }; - - const { data } = await apiFn(params); - if (data) { - tableData.value = data.data; - - setEmpty(data.data.length === 0); - } - endLoading(); + function updateData(update: TableData[]) { + data.value = update; } - const pagination: PaginationProps = reactive({ - page: 1, - pageSize: 10, - showSizePicker: true, - pageSizes: [10, 15, 20, 25, 30], + let dataSource: TableData[] = []; + function setDataSource(source: TableData[]) { + dataSource = source; + } + + function resetData() { + data.value = dataSource; + } + + const columns = ref(params.columns) as Ref[]>; + + const pagination = reactive({ + ...getPagination(params.pagination), onChange: (page: number) => { pagination.page = page; }, @@ -76,14 +93,59 @@ export function useNaiveTable) { + Object.assign(pagination, update); + } + + async function getData() { + const apiParams: Params = { ...params.apiParams }; + apiParams.page = apiParams.page || pagination.page; + apiParams.pageSize = apiParams.pageSize || pagination.pageSize; + + startLoading(); + const { data: apiData } = await params.apiFn(apiParams); + + if (apiData) { + const transformedData = params.transformer(apiData); + + updateData(transformedData.data); + + setDataSource(transformedData.data); + + setEmpty(transformedData.data.length === 0); + + updatePagination({ page: transformedData.pageNum, pageSize: transformedData.pageSize }); + } + + endLoading(); + } + + if (immediate) { + getData(); + } return { - tableData, + data, columns, loading, empty, pagination, - start: getTableData + getData, + updateData, + resetData }; } + +function getPagination(pagination?: Partial) { + const defaultPagination: Partial = { + page: 1, + pageSize: 10, + showSizePicker: true, + pageSizes: [10, 15, 20, 25, 30] + }; + Object.assign(defaultPagination, pagination); + + return defaultPagination; +}