use-table.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { ref, reactive } from 'vue';
  2. import type { Ref } from 'vue';
  3. import type { DataTableBaseColumn, DataTableSelectionColumn, DataTableExpandColumn, PaginationProps } from 'naive-ui';
  4. import type { TableColumnGroup, InternalRowData } from 'naive-ui/es/data-table/src/interface';
  5. import { useLoadingEmpty } from '../common';
  6. /**
  7. * 表格分页参数
  8. */
  9. type PaginationParams = Pick<PaginationProps, 'page' | 'pageSize'>;
  10. /*
  11. * 表格请求接口的参数
  12. */
  13. type ApiParams = Record<string, unknown> & PaginationParams;
  14. /**
  15. * 表格请求接口的结果
  16. * @description 这里用属性list来表示后端接口返回的表格数据
  17. */
  18. type ApiData<TableData = Record<string, unknown>> = Record<string, unknown> & { list: TableData[] };
  19. /**
  20. * 表格接口的请求函数
  21. */
  22. type ApiFn<Params = ApiParams, TableData = Record<string, unknown>> = (
  23. params: Params
  24. ) => Promise<Service.RequestResult<ApiData<TableData>>>;
  25. /**
  26. * 表格接口请求后转换后的数据
  27. */
  28. type TransformedTableData<TableData = Record<string, unknown>> = {
  29. data: TableData[];
  30. pageNum: number;
  31. pageSize: number;
  32. total: number;
  33. };
  34. /**
  35. * 表格的列
  36. */
  37. type DataTableColumn<T = InternalRowData> =
  38. | (Omit<TableColumnGroup<T>, 'key'> & { key: keyof T })
  39. | (Omit<DataTableBaseColumn<T>, 'key'> & { key: keyof T })
  40. | DataTableSelectionColumn<T>
  41. | DataTableExpandColumn<T>;
  42. /**
  43. * 表格数据转换器
  44. * @description 将不同接口的表格数据转换成统一的类型
  45. */
  46. type Transformer<TableData = Record<string, unknown>> = (
  47. apiData: ApiData<TableData>
  48. ) => TransformedTableData<TableData>;
  49. type TableParams<TableData = Record<string, unknown>, Params = ApiParams> = {
  50. apiFn: ApiFn<Params, TableData>;
  51. apiParams: Params;
  52. transformer: Transformer<TableData>;
  53. columns: DataTableColumn<TableData>[];
  54. pagination?: PaginationProps;
  55. };
  56. export function useTable<TableData extends Record<string, unknown>, Params extends ApiParams>(
  57. params: TableParams<TableData, Params>,
  58. immediate = true
  59. ) {
  60. const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty();
  61. const data: Ref<TableData[]> = ref([]);
  62. function updateData(update: TableData[]) {
  63. data.value = update;
  64. }
  65. let dataSource: TableData[] = [];
  66. function setDataSource(source: TableData[]) {
  67. dataSource = source;
  68. }
  69. function resetData() {
  70. data.value = dataSource;
  71. }
  72. const columns = ref(params.columns) as Ref<DataTableColumn<TableData>[]>;
  73. const pagination = reactive({
  74. ...getPagination(params.pagination),
  75. onChange: (page: number) => {
  76. pagination.page = page;
  77. },
  78. onUpdatePageSize: (pageSize: number) => {
  79. pagination.pageSize = pageSize;
  80. pagination.page = 1;
  81. }
  82. }) as PaginationProps;
  83. function updatePagination(update: Partial<PaginationProps>) {
  84. Object.assign(pagination, update);
  85. }
  86. async function getData() {
  87. const apiParams: Params = { ...params.apiParams };
  88. apiParams.page = apiParams.page || pagination.page;
  89. apiParams.pageSize = apiParams.pageSize || pagination.pageSize;
  90. startLoading();
  91. const { data: apiData } = await params.apiFn(apiParams);
  92. if (apiData) {
  93. const transformedData = params.transformer(apiData);
  94. updateData(transformedData.data);
  95. setDataSource(transformedData.data);
  96. setEmpty(transformedData.data.length === 0);
  97. updatePagination({ page: transformedData.pageNum, pageSize: transformedData.pageSize });
  98. }
  99. endLoading();
  100. }
  101. if (immediate) {
  102. getData();
  103. }
  104. return {
  105. data,
  106. columns,
  107. loading,
  108. empty,
  109. pagination,
  110. getData,
  111. updateData,
  112. resetData
  113. };
  114. }
  115. function getPagination(pagination?: Partial<PaginationProps>) {
  116. const defaultPagination: Partial<PaginationProps> = {
  117. page: 1,
  118. pageSize: 10,
  119. showSizePicker: true,
  120. pageSizes: [10, 15, 20, 25, 30]
  121. };
  122. Object.assign(defaultPagination, pagination);
  123. return defaultPagination;
  124. }