import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
|
import { Table, Input, Popconfirm, message } from 'antd'
|
import { DeleteOutlined, PlusOutlined, SwapOutlined, DragOutlined } from '@ant-design/icons'
|
|
import Utils from '@/utils/utils.js'
|
import asyncComponent from '@/utils/asyncComponent'
|
import './index.scss'
|
|
const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
|
|
class MoveTd extends React.Component {
|
render() {
|
const { connectDragSource, connectDropTarget } = this.props
|
|
return connectDragSource(
|
connectDropTarget(<td className="mk-move-col"><DragOutlined /></td>),
|
)
|
}
|
}
|
|
const rowSource = {
|
beginDrag(props) {
|
return {
|
index: props.index,
|
}
|
}
|
}
|
|
const rowTarget = {
|
drop(props, monitor) {
|
const dragIndex = monitor.getItem().index
|
const hoverIndex = props.index
|
|
if (dragIndex === hoverIndex) {
|
return
|
}
|
|
props.moveRow(dragIndex, hoverIndex)
|
|
monitor.getItem().index = hoverIndex
|
},
|
}
|
|
const DragableTd = DropTarget('td', rowTarget, connect => ({
|
connectDropTarget: connect.dropTarget(),
|
}))(
|
DragSource('td', rowSource, (connect, monitor) => ({
|
connectDragSource: connect.dragSource(),
|
// isDragging: monitor.isDragging()
|
}))(MoveTd),
|
)
|
|
class EditableCell extends Component {
|
state = {
|
editing: false,
|
value: ''
|
}
|
|
trigger = () => {
|
const { dataIndex, record } = this.props
|
|
this.setState({ editing: true, value: record[dataIndex] }, () => {
|
if (this.input && this.input.select) {
|
this.input.select()
|
} else if (this.input && this.input.focus) {
|
this.input.focus()
|
}
|
})
|
}
|
|
save = () => {
|
const { record, handleSave, dataIndex } = this.props
|
const { value } = this.state
|
|
handleSave({ ...record, [dataIndex]: value })
|
|
this.setState({ editing: false, value: '' })
|
}
|
|
changeUrl = (val) => {
|
const { record, handleSave, dataIndex } = this.props
|
|
handleSave({ ...record, [dataIndex]: val })
|
}
|
|
renderCell = () => {
|
const { dataIndex, inputType, record } = this.props
|
const { editing } = this.state
|
|
if (inputType === 'file') {
|
return <SourceComponent initialValue={record[dataIndex]} type="" onChange={this.changeUrl} placement="right"/>
|
}
|
|
if (!editing) {
|
return (
|
<div
|
className="editable-cell-value-wrap"
|
onClick={this.trigger}
|
>
|
{record[dataIndex]}
|
</div>
|
)
|
} else {
|
return <Input ref={node => (this.input = node)} defaultValue={record[dataIndex]} autoComplete="off" onChange={(e) => this.setState({value: e.target.value})} onPressEnter={this.save} onBlur={this.save} />
|
}
|
}
|
|
render() {
|
const { editable, dataIndex, index } = this.props
|
|
if (dataIndex === '$move') {
|
return (<DragableTd key={index} {...this.props} />)
|
}
|
|
if (editable) {
|
return (
|
<td>{this.renderCell()}</td>
|
)
|
}
|
|
return (
|
<td {...this.props}/>
|
)
|
}
|
}
|
|
class EditTable extends Component {
|
static propTpyes = {
|
type: PropTypes.any,
|
module: PropTypes.string,
|
columns: PropTypes.array,
|
onChange: PropTypes.func
|
}
|
|
state = {
|
columns: [],
|
dataSource: [],
|
count: 0
|
}
|
|
UNSAFE_componentWillMount () {
|
const { columns, value } = this.props
|
let data = value || []
|
|
this.setState({
|
columns: this.getColumns(),
|
dataSource: data.map(item => {
|
columns.forEach(n => {
|
if (item[n.key] !== undefined) return
|
item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
|
})
|
return item
|
}),
|
count: data.length
|
})
|
}
|
|
moveRow = (dragId, hoverId) => {
|
const { dataSource } = this.state
|
let dragIndex = -1
|
let hoverIndex = -1
|
|
dataSource.forEach((item, i) => {
|
if (item.key === dragId) {
|
dragIndex = i
|
} else if (item.key === hoverId) {
|
hoverIndex = i
|
}
|
})
|
|
if (dragIndex === -1 || hoverIndex === -1) return
|
|
let _data = fromJS(dataSource).toJS()
|
|
_data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
|
|
this.setState({
|
dataSource: _data
|
}, () => {
|
this.props.onChange(_data)
|
})
|
}
|
|
handleHide = (key) => {
|
let _data = this.state.dataSource.map(item => {
|
if (item.key === key) {
|
item.Hide = !item.Hide
|
}
|
return item
|
})
|
|
this.setState({
|
dataSource: _data
|
}, () => {
|
this.props.onChange(_data)
|
})
|
}
|
|
handleDelete = (key) => {
|
const { dataSource } = this.state
|
let _data = dataSource.filter(item => item.key !== key)
|
|
this.setState({ dataSource: _data }, () => {
|
this.props.onChange(_data)
|
})
|
}
|
|
handleAdd = () => {
|
const { columns } = this.props
|
const { count, dataSource } = this.state
|
|
let item = { key: Utils.getuuid() }
|
|
columns.forEach(m => {
|
item[m.key] = ''
|
})
|
|
if (item.Value === '') {
|
item.Value = `${count + 1}`
|
}
|
if (item.$value === '') {
|
item.$value = `${count + 1}`
|
}
|
|
item.Text = `${count + 1}`
|
|
let _data = [...dataSource, item]
|
|
this.setState({
|
dataSource: _data,
|
count: count + 1
|
}, () => {
|
this.props.onChange(_data)
|
})
|
}
|
|
handleSave = row => {
|
const { columns, type } = this.props
|
const newData = [...this.state.dataSource]
|
const index = newData.findIndex(item => row.key === item.key)
|
const item = newData[index]
|
|
if (type === 'proc') {
|
// if (!row.origin || /^\s+$/.test(row.origin)) {
|
// message.warning(columns[0].title + '为空时无效!')
|
// }
|
} else {
|
let val = ''
|
let repeat = false
|
let _type = ''
|
columns.forEach(col => {
|
if (!col.strict) return
|
|
if (col.key === 'ParentID') {
|
_type = 'mutil'
|
}
|
|
val += row[col.key]
|
})
|
|
newData.forEach(item => {
|
if (row.key === item.key) return
|
|
let _val = ''
|
columns.forEach(col => {
|
if (!col.strict) return
|
|
_val += item[col.key]
|
})
|
|
if (val === _val) {
|
repeat = true
|
}
|
})
|
if (repeat) {
|
if (_type === 'mutil') {
|
message.warning('相同ParentID下,此Value值已存在!')
|
} else {
|
message.warning('此Value值已存在!')
|
}
|
}
|
}
|
|
newData.splice(index, 1, {
|
...item,
|
...row
|
})
|
this.setState({ dataSource: newData }, () => {
|
this.props.onChange(newData)
|
})
|
}
|
|
getColumns = () => {
|
const { columns } = this.props
|
|
let fields = [{
|
title: ' ',
|
width: '60px',
|
dataIndex: '$move',
|
onCell: (record) => ({
|
index: record.key,
|
dataIndex: '$move',
|
moveRow: this.moveRow
|
})
|
}]
|
columns.forEach(n => {
|
let col = {
|
title: n.title,
|
dataIndex: n.key,
|
onCell: record => ({
|
record,
|
editable: true,
|
inputType: n.type || 'text',
|
dataIndex: n.key,
|
handleSave: this.handleSave
|
})
|
}
|
|
if (n.width) {
|
col.width = n.width
|
}
|
if (n.fixed) {
|
delete col.onCell
|
}
|
|
fields.push(col)
|
})
|
|
fields.push({
|
title: '操作',
|
align: 'center',
|
width: '110px',
|
dataIndex: 'operation',
|
render: (text, record) =>
|
(
|
<div style={{fontSize: '15px'}}>
|
<span className="operation-btn" title="显示/隐藏" onClick={() => this.handleHide(record.key)} style={{color: 'rgb(142, 68, 173)'}}><SwapOutlined /></span>
|
<Popconfirm
|
title="确定删除吗?"
|
overlayClassName="popover-confirm"
|
onConfirm={() => this.handleDelete(record.key)
|
}>
|
<span style={{color: '#ff4d4f', cursor: 'pointer'}}><DeleteOutlined /></span>
|
</Popconfirm>
|
</div>
|
)
|
})
|
|
return fields
|
}
|
|
handleEmpty = () => {
|
const { columns, module } = this.props
|
const { dataSource } = this.state
|
|
if (dataSource.filter(item => item.Value === '').length > 0) {
|
message.warning('Value为空已存在!')
|
return
|
}
|
|
let item = { key: Utils.getuuid() }
|
|
columns.forEach(m => {
|
item[m.key] = ''
|
})
|
|
item.Text = module === 'form' ? '空' : '全部'
|
|
let _data = [item, ...dataSource]
|
|
this.setState({
|
dataSource: _data,
|
}, () => {
|
this.props.onChange(_data)
|
})
|
}
|
|
resetColumn = () => {
|
const { columns, value } = this.props
|
|
let data = fromJS(value).toJS().map(item => {
|
columns.forEach(n => {
|
if (item[n.key] !== undefined) return
|
item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
|
})
|
return item
|
})
|
|
this.setState({
|
columns: this.getColumns(),
|
dataSource: data,
|
count: data.length
|
}, () => {
|
this.props.onChange(data)
|
})
|
}
|
|
UNSAFE_componentWillReceiveProps (nextProps) {
|
if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
|
this.setState({}, () => {
|
this.resetColumn()
|
})
|
}
|
}
|
|
render() {
|
const { module } = this.props
|
const { dataSource, columns } = this.state
|
const components = {
|
body: {
|
cell: EditableCell
|
}
|
}
|
|
return (
|
<div className="common-modal-edit-table">
|
{module ? <span className="add-row add-row-empty" onClick={this.handleEmpty}>{module === 'form' ? '空' : '全部'}</span> : null}
|
<PlusOutlined className="add-row" onClick={this.handleAdd} />
|
<DndProvider>
|
<Table
|
components={components}
|
rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
|
bordered
|
dataSource={dataSource}
|
columns={columns}
|
pagination={false}
|
/>
|
</DndProvider>
|
</div>
|
)
|
}
|
}
|
|
export default EditTable
|