useTable.ts 5.8 KB

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