TableForm.tsx 6.58 KB
Newer Older
陈帅's avatar
陈帅 committed
1 2 3
import { Button, Divider, Input, Popconfirm, Table, message } from 'antd';
import React, { Fragment, PureComponent } from 'react';

4 5
import { isEqual } from 'lodash';
import styles from '../style.less';
6

lijiehua's avatar
lijiehua committed
7
class TableForm extends PureComponent {
陈帅's avatar
陈帅 committed
8 9 10 11 12 13 14 15 16
  static getDerivedStateFromProps(nextProps, preState) {
    if (isEqual(nextProps.value, preState.value)) {
      return null;
    }
    return {
      data: nextProps.value,
      value: nextProps.value,
    };
  }
陈帅's avatar
陈帅 committed
17

18 19 20
  index = 0;

  cacheOriginData = {};
陈帅's avatar
陈帅 committed
21

陈帅's avatar
陈帅 committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  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)}
              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)}
              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)}
              onKeyPress={e => this.handleKeyPress(e, record.key)}
              placeholder="所属部门"
            />
          );
        }
        return text;
      },
    },
    {
      title: '操作',
      key: 'action',
      render: (text, record) => {
        const { loading } = this.state;
        if (!!record.editable && loading) {
          return null;
        }
        if (record.editable) {
          if (record.isNew) {
            return (
              <span>
                <a onClick={e => this.saveRow(e, record.key)}>添加</a>
                <Divider type="vertical" />
                <Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
                  <a>删除</a>
                </Popconfirm>
              </span>
            );
          }
          return (
            <span>
              <a onClick={e => this.saveRow(e, record.key)}>保存</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>
        );
      },
    },
  ];
陈帅's avatar
陈帅 committed
121

122 123 124 125 126
  constructor(props) {
    super(props);

    this.state = {
      data: props.value,
jim chen's avatar
jim chen committed
127
      loading: false,
128 129
      /* eslint-disable-next-line react/no-unused-state */
      value: props.value,
130 131
    };
  }
jim's avatar
jim committed
132

afc163's avatar
afc163 committed
133
  getRowByKey(key, newData) {
陈帅's avatar
陈帅 committed
134 135
    const { data } = this.state;
    return (newData || data).filter(item => item.key === key)[0];
136
  }
陈帅's avatar
陈帅 committed
137

jim's avatar
jim committed
138
  toggleEditable = (e, key) => {
139
    e.preventDefault();
陈帅's avatar
陈帅 committed
140 141
    const { data } = this.state;
    const newData = data.map(item => ({ ...item }));
afc163's avatar
afc163 committed
142
    const target = this.getRowByKey(key, newData);
143 144 145 146 147 148
    if (target) {
      // 进入编辑状态时保存原始数据
      if (!target.editable) {
        this.cacheOriginData[key] = { ...target };
      }
      target.editable = !target.editable;
afc163's avatar
afc163 committed
149
      this.setState({ data: newData });
150
    }
jim's avatar
jim committed
151
  };
陈帅's avatar
陈帅 committed
152 153

  newMember = () => {
154 155 156 157 158 159 160 161 162
    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,
陈帅's avatar
陈帅 committed
163
    });
164 165
    this.index += 1;
    this.setState({ data: newData });
陈帅's avatar
陈帅 committed
166 167
  };

afc163's avatar
afc163 committed
168
  remove(key) {
169
    const { data } = this.state;
陈帅's avatar
陈帅 committed
170 171
    const { onChange } = this.props;
    const newData = data.filter(item => item.key !== key);
172
    this.setState({ data: newData });
陈帅's avatar
陈帅 committed
173
    onChange(newData);
afc163's avatar
afc163 committed
174
  }
陈帅's avatar
陈帅 committed
175

176 177 178 179 180 181
  handleKeyPress(e, key) {
    if (e.key === 'Enter') {
      this.saveRow(e, key);
    }
  }

182
  handleFieldChange(e, fieldName, key) {
陈帅's avatar
陈帅 committed
183 184
    const { data } = this.state;
    const newData = data.map(item => ({ ...item }));
afc163's avatar
afc163 committed
185
    const target = this.getRowByKey(key, newData);
186 187 188 189 190
    if (target) {
      target[fieldName] = e.target.value;
      this.setState({ data: newData });
    }
  }
陈帅's avatar
陈帅 committed
191

192
  saveRow(e, key) {
afc163's avatar
afc163 committed
193
    e.persist();
jim chen's avatar
jim chen committed
194 195 196
    this.setState({
      loading: true,
    });
afc163's avatar
afc163 committed
197 198 199 200 201
    setTimeout(() => {
      if (this.clickedCancel) {
        this.clickedCancel = false;
        return;
      }
afc163's avatar
afc163 committed
202
      const target = this.getRowByKey(key) || {};
afc163's avatar
afc163 committed
203 204
      if (!target.workId || !target.name || !target.department) {
        message.error('请填写完整成员信息。');
afc163's avatar
afc163 committed
205
        e.target.focus();
206 207 208
        this.setState({
          loading: false,
        });
afc163's avatar
afc163 committed
209 210
        return;
      }
afc163's avatar
afc163 committed
211
      delete target.isNew;
afc163's avatar
afc163 committed
212
      this.toggleEditable(e, key);
WeiYang Qiu's avatar
WeiYang Qiu committed
213 214
      const { data } = this.state;
      const { onChange } = this.props;
陈帅's avatar
陈帅 committed
215
      onChange(data);
jim chen's avatar
jim chen committed
216 217 218 219
      this.setState({
        loading: false,
      });
    }, 500);
220
  }
陈帅's avatar
陈帅 committed
221

222
  cancel(e, key) {
afc163's avatar
afc163 committed
223
    this.clickedCancel = true;
224
    e.preventDefault();
225
    const { data } = this.state;
陈帅's avatar
陈帅 committed
226
    const newData = data.map(item => ({ ...item }));
afc163's avatar
afc163 committed
227
    const target = this.getRowByKey(key, newData);
228 229 230 231
    if (this.cacheOriginData[key]) {
      Object.assign(target, this.cacheOriginData[key]);
      delete this.cacheOriginData[key];
    }
WeiYang Qiu's avatar
WeiYang Qiu committed
232
    target.editable = false;
afc163's avatar
afc163 committed
233
    this.setState({ data: newData });
234
    this.clickedCancel = false;
235
  }
陈帅's avatar
陈帅 committed
236

237
  render() {
238 239
    const { loading, data } = this.state;

240
    return (
陈帅's avatar
陈帅 committed
241
      <Fragment>
242
        <Table
陈帅's avatar
陈帅 committed
243
          loading={loading}
陈帅's avatar
陈帅 committed
244
          columns={this.columns}
245
          dataSource={data}
246
          pagination={false}
247
          rowClassName={record => (record.editable ? styles.editable : '')}
248 249
        />
        <Button
250
          style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
251 252 253 254 255 256
          type="dashed"
          onClick={this.newMember}
          icon="plus"
        >
          新增成员
        </Button>
陈帅's avatar
陈帅 committed
257
      </Fragment>
258 259 260
    );
  }
}
lijiehua's avatar
lijiehua committed
261 262

export default TableForm;