useTable.ts 6.0 KB

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