import React , { Component } from 'react' ; import { Alert , Form , Table } from 'antd' ; import { ColumnProps , TableRowSelection , TableProps } from 'antd/es/table' ; import { FormattedMessage } from 'umi-plugin-react/locale' ; import { FormComponentProps } from 'antd/es/form' ; import { WrappedFormUtils } from 'antd/es/form/Form' ; import EditableCell , { EditingRender } from './EditableCell' ; import styles from './index.less' ; export interface TableListItem { id ? : number | string ; disabled ? : boolean ; editing ? : boolean ; } export interface StandardTableColumnProps < T > extends Omit < ColumnProps < T > , 'render' > { editable ? : boolean ; editingRender ? : ( ( text : any , record : any , index : number , title : string , dataIndex : string , form : WrappedFormUtils ) => React . ReactNode ) | EditingRender ; needTotal ? : boolean ; total ? : number ; render ? : ( text : any , record : T , index : number , form ? : WrappedFormUtils ) => React . ReactNode ; } export interface StandardTableProps < T > extends Omit < TableProps < T > , 'columns' > , FormComponentProps { columns : StandardTableColumnProps < T > [ ] ; data ? : { list : T [ ] ; pagination ? : StandardTableProps < T > [ 'pagination' ] ; } ; selectedRows ? : T [ ] ; onSelectRow ? : ( rows : T [ ] ) => void ; } interface StandardTableState < T > { selectedRowKeys : string [ ] ; needTotalList : StandardTableColumnProps < T > [ ] ; } function initTotalList < T > ( columns ) { if ( ! columns ) { return [ ] ; } const totalList = [ ] ; columns . forEach ( column => { if ( column . needTotal ) { totalList . push ( { ... column , total : 0 } ) ; } } ) ; return totalList ; } class StandardTable < T extends TableListItem > extends Component < StandardTableProps < T > , StandardTableState < T > > { static getDerivedStateFromProps < T > ( nextProps ) { if ( nextProps . selectedRows && nextProps . selectedRows . length === 0 ) { const needTotalList = initTotalList ( nextProps . columns ) ; return { selectedRowKeys : [ ] , needTotalList , } ; } return null ; } constructor ( props ) { super ( props ) ; const { columns } = props ; const needTotalList = initTotalList ( columns ) ; this . state = { selectedRowKeys : [ ] , needTotalList , } ; } handleRowSelectChange : TableRowSelection < T > [ 'onChange' ] = ( selectedRowKeys , selectedRows ) => { const currySelectedRowKeys = selectedRowKeys as string [ ] ; let { needTotalList } = this . state ; needTotalList = needTotalList . map ( item => ( { ... item , total : selectedRows . reduce ( ( sum , val ) => sum + parseFloat ( val [ item . dataIndex || 0 ] ) , 0 ) , } ) ) ; const { onSelectRow } = this . props ; if ( onSelectRow ) { onSelectRow ( selectedRows ) ; } this . setState ( { selectedRowKeys : currySelectedRowKeys , needTotalList } ) ; } ; handleTableChange : TableProps < T > [ 'onChange' ] = ( pagination , filters , sorter , ... rest ) => { const { onChange } = this . props ; if ( onChange ) { onChange ( pagination , filters , sorter , ... rest ) ; } } ; cleanSelectedKeys = ( ) => { if ( this . handleRowSelectChange ) { this . handleRowSelectChange ( [ ] , [ ] ) ; } } ; render ( ) { const { selectedRowKeys , needTotalList } = this . state ; const { form , columns , data , rowKey , onSelectRow , ... rest } = this . props ; const { list = [ ] , pagination = false } = data || { } ; const paginationProps = { showSizeChanger : true , showQuickJumper : true , showTotal : ( total , range ) => ( < FormattedMessage id = "component.pagination.total" values = { { range0 : range [ 0 ] , range1 : range [ 1 ] , total } } />), ... pagination , } ; const { scroll } = this . props ; let scrollX = false ; if ( scroll && scroll . x ) { scrollX = true ; } const rowSelection = { fixed : scrollX , selectedRowKeys , onChange : this . handleRowSelectChange , getCheckboxProps : ( record ) => ( { disabled : record . disabled , } ) , } ; const components = { body : { cell : EditableCell , } , } ; const wrappedColumns = columns . map ( col => { let { render } = col ; if ( typeof render !== 'undefined' ) { render = ( text , record , index ) => col . render ( text , record , index , form ) ; } if ( col . editable === false ) { return { ... col , render , } ; } return { ... col , render , onCell : ( record ) => ( { record , dataIndex : col . dataIndex , title : col . title , editing : record . editing , editingRender : col . editingRender , form , } ) , } ; } ) ; return ( < div className = { styles . standardTable } > { onSelectRow && ( < div className = { styles . tableAlert } > < Alert message = { < > < FormattedMessage id = "component.standardTable.items.selected" values = { { count : < a style = { { fontWeight : 600 } } > { selectedRowKeys . length } < /a> }}/ > { needTotalList . map ( ( item , index ) => ( < span style = { { marginLeft : 8 } } key = { item . dataIndex } > { item . title } 总计 & nbsp ; < span style = { { fontWeight : 600 } } > { item . render ? item . render ( item . total , item as any , index ) : item . total } < /span> < /span>))} < a onClick = { this . cleanSelectedKeys } style = { { marginLeft : 24 } } > < FormattedMessage id = "component.standardTable.items.clear" / > < /a> < />} type="info" showIcon/ > < /div>)} < Table rowKey = { rowKey || 'id' } rowSelection = { onSelectRow && rowSelection } dataSource = { list } pagination = { pagination ? paginationProps : false } components = { components } columns = { wrappedColumns } onChange = { this . handleTableChange } { ... rest } /> < /div>); } } export default Form . create < StandardTableProps < any > > ( ) ( StandardTable ) ;