import { PureComponent } from 'react'; import classnames from 'classnames'; import ColGroup from './ColGroup'; import { GridSortType, IGridOnChangeConfig, IGridScrollDelta, IGridInnerFixedType, } from './types'; import { IGridInnerColumn, IGridProps } from './Grid'; import Store from './Store'; import isNil from '../utils/isNil'; import ToolTip from '../tooltip'; import Icon from '../icon'; export interface IGridHeaderProps { size: IGridProps['size']; prefix: string; columns: Array>; sortType: GridSortType; defaultSortType?: GridSortType; sortBy?: string; onChange: (config: IGridOnChangeConfig) => void; store: Store; fixed?: IGridInnerFixedType; fixedColumnsHeadRowsHeight: Array; scroll: IGridScrollDelta; } interface IHeaderCell { key: string | number; className: string; children?: React.ReactNode; colSpan?: number; rowSpan?: number; } interface IGridHeaderState<> { rows: Array>; } const sortToolTipMap = new Map([ ['', '取消排序'], ['asc', '点击升序'], ['desc', '点击降序'], ]); class Header extends PureComponent< IGridHeaderProps, IGridHeaderState > { constructor(props: IGridHeaderProps) { super(props); this.state = { rows: this.getHeaderRows(props), }; } unsubscribe: any; getSortInfo = ( column: IGridInnerColumn, props: IGridHeaderProps ) => { const { sortBy, sortType = '', defaultSortType = 'desc' } = props; const name = column.name; let newSortType: GridSortType; if (name === sortBy) { if (sortType === '') { newSortType = defaultSortType; } else if (sortType === defaultSortType) { newSortType = defaultSortType === 'asc' ? 'desc' : 'asc'; } else { newSortType = ''; } } if (name !== sortBy) { newSortType = defaultSortType; } return { sortBy: name, sortType: newSortType, sortTooltip: sortToolTipMap.get(newSortType), }; }; getChildrenAndEvents = ( column: IGridInnerColumn, props: IGridHeaderProps ) => { const { prefix, sortBy, sortType, onChange } = props; const cn = classnames(`${prefix}-grid-thead-sort`, { [`${prefix}-grid-thead-sort-${sortType}`]: sortType && column.name === sortBy, }); if (column.needSort) { const { sortBy, sortType, sortTooltip } = this.getSortInfo(column, props); return { children: (
{column.title}
), onClick: () => onChange({ sortBy, sortType }), }; } return { children: column.title, }; }; getHeaderRows = ( passProps?: IGridHeaderProps, columns?: Array>, currentRow = 0, rows: Array> = [] ) => { const props = passProps || this.props; const { prefix, columns: propsColumns } = props; columns = columns || propsColumns; rows[currentRow] = rows[currentRow] || []; (columns || []).forEach((column, index) => { if (column.rowSpan && rows.length < column.rowSpan) { while (rows.length < column.rowSpan) { rows.push([]); } } const { name, key, className, colSpan, rowSpan, nowrap, noWrap, textAlign, width, } = column; const cell: IHeaderCell = { key: name || key || index, className: classnames(`${prefix}-grid-th`, className, { [`${prefix}-grid-text-align-${textAlign}`]: textAlign, [`${prefix}-grid-nowrap`]: noWrap ?? nowrap, [`${prefix}-grid-th-selection`]: ['selection-column', 'selection-column-single'].indexOf(key) !== -1, [`${prefix}-grid-th-expand`]: key === 'expand-column', [`${prefix}-grid-th-sortable`]: column.needSort, [`${prefix}-grid-th-break-word`]: typeof width !== undefined, }), ...this.getChildrenAndEvents(column, props), }; if (column.children) { this.getHeaderRows(props, column.children, currentRow + 1, rows); } if (typeof colSpan === 'number') { cell.colSpan = colSpan; } if (typeof rowSpan === 'number') { cell.rowSpan = rowSpan; } if (cell.colSpan !== 0) { rows[currentRow].push(cell); } }); return rows.filter(row => row.length > 0); }; subscribe = () => { const { store } = this.props; this.unsubscribe = store.subscribe('columns', () => { this.setState({ rows: this.getHeaderRows() }); }); }; componentDidMount() { this.subscribe(); } // 等重构再删了吧,改不动 // eslint-disable-next-line react/no-deprecated componentWillReceiveProps(nextProps: IGridHeaderProps) { if ( nextProps.columns !== this.props.columns || nextProps.sortType !== this.props.sortType || nextProps.sortBy !== this.props.sortBy ) { this.setState({ rows: this.getHeaderRows(nextProps), }); } } componentWillUnmount() { if (this.unsubscribe) { this.unsubscribe(); } } renderThead() { const { prefix, fixed, fixedColumnsHeadRowsHeight } = this.props; const { rows } = this.state; const headerHeight = fixedColumnsHeadRowsHeight[0]; const rowsLen = rows.length; return ( {(rows || []).map((row, index) => { const height = fixed && headerHeight ? (headerHeight as number) / rowsLen : undefined; return ( {row.map(({ key, ...props }) => ( ))} ); })} ); } render() { const { scroll, fixed, prefix, columns, size } = this.props; const headerStyle: React.CSSProperties = {}; if (!fixed && !isNil(scroll.x)) { headerStyle.width = scroll.x; } return scroll.y ? ( {this.renderThead()}
) : ( this.renderThead() ); } } export default Header;