动态菜单和动态路由的 antd pro

TableForm.js 6.3KB

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