import React from 'react'; import {ClassNamesFn} from '../../theme'; import {IColumn, IRow} from '../../store/table'; import {SchemaNode, Action} from '../../types'; import {TableRow} from './TableRow'; import {filter} from '../../utils/tpl'; import {observer} from 'mobx-react'; import {trace, reaction} from 'mobx'; import {createObject, flattenTree} from '../../utils/helper'; import {LocaleProps} from '../../locale'; export interface TableBodyProps extends LocaleProps { className?: string; rowsProps?: any; tableClassName?: string; classnames: ClassNamesFn; columns: Array; rows: Array; render: (region: string, node: SchemaNode, props?: any) => JSX.Element; renderCell: ( region: string, column: IColumn, item: IRow, props: any ) => React.ReactNode; onCheck: (item: IRow) => void; onQuickChange?: ( item: IRow, values: object, saveImmediately?: boolean | any, savePristine?: boolean ) => void; footable?: boolean; ignoreFootableContent?: boolean; footableColumns: Array; checkOnItemClick?: boolean; buildItemProps?: (item: IRow, index: number) => any; onAction?: (e: React.UIEvent, action: Action, ctx: object) => void; rowClassNameExpr?: string; rowClassName?: string; data?: any; prefixRow?: Array; affixRow?: Array; } export class TableBody extends React.Component { reaction?: () => void; constructor(props: TableBodyProps) { super(props); const rows = props.rows; this.reaction = reaction( () => `${flattenTree(rows) .map(item => `${item.id}`) .join(',')}${rows .filter(item => item.checked) .map(item => item.id) .join(',')}`, () => this.forceUpdate(), { onError: () => this.reaction!() } ); } shouldComponentUpdate(nextProps: TableBodyProps) { const props = this.props; if ( props.columns !== nextProps.columns || props.buildItemProps !== nextProps.buildItemProps || props.prefixRow || props.affixRow ) { return true; } return false; } componentWillUnmount() { this.reaction?.(); } renderRows( rows: Array, columns = this.props.columns, rowProps: any = {} ): any { const { rowClassName, rowClassNameExpr, onAction, buildItemProps, checkOnItemClick, classnames: cx, render, renderCell, onCheck, onQuickChange, footable, ignoreFootableContent, footableColumns } = this.props; return rows.map((item: IRow, rowIndex: number) => { const itemProps = buildItemProps ? buildItemProps(item, rowIndex) : null; const doms = [ 1 && rowIndex === rows.length - 1 } )} columns={columns} renderCell={renderCell} render={render} onAction={onAction} onCheck={onCheck} // todo 先注释 quickEditEnabled={item.depth === 1} onQuickChange={onQuickChange} {...rowProps} /> ]; if (footable && footableColumns.length) { if (item.depth === 1) { doms.push( ); } } else if (item.children.length) { // 嵌套表格 doms.push( ...this.renderRows(item.children, columns, { ...rowProps, parent: item }) ); } return doms; }); } renderSummaryRow(items?: Array) { const {columns, render, data, classnames: cx, rows} = this.props; if (!(Array.isArray(items) && items.length)) { return null; } const filterColumns = columns.filter(item => item.toggable); const result: any[] = []; for (let index = 0; index < filterColumns.length; index++) { const item = items[filterColumns[index].rawIndex]; item && result.push({...item}); } // 如果是勾选栏,让它和下一列合并。 if (columns[0].type === '__checkme' && result[0]) { result[0].colSpan = (result[0].colSpan || 1) + 1; } // 如果是展开栏,让它和下一列合并。 if (columns[0].type === '__expandme' && result[0]) { result[0].colSpan = (result[0].colSpan || 1) + 1; } // 缺少的单元格补齐 const appendLen = columns.length - result.reduce((p, c) => p + (c.colSpan || 1), 0); if (appendLen) { const item = result.pop(); result.push({ ...item, colSpan: (item.colSpan || 1) + appendLen }); } const ctx = createObject(data, { items: rows.map(row => row.locals) }); return ( {result.map((item, index) => { const Com = item.isHead ? 'th' : 'td'; return ( {render(`summary-row/${index}`, item, { data: ctx })} ); })} ); } renderSummary(items?: Array) { return Array.isArray(items) ? items.some(i => Array.isArray(i)) ? items.map(i => this.renderSummaryRow(Array.isArray(i) ? i : [i])) : this.renderSummaryRow(items) : null; } render() { const { classnames: cx, className, render, rows, columns, rowsProps, prefixRow, affixRow, translate: __ } = this.props; return ( {rows.length ? ( <> {this.renderSummary(prefixRow)} {this.renderRows(rows, columns, rowsProps)} {this.renderSummary(affixRow)} ) : null} ); } }