TableForm.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import React, { PureComponent } from 'react';
  2. import { Table, Button, Input, message, Popconfirm, Divider } from 'antd';
  3. import styles from './style.less';
  4. export default class TableForm extends PureComponent {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. data: props.value,
  9. };
  10. }
  11. componentWillReceiveProps(nextProps) {
  12. if ('value' in nextProps) {
  13. this.setState({
  14. data: nextProps.value,
  15. });
  16. }
  17. }
  18. getRowByKey(key, newData) {
  19. return (newData || this.state.data).filter(item => item.key === key)[0];
  20. }
  21. index = 0;
  22. cacheOriginData = {};
  23. handleSubmit = (e) => {
  24. e.preventDefault();
  25. this.props.form.validateFieldsAndScroll((err, values) => {
  26. if (!err) {
  27. this.props.dispatch({
  28. type: 'form/submit',
  29. payload: values,
  30. });
  31. }
  32. });
  33. }
  34. toggleEditable(e, key) {
  35. e.preventDefault();
  36. const newData = this.state.data.map(item => ({ ...item }));
  37. const target = this.getRowByKey(key, newData);
  38. if (target) {
  39. // 进入编辑状态时保存原始数据
  40. if (!target.editable) {
  41. this.cacheOriginData[key] = { ...target };
  42. }
  43. target.editable = !target.editable;
  44. this.setState({ data: newData });
  45. }
  46. }
  47. remove(key) {
  48. const newData = this.state.data.filter(item => item.key !== key);
  49. this.setState({ data: newData });
  50. this.props.onChange(newData);
  51. }
  52. newMember = () => {
  53. const newData = this.state.data.map(item => ({ ...item }));
  54. newData.push({
  55. key: `NEW_TEMP_ID_${this.index}`,
  56. workId: '',
  57. name: '',
  58. department: '',
  59. editable: true,
  60. isNew: true,
  61. });
  62. this.index += 1;
  63. this.setState({ data: newData });
  64. }
  65. handleKeyPress(e, key) {
  66. if (e.key === 'Enter') {
  67. this.saveRow(e, key);
  68. }
  69. }
  70. handleFieldChange(e, fieldName, key) {
  71. const newData = this.state.data.map(item => ({ ...item }));
  72. const target = this.getRowByKey(key, newData);
  73. if (target) {
  74. target[fieldName] = e.target.value;
  75. this.setState({ data: newData });
  76. }
  77. }
  78. saveRow(e, key) {
  79. e.persist();
  80. // save field when blur input
  81. setTimeout(() => {
  82. if (document.activeElement.tagName === 'INPUT' &&
  83. document.activeElement !== e.target) {
  84. return;
  85. }
  86. if (this.clickedCancel) {
  87. this.clickedCancel = false;
  88. return;
  89. }
  90. const target = this.getRowByKey(key) || {};
  91. if (!target.workId || !target.name || !target.department) {
  92. message.error('请填写完整成员信息。');
  93. e.target.focus();
  94. return;
  95. }
  96. delete target.isNew;
  97. this.toggleEditable(e, key);
  98. this.props.onChange(this.state.data);
  99. }, 10);
  100. }
  101. cancel(e, key) {
  102. this.clickedCancel = true;
  103. e.preventDefault();
  104. const newData = this.state.data.map(item => ({ ...item }));
  105. const target = this.getRowByKey(key, newData);
  106. if (this.cacheOriginData[key]) {
  107. Object.assign(target, this.cacheOriginData[key]);
  108. target.editable = false;
  109. delete this.cacheOriginData[key];
  110. }
  111. this.setState({ data: newData });
  112. }
  113. render() {
  114. const columns = [{
  115. title: '成员姓名',
  116. dataIndex: 'name',
  117. key: 'name',
  118. width: '20%',
  119. render: (text, record) => {
  120. if (record.editable) {
  121. return (
  122. <Input
  123. value={text}
  124. autoFocus
  125. onChange={e => this.handleFieldChange(e, 'name', record.key)}
  126. onBlur={e => this.saveRow(e, record.key)}
  127. onKeyPress={e => this.handleKeyPress(e, record.key)}
  128. placeholder="成员姓名"
  129. />
  130. );
  131. }
  132. return text;
  133. },
  134. }, {
  135. title: '工号',
  136. dataIndex: 'workId',
  137. key: 'workId',
  138. width: '20%',
  139. render: (text, record) => {
  140. if (record.editable) {
  141. return (
  142. <Input
  143. value={text}
  144. onChange={e => this.handleFieldChange(e, 'workId', record.key)}
  145. onBlur={e => this.saveRow(e, record.key)}
  146. onKeyPress={e => this.handleKeyPress(e, record.key)}
  147. placeholder="工号"
  148. />
  149. );
  150. }
  151. return text;
  152. },
  153. }, {
  154. title: '所属部门',
  155. dataIndex: 'department',
  156. key: 'department',
  157. width: '40%',
  158. render: (text, record) => {
  159. if (record.editable) {
  160. return (
  161. <Input
  162. value={text}
  163. onChange={e => this.handleFieldChange(e, 'department', record.key)}
  164. onBlur={e => this.saveRow(e, record.key)}
  165. onKeyPress={e => this.handleKeyPress(e, record.key)}
  166. placeholder="所属部门"
  167. />
  168. );
  169. }
  170. return text;
  171. },
  172. }, {
  173. title: '操作',
  174. key: 'action',
  175. render: (text, record) => {
  176. if (record.editable) {
  177. if (record.isNew) {
  178. return (
  179. <span>
  180. <a>保存</a>
  181. <Divider type="vertical" />
  182. <Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
  183. <a>删除</a>
  184. </Popconfirm>
  185. </span>
  186. );
  187. }
  188. return (
  189. <span>
  190. <a>保存</a>
  191. <Divider type="vertical" />
  192. <a onClick={e => this.cancel(e, record.key)}>取消</a>
  193. </span>
  194. );
  195. }
  196. return (
  197. <span>
  198. <a onClick={e => this.toggleEditable(e, record.key)}>编辑</a>
  199. <Divider type="vertical" />
  200. <Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
  201. <a>删除</a>
  202. </Popconfirm>
  203. </span>
  204. );
  205. },
  206. }];
  207. return (
  208. <div>
  209. <Table
  210. columns={columns}
  211. dataSource={this.state.data}
  212. pagination={false}
  213. rowClassName={(record) => {
  214. return record.editable ? styles.editable : '';
  215. }}
  216. />
  217. <Button
  218. style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
  219. type="dashed"
  220. onClick={this.newMember}
  221. icon="plus"
  222. >
  223. 新增成员
  224. </Button>
  225. </div>
  226. );
  227. }
  228. }