king
2021-12-22 bd1dfc9e6c9b9f8076ca2783ce598e0936b4c664
src/templates/zshare/modalform/fieldtable/index.jsx
@@ -1,72 +1,13 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Table, Input, InputNumber, Popconfirm, Form, Icon, notification, Select } from 'antd'
import { notification } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import ColorSketch from '@/mob/colorsketch'
import asyncComponent from '@/utils/asyncComponent'
import Utils from '@/utils/utils.js'
import './index.scss'
const EditableContext = React.createContext()
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType } = this.props
    if (inputType === 'number') {
      return <InputNumber min={12} max={50} precision={0} onPressEnter={() => this.getValue(form)} />
    } else if (inputType === 'color') {
      return <ColorSketch />
    } else if (inputType === 'select') {
      return <Select>
        <Select.Option key="left" value="left"> left </Select.Option>
        <Select.Option key="center" value="center"> center </Select.Option>
        <Select.Option key="right" value="right"> right </Select.Option>
        <Select.Option key="justify" value="justify"> justify </Select.Option>
      </Select>
    } else {
      return <Input onPressEnter={() => this.getValue(form)} />
    }
  }
  getValue = (form) => {
    const { record } = this.props
    form.validateFields((error, row) => {
      if (error) {
        return
      }
      this.props.onSave({...record, ...row})
    })
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, dataIndex, title, record, children, className } = this.props
    return (
      <td className={className}>
        {editing ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
                {
                  required: true,
                  message: `Please Input ${title}!`,
                },
              ],
              initialValue: record[dataIndex],
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
        )}
      </td>
    )
  }
  render() {
    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
  }
}
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
class EdiFieldsTable extends Component {
  static propTpyes = {
@@ -75,28 +16,32 @@
  }
  UNSAFE_componentWillMount () {
    let data = this.props['data-__meta'].initialValue
    let data = this.props['data-__meta'].initialValue || []
    this.setState({
      data: data
      data: data.map(item => {
        item.uuid = item.uuid || item.key
        return item
      })
    })
  }
  state = {
    data: [],
    editingKey: '',
    columns: [
      {
        title: '字段名',
        dataIndex: 'field',
        inputType: 'input',
        editable: true,
        width: '20%',
      },
      {
        title: '字体颜色',
        dataIndex: 'color',
        inputType: 'color',
        editable: true,
        width: '20%',
        render: (text, record) => {
          return <span style={{color: text}}>示例</span>
        }
@@ -105,142 +50,42 @@
        title: '字体大小',
        dataIndex: 'fontSize',
        inputType: 'number',
        min: 12,
        max: 50,
        editable: true,
        width: '20%',
      },
      {
        title: '对齐方式',
        dataIndex: 'align',
        inputType: 'select',
        editable: true,
      },
      {
        title: 'operation',
        dataIndex: 'operation',
        width: '18%',
        render: (text, record) => {
          const { editingKey } = this.state
          const editable = this.isEditing(record)
          return editable ? (
            <span>
              <EditableContext.Consumer>
                {form => (
                  <span onClick={() => this.save(form, record.key)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                    保存
                  </span>
                )}
              </EditableContext.Consumer>
              <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.key)}>取消</span>
            </span>
          ) : (
            <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
              <span className="primary" onClick={() => {editingKey === '' && this.edit(record.key)}}><Icon type="edit" /></span>
              <span className="primary" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'up')}}><Icon type="arrow-up" /></span>
              <span className="danger" onClick={() => {editingKey === '' && this.handleUpDown(record.key, 'down')}}><Icon type="arrow-down" /></span>
              {editingKey === '' ? <Popconfirm
                overlayClassName="popover-confirm"
                title={this.props.dict['model.query.delete']}
                onConfirm={() => this.handleDelete(record.key)
              }>
                <span className="danger"><Icon type="delete" /></span>
              </Popconfirm> : null}
              {editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null}
            </div>
          )
        },
      },
        width: '20%',
        options: [
          {value: 'left', text: 'left'},
          {value: 'center', text: 'center'},
          {value: 'right', text: 'right'},
          {value: 'justify', text: 'justify'}
        ]
      }
    ]
  }
  isEditing = record => record.key === this.state.editingKey
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  onSave = (record) => {
    const newData = [...this.state.data]
    const index = newData.findIndex(item => record.key === item.key)
    if (index > -1) {
      newData.splice(index, 1, record)
      this.setState({ data: newData, editingKey: '' }, () => {
        this.props.onChange(newData)
      })
    }
  }
  handleDelete = (key) => {
    const { data } = this.state
    let _data = data.filter(item => key !== item.key)
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  handleUpDown = (key, direction) => {
    let _data = fromJS(this.state.data).toJS()
    const index = _data.findIndex(item => key === item.key)
    if ((index === 0 && direction === 'up') || (index === _data.length - 1 && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      _data.splice(index - 1, 0, ..._data.splice(index, 1))
    } else {
      _data.splice(index + 1, 0, ..._data.splice(index, 1))
    }
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  save(form, key) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      const newData = [...this.state.data]
      const index = newData.findIndex(item => key === item.key)
      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, {
          ...item,
          ...row,
        })
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      } else {
        newData.push(row);
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      }
    })
  }
  handleAdd = () => {
    if (this.state.editingKey) {
      notification.warning({
        top: 92,
        message: '请保存编辑中的元素!',
        duration: 5
      })
      return
    }
    let _index = this.state.data.length + 1
    let item = {
      key: Utils.getuuid(),
      field: `field${this.state.data.length + 1}`,
      field: `field${_index}`,
      color: 'rgba(0, 0, 0, 0.85)',
      align: 'left',
      fontSize: 14,
    }
    item.uuid = item.key
    while (this.state.data.filter(cell => cell.field === item.field).length > 0) {
      _index++
      item.field = `field${_index}`
    }
    let data = [...this.state.data, item]
@@ -250,50 +95,33 @@
    })
  }
  edit(key) {
    this.setState({ editingKey: key })
  changeData = (data) => {
    let fields = data.map(cell => cell.field)
    fields = Array.from(new Set(fields))
    if (data.length > 1 && data.length > fields.length) {
      notification.warning({
        top: 92,
        message: '字段名不可重复!',
        duration: 5
      })
      return
    }
    Array.from(new Set(fields))
    this.setState({ data }, () => {
      this.props.onChange(data)
    })
  }
  render() {
    const components = {
      body: {
        cell: EditableCell,
      },
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) {
        return col
      }
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          title: col.title,
          editing: this.isEditing(record),
          onSave: this.onSave,
        }),
      }
    })
    const { data, columns } = this.state
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-card-field-table">
          {this.state.data.length < 3 ? <Icon className="add-row" type="plus" onClick={this.handleAdd} /> : null}
          <Table
            components={components}
            bordered
            dataSource={this.state.data}
            columns={columns}
            rowClassName="editable-row"
            pagination={false}
          />
        </div>
      </EditableContext.Provider>
      <div className="modal-card-field-table">
        {data.length < 3 ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
        <EditTable actions={['edit', 'move', 'del']} data={data} columns={columns} onChange={this.changeData}/>
      </div>
    )
  }
}
export default Form.create()(EdiFieldsTable)
export default EdiFieldsTable