Browse Source

wip: Table改版中

kailong321200875 2 years ago
parent
commit
002d03a0ad

+ 1 - 1
src/api/table/index.ts

@@ -1,7 +1,7 @@
 import request from '@/config/axios'
 import type { TableData } from './types'
 
-export const getTableListApi = (params: any): Promise<IResponse> => {
+export const getTableListApi = (params: any) => {
   return request.get({ url: '/example/list', params })
 }
 

+ 1 - 1
src/components/Form/index.ts

@@ -31,7 +31,7 @@ export type {
   FormProps,
   PlaceholderModel,
   InputPasswordComponentProps,
-  CheckboxButtonComponentProps
+  TreeSelectComponentProps
 } from './src/types'
 
 export interface FormExpose {

+ 36 - 4
src/components/Form/src/Form.vue

@@ -1,6 +1,14 @@
 <script lang="tsx">
 import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
-import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
+import {
+  ElForm,
+  ElFormItem,
+  ElRow,
+  ElCol,
+  FormRules,
+  ComponentSize
+  // FormItemProp
+} from 'element-plus'
 import { componentMap } from './helper/componentMap'
 import { propTypes } from '@/utils/propTypes'
 import { getSlot } from '@/utils/tsxHelper'
@@ -47,7 +55,7 @@ export default defineComponent({
     isCol: propTypes.bool.def(true),
     // 表单数据对象
     model: {
-      type: Object as PropType<Recordable>,
+      type: Object as PropType<any>,
       default: () => ({})
     },
     // 是否自动设置placeholder
@@ -55,7 +63,30 @@ export default defineComponent({
     // 是否自定义内容
     isCustom: propTypes.bool.def(false),
     // 表单label宽度
-    labelWidth: propTypes.oneOfType([String, Number]).def('auto')
+    labelWidth: propTypes.oneOfType([String, Number]).def('auto'),
+    rules: {
+      type: Object as PropType<FormRules>,
+      default: () => ({})
+    },
+    labelPosition: propTypes.oneOf(['left', 'right', 'top']).def('right'),
+    labelSuffix: propTypes.string.def(''),
+    hideRequiredAsterisk: propTypes.bool.def(false),
+    requireAsteriskPosition: propTypes.oneOf(['left', 'right']).def('left'),
+    showMessage: propTypes.bool.def(true),
+    inlineMessage: propTypes.bool.def(false),
+    statusIcon: propTypes.bool.def(false),
+    validateOnRuleChange: propTypes.bool.def(true),
+    size: {
+      type: String as PropType<ComponentSize>,
+      default: 'small'
+    },
+    disabled: propTypes.bool.def(false),
+    scrollToError: propTypes.bool.def(false),
+    scrollToErrorOffset: propTypes.oneOfType([Boolean, Object]).def(undefined)
+    // onValidate: {
+    //   type: Function as PropType<(prop: FormItemProp, isValid: boolean, message: string) => void>,
+    //   default: () => {}
+    // }
   },
   emits: ['register'],
   setup(props, { slots, expose, emit }) {
@@ -93,6 +124,7 @@ export default defineComponent({
 
     const setProps = (props: FormProps = {}) => {
       mergeProps.value = Object.assign(unref(mergeProps), props)
+      // @ts-ignore
       outsideProps.value = props
     }
 
@@ -336,7 +368,7 @@ export default defineComponent({
           delete props[key]
         }
       }
-      return props
+      return props as FormProps
     }
 
     return () => (

+ 67 - 71
src/components/Form/src/types/index.ts

@@ -17,8 +17,7 @@ import {
   DatePickerProps,
   FormItemProps as ElFormItemProps,
   FormProps as ElFormProps,
-  TextareaProps,
-  CheckboxButtonProps
+  ISelectProps
 } from 'element-plus'
 import { IEditorConfig } from '@wangeditor/editor'
 import { CSSProperties } from 'vue'
@@ -121,55 +120,7 @@ export interface SelectOption {
   [key: string]: any
 }
 
-export interface SelectComponentProps {
-  multiple?: boolean
-  disabled?: boolean
-  valueKey?: string
-  size?: ComponentSize
-  clearable?: boolean
-  collapseTags?: boolean
-  collapseTagsTooltip?: number
-  multipleLimit?: number
-  name?: string
-  effect?: string
-  autocomplete?: string
-  placeholder?: string
-  filterable?: boolean
-  allowCreate?: boolean
-  filterMethod?: (query: string, item: any) => boolean
-  remote?: boolean
-  remoteMethod?: (query: string) => void
-  remoteShowSuffix?: boolean
-  loading?: boolean
-  loadingText?: string
-  noMatchText?: string
-  noDataText?: string
-  popperClass?: string
-  reserveKeyword?: boolean
-  defaultFirstOption?: boolean
-  popperAppendToBody?: boolean
-  teleported?: boolean
-  persistent?: boolean
-  automaticDropdown?: boolean
-  clearIcon?: string | JSX.Element | null
-  fitInputWidth?: boolean
-  suffixIcon?: string | JSX.Element | null
-  tagType?: 'success' | 'info' | 'warning' | 'danger'
-  validateEvent?: boolean
-  placement?:
-    | 'top'
-    | 'top-start'
-    | 'top-end'
-    | 'bottom'
-    | 'bottom-start'
-    | 'bottom-end'
-    | 'left'
-    | 'left-start'
-    | 'left-end'
-    | 'right'
-    | 'right-start'
-    | 'right-end'
-  maxCollapseTags?: number
+export interface SelectComponentProps extends Omit<Partial<ISelectProps>, 'options'> {
   /**
    * 数据源的字段别名
    */
@@ -400,25 +351,6 @@ export interface CheckboxGroupComponentProps extends Partial<CheckboxGroupProps>
   style?: CSSProperties
 }
 
-export interface CheckboxButtonComponentProps extends Partial<CheckboxButtonProps> {
-  options?: CheckboxOption[]
-  /**
-   * 数据源的字段别名
-   */
-  props?: {
-    label?: string
-    value?: string
-    disabled?: string
-  }
-  on?: {
-    change?: (value: string | number | boolean) => void
-  }
-  slots?: {
-    default?: (...args: any[]) => JSX.Element[] | null
-  }
-  style?: CSSProperties
-}
-
 export interface DividerComponentProps extends Partial<DividerProps> {
   on?: {
     change?: (value: number) => void
@@ -573,6 +505,70 @@ export interface FormItemProps extends Partial<ElFormItemProps> {
   }
 }
 
+export interface TreeSelectComponentProps
+  extends Omit<Partial<SelectComponentProps>, 'props' | 'on' | 'slots'> {
+  data?: any[]
+  emptyText?: string
+  nodeKey?: string
+  props?: {
+    children?: string
+    label?: string | ((...args: any[]) => string)
+    disabled?: string | ((...args: any[]) => string)
+    isLeaf?: string | ((...args: any[]) => string)
+    class?: string | ((...args: any[]) => string)
+  }
+  renderAfterExpand?: boolean
+  load?: (...args: any[]) => Promise<any>
+  renderContent?: (...args: any[]) => JSX.Element | null
+  highlightCurrent?: boolean
+  defaultExpandAll?: boolean
+  expandOnClickNode?: boolean
+  checkOnClickNode?: boolean
+  autoExpandParent?: boolean
+  defaultExpandedKeys?: any[]
+  showCheckbox?: boolean
+  checkStrictly?: boolean
+  defaultCheckedKeys?: any[]
+  currentNodeKey?: string | number
+  filterNodeMethod?: (...args: any[]) => boolean
+  accordion?: boolean
+  indent?: number
+  icon?: string | ((...args: any[]) => JSX.Element | null)
+  lazy?: boolean
+  draggable?: boolean
+  allowDrag?: (...args: any[]) => boolean
+  allowDrop?: (...args: any[]) => boolean
+  on?: {
+    change?: (value: string | number | boolean | Object) => void
+    visibleChange?: (visible: boolean) => void
+    removeTag?: (tag: any) => void
+    clear?: () => void
+    blur?: (event: FocusEvent) => void
+    focus?: (event: FocusEvent) => void
+    nodeClick?: (...args: any[]) => void
+    nodeContextMenu?: (...args: any[]) => void
+    checkChange?: (...args: any[]) => void
+    check?: (...args: any[]) => void
+    currentChange?: (...args: any[]) => void
+    nodeExpand?: (...args: any[]) => void
+    nodeCollapse?: (...args: any[]) => void
+    nodeDragStart?: (...args: any[]) => void
+    nodeDragEnter?: (...args: any[]) => void
+    nodeDragLeave?: (...args: any[]) => void
+    nodeDragOver?: (...args: any[]) => void
+    nodeDragEnd?: (...args: any[]) => void
+    nodeDrop?: (...args: any[]) => void
+  }
+  slots?: {
+    default?: (...args: any[]) => JSX.Element | null
+    optionGroupDefault?: (item: SelectOption) => JSX.Element
+    optionDefault?: (option: SelectOption) => JSX.Element | null
+    prefix?: (...args: any[]) => JSX.Element | null
+    empty?: (...args: any[]) => JSX.Element | null
+  }
+  style?: CSSProperties
+}
+
 export interface FormSchema {
   /**
    * 唯一标识
@@ -610,7 +606,7 @@ export interface FormSchema {
     | DateTimePickerComponentProps
     | TimePickerComponentProps
     | InputPasswordComponentProps
-    | CheckboxButtonComponentProps
+    | TreeSelectComponentProps
 
   /**
    * formItem组件属性,具体可以查看element-plus文档

+ 1 - 0
src/components/Search/src/Search.vue

@@ -112,6 +112,7 @@ const getProps = computed(() => {
 
 const setProps = (props: SearchProps = {}) => {
   mergeProps.value = Object.assign(unref(mergeProps), props)
+  // @ts-ignore
   outsideProps.value = props
 }
 

+ 168 - 32
src/components/Table/src/Table.vue

@@ -1,11 +1,11 @@
 <script lang="tsx">
-import { ElTable, ElTableColumn, ElPagination } from 'element-plus'
+import { ElTable, ElTableColumn, ElPagination, ComponentSize, ElTooltipProps } from 'element-plus'
 import { defineComponent, PropType, ref, computed, unref, watch, onMounted } from 'vue'
 import { propTypes } from '@/utils/propTypes'
 import { setIndex } from './helper'
-import { getSlot } from '@/utils/tsxHelper'
-import type { TableProps, TableColumn, TableSlotDefault, Pagination, TableSetProps } from './types'
+import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
 import { set } from 'lodash-es'
+import { CSSProperties } from 'vue'
 
 export default defineComponent({
   name: 'Table',
@@ -45,10 +45,137 @@ export default defineComponent({
     data: {
       type: Array as PropType<Recordable[]>,
       default: () => []
-    }
+    },
+    height: propTypes.oneOfType([Number, String]),
+    maxHeight: propTypes.oneOfType([Number, String]),
+    stripe: propTypes.bool.def(false),
+    border: propTypes.bool.def(false),
+    size: {
+      type: String as PropType<ComponentSize>,
+      validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v)
+    },
+    fit: propTypes.bool.def(true),
+    showHeader: propTypes.bool.def(true),
+    highlightCurrentRow: propTypes.bool.def(false),
+    currentRowKey: propTypes.oneOfType([Number, String]),
+    // row-class-name, 类型为 (row: Recordable, rowIndex: number) => string | string
+    rowClassName: {
+      type: [Function, String] as PropType<(row: Recordable, rowIndex: number) => string | string>,
+      default: ''
+    },
+    rowStyle: {
+      type: [Function, Object] as PropType<
+        (row: Recordable, rowIndex: number) => Recordable | CSSProperties
+      >,
+      default: () => undefined
+    },
+    cellClassName: {
+      type: [Function, String] as PropType<
+        (row: Recordable, column: any, rowIndex: number) => string | string
+      >,
+      default: ''
+    },
+    cellStyle: {
+      type: [Function, Object] as PropType<
+        (row: Recordable, column: any, rowIndex: number) => Recordable | CSSProperties
+      >,
+      default: () => undefined
+    },
+    headerRowClassName: {
+      type: [Function, String] as PropType<(row: Recordable, rowIndex: number) => string | string>,
+      default: ''
+    },
+    headerRowStyle: {
+      type: [Function, Object] as PropType<
+        (row: Recordable, rowIndex: number) => Recordable | CSSProperties
+      >,
+      default: () => undefined
+    },
+    headerCellClassName: {
+      type: [Function, String] as PropType<
+        (row: Recordable, column: any, rowIndex: number) => string | string
+      >,
+      default: ''
+    },
+    headerCellStyle: {
+      type: [Function, Object] as PropType<
+        (row: Recordable, column: any, rowIndex: number) => Recordable | CSSProperties
+      >,
+      default: () => undefined
+    },
+    rowKey: {
+      type: [Function, String] as PropType<(row: Recordable) => string | string>,
+      default: () => 'id'
+    },
+    emptyText: propTypes.string.def('No Data'),
+    defaultExpandAll: propTypes.bool.def(false),
+    expandRowKeys: {
+      type: Array as PropType<string[]>,
+      default: () => []
+    },
+    defaultSort: {
+      type: Object as PropType<{ prop: string; order: string }>,
+      default: () => ({})
+    },
+    tooltipEffect: {
+      type: String as PropType<'dark' | 'light'>,
+      default: 'dark'
+    },
+    tooltipOptions: {
+      type: Object as PropType<
+        Pick<
+          ElTooltipProps,
+          | 'effect'
+          | 'enterable'
+          | 'hideAfter'
+          | 'offset'
+          | 'placement'
+          | 'popperClass'
+          | 'popperOptions'
+          | 'showAfter'
+          | 'showArrow'
+        >
+      >,
+      default: () => ({
+        enterable: true,
+        placement: 'top',
+        showArrow: true,
+        hideAfter: 200,
+        popperOptions: { strategy: 'fixed' }
+      })
+    },
+    showSummary: propTypes.bool.def(false),
+    sumText: propTypes.string.def('Sum'),
+    summaryMethod: {
+      type: Function as PropType<(param: { columns: any[]; data: any[] }) => any[]>,
+      default: () => undefined
+    },
+    spanMethod: {
+      type: Function as PropType<
+        (param: { row: any; column: any; rowIndex: number; columnIndex: number }) => any[]
+      >,
+      default: () => undefined
+    },
+    selectOnIndeterminate: propTypes.bool.def(true),
+    indent: propTypes.number.def(16),
+    lazy: propTypes.bool.def(false),
+    load: {
+      type: Function as PropType<(row: Recordable, treeNode: any, resolve: Function) => void>,
+      default: () => undefined
+    },
+    treeProps: {
+      type: Object as PropType<{ hasChildren: string; children: string; label: string }>,
+      default: () => ({ hasChildren: 'hasChildren', children: 'children', label: 'label' })
+    },
+    tableLayout: {
+      type: String as PropType<'auto' | 'fixed'>,
+      default: 'fixed'
+    },
+    scrollbarAlwaysOn: propTypes.bool.def(false),
+    flexible: propTypes.bool.def(false)
   },
   emits: ['update:pageSize', 'update:currentPage', 'register'],
-  setup(props, { attrs, slots, emit, expose }) {
+  setup(props, { attrs, emit, expose }) {
     const elTableRef = ref<ComponentRef<typeof ElTable>>()
 
     // 注册
@@ -74,7 +201,7 @@ export default defineComponent({
 
     const setProps = (props: TableProps = {}) => {
       mergeProps.value = Object.assign(unref(mergeProps), props)
-      outsideProps.value = props
+      outsideProps.value = { ...props } as any
     }
 
     const setColumn = (columnProps: TableSetProps[], columnsChildren?: TableColumn[]) => {
@@ -186,6 +313,22 @@ export default defineComponent({
       return columnsChildren.map((v) => {
         const props = { ...v } as any
         if (props.children) delete props.children
+
+        const children = v.children
+
+        const slots = {
+          default: (...args: any[]) => {
+            if (props?.slots?.default) {
+              return slots.default(args)
+            } else if (children && children.length) {
+              return renderTreeTableColumn(children)
+            }
+          }
+        }
+        if (props?.slots?.header) {
+          slots['header'] = (...args: any[]) => props.slots.header(args)
+        }
+
         return (
           <ElTableColumn
             showOverflowTooltip={showOverflowTooltip}
@@ -194,17 +337,7 @@ export default defineComponent({
             {...props}
             prop={v.field}
           >
-            {{
-              default: (data: TableSlotDefault) =>
-                v.children && v.children.length
-                  ? renderTableColumn(v.children)
-                  : // @ts-ignore
-                    getSlot(slots, v.field, data) ||
-                    v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
-                    data.row[v.field],
-              // @ts-ignore
-              header: getSlot(slots, `${v.field}-header`)
-            }}
+            {slots}
           </ElTableColumn>
         )
       })
@@ -241,6 +374,22 @@ export default defineComponent({
           } else {
             const props = { ...v } as any
             if (props.children) delete props.children
+
+            const children = v.children
+
+            const slots = {
+              default: (...args: any[]) => {
+                if (props?.slots?.default) {
+                  return slots.default(args)
+                } else if (children && children.length) {
+                  return renderTreeTableColumn(children)
+                }
+              }
+            }
+            if (props?.slots?.header) {
+              slots['header'] = (...args: any[]) => props.slots.header(args)
+            }
+
             return (
               <ElTableColumn
                 showOverflowTooltip={showOverflowTooltip}
@@ -249,17 +398,7 @@ export default defineComponent({
                 {...props}
                 prop={v.field}
               >
-                {{
-                  default: (data: TableSlotDefault) =>
-                    v.children && v.children.length
-                      ? renderTreeTableColumn(v.children)
-                      : // @ts-ignore
-                        getSlot(slots, v.field, data) ||
-                        v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
-                        data.row[v.field],
-                  // @ts-ignore
-                  header: () => getSlot(slots, `${v.field}-header`) || v.label
-                }}
+                {slots}
               </ElTableColumn>
             )
           }
@@ -270,16 +409,13 @@ export default defineComponent({
     return () => (
       <div v-loading={unref(getProps).loading}>
         <ElTable
-          // @ts-ignore
           ref={elTableRef}
           data={unref(getProps).data}
           onSelection-change={selectionChange}
           {...unref(getBindValue)}
         >
           {{
-            default: () => renderTableColumn(),
-            // @ts-ignore
-            append: () => getSlot(slots, 'append')
+            default: () => renderTableColumn()
           }}
         </ElTable>
         {unref(getProps).pagination ? (

+ 3 - 4
src/components/Table/src/types/index.ts

@@ -1,9 +1,10 @@
+import { TableProps as ElTableProps } from 'element-plus'
 export interface TableColumn {
   field: string
   label?: string
   children?: TableColumn[]
   slots?: {
-    defalut?: (...args: any[]) => JSX.Element | null
+    default?: (...args: any[]) => JSX.Element | JSX.Element[] | null
     header?: (...args: any[]) => JSX.Element | null
   }
   index?: number | ((index: number) => number)
@@ -65,7 +66,7 @@ export interface TableSetProps {
   value: any
 }
 
-export interface TableProps {
+export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> {
   pageSize?: number
   currentPage?: number
   // 是否多选
@@ -87,6 +88,4 @@ export interface TableProps {
   // 表头对齐方式
   headerAlign?: 'left' | 'center' | 'right'
   data?: Recordable
-  expand?: boolean
-  [key: string]: any
 }

+ 144 - 102
src/hooks/web/useTable.ts

@@ -1,6 +1,6 @@
 import { Table, TableExpose, TableProps, TableSetProps } from '@/components/Table'
 import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
-import { ref, reactive, watch, computed, unref, nextTick } from 'vue'
+import { ref, reactive, watch, computed, unref, nextTick, onMounted } from 'vue'
 import { get } from 'lodash-es'
 import { useI18n } from '@/hooks/web/useI18n'
 
@@ -13,17 +13,28 @@ interface TableResponse<T = any> {
   pageSize: number
 }
 
-interface UseTableConfig<T = any> {
-  getListApi: (option: any) => Promise<IResponse<TableResponse<T>>>
-  delListApi?: (option: any) => Promise<IResponse>
-  // 返回数据格式配置
-  response: {
-    list: string
+interface UseTableConfig {
+  // 是否初始化请求一次
+  immediate?: boolean
+  // 获取数据字段映射
+  props?: {
+    list?: string
     total?: string
   }
+  fetchDataApi: () => Promise<{
+    list: any[]
+    total: number
+  }>
+  // getListApi: (option: any) => Promise<IResponse<TableResponse<T>>>
+  // delListApi?: (option: any) => Promise<IResponse>
+  // 返回数据格式配置
+  // response: {
+  //   list: string
+  //   total?: string
+  // }
   // 默认传递的参数
-  defaultParams?: Recordable
-  props?: TableProps
+  // defaultParams?: Recordable
+  // props?: TableProps
 }
 
 interface TableObject<T = any> {
@@ -36,8 +47,16 @@ interface TableObject<T = any> {
   currentRow: Nullable<T>
 }
 
-export const useTable = <T = any>(config?: UseTableConfig<T>) => {
-  const tableObject = reactive<TableObject<T>>({
+export const useTable = (config: UseTableConfig) => {
+  const { immediate = true } = config
+
+  const loading = ref(false)
+  const pageIndex = ref(1)
+  const pageSize = ref(10)
+  const total = ref(0)
+  const dataList = ref<any[]>([])
+
+  const tableObject = reactive<TableObject>({
     // 页数
     pageSize: 10,
     // 当前页
@@ -48,7 +67,7 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
     list: [],
     // AxiosConfig 配置
     params: {
-      ...(config?.defaultParams || {})
+      // ...(config?.defaultParams || {})
     },
     // 加载中
     loading: true,
@@ -64,25 +83,31 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
     }
   })
 
-  watch(
-    () => tableObject.currentPage,
-    () => {
+  // watch(
+  //   () => tableObject.currentPage,
+  //   () => {
+  //     methods.getList()
+  //   }
+  // )
+
+  // watch(
+  //   () => tableObject.pageSize,
+  //   () => {
+  //     // 当前页不为1时,修改页数后会导致多次调用getList方法
+  //     if (tableObject.currentPage === 1) {
+  //       methods.getList()
+  //     } else {
+  //       tableObject.currentPage = 1
+  //       methods.getList()
+  //     }
+  //   }
+  // )
+
+  onMounted(() => {
+    if (immediate) {
       methods.getList()
     }
-  )
-
-  watch(
-    () => tableObject.pageSize,
-    () => {
-      // 当前页不为1时,修改页数后会导致多次调用getList方法
-      if (tableObject.currentPage === 1) {
-        methods.getList()
-      } else {
-        tableObject.currentPage = 1
-        methods.getList()
-      }
-    }
-  )
+  })
 
   // Table实例
   const tableRef = ref<typeof Table & TableExpose>()
@@ -104,91 +129,108 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
     return table
   }
 
-  const delData = async (ids: string[] | number[]) => {
-    const res = await (config?.delListApi && config?.delListApi(ids))
-    if (res) {
-      ElMessage.success(t('common.delSuccess'))
+  // const delData = async (ids: string[] | number[]) => {
+  //   const res = await (config?.delListApi && config?.delListApi(ids))
+  //   if (res) {
+  //     ElMessage.success(t('common.delSuccess'))
 
-      // 计算出临界点
-      const currentPage =
-        tableObject.total % tableObject.pageSize === ids.length || tableObject.pageSize === 1
-          ? tableObject.currentPage > 1
-            ? tableObject.currentPage - 1
-            : tableObject.currentPage
-          : tableObject.currentPage
+  //     // 计算出临界点
+  //     const currentPage =
+  //       tableObject.total % tableObject.pageSize === ids.length || tableObject.pageSize === 1
+  //         ? tableObject.currentPage > 1
+  //           ? tableObject.currentPage - 1
+  //           : tableObject.currentPage
+  //         : tableObject.currentPage
 
-      tableObject.currentPage = currentPage
-      methods.getList()
-    }
-  }
+  //     tableObject.currentPage = currentPage
+  //     methods.getList()
+  //   }
+  // }
 
   const methods = {
     getList: async () => {
-      tableObject.loading = true
-      const res = await config?.getListApi(unref(paramsObj)).finally(() => {
-        tableObject.loading = false
-      })
-      if (res) {
-        tableObject.list = get(res.data || {}, config?.response.list as string)
-        tableObject.total = get(res.data || {}, config?.response?.total as string) || 0
-      }
-    },
-    setProps: async (props: TableProps = {}) => {
-      const table = await getTable()
-      table?.setProps(props)
-    },
-    setColumn: async (columnProps: TableSetProps[]) => {
-      const table = await getTable()
-      table?.setColumn(columnProps)
-    },
-    getSelections: async () => {
-      const table = await getTable()
-      return (table?.selections || []) as T[]
-    },
-    // 与Search组件结合
-    setSearchParams: (data: Recordable) => {
-      tableObject.currentPage = 1
-      tableObject.params = Object.assign(tableObject.params, {
-        pageSize: tableObject.pageSize,
-        pageIndex: tableObject.currentPage,
-        ...data
-      })
-      methods.getList()
-    },
-    // 删除数据
-    delList: async (ids: string[] | number[], multiple: boolean, message = true) => {
-      const tableRef = await getTable()
-      if (multiple) {
-        if (!tableRef?.selections.length) {
-          ElMessage.warning(t('common.delNoData'))
-          return
-        }
-      } else {
-        if (!tableObject.currentRow) {
-          ElMessage.warning(t('common.delNoData'))
-          return
+      loading.value = true
+      try {
+        const res = await config?.fetchDataApi()
+        console.log('fetchDataApi res', res)
+        if (res) {
+          dataList.value = res.list
+          total.value = res.total
         }
+      } catch (err) {
+        console.log('fetchDataApi error')
+      } finally {
+        loading.value = false
       }
-      if (message) {
-        ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), {
-          confirmButtonText: t('common.delOk'),
-          cancelButtonText: t('common.delCancel'),
-          type: 'warning'
-        }).then(async () => {
-          await delData(ids)
-        })
-      } else {
-        await delData(ids)
-      }
+      // const res = await config?.getListApi(unref(paramsObj)).finally(() => {
+      //   tableObject.loading = false
+      // })
+      // if (res) {
+      //   tableObject.list = get(res.data || {}, config?.response.list as string)
+      //   tableObject.total = get(res.data || {}, config?.response?.total as string) || 0
+      // }
     }
+    // setProps: async (props: TableProps = {}) => {
+    //   const table = await getTable()
+    //   table?.setProps(props)
+    // },
+    // setColumn: async (columnProps: TableSetProps[]) => {
+    //   const table = await getTable()
+    //   table?.setColumn(columnProps)
+    // },
+    // getSelections: async () => {
+    //   const table = await getTable()
+    //   return (table?.selections || []) as T[]
+    // },
+    // // 与Search组件结合
+    // setSearchParams: (data: Recordable) => {
+    //   tableObject.currentPage = 1
+    //   tableObject.params = Object.assign(tableObject.params, {
+    //     pageSize: tableObject.pageSize,
+    //     pageIndex: tableObject.currentPage,
+    //     ...data
+    //   })
+    //   methods.getList()
+    // },
+    // // 删除数据
+    // delList: async (ids: string[] | number[], multiple: boolean, message = true) => {
+    //   const tableRef = await getTable()
+    //   if (multiple) {
+    //     if (!tableRef?.selections.length) {
+    //       ElMessage.warning(t('common.delNoData'))
+    //       return
+    //     }
+    //   } else {
+    //     if (!tableObject.currentRow) {
+    //       ElMessage.warning(t('common.delNoData'))
+    //       return
+    //     }
+    //   }
+    //   if (message) {
+    //     ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), {
+    //       confirmButtonText: t('common.delOk'),
+    //       cancelButtonText: t('common.delCancel'),
+    //       type: 'warning'
+    //     }).then(async () => {
+    //       await delData(ids)
+    //     })
+    //   } else {
+    //     await delData(ids)
+    //   }
+    // }
   }
 
-  config?.props && methods.setProps(config.props)
-
   return {
-    register,
+    tableRegister: register,
     elTableRef,
     tableObject,
-    methods
+    methods,
+    tableState: {
+      pageIndex,
+      pageSize,
+      total,
+      dataList,
+      loading
+    }
   }
 }

+ 8 - 8
src/router/index.ts

@@ -176,15 +176,15 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
             meta: {
               title: t('router.defaultTable')
             }
+          },
+          {
+            path: 'use-table',
+            component: () => import('@/views/Components/Table/UseTableDemo.vue'),
+            name: 'UseTable',
+            meta: {
+              title: 'UseTable'
+            }
           }
-          // {
-          //   path: 'use-table',
-          //   component: () => import('@/views/Components/Table/UseTableDemo.vue'),
-          //   name: 'UseTable',
-          //   meta: {
-          //     title: 'UseTable'
-          //   }
-          // }
         ]
       },
       {

+ 12 - 9
src/views/Components/Table/DefaultTable.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script setup lang="tsx">
 import { ContentWrap } from '@/components/ContentWrap'
 import { useI18n } from '@/hooks/web/useI18n'
 import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
@@ -52,7 +52,16 @@ const columns: TableColumn[] = [
   },
   {
     field: 'action',
-    label: t('tableDemo.action')
+    label: t('tableDemo.action'),
+    slots: {
+      default: (data) => {
+        return (
+          <ElButton type="primary" onClick={() => actionFn(data)}>
+            {t('tableDemo.action')}
+          </ElButton>
+        )
+      }
+    }
   }
 ]
 
@@ -90,12 +99,6 @@ const actionFn = (data: TableSlotDefault) => {
       :data="tableDataList"
       :loading="loading"
       :defaultSort="{ prop: 'display_time', order: 'descending' }"
-    >
-      <template #action="data">
-        <ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
-          {{ t('tableDemo.action') }}
-        </ElButton>
-      </template>
-    </Table>
+    />
   </ContentWrap>
 </template>

+ 56 - 45
src/views/Components/Table/UseTableDemo.vue

@@ -1,41 +1,52 @@
-<script setup lang="ts">
+<script setup lang="tsx">
 import { ContentWrap } from '@/components/ContentWrap'
 import { useI18n } from '@/hooks/web/useI18n'
-import { Table } from '@/components/Table'
+import { Table, Pagination, TableColumn, TableSlotDefault } from '@/components/Table'
 import { getTableListApi } from '@/api/table'
 import { TableData } from '@/api/table/types'
 import { ref, h, reactive, unref } from 'vue'
 import { ElTag, ElButton } from 'element-plus'
 import { useTable } from '@/hooks/web/useTable'
-import { Pagination, TableColumn, TableSlotDefault } from '@/types/table'
 
-const { register, tableObject, methods, elTableRef } = useTable<TableData>({
-  getListApi: getTableListApi,
-  response: {
-    list: 'list',
-    total: 'total'
+const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable({
+  fetchDataApi: async () => {
+    const { pageIndex, pageSize } = tableState
+    const res = await getTableListApi({
+      pageIndex: unref(pageIndex),
+      pageSize: unref(pageSize)
+    })
+    return {
+      list: res.data.list,
+      total: res.data.total
+    }
   }
+  // getListApi: getTableListApi,
+  // response: {
+  //   list: 'list',
+  //   total: 'total'
+  // }
 })
+const { loading, dataList, total, pageIndex, pageSize } = tableState
 
-const { getList } = methods
+// const { getList } = methods
 
-getList()
+// getList()
 
-const {
-  register: register2,
-  tableObject: tableObject2,
-  methods: methods2
-} = useTable<TableData>({
-  getListApi: getTableListApi,
-  response: {
-    list: 'list',
-    total: 'total'
-  }
-})
+// const {
+//   register: register2,
+//   tableObject: tableObject2,
+//   methods: methods2
+// } = useTable<TableData>({
+//   getListApi: getTableListApi,
+//   response: {
+//     list: 'list',
+//     total: 'total'
+//   }
+// })
 
-const { getList: getList2 } = methods2
+// const { getList: getList2 } = methods2
 
-getList2()
+// getList2()
 
 const { t } = useI18n()
 
@@ -65,17 +76,14 @@ const columns = reactive<TableColumn[]>([
         field: 'importance',
         label: t('tableDemo.importance'),
         formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-          return h(
-            ElTag,
-            {
-              type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
-            },
-            () =>
-              cellValue === 1
+          return (
+            <ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
+              {cellValue === 1
                 ? t('tableDemo.important')
                 : cellValue === 2
                 ? t('tableDemo.good')
-                : t('tableDemo.commonly')
+                : t('tableDemo.commonly')}
+            </ElTag>
           )
         }
       },
@@ -87,7 +95,16 @@ const columns = reactive<TableColumn[]>([
   },
   {
     field: 'action',
-    label: t('tableDemo.action')
+    label: t('tableDemo.action'),
+    slots: {
+      default: (data) => {
+        return (
+          <ElButton type="primary" onClick={() => actionFn(data)}>
+            {t('tableDemo.action')}
+          </ElButton>
+        )
+      }
+    }
   }
 ])
 
@@ -171,20 +188,14 @@ const selectAllNone = () => {
   </ContentWrap>
   <ContentWrap :title="`UseTable ${t('tableDemo.example')}`">
     <Table
-      v-model:pageSize="tableObject.pageSize"
-      v-model:currentPage="tableObject.currentPage"
+      v-model:pageSize="pageSize"
+      v-model:currentPage="pageIndex"
       :columns="columns"
-      :data="tableObject.tableList"
-      :loading="tableObject.loading"
+      :data="dataList"
+      :loading="loading"
       :pagination="paginationObj"
-      @register="register"
+      @register="tableRegister"
     >
-      <template #action="data">
-        <ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
-          {{ t('tableDemo.action') }}
-        </ElButton>
-      </template>
-
       <template #expand="data">
         <div class="ml-30px">
           <div>{{ t('tableDemo.title') }}:{{ data.row.title }}</div>
@@ -195,7 +206,7 @@ const selectAllNone = () => {
     </Table>
   </ContentWrap>
 
-  <ContentWrap :title="`UseTable 2 ${t('tableDemo.example')}`">
+  <!-- <ContentWrap :title="`UseTable 2 ${t('tableDemo.example')}`">
     <Table
       v-model:pageSize="tableObject2.pageSize"
       v-model:currentPage="tableObject2.currentPage"
@@ -219,5 +230,5 @@ const selectAllNone = () => {
         </div>
       </template>
     </Table>
-  </ContentWrap>
+  </ContentWrap> -->
 </template>