king
2022-03-03 3fc643dea8f8c957a95a86d250b5d8b06fb740e1
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -270,8 +270,10 @@
  }
  render() {
    let { col, config, record, style, className } = this.props
    let { col, config, record, style, className, ...resProps } = this.props
    const { editing, value, err } = this.state
    if (!col) return (<td {...resProps} className={className} style={style}/>)
    let children = null
    if (col.type === 'text') {
@@ -314,7 +316,7 @@
          } else if (col.editType === 'switch') {
            let _value = record[col.field] !== undefined ? record[col.field] : ''
            return (<td className="editing_table_cell">
              <CusSwitch config={col} defaultValue={_value} onChange={this.onSwitchChange} onBlur={this.switchBlur}/>
              <CusSwitch config={col} defaultValue={_value} autoFocus={true} onChange={this.onSwitchChange} onBlur={this.switchBlur}/>
            </td>)
          } else {
            let _value = record[col.field] !== undefined ? record[col.field] : ''
@@ -332,7 +334,11 @@
            </td>)
          }
        } else {
          return (<td className={className + ' pointer'} style={style}><div className="mk-mask" onClick={this.focus}></div>{content}</td>)
          return (<td className={className + ' pointer'} style={style}>
            {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}
            <div className="mk-mask" onClick={this.focus}></div>{content}
            {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}
          </td>)
        }
      } else {
        children = content
@@ -387,7 +393,11 @@
            {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
          </td>)
        } else {
          return (<td className={className + ' pointer'} style={style}><div className="mk-mask" onClick={this.focus}></div>{content}</td>)
          return (<td className={className + ' pointer'} style={style}>
            {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}
            <div className="mk-mask" onClick={this.focus}></div>{content}
            {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}
          </td>)
        }
      } else {
        children = content
@@ -475,6 +485,338 @@
  }
}
class BodyAllCell extends React.Component {
  state = {
    err: null
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props.record), fromJS(nextProps.record)) ||
      nextState.err !== this.state.err
  }
  componentDidMount () {
    MKEmitter.addListener('tdFocus', this.tdFocus)
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('tdFocus', this.tdFocus)
  }
  tdFocus = (id) => {
    const { col, record } = this.props
    if (id !== col.uuid + record.$$uuid) return
    this.focus()
  }
  enterPress = () => {
    const { col, record } = this.props
    setTimeout(() => {
      if (col.enter === '$next') {
        MKEmitter.emit('nextLine', col, record.$$uuid)
      } else {
        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
      }
    }, 50)
  }
  focus = () => {
    const { col, record } = this.props
    if (col.editType === 'switch' || col.editType === 'select') {
      let node = document.getElementById(col.uuid + record.$$uuid)
      node && node.click()
    } else {
      let err = null
      let val = record[col.field] !== undefined ? record[col.field] : ''
      if (col.type === 'number') {
        val = +val
        if (isNaN(val)) {
          val = 0
        }
        if (typeof(col.max) === 'number' && val > col.max) {
          err = col.label + '最大为' + col.max
        } else if (typeof(col.min) === 'number' && val < col.min) {
          err = col.label + '最小为' + col.min
        }
      } else if (col.required === 'true' && !val) {
        err = '请填写' + col.label
      }
      this.setState({err}, () => {
        let node = document.getElementById(col.uuid + record.$$uuid)
        node && node.select()
      })
    }
  }
  onChange = (val) => {
    const { col, record } = this.props
    let err = null
    if (col.type === 'number') {
      val = +val
      if (isNaN(val)) {
        val = 0
      }
      if (typeof(col.max) === 'number' && val > col.max) {
        err = col.label + '最大为' + col.max
      } else if (typeof(col.min) === 'number' && val < col.min) {
        err = col.label + '最小为' + col.min
      }
    } else if (col.required === 'true' && !val) {
      err = '请填写' + col.label
    }
    this.setState({err})
    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
  }
  onSwitchChange = (val) => {
    const { col, record } = this.props
    setTimeout(() => {
      if (col.enter === '$next') {
        MKEmitter.emit('nextLine', col, record.$$uuid)
      } else {
        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
      }
    }, 50)
    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val})
  }
  onSelectChange = (val, option) => {
    const { col, record } = this.props
    let values = {}
    let _option = col.options.filter(m => m.key === option.key)[0]
    if (_option) {
      if (col.linkSubField) {
        col.linkSubField.forEach(m => {
          values[m] = _option[m] !== undefined ? _option[m] : ''
        })
      }
      if (col.editField) {
        values[col.field] = _option.label
        values[col.editField] = val
      } else {
        values[col.field] = val
      }
    }
    setTimeout(() => {
      if (col.enter === '$next') {
        MKEmitter.emit('nextLine', col, record.$$uuid)
      } else {
        MKEmitter.emit('tdFocus', col.enter + record.$$uuid)
      }
    }, 50)
    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
  }
  render() {
    let { col, config, record, style, className } = this.props
    const { err } = this.state
    let children = null
    if (col.type === 'text') {
      if (col.editable === 'true') {
        let _value = record[col.field] !== undefined ? record[col.field] : ''
        if (!col.editType || col.editType === 'text') {
          children = (<>
            <Input id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
            {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
          </>)
        } else if (col.editType === 'switch') {
          children = (
            <CusSwitch config={col} autoFocus={false} defaultValue={_value} onChange={this.onSwitchChange} onBlur={() => {}}/>
          )
        } else {
          children = (<>
            <Select
              showSearch
              defaultValue={_value}
              id={col.uuid + record.$$uuid}
              onBlur={() => this.setState({editing: false})}
              filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
              onSelect={this.onSelectChange}
            >
              {col.options.map((item, i) => (<Select.Option key={item.key} disabled={item.$disabled} value={item.value}>{item.label}</Select.Option>))}
            </Select>
          </>)
        }
      } else {
        let content = ''
        if (record[col.field] !== undefined) {
          content = `${record[col.field]}`
        }
        if (content !== '') {
          if (col.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(content)) {
            content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)}`
          } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(content)) {
            content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)} ${content.substr(11, 2)}:${content.substr(14, 2)}:${content.substr(17, 2)}`
          }
          content = (col.prefix || '') + content + (col.postfix || '')
        }
        if (col.marks) {
          let mark = getMark(col.marks, record, style)
          style = mark.style
          if (mark.icon) {
            if (mark.position === 'front') {
              content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span>
            } else {
              content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span>
            }
          }
        }
        children = content
      }
    } else if (col.type === 'number') {
      if (col.editable === 'true') {
        let _value = record[col.field] !== undefined ? record[col.field] : ''
        children = (<>
          <InputNumber id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress}/>
          {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null}
        </>)
      } else {
        let content = ''
        try {
          content = parseFloat(record[col.field])
          if (isNaN(content)) {
            content = ''
          }
        } catch (e) {
          content = ''
        }
        if (content !== '') {
          let decimal = col.decimal || 0
          if (col.format === 'percent') {
            content = content * 100
            decimal = decimal > 2 ? decimal - 2 : 0
          } else if (col.format === 'abs') {
            content = Math.abs(content)
          }
          content = content.toFixed(decimal)
          if (col.format === 'thdSeparator') {
            content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
          }
          content = col.prefix + content + col.postfix
        }
        if (col.marks) {
          let mark = getMark(col.marks, record, style)
          style = mark.style
          if (mark.icon) {
            if (mark.position === 'front') {
              content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span>
            } else {
              content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span>
            }
          }
        }
        children = content
      }
    } else if (col.type === 'textarea') {
      let content = ''
      if (record[col.field] !== undefined) {
        content = `${record[col.field]}`
      }
      if (content) {
        content = col.prefix + content + col.postfix
      }
      children = (
        <div>
          {content ? <Paragraph copyable ellipsis={{ rows: 3, expandable: true }}>{content}</Paragraph> : null }
        </div>
      )
    } else if (col.type === 'formula') {
      let content = col.formula
      Object.keys(record).forEach(key => {
        let reg = new RegExp('@' + key + '@', 'ig')
        content = content.replace(reg, record[key])
      })
      if (col.eval !== 'false') {
        try {
          // eslint-disable-next-line
          content = eval(content)
        } catch (e) {
          content = ''
        }
      }
      content = content === undefined ? '' : content
      if (content !== '') {
        content = `${col.prefix || ''}${content}${col.postfix || ''}`
        if (col.eval === 'false') {
          content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
          content = <span dangerouslySetInnerHTML={{__html: content}}></span>
        }
      }
      if (col.marks) {
        let mark = getMark(col.marks, record, style)
        style = mark.style
        if (mark.icon) {
          if (mark.position === 'front') {
            content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span>
          } else {
            content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span>
          }
        }
      }
      children = content
    } else if (col.type === 'custom') {
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'operation') {
      style.padding = '0px 5px'
      children = (
        <Button type="link" style={{color: 'rgb(255, 77, 79)', backgroundColor: 'transparent'}} onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})}>删除</Button>
      )
    }
    return (<td className={'editing_all_table_cell ' + className} style={style}>{col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}{children}{col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}</td>)
  }
}
class NormalTable extends Component {
  static propTpyes = {
    statFValue: PropTypes.any,       // 合计字段数据
@@ -495,6 +837,7 @@
    data: [],
    edData: [],
    edColumns: [],
    selectedRowKeys: [],  // 表格中选中行
    tableId: '',          // 表格ID
    pageIndex: 1,         // 初始页面索引
    pageSize: 10,         // 每页数据条数
@@ -551,7 +894,7 @@
        _copy.sorter = false
        if (item.editable === 'true') {
          _copy.title = <span>{item.label}<EditOutlined className="system-color" style={{position: 'absolute', bottom: '2px', right: '5px'}}/></span>
          _copy.title = <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span>
        }
        edColumns.push(_copy)
      }
@@ -617,6 +960,7 @@
    })
    if (editable === 'true' && data && data.length > 0) {
      this.setState({editable: 'false'})
      setTimeout(() => {
        this.pickupChange()
      }, 200)
@@ -647,6 +991,7 @@
    if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
      this.setState({data: nextProps.data || []})
      if (this.state.editable === 'true' && !this.state.pickup) {
        this.setState({editable: 'false'})
        setTimeout(() => {
          this.pickupChange()
        }, 200)
@@ -805,21 +1150,28 @@
      return item
    })
    this.setState({edColumns: []}, () => {
      this.setState({edColumns: _edColumns})
    if (this.state.pickup) {
      this.setState({
        pickup: false
      }, () => {
        this.setState({pickup: true, edColumns: _edColumns})
    })
    } else {
      this.setState({edColumns: _edColumns})
    }
  }
  
  nextLine = (col, index) => {
  nextLine = (col, uuid) => {
    const { setting } = this.props
    const { edData, initEditLine, tableId } = this.state
    if (col.tableId !== tableId) return
    index = +index
    let index = edData.findIndex(item => item.$$uuid === uuid)
    let next = edData[index + 1] || null
    if (index < edData.length && initEditLine) {
      MKEmitter.emit('tdFocus', initEditLine.uuid + (index + 1))
    if (next && initEditLine) {
      MKEmitter.emit('tdFocus', initEditLine.uuid + next.$$uuid)
    } else if (col.footEnter === 'add' && setting.addable === 'true') {
      setTimeout(() => {
        this.plusLine()
@@ -1205,12 +1557,82 @@
    })
  }
  /**
   *
   */
  onSelectChange = selectedRowKeys => {
    this.setState({ selectedRowKeys })
    let activeId = ''
    if (selectedRowKeys.length > 0) {
      activeId = selectedRowKeys.slice(-1)[0]
    }
    this.changedata(activeId)
    this.selectdata(selectedRowKeys)
  }
  /**
   * @description 点击整行,触发切换, 判断是否可选,单选或多选,进行对应操作
   */
  changeRow = (index) => {
    const { setting } = this.props
    if (!setting.tableType || this.state.pickup) return
    let newkeys = fromJS(this.state.selectedRowKeys).toJS()
    let activeId = ''
    if (setting.tableType === 'radio') {
      activeId = index
      newkeys = [index]
      this.setState({ selectedRowKeys: newkeys })
    } else {
      if (newkeys.includes(index)) {
        newkeys = newkeys.filter(item => item !== index)
        if (newkeys.length > 0) {
          activeId = newkeys.slice(-1)[0]
        }
      } else {
        activeId = index
        newkeys.push(index)
      }
      this.setState({ selectedRowKeys: newkeys })
    }
    this.changedata(activeId)
    this.selectdata(newkeys)
  }
  changedata = (id) => {
    const { MenuID } = this.props
    const { data } = this.state
    let _data = ''
    if (id) {
      _data = data.filter(item => item.$$uuid === id)[0] || ''
    }
    MKEmitter.emit('resetSelectLine', MenuID, id, _data)
  }
  selectdata = (keys) => {
    const { data } = this.state
    let _data = data.filter(item => keys.includes(item.$$uuid))
    this.props.chgSelectData(_data)
  }
  changeTable = (pagination, filters, sorter) => {
    const { orderfields } = this.state
    this.setState({
      pageIndex: pagination.current,
      pageSize: pagination.pageSize
      pageSize: pagination.pageSize,
      selectedRowKeys: [],
    })
    sorter.field = orderfields[sorter.field] || ''
@@ -1223,15 +1645,20 @@
    if (id !== MenuID) return
    if (repage !== 'false') {
    if (repage === 'false') {
      this.setState({
        pageIndex: 1
        selectedRowKeys: [],
      })
    } else {
      this.setState({
        pageIndex: 1,
        selectedRowKeys: [],
      })
    }
  }
  pickupChange = () => {
    const { submit } = this.props
    const { submit, MenuID } = this.props
    const { data } = this.state
    let pickup = !this.state.pickup
@@ -1264,6 +1691,7 @@
        onCancel() {}
      })
    } else {
      pickup && MKEmitter.emit('resetSelectLine', MenuID, '', '')
      this.setState({
        data: [],
        edData: [],
@@ -1281,12 +1709,12 @@
  render() {
    const { setting, statFValue, lineMarks, submit } = this.props
    const { pickup, tableId, data, edData, columns, edColumns, loading, pageOptions } = this.state
    const { pickup, tableId, data, edData, columns, edColumns, loading, pageOptions, selectedRowKeys } = this.state
    const components = {
      body: {
        row: BodyRow,
        cell: BodyCell
        cell: setting.editType !== 'multi' || !pickup ? BodyCell : BodyAllCell
      }
    }
@@ -1298,6 +1726,16 @@
      _data = edData
      _data = _data.filter(item => !item.$deleted)
      _columns = edColumns
    }
    // 设置表格选择属性:单选、多选、不可选
    let rowSelection = null
    if (setting.tableType && !pickup) {
      rowSelection = {
        selectedRowKeys,
        type: (setting.tableType === 'radio') ? 'radio' : 'checkbox',
        onChange: this.onSelectChange
      }
    }
    let _pagination = false
@@ -1330,6 +1768,7 @@
          style={setting.style}
          size={setting.size || 'middle'}
          bordered={setting.bordered !== 'false'}
          rowSelection={rowSelection}
          columns={_columns}
          dataSource={_data}
          loading={this.props.loading}
@@ -1337,7 +1776,8 @@
          onRow={(record, index) => {
            return {
              lineMarks,
              data: record
              data: record,
              onClick: () => {this.changeRow(record.$$uuid)},
            }
          }}
          onChange={this.changeTable}