import { Button, Divider, Input, Popconfirm, Table, message } from 'antd'; import React, { Fragment, PureComponent } from 'react'; import { isEqual } from 'lodash'; import styles from '../style.less'; interface TableFormDateType { key: string; workId?: string; name?: string; department?: string; isNew?: boolean; editable?: boolean; } interface TableFormProps { loading?: boolean; value?: TableFormDateType[]; onChange?: (value: TableFormDateType[]) => void; } interface TableFormState { loading?: boolean; value?: TableFormDateType[]; data?: TableFormDateType[]; } class TableForm extends PureComponent { static getDerivedStateFromProps(nextProps: TableFormProps, preState: TableFormState) { if (isEqual(nextProps.value, preState.value)) { return null; } return { data: nextProps.value, value: nextProps.value, }; } clickedCancel: boolean = false; index = 0; cacheOriginData = {}; columns = [ { title: '成员姓名', dataIndex: 'name', key: 'name', width: '20%', render: (text: string, record: TableFormDateType) => { if (record.editable) { return ( this.handleFieldChange(e, 'name', record.key)} onKeyPress={e => this.handleKeyPress(e, record.key)} placeholder="成员姓名" /> ); } return text; }, }, { title: '工号', dataIndex: 'workId', key: 'workId', width: '20%', render: (text: string, record: TableFormDateType) => { if (record.editable) { return ( this.handleFieldChange(e, 'workId', record.key)} onKeyPress={e => this.handleKeyPress(e, record.key)} placeholder="工号" /> ); } return text; }, }, { title: '所属部门', dataIndex: 'department', key: 'department', width: '40%', render: (text: string, record: TableFormDateType) => { if (record.editable) { return ( this.handleFieldChange(e, 'department', record.key)} onKeyPress={e => this.handleKeyPress(e, record.key)} placeholder="所属部门" /> ); } return text; }, }, { title: '操作', key: 'action', render: (text: string, record: TableFormDateType) => { const { loading } = this.state; if (!!record.editable && loading) { return null; } if (record.editable) { if (record.isNew) { return ( this.saveRow(e, record.key)}>添加 this.remove(record.key)}> 删除 ); } return ( this.saveRow(e, record.key)}>保存 this.cancel(e, record.key)}>取消 ); } return ( this.toggleEditable(e, record.key)}>编辑 this.remove(record.key)}> 删除 ); }, }, ]; constructor(props: TableFormProps) { super(props); this.state = { data: props.value, loading: false, value: props.value, }; } getRowByKey(key: string, newData?: TableFormDateType[]) { const { data = [] } = this.state; return (newData || data).filter(item => item.key === key)[0]; } toggleEditable = (e: React.MouseEvent | React.KeyboardEvent, key: string) => { e.preventDefault(); const { data = [] } = this.state; const newData = data.map(item => ({ ...item })); const target = this.getRowByKey(key, newData); if (target) { // 进入编辑状态时保存原始数据 if (!target.editable) { this.cacheOriginData[key] = { ...target }; } target.editable = !target.editable; this.setState({ data: newData }); } }; newMember = () => { const { data = [] } = this.state; const newData = data.map(item => ({ ...item })); newData.push({ key: `NEW_TEMP_ID_${this.index}`, workId: '', name: '', department: '', editable: true, isNew: true, }); this.index += 1; this.setState({ data: newData }); }; remove(key: string) { const { data = [] } = this.state; const { onChange } = this.props; const newData = data.filter(item => item.key !== key); this.setState({ data: newData }); if (onChange) { onChange(newData); } } handleKeyPress(e: React.KeyboardEvent, key: string) { if (e.key === 'Enter') { this.saveRow(e, key); } } handleFieldChange(e: React.ChangeEvent, fieldName: string, key: string) { const { data = [] } = this.state; const newData = [...data]; const target = this.getRowByKey(key, newData); if (target) { target[fieldName] = e.target.value; this.setState({ data: newData }); } } saveRow(e: React.MouseEvent | React.KeyboardEvent, key: string) { e.persist(); this.setState({ loading: true, }); setTimeout(() => { if (this.clickedCancel) { this.clickedCancel = false; return; } const target = this.getRowByKey(key) || {}; if (!target.workId || !target.name || !target.department) { message.error('请填写完整成员信息。'); (e.target as HTMLInputElement).focus(); this.setState({ loading: false, }); return; } delete target.isNew; this.toggleEditable(e, key); const { data = [] } = this.state; const { onChange } = this.props; if (onChange) { onChange(data); } this.setState({ loading: false, }); }, 500); } cancel(e: React.MouseEvent, key: string) { this.clickedCancel = true; e.preventDefault(); const { data = [] } = this.state; const newData = [...data]; newData.map(item => { if (item.key === key) { if (this.cacheOriginData[key]) { delete this.cacheOriginData[key]; return { ...item, ...this.cacheOriginData[key], editable: false, }; } } return item; }); this.setState({ data: newData }); this.clickedCancel = false; } render() { const { loading, data } = this.state; return ( loading={loading} columns={this.columns} dataSource={data} pagination={false} rowClassName={record => (record.editable ? styles.editable : '')} /> ); } } export default TableForm;