import React from 'react'
import { Table, Input, InputNumber, Form, Select } from 'antd'
import { OPTION_TYPE } from '../../constants/typeConstant'
import event, { EVENT_TYPE } from '../../utils/event'
import Common from '../../utils/common'
// 支持按行编辑的table
// 必传参数:columns、onSave、newRowKey、updateList
// column以editable标识是否可编辑, inputType标识编辑时为input还是select等, optionList标识为select时的可选值
const EditableContext = React.createContext()
class EditableCell extends React.Component {
getInput = () => {
const {inputType, mode, optionList} = this.props
switch(inputType){
case 'input':
return <Input style={{width: '100%'}}/>
case 'number':
return <InputNumber style={{width: '100%'}}/>
case 'select':
return <Select style={{width: '100%'}}
showSearch
allowClear
mode={mode || 'multiple'}
optionFilterProp="children"
>
{optionList?.map((item) => (
<Select.Option value={item.value} key={item.value}>
{item.label}
</Select.Option>
))
}
</Select>
}
return <Input/>
}
renderCell = ({ getFieldDecorator }) => {
const {
editing,
dataIndex,
title,
inputType,
required,
record,
index,
children,
...restProps
} = this.props
return (
<td {...restProps}>
{editing ? (
<Form.Item style={{ margin: 0 }}>
{getFieldDecorator(dataIndex, {
rules: [
{
required: required == true || false,
message: required == true ? `请输入 ${title}!`: ''
}
],
initialValue: (record[dataIndex] && Array.isArray(record[dataIndex])) ?
record[dataIndex]?.map(item => Common.types(item).isObject ? item.value : item) :
(Common.types(record[dataIndex]).isObject ? record[dataIndex].value : record[dataIndex])
})(this.getInput())}
</Form.Item>
) : (
children
)}
</td>
)
}
render() {
return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
}
}
class EditableTable extends React.Component {
constructor(props) {
super(props)
this.state = { editingKey: '' }
}
componentDidMount(){
event.addListener(EVENT_TYPE.ADD_ROW_IN_EDITABLE_TABLE, this.editNewRow)
}
componentWillUnmount(){
event.removeListener(EVENT_TYPE.ADD_ROW_IN_EDITABLE_TABLE, this.editNewRow)
}
isEditing = record => record.key === this.state.editingKey
// 取消
cancel = (key) => {
const {updateList} = this.props
updateList && updateList()
this.setState({ editingKey: '' })
}
//保存
save(form, oldRow, onSave) {
const { updateList} = this.props
form.validateFields((error, row) => {
if (error) {
return
}
//调用自定义保存方法
const newRow = {...oldRow, ...row}
onSave(newRow)
updateList && updateList()
this.setState({ editingKey: '' })
})
}
// 切换为编辑状态
edit(key) {
this.setState({ editingKey: key })
}
// 新增行切换为编辑状态
editNewRow = () =>{
const {newRowKey} = this.props
this.setState({ editingKey: newRowKey || 'new_row' })
}
formatColumns = () => {
const {columns, handleView, handleDelete} = this.props
const newColumns = [...columns]
return newColumns?.map(column => {
if(column?.dataIndex == 'operation'){
const viewOption = column.options?.find(option => option.type === OPTION_TYPE.VIEW)
const editOption = column.options?.find(option => option.type === OPTION_TYPE.EDIT)
const deleteOption = column.options?.find(option => option.type === OPTION_TYPE.DELETE)
column.render = (text, record) => {
const { editingKey } = this.state
const editable = this.isEditing(record)
return <>
{
viewOption && !editable &&
viewOption?.render(record)
}
{editOption &&(
editable ? (
<span>
<EditableContext.Consumer>
{form => (
<a
onClick={() => this.save(form, record, editOption.onSave)}
style={{ marginRight: 10 }}
>
保存
</a>
)}
</EditableContext.Consumer>
<a
onClick={() => this.cancel(record.key)}
>
取消
</a>
</span>
) : (
<a disabled={editingKey !== ''}
onClick={() => this.edit(record.key)}
style={{ marginRight: 10 }}
>
编辑
</a>
)
)}
{
deleteOption && !editable &&
deleteOption?.render(record)
}
</>
}
}
if(!column.editable) {
return column
}
return {
...column,
onCell: record => ({
record,
inputType: column.inputType,
dataIndex: column.dataIndex,
title: column.title,
required: column.required,
mode: column.mode,
optionList: column.optionList,
editing: this.isEditing(record)
})
}
})
}
render() {
const {columns, ...restProps} = this.props
const components = {
body: {
cell: EditableCell
}
}
return (
<EditableContext.Provider value={this.props.form}>
<Table
components={components}
columns={this.formatColumns()}
{...restProps}
/>
</EditableContext.Provider>
)
}
}
export default Form.create()(EditableTable)