useTable.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { reactive, ref, computed, watch, unref } from 'vue'
  2. import { typeOf } from '@/utils/common'
  3. import useFetch from '@/hooks/useFetch'
  4. import useSection from '@/hooks/useSection'
  5. import type { Ref } from 'vue'
  6. import type {
  7. ApiKeys,
  8. BaseMultiplePageQuery,
  9. MultipleResult,
  10. ExtractApiParams,
  11. ExtractApiResponse,
  12. ExtractMultipleApiResponse,
  13. } from '@/api/api'
  14. import type { PaginationProps } from 'element-plus'
  15. import type { InstanceTable, InstanceElTable } from 'global-type'
  16. type P = Parameters<typeof useFetch>
  17. type ReturnTable<T extends ApiKeys, D extends boolean | OptionalPage = true> = {
  18. tableRef: Ref<InstanceTable | undefined>
  19. elTableRef: Ref<InstanceElTable | undefined>
  20. pagination: Ref<Partial<PaginationProps>>
  21. currentPage: Ref<number>
  22. loading: Ref<boolean>
  23. data: Ref<D extends false ? ExtractApiResponse<T> : ExtractMultipleApiResponse<T>[]>
  24. error: unknown
  25. hasSelected?: Ref<boolean>
  26. onSectionChange: (rows: ExtractMultipleApiResponse<T>[]) => void
  27. selectedList: ExtractMultipleApiResponse<T>[]
  28. fetchTable: () => void
  29. }
  30. type OptionalPage = Partial<BaseMultiplePageQuery>
  31. export type ModelType<T extends ApiKeys> = Omit<ExtractApiParams<T>, keyof BaseMultiplePageQuery>
  32. export type MultipleResponseType<T extends ApiKeys> = ExtractMultipleApiResponse<T>
  33. export type ResponseType<T extends ApiKeys> = ExtractApiResponse<T>
  34. const DEFAULT_PARAMS: BaseMultiplePageQuery = {
  35. pageNumber: 1,
  36. pageSize: 10,
  37. }
  38. const DEFAULT_PAGINATION: Partial<PaginationProps> = {
  39. layout: 'prev,pager,next',
  40. }
  41. function isPageQuery(c: any): c is OptionalPage {
  42. return typeOf(c) === 'object'
  43. }
  44. const useTable = <
  45. T extends ApiKeys,
  46. C extends Partial<ModelType<T>> = Partial<ModelType<T>>,
  47. D extends boolean | OptionalPage = true
  48. >(
  49. api: T,
  50. additional?: C,
  51. pageQuery?: D,
  52. httpConfig: P[1] = 'post',
  53. immediate = true
  54. ): ReturnTable<T, D> => {
  55. const tableRef = ref<InstanceTable>()
  56. const elTableRef = computed(() => {
  57. return tableRef?.value?.tableRef
  58. })
  59. const { hasSelected, onSectionChange, selectedList } = useSection<ExtractMultipleApiResponse<T>>()
  60. const multipleType = pageQuery !== false
  61. const baseParams = reactive<BaseMultiplePageQuery>(
  62. Object.assign(DEFAULT_PARAMS, isPageQuery(pageQuery) ? pageQuery : {})
  63. )
  64. const currentPage = computed({
  65. get() {
  66. return baseParams.pageNumber
  67. },
  68. set(n: number) {
  69. baseParams.pageNumber = n
  70. },
  71. })
  72. const payload = computed(() => {
  73. return Object.assign({}, multipleType ? baseParams : {}, additional || {}) as ExtractApiParams<T>
  74. })
  75. const { loading, fetch, cancel, error, result } = useFetch(api, httpConfig)
  76. const fetchTable = () => {
  77. cancel()
  78. fetch(payload.value)
  79. }
  80. watch(payload, () => fetchTable(), { immediate })
  81. const pageCount = computed(() => {
  82. return multipleType ? (result.value as MultipleResult<ExtractApiResponse<T>>)?.pageCount || 1 : 1
  83. })
  84. const total = computed(() => {
  85. return multipleType
  86. ? (result.value as MultipleResult<ExtractApiResponse<T>>)?.totalCount || 0
  87. : (result.value as Array<any>).length || 0
  88. })
  89. const data = computed(() => {
  90. return multipleType
  91. ? (result.value as MultipleResult<ExtractMultipleApiResponse<T>>)?.result || []
  92. : (unref(result) as any)
  93. })
  94. const pagination = computed(() => {
  95. return Object.assign(DEFAULT_PAGINATION, {
  96. pageSize: baseParams.pageSize,
  97. pageCount: pageCount.value,
  98. total: total.value,
  99. })
  100. })
  101. return {
  102. tableRef,
  103. elTableRef,
  104. hasSelected,
  105. onSectionChange,
  106. fetchTable,
  107. selectedList,
  108. loading,
  109. data,
  110. pagination,
  111. currentPage: currentPage,
  112. error,
  113. }
  114. }
  115. export default useTable