king
2025-02-06 eed746580d059ab1bb01fec5a4c117a82c861ff2
src/templates/zshare/editTable/index.jsx
@@ -2,13 +2,12 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Input, InputNumber, Popconfirm, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined } from '@ant-design/icons'
import { Table, Input, InputNumber, Popconfirm, Switch, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined, PlusOutlined, ConsoleSqlOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import ColorSketch from '@/mob/colorsketch'
import asyncComponent from '@/utils/asyncComponent'
import CusSwitch from './cusSwitch'
import MKEmitter from '@/utils/events.js'
import './index.scss'
@@ -18,6 +17,52 @@
const { confirm } = Modal
let dragingIndex = -1
const { Paragraph } = Typography
class CusSwitch extends Component {
  static propTpyes = {
    defaultValue: PropTypes.any,
    value: PropTypes.any,
    onChange: PropTypes.func
  }
  state = {
    status: true
  }
  UNSAFE_componentWillMount () {
    const { defaultValue, value } = this.props
    let initVal = 'true'
    if (this.props['data-__meta']) {
      initVal = this.props['data-__meta'].initialValue
    } else if (defaultValue) {
      initVal = defaultValue
    } else if (value) {
      initVal = value
    }
    if (initVal === 'false') {
      initVal = false
    } else {
      initVal = true
    }
    this.setState({status: initVal})
  }
  changeStatus = (val) => {
    this.setState({ status: val }, () => {
      let _val = val ? 'true' : 'false'
      this.props.onChange && this.props.onChange(_val)
    })
  }
  render() {
    const { status } = this.state
    return (
      <Switch checkedChildren="是" unCheckedChildren="否" checked={status} onChange={this.changeStatus} />
    )
  }
}
class BodyRow extends React.Component {
  render() {
@@ -78,7 +123,7 @@
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType, options, min, max, unlimit, allowClear } = this.props
    const { inputType, options, min, max, unlimit, allowClear, typeChange } = this.props
    if (inputType === 'number' && unlimit) {
      return <InputNumber onPressEnter={() => this.getValue(form)} />
@@ -92,7 +137,7 @@
      return <CusSwitch />
    } else if (inputType === 'select') {
      return (
        <Select>
        <Select onChange={typeChange}>
          {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
        </Select>
      )
@@ -131,11 +176,18 @@
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, dataIndex, title, record, children, className, required, inputType, rules } = this.props
    const { editing, pass, dataIndex, title, record, children, className, required, inputType, rules } = this.props
    if (!editing) {
      return (
        <td className={className}>
          {children}
        </td>
      )
    }
    return (
      <td className={className}>
        {editing ? (
        {pass ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
@@ -149,7 +201,7 @@
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
          null
        )}
      </td>
    )
@@ -173,7 +225,9 @@
    data: [],
    editingKey: '',
    editLineId: '',
    columns: []
    columns: [],
    keyCol: null,
    keyVal: ''
  }
  UNSAFE_componentWillMount () {
@@ -181,6 +235,7 @@
    let columns = fromJS(this.props.columns).toJS()
    let operation = null
    let extra = null
    let keyCol = null
    
    if (actions) {
      actions.forEach(item => {
@@ -192,9 +247,17 @@
    if (actions && (actions.includes('edit') || actions.includes('copy') || actions.includes('del'))) {
      let _operation = null
      let render = null
      columns = columns.filter(item => {
        if (item.dataIndex === 'operation') {
          _operation = item
        }
        if (item.keyCol) {
          keyCol = item.dataIndex
        }
        if (item.dataIndex === 'sqlRender') {
          render = item.render
          return false
        }
        return item.dataIndex !== 'operation'
      })
@@ -226,7 +289,7 @@
            </div>
          ) : (
            <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')} style={{minWidth: '110px', whiteSpace: 'nowrap'}}>
              {actions.includes('edit') ? <span className="primary" title="编辑" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><EditOutlined /></span> : null}
              {actions.includes('edit') ? <span className="primary" title="编辑" onClick={() => {editingKey === '' && this.edit(record)}}><EditOutlined /></span> : null}
              {extra ? <span className="status" title={extra[2]} onClick={() => {editingKey === '' && this.handleStatus(record, extra[1])}}><SwapOutlined /></span> : null}
              {actions.includes('status') ? <span className="status" title="是否启用" onClick={() => {editingKey === '' && this.handleStatus(record, 'status')}}><SwapOutlined /></span> : null}
              {actions.includes('copy') ? <span className="copy" title="复制" onClick={() => {editingKey === '' && this.copy(record)}}><CopyOutlined /></span> : null}
@@ -234,10 +297,11 @@
                overlayClassName="popover-confirm"
                title="确定删除吗?"
                onConfirm={() => this.handleDelete(record.uuid)
              }>
                }>
                <span className="danger"><DeleteOutlined /></span>
              </Popconfirm> : null}
              {actions.includes('del') && editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
              {actions.includes('sql') ? <span className="primary" title="SQL" onClick={() => {editingKey === '' && this.showSql(record, render)}}><ConsoleSqlOutlined /></span> : null}
            </div>
          )
        }
@@ -253,11 +317,13 @@
    this.setState({
      data: data || [],
      operation,
      columns
      columns,
      keyCol
    })
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.state.data), fromJS(nextProps.data))) {
      this.setState({data: nextProps.data, editingKey: ''})
    } else if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
@@ -294,6 +360,20 @@
    MKEmitter.removeListener('editLineId', this.getEditLineId)
  }
  showSql = (record, render) => {
    let list = render(record)
    if (list) {
      Modal.info({
        title: '',
        width: 700,
        className: 'sql-example',
        icon: null,
        content: list.map((n, index) => <div key={index} dangerouslySetInnerHTML={{ __html: n }}></div>)
      })
    }
  }
  getEditLineId = (id) => {
    this.setState({ editLineId: id })
  }
@@ -305,14 +385,14 @@
  }
  clear = () => {
    const _this = this
    const that = this
    
    confirm({
      title: '确定清空列表吗?',
      content: '',
      onOk() {
        _this.setState({ data: [], editingKey: '' }, () => {
          _this.props.onChange([])
        that.setState({ data: [], editingKey: '' }, () => {
          that.props.onChange([])
        })
      },
      onCancel() {}
@@ -339,11 +419,6 @@
    }
    try {
      let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
      if (srcid) {
        msg.$srcId = srcid
      }
      msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
    } catch (e) {
      console.warn('Stringify Failure')
@@ -389,7 +464,7 @@
        } else {
          let datatype = 'Nvarchar(50)'
          let fieldlength = 50
          if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048].includes(col.fieldlength)) {
          if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048, 4000].includes(col.fieldlength)) {
            fieldlength = col.fieldlength
            datatype = `Nvarchar(${fieldlength})`
          }
@@ -410,78 +485,151 @@
      return
    }
    if (res.type === 'line') {
      let unique = true
    let ucol = columns.filter(col => col.unique === true)[0]
    const that = this
    if (data.length === 0) {
      if (res.type === 'line') {
        res.data.uuid = Utils.getuuid()
        data.push(res.data)
      } else if (res.type === 'array') {
        res.data.forEach(cell => {
          cell.uuid = Utils.getuuid()
          data.push(cell)
        })
      }
      this.setState({ data, editingKey: '', editLineId: res.type === 'line' ? res.data.uuid : '' }, () => {
        this.props.onChange(data)
      })
    } else if (res.type === 'line') {
      let index = -1
      res.data.uuid = Utils.getuuid()
      columns.forEach(col => {
        if (col.unique !== true || !unique) return
        if (col.uniqueFunc) {
          unique = col.uniqueFunc(data, res.data)
        } else if (col.strict) {
          let key = res.data[col.dataIndex].toLowerCase()
          let _index = data.findIndex(item => key === item[col.dataIndex].toLowerCase())
      if (ucol) {
        if (ucol.uniqueFunc) {
          let msg = ucol.uniqueFunc(data, res.data)
          if (_index > -1) {
          if (msg) {
            notification.warning({
              top: 92,
              message: col.title + '不可重复!',
              message: msg,
              duration: 5
            })
            unique = false
            callback()
            return
          }
        } else if (ucol.strict) {
          let key = res.data[ucol.dataIndex].toLowerCase()
          index = data.findIndex(item => key === item[ucol.dataIndex].toLowerCase())
        } else {
          index = data.findIndex(item => res.data[ucol.dataIndex] === item[ucol.dataIndex])
        }
      }
      if (index > -1) {
        callback()
        data.splice(index, 1, res.data)
        confirm({
          title: `${ucol.title}(${res.data[ucol.dataIndex]})已存在!`,
          okText: '知道了',
          cancelText: '替换',
          onOk() {},
          onCancel() {
            that.setState({ data, editingKey: '', editLineId: res.data.uuid || '' }, () => {
              that.props.onChange(data)
            })
          }
        })
        return
      } else {
        if (type === 'excelcolumn') {
          data.push(res.data)
        } else {
          data.unshift(res.data)
        }
        this.setState({ data, editingKey: '', editLineId: res.data.uuid || '' }, () => {
          this.props.onChange(data)
        })
      }
    } else if (res.type === 'array') {
      let repeats = []
      let vals = []
      if (ucol) {
        if (ucol.uniqueFunc) {
        } else if (ucol.strict) {
          vals = data.map(item => item[ucol.dataIndex].toLowerCase())
        } else {
          vals = data.map(item => item[ucol.dataIndex])
        }
      }
      res.data.forEach(cell => {
        cell.uuid = Utils.getuuid()
        if (ucol) {
          let unique = true
          if (ucol.uniqueFunc) {
            let msg = ucol.uniqueFunc(data, cell)
            if (msg) return
          } else if (ucol.strict) {
            unique = !vals.includes(cell[ucol.dataIndex].toLowerCase())
          } else {
            unique = !vals.includes(cell[ucol.dataIndex])
          }
          if (unique) {
            data.push(cell)
          } else {
            repeats.push(cell)
          }
        } else {
          let _index = data.findIndex(item => res.data[col.dataIndex] === item[col.dataIndex])
          if (_index > -1) {
            notification.warning({
              top: 92,
              message: col.title + '不可重复!',
              duration: 5
            })
            unique = false
          }
          data.push(cell)
        }
      })
      if (!unique) return
      data.unshift(res.data)
      this.setState({ data, editingKey: '', editLineId: res.data.uuid || '' }, () => {
        this.props.onChange(data)
      })
    } else if (res.type === 'array') {
      res.data.forEach(cell => {
        let unique = true
        cell.uuid = Utils.getuuid()
        columns.forEach(col => {
          if (col.unique !== true || !unique) return
          if (col.uniqueFunc) {
            unique = col.uniqueFunc(data, cell)
          } else if (col.strict) {
            let _index = data.findIndex(item => cell[col.dataIndex].toLowerCase() === item[col.dataIndex].toLowerCase())
            if (_index > -1) {
              unique = false
      if (repeats.length) {
        callback()
        let _data = fromJS(data).toJS().map(cell => {
          let _cell = cell
          repeats.forEach(item => {
            if (ucol.strict) {
              if (cell[ucol.dataIndex].toLowerCase() === item[ucol.dataIndex].toLowerCase()) {
                _cell = item
              }
            } else if (cell[ucol.dataIndex] === item[ucol.dataIndex]) {
              _cell = item
            }
          } else {
            let _index = data.findIndex(item => cell[col.dataIndex] === item[col.dataIndex])
            if (_index > -1) {
              unique = false
            }
          }
          })
          return _cell
        })
        if (!unique) return
        data.push(cell)
      })
      this.setState({ data, editingKey: '' }, () => {
        this.props.onChange(data)
      })
        confirm({
          content: `存在重复的${ucol.title},请选择处理方式。`,
          okText: '跳过',
          cancelText: '替换',
          onOk() {
            that.setState({ data, editingKey: '', editLineId: '' }, () => {
              that.props.onChange(data)
            })
          },
          onCancel() {
            that.setState({ data: _data, editingKey: '', editLineId: '' }, () => {
              that.props.onChange(data)
            })
          }
        })
        return
      } else {
        this.setState({ data, editingKey: '' }, () => {
          this.props.onChange(data)
        })
      }
    }
    callback()
@@ -518,40 +666,56 @@
      return
    }
    let unique = true
    let forbid = false
    columns.forEach(col => {
      if (col.unique !== true || !unique) return
      if (!col.forbids || forbid) return
      if (col.uniqueFunc) {
        unique = col.uniqueFunc(newData, record)
        return
      } else if (col.strict) {
        let key = record[col.dataIndex].toLowerCase()
        let _index = newData.findIndex(item => key === item[col.dataIndex].toLowerCase())
        if (_index > -1) {
          notification.warning({
            top: 92,
            message: col.title + '不可重复!',
            duration: 5
          })
          unique = false
        }
      } else {
        let _index = newData.findIndex(item => record.uuid !== item.uuid && record[col.dataIndex] === item[col.dataIndex])
        if (_index > -1) {
          notification.warning({
            top: 92,
            message: col.title + '不可重复!',
            duration: 5
          })
          unique = false
        }
      let key = record[col.dataIndex].toLowerCase()
      if (col.forbids.includes(key)) {
        forbid = col.title + '不可使用' + record[col.dataIndex]
      }
    })
    if (!unique) return
    if (forbid) {
      notification.warning({
        top: 92,
        message: forbid,
        duration: 5
      })
      return
    }
    let ucol = columns.filter(col => col.unique === true)[0]
    if (ucol) {
      let index = -1
      if (ucol.uniqueFunc) {
        let msg = ucol.uniqueFunc(newData, record)
        if (msg) {
          notification.warning({
            top: 92,
            message: msg,
            duration: 5
          })
          return
        }
      } else if (ucol.strict) {
        let key = record[ucol.dataIndex].toLowerCase()
        index = newData.findIndex(item => record.uuid !== item.uuid && key === item[ucol.dataIndex].toLowerCase())
      } else {
        index = newData.findIndex(item => record.uuid !== item.uuid && record[ucol.dataIndex] === item[ucol.dataIndex])
      }
      if (index > -1) {
        notification.warning({
          top: 92,
          message: ucol.title + '不可重复!',
          duration: 5
        })
        return
      }
    }
    newData.splice(index, 1, record)
    this.setState({ data: newData, editingKey: '' }, () => {
@@ -584,40 +748,56 @@
        row.uuid = uuid
      }
      let unique = true
      columns.forEach(col => {
        if (col.unique !== true || !unique) return
      let forbid = false
        if (col.uniqueFunc) {
          unique = col.uniqueFunc(newData, row)
          return
        } else if (col.strict) {
          let key = row[col.dataIndex].toLowerCase()
          let _index = newData.findIndex(item => key === item[col.dataIndex].toLowerCase())
          if (_index > -1) {
            notification.warning({
              top: 92,
              message: col.title + '不可重复!',
              duration: 5
            })
            unique = false
          }
        } else {
          let _index = newData.findIndex(item => row.uuid !== item.uuid && row[col.dataIndex] === item[col.dataIndex])
          if (_index > -1) {
            notification.warning({
              top: 92,
              message: col.title + '不可重复!',
              duration: 5
            })
            unique = false
          }
      columns.forEach(col => {
        if (!col.forbids || forbid) return
        let key = row[col.dataIndex].toLowerCase()
        if (col.forbids.includes(key)) {
          forbid = col.title + '不可使用' + row[col.dataIndex]
        }
      })
      if (!unique) return
      if (forbid) {
        notification.warning({
          top: 92,
          message: forbid,
          duration: 5
        })
        return
      }
      let ucol = columns.filter(col => col.unique === true)[0]
      if (ucol) {
        let _index = -1
        if (ucol.uniqueFunc) {
          let msg = ucol.uniqueFunc(newData, row)
          if (msg) {
            notification.warning({
              top: 92,
              message: msg,
              duration: 5
            })
            return
          }
        } else if (ucol.strict) {
          let key = row[ucol.dataIndex].toLowerCase()
          _index = newData.findIndex(item => row.uuid !== item.uuid && key === item[ucol.dataIndex].toLowerCase())
        } else {
          _index = newData.findIndex(item => row.uuid !== item.uuid && row[ucol.dataIndex] === item[ucol.dataIndex])
        }
        if (_index > -1) {
          notification.warning({
            top: 92,
            message: ucol.title + '不可重复!',
            duration: 5
          })
          return
        }
      }
      if (index > -1) {
        newData.splice(index, 1, row)
@@ -633,8 +813,14 @@
    })
  }
  edit(uuid) {
    this.setState({ editingKey: uuid })
  edit(record) {
    const { keyCol } = this.state
    this.setState({ editingKey: record.uuid, keyVal: keyCol ? record[keyCol] : '' })
  }
  typeChange = (val) => {
    this.setState({ keyVal: val })
  }
  moveRow = (dragIndex, hoverIndex) => {
@@ -652,9 +838,40 @@
    })
  }
  handleAdd = () => {
    const { columns } = this.props
    const { data } = this.state
    let _index = data.length + 1
    let item = {
      uuid: Utils.getuuid()
    }
    columns.forEach(col => {
      if (!col.dataIndex) return
      item[col.dataIndex] = col.initval || ''
      if (col.unique) {
        while (data.filter(cell => cell[col.dataIndex] === item[col.dataIndex]).length > 0) {
          _index++
          item[col.dataIndex] = col.initval + _index
        }
      }
    })
    let _data = [...data, item]
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  render() {
    const { actions, indexShow, searchKey } = this.props
    const { editLineId } = this.state
    const { editLineId, keyVal } = this.state
    let components = {
      body: {
@@ -671,9 +888,11 @@
    
    let  columns = this.state.columns.map(col => {
      if (col.copy) {
        col.render = (text) => (<Paragraph copyable>{text}</Paragraph>)
        col.render = (text, record) => (<Paragraph copyable={{ text: text, onCopy: () => this.setState({editLineId: record.uuid}) }}>{text}</Paragraph>)
      }
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
@@ -687,9 +906,12 @@
          unlimit: col.unlimit,
          required: col.required !== false ? true : false,
          allowClear: col.allowClear === true,
          keyCol: col.keyCol === true,
          title: col.title,
          editing: this.isEditing(record),
          pass: col.keyVals ? col.keyVals.includes(keyVal) : true,
          onSave: this.onSave,
          typeChange: this.typeChange,
        }),
      }
    })
@@ -709,11 +931,22 @@
      return item
    })
    let reg = searchKey ? new RegExp(searchKey, 'i') : null
    let reg = null
    let regs = []
    if (searchKey) {
      reg = new RegExp(searchKey, 'i')
      this.state.columns.forEach(col => {
        if (col.searchable) {
          regs.push(col.dataIndex)
        }
      })
    }
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-edit-table">
          {actions.includes('add') ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
          <DndProvider>
            <Table
              bordered
@@ -727,7 +960,7 @@
                  className += ' active'
                }
                if (searchKey) {
                  if (!reg.test(record.field) && !reg.test(record.label)) {
                  if (regs.findIndex(f => reg.test(record[f])) === -1) {
                    className += ' hidden'
                  }
                }
@@ -739,6 +972,10 @@
                ...moveprops
              })}
            />
            {actions.includes('copy') && data.length > 10 ? <span className="footer-copy-control">
              <CopyOutlined title="复制" onClick={() => this.copy()} />
              <PasteBoard getPasteValue={this.pasteSubmit}/>
            </span> : null}
          </DndProvider>
        </div>
      </EditableContext.Provider>