diff --git a/packages/react-table/src/TableTr.tsx b/packages/react-table/src/TableTr.tsx index 2f1d2d7cff..fcfceb5515 100644 --- a/packages/react-table/src/TableTr.tsx +++ b/packages/react-table/src/TableTr.tsx @@ -1,12 +1,13 @@ import React, { useMemo, useState, useEffect } from 'react'; import Icon from '@uiw/react-icon'; -import { LocationWidth, TableProps } from './'; +import { LocationWidth, TableColumns, TableProps } from './'; import './style/index.less'; import { noop } from '@uiw/utils'; import { locationFixed } from './util'; interface TableTrProps { rowKey?: keyof T; + header: TableColumns[][]; data: T[]; keys: TableProps['columns']; render: { [key: string]: any }; @@ -19,7 +20,7 @@ interface TableTrProps { // 层级 hierarchy: number; childrenColumnName: string; - locationWidth: { [key: number]: LocationWidth }; + locationWidth: { [key: string]: LocationWidth }; } export default function TableTr(props: TableTrProps) { @@ -36,6 +37,7 @@ export default function TableTr(props: TableTr indentSize, childrenColumnName, locationWidth, + header, } = props; const [isOpacity, setIsOpacity] = useState(false); const [childrenIndex, setChildrenIndex] = useState(0); @@ -65,6 +67,14 @@ export default function TableTr(props: TableTr ); }; }, [expandIndex]); + const getIndex = (key: string) => { + let j = 0; + const i = header.findIndex((it) => { + j = it.findIndex((item) => item.key === key); + return j > -1; + }); + return `${i}${j}`; + }; if (!Array.isArray(data) || !data.length) { return null; } @@ -113,7 +123,11 @@ export default function TableTr(props: TableTr return ( {objs.children} diff --git a/packages/react-table/src/ThComponent.tsx b/packages/react-table/src/ThComponent.tsx index 5711369687..83d7c2667c 100644 --- a/packages/react-table/src/ThComponent.tsx +++ b/packages/react-table/src/ThComponent.tsx @@ -10,13 +10,18 @@ interface ThComponentProps { titleNode: JSX.Element; onCellHead: TableProps['onCellHead']; rowNum: number; - locationWidth: { [key: number]: LocationWidth }; - updateLocation: (params: LocationWidth, index: number) => void; + locationWidth: { [key: string]: LocationWidth }; + updateLocation: (params: LocationWidth, index: string, key: string, colSpan?: number) => void; } export default class ThComponent extends Component> { componentDidMount() { - const rect = ReactDOM.findDOMNode(this); - this.props.updateLocation({ width: (rect as Element).getBoundingClientRect().width }, this.props.colNum); + const rect = ReactDOM.findDOMNode(this) as Element; + this.props.updateLocation( + { width: rect.getBoundingClientRect().width }, + `${this.props.rowNum}${this.props.colNum}`, + this.props.item.key!, + this.props.item.colSpan, + ); } render() { @@ -34,7 +39,7 @@ export default class ThComponent extends Component> { onCellHead?.(item, colNum, rowNum!, evn)} > diff --git a/packages/react-table/src/Thead.tsx b/packages/react-table/src/Thead.tsx index 5cffc332c0..d4c600e4cd 100644 --- a/packages/react-table/src/Thead.tsx +++ b/packages/react-table/src/Thead.tsx @@ -9,8 +9,8 @@ export interface TheadProps extends IPr onCellHead?: TableProps['onCellHead']; align?: TableColumns['align']; className?: TableColumns['className']; - locationWidth?: { [key: number]: LocationWidth }; - updateLocation?: (params: LocationWidth, index: number) => void; + locationWidth?: { [key: string]: LocationWidth }; + updateLocation?: (params: LocationWidth, index: string, key: string, colSpan?: number) => void; } export default function TheadComponent( diff --git a/packages/react-table/src/index.tsx b/packages/react-table/src/index.tsx index d6e1a2e8ac..81023bc333 100644 --- a/packages/react-table/src/index.tsx +++ b/packages/react-table/src/index.tsx @@ -74,12 +74,15 @@ export interface LocationWidth { left?: number; right?: number; width: number; + key?: string; + colSpan?: number; } export interface ICellOptions { rowNum: number; colNum: number; keyName: string; } + export default function Table(props: TableProps = {}) { const { prefixCls = 'w-table', @@ -99,35 +102,70 @@ export default function Table(props: TablePro ...other } = props; const [expandIndex, setExpandIndex] = useState>([]); - const [locationWidth, setLocationWidth] = useState<{ [key: number]: LocationWidth }>({}); - const finalLocationWidth = useRef<{ [key: number]: LocationWidth }>({}); - const updateLocation = (params: LocationWidth, index: number) => { + const [locationWidth, setLocationWidth] = useState<{ [key: string]: LocationWidth }>({}); + const finalLocationWidth = useRef<{ [key: string]: LocationWidth }>({}); + const updateLocation = (params: LocationWidth, index: string, key: string, colSpan: number = 0) => { finalLocationWidth.current = { ...finalLocationWidth.current, [index]: { ...finalLocationWidth.current[index], ...params, + key: key, + colSpan, }, }; - if (index === columns.length - 1) { + if (index === `${header.length - 1}${header[header.length - 1].length - 1}`) { setLocationWidth(computed()); } }; - const computed = () => { - let left = 0, - right = 0; - for (let index = 0; index < columns.length; index++) { - if (finalLocationWidth.current[index]) { - finalLocationWidth.current[index].left = left; - left = finalLocationWidth.current[index].width + left; + const deepClumnsLocation = ( + params: Array | number>, + fistIndex: number, + leftOrRight: 'left' | 'right', + isReverse: boolean, + ) => { + let initialValue = 0, + lastIndex = isReverse ? 0 : params.length - 1, + deepParams: Array | number> = []; + params.forEach(() => { + let abs = Math.abs(lastIndex); + const i = `${fistIndex}${abs}`; + if (isReverse) { + lastIndex += 1; + } else { + lastIndex -= 1; } - } - for (let index = columns.length - 1; index > -1; index--) { - if (finalLocationWidth.current[index]) { - finalLocationWidth.current[index].right = right; - right = finalLocationWidth.current[index].width + right; + if (typeof params[abs] === 'number') { + initialValue = (params[abs] as number) + initialValue; + deepParams.push(params[abs]); + return; } - } + if (finalLocationWidth.current[i]) { + finalLocationWidth.current[i][leftOrRight] = initialValue; + initialValue = finalLocationWidth.current[i].width + initialValue; + } + if (Array.isArray((params[abs] as TableColumns).children)) { + deepParams.push(...(params[abs] as TableColumns).children!); + return; + } + if (finalLocationWidth.current[i]) { + deepParams.push(finalLocationWidth.current[i].width); + } else { + const parent = header.find((it) => it.find((it) => it.key === (params[abs] as TableColumns).key)) || []; + const sub = parent.findIndex((it) => it.key === (params[abs] as TableColumns).key); + if (finalLocationWidth.current[`${i[0]}${sub}`]) { + // 合并单元格 + deepParams.push(finalLocationWidth.current[`${i[0]}${sub}`].width); + } + } + }); + if (deepParams.filter((it) => typeof it !== 'number').length) + deepClumnsLocation(deepParams, fistIndex + 1, leftOrRight, isReverse); + }; + + const computed = () => { + deepClumnsLocation(columns, 0, 'left', true); + deepClumnsLocation(columns, 0, 'right', false); return finalLocationWidth.current; }; useEffect(() => { @@ -277,6 +315,7 @@ export default function Table(props: TablePro rowKey={rowKey} locationWidth={locationWidth} data={data} + header={header} keys={self.keys} render={render} ellipsis={ellipsis} diff --git a/packages/react-table/src/util.ts b/packages/react-table/src/util.ts index 5f96cf9d80..c66f8f015e 100644 --- a/packages/react-table/src/util.ts +++ b/packages/react-table/src/util.ts @@ -131,8 +131,8 @@ export function getAllColumnsKeys(data: TableColumns[], keys: TableColumns export function locationFixed( fixed: boolean | 'left' | 'right', - location: { [key: number]: LocationWidth }, - index: number, + location: { [key: string]: LocationWidth }, + index: string, ): React.CSSProperties { if (!fixed) return {}; if (fixed === 'right') return { right: location[index]?.right };