From 0ef26f8372cbcb71a20de69f25fb5f2b291d91df Mon Sep 17 00:00:00 2001 From: Barrior Date: Tue, 18 Jun 2024 16:27:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=90=88=E8=AE=A1?= =?UTF-8?q?=E6=A0=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../search-table-react/src/SearchTable.tsx | 11 ++ .../src/hooks/useColumns/index.tsx | 2 +- .../src/hooks/useRequest.ts | 17 ++- .../src/hooks/useScrollY.ts | 12 +- .../src/hooks/useSummary/helpers.tsx | 129 ++++++++++++++++++ .../src/hooks/useSummary/index.tsx | 48 +++++++ .../search-table-react/src/typings/index.d.ts | 4 + .../search-table-react/src/typings/table.d.ts | 9 ++ 8 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 packages/search-table-react/src/hooks/useSummary/helpers.tsx create mode 100644 packages/search-table-react/src/hooks/useSummary/index.tsx diff --git a/packages/search-table-react/src/SearchTable.tsx b/packages/search-table-react/src/SearchTable.tsx index 5236763..f5ef1cb 100644 --- a/packages/search-table-react/src/SearchTable.tsx +++ b/packages/search-table-react/src/SearchTable.tsx @@ -11,6 +11,7 @@ import useColumns from './hooks/useColumns' import useRequest from './hooks/useRequest' import useScrollY from './hooks/useScrollY' import useSearch from './hooks/useSearch' +import useSummary from './hooks/useSummary' import type { ISearchTableProps, ISearchTableRef } from './typings/index.d' const { classNames, isPlainObject } = utils @@ -49,6 +50,8 @@ const SearchTable = ( loading, dataSource, setDataSource, + summaryData, + setSummaryData, innerPagination, runRequest, requestParamsRef, @@ -59,6 +62,9 @@ const SearchTable = ( updateScrollY, }) + // 总结栏处理 + const { finalSummary } = useSummary({ table, finalColumns, summaryData }) + // 搜索栏 const { handleSearchChange, @@ -98,6 +104,10 @@ const SearchTable = ( setDataSource(data) forceUpdate() }, + setSummaryDataAndRender: (data) => { + setSummaryData(data) + forceUpdate() + }, updateScrollY, })) @@ -149,6 +159,7 @@ const SearchTable = ( y: scrollY, ...table?.scroll, }} + summary={finalSummary} /> {footer?.(comRenderParams)} diff --git a/packages/search-table-react/src/hooks/useColumns/index.tsx b/packages/search-table-react/src/hooks/useColumns/index.tsx index dfbc2f6..a491b78 100644 --- a/packages/search-table-react/src/hooks/useColumns/index.tsx +++ b/packages/search-table-react/src/hooks/useColumns/index.tsx @@ -53,7 +53,7 @@ export default function useColumns({ table }: IUseColumnsParams) { columns.unshift({ title: '序号', align: 'center', - width: 60, + width: 70, fixed: 'left', render: (_t: string, _r: object, index: number) => index + 1, key: EColumnsKeys.rowNumber, diff --git a/packages/search-table-react/src/hooks/useRequest.ts b/packages/search-table-react/src/hooks/useRequest.ts index 7f61b4c..61d1a40 100644 --- a/packages/search-table-react/src/hooks/useRequest.ts +++ b/packages/search-table-react/src/hooks/useRequest.ts @@ -32,11 +32,17 @@ export default function useRequest({ searchValueRef, }: IUseRequest) { // 分页参数 - const paginationRef = useRef({ current: 1, pageSize: 10, total: 0 }) + const paginationRef = useRef({ + current: 1, + pageSize: (table.pagination !== false ? table.pagination?.defaultPageSize : 10) || 10, + total: 0, + }) // 请求参数 const requestParamsRef = useRef({}) // 表格数据源 const dataSourceRef = useRef([]) + // 合计栏数据 + const summaryDataRef = useRef({}) // 是否加载表格数据中 const [loading, setLoading] = useState(false) @@ -95,6 +101,9 @@ export default function useRequest({ // 存储数据源 dataSourceRef.current = res.data || [] + // 存储合计栏数据 + summaryDataRef.current = res.summaryData || {} + // 成功返回数据 result = { ...res, @@ -145,10 +154,16 @@ export default function useRequest({ dataSourceRef.current = data }) + const setSummaryData = useMemoizedFn((data: IObjectAny) => { + summaryDataRef.current = data + }) + return { loading, dataSource: dataSourceRef.current, setDataSource, + summaryData: summaryDataRef.current, + setSummaryData, innerPagination, requestParamsRef, runRequest, diff --git a/packages/search-table-react/src/hooks/useScrollY.ts b/packages/search-table-react/src/hooks/useScrollY.ts index 523f14b..a42e9df 100644 --- a/packages/search-table-react/src/hooks/useScrollY.ts +++ b/packages/search-table-react/src/hooks/useScrollY.ts @@ -30,11 +30,14 @@ export default function useScrollY({ table, rootElemRef }: IUseScrollYParams) { const tableElem = rootElemRef.current.querySelector(`.${EClassNames.table}`) const theadElem = tableElem?.querySelector('thead') + const tfootElem = tableElem?.querySelector('tfoot') const paginationElem = tableElem?.querySelector(`.${EClassNames.pagination}`) + const tableElements = [theadElem, tfootElem, paginationElem] // 内容元素的总高度 let elementsHeight = 0 + // 累加子节点高度,排除 table forEach(rootElemRef.current.children, (child) => { // 表格元素的内容高度这里排除,需要单独计算 if (child !== tableElem) { @@ -45,11 +48,10 @@ export default function useScrollY({ table, rootElemRef }: IUseScrollYParams) { // 加上表格的 marginTop elementsHeight += getNumericStyleValue(tableElem as HTMLElement, 'marginTop') - // 加上表头高度 - elementsHeight += calcOuterHeight(theadElem) - - // 加上分页高度 - elementsHeight += calcOuterHeight(paginationElem as HTMLElement) + // 累加表格内元素 + forEach(tableElements, (elem) => { + elementsHeight += calcOuterHeight(elem as HTMLElement) + }) // 设置 scrollY 的值 setScrollY(rootElemRef.current.clientHeight - elementsHeight) diff --git a/packages/search-table-react/src/hooks/useSummary/helpers.tsx b/packages/search-table-react/src/hooks/useSummary/helpers.tsx new file mode 100644 index 0000000..11125bf --- /dev/null +++ b/packages/search-table-react/src/hooks/useSummary/helpers.tsx @@ -0,0 +1,129 @@ +import type { IObjectAny } from '@schema-render/core-react' +import { utils } from '@schema-render/core-react' +import { Table } from 'antd' +import type { Key, ReactNode } from 'react' + +import { EColumnsKeys } from '../../constants' +import type { IColumnType } from '../../typings/table.d' +import { forEach } from '../../utils/common' + +const { isArray, isNil } = utils + +export interface ICreateTableSummaryParams { + /** 平铺的列数据 */ + flattenedColumns: IColumnType[] + /** 「合计」数据 */ + summaryData: IObjectAny + /** 「合计」文案 */ + summaryText?: ReactNode + /** + * 表格是否存在 checkbox 选择框,存在会给「合计」索引自动 +1 + */ + hasRowSelection?: boolean + /** + * 是否存在序号栏 + */ + hasRowNumber?: boolean +} + +/** + * 获取默认文案 + */ +function getSummaryDefaultText(dataKey: Key, summaryText: ReactNode) { + // 序号栏显示“合计”文案 + if (dataKey === EColumnsKeys.rowNumber) { + return summaryText + } + + // 操作栏默认为空 + if (dataKey === EColumnsKeys.actions) { + return '' + } + + // 其他列数据不存在显示中横线 + return '-' +} + +/** + * 获取平铺的 columns + */ +export function getFlattenedColumns(columns?: IColumnType[]) { + const flattened: IColumnType[] = [] + + function traverse(list?: IColumnType[]) { + forEach(list, (item) => { + if (isArray(item.children)) { + traverse(item.children) + } else { + flattened.push(item) + } + }) + } + + traverse(columns) + + return flattened +} + +/** + * 创建 Antd Table 总结栏列表数据 + */ +function createTableSummaryItems({ + flattenedColumns, + summaryData, + summaryText = '合计', + hasRowNumber = false, + hasRowSelection = false, +}: ICreateTableSummaryParams) { + const resultList: { index: number; text: ReactNode; colSpan?: number }[] = [] + + let index = -1 + + if (hasRowSelection) { + index++ + resultList.push({ + index, + text: hasRowNumber ? '' : summaryText, + }) + } + + forEach(flattenedColumns, ({ key, dataIndex }) => { + const strDataIndex = (isArray(dataIndex) ? dataIndex.join('.') : dataIndex) as string + const dataKey = key || strDataIndex + const content = summaryData[dataKey] + + index++ + + resultList.push({ + index, + text: isNil(content) ? getSummaryDefaultText(dataKey, summaryText) : content, + }) + }) + + return resultList +} + +/** + * 创建 antd table 总结栏 + */ +export function createTableSummary(p: ICreateTableSummaryParams) { + const items = createTableSummaryItems(p) + return ( + + + {items.map((item) => { + return ( + + {item.text} + + ) + })} + + + ) +} diff --git a/packages/search-table-react/src/hooks/useSummary/index.tsx b/packages/search-table-react/src/hooks/useSummary/index.tsx new file mode 100644 index 0000000..43f9a19 --- /dev/null +++ b/packages/search-table-react/src/hooks/useSummary/index.tsx @@ -0,0 +1,48 @@ +import type { IObjectAny } from '@schema-render/core-react' +import { useMemoizedFn } from '@schema-render/core-react' +import { useMemo } from 'react' + +import type { ISearchTableProps } from '../../typings/index.d' +import type { IColumnType } from '../../typings/table' +import { isEmpty } from '../../utils/common' +import { createTableSummary, getFlattenedColumns } from './helpers' + +interface IUseSummaryParams { + table: ISearchTableProps['table'] + finalColumns: IColumnType[] + summaryData: IObjectAny +} + +/** + * 总结栏处理:支持合计数据分布 + */ +export default function useSummary({ + table, + finalColumns, + summaryData, +}: IUseSummaryParams) { + const flattenedColumns = useMemo( + () => getFlattenedColumns(finalColumns), + [finalColumns] + ) + + const renderSummary = useMemoizedFn(() => { + return createTableSummary({ + flattenedColumns, + summaryData, + summaryText: table.summaryText, + hasRowSelection: !!table.rowSelection, + hasRowNumber: table.showRowNumber, + }) + }) + + const finalSummary = table.summary + ? table.summary + : isEmpty(summaryData) + ? undefined + : renderSummary + + return { + finalSummary, + } +} diff --git a/packages/search-table-react/src/typings/index.d.ts b/packages/search-table-react/src/typings/index.d.ts index 54be349..72f22fa 100644 --- a/packages/search-table-react/src/typings/index.d.ts +++ b/packages/search-table-react/src/typings/index.d.ts @@ -154,6 +154,10 @@ export interface ISearchTableRef { * 设置表格列表数据 */ setDataSourceAndRender: (dataSource: IObjectAny[]) => void + /** + * 设置合计栏数据 + */ + setSummaryDataAndRender: (data: IObjectAny) => void /** * 获取搜索参数 */ diff --git a/packages/search-table-react/src/typings/table.d.ts b/packages/search-table-react/src/typings/table.d.ts index 1713ac0..2df32a8 100644 --- a/packages/search-table-react/src/typings/table.d.ts +++ b/packages/search-table-react/src/typings/table.d.ts @@ -51,6 +51,15 @@ export type ITableProps = IAntdTableProps & { * 自动计算表格 scrollY 属性,达到自动适配屏幕高度的效果 */ autoScrollY?: boolean + /** + * 合计栏 + */ + summaryText?: ReactNode + + // 注册 valueType + // registerValueType?: { + // [type: string]: (text: string, record: IObjectAny, index: number) => ReactNode + // } } /**