可编辑表格

import React from 'react'
import {Table} from 'antd'
import { EditableFormRow } from './component/EditableRow'
import EditableCell from './component/EditableCell'
import cloneDeep from 'lodash-es/cloneDeep'
import { getInitTableData } from './contants'

interface Props {
  isCanEdit: boolean
  capacity: any[]
}
interface columnsItem {
  title?: string
  dataIndex: string
  editable?: boolean
  width: string
  key?: string
  render?: (text, record) => any
}
interface State {
  dataSource: any[]
  columns: columnsItem[]
}
export default class EditableTable extends React.Component<Props, State> {
  ref: any
  constructor(props) {
    super(props)
    const { isCanEdit } = props
    this.ref = React.createRef()

    this.state = {
      dataSource: [],
      columns: [
        {
          dataIndex: 'date',
          width: '10%',
        },
        {
          title: '产能目标',
          dataIndex: 'capacityTarget',
          editable: isCanEdit,
          width: '10%',
          key: 'capacityTarget',
        },
        {
          title: '产能',
          dataIndex: 'capacityValue',
          editable: isCanEdit,
          width: '10%',
          key: 'capacityValue',
        },
        {
          title: '产能完成率',
          dataIndex: 'capacityCompleteRate',
          width: '10%',
          render: (text, record) => {
            const { capacityValue, capacityTarget } = record
            if (!Number(capacityValue)) {
              return '0.0%'
            }
            if (!Number(capacityTarget)) {
              return '100%'
            }
            const capacityCompleteRate = (
              (capacityValue / capacityTarget) *
              100
            ).toFixed(1)
            return `${capacityCompleteRate}%`
          },
        },
      ],
    }
  }

  componentDidMount(): void {
    const { capacity } = this.props

    let dataSource = capacity
    if (!dataSource?.length) {
      dataSource = getInitTableData()
    }
    this.setState({
      dataSource,
    })
  }

  getTableData = (): any[] => {
    const { dataSource } = this.state
    const flag = dataSource.some((item) => {
      return item?.capacityTarget === null || item?.capacityValue === null
    })
    return !flag ? dataSource : []
  }

  handleSave = (row): void => {
    const { dataSource } = this.state
    const newData = cloneDeep(dataSource)
    const { capacityValue, capacityTarget } = row
    if (!capacityValue) {
      row.capacityCompleteRate = '0.0%'
    } else {
      if (!Number(capacityTarget)) {
        row.capacityCompleteRate = '100%'
      } else {
        row.capacityCompleteRate = (
          (+capacityValue / +capacityTarget) *
          100
        ).toFixed(1)
      }
    }

    const index = newData.findIndex((item) => row.date === item.date)
    const item = newData[index]
    newData.splice(index, 1, {
      ...item,
      ...row,
    })
    this.setState({
      dataSource: newData,
    })
  }

  render(): React.ReactElement {
    const { columns, dataSource } = this.state
    const components = {
      body: {
        row: EditableFormRow,
        cell: EditableCell,
      },
    }
    const newColumns = columns.map((col) => {
      if (!col.editable) {
        return col
      }
      return {
        ...col,
        onCell: (record) => ({
          record,
          editable: col.editable,
          dataIndex: col.dataIndex,
          title: col.title,
          handleSave: this.handleSave,
        }),
      }
    })
    return (
      <div className={'steamer__component__services-edit-table'}>
        <Table
          components={components}
          rowClassName={() => 'editable-row'}
          bordered
          dataSource={dataSource}
          columns={newColumns}
          size="small"
          pagination={false}
          ref={(r) => {
            this.ref = r
          }}
        />
      </div>
    )
  }
}

contants.ts
import moment from 'moment'

interface capacityItem {
  date: string
  capacityTarget: number | null
  capacityValue: number | null
  capacityCompleteRate: number
}

export const getInitTableData = (): capacityItem[] => {
  const initCapacity: capacityItem[] = []
  for (let i = 1; i < 7; i++) {
    const date = `${moment().add(-i, 'months').format('YYYY年MM')}`
    initCapacity.push({
      date,
      capacityTarget: null,
      capacityValue: null,
      capacityCompleteRate: 0,
    })
  }
  return initCapacity
}
EditableCell
import React from 'react'
import { EditableContext } from '../utils'

const { antd } = window.steamer.services
const { Form, InputNumber } = antd
interface Props {
  handleSave: (value) => void
  dataIndex: string
  record: any
  title: string
  editable: boolean
}
class EditableCell extends React.Component<Props> {
  state = {
    editing: false,
  }

  input: any

  toggleEdit = (): void => {
    const editing = !this.state.editing
    this.setState({ editing })
  }

  save = (e): void => {
    const { record, handleSave } = this.props
    this.form.validateFields((error, values) => {
      this.toggleEdit()
      if (error?.[e.currentTarget.id]) {
        handleSave({ ...record })
        return
      }
      handleSave({ ...record, ...values })
    })
  }

  handValue = (value): any => {
    if (value) {
      const idx = `${value}`.split('').findIndex((val) => isNaN(parseInt(val)))
      let newValue = value
      if (idx >= 0) {
        newValue = `${value}`.slice(0, idx)
      }
      return newValue
    } else {
      return value
    }
  }

  renderCell = (form): React.ReactElement => {
    this.form = form
    const { children, dataIndex, record, title } = this.props
    const { editing } = this.state
    const min = dataIndex === 'capacityValue' ? 0 : 1
    return editing ? (
      <Form.Item style={{ margin: 0 }}>
        {form.getFieldDecorator(dataIndex, {
          rules: [
            {
              required: true,
              type: 'number',
              min,
              max: 999999,
              message: `${title}必填且为${min}~999999的整数`,
            },
          ],
          getValueFromEvent: (e) => {
            return this.handValue(e)
          },
          initialValue: record[dataIndex],
        })(
          <InputNumber
            onPressEnter={this.save}
            onBlur={this.save}
            max={999999}
            min={min}
            style={{
              width: '100%',
            }}
          />,
        )}
      </Form.Item>
    ) : (
      <div style={{ height: '25px' }} onClick={this.toggleEdit}>
        {children}
      </div>
    )
  }

  render(): React.ReactElement {
    const {
      editable,
      dataIndex,
      title,
      record,
      index,
      handleSave,
      children,
      ...restProps
    } = this.props
    return (
      <td {...restProps}>
        {editable ? (
          <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
        ) : (
          children
        )}
      </td>
    )
  }
}
export default EditableCell

EditableRow.tsx
import React from 'react'
import { EditableContext } from '../utils'
import {Form} from 'antd'


export const EditableRow = ({ form, index, ...props }): React.ReactElement => (
  <EditableContext.Provider value={form}>
    <tr {...props} />
  </EditableContext.Provider>
)

export const EditableFormRow = Form.create()(EditableRow)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值