diff --git a/packages/amis-ui/scss/components/_table2.scss b/packages/amis-ui/scss/components/_table2.scss index fa3cdd22c09..d7e449df33a 100644 --- a/packages/amis-ui/scss/components/_table2.scss +++ b/packages/amis-ui/scss/components/_table2.scss @@ -619,6 +619,26 @@ .#{$ns}Table-header { padding: 0; } + + &-self-sticky { + position: relative !important; + + .#{$ns}Table-content { + overflow-x: unset !important; + } + + .#{$ns}Table-row { + z-index: 1; + } + + .#{$ns}Table-cell-self-sticky { + z-index: 2 !important; + } + + .#{$ns}Table-cell-fix-left { + z-index: 3 !important; + } + } } &.#{$ns}Table-ping-left { diff --git a/packages/amis-ui/src/components/table/Cell.tsx b/packages/amis-ui/src/components/table/Cell.tsx index 909bb183971..557f9bc2a70 100644 --- a/packages/amis-ui/src/components/table/Cell.tsx +++ b/packages/amis-ui/src/components/table/Cell.tsx @@ -14,6 +14,7 @@ const zIndex = 1; export interface Props extends ThemeProps { fixed?: string | boolean; // left | right + selfSticky?: boolean; rowSpan?: number | any; colSpan?: number | any; key?: string | number; @@ -33,6 +34,7 @@ export interface Props extends ThemeProps { export default class BodyCell extends React.PureComponent { static defaultProps = { fixed: '', + selfSticky: false, wrapperComponent: 'td', rowSpan: null, colSpan: null @@ -41,6 +43,7 @@ export default class BodyCell extends React.PureComponent { render() { const { fixed, + selfSticky, rowSpan, colSpan, children, @@ -54,16 +57,27 @@ export default class BodyCell extends React.PureComponent { testIdBuilder } = this.props; + let _style: object = {...style}; + + if (fixed || selfSticky) { + _style = { + position: 'sticky', + zIndex, + ..._style + }; + } + return ( 1 ? rowSpan : null} colSpan={colSpan && colSpan > 1 ? colSpan : null} className={cx('Table-cell', className, { [cx(`Table-cell-fix-${fixed}`)]: fixed, + [`Table-cell-self-sticky`]: selfSticky, [`text-${column?.align}`]: column?.align, [`align-${column?.vAlign}`]: column?.vAlign })} - style={fixed ? {position: 'sticky', zIndex, ...style} : {...style}} + style={_style} data-depth={depth || null} data-col={col} {...testIdBuilder?.getTestId()} diff --git a/packages/amis-ui/src/components/table/Head.tsx b/packages/amis-ui/src/components/table/Head.tsx index c1c866dda65..49b9d69e13b 100644 --- a/packages/amis-ui/src/components/table/Head.tsx +++ b/packages/amis-ui/src/components/table/Head.tsx @@ -9,7 +9,8 @@ import { getBuildColumns, getAllSelectableRows, updateFixedRow, - hasFixedColumn + hasFixedColumn, + updateStickyRow } from './util'; import { ColumnProps, @@ -50,6 +51,7 @@ export interface Props extends ThemeProps { onFilter?: Function; onResizeMouseDown: Function; testIdBuilder?: TestIdBuilder; + selfSticky?: boolean; } export default class Head extends React.PureComponent { @@ -83,7 +85,7 @@ export default class Head extends React.PureComponent { } updateFixedRow() { - const {classnames: cx} = this.props; + const {classnames: cx, selfSticky} = this.props; const thead = this.domRef.current; const children = thead?.children; for (let i = 0; i < (children?.length || 0); i++) { @@ -92,6 +94,10 @@ export default class Head extends React.PureComponent { this.prependColumns(cols); } + if (selfSticky) { + updateStickyRow(children as HTMLCollection, i); + } + if (hasFixedColumn(cols)) { updateFixedRow(children?.[i] as HTMLTableRowElement, cols, cx); } @@ -134,7 +140,8 @@ export default class Head extends React.PureComponent { onFilter, onResizeMouseDown, testIdBuilder, - className + className, + selfSticky } = this.props; const {thColumns, tdColumns} = getBuildColumns(columns); @@ -307,6 +314,7 @@ export default class Head extends React.PureComponent { colSpan={item.colSpan} classnames={cx} classPrefix={classPrefix} + selfSticky={selfSticky} fixed={item.fixed === true ? 'left' : item.fixed} className={cx({ 'Table-cell-last': thIndex === maxCount diff --git a/packages/amis-ui/src/components/table/index.tsx b/packages/amis-ui/src/components/table/index.tsx index 236f6d66808..30e4f59ea73 100644 --- a/packages/amis-ui/src/components/table/index.tsx +++ b/packages/amis-ui/src/components/table/index.tsx @@ -690,7 +690,9 @@ export class Table extends React.PureComponent { onSelectAll, onFilter, testIdBuilder, - headerClassName + headerClassName, + sticky, + autoFillHeight } = this.props; const rowSelectionKeyField = this.getRowSelectionKeyField(); @@ -705,6 +707,7 @@ export class Table extends React.PureComponent { return ( { resizable, columns, sticky, + autoFillHeight, classnames: cx } = this.props; @@ -1677,10 +1681,15 @@ export class Table extends React.PureComponent { ) : null} - {hasScrollY || sticky ? ( + {hasScrollY || (sticky && !autoFillHeight) ? ( this.renderScrollTable() ) : ( -
+
{this.renderTable()}
)} diff --git a/packages/amis-ui/src/components/table/util.ts b/packages/amis-ui/src/components/table/util.ts index 170a8c8c0ba..1b9da0d5c67 100644 --- a/packages/amis-ui/src/components/table/util.ts +++ b/packages/amis-ui/src/components/table/util.ts @@ -225,6 +225,18 @@ function getPreviousLeftWidth( return width; } +function getPreviousTopHeight(thead: HTMLCollection, rowIndex: number) { + let height = 0; + + for (let i = 0; i < rowIndex; i++) { + if (thead && thead[i]) { + const dom = thead[i] as HTMLElement; + height += dom.offsetHeight; + } + } + return height; +} + function getAfterRightWidth( doms: HTMLCollection, index: number, @@ -292,6 +304,18 @@ export function updateFixedRow( } } +// 更新一个tr下的th的top +export function updateStickyRow(thead: HTMLCollection, rowIndex: number) { + const children = thead[rowIndex]?.children || []; + + for (let i = 0; i < children.length; i++) { + const dom = children[i] as HTMLElement; + dom.style.removeProperty('top'); + dom.style.top = + rowIndex > 0 ? getPreviousTopHeight(thead, rowIndex) + 'px' : '0'; + } +} + export function hasFixedColumn(columns: Array) { return find(columns, column => column.fixed); }