Browse Source

feat: add generic support for Table

main
刘凯 1 year ago
parent
commit
68955d3a0b
  1. 18
      src/components/Table/src/BasicTable.vue
  2. 19
      src/components/Table/src/hooks/useDataSource.ts
  3. 21
      src/components/Table/src/props.ts
  4. 10
      src/components/Table/src/types/table.ts

18
src/components/Table/src/BasicTable.vue

@ -1,9 +1,9 @@
<!-- eslint-disable no-useless-call -->
<script lang="ts" setup>
<script lang="ts" setup generic="T extends Recordable = Recordable">
import { computed, inject, ref, toRaw, unref, useAttrs, useSlots, watchEffect } from 'vue'
import { Table } from 'ant-design-vue'
import { omit } from 'lodash-es'
import type { BasicTableProps, ColumnChangeParam, InnerHandlers, SizeType, TableActionType } from './types/table'
import type { BasicTableProps, ColumnChangeParam, InnerHandlers, SizeType, SlotBodyCellProps, TableActionType } from './types/table'
import HeaderCell from './components/HeaderCell.vue'
import { usePagination } from './hooks/usePagination'
@ -20,7 +20,7 @@ import { useTableExpand } from './hooks/useTableExpand'
import { createTableContext } from './hooks/useTableContext'
import { useTableFooter } from './hooks/useTableFooter'
import { useTableForm } from './hooks/useTableForm'
import { basicProps } from './props'
import { defineTableProps } from './props'
import { useDesign } from '@/hooks/web/useDesign'
import { PageWrapperFixedHeightKey } from '@/enums/pageEnum'
@ -30,7 +30,7 @@ import { warn } from '@/utils/log'
defineOptions({ name: 'BasicTable' })
const props = defineProps(basicProps)
const props = defineProps(defineTableProps<T>())
const emit = defineEmits([
'fetch-success',
@ -109,7 +109,7 @@ const {
reload,
getAutoCreateKey,
updateTableData,
} = useDataSource(
} = useDataSource<T>(
getProps,
{
tableData,
@ -239,7 +239,7 @@ function setProps(props: Partial<BasicTableProps>) {
innerPropsRef.value = { ...unref(innerPropsRef), ...props }
}
const tableAction: TableActionType = {
const tableAction: TableActionType<T> = {
reload: async params => void reload(params),
getSelectRows,
setSelectedRows,
@ -312,7 +312,8 @@ emit('register', tableAction, formActions)
@resize-column="setColumnWidth"
>
<template v-for="item in Object.keys($slots)" #[item]="data" :key="item">
<slot :name="item" v-bind="data || {}" />
<!-- eslint-disable-next-line vue/no-extra-parens -->
<slot :name="item" v-bind="((data || {}) as SlotBodyCellProps<T>)" />
</template>
<template #headerCell="{ column }">
<slot name="headerCell" v-bind="{ column }">
@ -321,7 +322,8 @@ emit('register', tableAction, formActions)
</template>
<!-- 增加对antdv3.x兼容 -->
<template #bodyCell="data">
<slot name="bodyCell" v-bind="data || {}" />
<!-- eslint-disable-next-line vue/no-extra-parens -->
<slot name="bodyCell" v-bind="((data || {}) as SlotBodyCellProps<T>)" />
</template>
<!-- <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index"> -->
<!-- <HeaderCell :column="column" /> -->

19
src/components/Table/src/hooks/useDataSource.ts

@ -5,6 +5,7 @@ import { cloneDeep, get, merge } from 'lodash-es'
import type { PaginationProps } from '../types/pagination'
import type { BasicTableProps, FetchParams, SorterResult } from '../types/table'
import { FETCH_SETTING, PAGE_SIZE, ROW_KEY } from '../const'
import type { EditRecordRow } from '../components/editable'
import { isBoolean, isFunction, isObject } from '@/utils/is'
import { buildUUID } from '@/utils/uuid'
@ -21,7 +22,7 @@ interface SearchState {
sortInfo: Recordable
filterInfo: Record<string, string[]>
}
export function useDataSource(
export function useDataSource<T extends Recordable = Recordable>(
propsRef: ComputedRef<BasicTableProps>,
{
getPaginationInfo,
@ -128,18 +129,18 @@ export function useDataSource(
return unref(dataSourceRef)
})
async function updateTableData(index: number, key: string, value: any) {
async function updateTableData<K extends keyof T>(index: number, key: K, value: T[K]): Promise<EditRecordRow<T>> {
const record = dataSourceRef.value[index]
if (record)
dataSourceRef.value[index][key] = value
(dataSourceRef as any).value[index][key] = value
return dataSourceRef.value[index]
return dataSourceRef.value[index] as any
}
function updateTableDataRecord(
rowKey: string | number,
record: Recordable,
): Recordable | undefined {
record: T,
): EditRecordRow<T> | undefined {
const row = findTableDataRecord(rowKey)
if (row) {
@ -200,14 +201,14 @@ export function useDataSource(
}
function insertTableDataRecord(
record: Recordable | Recordable[],
record: T | T[],
index?: number,
): Recordable[] | undefined {
): EditRecordRow<T>[] | undefined {
// if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
index = index ?? dataSourceRef.value?.length
const _record = isObject(record) ? [record as Recordable] : (record as Recordable[])
unref(dataSourceRef).splice(index, 0, ..._record)
return unref(dataSourceRef)
return unref(dataSourceRef) as any
}
function findTableDataRecord(rowKey: string | number) {

21
src/components/Table/src/props.ts

@ -10,11 +10,13 @@ import type {
TableSetting,
} from './types/table'
import { DEFAULT_FILTER_FN, DEFAULT_SIZE, DEFAULT_SORT_FN, FETCH_SETTING } from './const'
import type { EditRecordRow } from './components/editable'
import type { FormProps } from '@/components/Form'
import { propTypes } from '@/utils/propTypes'
export const basicProps = {
export function defineTableProps<T>() {
return {
clickToRowSelect: { type: Boolean, default: true },
isTreeTable: Boolean,
tableSetting: propTypes.shape<TableSetting>({}),
@ -42,7 +44,12 @@ export const basicProps = {
indentSize: propTypes.number.def(24),
canColDrag: { type: Boolean, default: true },
api: {
type: Function as PropType<(...arg: any[]) => Promise<any>>,
type: Function as PropType<
(...arg: any[]) => Promise<
| T[]
| { list: T[], pageNo?: number, pageSize?: number, total?: number }
>
>,
default: null,
},
beforeFetch: {
@ -102,7 +109,7 @@ export const basicProps = {
clearSelectOnPageChange: propTypes.bool,
resizeHeightOffset: propTypes.number.def(0),
rowSelection: {
type: Object as PropType<TableRowSelection | null>,
type: Object as PropType<TableRowSelection<EditRecordRow<T>> | null>,
default: null,
},
title: {
@ -114,11 +121,12 @@ export const basicProps = {
},
maxHeight: propTypes.number,
dataSource: {
type: Array as PropType<Recordable[]>,
type: Array as PropType<T[]>,
default: null,
},
rowKey: {
type: [String, Function] as PropType<string | ((record: Recordable) => string)>,
// eslint-disable-next-line ts/ban-types
type: [String, Function] as PropType<keyof T | ((record: T) => keyof T) | (string & {})>,
default: '',
},
bordered: propTypes.bool,
@ -137,7 +145,7 @@ export const basicProps = {
beforeEditSubmit: {
type: Function as PropType<
(data: {
record: Recordable
record: T
index: number
key: string | number
value: any
@ -149,3 +157,4 @@ export const basicProps = {
default: DEFAULT_SIZE,
},
}
}

10
src/components/Table/src/types/table.ts

@ -1,6 +1,7 @@
import type { VNodeChild } from 'vue'
import type { TableRowSelection as ITableRowSelection, Key } from 'ant-design-vue/lib/table/interface'
import type { ColumnProps } from 'ant-design-vue/lib/table'
import type { Table } from 'ant-design-vue'
import type { EditRecordRow } from '../components/editable'
import type { PaginationProps } from './pagination'
@ -210,7 +211,8 @@ export interface BasicTableProps<T = Recordable<any>> {
// 在分页改变的时候清空选项
clearSelectOnPageChange?: boolean
//
rowKey?: keyof T | ((record: T) => keyof T)
// eslint-disable-next-line ts/ban-types
rowKey?: keyof T | ((record: T) => keyof T) | (string & {})
// 数据
dataSource?: T[]
// 标题右侧提示
@ -382,7 +384,7 @@ export interface BasicTableProps<T = Recordable<any>> {
* The cell will not submit data while callback return false
*/
beforeEditSubmit?: (data: {
record: Recordable
record: T
index: number
key: string | number
value: any
@ -500,3 +502,7 @@ export interface ColumnChangeParam {
export interface InnerHandlers {
onColumnsChange: (data: ColumnChangeParam[]) => void
}
export type SlotBodyCellProps<T> =
& Omit<Parameters<Required<InstanceType<typeof Table>['$slots']>['bodyCell']>[0], 'record'>
& { record: EditRecordRow<T> }