useTable.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import { Table, TableExpose } from '@/components/Table'
  2. import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
  3. import { ref, reactive, watch, computed, unref, nextTick } from 'vue'
  4. import { get } from 'lodash-es'
  5. import type { TableProps } from '@/components/Table/src/types'
  6. import { useI18n } from '@/hooks/web/useI18n'
  7. import { TableSetPropsType } from '@/types/table'
  8. const { t } = useI18n()
  9. interface TableResponse<T = any> {
  10. total: number
  11. list: T[]
  12. pageNumber: number
  13. pageSize: number
  14. }
  15. interface UseTableConfig<T = any> {
  16. getListApi: (option: any) => Promise<IResponse<TableResponse<T>>>
  17. delListApi?: (option: any) => Promise<IResponse>
  18. // 返回数据格式配置
  19. response: {
  20. list: string
  21. total?: string
  22. }
  23. props?: TableProps
  24. }
  25. interface TableObject<T = any> {
  26. pageSize: number
  27. currentPage: number
  28. total: number
  29. tableList: T[]
  30. params: any
  31. loading: boolean
  32. currentRow: Nullable<T>
  33. }
  34. export const useTable = <T = any>(config?: UseTableConfig<T>) => {
  35. const tableObject = reactive<TableObject<T>>({
  36. // 页数
  37. pageSize: 10,
  38. // 当前页
  39. currentPage: 1,
  40. // 总条数
  41. total: 10,
  42. // 表格数据
  43. tableList: [],
  44. // AxiosConfig 配置
  45. params: {},
  46. // 加载中
  47. loading: true,
  48. // 当前行的数据
  49. currentRow: null
  50. })
  51. const paramsObj = computed(() => {
  52. return {
  53. ...tableObject.params,
  54. pageSize: tableObject.pageSize,
  55. pageIndex: tableObject.currentPage
  56. }
  57. })
  58. watch(
  59. () => tableObject.currentPage,
  60. () => {
  61. methods.getList()
  62. }
  63. )
  64. watch(
  65. () => tableObject.pageSize,
  66. () => {
  67. // 当前页不为1时,修改页数后会导致多次调用getList方法
  68. if (tableObject.currentPage === 1) {
  69. methods.getList()
  70. } else {
  71. tableObject.currentPage = 1
  72. methods.getList()
  73. }
  74. }
  75. )
  76. // Table实例
  77. const tableRef = ref<typeof Table & TableExpose>()
  78. // ElTable实例
  79. const elTableRef = ref<ComponentRef<typeof ElTable>>()
  80. const register = (ref: typeof Table & TableExpose, elRef: ComponentRef<typeof ElTable>) => {
  81. tableRef.value = ref
  82. elTableRef.value = unref(elRef)
  83. }
  84. const getTable = async () => {
  85. await nextTick()
  86. const table = unref(tableRef)
  87. if (!table) {
  88. console.error('The table is not registered. Please use the register method to register')
  89. }
  90. return table
  91. }
  92. const delData = async (ids: string[] | number[]) => {
  93. const res = await (config?.delListApi && config?.delListApi(ids))
  94. if (res) {
  95. ElMessage.success(t('common.delSuccess'))
  96. // 计算出临界点
  97. const currentPage =
  98. tableObject.total % tableObject.pageSize === ids.length || tableObject.pageSize === 1
  99. ? tableObject.currentPage > 1
  100. ? tableObject.currentPage - 1
  101. : tableObject.currentPage
  102. : tableObject.currentPage
  103. tableObject.currentPage = currentPage
  104. methods.getList()
  105. }
  106. }
  107. const methods = {
  108. getList: async () => {
  109. tableObject.loading = true
  110. const res = await config?.getListApi(unref(paramsObj)).finally(() => {
  111. tableObject.loading = false
  112. })
  113. if (res) {
  114. tableObject.tableList = get(res.data || {}, config?.response.list as string)
  115. tableObject.total = get(res.data || {}, config?.response?.total as string) || 0
  116. }
  117. },
  118. setProps: async (props: TableProps = {}) => {
  119. const table = await getTable()
  120. table?.setProps(props)
  121. },
  122. setColumn: async (columnProps: TableSetPropsType[]) => {
  123. const table = await getTable()
  124. table?.setColumn(columnProps)
  125. },
  126. getSelections: async () => {
  127. const table = await getTable()
  128. return (table?.selections || []) as T[]
  129. },
  130. // 与Search组件结合
  131. setSearchParams: (data: Recordable) => {
  132. tableObject.currentPage = 1
  133. tableObject.params = Object.assign(tableObject.params, {
  134. pageSize: tableObject.pageSize,
  135. pageIndex: tableObject.currentPage,
  136. ...data
  137. })
  138. methods.getList()
  139. },
  140. // 删除数据
  141. delList: async (ids: string[] | number[], multiple: boolean, message = true) => {
  142. const tableRef = await getTable()
  143. if (multiple) {
  144. if (!tableRef?.selections.length) {
  145. ElMessage.warning(t('common.delNoData'))
  146. return
  147. }
  148. } else {
  149. if (!tableObject.currentRow) {
  150. ElMessage.warning(t('common.delNoData'))
  151. return
  152. }
  153. }
  154. if (message) {
  155. ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), {
  156. confirmButtonText: t('common.delOk'),
  157. cancelButtonText: t('common.delCancel'),
  158. type: 'warning'
  159. }).then(async () => {
  160. await delData(ids)
  161. })
  162. } else {
  163. await delData(ids)
  164. }
  165. }
  166. }
  167. config?.props && methods.setProps(config.props)
  168. return {
  169. register,
  170. elTableRef,
  171. tableObject,
  172. methods
  173. }
  174. }