Quellcode durchsuchen

feat: Table重构

kailong321200875 vor 1 Jahr
Ursprung
Commit
94800b0120

+ 9 - 0
mock/role/index.ts

@@ -142,6 +142,14 @@ const adminList = [
               title: 'UseTable'
             }
           },
+          {
+            path: 'tree-table',
+            component: 'views/Components/Table/TreeTable',
+            name: 'TreeTable',
+            meta: {
+              title: 'TreeTable'
+            }
+          },
           {
             path: 'ref-table',
             component: 'views/Components/Table/RefTable',
@@ -481,6 +489,7 @@ const testList: string[] = [
   '/components/table',
   '/components/table/default-table',
   '/components/table/use-table',
+  '/components/table/tree-table',
   '/components/table/ref-table',
   '/components/editor-demo',
   '/components/editor-demo/editor',

+ 122 - 2
mock/table/index.ts

@@ -12,7 +12,7 @@ const count = 100
 const baseContent =
   '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
 
-let List: {
+interface ListProps {
   id: string
   author: string
   title: string
@@ -20,7 +20,20 @@ let List: {
   importance: number
   display_time: string
   pageviews: number
-}[] = []
+}
+
+interface TreeListProps {
+  id: string
+  author: string
+  title: string
+  content: string
+  importance: number
+  display_time: string
+  pageviews: number
+  children: TreeListProps[]
+}
+
+let List: ListProps[] = []
 
 for (let i = 0; i < count; i++) {
   List.push(
@@ -38,7 +51,114 @@ for (let i = 0; i < count; i++) {
   )
 }
 
+const treeList: TreeListProps[] = []
+
+for (let i = 0; i < count; i++) {
+  treeList.push(
+    Mock.mock({
+      id: toAnyString(),
+      // timestamp: +Mock.Random.date('T'),
+      author: '@first',
+      title: '@title(5, 10)',
+      content: baseContent,
+      importance: '@integer(1, 3)',
+      display_time: '@datetime',
+      pageviews: '@integer(300, 5000)',
+      children: [
+        {
+          id: toAnyString(),
+          // timestamp: +Mock.Random.date('T'),
+          author: '@first',
+          title: '@title(5, 10)',
+          content: baseContent,
+          importance: '@integer(1, 3)',
+          display_time: '@datetime',
+          pageviews: '@integer(300, 5000)',
+          children: [
+            {
+              id: toAnyString(),
+              // timestamp: +Mock.Random.date('T'),
+              author: '@first',
+              title: '@title(5, 10)',
+              content: baseContent,
+              importance: '@integer(1, 3)',
+              display_time: '@datetime',
+              pageviews: '@integer(300, 5000)'
+            },
+            {
+              id: toAnyString(),
+              // timestamp: +Mock.Random.date('T'),
+              author: '@first',
+              title: '@title(5, 10)',
+              content: baseContent,
+              importance: '@integer(1, 3)',
+              display_time: '@datetime',
+              pageviews: '@integer(300, 5000)'
+            }
+          ]
+        },
+        {
+          id: toAnyString(),
+          // timestamp: +Mock.Random.date('T'),
+          author: '@first',
+          title: '@title(5, 10)',
+          content: baseContent,
+          importance: '@integer(1, 3)',
+          display_time: '@datetime',
+          pageviews: '@integer(300, 5000)'
+        },
+        {
+          id: toAnyString(),
+          // timestamp: +Mock.Random.date('T'),
+          author: '@first',
+          title: '@title(5, 10)',
+          content: baseContent,
+          importance: '@integer(1, 3)',
+          display_time: '@datetime',
+          pageviews: '@integer(300, 5000)'
+        },
+        {
+          id: toAnyString(),
+          // timestamp: +Mock.Random.date('T'),
+          author: '@first',
+          title: '@title(5, 10)',
+          content: baseContent,
+          importance: '@integer(1, 3)',
+          display_time: '@datetime',
+          pageviews: '@integer(300, 5000)'
+        }
+      ]
+      // image_uri
+    })
+  )
+}
+
 export default [
+  // 树形列表接口
+  {
+    url: '/example/treeList',
+    method: 'get',
+    timeout,
+    response: ({ query }) => {
+      const { title, pageIndex, pageSize } = query
+      const mockList = treeList.filter((item) => {
+        if (title && item.title.indexOf(title) < 0) return false
+        return true
+      })
+      const pageList = mockList.filter(
+        (_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
+      )
+      return {
+        data: {
+          code: code,
+          data: {
+            total: mockList.length,
+            list: pageList
+          }
+        }
+      }
+    }
+  },
   // 列表接口
   {
     url: '/example/list',

+ 4 - 0
src/api/table/index.ts

@@ -5,6 +5,10 @@ export const getTableListApi = (params: any) => {
   return request.get({ url: '/example/list', params })
 }
 
+export const getTreeTableListApi = (params: any) => {
+  return request.get({ url: '/example/treeList', params })
+}
+
 export const saveTableApi = (data: Partial<TableData>): Promise<IResponse> => {
   return request.post({ url: '/example/save', data })
 }

+ 3 - 1
src/components/Table/index.ts

@@ -1,6 +1,6 @@
 import Table from './src/Table.vue'
 import { ElTable } from 'element-plus'
-import { TableSetProps } from './src/types'
+import { TableColumn, TableSetProps } from './src/types'
 
 export type {
   TableColumn,
@@ -13,6 +13,8 @@ export type {
 export interface TableExpose {
   setProps: (props: Recordable) => void
   setColumn: (columnProps: TableSetProps[]) => void
+  addColumn: (column: TableColumn, index?: number) => void
+  delColumn: (field: string) => void
   selections: Recordable[]
   elTableRef: ComponentRef<typeof ElTable>
 }

+ 95 - 91
src/components/Table/src/Table.vue

@@ -6,14 +6,13 @@ import { setIndex } from './helper'
 import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
 import { set } from 'lodash-es'
 import { CSSProperties } from 'vue'
+import { getSlot } from '@/utils/tsxHelper'
 
 export default defineComponent({
   name: 'Table',
   props: {
     pageSize: propTypes.number.def(10),
     currentPage: propTypes.number.def(1),
-    // 是否多选
-    selection: propTypes.bool.def(true),
     // 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip,
     showOverflowTooltip: propTypes.bool.def(true),
     // 表头
@@ -49,7 +48,7 @@ export default defineComponent({
     height: propTypes.oneOfType([Number, String]),
     maxHeight: propTypes.oneOfType([Number, String]),
     stripe: propTypes.bool.def(false),
-    border: propTypes.bool.def(false),
+    border: propTypes.bool.def(true),
     size: {
       type: String as PropType<ComponentSize>,
       validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v)
@@ -103,10 +102,7 @@ export default defineComponent({
       >,
       default: () => undefined
     },
-    rowKey: {
-      type: [Function, String] as PropType<(row: Recordable) => string | string>,
-      default: () => 'id'
-    },
+    rowKey: propTypes.string.def('id'),
     emptyText: propTypes.string.def('No Data'),
     defaultExpandAll: propTypes.bool.def(false),
     expandRowKeys: {
@@ -164,7 +160,7 @@ export default defineComponent({
       default: () => undefined
     },
     treeProps: {
-      type: Object as PropType<{ hasChildren: string; children: string; label: string }>,
+      type: Object as PropType<{ hasChildren?: string; children?: string; label?: string }>,
       default: () => ({ hasChildren: 'hasChildren', children: 'children', label: 'label' })
     },
     tableLayout: {
@@ -175,7 +171,7 @@ export default defineComponent({
     flexible: propTypes.bool.def(false)
   },
   emits: ['update:pageSize', 'update:currentPage', 'register'],
-  setup(props, { attrs, emit, expose }) {
+  setup(props, { attrs, emit, slots, expose }) {
     const elTableRef = ref<ComponentRef<typeof ElTable>>()
 
     // 注册
@@ -217,6 +213,23 @@ export default defineComponent({
       }
     }
 
+    const addColumn = (column: TableColumn, index?: number) => {
+      const { columns } = unref(getProps)
+      if (index) {
+        columns.splice(index, 0, column)
+      } else {
+        columns.push(column)
+      }
+    }
+
+    const delColumn = (field: string) => {
+      const { columns } = unref(getProps)
+      const index = columns.findIndex((item) => item.field === field)
+      if (index > -1) {
+        columns.splice(index, 1)
+      }
+    }
+
     const selections = ref<Recordable[]>([])
 
     const selectionChange = (selection: Recordable[]) => {
@@ -226,6 +239,8 @@ export default defineComponent({
     expose({
       setProps,
       setColumn,
+      delColumn,
+      addColumn,
       selections,
       elTableRef
     })
@@ -275,42 +290,17 @@ export default defineComponent({
     )
 
     const getBindValue = computed(() => {
-      const bindValue: Recordable = { ...attrs, ...props }
+      const bindValue: Recordable = { ...attrs, ...unref(getProps) }
       delete bindValue.columns
       delete bindValue.data
+      console.log(bindValue)
       return bindValue
     })
 
-    const renderTableSelection = () => {
-      const { selection, reserveSelection, align, headerAlign } = unref(getProps)
-      // 渲染多选
-      return selection ? (
-        <ElTableColumn
-          type="selection"
-          reserveSelection={reserveSelection}
-          align={align}
-          headerAlign={headerAlign}
-          width="50"
-        ></ElTableColumn>
-      ) : undefined
-    }
-
-    // const renderTableExpand = () => {
-    //   const { align, headerAlign, expand } = unref(getProps)
-    //   // 渲染展开行
-    //   return expand ? (
-    //     <ElTableColumn type="expand" align={align} headerAlign={headerAlign}>
-    //       {{
-    //         // @ts-ignore
-    //         default: (data: TableSlotDefault) => getSlot(slots, 'expand', data)
-    //       }}
-    //     </ElTableColumn>
-    //   ) : undefined
-    // }
-
     const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
       const { align, headerAlign, showOverflowTooltip } = unref(getProps)
       return columnsChildren.map((v) => {
+        if (v.hidden) return null
         const props = { ...v } as any
         if (props.children) delete props.children
 
@@ -318,11 +308,13 @@ export default defineComponent({
 
         const slots = {
           default: (...args: any[]) => {
-            if (props?.slots?.default) {
-              return slots.default(args)
-            } else if (children && children.length) {
-              return renderTreeTableColumn(children)
-            }
+            const data = args[0]
+            return children && children.length
+              ? renderTreeTableColumn(children)
+              : props?.slots?.default
+              ? props.slots.default(args)
+              : v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
+                data.row[v.field]
           }
         }
         if (props?.slots?.header) {
@@ -351,59 +343,69 @@ export default defineComponent({
         currentPage,
         align,
         headerAlign,
-        showOverflowTooltip
+        showOverflowTooltip,
+        reserveSelection
       } = unref(getProps)
-      return [renderTableSelection()].concat(
-        (columnsChildren || columns).map((v) => {
-          // 自定生成序号
-          if (v.type === 'index') {
-            return (
-              <ElTableColumn
-                type="index"
-                index={
-                  v.index
-                    ? v.index
-                    : (index) => setIndex(reserveIndex, index, pageSize, currentPage)
-                }
-                align={v.align || align}
-                headerAlign={v.headerAlign || headerAlign}
-                label={v.label}
-                width="65px"
-              ></ElTableColumn>
-            )
-          } 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)
-                }
+      return (columnsChildren || columns).map((v) => {
+        if (v.hidden) return null
+        if (v.type === 'index') {
+          return (
+            <ElTableColumn
+              type="index"
+              index={
+                v.index ? v.index : (index) => setIndex(reserveIndex, index, pageSize, currentPage)
               }
-            }
-            if (props?.slots?.header) {
-              slots['header'] = (...args: any[]) => props.slots.header(args)
-            }
+              align={v.align || align}
+              headerAlign={v.headerAlign || headerAlign}
+              label={v.label}
+              width="65px"
+            ></ElTableColumn>
+          )
+        } else if (v.type === 'selection') {
+          return (
+            <ElTableColumn
+              type="selection"
+              reserveSelection={reserveSelection}
+              align={align}
+              headerAlign={headerAlign}
+              width="50"
+            ></ElTableColumn>
+          )
+        } else {
+          const props = { ...v } as any
+          if (props.children) delete props.children
+
+          const children = v.children
 
-            return (
-              <ElTableColumn
-                showOverflowTooltip={showOverflowTooltip}
-                align={align}
-                headerAlign={headerAlign}
-                {...props}
-                prop={v.field}
-              >
-                {slots}
-              </ElTableColumn>
-            )
+          const slots = {
+            default: (...args: any[]) => {
+              const data = args[0]
+              return children && children.length
+                ? renderTreeTableColumn(children)
+                : props?.slots?.default
+                ? props.slots.default(args)
+                : v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
+                  data.row[v.field]
+            }
           }
-        })
-      )
+          if (props?.slots?.header) {
+            slots['header'] = (...args: any[]) => props.slots.header(args)
+          }
+
+          return (
+            <ElTableColumn
+              showOverflowTooltip={showOverflowTooltip}
+              align={align}
+              headerAlign={headerAlign}
+              {...props}
+              prop={v.field}
+            >
+              {slots}
+            </ElTableColumn>
+          )
+        }
+      })
     }
 
     return () => (
@@ -415,7 +417,9 @@ export default defineComponent({
           {...unref(getBindValue)}
         >
           {{
-            default: () => renderTableColumn()
+            default: () => renderTableColumn(),
+            empty: () => getSlot(slots, 'empty') || props.emptyText,
+            append: () => getSlot(slots, 'append')
           }}
         </ElTable>
         {unref(getProps).pagination ? (

+ 5 - 2
src/components/Table/src/types/index.ts

@@ -2,6 +2,11 @@ import { TableProps as ElTableProps } from 'element-plus'
 export interface TableColumn {
   field: string
   label?: string
+  type?: string
+  /**
+   * 是否隐藏
+   */
+  hidden?: boolean
   children?: TableColumn[]
   slots?: {
     default?: (...args: any[]) => JSX.Element | JSX.Element[] | null
@@ -69,8 +74,6 @@ export interface TableSetProps {
 export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> {
   pageSize?: number
   currentPage?: number
-  // 是否多选
-  selection?: boolean
   // 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip,
   showOverflowTooltip?: boolean
   // 表头

+ 1 - 1
src/hooks/web/useForm.ts

@@ -32,7 +32,7 @@ export const useForm = () => {
   const methods = {
     /**
      * @description 设置form组件的props
-     * @param field FormItem的field
+     * @param props form组件的props
      */
     setProps: async (props: FormProps = {}) => {
       const form = await getForm()

+ 85 - 119
src/hooks/web/useTable.ts

@@ -1,107 +1,46 @@
-import { Table, TableExpose, TableProps, TableSetProps } from '@/components/Table'
-import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
-import { ref, reactive, watch, computed, unref, nextTick, onMounted } from 'vue'
-import { get } from 'lodash-es'
-import { useI18n } from '@/hooks/web/useI18n'
-
-const { t } = useI18n()
-
-interface TableResponse<T = any> {
-  total: number
-  list: T[]
-  pageNumber: number
-  pageSize: number
-}
+import { Table, TableExpose, TableProps, TableSetProps, TableColumn } from '@/components/Table'
+import { ElTable } from 'element-plus'
+import { ref, watch, unref, nextTick, onMounted } from 'vue'
 
 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
-}
-
-interface TableObject<T = any> {
-  pageSize: number
-  currentPage: number
-  total: number
-  list: T[]
-  params: any
-  loading: boolean
-  currentRow: Nullable<T>
 }
 
 export const useTable = (config: UseTableConfig) => {
   const { immediate = true } = config
 
   const loading = ref(false)
-  const pageIndex = ref(1)
+  const currentPage = ref(1)
   const pageSize = ref(10)
   const total = ref(0)
   const dataList = ref<any[]>([])
 
-  const tableObject = reactive<TableObject>({
-    // 页数
-    pageSize: 10,
-    // 当前页
-    currentPage: 1,
-    // 总条数
-    total: 10,
-    // 表格数据
-    list: [],
-    // AxiosConfig 配置
-    params: {
-      // ...(config?.defaultParams || {})
-    },
-    // 加载中
-    loading: true,
-    // 当前行的数据
-    currentRow: null
-  })
-
-  const paramsObj = computed(() => {
-    return {
-      ...tableObject.params,
-      pageSize: tableObject.pageSize,
-      pageIndex: tableObject.currentPage
+  watch(
+    () => currentPage.value,
+    () => {
+      methods.getList()
     }
-  })
-
-  // watch(
-  //   () => tableObject.currentPage,
-  //   () => {
-  //     methods.getList()
-  //   }
-  // )
-
-  // watch(
-  //   () => tableObject.pageSize,
-  //   () => {
-  //     // 当前页不为1时,修改页数后会导致多次调用getList方法
-  //     if (tableObject.currentPage === 1) {
-  //       methods.getList()
-  //     } else {
-  //       tableObject.currentPage = 1
-  //       methods.getList()
-  //     }
-  //   }
-  // )
+  )
+
+  watch(
+    () => pageSize.value,
+    () => {
+      // 当前页不为1时,修改页数后会导致多次调用getList方法
+      if (unref(currentPage) === 1) {
+        methods.getList()
+      } else {
+        currentPage.value = 1
+        methods.getList()
+      }
+    }
+  )
 
   onMounted(() => {
     if (immediate) {
@@ -148,6 +87,9 @@ export const useTable = (config: UseTableConfig) => {
   // }
 
   const methods = {
+    /**
+     * 获取表单数据
+     */
     getList: async () => {
       loading.value = true
       try {
@@ -162,36 +104,62 @@ export const useTable = (config: UseTableConfig) => {
       } finally {
         loading.value = false
       }
-      // 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
-      // }
+    },
+
+    /**
+     * @description 设置table组件的props
+     * @param props table组件的props
+     */
+    setProps: async (props: TableProps = {}) => {
+      const table = await getTable()
+      table?.setProps(props)
+    },
+
+    /**
+     * @description 设置column
+     * @param columnProps 需要设置的列
+     */
+    setColumn: async (columnProps: TableSetProps[]) => {
+      const table = await getTable()
+      table?.setColumn(columnProps)
+    },
+
+    /**
+     * @description 新增column
+     * @param tableColumn 需要新增数据
+     * @param index 在哪里新增
+     */
+    addColumn: async (tableColumn: TableColumn, index?: number) => {
+      const table = await getTable()
+      table?.addColumn(tableColumn, index)
+    },
+
+    /**
+     * @description 删除column
+     * @param field 删除哪个数据
+     */
+    delColumn: async (field: string) => {
+      const table = await getTable()
+      table?.delColumn(field)
+    },
+
+    /**
+     * @description 获取全选数据
+     * @returns
+     */
+    getSelections: async () => {
+      const table = await getTable()
+      return table?.selections || []
+    },
+
+    /**
+     * @description 获取ElTable组件的实例
+     * @returns ElTable instance
+     */
+    getElTableExpose: async () => {
+      await getTable()
+      return unref(elTableRef)
     }
-    // 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()
@@ -222,11 +190,9 @@ export const useTable = (config: UseTableConfig) => {
 
   return {
     tableRegister: register,
-    elTableRef,
-    tableObject,
-    methods,
+    tableMethods: methods,
     tableState: {
-      pageIndex,
+      currentPage,
       pageSize,
       total,
       dataList,

+ 5 - 1
src/locales/en.ts

@@ -417,7 +417,11 @@ export default {
     hiddenExpandedRows: 'Hidden expanded rows',
     changeTitle: 'Change title',
     header: 'Header',
-    selectAllNone: 'Select all / none'
+    selectAllNone: 'Select all / none',
+    delOrAddAction: 'Delete or add action',
+    showOrHiddenStripe: 'Show or hidden stripe',
+    showOrHiddenBorder: 'Show or hidden border',
+    fixedHeaderOrAuto: 'Fixed header or auto'
   },
   richText: {
     richText: 'Rich text',

+ 5 - 1
src/locales/zh-CN.ts

@@ -412,7 +412,11 @@ export default {
     hiddenExpandedRows: '隐藏展开行',
     changeTitle: '修改标题',
     header: '头部',
-    selectAllNone: '全选/全不选'
+    selectAllNone: '全选/全不选',
+    delOrAddAction: '删除/添加操作列',
+    showOrHiddenStripe: '显示/隐藏斑马纹',
+    showOrHiddenBorder: '显示/隐藏边框',
+    fixedHeaderOrAuto: '固定头部/自动'
   },
   richText: {
     richText: '富文本',

+ 8 - 0
src/router/index.ts

@@ -184,6 +184,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
             meta: {
               title: 'UseTable'
             }
+          },
+          {
+            path: 'tree-table',
+            component: () => import('@/views/Components/Table/TreeTable.vue'),
+            name: 'TreeTable',
+            meta: {
+              title: 'TreeTable'
+            }
           }
         ]
       },

+ 115 - 0
src/views/Components/Table/TreeTable.vue

@@ -0,0 +1,115 @@
+<script setup lang="tsx">
+import { ContentWrap } from '@/components/ContentWrap'
+import { useI18n } from '@/hooks/web/useI18n'
+import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
+import { getTreeTableListApi } from '@/api/table'
+import { reactive, unref } from 'vue'
+import { ElTag, ElButton } from 'element-plus'
+import { useTable } from '@/hooks/web/useTable'
+
+const { tableRegister, tableState } = useTable({
+  fetchDataApi: async () => {
+    const { currentPage, pageSize } = tableState
+    const res = await getTreeTableListApi({
+      pageIndex: unref(currentPage),
+      pageSize: unref(pageSize)
+    })
+    return {
+      list: res.data.list,
+      total: res.data.total
+    }
+  }
+})
+const { loading, dataList, total, currentPage, pageSize } = tableState
+
+const { t } = useI18n()
+
+const columns = reactive<TableColumn[]>([
+  {
+    field: 'selection',
+    type: 'selection'
+  },
+  {
+    field: 'index',
+    label: t('tableDemo.index'),
+    type: 'index'
+  },
+  {
+    field: 'content',
+    label: t('tableDemo.header'),
+    children: [
+      {
+        field: 'title',
+        label: t('tableDemo.title')
+      },
+      {
+        field: 'author',
+        label: t('tableDemo.author')
+      },
+      {
+        field: 'display_time',
+        label: t('tableDemo.displayTime')
+      },
+      {
+        field: 'importance',
+        label: t('tableDemo.importance'),
+        formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
+          return (
+            <ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
+              {cellValue === 1
+                ? t('tableDemo.important')
+                : cellValue === 2
+                ? t('tableDemo.good')
+                : t('tableDemo.commonly')}
+            </ElTag>
+          )
+        }
+      },
+      {
+        field: 'pageviews',
+        label: t('tableDemo.pageviews')
+      }
+    ]
+  },
+  {
+    field: 'action',
+    label: t('tableDemo.action'),
+    slots: {
+      default: (data) => {
+        return (
+          <ElButton type="primary" onClick={() => actionFn(data)}>
+            {t('tableDemo.action')}
+          </ElButton>
+        )
+      }
+    }
+  }
+])
+
+const actionFn = (data: TableSlotDefault) => {
+  console.log(data)
+}
+</script>
+
+<template>
+  <ContentWrap :title="`TreeTable ${t('tableDemo.example')}`">
+    <Table
+      v-model:pageSize="pageSize"
+      v-model:currentPage="currentPage"
+      :columns="columns"
+      :data="dataList"
+      row-key="id"
+      :loading="loading"
+      :pagination="{
+        total: total
+      }"
+      @register="tableRegister"
+    />
+  </ContentWrap>
+</template>
+
+<style lang="less" scoped>
+.el-button {
+  margin-top: 10px;
+}
+</style>

+ 118 - 89
src/views/Components/Table/UseTableDemo.vue

@@ -1,18 +1,17 @@
 <script setup lang="tsx">
 import { ContentWrap } from '@/components/ContentWrap'
 import { useI18n } from '@/hooks/web/useI18n'
-import { Table, Pagination, TableColumn, TableSlotDefault } from '@/components/Table'
+import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
 import { getTableListApi } from '@/api/table'
-import { TableData } from '@/api/table/types'
-import { ref, h, reactive, unref } from 'vue'
+import { ref, reactive, unref } from 'vue'
 import { ElTag, ElButton } from 'element-plus'
 import { useTable } from '@/hooks/web/useTable'
 
-const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable({
+const { tableRegister, tableMethods, tableState } = useTable({
   fetchDataApi: async () => {
-    const { pageIndex, pageSize } = tableState
+    const { currentPage, pageSize } = tableState
     const res = await getTableListApi({
-      pageIndex: unref(pageIndex),
+      pageIndex: unref(currentPage),
       pageSize: unref(pageSize)
     })
     return {
@@ -20,37 +19,39 @@ const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable
       total: res.data.total
     }
   }
-  // getListApi: getTableListApi,
-  // response: {
-  //   list: 'list',
-  //   total: 'total'
-  // }
 })
-const { loading, dataList, total, pageIndex, pageSize } = tableState
-
-// const { getList } = methods
-
-// getList()
-
-// const {
-//   register: register2,
-//   tableObject: tableObject2,
-//   methods: methods2
-// } = useTable<TableData>({
-//   getListApi: getTableListApi,
-//   response: {
-//     list: 'list',
-//     total: 'total'
-//   }
-// })
-
-// const { getList: getList2 } = methods2
-
-// getList2()
+const { loading, dataList, total, currentPage, pageSize } = tableState
+const { setProps, setColumn, getElTableExpose, addColumn, delColumn } = tableMethods
 
 const { t } = useI18n()
 
 const columns = reactive<TableColumn[]>([
+  {
+    field: 'expand',
+    type: 'expand',
+    slots: {
+      default: (data: TableSlotDefault[]) => {
+        const { row } = data[0]
+        return (
+          <div class="ml-30px">
+            <div>
+              {t('tableDemo.title')}:{row.title}
+            </div>
+            <div>
+              {t('tableDemo.author')}:{row.author}
+            </div>
+            <div>
+              {t('tableDemo.displayTime')}:{row.display_time}
+            </div>
+          </div>
+        )
+      }
+    }
+  },
+  {
+    field: 'selection',
+    type: 'selection'
+  },
   {
     field: 'index',
     label: t('tableDemo.index'),
@@ -112,36 +113,30 @@ const actionFn = (data: TableSlotDefault) => {
   console.log(data)
 }
 
-const paginationObj = ref<Pagination>()
-
+const canShowPagination = ref(true)
 const showPagination = (show: boolean) => {
-  if (show) {
-    paginationObj.value = {
-      total: tableObject.total
-    }
-  } else {
-    paginationObj.value = undefined
-  }
+  canShowPagination.value = show
 }
 
 const reserveIndex = (custom: boolean) => {
-  const { setProps } = methods
   setProps({
     reserveIndex: custom
   })
 }
 
 const showSelections = (show: boolean) => {
-  const { setProps } = methods
-  setProps({
-    selection: show
-  })
+  setColumn([
+    {
+      field: 'selection',
+      path: 'hidden',
+      value: !show
+    }
+  ])
 }
 
 const index = ref(1)
 
 const changeTitle = () => {
-  const { setColumn } = methods
   setColumn([
     {
       field: 'title',
@@ -153,19 +148,69 @@ const changeTitle = () => {
 }
 
 const showExpandedRows = (show: boolean) => {
-  const { setProps } = methods
+  setColumn([
+    {
+      field: 'expand',
+      path: 'hidden',
+      value: !show
+    }
+  ])
+}
+
+const selectAllNone = async () => {
+  const elTableRef = await getElTableExpose()
+  elTableRef?.toggleAllSelection()
+}
+
+const showAction = ref(true)
+const delOrAddAction = () => {
+  if (unref(showAction)) {
+    delColumn('action')
+    showAction.value = false
+  } else {
+    addColumn({
+      field: 'action',
+      label: t('tableDemo.action'),
+      slots: {
+        default: (data) => {
+          return (
+            <ElButton type="primary" onClick={() => actionFn(data)}>
+              {t('tableDemo.action')}
+            </ElButton>
+          )
+        }
+      }
+    })
+    showAction.value = true
+  }
+}
+
+const showStripe = ref(false)
+const showOrHiddenStripe = () => {
   setProps({
-    expand: show
+    stripe: !unref(showStripe)
   })
+  showStripe.value = !unref(showStripe)
 }
 
-const selectAllNone = () => {
-  unref(elTableRef)?.toggleAllSelection()
+const height = ref<string | number>('auto')
+const fixedHeaderOrAuto = () => {
+  if (unref(height) === 'auto') {
+    setProps({
+      height: 300
+    })
+    height.value = 300
+  } else {
+    setProps({
+      height: 'auto'
+    })
+    height.value = 'auto'
+  }
 }
 </script>
 
 <template>
-  <ContentWrap :title="`UseTable ${t('tableDemo.operate')}`">
+  <ContentWrap :title="`UseTable ${t('tableDemo.operate')}`" style="margin-bottom: 20px">
     <ElButton @click="showPagination(true)">
       {{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }}
     </ElButton>
@@ -185,50 +230,34 @@ const selectAllNone = () => {
     <ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</ElButton>
 
     <ElButton @click="selectAllNone">{{ t('tableDemo.selectAllNone') }}</ElButton>
+
+    <ElButton @click="delOrAddAction">{{ t('tableDemo.delOrAddAction') }}</ElButton>
+
+    <ElButton @click="showOrHiddenStripe">{{ t('tableDemo.showOrHiddenStripe') }}</ElButton>
+
+    <ElButton @click="fixedHeaderOrAuto">{{ t('tableDemo.fixedHeaderOrAuto') }}</ElButton>
   </ContentWrap>
   <ContentWrap :title="`UseTable ${t('tableDemo.example')}`">
     <Table
       v-model:pageSize="pageSize"
-      v-model:currentPage="pageIndex"
+      v-model:currentPage="currentPage"
       :columns="columns"
       :data="dataList"
       :loading="loading"
-      :pagination="paginationObj"
+      :pagination="
+        canShowPagination
+          ? {
+              total: total
+            }
+          : undefined
+      "
       @register="tableRegister"
-    >
-      <template #expand="data">
-        <div class="ml-30px">
-          <div>{{ t('tableDemo.title') }}:{{ data.row.title }}</div>
-          <div>{{ t('tableDemo.author') }}:{{ data.row.author }}</div>
-          <div>{{ t('tableDemo.displayTime') }}:{{ data.row.display_time }}</div>
-        </div>
-      </template>
-    </Table>
+    />
   </ContentWrap>
-
-  <!-- <ContentWrap :title="`UseTable 2 ${t('tableDemo.example')}`">
-    <Table
-      v-model:pageSize="tableObject2.pageSize"
-      v-model:currentPage="tableObject2.currentPage"
-      :columns="columns"
-      :data="tableObject2.tableList"
-      :loading="tableObject2.loading"
-      :pagination="paginationObj"
-      @register="register2"
-    >
-      <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>
-          <div>{{ t('tableDemo.author') }}:{{ data.row.author }}</div>
-          <div>{{ t('tableDemo.displayTime') }}:{{ data.row.display_time }}</div>
-        </div>
-      </template>
-    </Table>
-  </ContentWrap> -->
 </template>
+
+<style lang="less" scoped>
+.el-button {
+  margin-top: 10px;
+}
+</style>