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)
08-29
933
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
11-03
1万+
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
07-03
7866
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)