github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/hooks/web/useTable.ts (about)

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