You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.4 KiB
235 lines
6.4 KiB
import React, { PureComponent } from 'react';
|
|
import Debounce from 'lodash-decorators/debounce';
|
|
import Bind from 'lodash-decorators/bind';
|
|
import { Table, Button, Input, message, Popconfirm, Divider } from 'antd';
|
|
import styles from './style.less';
|
|
|
|
export default class TableForm extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
data: props.value,
|
|
};
|
|
}
|
|
componentWillReceiveProps(nextProps) {
|
|
if ('value' in nextProps) {
|
|
this.setState({
|
|
data: nextProps.value,
|
|
});
|
|
}
|
|
}
|
|
getRowByKey(key, newData) {
|
|
return (newData || this.state.data).filter(item => item.key === key)[0];
|
|
}
|
|
index = 0;
|
|
cacheOriginData = {};
|
|
handleSubmit = (e) => {
|
|
e.preventDefault();
|
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
|
if (!err) {
|
|
this.props.dispatch({
|
|
type: 'form/submit',
|
|
payload: values,
|
|
});
|
|
}
|
|
});
|
|
}
|
|
@Bind()
|
|
@Debounce(400)
|
|
toggleEditable(e, key) {
|
|
e.preventDefault();
|
|
const newData = this.state.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 });
|
|
}
|
|
}
|
|
remove(key) {
|
|
const newData = this.state.data.filter(item => item.key !== key);
|
|
this.setState({ data: newData });
|
|
this.props.onChange(newData);
|
|
}
|
|
newMember = () => {
|
|
const newData = this.state.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 });
|
|
}
|
|
handleKeyPress(e, key) {
|
|
if (e.key === 'Enter') {
|
|
this.saveRow(e, key);
|
|
}
|
|
}
|
|
handleFieldChange(e, fieldName, key) {
|
|
const newData = this.state.data.map(item => ({ ...item }));
|
|
const target = this.getRowByKey(key, newData);
|
|
if (target) {
|
|
target[fieldName] = e.target.value;
|
|
this.setState({ data: newData });
|
|
}
|
|
}
|
|
saveRow(e, key) {
|
|
e.persist();
|
|
// save field when blur input
|
|
setTimeout(() => {
|
|
if (document.activeElement.tagName === 'INPUT' &&
|
|
document.activeElement !== e.target) {
|
|
return;
|
|
}
|
|
if (this.clickedCancel) {
|
|
this.clickedCancel = false;
|
|
return;
|
|
}
|
|
const target = this.getRowByKey(key) || {};
|
|
if (!target.workId || !target.name || !target.department) {
|
|
message.error('请填写完整成员信息。');
|
|
e.target.focus();
|
|
return;
|
|
}
|
|
delete target.isNew;
|
|
this.toggleEditable(e, key);
|
|
this.props.onChange(this.state.data);
|
|
}, 10);
|
|
}
|
|
cancel(e, key) {
|
|
this.clickedCancel = true;
|
|
e.preventDefault();
|
|
const newData = this.state.data.map(item => ({ ...item }));
|
|
const target = this.getRowByKey(key, newData);
|
|
if (this.cacheOriginData[key]) {
|
|
Object.assign(target, this.cacheOriginData[key]);
|
|
target.editable = false;
|
|
delete this.cacheOriginData[key];
|
|
}
|
|
this.setState({ data: newData });
|
|
}
|
|
render() {
|
|
const columns = [{
|
|
title: '成员姓名',
|
|
dataIndex: 'name',
|
|
key: 'name',
|
|
width: '20%',
|
|
render: (text, record) => {
|
|
if (record.editable) {
|
|
return (
|
|
<Input
|
|
value={text}
|
|
autoFocus
|
|
onChange={e => this.handleFieldChange(e, 'name', record.key)}
|
|
onBlur={e => this.saveRow(e, record.key)}
|
|
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
|
placeholder="成员姓名"
|
|
/>
|
|
);
|
|
}
|
|
return text;
|
|
},
|
|
}, {
|
|
title: '工号',
|
|
dataIndex: 'workId',
|
|
key: 'workId',
|
|
width: '20%',
|
|
render: (text, record) => {
|
|
if (record.editable) {
|
|
return (
|
|
<Input
|
|
value={text}
|
|
onChange={e => this.handleFieldChange(e, 'workId', record.key)}
|
|
onBlur={e => this.saveRow(e, record.key)}
|
|
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
|
placeholder="工号"
|
|
/>
|
|
);
|
|
}
|
|
return text;
|
|
},
|
|
}, {
|
|
title: '所属部门',
|
|
dataIndex: 'department',
|
|
key: 'department',
|
|
width: '40%',
|
|
render: (text, record) => {
|
|
if (record.editable) {
|
|
return (
|
|
<Input
|
|
value={text}
|
|
onChange={e => this.handleFieldChange(e, 'department', record.key)}
|
|
onBlur={e => this.saveRow(e, record.key)}
|
|
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
|
placeholder="所属部门"
|
|
/>
|
|
);
|
|
}
|
|
return text;
|
|
},
|
|
}, {
|
|
title: '操作',
|
|
key: 'action',
|
|
render: (text, record) => {
|
|
if (record.editable) {
|
|
if (record.isNew) {
|
|
return (
|
|
<span>
|
|
<a>保存</a>
|
|
<Divider type="vertical" />
|
|
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
|
|
<a>删除</a>
|
|
</Popconfirm>
|
|
</span>
|
|
);
|
|
}
|
|
return (
|
|
<span>
|
|
<a>保存</a>
|
|
<Divider type="vertical" />
|
|
<a onClick={e => this.cancel(e, record.key)}>取消</a>
|
|
</span>
|
|
);
|
|
}
|
|
return (
|
|
<span>
|
|
<a onClick={e => this.toggleEditable(e, record.key)}>编辑</a>
|
|
<Divider type="vertical" />
|
|
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
|
|
<a>删除</a>
|
|
</Popconfirm>
|
|
</span>
|
|
);
|
|
},
|
|
}];
|
|
|
|
return (
|
|
<div>
|
|
<Table
|
|
columns={columns}
|
|
dataSource={this.state.data}
|
|
pagination={false}
|
|
rowClassName={(record) => {
|
|
return record.editable ? styles.editable : '';
|
|
}}
|
|
/>
|
|
<Button
|
|
style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
|
|
type="dashed"
|
|
onClick={this.newMember}
|
|
icon="plus"
|
|
>
|
|
新增成员
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|