diff --git a/src/hooks/business/use-table.ts b/src/hooks/business/use-table.ts index e0624aa4b..7417fd7cf 100644 --- a/src/hooks/business/use-table.ts +++ b/src/hooks/business/use-table.ts @@ -1,74 +1,91 @@ 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 DataTableColumn = - | (Omit, 'key'> & { key: keyof T }) - | (Omit, 'key'> & { key: keyof T }) - | DataTableSelectionColumn - | DataTableExpandColumn; +type PaginationParams = Pick; /** - * 表格分页参数 + * 表格请求接口的参数 */ -type TablePaginationParams = Pick; +type ApiParams = Record & PaginationParams; /** - * 表格接口的请求参数 + * 表格请求接口的结果 + * @description 这里用属性list来表示后端接口返回的表格数据 */ -type TableApiParams = Record & TablePaginationParams; +type ApiData> = Record & { list: TableData[] }; /** - * 表格接口的请求数据 + * 表格接口的请求函数 + */ +type ApiFn> = ( + params: Params +) => Promise>>; + +/** + * 表格接口请求后转换后的数据 */ -type TableApiData = { - data: T[]; +type TransformedTableData> = { + data: TableData[]; pageNum: number; pageSize: number; total: number; }; /** - * 表格接口的请求函数 + * 表格的列 */ -type TableApiFn

= ( - params: P -) => Promise>>; - -export function useNaiveTable( - apiFn: TableApiFn, - apiParams: P, - columns: MaybeComputedRef[]> -) { - const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty(); +type DataTableColumn = + | (Omit, 'key'> & { key: keyof T }) + | (Omit, 'key'> & { key: keyof T }) + | DataTableSelectionColumn + | DataTableExpandColumn; - const tableData: Ref = ref([]); +/** + * 表格数据转换器 + * @description 将不同接口的表格数据转换成统一的类型 + */ +type Transformer> = ( + apiData: ApiData +) => TransformedTableData; - async function getTableData(paginationParams?: TablePaginationParams) { - startLoading(); +type TableParams, Params = ApiParams> = { + apiFn: ApiFn; + apiParams: Params; + transformer: Transformer; + columns: DataTableColumn[]; + pagination?: PaginationProps; +}; - const params = { ...apiParams, ...paginationParams }; +export function useTable, Params extends ApiParams>( + params: TableParams, + immediate = true +) { + const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty(); + const data: Ref = ref([]); - const { data } = await apiFn(params); - if (data) { - tableData.value = data.data; + function updateData(update: TableData[]) { + data.value = update; + } - setEmpty(data.data.length === 0); - } - endLoading(); + let dataSource: TableData[] = []; + function setDataSource(source: TableData[]) { + dataSource = source; } - const pagination: PaginationProps = reactive({ - page: 1, - pageSize: 10, - showSizePicker: true, - pageSizes: [10, 15, 20, 25, 30], + 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; +}